aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/idle/intel_idle.c178
-rw-r--r--drivers/ieee802154/Makefile2
-rw-r--r--drivers/ieee802154/fakehard.c2
-rw-r--r--drivers/infiniband/core/addr.c1
-rw-r--r--drivers/infiniband/core/cache.c3
-rw-r--r--drivers/infiniband/core/cm.c64
-rw-r--r--drivers/infiniband/core/cm_msgs.h32
-rw-r--r--drivers/infiniband/core/cma.c158
-rw-r--r--drivers/infiniband/core/device.c6
-rw-r--r--drivers/infiniband/core/fmr_pool.c1
-rw-r--r--drivers/infiniband/core/iwcm.c35
-rw-r--r--drivers/infiniband/core/mad.c4
-rw-r--r--drivers/infiniband/core/multicast.c1
-rw-r--r--drivers/infiniband/core/netlink.c1
-rw-r--r--drivers/infiniband/core/packer.c1
-rw-r--r--drivers/infiniband/core/sysfs.c27
-rw-r--r--drivers/infiniband/core/ucm.c2
-rw-r--r--drivers/infiniband/core/ucma.c8
-rw-r--r--drivers/infiniband/core/ud_header.c1
-rw-r--r--drivers/infiniband/core/umem.c20
-rw-r--r--drivers/infiniband/core/user_mad.c54
-rw-r--r--drivers/infiniband/core/uverbs.h21
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c735
-rw-r--r--drivers/infiniband/core/uverbs_main.c74
-rw-r--r--drivers/infiniband/core/uverbs_marshall.c1
-rw-r--r--drivers/infiniband/core/verbs.c377
-rw-r--r--drivers/infiniband/hw/amso1100/c2.c12
-rw-r--r--drivers/infiniband/hw/amso1100/c2_ae.c5
-rw-r--r--drivers/infiniband/hw/amso1100/c2_intr.c5
-rw-r--r--drivers/infiniband/hw/amso1100/c2_provider.c14
-rw-r--r--drivers/infiniband/hw/cxgb3/Makefile2
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c10
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_ev.c6
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c9
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c14
-rw-r--r--drivers/infiniband/hw/cxgb4/Makefile2
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c468
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c8
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c41
-rw-r--r--drivers/infiniband/hw/cxgb4/ev.c10
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h23
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c8
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c42
-rw-r--r--drivers/infiniband/hw/cxgb4/resource.c9
-rw-r--r--drivers/infiniband/hw/cxgb4/user.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_eq.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_tools.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c69
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c12
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c198
-rw-r--r--drivers/infiniband/hw/ipath/ipath_srq.c5
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sysfs.c1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_user_pages.c6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_user_sdma.c7
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c1
-rw-r--r--drivers/infiniband/hw/mlx4/Kconfig3
-rw-r--r--drivers/infiniband/hw/mlx4/ah.c6
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c80
-rw-r--r--drivers/infiniband/hw/mlx4/main.c129
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h14
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c146
-rw-r--r--drivers/infiniband/hw/mlx4/srq.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_catas.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c277
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h93
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c43
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c175
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c101
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c43
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c37
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c83
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c49
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c33
-rw-r--r--drivers/infiniband/hw/nes/Makefile2
-rw-r--r--drivers/infiniband/hw/nes/nes.c8
-rw-r--r--drivers/infiniband/hw/nes/nes.h17
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c1123
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.h75
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c118
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h39
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c83
-rw-r--r--drivers/infiniband/hw/nes/nes_utils.c53
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c21
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h12
-rw-r--r--drivers/infiniband/hw/qib/qib.h31
-rw-r--r--drivers/infiniband/hw/qib/qib_diag.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_driver.c21
-rw-r--r--drivers/infiniband/hw/qib/qib_eeprom.c180
-rw-r--r--drivers/infiniband/hw/qib/qib_file_ops.c19
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c31
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c225
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c10
-rw-r--r--drivers/infiniband/hw/qib/qib_keys.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.c80
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.h143
-rw-r--r--drivers/infiniband/hw/qib/qib_pcie.c9
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c90
-rw-r--r--drivers/infiniband/hw/qib/qib_qsfp.c35
-rw-r--r--drivers/infiniband/hw/qib/qib_qsfp.h3
-rw-r--r--drivers/infiniband/hw/qib/qib_rc.c46
-rw-r--r--drivers/infiniband/hw/qib/qib_ruc.c7
-rw-r--r--drivers/infiniband/hw/qib/qib_sd7220.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_sdma.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_srq.c5
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c37
-rw-r--r--drivers/infiniband/hw/qib/qib_tx.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_uc.c25
-rw-r--r--drivers/infiniband/hw/qib/qib_ud.c9
-rw-r--r--drivers/infiniband/hw/qib/qib_user_pages.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_user_sdma.c6
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.c51
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c13
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c37
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c8
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c102
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h7
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c35
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c33
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c8
-rw-r--r--drivers/input/gameport/gameport.c2
-rw-r--r--drivers/input/joystick/analog.c4
-rw-r--r--drivers/input/joystick/as5011.c1
-rw-r--r--drivers/input/joystick/xpad.c52
-rw-r--r--drivers/input/mouse/alps.c63
-rw-r--r--drivers/input/mouse/bcm5974.c80
-rw-r--r--drivers/input/mouse/elantech.c817
-rw-r--r--drivers/input/mouse/elantech.h59
-rw-r--r--drivers/input/mouse/gpio_mouse.c2
-rw-r--r--drivers/input/mouse/hgpk.c85
-rw-r--r--drivers/input/mouse/hgpk.h11
-rw-r--r--drivers/input/mouse/lifebook.c10
-rw-r--r--drivers/input/mouse/logips2pp.c16
-rw-r--r--drivers/input/mouse/psmouse-base.c67
-rw-r--r--drivers/input/mouse/psmouse.h25
-rw-r--r--drivers/input/mouse/pxa930_trkball.c3
-rw-r--r--drivers/input/mouse/sentelic.c22
-rw-r--r--drivers/input/mouse/sentelic.h3
-rw-r--r--drivers/input/mouse/synaptics.c925
-rw-r--r--drivers/input/mouse/synaptics.h52
-rw-r--r--drivers/input/mouse/synaptics_i2c.c4
-rw-r--r--drivers/input/serio/ams_delta_serio.c1
-rw-r--r--drivers/input/serio/at32psif.c2
-rw-r--r--drivers/input/serio/hp_sdc.c2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h98
-rw-r--r--drivers/input/serio/i8042.c37
-rw-r--r--drivers/input/serio/libps2.c2
-rw-r--r--drivers/input/serio/sa1111ps2.c6
-rw-r--r--drivers/input/serio/serio_raw.c215
-rw-r--r--drivers/input/serio/serport.c45
-rw-r--r--drivers/input/serio/xilinx_ps2.c2
-rw-r--r--drivers/input/tablet/aiptek.c1
-rw-r--r--drivers/input/tablet/wacom.h10
-rw-r--r--drivers/input/tablet/wacom_sys.c383
-rw-r--r--drivers/input/tablet/wacom_wac.c167
-rw-r--r--drivers/isdn/Kconfig2
-rw-r--r--drivers/isdn/capi/kcapi_proc.c1
-rw-r--r--drivers/isdn/divert/divert_procfs.c6
-rw-r--r--drivers/isdn/gigaset/asyncdata.c1
-rw-r--r--drivers/isdn/gigaset/capi.c5
-rw-r--r--drivers/isdn/gigaset/dummyll.c1
-rw-r--r--drivers/isdn/gigaset/ev-layer.c5
-rw-r--r--drivers/isdn/gigaset/gigaset.h2
-rw-r--r--drivers/isdn/gigaset/i4l.c1
-rw-r--r--drivers/isdn/gigaset/interface.c1
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c1
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNinfineon.c1
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c1
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c1
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c1
-rw-r--r--drivers/isdn/hardware/mISDN/speedfax.c1
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c1
-rw-r--r--drivers/isdn/hisax/callc.c4
-rw-r--r--drivers/isdn/hisax/hisax.h5
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c1
-rw-r--r--drivers/isdn/hisax/isdnl1.h2
-rw-r--r--drivers/isdn/hisax/isdnl3.c2
-rw-r--r--drivers/isdn/hisax/l3dss1.c6
-rw-r--r--drivers/isdn/hisax/st5481_d.c4
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c2
-rw-r--r--drivers/isdn/i4l/isdn_common.c4
-rw-r--r--drivers/isdn/i4l/isdn_net.c8
-rw-r--r--drivers/isdn/i4l/isdn_tty.c3
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c31
-rw-r--r--drivers/isdn/mISDN/clock.c1
-rw-r--r--drivers/isdn/mISDN/dsp_audio.c1
-rw-r--r--drivers/isdn/mISDN/dsp_core.c3
-rw-r--r--drivers/isdn/mISDN/dsp_pipeline.c1
-rw-r--r--drivers/isdn/mISDN/l1oip_codec.c6
-rw-r--r--drivers/isdn/mISDN/socket.c14
-rw-r--r--drivers/lguest/core.c20
-rw-r--r--drivers/lguest/interrupts_and_traps.c10
-rw-r--r--drivers/lguest/lg.h2
-rw-r--r--drivers/lguest/lguest_device.c38
-rw-r--r--drivers/lguest/lguest_user.c18
-rw-r--r--drivers/lguest/page_tables.c282
-rw-r--r--drivers/lguest/x86/core.c107
-rw-r--r--drivers/macintosh/nvram.c4
-rw-r--r--drivers/macintosh/via-macii.c2
-rw-r--r--drivers/macintosh/via-maciisi.c4
-rw-r--r--drivers/macintosh/windfarm_core.c2
-rw-r--r--drivers/media/common/saa7146_core.c75
-rw-r--r--drivers/media/common/saa7146_fops.c119
-rw-r--r--drivers/media/common/saa7146_hlp.c15
-rw-r--r--drivers/media/common/saa7146_i2c.c60
-rw-r--r--drivers/media/common/saa7146_vbi.c48
-rw-r--r--drivers/media/common/saa7146_video.c184
-rw-r--r--drivers/media/common/tuners/Kconfig10
-rw-r--r--drivers/media/common/tuners/Makefile5
-rw-r--r--drivers/media/common/tuners/mt20xx.c24
-rw-r--r--drivers/media/common/tuners/mxl5005s.c22
-rw-r--r--drivers/media/common/tuners/mxl5007t.c3
-rw-r--r--drivers/media/common/tuners/tda18212.c31
-rw-r--r--drivers/media/common/tuners/tda18212_priv.h44
-rw-r--r--drivers/media/common/tuners/tda18218.c2
-rw-r--r--drivers/media/common/tuners/tda18271-common.c32
-rw-r--r--drivers/media/common/tuners/tda18271-fe.c2
-rw-r--r--drivers/media/common/tuners/tda18271-priv.h39
-rw-r--r--drivers/media/common/tuners/tda827x.c8
-rw-r--r--drivers/media/common/tuners/tuner-types.c5
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c18
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.h1
-rw-r--r--drivers/media/dvb/Kconfig4
-rw-r--r--drivers/media/dvb/Makefile3
-rw-r--r--drivers/media/dvb/b2c2/Makefile4
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h1
-rw-r--r--drivers/media/dvb/bt8xx/Makefile8
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c4
-rw-r--r--drivers/media/dvb/dm1105/Makefile2
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c1
-rw-r--r--drivers/media/dvb/dvb-core/Makefile4
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c8
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c98
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h1
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.h21
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig29
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile16
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c4
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-fe.c2
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-remote.c2
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.c10
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c183
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.h1
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c406
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.h17
-rw-r--r--drivers/media/dvb/dvb-usb/au6610.c9
-rw-r--r--drivers/media/dvb/dvb-usb/az6027.c26
-rw-r--r--drivers/media/dvb/dvb-usb/ce6230.c9
-rw-r--r--drivers/media/dvb/dvb-usb/cinergyT2-core.c5
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c142
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c36
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c549
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c27
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c31
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c3
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c16
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c14
-rw-r--r--drivers/media/dvb/dvb-usb/dtv5100.c11
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c153
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h9
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c41
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c28
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h39
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c115
-rw-r--r--drivers/media/dvb/dvb-usb/ec168.c9
-rw-r--r--drivers/media/dvb/dvb-usb/friio.c7
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.c9
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk-fe.c17
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c5
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.h3
-rw-r--r--drivers/media/dvb/dvb-usb/lmedm04.c68
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c58
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c4
-rw-r--r--drivers/media/dvb/dvb-usb/opera1.c13
-rw-r--r--drivers/media/dvb/dvb-usb/technisat-usb2.c32
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.c407
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c8
-rw-r--r--drivers/media/dvb/dvb-usb/usb-urb.c4
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c5
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c5
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.h3
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c2
-rw-r--r--drivers/media/dvb/firewire/firedtv-ci.c34
-rw-r--r--drivers/media/dvb/frontends/Kconfig51
-rw-r--r--drivers/media/dvb/frontends/Makefile11
-rw-r--r--drivers/media/dvb/frontends/au8522_decoder.c2
-rw-r--r--drivers/media/dvb/frontends/cx24113.c20
-rw-r--r--drivers/media/dvb/frontends/cx24116.c14
-rw-r--r--drivers/media/dvb/frontends/cxd2820r.h13
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_c.c1
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_core.c74
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_priv.h5
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_t.c1
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_t2.c1
-rw-r--r--drivers/media/dvb/frontends/dib3000.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c2
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c7
-rw-r--r--drivers/media/dvb/frontends/dib8000.c33
-rw-r--r--drivers/media/dvb/frontends/dib9000.c3
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.c1
-rw-r--r--drivers/media/dvb/frontends/drxd_hard.c33
-rw-r--r--drivers/media/dvb/frontends/ds3000.c7
-rw-r--r--drivers/media/dvb/frontends/itd1000.c25
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c2
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c14
-rw-r--r--drivers/media/dvb/frontends/stb0899_algo.c3
-rw-r--r--drivers/media/dvb/frontends/stb0899_drv.c6
-rw-r--r--drivers/media/dvb/frontends/stv0288.c29
-rw-r--r--drivers/media/dvb/frontends/stv090x.c35
-rw-r--r--drivers/media/dvb/frontends/tda10048.c37
-rw-r--r--drivers/media/dvb/frontends/tda10048.h8
-rw-r--r--drivers/media/dvb/mantis/Makefile2
-rw-r--r--drivers/media/dvb/mantis/hopper_cards.c6
-rw-r--r--drivers/media/dvb/mantis/mantis_ca.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_cards.c6
-rw-r--r--drivers/media/dvb/mantis/mantis_common.h6
-rw-r--r--drivers/media/dvb/mantis/mantis_dma.c92
-rw-r--r--drivers/media/dvb/mantis/mantis_evm.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_hif.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_ioc.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_pcmcia.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_uart.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_vp1034.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_vp1041.c1
-rw-r--r--drivers/media/dvb/ngene/Kconfig2
-rw-r--r--drivers/media/dvb/ngene/Makefile8
-rw-r--r--drivers/media/dvb/ngene/ngene-cards.c182
-rw-r--r--drivers/media/dvb/ngene/ngene-core.c26
-rw-r--r--drivers/media/dvb/ngene/ngene-dvb.c46
-rw-r--r--drivers/media/dvb/ngene/ngene.h7
-rw-r--r--drivers/media/dvb/pluto2/Makefile2
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c1
-rw-r--r--drivers/media/dvb/pt1/Makefile2
-rw-r--r--drivers/media/dvb/siano/Makefile4
-rw-r--r--drivers/media/dvb/siano/sms-cards.c1
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c2
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h1
-rw-r--r--drivers/media/dvb/siano/smsendian.c1
-rw-r--r--drivers/media/dvb/siano/smssdio.c1
-rw-r--r--drivers/media/dvb/siano/smsusb.c1
-rw-r--r--drivers/media/dvb/ttpci/Makefile4
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c32
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c47
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c1
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c2
-rw-r--r--drivers/media/dvb/ttpci/budget.h1
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.c29
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.h1
-rw-r--r--drivers/media/dvb/ttusb-budget/Makefile2
-rw-r--r--drivers/media/dvb/ttusb-dec/Makefile2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c3
-rw-r--r--drivers/media/radio/wl128x/fmdrv.h5
-rw-r--r--drivers/media/radio/wl128x/fmdrv_v4l2.c13
-rw-r--r--drivers/media/video/au0828/Makefile8
-rw-r--r--drivers/media/video/au0828/au0828-cards.c12
-rw-r--r--drivers/media/video/au0828/au0828-core.c1
-rw-r--r--drivers/media/video/au0828/au0828-video.c5
-rw-r--r--drivers/media/video/bt8xx/Makefile6
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c249
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c304
-rw-r--r--drivers/media/video/bt8xx/bttv-gpio.c4
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c56
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c37
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c25
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c9
-rw-r--r--drivers/media/video/bt8xx/bttvp.h21
-rw-r--r--drivers/media/video/cpia2/cpia2.h5
-rw-r--r--drivers/media/video/cpia2/cpia2_usb.c1
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c12
-rw-r--r--drivers/media/video/cx18/Makefile6
-rw-r--r--drivers/media/video/cx18/cx18-alsa-main.c1
-rw-r--r--drivers/media/video/cx18/cx18-driver.c2
-rw-r--r--drivers/media/video/cx18/cx18-driver.h6
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c2
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c19
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c2
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.h2
-rw-r--r--drivers/media/video/cx18/cx18-streams.c13
-rw-r--r--drivers/media/video/cx18/cx18-version.h8
-rw-r--r--drivers/media/video/cx231xx/Makefile10
-rw-r--r--drivers/media/video/cx231xx/cx231xx-avcore.c4
-rw-r--r--drivers/media/video/cx231xx/cx231xx-cards.c78
-rw-r--r--drivers/media/video/cx231xx/cx231xx-core.c4
-rw-r--r--drivers/media/video/cx231xx/cx231xx-video.c29
-rw-r--r--drivers/media/video/cx231xx/cx231xx.h5
-rw-r--r--drivers/media/video/cx23885/Kconfig2
-rw-r--r--drivers/media/video/cx23885/Makefile12
-rw-r--r--drivers/media/video/cx23885/altera-ci.c1
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c1
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c125
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c112
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c28
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c1
-rw-r--r--drivers/media/video/cx23885/cx23885-input.c6
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h3
-rw-r--r--drivers/media/video/cx23885/cx23885-vbi.c72
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c359
-rw-r--r--drivers/media/video/cx23885/cx23885.h60
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c12
-rw-r--r--drivers/media/video/cx25840/Makefile2
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c10
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c19
-rw-r--r--drivers/media/video/cx25840/cx25840-ir.c13
-rw-r--r--drivers/media/video/cx88/Makefile8
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c19
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c20
-rw-r--r--drivers/media/video/cx88/cx88-cards.c166
-rw-r--r--drivers/media/video/cx88/cx88-core.c8
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c77
-rw-r--r--drivers/media/video/cx88/cx88-input.c4
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c35
-rw-r--r--drivers/media/video/cx88/cx88-video.c65
-rw-r--r--drivers/media/video/cx88/cx88.h7
-rw-r--r--drivers/media/video/davinci/Kconfig23
-rw-r--r--drivers/media/video/davinci/Makefile2
-rw-r--r--drivers/media/video/davinci/dm355_ccdc.c1
-rw-r--r--drivers/media/video/davinci/dm644x_ccdc.c1
-rw-r--r--drivers/media/video/davinci/vpif.c2
-rw-r--r--drivers/media/video/davinci/vpif_capture.c9
-rw-r--r--drivers/media/video/davinci/vpif_capture.h7
-rw-r--r--drivers/media/video/davinci/vpif_display.c9
-rw-r--r--drivers/media/video/davinci/vpif_display.h8
-rw-r--r--drivers/media/video/em28xx/Kconfig14
-rw-r--r--drivers/media/video/em28xx/Makefile14
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c251
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c308
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c129
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c243
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c17
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c7
-rw-r--r--drivers/media/video/em28xx/em28xx-reg.h1
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c72
-rw-r--r--drivers/media/video/em28xx/em28xx.h27
-rw-r--r--drivers/media/video/et61x251/et61x251.h67
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c18
-rw-r--r--drivers/media/video/et61x251/et61x251_tas5130d1b.c2
-rw-r--r--drivers/media/video/gspca/Kconfig20
-rw-r--r--drivers/media/video/gspca/Makefile4
-rw-r--r--drivers/media/video/gspca/benq.c31
-rw-r--r--drivers/media/video/gspca/conex.c6
-rw-r--r--drivers/media/video/gspca/cpia1.c7
-rw-r--r--drivers/media/video/gspca/etoms.c6
-rw-r--r--drivers/media/video/gspca/finepix.c8
-rw-r--r--drivers/media/video/gspca/gl860/Makefile2
-rw-r--r--drivers/media/video/gspca/gl860/gl860.c8
-rw-r--r--drivers/media/video/gspca/gl860/gl860.h1
-rw-r--r--drivers/media/video/gspca/gspca.c306
-rw-r--r--drivers/media/video/gspca/gspca.h22
-rw-r--r--drivers/media/video/gspca/jeilinj.c20
-rw-r--r--drivers/media/video/gspca/kinect.c42
-rw-r--r--drivers/media/video/gspca/konica.c16
-rw-r--r--drivers/media/video/gspca/m5602/Makefile2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c9
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.c28
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.c21
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c19
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.c21
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c35
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c30
-rw-r--r--drivers/media/video/gspca/mars.c6
-rw-r--r--drivers/media/video/gspca/mr97310a.c24
-rw-r--r--drivers/media/video/gspca/nw80x.c9
-rw-r--r--drivers/media/video/gspca/ov519.c172
-rw-r--r--drivers/media/video/gspca/ov534.c12
-rw-r--r--drivers/media/video/gspca/ov534_9.c516
-rw-r--r--drivers/media/video/gspca/pac207.c14
-rw-r--r--drivers/media/video/gspca/pac7302.c18
-rw-r--r--drivers/media/video/gspca/pac7311.c15
-rw-r--r--drivers/media/video/gspca/sn9c2028.c14
-rw-r--r--drivers/media/video/gspca/sn9c20x.c77
-rw-r--r--drivers/media/video/gspca/sonixj.c51
-rw-r--r--drivers/media/video/gspca/spca1528.c34
-rw-r--r--drivers/media/video/gspca/spca500.c6
-rw-r--r--drivers/media/video/gspca/spca501.c4
-rw-r--r--drivers/media/video/gspca/spca505.c8
-rw-r--r--drivers/media/video/gspca/spca508.c6
-rw-r--r--drivers/media/video/gspca/spca561.c4
-rw-r--r--drivers/media/video/gspca/sq905.c17
-rw-r--r--drivers/media/video/gspca/sq905c.c10
-rw-r--r--drivers/media/video/gspca/sq930x.c21
-rw-r--r--drivers/media/video/gspca/stk014.c16
-rw-r--r--drivers/media/video/gspca/stv0680.c6
-rw-r--r--drivers/media/video/gspca/stv06xx/Makefile2
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.c18
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.h6
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c10
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c4
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_st6422.c4
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c32
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h56
-rw-r--r--drivers/media/video/gspca/sunplus.c13
-rw-r--r--drivers/media/video/gspca/t613.c14
-rw-r--r--drivers/media/video/gspca/vc032x.c13
-rw-r--r--drivers/media/video/gspca/vicam.c12
-rw-r--r--drivers/media/video/gspca/w996Xcf.c8
-rw-r--r--drivers/media/video/gspca/xirlink_cit.c14
-rw-r--r--drivers/media/video/gspca/zc3xx.c15
-rw-r--r--drivers/media/video/hdpvr/Makefile4
-rw-r--r--drivers/media/video/hdpvr/hdpvr-core.c25
-rw-r--r--drivers/media/video/hdpvr/hdpvr-i2c.c1
-rw-r--r--drivers/media/video/hdpvr/hdpvr-video.c2
-rw-r--r--drivers/media/video/hdpvr/hdpvr.h6
-rw-r--r--drivers/media/video/ivtv/Makefile8
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c19
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c20
-rw-r--r--drivers/media/video/ivtv/ivtv-version.h7
-rw-r--r--drivers/media/video/m5mols/Kconfig3
-rw-r--r--drivers/media/video/m5mols/Makefile2
-rw-r--r--drivers/media/video/m5mols/m5mols.h563
-rw-r--r--drivers/media/video/m5mols/m5mols_capture.c2
-rw-r--r--drivers/media/video/m5mols/m5mols_controls.c369
-rw-r--r--drivers/media/video/m5mols/m5mols_core.c1729
-rw-r--r--drivers/media/video/m5mols/m5mols_reg.h390
-rw-r--r--drivers/media/video/omap/Kconfig7
-rw-r--r--drivers/media/video/omap/Makefile1
-rw-r--r--drivers/media/video/omap/omap_vout.c707
-rw-r--r--drivers/media/video/omap/omap_voutdef.h78
-rw-r--r--drivers/media/video/omap/omap_voutlib.c46
-rw-r--r--drivers/media/video/omap/omap_voutlib.h12
-rw-r--r--drivers/media/video/omap3isp/Makefile4
-rw-r--r--drivers/media/video/omap3isp/isp.c55
-rw-r--r--drivers/media/video/omap3isp/isp.h84
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c131
-rw-r--r--drivers/media/video/omap3isp/ispccp2.c150
-rw-r--r--drivers/media/video/omap3isp/ispccp2.h1
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.c91
-rw-r--r--drivers/media/video/omap3isp/isph3a_aewb.c2
-rw-r--r--drivers/media/video/omap3isp/isph3a_af.c2
-rw-r--r--drivers/media/video/omap3isp/isphist.c2
-rw-r--r--drivers/media/video/omap3isp/isppreview.c419
-rw-r--r--drivers/media/video/omap3isp/isppreview.h9
-rw-r--r--drivers/media/video/omap3isp/ispqueue.c4
-rw-r--r--drivers/media/video/omap3isp/ispreg.h3
-rw-r--r--drivers/media/video/omap3isp/ispresizer.c104
-rw-r--r--drivers/media/video/omap3isp/ispstat.c68
-rw-r--r--drivers/media/video/omap3isp/ispstat.h2
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c39
-rw-r--r--drivers/media/video/omap3isp/ispvideo.h4
-rw-r--r--drivers/media/video/pvrusb2/Makefile8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c18
-rw-r--r--drivers/media/video/saa7134/Makefile8
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c13
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c12
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c25
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c2
-rw-r--r--drivers/media/video/saa7134/saa7134.h15
-rw-r--r--drivers/media/video/saa7164/Makefile10
-rw-r--r--drivers/media/video/saa7164/saa7164-cards.c62
-rw-r--r--drivers/media/video/saa7164/saa7164-core.c4
-rw-r--r--drivers/media/video/saa7164/saa7164-dvb.c1
-rw-r--r--drivers/media/video/saa7164/saa7164-encoder.c6
-rw-r--r--drivers/media/video/saa7164/saa7164-vbi.c6
-rw-r--r--drivers/media/video/saa7164/saa7164.h2
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c16
-rw-r--r--drivers/media/video/tlg2300/Makefile8
-rw-r--r--drivers/media/video/tlg2300/pd-common.h1
-rw-r--r--drivers/media/video/tlg2300/pd-dvb.c2
-rw-r--r--drivers/media/video/tlg2300/pd-main.c1
-rw-r--r--drivers/media/video/tlg2300/pd-radio.c2
-rw-r--r--drivers/media/video/usbvision/Makefile4
-rw-r--r--drivers/media/video/usbvision/usbvision-cards.c1
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c12
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c12
-rw-r--r--drivers/media/video/uvc/uvc_driver.c40
-rw-r--r--drivers/media/video/uvc/uvc_queue.c2
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c60
-rw-r--r--drivers/media/video/uvc/uvc_video.c39
-rw-r--r--drivers/media/video/uvc/uvcvideo.h107
-rw-r--r--drivers/media/video/zoran/zoran.h4
-rw-r--r--drivers/media/video/zoran/zoran_card.c7
-rw-r--r--drivers/media/video/zoran/zoran_driver.c3
-rw-r--r--drivers/memstick/core/memstick.c1
-rw-r--r--drivers/memstick/core/mspro_block.c4
-rw-r--r--drivers/memstick/host/jmb38x_ms.c1
-rw-r--r--drivers/memstick/host/tifm_ms.c1
-rw-r--r--drivers/message/fusion/mptbase.c92
-rw-r--r--drivers/message/fusion/mptbase.h72
-rw-r--r--drivers/message/fusion/mptsas.c47
-rw-r--r--drivers/message/fusion/mptscsih.c20
-rw-r--r--drivers/message/fusion/mptscsih.h1
-rw-r--r--drivers/message/i2o/i2o_scsi.c2
-rw-r--r--drivers/message/i2o/iop.c8
-rw-r--r--drivers/message/i2o/pci.c1
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.c389
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.h9
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_i2c.c45
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_spi.c2
-rw-r--r--drivers/misc/sgi-gru/grukservices.c1
-rw-r--r--drivers/misc/ti-st/st_core.c10
-rw-r--r--drivers/misc/ti-st/st_kim.c34
-rw-r--r--drivers/misc/ti-st/st_ll.c19
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c31
-rw-r--r--drivers/mtd/chips/fwh_lock.h3
-rw-r--r--drivers/mtd/chips/jedec_probe.c34
-rw-r--r--drivers/mtd/devices/Kconfig13
-rw-r--r--drivers/mtd/devices/Makefile3
-rw-r--r--drivers/mtd/devices/doc2000.c17
-rw-r--r--drivers/mtd/devices/doc2001.c11
-rw-r--r--drivers/mtd/devices/doc2001plus.c11
-rw-r--r--drivers/mtd/devices/docecc.c2
-rw-r--r--drivers/mtd/devices/docprobe.c5
-rw-r--r--drivers/mtd/devices/lart.c18
-rw-r--r--drivers/mtd/devices/m25p80.c111
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c91
-rw-r--r--drivers/mtd/devices/sst25l.c46
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c1
-rw-r--r--drivers/mtd/onenand/generic.c14
-rw-r--r--drivers/mtd/onenand/omap2.c18
-rw-r--r--drivers/mtd/onenand/onenand_base.c114
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c9
-rw-r--r--drivers/mtd/onenand/samsung.c13
-rw-r--r--drivers/mtd/tests/mtd_oobtest.c33
-rw-r--r--drivers/mtd/tests/mtd_pagetest.c37
-rw-r--r--drivers/mtd/tests/mtd_readtest.c13
-rw-r--r--drivers/mtd/tests/mtd_speedtest.c17
-rw-r--r--drivers/mtd/tests/mtd_stresstest.c11
-rw-r--r--drivers/mtd/tests/mtd_subpagetest.c17
-rw-r--r--drivers/mtd/tests/mtd_torturetest.c11
-rw-r--r--drivers/mtd/ubi/build.c28
-rw-r--r--drivers/mtd/ubi/cdev.c12
-rw-r--r--drivers/mtd/ubi/debug.c269
-rw-r--r--drivers/mtd/ubi/debug.h115
-rw-r--r--drivers/mtd/ubi/eba.c5
-rw-r--r--drivers/mtd/ubi/io.c44
-rw-r--r--drivers/mtd/ubi/kapi.c2
-rw-r--r--drivers/mtd/ubi/misc.c4
-rw-r--r--drivers/mtd/ubi/scan.c10
-rw-r--r--drivers/mtd/ubi/ubi.h8
-rw-r--r--drivers/mtd/ubi/upd.c10
-rw-r--r--drivers/mtd/ubi/vmt.c3
-rw-r--r--drivers/mtd/ubi/vtbl.c22
-rw-r--r--drivers/mtd/ubi/wl.c44
-rw-r--r--drivers/net/appletalk/cops.c2
-rw-r--r--drivers/net/appletalk/ltpc.c10
-rw-r--r--drivers/net/arcnet/Kconfig12
-rw-r--r--drivers/net/arcnet/Makefile1
-rw-r--r--drivers/net/arcnet/arc-rimi.c1
-rw-r--r--drivers/net/arcnet/com20020-isa.c1
-rw-r--r--drivers/net/arcnet/com20020-pci.c1
-rw-r--r--drivers/net/arcnet/com20020.c3
-rw-r--r--drivers/net/arcnet/com90io.c1
-rw-r--r--drivers/net/arcnet/com90xx.c1
-rw-r--r--drivers/net/bonding/bond_3ad.c71
-rw-r--r--drivers/net/bonding/bond_3ad.h9
-rw-r--r--drivers/net/bonding/bond_alb.c17
-rw-r--r--drivers/net/bonding/bond_debugfs.c2
-rw-r--r--drivers/net/bonding/bond_ipv6.c8
-rw-r--r--drivers/net/bonding/bond_main.c485
-rw-r--r--drivers/net/bonding/bond_procfs.c14
-rw-r--r--drivers/net/bonding/bond_sysfs.c219
-rw-r--r--drivers/net/bonding/bonding.h17
-rw-r--r--drivers/net/caif/Kconfig9
-rw-r--r--drivers/net/caif/Makefile3
-rw-r--r--drivers/net/caif/caif_serial.c2
-rw-r--r--drivers/net/caif/caif_shm_u5500.c1
-rw-r--r--drivers/net/caif/caif_shmcore.c2
-rw-r--r--drivers/net/caif/caif_spi.c5
-rw-r--r--drivers/net/caif/caif_spi_slave.c1
-rw-r--r--drivers/net/can/Kconfig8
-rw-r--r--drivers/net/can/at91_can.c376
-rw-r--r--drivers/net/can/bfin_can.c137
-rw-r--r--drivers/net/can/c_can/c_can.c14
-rw-r--r--drivers/net/can/c_can/c_can_platform.c2
-rw-r--r--drivers/net/can/dev.c41
-rw-r--r--drivers/net/can/flexcan.c243
-rw-r--r--drivers/net/can/janz-ican3.c1
-rw-r--r--drivers/net/can/mscan/mscan.c37
-rw-r--r--drivers/net/can/sja1000/Kconfig14
-rw-r--r--drivers/net/can/sja1000/Makefile2
-rw-r--r--drivers/net/can/sja1000/plx_pci.c8
-rw-r--r--drivers/net/can/sja1000/sja1000.c34
-rw-r--r--drivers/net/can/sja1000/sja1000.h5
-rw-r--r--drivers/net/can/sja1000/sja1000_of_platform.c34
-rw-r--r--drivers/net/can/slcan.c67
-rw-r--r--drivers/net/can/softing/softing_fw.c1
-rw-r--r--drivers/net/can/softing/softing_main.c4
-rw-r--r--drivers/net/can/ti_hecc.c4
-rw-r--r--drivers/net/can/usb/esd_usb2.c1
-rw-r--r--drivers/net/can/vcan.c2
-rw-r--r--drivers/net/cris/eth_v10.c2
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c1
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c1
-rw-r--r--drivers/net/hamradio/dmascc.c2
-rw-r--r--drivers/net/hamradio/hdlcdrv.c2
-rw-r--r--drivers/net/hamradio/yam.c1
-rw-r--r--drivers/net/irda/Kconfig4
-rw-r--r--drivers/net/irda/ali-ircc.c1
-rw-r--r--drivers/net/irda/donauboe.c1
-rw-r--r--drivers/net/irda/nsc-ircc.c1
-rw-r--r--drivers/net/irda/pxaficp_ir.c2
-rw-r--r--drivers/net/irda/sh_irda.c126
-rw-r--r--drivers/net/irda/sh_sir.c4
-rw-r--r--drivers/net/irda/sir_dev.c1
-rw-r--r--drivers/net/irda/smsc-ircc2.c19
-rw-r--r--drivers/net/irda/toim3232-sir.c2
-rw-r--r--drivers/net/irda/via-ircc.c1
-rw-r--r--drivers/net/irda/via-ircc.h2
-rw-r--r--drivers/net/irda/vlsi_ir.c1
-rw-r--r--drivers/net/irda/w83977af_ir.c1
-rw-r--r--drivers/net/phy/broadcom.c2
-rw-r--r--drivers/net/phy/dp83640.c209
-rw-r--r--drivers/net/phy/icplus.c103
-rw-r--r--drivers/net/phy/national.c17
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/phy/phy_device.c4
-rw-r--r--drivers/net/phy/realtek.c1
-rw-r--r--drivers/net/phy/vitesse.c34
-rw-r--r--drivers/net/tokenring/3c359.c8
-rw-r--r--drivers/net/tokenring/Kconfig15
-rw-r--r--drivers/net/tokenring/Makefile21
-rw-r--r--drivers/net/tokenring/ibmtr.c5
-rw-r--r--drivers/net/tokenring/lanstreamer.c2
-rw-r--r--drivers/net/tokenring/madgemc.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tokenring/smctr.c2
-rw-r--r--drivers/net/tokenring/tms380tr.c2
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c194
-rw-r--r--drivers/net/vmxnet3/vmxnet3_ethtool.c55
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h8
-rw-r--r--drivers/net/wan/c101.c30
-rw-r--r--drivers/net/wan/cosa.c226
-rw-r--r--drivers/net/wan/cycx_drv.c81
-rw-r--r--drivers/net/wan/cycx_main.c32
-rw-r--r--drivers/net/wan/cycx_x25.c177
-rw-r--r--drivers/net/wan/dlci.c22
-rw-r--r--drivers/net/wan/dscc4.c81
-rw-r--r--drivers/net/wan/farsync.c9
-rw-r--r--drivers/net/wan/hd64570.c8
-rw-r--r--drivers/net/wan/hd64572.c8
-rw-r--r--drivers/net/wan/hdlc.c16
-rw-r--r--drivers/net/wan/hdlc_cisco.c21
-rw-r--r--drivers/net/wan/hdlc_fr.c96
-rw-r--r--drivers/net/wan/hdlc_ppp.c23
-rw-r--r--drivers/net/wan/hdlc_x25.c28
-rw-r--r--drivers/net/wan/hostess_sv11.c11
-rw-r--r--drivers/net/wan/ixp4xx_hss.c28
-rw-r--r--drivers/net/wan/lapbether.c21
-rw-r--r--drivers/net/wan/lmc/lmc_var.h2
-rw-r--r--drivers/net/wan/n2.c42
-rw-r--r--drivers/net/wan/pc300_drv.c4
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/pc300too.c36
-rw-r--r--drivers/net/wan/pci200syn.c29
-rw-r--r--drivers/net/wan/sbni.c74
-rw-r--r--drivers/net/wan/sdla.c52
-rw-r--r--drivers/net/wan/sealevel.c11
-rw-r--r--drivers/net/wan/wanxl.c94
-rw-r--r--drivers/net/wan/x25_asy.c50
-rw-r--r--drivers/net/wan/z85230.c34
-rw-r--r--drivers/net/wimax/i2400m/control.c2
-rw-r--r--drivers/net/wimax/i2400m/debugfs.c1
-rw-r--r--drivers/net/wimax/i2400m/fw.c1
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h2
-rw-r--r--drivers/net/wimax/i2400m/netdev.c1
-rw-r--r--drivers/net/wimax/i2400m/rx.c2
-rw-r--r--drivers/net/wimax/i2400m/sdio.c1
-rw-r--r--drivers/net/wimax/i2400m/tx.c1
-rw-r--r--drivers/net/wimax/i2400m/usb-rx.c2
-rw-r--r--drivers/net/wimax/i2400m/usb.c5
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c50
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.c90
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h486
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c71
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c1226
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h263
-rw-r--r--drivers/net/wireless/ath/ath5k/caps.c51
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c439
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h25
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.c11
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c21
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c60
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h12
-rw-r--r--drivers/net/wireless/ath/ath5k/gpio.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/initvals.c17
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c75
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c274
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c53
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c45
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c222
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c25
-rw-r--r--drivers/net/wireless/ath/ath5k/reg.h89
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c166
-rw-r--r--drivers/net/wireless/ath/ath5k/rfbuffer.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/rfgain.h8
-rw-r--r--drivers/net/wireless/ath/ath5k/rfkill.c67
-rw-r--r--drivers/net/wireless/ath/ath5k/sysfs.c43
-rw-r--r--drivers/net/wireless/ath/ath5k/trace.h24
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig10
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_initvals.h131
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c48
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9001_initvals.h266
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c96
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_initvals.h3403
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c316
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h210
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c286
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c369
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c657
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c392
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c152
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c188
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h135
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h57
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c106
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c21
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c32
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c573
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h69
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h17
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c284
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c181
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c253
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c38
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c67
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h83
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c475
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h104
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c138
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c70
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h57
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c810
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c60
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c101
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c340
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h127
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c1234
-rw-r--r--drivers/net/wireless/ath/carl9170/Kconfig14
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h38
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c34
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h5
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c6
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h30
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h21
-rw-r--r--drivers/net/wireless/ath/carl9170/hw.h56
-rw-r--r--drivers/net/wireless/ath/carl9170/led.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c129
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c257
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c28
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c309
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c31
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h6
-rw-r--r--drivers/net/wireless/ath/carl9170/wlan.h25
-rw-r--r--drivers/net/wireless/b43/Kconfig48
-rw-r--r--drivers/net/wireless/b43/Makefile5
-rw-r--r--drivers/net/wireless/b43/b43.h140
-rw-r--r--drivers/net/wireless/b43/debugfs.c2
-rw-r--r--drivers/net/wireless/b43/dma.c265
-rw-r--r--drivers/net/wireless/b43/dma.h26
-rw-r--r--drivers/net/wireless/b43/leds.c17
-rw-r--r--drivers/net/wireless/b43/lo.c8
-rw-r--r--drivers/net/wireless/b43/main.c866
-rw-r--r--drivers/net/wireless/b43/main.h4
-rw-r--r--drivers/net/wireless/b43/pcmcia.c3
-rw-r--r--drivers/net/wireless/b43/phy_a.c23
-rw-r--r--drivers/net/wireless/b43/phy_common.c54
-rw-r--r--drivers/net/wireless/b43/phy_common.h8
-rw-r--r--drivers/net/wireless/b43/phy_g.c94
-rw-r--r--drivers/net/wireless/b43/phy_lp.c137
-rw-r--r--drivers/net/wireless/b43/phy_n.c665
-rw-r--r--drivers/net/wireless/b43/phy_n.h4
-rw-r--r--drivers/net/wireless/b43/pio.c40
-rw-r--r--drivers/net/wireless/b43/radio_2055.c3
-rw-r--r--drivers/net/wireless/b43/radio_2055.h5
-rw-r--r--drivers/net/wireless/b43/radio_2056.c2
-rw-r--r--drivers/net/wireless/b43/radio_2056.h31
-rw-r--r--drivers/net/wireless/b43/rfkill.c11
-rw-r--r--drivers/net/wireless/b43/sdio.c12
-rw-r--r--drivers/net/wireless/b43/sysfs.c6
-rw-r--r--drivers/net/wireless/b43/tables.c2
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.c17
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c3
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h8
-rw-r--r--drivers/net/wireless/b43/wa.c26
-rw-r--r--drivers/net/wireless/b43/xmit.c175
-rw-r--r--drivers/net/wireless/b43/xmit.h88
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h25
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/dma.c387
-rw-r--r--drivers/net/wireless/b43legacy/dma.h109
-rw-r--r--drivers/net/wireless/b43legacy/ilt.c2
-rw-r--r--drivers/net/wireless/b43legacy/leds.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c23
-rw-r--r--drivers/net/wireless/b43legacy/main.h2
-rw-r--r--drivers/net/wireless/b43legacy/phy.c2
-rw-r--r--drivers/net/wireless/b43legacy/phy.h2
-rw-r--r--drivers/net/wireless/b43legacy/pio.c2
-rw-r--r--drivers/net/wireless/b43legacy/radio.c2
-rw-r--r--drivers/net/wireless/b43legacy/radio.h2
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c2
-rw-r--r--drivers/net/wireless/b43legacy/sysfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h1
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c31
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c48
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.h1
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c4
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_tx.c2
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_wx.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945-rs.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945.c5
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-lib.c79
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-rs.c4
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-rx.c78
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-sta.c4
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-tx.c5
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965.c11
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-commands.h11
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.c112
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.h23
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-debugfs.c193
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-dev.h61
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-devtrace.c3
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-devtrace.h60
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-eeprom.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-helpers.h9
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-rx.c22
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-scan.c93
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-sta.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-tx.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c302
-rw-r--r--drivers/net/wireless/iwlegacy/iwl4965-base.c484
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c6
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.c1
-rw-r--r--drivers/net/wireless/libertas/README25
-rw-r--r--drivers/net/wireless/libertas/cfg.c152
-rw-r--r--drivers/net/wireless/libertas/cfg.h2
-rw-r--r--drivers/net/wireless/libertas/cmd.c52
-rw-r--r--drivers/net/wireless/libertas/cmd.h2
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c7
-rw-r--r--drivers/net/wireless/libertas/debugfs.c8
-rw-r--r--drivers/net/wireless/libertas/decl.h6
-rw-r--r--drivers/net/wireless/libertas/dev.h32
-rw-r--r--drivers/net/wireless/libertas/ethtool.c2
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c313
-rw-r--r--drivers/net/wireless/libertas/if_spi.c14
-rw-r--r--drivers/net/wireless/libertas/if_usb.c36
-rw-r--r--drivers/net/wireless/libertas/main.c268
-rw-r--r--drivers/net/wireless/libertas/mesh.c1010
-rw-r--r--drivers/net/wireless/libertas/mesh.h58
-rw-r--r--drivers/net/wireless/libertas/rx.c3
-rw-r--r--drivers/net/wireless/libertas/tx.c5
-rw-r--r--drivers/net/wireless/libertas_tf/cmd.c2
-rw-r--r--drivers/net/wireless/libertas_tf/deb_defs.h2
-rw-r--r--drivers/net/wireless/libertas_tf/if_usb.c2
-rw-r--r--drivers/net/wireless/libertas_tf/main.c4
-rw-r--r--drivers/net/wireless/mwifiex/11n.c36
-rw-r--r--drivers/net/wireless/mwifiex/11n.h14
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c55
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.h1
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c5
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h5
-rw-r--r--drivers/net/wireless/mwifiex/Kconfig11
-rw-r--r--drivers/net/wireless/mwifiex/Makefile3
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c442
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.h3
-rw-r--r--drivers/net/wireless/mwifiex/cfp.c10
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c83
-rw-r--r--drivers/net/wireless/mwifiex/debugfs.c35
-rw-r--r--drivers/net/wireless/mwifiex/decl.h13
-rw-r--r--drivers/net/wireless/mwifiex/fw.h62
-rw-r--r--drivers/net/wireless/mwifiex/init.c96
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h6
-rw-r--r--drivers/net/wireless/mwifiex/join.c58
-rw-r--r--drivers/net/wireless/mwifiex/main.c310
-rw-r--r--drivers/net/wireless/mwifiex/main.h135
-rw-r--r--drivers/net/wireless/mwifiex/scan.c1665
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c116
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h30
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c177
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c52
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c9
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c339
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_tx.c15
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c47
-rw-r--r--drivers/net/wireless/mwifiex/util.c5
-rw-r--r--drivers/net/wireless/mwifiex/util.h9
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c38
-rw-r--r--drivers/net/wireless/orinoco/airport.c9
-rw-r--r--drivers/net/wireless/orinoco/cfg.c6
-rw-r--r--drivers/net/wireless/orinoco/fw.c8
-rw-r--r--drivers/net/wireless/orinoco/fw.h2
-rw-r--r--drivers/net/wireless/orinoco/hermes.c40
-rw-r--r--drivers/net/wireless/orinoco/hermes.h37
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.c8
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.h12
-rw-r--r--drivers/net/wireless/orinoco/hw.c48
-rw-r--r--drivers/net/wireless/orinoco/hw.h2
-rw-r--r--drivers/net/wireless/orinoco/main.c50
-rw-r--r--drivers/net/wireless/orinoco/mic.c8
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h16
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c11
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c3
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c6
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c25
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c10
-rw-r--r--drivers/net/wireless/orinoco/wext.c15
-rw-r--r--drivers/net/wireless/p54/eeprom.c27
-rw-r--r--drivers/net/wireless/p54/fwio.c3
-rw-r--r--drivers/net/wireless/p54/main.c117
-rw-r--r--drivers/net/wireless/p54/p54.h18
-rw-r--r--drivers/net/wireless/p54/p54pci.c1
-rw-r--r--drivers/net/wireless/p54/p54pci.h1
-rw-r--r--drivers/net/wireless/p54/p54spi.c2
-rw-r--r--drivers/net/wireless/p54/p54usb.c1
-rw-r--r--drivers/net/wireless/p54/txrx.c73
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c8
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h1
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c1
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig9
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c52
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c43
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h21
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c592
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c68
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c138
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h38
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c35
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c95
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c180
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c45
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c13
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c7
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c6
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/rtl8187.h10
-rw-r--r--drivers/net/wireless/rtlwifi/Kconfig17
-rw-r--r--drivers/net/wireless/rtlwifi/Makefile1
-rw-r--r--drivers/net/wireless/rtlwifi/base.c284
-rw-r--r--drivers/net/wireless/rtlwifi/base.h2
-rw-r--r--drivers/net/wireless/rtlwifi/cam.c9
-rw-r--r--drivers/net/wireless/rtlwifi/core.c30
-rw-r--r--drivers/net/wireless/rtlwifi/core.h2
-rw-r--r--drivers/net/wireless/rtlwifi/debug.c2
-rw-r--r--drivers/net/wireless/rtlwifi/debug.h5
-rw-r--r--drivers/net/wireless/rtlwifi/efuse.c15
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c318
-rw-r--r--drivers/net/wireless/rtlwifi/pci.h42
-rw-r--r--drivers/net/wireless/rtlwifi/ps.c99
-rw-r--r--drivers/net/wireless/rtlwifi/ps.h3
-rw-r--r--drivers/net/wireless/rtlwifi/rc.c2
-rw-r--r--drivers/net/wireless/rtlwifi/regd.c18
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c8
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c10
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/main.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c15
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/def.h154
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c53
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/led.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/phy.c16
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/reg.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/rf.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/sw.c80
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.c128
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/def.h4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c181
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/led.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.c32
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/phy.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/rf.c31
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c101
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/trx.c36
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/def.h41
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/dm.c7
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c84
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/led.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/phy.c29
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/reg.h7
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/rf.c8
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c71
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c183
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c161
-rw-r--r--drivers/net/wireless/rtlwifi/usb.h3
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h77
-rw-r--r--drivers/net/wireless/wl1251/acx.c6
-rw-r--r--drivers/net/wireless/wl1251/cmd.c2
-rw-r--r--drivers/net/wireless/wl1251/cmd.h2
-rw-r--r--drivers/net/wireless/wl1251/main.c3
-rw-r--r--drivers/net/wireless/wl1251/sdio.c1
-rw-r--r--drivers/net/wireless/wl1251/spi.c1
-rw-r--r--drivers/net/wireless/wl1251/wl12xx_80211.h2
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig12
-rw-r--r--drivers/net/wireless/wl12xx/Makefile6
-rw-r--r--drivers/net/wireless/wl12xx/acx.c445
-rw-r--r--drivers/net/wireless/wl12xx/acx.h433
-rw-r--r--drivers/net/wireless/wl12xx/boot.c56
-rw-r--r--drivers/net/wireless/wl12xx/boot.h3
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c889
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h410
-rw-r--r--drivers/net/wireless/wl12xx/conf.h452
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c216
-rw-r--r--drivers/net/wireless/wl12xx/event.c127
-rw-r--r--drivers/net/wireless/wl12xx/event.h71
-rw-r--r--drivers/net/wireless/wl12xx/ini.h3
-rw-r--r--drivers/net/wireless/wl12xx/init.c142
-rw-r--r--drivers/net/wireless/wl12xx/io.c7
-rw-r--r--drivers/net/wireless/wl12xx/io.h16
-rw-r--r--drivers/net/wireless/wl12xx/main.c2031
-rw-r--r--drivers/net/wireless/wl12xx/ps.c31
-rw-r--r--drivers/net/wireless/wl12xx/reg.h75
-rw-r--r--drivers/net/wireless/wl12xx/rx.c102
-rw-r--r--drivers/net/wireless/wl12xx/rx.h30
-rw-r--r--drivers/net/wireless/wl12xx/scan.c271
-rw-r--r--drivers/net/wireless/wl12xx/scan.h49
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c87
-rw-r--r--drivers/net/wireless/wl12xx/sdio_test.c17
-rw-r--r--drivers/net/wireless/wl12xx/spi.c20
-rw-r--r--drivers/net/wireless/wl12xx/testmode.c53
-rw-r--r--drivers/net/wireless/wl12xx/tx.c346
-rw-r--r--drivers/net/wireless/wl12xx/tx.h54
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h217
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_80211.h27
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_def.h6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c120
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c130
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h5
-rw-r--r--drivers/net/xen-netback/common.h12
-rw-r--r--drivers/net/xen-netback/interface.c3
-rw-r--r--drivers/net/xen-netback/netback.c468
-rw-r--r--drivers/net/xen-netback/xenbus.c33
-rw-r--r--drivers/of/Kconfig8
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/address.c49
-rw-r--r--drivers/of/base.c337
-rw-r--r--drivers/of/fdt.c13
-rw-r--r--drivers/of/gpio.c16
-rw-r--r--drivers/of/irq.c122
-rw-r--r--drivers/of/of_mdio.c1
-rw-r--r--drivers/of/of_net.c46
-rw-r--r--drivers/of/of_pci.c114
-rw-r--r--drivers/of/of_spi.c1
-rw-r--r--drivers/of/pdt.c8
-rw-r--r--drivers/of/platform.c206
-rw-r--r--drivers/oprofile/event_buffer.c4
-rw-r--r--drivers/oprofile/oprofile_perf.c8
-rw-r--r--drivers/oprofile/oprofile_stats.h2
-rw-r--r--drivers/oprofile/oprofilefs.c6
-rw-r--r--drivers/parisc/ccio-dma.c1
-rw-r--r--drivers/parisc/sba_iommu.c17
-rw-r--r--drivers/parport/parport_ax88796.c2
-rw-r--r--drivers/parport/parport_pc.c67
-rw-r--r--drivers/parport/parport_serial.c229
-rw-r--r--drivers/pci/Kconfig38
-rw-r--r--drivers/pci/Makefile8
-rw-r--r--drivers/pci/access.c61
-rw-r--r--drivers/pci/dmar.c1461
-rw-r--r--drivers/pci/hotplug-pci.c1
-rw-r--r--drivers/pci/hotplug.c2
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c6
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c136
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c17
-rw-r--r--drivers/pci/hotplug/pciehp.h3
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c1
-rw-r--r--drivers/pci/hotplug/pciehp_core.c27
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c8
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c50
-rw-r--r--drivers/pci/hotplug/pcihp_slot.c48
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c3
-rw-r--r--drivers/pci/hotplug/shpchp.h3
-rw-r--r--drivers/pci/hotplug/shpchp_core.c36
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c10
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c21
-rw-r--r--drivers/pci/htirq.c1
-rw-r--r--drivers/pci/intel-iommu.c4059
-rw-r--r--drivers/pci/intr_remapping.c798
-rw-r--r--drivers/pci/intr_remapping.h17
-rw-r--r--drivers/pci/ioapic.c1
-rw-r--r--drivers/pci/iov.c150
-rw-r--r--drivers/pci/iova.c435
-rw-r--r--drivers/pci/irq.c1
-rw-r--r--drivers/pci/msi.c1
-rw-r--r--drivers/pci/pci-acpi.c6
-rw-r--r--drivers/pci/pci-driver.c18
-rw-r--r--drivers/pci/pci-label.c2
-rw-r--r--drivers/pci/pci-sysfs.c3
-rw-r--r--drivers/pci/pci.c176
-rw-r--r--drivers/pci/pci.h6
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c77
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c3
-rw-r--r--drivers/pci/pcie/aspm.c2
-rw-r--r--drivers/pci/pcie/pme.c9
-rw-r--r--drivers/pci/pcie/portdrv_pci.c1
-rw-r--r--drivers/pci/probe.c250
-rw-r--r--drivers/pci/quirks.c161
-rw-r--r--drivers/pci/rom.c8
-rw-r--r--drivers/pci/setup-bus.c136
-rw-r--r--drivers/pci/setup-irq.c4
-rw-r--r--drivers/pci/setup-res.c9
-rw-r--r--drivers/pci/slot.c1
-rw-r--r--drivers/pci/vpd.c1
-rw-r--r--drivers/pci/xen-pcifront.c2
-rw-r--r--drivers/pcmcia/at91_cf.c11
-rw-r--r--drivers/pcmcia/db1xxx_ss.c1
-rw-r--r--drivers/pcmcia/electra_cf.c4
-rw-r--r--drivers/pcmcia/pxa2xx_balloon3.c12
-rw-r--r--drivers/pcmcia/pxa2xx_base.c1
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x255.c12
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c12
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x2xx.c3
-rw-r--r--drivers/pcmcia/pxa2xx_colibri.c11
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c10
-rw-r--r--drivers/pcmcia/pxa2xx_palmld.c11
-rw-r--r--drivers/pcmcia/pxa2xx_palmtc.c11
-rw-r--r--drivers/pcmcia/pxa2xx_palmtx.c11
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c3
-rw-r--r--drivers/pcmcia/pxa2xx_stargate2.c34
-rw-r--r--drivers/pcmcia/pxa2xx_trizeps4.c4
-rw-r--r--drivers/pcmcia/pxa2xx_viper.c10
-rw-r--r--drivers/pcmcia/pxa2xx_vpac270.c2
-rw-r--r--drivers/pcmcia/rsrc_iodyn.c6
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c6
-rw-r--r--drivers/pcmcia/sa1100_simpad.c35
-rw-r--r--drivers/pcmcia/soc_common.c7
-rw-r--r--drivers/pcmcia/topic.h16
-rw-r--r--drivers/platform/x86/Kconfig34
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c427
-rw-r--r--drivers/platform/x86/acerhdf.c13
-rw-r--r--drivers/platform/x86/asus-laptop.c387
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c27
-rw-r--r--drivers/platform/x86/asus-wmi.c233
-rw-r--r--drivers/platform/x86/asus-wmi.h7
-rw-r--r--drivers/platform/x86/compal-laptop.c9
-rw-r--r--drivers/platform/x86/dell-laptop.c122
-rw-r--r--drivers/platform/x86/dell-wmi.c10
-rw-r--r--drivers/platform/x86/eeepc-laptop.c2
-rw-r--r--drivers/platform/x86/eeepc-wmi.c27
-rw-r--r--drivers/platform/x86/hp_accel.c14
-rw-r--r--drivers/platform/x86/ibm_rtl.c2
-rw-r--r--drivers/platform/x86/ideapad-laptop.c403
-rw-r--r--drivers/platform/x86/intel_ips.c4
-rw-r--r--drivers/platform/x86/intel_menlow.c2
-rw-r--r--drivers/platform/x86/intel_mid_thermal.c26
-rw-r--r--drivers/platform/x86/intel_rar_register.c4
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c3
-rw-r--r--drivers/platform/x86/intel_scu_ipcutil.c8
-rw-r--r--drivers/platform/x86/msi-laptop.c10
-rw-r--r--drivers/platform/x86/msi-wmi.c6
-rw-r--r--drivers/platform/x86/samsung-laptop.c272
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c15
-rw-r--r--drivers/platform/x86/topstar-laptop.c1
-rw-r--r--drivers/platform/x86/toshiba_acpi.c652
-rw-r--r--drivers/platform/x86/wmi.c1
-rw-r--r--drivers/pnp/pnpacpi/core.c1
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c40
-rw-r--r--drivers/pnp/pnpbios/rsparser.c12
-rw-r--r--drivers/pps/clients/Kconfig9
-rw-r--r--drivers/pps/clients/Makefile1
-rw-r--r--drivers/pps/clients/pps-ktimer.c12
-rw-r--r--drivers/pps/clients/pps-ldisc.c10
-rw-r--r--drivers/pps/clients/pps_parport.c9
-rw-r--r--drivers/pps/kapi.c20
-rw-r--r--drivers/pps/pps.c47
-rw-r--r--drivers/ps3/ps3-vuart.c2
-rw-r--r--drivers/ps3/ps3stor_lib.c3
-rw-r--r--drivers/ps3/sys-manager-core.c1
-rw-r--r--drivers/rapidio/Kconfig6
-rw-r--r--drivers/rapidio/Makefile1
-rw-r--r--drivers/rapidio/rio-scan.c6
-rw-r--r--drivers/rapidio/switches/idt_gen2.c1
-rw-r--r--drivers/s390/block/dasd.c596
-rw-r--r--drivers/s390/block/dasd_eckd.c54
-rw-r--r--drivers/s390/block/dasd_eer.c2
-rw-r--r--drivers/s390/block/dasd_fba.c1
-rw-r--r--drivers/s390/block/dasd_int.h59
-rw-r--r--drivers/s390/block/dasd_ioctl.c48
-rw-r--r--drivers/s390/block/dasd_proc.c110
-rw-r--r--drivers/s390/block/dcssblk.c7
-rw-r--r--drivers/s390/block/xpram.c5
-rw-r--r--drivers/s390/char/Kconfig3
-rw-r--r--drivers/s390/char/con3215.c23
-rw-r--r--drivers/s390/char/fs3270.c3
-rw-r--r--drivers/s390/char/raw3270.c3
-rw-r--r--drivers/s390/char/sclp_async.c9
-rw-r--r--drivers/s390/char/sclp_cmd.c10
-rw-r--r--drivers/s390/char/sclp_cpi_sys.c1
-rw-r--r--drivers/s390/char/sclp_quiesce.c5
-rw-r--r--drivers/s390/char/tape_34xx.c1
-rw-r--r--drivers/s390/char/tape_3590.c1
-rw-r--r--drivers/s390/char/tape_core.c2
-rw-r--r--drivers/s390/char/vmcp.c1
-rw-r--r--drivers/s390/char/vmlogrdr.c2
-rw-r--r--drivers/s390/char/vmur.c4
-rw-r--r--drivers/s390/char/vmwatchdog.c4
-rw-r--r--drivers/s390/char/zcore.c23
-rw-r--r--drivers/s390/cio/blacklist.c3
-rw-r--r--drivers/s390/cio/ccwgroup.c299
-rw-r--r--drivers/s390/cio/ccwreq.c23
-rw-r--r--drivers/s390/cio/chp.c2
-rw-r--r--drivers/s390/cio/chsc.c7
-rw-r--r--drivers/s390/cio/chsc_sch.c5
-rw-r--r--drivers/s390/cio/cio.c27
-rw-r--r--drivers/s390/cio/cio.h5
-rw-r--r--drivers/s390/cio/css.c112
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c17
-rw-r--r--drivers/s390/cio/device.h15
-rw-r--r--drivers/s390/cio/device_fsm.c30
-rw-r--r--drivers/s390/cio/device_ops.c20
-rw-r--r--drivers/s390/cio/io_sch.h7
-rw-r--r--drivers/s390/cio/qdio.h52
-rw-r--r--drivers/s390/cio/qdio_debug.c27
-rw-r--r--drivers/s390/cio/qdio_main.c332
-rw-r--r--drivers/s390/cio/qdio_setup.c85
-rw-r--r--drivers/s390/cio/qdio_thinint.c140
-rw-r--r--drivers/s390/crypto/ap_bus.c123
-rw-r--r--drivers/s390/crypto/ap_bus.h22
-rw-r--r--drivers/s390/crypto/zcrypt_api.c2
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c2
-rw-r--r--drivers/s390/crypto/zcrypt_mono.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c2
-rw-r--r--drivers/s390/kvm/kvm_virtio.c9
-rw-r--r--drivers/s390/net/Kconfig2
-rw-r--r--drivers/s390/net/claw.c3
-rw-r--r--drivers/s390/net/ctcm_main.c3
-rw-r--r--drivers/s390/net/ctcm_mpc.h1
-rw-r--r--drivers/s390/net/ctcm_sysfs.c2
-rw-r--r--drivers/s390/net/fsm.h2
-rw-r--r--drivers/s390/net/lcs.c13
-rw-r--r--drivers/s390/net/netiucv.c2
-rw-r--r--drivers/s390/net/qeth_core.h51
-rw-r--r--drivers/s390/net/qeth_core_main.c786
-rw-r--r--drivers/s390/net/qeth_l2_main.c4
-rw-r--r--drivers/s390/net/qeth_l3.h4
-rw-r--r--drivers/s390/net/qeth_l3_main.c195
-rw-r--r--drivers/s390/net/qeth_l3_sys.c114
-rw-r--r--drivers/s390/scsi/zfcp_aux.c1
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c1
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c37
-rw-r--r--drivers/s390/scsi/zfcp_def.h7
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c80
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c63
-rw-r--r--drivers/s390/scsi/zfcp_qdio.h66
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c24
-rw-r--r--drivers/sbus/char/bbc_envctrl.c6
-rw-r--r--drivers/sbus/char/bbc_i2c.c38
-rw-r--r--drivers/sbus/char/display7seg.c15
-rw-r--r--drivers/sbus/char/envctrl.c12
-rw-r--r--drivers/sbus/char/flash.c12
-rw-r--r--drivers/sbus/char/uctrl.c12
-rw-r--r--drivers/scsi/aacraid/aachba.c1
-rw-r--r--drivers/scsi/aacraid/commctrl.c3
-rw-r--r--drivers/scsi/aacraid/linit.c9
-rw-r--r--drivers/scsi/aacraid/src.c1
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx3
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx3
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dump.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_scb.c1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c2
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c20
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h2
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c60
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.h2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c315
-rw-r--r--drivers/scsi/be2iscsi/be_main.h9
-rw-r--r--drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h1162
-rw-r--r--drivers/scsi/bnx2fc/Kconfig3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h123
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_constants.h139
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.h16
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c444
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c896
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c829
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c284
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c92
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h4
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h14
-rw-r--r--drivers/scsi/bnx2i/Kconfig3
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h37
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c218
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c174
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c120
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kbuild2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kconfig3
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c25
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kbuild2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kconfig3
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c21
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c79
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.h3
-rw-r--r--drivers/scsi/device_handler/scsi_dh.c62
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c109
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c1
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c1
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c91
-rw-r--r--drivers/scsi/dpt/dpti_i2o.h2
-rw-r--r--drivers/scsi/fcoe/fcoe.c407
-rw-r--r--drivers/scsi/fcoe/fcoe.h11
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c4
-rw-r--r--drivers/scsi/fcoe/fcoe_transport.c108
-rw-r--r--drivers/scsi/fnic/fnic.h2
-rw-r--r--drivers/scsi/fnic/fnic_main.c21
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c3
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c10
-rw-r--r--drivers/scsi/isci/host.c102
-rw-r--r--drivers/scsi/isci/host.h23
-rw-r--r--drivers/scsi/isci/init.c54
-rw-r--r--drivers/scsi/isci/phy.c13
-rw-r--r--drivers/scsi/isci/port.c148
-rw-r--r--drivers/scsi/isci/port.h6
-rw-r--r--drivers/scsi/isci/probe_roms.h4
-rw-r--r--drivers/scsi/isci/registers.h122
-rw-r--r--drivers/scsi/isci/remote_device.c109
-rw-r--r--drivers/scsi/isci/remote_device.h14
-rw-r--r--drivers/scsi/isci/request.c383
-rw-r--r--drivers/scsi/isci/request.h34
-rw-r--r--drivers/scsi/isci/task.c730
-rw-r--r--drivers/scsi/isci/task.h54
-rw-r--r--drivers/scsi/libfc/fc_disc.c1
-rw-r--r--drivers/scsi/libfc/fc_elsct.c1
-rw-r--r--drivers/scsi/libfc/fc_exch.c111
-rw-r--r--drivers/scsi/libfc/fc_fcp.c41
-rw-r--r--drivers/scsi/libfc/fc_libfc.c1
-rw-r--r--drivers/scsi/libfc/fc_lport.c95
-rw-r--r--drivers/scsi/libfc/fc_npiv.c1
-rw-r--r--drivers/scsi/libfc/fc_rport.c15
-rw-r--r--drivers/scsi/libsas/sas_ata.c14
-rw-r--r--drivers/scsi/libsas/sas_discover.c19
-rw-r--r--drivers/scsi/libsas/sas_expander.c35
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c104
-rw-r--r--drivers/scsi/libsas/sas_init.c43
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c146
-rw-r--r--drivers/scsi/libsas/sas_task.c1
-rw-r--r--drivers/scsi/lpfc/lpfc.h27
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c88
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c37
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c1539
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.h125
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c35
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c227
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h8
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h300
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c296
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c80
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c245
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c751
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h18
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h50
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c16
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c3
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h23
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c275
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c27
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c193
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h19
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h19
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h225
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h6
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h115
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c667
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h88
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c68
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c40
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c1004
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c2
-rw-r--r--drivers/scsi/mvsas/Kconfig9
-rw-r--r--drivers/scsi/mvsas/mv_64xx.c101
-rw-r--r--drivers/scsi/mvsas/mv_94xx.c541
-rw-r--r--drivers/scsi/mvsas/mv_94xx.h99
-rw-r--r--drivers/scsi/mvsas/mv_chips.h17
-rw-r--r--drivers/scsi/mvsas/mv_defs.h13
-rw-r--r--drivers/scsi/mvsas/mv_init.c210
-rw-r--r--drivers/scsi/mvsas/mv_sas.c493
-rw-r--r--drivers/scsi/mvsas/mv_sas.h110
-rw-r--r--drivers/scsi/osd/Kconfig4
-rw-r--r--drivers/scsi/osd/osd_initiator.c1
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c73
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c4
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c93
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c322
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c593
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h42
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c398
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h187
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h14
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h27
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c371
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c889
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h37
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c410
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c784
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c1243
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c162
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c1565
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h259
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c887
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c275
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/qla4xxx/Kconfig3
-rw-r--r--drivers/scsi/qla4xxx/Makefile2
-rw-r--r--drivers/scsi/qla4xxx/ql4_attr.c76
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h263
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h206
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h85
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c1015
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c68
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c83
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c835
-rw-r--r--drivers/scsi/qla4xxx/ql4_nvram.c21
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c17
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c3301
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c4
-rw-r--r--drivers/sfi/sfi_core.h3
-rw-r--r--drivers/sh/Makefile8
-rw-r--r--drivers/sh/clk/core.c123
-rw-r--r--drivers/sh/intc/chip.c12
-rw-r--r--drivers/sh/intc/core.c2
-rw-r--r--drivers/sh/intc/dynamic.c1
-rw-r--r--drivers/sh/intc/userimask.c1
-rw-r--r--drivers/sh/intc/virq.c1
-rw-r--r--drivers/sh/maple/maple.c1
-rw-r--r--drivers/sh/pfc.c29
-rw-r--r--drivers/ssb/b43_pci_bridge.c3
-rw-r--r--drivers/ssb/driver_chipcommon.c3
-rw-r--r--drivers/ssb/driver_chipcommon_pmu.c7
-rw-r--r--drivers/ssb/driver_extif.c2
-rw-r--r--drivers/ssb/driver_gige.c16
-rw-r--r--drivers/ssb/driver_mipscore.c2
-rw-r--r--drivers/ssb/driver_pcicore.c13
-rw-r--r--drivers/ssb/embedded.c3
-rw-r--r--drivers/ssb/main.c59
-rw-r--r--drivers/ssb/pci.c11
-rw-r--r--drivers/ssb/pcihost_wrapper.c9
-rw-r--r--drivers/ssb/pcmcia.c2
-rw-r--r--drivers/ssb/scan.c5
-rw-r--r--drivers/ssb/sdio.c2
-rw-r--r--drivers/ssb/sprom.c2
-rw-r--r--drivers/staging/bcm/Bcmchar.c3172
-rw-r--r--drivers/staging/bcm/Debug.h2
-rw-r--r--drivers/staging/bcm/InterfaceDld.c456
-rw-r--r--drivers/staging/bcm/InterfaceInit.c43
-rw-r--r--drivers/staging/bcm/InterfaceInit.h5
-rw-r--r--drivers/staging/bcm/InterfaceMisc.c304
-rw-r--r--drivers/staging/bcm/InterfaceRx.c4
-rw-r--r--drivers/staging/bcm/Macros.h337
-rw-r--r--drivers/staging/bcm/Misc.c1843
-rw-r--r--drivers/staging/bcm/PHSModule.c24
-rw-r--r--drivers/staging/bcm/PHSModule.h2
-rw-r--r--drivers/staging/bcm/headers.h10
-rw-r--r--drivers/staging/bcm/nvm.c13
-rw-r--r--drivers/staging/bcm/sort.c77
-rw-r--r--drivers/staging/comedi/Kconfig28
-rw-r--r--drivers/staging/comedi/comedi.h6
-rw-r--r--drivers/staging/comedi/comedi_compat32.c12
-rw-r--r--drivers/staging/comedi/comedi_fops.c43
-rw-r--r--drivers/staging/comedi/comedidev.h3
-rw-r--r--drivers/staging/comedi/drivers.c4
-rw-r--r--drivers/staging/comedi/drivers/Makefile2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c2
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c1
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c17
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c2
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c2
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c13
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c5
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c123
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c21
-rw-r--r--drivers/staging/comedi/drivers/das08.c2
-rw-r--r--drivers/staging/comedi/drivers/das1800.c28
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c57
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c14
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c1
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c1
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c1
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c34
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c12
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c22
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c45
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c6
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c46
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c7
-rw-r--r--drivers/staging/crystalhd/bc_dts_defs.h4
-rw-r--r--drivers/staging/crystalhd/bc_dts_glob_lnx.h6
-rw-r--r--drivers/staging/crystalhd/bc_dts_types.h57
-rw-r--r--drivers/staging/crystalhd/crystalhd_cmds.h2
-rw-r--r--drivers/staging/crystalhd/crystalhd_fw_if.h532
-rw-r--r--drivers/staging/crystalhd/crystalhd_misc.h6
-rw-r--r--drivers/staging/cxt1e1/Kconfig3
-rw-r--r--drivers/staging/cxt1e1/linux.c7
-rw-r--r--drivers/staging/cxt1e1/sbecom_inline_linux.h65
-rw-r--r--drivers/staging/echo/echo.c11
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf14
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.h490
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c196
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h66
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c562
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c244
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c31
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_hw.c11
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h32
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_usb.h413
-rw-r--r--drivers/staging/iio/addac/Kconfig5
-rw-r--r--drivers/staging/iio/addac/adt7316-i2c.c3
-rw-r--r--drivers/staging/iio/addac/adt7316.c248
-rw-r--r--drivers/staging/iio/dac/Kconfig38
-rw-r--r--drivers/staging/iio/dac/Makefile3
-rw-r--r--drivers/staging/iio/dac/ad5446.c126
-rw-r--r--drivers/staging/iio/dac/ad5446.h2
-rw-r--r--drivers/staging/iio/dac/ad5504.c141
-rw-r--r--drivers/staging/iio/dac/ad5504.h2
-rw-r--r--drivers/staging/iio/dac/ad5624r.h1
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c95
-rw-r--r--drivers/staging/iio/dac/ad5791.c246
-rw-r--r--drivers/staging/iio/dac/ad5791.h8
-rw-r--r--drivers/staging/iio/dac/dac.h2
-rw-r--r--drivers/staging/iio/dac/max517.c70
-rw-r--r--drivers/staging/iio/dds/Kconfig4
-rw-r--r--drivers/staging/iio/dds/ad5930.c39
-rw-r--r--drivers/staging/iio/dds/ad9832.c71
-rw-r--r--drivers/staging/iio/dds/ad9832.h2
-rw-r--r--drivers/staging/iio/dds/ad9834.c92
-rw-r--r--drivers/staging/iio/dds/ad9834.h2
-rw-r--r--drivers/staging/iio/dds/ad9850.c39
-rw-r--r--drivers/staging/iio/dds/ad9852.c41
-rw-r--r--drivers/staging/iio/dds/ad9910.c39
-rw-r--r--drivers/staging/iio/dds/ad9951.c39
-rw-r--r--drivers/staging/iio/imu/Kconfig16
-rw-r--r--drivers/staging/iio/imu/Makefile2
-rw-r--r--drivers/staging/iio/imu/adis16400.h9
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c660
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c50
-rw-r--r--drivers/staging/iio/imu/adis16400_trigger.c17
-rw-r--r--drivers/staging/iio/light/Kconfig6
-rw-r--r--drivers/staging/iio/light/isl29018.c271
-rw-r--r--drivers/staging/iio/light/tsl2563.c176
-rw-r--r--drivers/staging/iio/light/tsl2583.c222
-rw-r--r--drivers/staging/iio/meter/Kconfig8
-rw-r--r--drivers/staging/iio/meter/Makefile2
-rw-r--r--drivers/staging/iio/meter/ade7753.c107
-rw-r--r--drivers/staging/iio/meter/ade7753.h10
-rw-r--r--drivers/staging/iio/meter/ade7754.c103
-rw-r--r--drivers/staging/iio/meter/ade7754.h12
-rw-r--r--drivers/staging/iio/meter/ade7758.h13
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c81
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c58
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c17
-rw-r--r--drivers/staging/iio/meter/ade7759.c101
-rw-r--r--drivers/staging/iio/meter/ade7759.h12
-rw-r--r--drivers/staging/iio/meter/ade7854-i2c.c40
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c41
-rw-r--r--drivers/staging/iio/meter/ade7854.c77
-rw-r--r--drivers/staging/iio/meter/ade7854.h36
-rw-r--r--drivers/staging/intel_sst/intel_sst.c16
-rw-r--r--drivers/staging/intel_sst/intel_sst_app_interface.c4
-rw-r--r--drivers/staging/intel_sst/intel_sst_common.h2
-rw-r--r--drivers/staging/intel_sst/intel_sst_drv_interface.c11
-rw-r--r--drivers/staging/intel_sst/intel_sst_dsp.c2
-rw-r--r--drivers/staging/intel_sst/intelmid.c1
-rw-r--r--drivers/staging/intel_sst/intelmid_v2_control.c2
-rw-r--r--drivers/staging/line6/audio.c1
-rw-r--r--drivers/staging/line6/pcm.c45
-rw-r--r--drivers/staging/mei/Kconfig2
-rw-r--r--drivers/staging/mei/TODO10
-rw-r--r--drivers/staging/mei/init.c181
-rw-r--r--drivers/staging/mei/interface.c13
-rw-r--r--drivers/staging/mei/interface.h8
-rw-r--r--drivers/staging/mei/interrupt.c128
-rw-r--r--drivers/staging/mei/iorw.c32
-rw-r--r--drivers/staging/mei/main.c117
-rw-r--r--drivers/staging/mei/mei_dev.h155
-rw-r--r--drivers/staging/mei/wd.c254
-rw-r--r--drivers/staging/nvec/Kconfig12
-rw-r--r--drivers/staging/nvec/Makefile1
-rw-r--r--drivers/staging/nvec/TODO16
-rw-r--r--drivers/staging/nvec/nvec-keytable.h225
-rw-r--r--drivers/staging/nvec/nvec.c959
-rw-r--r--drivers/staging/nvec/nvec.h217
-rw-r--r--drivers/staging/nvec/nvec_kbd.c95
-rw-r--r--drivers/staging/nvec/nvec_power.c352
-rw-r--r--drivers/staging/nvec/nvec_ps2.c114
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c27
-rw-r--r--drivers/staging/octeon/ethernet-rgmii.c34
-rw-r--r--drivers/staging/octeon/ethernet-rx.c29
-rw-r--r--drivers/staging/octeon/ethernet-sgmii.c14
-rw-r--r--drivers/staging/octeon/ethernet-spi.c1
-rw-r--r--drivers/staging/octeon/ethernet-tx.c17
-rw-r--r--drivers/staging/octeon/ethernet-util.h4
-rw-r--r--drivers/staging/octeon/ethernet-xaui.c22
-rw-r--r--drivers/staging/octeon/ethernet.c12
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c47
-rw-r--r--drivers/staging/panel/panel.c24
-rw-r--r--drivers/staging/pohmelfs/Kconfig8
-rw-r--r--drivers/staging/pohmelfs/crypto.c1
-rw-r--r--drivers/staging/pohmelfs/dir.c2
-rw-r--r--drivers/staging/pohmelfs/inode.c13
-rw-r--r--drivers/staging/pohmelfs/trans.c6
-rw-r--r--drivers/staging/rtl8187se/Makefile6
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h6
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_module.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c23
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c2
-rw-r--r--drivers/staging/rtl8187se/r8180.h1
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c5
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225z2.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/Makefile109
-rw-r--r--drivers/staging/rtl8192u/ieee80211/compress.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h6
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c3
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c21
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c2
-rw-r--r--drivers/staging/rtl8192u/r8192U.h1
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c12
-rw-r--r--drivers/staging/rtl8712/Kconfig8
-rw-r--r--drivers/staging/rtl8712/basic_types.h25
-rw-r--r--drivers/staging/rtl8712/big_endian.h25
-rw-r--r--drivers/staging/rtl8712/drv_types.h41
-rw-r--r--drivers/staging/rtl8712/ethernet.h25
-rw-r--r--drivers/staging/rtl8712/generic.h25
-rw-r--r--drivers/staging/rtl8712/hal_init.c68
-rw-r--r--drivers/staging/rtl8712/ieee80211.c35
-rw-r--r--drivers/staging/rtl8712/ieee80211.h62
-rw-r--r--drivers/staging/rtl8712/if_ether.h25
-rw-r--r--drivers/staging/rtl8712/little_endian.h25
-rw-r--r--drivers/staging/rtl8712/mlme_osdep.h25
-rw-r--r--drivers/staging/rtl8712/mp_custom_oid.h25
-rw-r--r--drivers/staging/rtl8712/os_intfs.c42
-rw-r--r--drivers/staging/rtl8712/osdep_intf.h25
-rw-r--r--drivers/staging/rtl8712/osdep_service.h70
-rw-r--r--drivers/staging/rtl8712/recv_linux.c6
-rw-r--r--drivers/staging/rtl8712/recv_osdep.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_bitdef.h21
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c18
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.h87
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c75
-rw-r--r--drivers/staging/rtl8712/rtl8712_event.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h28
-rw-r--r--drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c2
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c25
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.h31
-rw-r--r--drivers/staging/rtl8712/rtl8712_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_security_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_spec.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c303
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.h37
-rw-r--r--drivers/staging/rtl8712/rtl871x_byteorder.h19
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c172
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h77
-rw-r--r--drivers/staging/rtl8712/rtl871x_debug.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.h19
-rw-r--r--drivers/staging/rtl8712/rtl871x_event.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_ht.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c298
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c3
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.h27
-rw-r--r--drivers/staging/rtl8712/rtl871x_led.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c62
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h28
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c26
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.h26
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.h29
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c17
-rw-r--r--drivers/staging/rtl8712/rtl871x_rf.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c15
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c5
-rw-r--r--drivers/staging/rtl8712/rtl871x_wlan_sme.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c31
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h52
-rw-r--r--drivers/staging/rtl8712/sta_info.h33
-rw-r--r--drivers/staging/rtl8712/swab.h25
-rw-r--r--drivers/staging/rtl8712/usb_intf.c38
-rw-r--r--drivers/staging/rtl8712/usb_ops.h25
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c29
-rw-r--r--drivers/staging/rtl8712/usb_osintf.h26
-rw-r--r--drivers/staging/rtl8712/usb_vendor_req.h25
-rw-r--r--drivers/staging/rtl8712/wifi.h32
-rw-r--r--drivers/staging/rtl8712/wlan_bssdef.h25
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c27
-rw-r--r--drivers/staging/rtl8712/xmit_osdep.h26
-rw-r--r--drivers/staging/rts_pstor/Makefile2
-rw-r--r--drivers/staging/rts_pstor/ms.c3
-rw-r--r--drivers/staging/rts_pstor/rtsx.c172
-rw-r--r--drivers/staging/rts_pstor/rtsx.h20
-rw-r--r--drivers/staging/rts_pstor/rtsx_chip.c6
-rw-r--r--drivers/staging/rts_pstor/rtsx_scsi.c2
-rw-r--r--drivers/staging/rts_pstor/rtsx_transport.c11
-rw-r--r--drivers/staging/rts_pstor/sd.c99
-rw-r--r--drivers/staging/rts_pstor/sd.h5
-rw-r--r--drivers/staging/rts_pstor/spi.c2
-rw-r--r--drivers/staging/sep/sep_driver.c13
-rw-r--r--drivers/staging/sep/sep_driver_config.h2
-rw-r--r--drivers/staging/serqt_usb2/serqt_usb2.c36
-rw-r--r--drivers/staging/slicoss/Kconfig2
-rw-r--r--drivers/staging/slicoss/slicoss.c2
-rw-r--r--drivers/staging/sm7xx/smtcfb.c2
-rw-r--r--drivers/staging/speakup/devsynth.c5
-rw-r--r--drivers/staging/speakup/kobjects.c4
-rw-r--r--drivers/staging/speakup/main.c3
-rw-r--r--drivers/staging/speakup/speakup.h3
-rw-r--r--drivers/staging/speakup/speakup_soft.c11
-rw-r--r--drivers/staging/speakup/varhandlers.c4
-rw-r--r--drivers/staging/spectra/ffsport.c15
-rw-r--r--drivers/staging/spectra/lld_mtd.c6
-rw-r--r--drivers/staging/spectra/lld_nand.c18
-rw-r--r--drivers/staging/ste_rmi4/Makefile1
-rw-r--r--drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c44
-rw-r--r--drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h2
-rw-r--r--drivers/staging/tidspbridge/Kconfig2
-rw-r--r--drivers/staging/tidspbridge/core/dsp-clock.c16
-rw-r--r--drivers/staging/tidspbridge/gen/gh.c2
-rw-r--r--drivers/staging/tidspbridge/hw/hw_mmu.c2
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/host_os.h3
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c4
-rw-r--r--drivers/staging/vme/boards/vme_vmivme7805.c4
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c43
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c26
-rw-r--r--drivers/staging/vme/devices/vme_user.c122
-rw-r--r--drivers/staging/vme/devices/vme_user.h8
-rw-r--r--drivers/staging/vme/vme.c349
-rw-r--r--drivers/staging/vme/vme.h52
-rw-r--r--drivers/staging/vme/vme_api.txt90
-rw-r--r--drivers/staging/vme/vme_bridge.h17
-rw-r--r--drivers/staging/vt6655/IEEE11h.c406
-rw-r--r--drivers/staging/vt6655/bssdb.c2
-rw-r--r--drivers/staging/vt6655/device_main.c23
-rw-r--r--drivers/staging/vt6655/dpc.c30
-rw-r--r--drivers/staging/vt6655/ioctl.c1092
-rw-r--r--drivers/staging/vt6655/rf.c1
-rw-r--r--drivers/staging/vt6655/wmgr.c49
-rw-r--r--drivers/staging/vt6655/wpactl.c4
-rw-r--r--drivers/staging/vt6656/baseband.c3
-rw-r--r--drivers/staging/vt6656/dpc.c30
-rw-r--r--drivers/staging/vt6656/ioctl.c1040
-rw-r--r--drivers/staging/vt6656/main_usb.c13
-rw-r--r--drivers/staging/vt6656/usbpipe.c28
-rw-r--r--drivers/staging/vt6656/wmgr.c49
-rw-r--r--drivers/staging/vt6656/wpactl.c18
-rw-r--r--drivers/staging/winbond/mds_s.h2
-rw-r--r--drivers/staging/winbond/phy_calibration.c470
-rw-r--r--drivers/staging/winbond/wb35reg_s.h2
-rw-r--r--drivers/staging/winbond/wbusb.c3
-rw-r--r--drivers/staging/wlags49_h2/Makefile26
-rw-r--r--drivers/staging/wlags49_h2/debug.h61
-rw-r--r--drivers/staging/wlags49_h2/hcf.c6428
-rw-r--r--drivers/staging/wlags49_h2/hcf.h10
-rw-r--r--drivers/staging/wlags49_h2/hcfcfg.h1586
-rw-r--r--drivers/staging/wlags49_h2/hcfdef.h857
-rw-r--r--drivers/staging/wlags49_h2/mdd.h34
-rw-r--r--drivers/staging/wlags49_h2/wl_cs.c115
-rw-r--r--drivers/staging/wlags49_h2/wl_internal.h23
-rw-r--r--drivers/staging/wlags49_h2/wl_main.c6
-rw-r--r--drivers/staging/wlags49_h2/wl_netdev.c4
-rw-r--r--drivers/staging/wlags49_h2/wl_priv.c9
-rw-r--r--drivers/staging/wlags49_h2/wl_sysfs.c18
-rw-r--r--drivers/staging/wlags49_h2/wl_version.h7
-rw-r--r--drivers/staging/wlags49_h2/wl_wext.c1184
-rw-r--r--drivers/staging/wlags49_h2/wl_wext.h8
-rw-r--r--drivers/staging/wlags49_h25/Makefile26
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c2
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c4
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c1
-rw-r--r--drivers/staging/xgifb/TODO1
-rw-r--r--drivers/staging/xgifb/XGI_main.h238
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c1452
-rw-r--r--drivers/staging/xgifb/XGIfb.h48
-rw-r--r--drivers/staging/xgifb/vb_def.h605
-rw-r--r--drivers/staging/xgifb/vb_ext.c1
-rw-r--r--drivers/staging/xgifb/vb_ext.h20
-rw-r--r--drivers/staging/xgifb/vb_init.c258
-rw-r--r--drivers/staging/xgifb/vb_init.h2
-rw-r--r--drivers/staging/xgifb/vb_setmode.c1536
-rw-r--r--drivers/staging/xgifb/vb_struct.h97
-rw-r--r--drivers/staging/xgifb/vb_table.h1200
-rw-r--r--drivers/staging/xgifb/vb_util.c5
-rw-r--r--drivers/staging/xgifb/vgatypes.h11
-rw-r--r--drivers/staging/zram/Kconfig7
-rw-r--r--drivers/staging/zram/zram_drv.c607
-rw-r--r--drivers/staging/zram/zram_drv.h19
-rw-r--r--drivers/staging/zram/zram_sysfs.c85
-rw-r--r--drivers/target/loopback/Kconfig6
-rw-r--r--drivers/target/loopback/tcm_loop.c285
-rw-r--r--drivers/target/loopback/tcm_loop.h6
-rw-r--r--drivers/target/tcm_fc/Makefile17
-rw-r--r--drivers/target/tcm_fc/tcm_fc.h45
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c233
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c82
-rw-r--r--drivers/target/tcm_fc/tfc_io.c246
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c22
-rw-r--r--drivers/tty/hvc/Kconfig14
-rw-r--r--drivers/tty/hvc/Makefile4
-rw-r--r--drivers/tty/hvc/hvc_console.c72
-rw-r--r--drivers/tty/hvc/hvc_console.h4
-rw-r--r--drivers/tty/hvc/hvc_irq.c2
-rw-r--r--drivers/tty/hvc/hvc_iseries.c1
-rw-r--r--drivers/tty/hvc/hvc_vio.c409
-rw-r--r--drivers/tty/hvc/hvc_xen.c2
-rw-r--r--drivers/tty/hvc/hvcs.c10
-rw-r--r--drivers/tty/hvc/hvsi.c131
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c1
-rw-r--r--drivers/tty/serial/jsm/jsm.h3
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c20
-rw-r--r--drivers/tty/serial/jsm/jsm_neo.c2
-rw-r--r--drivers/tty/vt/consolemap.c2
-rw-r--r--drivers/tty/vt/keyboard.c3
-rw-r--r--drivers/tty/vt/selection.c4
-rw-r--r--drivers/tty/vt/vc_screen.c1
-rw-r--r--drivers/tty/vt/vt.c8
-rw-r--r--drivers/uio/uio.c30
-rw-r--r--drivers/uio/uio_pci_generic.c5
-rw-r--r--drivers/uio/uio_pdrv.c3
-rw-r--r--drivers/uio/uio_pdrv_genirq.c46
-rw-r--r--drivers/usb/atm/ueagle-atm.c38
-rw-r--r--drivers/usb/atm/usbatm.c4
-rw-r--r--drivers/usb/c67x00/c67x00-drv.c1
-rw-r--r--drivers/usb/host/whci/debug.c1
-rw-r--r--drivers/usb/host/whci/hcd.c1
-rw-r--r--drivers/usb/host/whci/init.c2
-rw-r--r--drivers/usb/image/microtek.c2
-rw-r--r--drivers/usb/mon/mon_bin.c1
-rw-r--r--drivers/usb/mon/mon_stat.c1
-rw-r--r--drivers/usb/mon/mon_text.c10
-rw-r--r--drivers/usb/musb/Kconfig81
-rw-r--r--drivers/usb/musb/Makefile4
-rw-r--r--drivers/usb/musb/am35x.c5
-rw-r--r--drivers/usb/musb/blackfin.c1
-rw-r--r--drivers/usb/musb/blackfin.h2
-rw-r--r--drivers/usb/musb/cppi_dma.c1
-rw-r--r--drivers/usb/musb/da8xx.c13
-rw-r--r--drivers/usb/musb/davinci.c8
-rw-r--r--drivers/usb/musb/musb_core.c188
-rw-r--r--drivers/usb/musb/musb_core.h82
-rw-r--r--drivers/usb/musb/musb_debugfs.c6
-rw-r--r--drivers/usb/musb/musb_gadget.c184
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c12
-rw-r--r--drivers/usb/musb/musb_host.c6
-rw-r--r--drivers/usb/musb/musb_host.h4
-rw-r--r--drivers/usb/musb/musb_regs.h6
-rw-r--r--drivers/usb/musb/musb_virthub.c6
-rw-r--r--drivers/usb/musb/musbhsdma.c2
-rw-r--r--drivers/usb/musb/omap2430.c15
-rw-r--r--drivers/usb/musb/tusb6010.c27
-rw-r--r--drivers/usb/musb/tusb6010_omap.c3
-rw-r--r--drivers/usb/musb/ux500_dma.c38
-rw-r--r--drivers/usb/renesas_usbhs/Kconfig15
-rw-r--r--drivers/usb/renesas_usbhs/Makefile10
-rw-r--r--drivers/usb/renesas_usbhs/common.c268
-rw-r--r--drivers/usb/renesas_usbhs/common.h104
-rw-r--r--drivers/usb/renesas_usbhs/mod.c81
-rw-r--r--drivers/usb/renesas_usbhs/mod.h61
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c930
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c472
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h70
-rw-r--r--drivers/usb/wusbcore/cbaf.c4
-rw-r--r--drivers/usb/wusbcore/devconnect.c1
-rw-r--r--drivers/usb/wusbcore/mmc.c1
-rw-r--r--drivers/usb/wusbcore/rh.c1
-rw-r--r--drivers/usb/wusbcore/security.c1
-rw-r--r--drivers/usb/wusbcore/wa-hc.c3
-rw-r--r--drivers/usb/wusbcore/wa-rpipe.c8
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c13
-rw-r--r--drivers/uwb/est.c1
-rw-r--r--drivers/uwb/i1480/dfu/dfu.c1
-rw-r--r--drivers/uwb/ie.c1
-rw-r--r--drivers/uwb/lc-dev.c15
-rw-r--r--drivers/uwb/lc-rc.c1
-rw-r--r--drivers/uwb/neh.c1
-rw-r--r--drivers/uwb/pal.c1
-rw-r--r--drivers/uwb/radio.c1
-rw-r--r--drivers/uwb/reset.c1
-rw-r--r--drivers/uwb/rsv.c1
-rw-r--r--drivers/uwb/scan.c1
-rw-r--r--drivers/uwb/umc-bus.c1
-rw-r--r--drivers/uwb/umc-dev.c1
-rw-r--r--drivers/uwb/umc-drv.c1
-rw-r--r--drivers/uwb/uwb-internal.h1
-rw-r--r--drivers/uwb/uwbd.c2
-rw-r--r--drivers/uwb/whc-rc.c2
-rw-r--r--drivers/uwb/whci.c1
-rw-r--r--drivers/vhost/net.c112
-rw-r--r--drivers/vhost/test.c5
-rw-r--r--drivers/vhost/vhost.c214
-rw-r--r--drivers/vhost/vhost.h34
-rw-r--r--drivers/video/aty/atyfb_base.c7
-rw-r--r--drivers/video/aty/mach64_accel.c3
-rw-r--r--drivers/video/aty/mach64_cursor.c22
-rw-r--r--drivers/video/aty/radeon_base.c10
-rw-r--r--drivers/video/console/bitblit.c3
-rw-r--r--drivers/video/console/fbcon_ccw.c3
-rw-r--r--drivers/video/console/fbcon_cw.c3
-rw-r--r--drivers/video/console/fbcon_ud.c3
-rw-r--r--drivers/video/console/vgacon.c81
-rw-r--r--drivers/video/i810/i810.h2
-rw-r--r--drivers/video/intelfb/intelfbhw.c6
-rw-r--r--drivers/video/logo/.gitignore7
-rw-r--r--drivers/video/logo/logo.c17
-rw-r--r--drivers/video/matrox/matroxfb_accel.c38
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/mb862xx/mb862xx-i2c.c3
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c11
-rw-r--r--drivers/video/mbx/mbxfb.c6
-rw-r--r--drivers/video/msm/mddi.c2
-rw-r--r--drivers/video/msm/mdp.c10
-rw-r--r--drivers/video/msm/msm_fb.c7
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c113
-rw-r--r--drivers/video/omap2/displays/panel-taal.c180
-rw-r--r--drivers/video/omap2/omapfb/Kconfig2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c73
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c302
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c40
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h37
-rw-r--r--drivers/video/pnx4008/sdum.c2
-rw-r--r--drivers/video/riva/fbdev.c5
-rw-r--r--drivers/video/savage/savagefb_accel.c1
-rw-r--r--drivers/video/savage/savagefb_driver.c16
-rw-r--r--drivers/video/sis/sis_main.c30
-rw-r--r--drivers/video/vermilion/vermilion.h2
-rw-r--r--drivers/video/via/dvi.c34
-rw-r--r--drivers/video/via/dvi.h3
-rw-r--r--drivers/video/via/global.c2
-rw-r--r--drivers/video/via/global.h2
-rw-r--r--drivers/video/via/hw.c548
-rw-r--r--drivers/video/via/hw.h285
-rw-r--r--drivers/video/via/lcd.c53
-rw-r--r--drivers/video/via/lcd.h7
-rw-r--r--drivers/video/via/share.h23
-rw-r--r--drivers/video/via/via-core.c2
-rw-r--r--drivers/video/via/via-gpio.c1
-rw-r--r--drivers/video/via/via_modesetting.c104
-rw-r--r--drivers/video/via/via_modesetting.h18
-rw-r--r--drivers/video/via/viafbdev.c170
-rw-r--r--drivers/video/via/viamode.c60
-rw-r--r--drivers/video/via/viamode.h4
-rw-r--r--drivers/virtio/Kconfig14
-rw-r--r--drivers/virtio/Makefile1
-rw-r--r--drivers/virtio/virtio.c20
-rw-r--r--drivers/virtio/virtio_balloon.c7
-rw-r--r--drivers/virtio/virtio_pci.c41
-rw-r--r--drivers/virtio/virtio_ring.c11
-rw-r--r--drivers/w1/masters/ds2490.c4
-rw-r--r--drivers/w1/masters/matrox_w1.c6
-rw-r--r--drivers/w1/slaves/w1_ds2408.c2
-rw-r--r--drivers/w1/slaves/w1_ds2760.c48
-rw-r--r--drivers/w1/slaves/w1_ds2780.c48
-rw-r--r--drivers/w1/slaves/w1_smem.c4
-rw-r--r--drivers/w1/slaves/w1_therm.c13
-rw-r--r--drivers/w1/w1.c6
-rw-r--r--drivers/w1/w1.h2
-rw-r--r--drivers/w1/w1_family.c3
-rw-r--r--drivers/w1/w1_family.h5
-rw-r--r--drivers/w1/w1_int.c5
-rw-r--r--drivers/w1/w1_int.h2
-rw-r--r--drivers/w1/w1_io.c7
-rw-r--r--drivers/w1/w1_log.h2
-rw-r--r--drivers/w1/w1_netlink.c27
-rw-r--r--drivers/w1/w1_netlink.h2
2180 files changed, 93745 insertions, 75572 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 026f9aa..44fde43 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -61,6 +61,7 @@
#include <linux/sched.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
+#include <linux/module.h>
#include <asm/mwait.h>
#include <asm/msr.h>
@@ -81,7 +82,8 @@ static unsigned int mwait_substates;
static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
+static int intel_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index);
static struct cpuidle_state *cpuidle_state_table;
@@ -109,7 +111,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C1 */
.name = "C1-NHM",
.desc = "MWAIT 0x00",
- .driver_data = (void *) 0x00,
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 3,
.target_residency = 6,
@@ -117,7 +118,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C2 */
.name = "C3-NHM",
.desc = "MWAIT 0x10",
- .driver_data = (void *) 0x10,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 20,
.target_residency = 80,
@@ -125,7 +125,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C3 */
.name = "C6-NHM",
.desc = "MWAIT 0x20",
- .driver_data = (void *) 0x20,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 200,
.target_residency = 800,
@@ -137,7 +136,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C1 */
.name = "C1-SNB",
.desc = "MWAIT 0x00",
- .driver_data = (void *) 0x00,
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 1,
.target_residency = 1,
@@ -145,7 +143,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C2 */
.name = "C3-SNB",
.desc = "MWAIT 0x10",
- .driver_data = (void *) 0x10,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 80,
.target_residency = 211,
@@ -153,7 +150,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C3 */
.name = "C6-SNB",
.desc = "MWAIT 0x20",
- .driver_data = (void *) 0x20,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 104,
.target_residency = 345,
@@ -161,19 +157,49 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C4 */
.name = "C7-SNB",
.desc = "MWAIT 0x30",
- .driver_data = (void *) 0x30,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 109,
.target_residency = 345,
.enter = &intel_idle },
};
+static struct cpuidle_state ivb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C0 */ },
+ { /* MWAIT C1 */
+ .name = "C1-IVB",
+ .desc = "MWAIT 0x00",
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 1,
+ .target_residency = 1,
+ .enter = &intel_idle },
+ { /* MWAIT C2 */
+ .name = "C3-IVB",
+ .desc = "MWAIT 0x10",
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 59,
+ .target_residency = 156,
+ .enter = &intel_idle },
+ { /* MWAIT C3 */
+ .name = "C6-IVB",
+ .desc = "MWAIT 0x20",
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 80,
+ .target_residency = 300,
+ .enter = &intel_idle },
+ { /* MWAIT C4 */
+ .name = "C7-IVB",
+ .desc = "MWAIT 0x30",
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 87,
+ .target_residency = 300,
+ .enter = &intel_idle },
+};
+
static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C0 */ },
{ /* MWAIT C1 */
.name = "C1-ATM",
.desc = "MWAIT 0x00",
- .driver_data = (void *) 0x00,
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 1,
.target_residency = 4,
@@ -181,7 +207,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C2 */
.name = "C2-ATM",
.desc = "MWAIT 0x10",
- .driver_data = (void *) 0x10,
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 20,
.target_residency = 80,
@@ -190,7 +215,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C4 */
.name = "C4-ATM",
.desc = "MWAIT 0x30",
- .driver_data = (void *) 0x30,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 100,
.target_residency = 400,
@@ -199,23 +223,55 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C6 */
.name = "C6-ATM",
.desc = "MWAIT 0x52",
- .driver_data = (void *) 0x52,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 140,
.target_residency = 560,
.enter = &intel_idle },
};
+static int get_driver_data(int cstate)
+{
+ int driver_data;
+ switch (cstate) {
+
+ case 1: /* MWAIT C1 */
+ driver_data = 0x00;
+ break;
+ case 2: /* MWAIT C2 */
+ driver_data = 0x10;
+ break;
+ case 3: /* MWAIT C3 */
+ driver_data = 0x20;
+ break;
+ case 4: /* MWAIT C4 */
+ driver_data = 0x30;
+ break;
+ case 5: /* MWAIT C5 */
+ driver_data = 0x40;
+ break;
+ case 6: /* MWAIT C6 */
+ driver_data = 0x52;
+ break;
+ default:
+ driver_data = 0x00;
+ }
+ return driver_data;
+}
+
/**
* intel_idle
* @dev: cpuidle_device
- * @state: cpuidle state
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
*
*/
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
+static int intel_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
{
unsigned long ecx = 1; /* break on interrupt flag */
- unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
+ struct cpuidle_state *state = &drv->states[index];
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+ unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
unsigned int cstate;
ktime_t kt_before, kt_after;
s64 usec_delta;
@@ -256,7 +312,10 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
if (!(lapic_timer_reliable_states & (1 << (cstate))))
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
- return usec_delta;
+ /* Update cpuidle counters */
+ dev->last_residency = (int)usec_delta;
+
+ return index;
}
static void __setup_broadcast_timer(void *arg)
@@ -359,6 +418,11 @@ static int intel_idle_probe(void)
cpuidle_state_table = snb_cstates;
break;
+ case 0x3A: /* IVB */
+ case 0x3E: /* IVB Xeon */
+ cpuidle_state_table = ivb_cstates;
+ break;
+
default:
pr_debug(PREFIX "does not run on family %d model %d\n",
boot_cpu_data.x86, boot_cpu_data.x86_model);
@@ -367,10 +431,8 @@ static int intel_idle_probe(void)
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
- else {
+ else
on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
- register_cpu_notifier(&setup_broadcast_notifier);
- }
pr_debug(PREFIX "v" INTEL_IDLE_VERSION
" model 0x%X\n", boot_cpu_data.x86_model);
@@ -398,6 +460,60 @@ static void intel_idle_cpuidle_devices_uninit(void)
return;
}
/*
+ * intel_idle_cpuidle_driver_init()
+ * allocate, initialize cpuidle_states
+ */
+static int intel_idle_cpuidle_driver_init(void)
+{
+ int cstate;
+ struct cpuidle_driver *drv = &intel_idle_driver;
+
+ drv->state_count = 1;
+
+ for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
+ int num_substates;
+
+ if (cstate > max_cstate) {
+ printk(PREFIX "max_cstate %d reached\n",
+ max_cstate);
+ break;
+ }
+
+ /* does the state exist in CPUID.MWAIT? */
+ num_substates = (mwait_substates >> ((cstate) * 4))
+ & MWAIT_SUBSTATE_MASK;
+ if (num_substates == 0)
+ continue;
+ /* is the state not enabled? */
+ if (cpuidle_state_table[cstate].enter == NULL) {
+ /* does the driver not know about the state? */
+ if (*cpuidle_state_table[cstate].name == '\0')
+ pr_debug(PREFIX "unaware of model 0x%x"
+ " MWAIT %d please"
+ " contact lenb@kernel.org",
+ boot_cpu_data.x86_model, cstate);
+ continue;
+ }
+
+ if ((cstate > 2) &&
+ !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ mark_tsc_unstable("TSC halts in idle"
+ " states deeper than C2");
+
+ drv->states[drv->state_count] = /* structure copy */
+ cpuidle_state_table[cstate];
+
+ drv->state_count += 1;
+ }
+
+ if (auto_demotion_disable_flags)
+ on_each_cpu(auto_demotion_disable, NULL, 1);
+
+ return 0;
+}
+
+
+/*
* intel_idle_cpuidle_devices_init()
* allocate, initialize, register cpuidle_devices
*/
@@ -431,22 +547,11 @@ static int intel_idle_cpuidle_devices_init(void)
continue;
/* is the state not enabled? */
if (cpuidle_state_table[cstate].enter == NULL) {
- /* does the driver not know about the state? */
- if (*cpuidle_state_table[cstate].name == '\0')
- pr_debug(PREFIX "unaware of model 0x%x"
- " MWAIT %d please"
- " contact lenb@kernel.org",
- boot_cpu_data.x86_model, cstate);
continue;
}
- if ((cstate > 2) &&
- !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
- mark_tsc_unstable("TSC halts in idle"
- " states deeper than C2");
-
- dev->states[dev->state_count] = /* structure copy */
- cpuidle_state_table[cstate];
+ dev->states_usage[dev->state_count].driver_data =
+ (void *)get_driver_data(cstate);
dev->state_count += 1;
}
@@ -459,8 +564,6 @@ static int intel_idle_cpuidle_devices_init(void)
return -EIO;
}
}
- if (auto_demotion_disable_flags)
- on_each_cpu(auto_demotion_disable, NULL, 1);
return 0;
}
@@ -478,10 +581,12 @@ static int __init intel_idle_init(void)
if (retval)
return retval;
+ intel_idle_cpuidle_driver_init();
retval = cpuidle_register_driver(&intel_idle_driver);
if (retval) {
+ struct cpuidle_driver *drv = cpuidle_get_driver();
printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
- cpuidle_get_driver()->name);
+ drv ? drv->name : "none");
return retval;
}
@@ -491,6 +596,9 @@ static int __init intel_idle_init(void)
return retval;
}
+ if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+ register_cpu_notifier(&setup_broadcast_notifier);
+
return 0;
}
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index 6899913..800a389 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1 @@
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
-
-ccflags-y := -DDEBUG -DCONFIG_FFD
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
index a5a49a1..eb0e2cc 100644
--- a/drivers/ieee802154/fakehard.c
+++ b/drivers/ieee802154/fakehard.c
@@ -370,8 +370,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
return -ENOMEM;
}
- phy->dev.platform_data = dev;
-
memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
dev->addr_len);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index f2a84c6..e9cf51b 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -37,6 +37,7 @@
#include <linux/inetdevice.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/module.h>
#include <net/arp.h>
#include <net/neighbour.h>
#include <net/route.h>
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index f9ba7d7..9353992 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -302,7 +302,8 @@ static void ib_cache_event(struct ib_event_handler *handler,
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_SM_CHANGE ||
- event->event == IB_EVENT_CLIENT_REREGISTER) {
+ event->event == IB_EVENT_CLIENT_REREGISTER ||
+ event->event == IB_EVENT_GID_CHANGE) {
work = kmalloc(sizeof *work, GFP_ATOMIC);
if (work) {
INIT_WORK(&work->work, ib_cache_task);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index fc0f2bd..8b72f39 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -36,6 +36,7 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
+#include <linux/module.h>
#include <linux/err.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
@@ -889,6 +890,8 @@ retest:
break;
case IB_CM_ESTABLISHED:
spin_unlock_irq(&cm_id_priv->lock);
+ if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
+ break;
ib_send_cm_dreq(cm_id, NULL, 0);
goto retest;
case IB_CM_DREQ_SENT:
@@ -1008,7 +1011,6 @@ static void cm_format_req(struct cm_req_msg *req_msg,
req_msg->service_id = param->service_id;
req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
- cm_req_set_resp_res(req_msg, param->responder_resources);
cm_req_set_init_depth(req_msg, param->initiator_depth);
cm_req_set_remote_resp_timeout(req_msg,
param->remote_cm_response_timeout);
@@ -1017,12 +1019,16 @@ static void cm_format_req(struct cm_req_msg *req_msg,
cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
cm_req_set_local_resp_timeout(req_msg,
param->local_cm_response_timeout);
- cm_req_set_retry_count(req_msg, param->retry_count);
req_msg->pkey = param->primary_path->pkey;
cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
- cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
- cm_req_set_srq(req_msg, param->srq);
+
+ if (param->qp_type != IB_QPT_XRC_INI) {
+ cm_req_set_resp_res(req_msg, param->responder_resources);
+ cm_req_set_retry_count(req_msg, param->retry_count);
+ cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
+ cm_req_set_srq(req_msg, param->srq);
+ }
if (pri_path->hop_limit <= 1) {
req_msg->primary_local_lid = pri_path->slid;
@@ -1080,7 +1086,8 @@ static int cm_validate_req_param(struct ib_cm_req_param *param)
if (!param->primary_path)
return -EINVAL;
- if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC)
+ if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC &&
+ param->qp_type != IB_QPT_XRC_INI)
return -EINVAL;
if (param->private_data &&
@@ -1601,18 +1608,24 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
rep_msg->local_comm_id = cm_id_priv->id.local_id;
rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
- cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
rep_msg->resp_resources = param->responder_resources;
- rep_msg->initiator_depth = param->initiator_depth;
cm_rep_set_target_ack_delay(rep_msg,
cm_id_priv->av.port->cm_dev->ack_delay);
cm_rep_set_failover(rep_msg, param->failover_accepted);
- cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
- cm_rep_set_srq(rep_msg, param->srq);
rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
+ if (cm_id_priv->qp_type != IB_QPT_XRC_TGT) {
+ rep_msg->initiator_depth = param->initiator_depth;
+ cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
+ cm_rep_set_srq(rep_msg, param->srq);
+ cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
+ } else {
+ cm_rep_set_srq(rep_msg, 1);
+ cm_rep_set_local_eecn(rep_msg, cpu_to_be32(param->qp_num));
+ }
+
if (param->private_data && param->private_data_len)
memcpy(rep_msg->private_data, param->private_data,
param->private_data_len);
@@ -1660,7 +1673,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
cm_id_priv->initiator_depth = param->initiator_depth;
cm_id_priv->responder_resources = param->responder_resources;
cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
- cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);
+ cm_id_priv->local_qpn = cpu_to_be32(param->qp_num & 0xFFFFFF);
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
return ret;
@@ -1731,7 +1744,7 @@ error: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
}
EXPORT_SYMBOL(ib_send_cm_rtu);
-static void cm_format_rep_event(struct cm_work *work)
+static void cm_format_rep_event(struct cm_work *work, enum ib_qp_type qp_type)
{
struct cm_rep_msg *rep_msg;
struct ib_cm_rep_event_param *param;
@@ -1740,7 +1753,7 @@ static void cm_format_rep_event(struct cm_work *work)
param = &work->cm_event.param.rep_rcvd;
param->remote_ca_guid = rep_msg->local_ca_guid;
param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
- param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));
+ param->remote_qpn = be32_to_cpu(cm_rep_get_qpn(rep_msg, qp_type));
param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
param->responder_resources = rep_msg->initiator_depth;
param->initiator_depth = rep_msg->resp_resources;
@@ -1808,7 +1821,7 @@ static int cm_rep_handler(struct cm_work *work)
return -EINVAL;
}
- cm_format_rep_event(work);
+ cm_format_rep_event(work, cm_id_priv->qp_type);
spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) {
@@ -1823,7 +1836,7 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
- cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+ cm_id_priv->timewait_info->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
spin_lock(&cm.lock);
/* Check for duplicate REP. */
@@ -1850,7 +1863,7 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->id.state = IB_CM_REP_RCVD;
cm_id_priv->id.remote_id = rep_msg->local_comm_id;
- cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+ cm_id_priv->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
cm_id_priv->initiator_depth = rep_msg->resp_resources;
cm_id_priv->responder_resources = rep_msg->initiator_depth;
cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
@@ -3492,7 +3505,8 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
qp_attr->path_mtu = cm_id_priv->path_mtu;
qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
- if (cm_id_priv->qp_type == IB_QPT_RC) {
+ if (cm_id_priv->qp_type == IB_QPT_RC ||
+ cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER;
qp_attr->max_dest_rd_atomic =
@@ -3537,15 +3551,21 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
- if (cm_id_priv->qp_type == IB_QPT_RC) {
- *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
- IB_QP_RNR_RETRY |
+ switch (cm_id_priv->qp_type) {
+ case IB_QPT_RC:
+ case IB_QPT_XRC_INI:
+ *qp_attr_mask |= IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
IB_QP_MAX_QP_RD_ATOMIC;
- qp_attr->timeout = cm_id_priv->av.timeout;
qp_attr->retry_cnt = cm_id_priv->retry_count;
qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
- qp_attr->max_rd_atomic =
- cm_id_priv->initiator_depth;
+ qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+ /* fall through */
+ case IB_QPT_XRC_TGT:
+ *qp_attr_mask |= IB_QP_TIMEOUT;
+ qp_attr->timeout = cm_id_priv->av.timeout;
+ break;
+ default:
+ break;
}
if (cm_id_priv->alt_av.ah_attr.dlid) {
*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 7e63c08..505db2a 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
*
@@ -86,7 +86,7 @@ struct cm_req_msg {
__be16 pkey;
/* path MTU:4, RDC exists:1, RNR retry count:3. */
u8 offset50;
- /* max CM Retries:4, SRQ:1, rsvd:3 */
+ /* max CM Retries:4, SRQ:1, extended transport type:3 */
u8 offset51;
__be16 primary_local_lid;
@@ -175,6 +175,11 @@ static inline enum ib_qp_type cm_req_get_qp_type(struct cm_req_msg *req_msg)
switch(transport_type) {
case 0: return IB_QPT_RC;
case 1: return IB_QPT_UC;
+ case 3:
+ switch (req_msg->offset51 & 0x7) {
+ case 1: return IB_QPT_XRC_TGT;
+ default: return 0;
+ }
default: return 0;
}
}
@@ -188,6 +193,12 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
req_msg->offset40) &
0xFFFFFFF9) | 0x2);
break;
+ case IB_QPT_XRC_INI:
+ req_msg->offset40 = cpu_to_be32((be32_to_cpu(
+ req_msg->offset40) &
+ 0xFFFFFFF9) | 0x6);
+ req_msg->offset51 = (req_msg->offset51 & 0xF8) | 1;
+ break;
default:
req_msg->offset40 = cpu_to_be32(be32_to_cpu(
req_msg->offset40) &
@@ -527,6 +538,23 @@ static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
(be32_to_cpu(rep_msg->offset12) & 0x000000FF));
}
+static inline __be32 cm_rep_get_local_eecn(struct cm_rep_msg *rep_msg)
+{
+ return cpu_to_be32(be32_to_cpu(rep_msg->offset16) >> 8);
+}
+
+static inline void cm_rep_set_local_eecn(struct cm_rep_msg *rep_msg, __be32 eecn)
+{
+ rep_msg->offset16 = cpu_to_be32((be32_to_cpu(eecn) << 8) |
+ (be32_to_cpu(rep_msg->offset16) & 0x000000FF));
+}
+
+static inline __be32 cm_rep_get_qpn(struct cm_rep_msg *rep_msg, enum ib_qp_type qp_type)
+{
+ return (qp_type == IB_QPT_XRC_INI) ?
+ cm_rep_get_local_eecn(rep_msg) : cm_rep_get_local_qpn(rep_msg);
+}
+
static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b6a33b3..d0d4aa9 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -41,6 +41,7 @@
#include <linux/idr.h>
#include <linux/inetdevice.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <net/tcp.h>
#include <net/ipv6.h>
@@ -81,6 +82,7 @@ static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps);
static DEFINE_IDR(ipoib_ps);
+static DEFINE_IDR(ib_ps);
struct cma_device {
struct list_head list;
@@ -359,6 +361,10 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
+ if (dev_ll != IB_LINK_LAYER_INFINIBAND &&
+ id_priv->id.ps == RDMA_PS_IPOIB)
+ return -EINVAL;
+
mutex_lock(&lock);
iboe_addr_get_sgid(dev_addr, &iboe_gid);
memcpy(&gid, dev_addr->src_dev_addr +
@@ -406,11 +412,6 @@ static int cma_disable_callback(struct rdma_id_private *id_priv,
return 0;
}
-static int cma_has_cm_dev(struct rdma_id_private *id_priv)
-{
- return (id_priv->id.device && id_priv->cm_id.ib);
-}
-
struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
void *context, enum rdma_port_space ps,
enum ib_qp_type qp_type)
@@ -920,11 +921,11 @@ void rdma_destroy_id(struct rdma_cm_id *id)
if (id_priv->cma_dev) {
switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+ if (id_priv->cm_id.ib)
ib_destroy_cm_id(id_priv->cm_id.ib);
break;
case RDMA_TRANSPORT_IWARP:
- if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw))
+ if (id_priv->cm_id.iw)
iw_destroy_cm_id(id_priv->cm_id.iw);
break;
default:
@@ -1085,12 +1086,12 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
if (cma_get_net_info(ib_event->private_data, listen_id->ps,
&ip_ver, &port, &src, &dst))
- goto err;
+ return NULL;
id = rdma_create_id(listen_id->event_handler, listen_id->context,
listen_id->ps, ib_event->param.req_rcvd.qp_type);
if (IS_ERR(id))
- goto err;
+ return NULL;
cma_save_net_info(&id->route.addr, &listen_id->route.addr,
ip_ver, port, src, dst);
@@ -1100,7 +1101,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,
GFP_KERNEL);
if (!rt->path_rec)
- goto destroy_id;
+ goto err;
rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
if (rt->num_paths == 2)
@@ -1114,7 +1115,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
&rt->addr.dev_addr);
if (ret)
- goto destroy_id;
+ goto err;
}
rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
@@ -1122,9 +1123,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
id_priv->state = RDMA_CM_CONNECT;
return id_priv;
-destroy_id:
- rdma_destroy_id(id);
err:
+ rdma_destroy_id(id);
return NULL;
}
@@ -1181,6 +1181,15 @@ static void cma_set_req_event_data(struct rdma_cm_event *event,
event->param.conn.qp_num = req_data->remote_qpn;
}
+static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
+{
+ return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
+ (ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
+ ((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
+ (id->qp_type == IB_QPT_UD)) ||
+ (!id->qp_type));
+}
+
static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{
struct rdma_id_private *listen_id, *conn_id;
@@ -1188,13 +1197,16 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
int offset, ret;
listen_id = cm_id->context;
+ if (!cma_check_req_qp_type(&listen_id->id, ib_event))
+ return -EINVAL;
+
if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
return -ECONNABORTED;
memset(&event, 0, sizeof event);
offset = cma_user_data_offset(listen_id->id.ps);
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
- if (listen_id->id.qp_type == IB_QPT_UD) {
+ if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
conn_id = cma_new_udp_id(&listen_id->id, ib_event);
event.param.ud.private_data = ib_event->private_data + offset;
event.param.ud.private_data_len =
@@ -1330,6 +1342,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
switch (iw_event->status) {
case 0:
event.event = RDMA_CM_EVENT_ESTABLISHED;
+ event.param.conn.initiator_depth = iw_event->ird;
+ event.param.conn.responder_resources = iw_event->ord;
break;
case -ECONNRESET:
case -ECONNREFUSED:
@@ -1345,6 +1359,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
break;
case IW_CM_EVENT_ESTABLISHED:
event.event = RDMA_CM_EVENT_ESTABLISHED;
+ event.param.conn.initiator_depth = iw_event->ird;
+ event.param.conn.responder_resources = iw_event->ord;
break;
default:
BUG_ON(1);
@@ -1435,8 +1451,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
event.param.conn.private_data = iw_event->private_data;
event.param.conn.private_data_len = iw_event->private_data_len;
- event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
- event.param.conn.responder_resources = attr.max_qp_rd_atom;
+ event.param.conn.initiator_depth = iw_event->ird;
+ event.param.conn.responder_resources = iw_event->ord;
/*
* Protect against the user destroying conn_id from another thread
@@ -1468,13 +1484,15 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)
{
struct ib_cm_compare_data compare_data;
struct sockaddr *addr;
+ struct ib_cm_id *id;
__be64 svc_id;
int ret;
- id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
- id_priv);
- if (IS_ERR(id_priv->cm_id.ib))
- return PTR_ERR(id_priv->cm_id.ib);
+ id = ib_create_cm_id(id_priv->id.device, cma_req_handler, id_priv);
+ if (IS_ERR(id))
+ return PTR_ERR(id);
+
+ id_priv->cm_id.ib = id;
addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
svc_id = cma_get_service_id(id_priv->id.ps, addr);
@@ -1497,12 +1515,15 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
{
int ret;
struct sockaddr_in *sin;
+ struct iw_cm_id *id;
+
+ id = iw_create_cm_id(id_priv->id.device,
+ iw_conn_req_handler,
+ id_priv);
+ if (IS_ERR(id))
+ return PTR_ERR(id);
- id_priv->cm_id.iw = iw_create_cm_id(id_priv->id.device,
- iw_conn_req_handler,
- id_priv);
- if (IS_ERR(id_priv->cm_id.iw))
- return PTR_ERR(id_priv->cm_id.iw);
+ id_priv->cm_id.iw = id;
sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
id_priv->cm_id.iw->local_addr = *sin;
@@ -2231,6 +2252,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
case RDMA_PS_IPOIB:
ps = &ipoib_ps;
break;
+ case RDMA_PS_IB:
+ ps = &ib_ps;
+ break;
default:
return -EPROTONOSUPPORT;
}
@@ -2484,10 +2508,14 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
{
struct ib_cm_sidr_req_param req;
struct rdma_route *route;
+ struct ib_cm_id *id;
int ret;
req.private_data_len = sizeof(struct cma_hdr) +
conn_param->private_data_len;
+ if (req.private_data_len < conn_param->private_data_len)
+ return -EINVAL;
+
req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
if (!req.private_data)
return -ENOMEM;
@@ -2501,12 +2529,13 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
if (ret)
goto out;
- id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,
- cma_sidr_rep_handler, id_priv);
- if (IS_ERR(id_priv->cm_id.ib)) {
- ret = PTR_ERR(id_priv->cm_id.ib);
+ id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler,
+ id_priv);
+ if (IS_ERR(id)) {
+ ret = PTR_ERR(id);
goto out;
}
+ id_priv->cm_id.ib = id;
req.path = route->path_rec;
req.service_id = cma_get_service_id(id_priv->id.ps,
@@ -2530,11 +2559,15 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
struct ib_cm_req_param req;
struct rdma_route *route;
void *private_data;
+ struct ib_cm_id *id;
int offset, ret;
memset(&req, 0, sizeof req);
offset = cma_user_data_offset(id_priv->id.ps);
req.private_data_len = offset + conn_param->private_data_len;
+ if (req.private_data_len < conn_param->private_data_len)
+ return -EINVAL;
+
private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
if (!private_data)
return -ENOMEM;
@@ -2543,12 +2576,12 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
memcpy(private_data + offset, conn_param->private_data,
conn_param->private_data_len);
- id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
- id_priv);
- if (IS_ERR(id_priv->cm_id.ib)) {
- ret = PTR_ERR(id_priv->cm_id.ib);
+ id = ib_create_cm_id(id_priv->id.device, cma_ib_handler, id_priv);
+ if (IS_ERR(id)) {
+ ret = PTR_ERR(id);
goto out;
}
+ id_priv->cm_id.ib = id;
route = &id_priv->id.route;
ret = cma_format_hdr(private_data, id_priv->id.ps, route);
@@ -2563,7 +2596,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
req.service_id = cma_get_service_id(id_priv->id.ps,
(struct sockaddr *) &route->addr.dst_addr);
req.qp_num = id_priv->qp_num;
- req.qp_type = IB_QPT_RC;
+ req.qp_type = id_priv->id.qp_type;
req.starting_psn = id_priv->seq_num;
req.responder_resources = conn_param->responder_resources;
req.initiator_depth = conn_param->initiator_depth;
@@ -2577,8 +2610,8 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
out:
- if (ret && !IS_ERR(id_priv->cm_id.ib)) {
- ib_destroy_cm_id(id_priv->cm_id.ib);
+ if (ret && !IS_ERR(id)) {
+ ib_destroy_cm_id(id);
id_priv->cm_id.ib = NULL;
}
@@ -2595,10 +2628,8 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
struct iw_cm_conn_param iw_param;
cm_id = iw_create_cm_id(id_priv->id.device, cma_iw_handler, id_priv);
- if (IS_ERR(cm_id)) {
- ret = PTR_ERR(cm_id);
- goto out;
- }
+ if (IS_ERR(cm_id))
+ return PTR_ERR(cm_id);
id_priv->cm_id.iw = cm_id;
@@ -2612,17 +2643,19 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
if (ret)
goto out;
- iw_param.ord = conn_param->initiator_depth;
- iw_param.ird = conn_param->responder_resources;
- iw_param.private_data = conn_param->private_data;
- iw_param.private_data_len = conn_param->private_data_len;
- if (id_priv->id.qp)
+ if (conn_param) {
+ iw_param.ord = conn_param->initiator_depth;
+ iw_param.ird = conn_param->responder_resources;
+ iw_param.private_data = conn_param->private_data;
+ iw_param.private_data_len = conn_param->private_data_len;
+ iw_param.qpn = id_priv->id.qp ? id_priv->qp_num : conn_param->qp_num;
+ } else {
+ memset(&iw_param, 0, sizeof iw_param);
iw_param.qpn = id_priv->qp_num;
- else
- iw_param.qpn = conn_param->qp_num;
+ }
ret = iw_cm_connect(cm_id, &iw_param);
out:
- if (ret && !IS_ERR(cm_id)) {
+ if (ret) {
iw_destroy_cm_id(cm_id);
id_priv->cm_id.iw = NULL;
}
@@ -2761,14 +2794,20 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id->qp_type == IB_QPT_UD)
- ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
- conn_param->private_data,
- conn_param->private_data_len);
- else if (conn_param)
- ret = cma_accept_ib(id_priv, conn_param);
- else
- ret = cma_rep_recv(id_priv);
+ if (id->qp_type == IB_QPT_UD) {
+ if (conn_param)
+ ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+ conn_param->private_data,
+ conn_param->private_data_len);
+ else
+ ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+ NULL, 0);
+ } else {
+ if (conn_param)
+ ret = cma_accept_ib(id_priv, conn_param);
+ else
+ ret = cma_rep_recv(id_priv);
+ }
break;
case RDMA_TRANSPORT_IWARP:
ret = cma_accept_iw(id_priv, conn_param);
@@ -2795,7 +2834,7 @@ int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_has_cm_dev(id_priv))
+ if (!id_priv->cm_id.ib)
return -EINVAL;
switch (id->device->node_type) {
@@ -2817,7 +2856,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_has_cm_dev(id_priv))
+ if (!id_priv->cm_id.ib)
return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) {
@@ -2848,7 +2887,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_has_cm_dev(id_priv))
+ if (!id_priv->cm_id.ib)
return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) {
@@ -3456,6 +3495,7 @@ static void __exit cma_cleanup(void)
idr_destroy(&tcp_ps);
idr_destroy(&udp_ps);
idr_destroy(&ipoib_ps);
+ idr_destroy(&ib_ps);
}
module_init(cma_init);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 4007f72..e711de4 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -627,6 +627,9 @@ int ib_modify_device(struct ib_device *device,
int device_modify_mask,
struct ib_device_modify *device_modify)
{
+ if (!device->modify_device)
+ return -ENOSYS;
+
return device->modify_device(device, device_modify_mask,
device_modify);
}
@@ -647,6 +650,9 @@ int ib_modify_port(struct ib_device *device,
u8 port_num, int port_modify_mask,
struct ib_port_modify *port_modify)
{
+ if (!device->modify_port)
+ return -ENOSYS;
+
if (port_num < start_port(device) || port_num > end_port(device))
return -EINVAL;
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 4507043..176c8f9 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -33,6 +33,7 @@
#include <linux/errno.h>
#include <linux/spinlock.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/jhash.h>
#include <linux/kthread.h>
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index a9c0423..2882556 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -45,6 +45,8 @@
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/sysctl.h>
#include <rdma/iw_cm.h>
#include <rdma/ib_addr.h>
@@ -64,6 +66,20 @@ struct iwcm_work {
struct list_head free_list;
};
+static unsigned int default_backlog = 256;
+
+static struct ctl_table_header *iwcm_ctl_table_hdr;
+static struct ctl_table iwcm_ctl_table[] = {
+ {
+ .procname = "default_backlog",
+ .data = &default_backlog,
+ .maxlen = sizeof(default_backlog),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ { }
+};
+
/*
* The following services provide a mechanism for pre-allocating iwcm_work
* elements. The design pre-allocates them based on the cm_id type:
@@ -418,6 +434,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
+ if (!backlog)
+ backlog = default_backlog;
+
ret = alloc_work_entries(cm_id_priv, backlog);
if (ret)
return ret;
@@ -1013,17 +1032,33 @@ int iw_cm_init_qp_attr(struct iw_cm_id *cm_id,
}
EXPORT_SYMBOL(iw_cm_init_qp_attr);
+static struct ctl_path iwcm_ctl_path[] = {
+ { .procname = "net" },
+ { .procname = "iw_cm" },
+ { }
+};
+
static int __init iw_cm_init(void)
{
iwcm_wq = create_singlethread_workqueue("iw_cm_wq");
if (!iwcm_wq)
return -ENOMEM;
+ iwcm_ctl_table_hdr = register_net_sysctl_table(&init_net,
+ iwcm_ctl_path,
+ iwcm_ctl_table);
+ if (!iwcm_ctl_table_hdr) {
+ pr_err("iw_cm: couldn't register sysctl paths\n");
+ destroy_workqueue(iwcm_wq);
+ return -ENOMEM;
+ }
+
return 0;
}
static void __exit iw_cm_cleanup(void)
{
+ unregister_net_sysctl_table(iwcm_ctl_table_hdr);
destroy_workqueue(iwcm_wq);
}
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index b4d8672..2fe428b 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -35,6 +35,7 @@
*/
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <rdma/ib_cache.h>
#include "mad_priv.h"
@@ -1596,6 +1597,9 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
mad->mad_hdr.class_version].class;
if (!class)
goto out;
+ if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
+ IB_MGMT_MAX_METHODS)
+ goto out;
method = class->method_table[convert_mgmt_class(
mad->mad_hdr.mgmt_class)];
if (method)
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 68b4162..d2360a8 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -34,6 +34,7 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/random.h>
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index 9227f4a..d1c8196 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -32,6 +32,7 @@
#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
+#include <linux/export.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#include <net/sock.h>
diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c
index 019bd4b..1b65986 100644
--- a/drivers/infiniband/core/packer.c
+++ b/drivers/infiniband/core/packer.c
@@ -31,6 +31,7 @@
* SOFTWARE.
*/
+#include <linux/export.h>
#include <linux/string.h>
#include <rdma/ib_pack.h>
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 9ab5df7..c61bca3 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -35,6 +35,7 @@
#include "core_priv.h"
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/string.h>
#include <rdma/ib_mad.h>
@@ -185,17 +186,35 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
if (ret)
return ret;
+ rate = (25 * attr.active_speed) / 10;
+
switch (attr.active_speed) {
- case 2: speed = " DDR"; break;
- case 4: speed = " QDR"; break;
+ case 2:
+ speed = " DDR";
+ break;
+ case 4:
+ speed = " QDR";
+ break;
+ case 8:
+ speed = " FDR10";
+ rate = 10;
+ break;
+ case 16:
+ speed = " FDR";
+ rate = 14;
+ break;
+ case 32:
+ speed = " EDR";
+ rate = 25;
+ break;
}
- rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
+ rate *= ib_width_enum_to_int(attr.active_width);
if (rate < 0)
return -EINVAL;
return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
- rate / 10, rate % 10 ? ".5" : "",
+ rate, (attr.active_speed == 1) ? ".5" : "",
ib_width_enum_to_int(attr.active_width), speed);
}
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 08f948d..b8a0b4a 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1122,7 +1122,7 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT;
- if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
+ if (hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
return -EINVAL;
if (hdr.in + sizeof(hdr) > len)
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 71be5ee..b37b0c0 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -41,6 +41,7 @@
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
+#include <linux/module.h>
#include <rdma/rdma_user_cm.h>
#include <rdma/ib_marshall.h>
@@ -276,7 +277,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
ucma_set_event_context(ctx, event, uevent);
uevent->resp.event = event->event;
uevent->resp.status = event->status;
- if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
+ if (cm_id->qp_type == IB_QPT_UD)
ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
else
ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -377,6 +378,9 @@ static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_
case RDMA_PS_IPOIB:
*qp_type = IB_QPT_UD;
return 0;
+ case RDMA_PS_IB:
+ *qp_type = cmd->qp_type;
+ return 0;
default:
return -EINVAL;
}
@@ -1270,7 +1274,7 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT;
- if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
+ if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
return -EINVAL;
if (hdr.in + sizeof(hdr) > len)
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c
index 9b737ff..72feee6 100644
--- a/drivers/infiniband/core/ud_header.c
+++ b/drivers/infiniband/core/ud_header.c
@@ -33,6 +33,7 @@
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/export.h>
#include <linux/if_ether.h>
#include <rdma/ib_pack.h>
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index b645e55..c1fef27 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -35,6 +35,7 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/sched.h>
+#include <linux/export.h>
#include <linux/hugetlb.h>
#include <linux/dma-attrs.h>
#include <linux/slab.h>
@@ -93,6 +94,17 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
if (dmasync)
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
+ if (!size)
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * If the combination of the addr and size requested for this memory
+ * region causes an integer overflow, return error.
+ */
+ if (((addr + size) < addr) ||
+ PAGE_ALIGN(addr + size) < (addr + size))
+ return ERR_PTR(-EINVAL);
+
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -136,7 +148,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
down_write(&current->mm->mmap_sem);
- locked = npages + current->mm->locked_vm;
+ locked = npages + current->mm->pinned_vm;
lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
@@ -206,7 +218,7 @@ out:
__ib_umem_release(context->device, umem, 0);
kfree(umem);
} else
- current->mm->locked_vm = locked;
+ current->mm->pinned_vm = locked;
up_write(&current->mm->mmap_sem);
if (vma_list)
@@ -222,7 +234,7 @@ static void ib_umem_account(struct work_struct *work)
struct ib_umem *umem = container_of(work, struct ib_umem, work);
down_write(&umem->mm->mmap_sem);
- umem->mm->locked_vm -= umem->diff;
+ umem->mm->pinned_vm -= umem->diff;
up_write(&umem->mm->mmap_sem);
mmput(umem->mm);
kfree(umem);
@@ -268,7 +280,7 @@ void ib_umem_release(struct ib_umem *umem)
} else
down_write(&mm->mmap_sem);
- current->mm->locked_vm -= diff;
+ current->mm->pinned_vm -= diff;
up_write(&mm->mmap_sem);
mmput(mm);
kfree(umem);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 8d261b6..c685881 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -458,8 +458,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
goto err;
}
- if (packet->mad.hdr.id < 0 ||
- packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
+ if (packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
ret = -EINVAL;
goto err;
}
@@ -703,7 +702,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
mutex_lock(&file->port->file_mutex);
mutex_lock(&file->mutex);
- if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+ if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
ret = -EINVAL;
goto out;
}
@@ -781,27 +780,19 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
{
struct ib_umad_port *port;
struct ib_umad_file *file;
- int ret;
+ int ret = -ENXIO;
port = container_of(inode->i_cdev, struct ib_umad_port, cdev);
- if (port)
- kref_get(&port->umad_dev->ref);
- else
- return -ENXIO;
mutex_lock(&port->file_mutex);
- if (!port->ib_dev) {
- ret = -ENXIO;
+ if (!port->ib_dev)
goto out;
- }
+ ret = -ENOMEM;
file = kzalloc(sizeof *file, GFP_KERNEL);
- if (!file) {
- kref_put(&port->umad_dev->ref, ib_umad_release_dev);
- ret = -ENOMEM;
+ if (!file)
goto out;
- }
mutex_init(&file->mutex);
spin_lock_init(&file->send_lock);
@@ -815,6 +806,13 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
list_add_tail(&file->port_list, &port->file_list);
ret = nonseekable_open(inode, filp);
+ if (ret) {
+ list_del(&file->port_list);
+ kfree(file);
+ goto out;
+ }
+
+ kref_get(&port->umad_dev->ref);
out:
mutex_unlock(&port->file_mutex);
@@ -881,10 +879,6 @@ static int ib_umad_sm_open(struct inode *inode, struct file *filp)
int ret;
port = container_of(inode->i_cdev, struct ib_umad_port, sm_cdev);
- if (port)
- kref_get(&port->umad_dev->ref);
- else
- return -ENXIO;
if (filp->f_flags & O_NONBLOCK) {
if (down_trylock(&port->sm_sem)) {
@@ -899,17 +893,27 @@ static int ib_umad_sm_open(struct inode *inode, struct file *filp)
}
ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
- if (ret) {
- up(&port->sm_sem);
- goto fail;
- }
+ if (ret)
+ goto err_up_sem;
filp->private_data = port;
- return nonseekable_open(inode, filp);
+ ret = nonseekable_open(inode, filp);
+ if (ret)
+ goto err_clr_sm_cap;
+
+ kref_get(&port->umad_dev->ref);
+
+ return 0;
+
+err_clr_sm_cap:
+ swap(props.set_port_cap_mask, props.clr_port_cap_mask);
+ ib_modify_port(port->ib_dev, port->port_num, 0, &props);
+
+err_up_sem:
+ up(&port->sm_sem);
fail:
- kref_put(&port->umad_dev->ref, ib_umad_release_dev);
return ret;
}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index a078e56..228af18 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -69,13 +69,16 @@
*/
struct ib_uverbs_device {
- struct kref ref;
+ atomic_t refcount;
int num_comp_vectors;
struct completion comp;
struct device *dev;
struct ib_device *ib_dev;
int devnum;
struct cdev cdev;
+ struct rb_root xrcd_tree;
+ struct mutex xrcd_tree_mutex;
+ struct kobject kobj;
};
struct ib_uverbs_event_file {
@@ -120,6 +123,16 @@ struct ib_uevent_object {
u32 events_reported;
};
+struct ib_uxrcd_object {
+ struct ib_uobject uobject;
+ atomic_t refcnt;
+};
+
+struct ib_usrq_object {
+ struct ib_uevent_object uevent;
+ struct ib_uxrcd_object *uxrcd;
+};
+
struct ib_uqp_object {
struct ib_uevent_object uevent;
struct list_head mcast_list;
@@ -142,6 +155,7 @@ extern struct idr ib_uverbs_ah_idr;
extern struct idr ib_uverbs_cq_idr;
extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr;
+extern struct idr ib_uverbs_xrcd_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
@@ -161,6 +175,7 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event);
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
#define IB_UVERBS_DECLARE_CMD(name) \
ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \
@@ -181,6 +196,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq);
IB_UVERBS_DECLARE_CMD(req_notify_cq);
IB_UVERBS_DECLARE_CMD(destroy_cq);
IB_UVERBS_DECLARE_CMD(create_qp);
+IB_UVERBS_DECLARE_CMD(open_qp);
IB_UVERBS_DECLARE_CMD(query_qp);
IB_UVERBS_DECLARE_CMD(modify_qp);
IB_UVERBS_DECLARE_CMD(destroy_qp);
@@ -195,5 +211,8 @@ IB_UVERBS_DECLARE_CMD(create_srq);
IB_UVERBS_DECLARE_CMD(modify_srq);
IB_UVERBS_DECLARE_CMD(query_srq);
IB_UVERBS_DECLARE_CMD(destroy_srq);
+IB_UVERBS_DECLARE_CMD(create_xsrq);
+IB_UVERBS_DECLARE_CMD(open_xrcd);
+IB_UVERBS_DECLARE_CMD(close_xrcd);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index c426992..3be21aa 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -47,6 +47,7 @@ static struct lock_class_key cq_lock_key;
static struct lock_class_key qp_lock_key;
static struct lock_class_key ah_lock_key;
static struct lock_class_key srq_lock_key;
+static struct lock_class_key xrcd_lock_key;
#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
do { \
@@ -240,11 +241,24 @@ static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0);
}
+static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context)
+{
+ struct ib_uobject *uobj;
+
+ uobj = idr_write_uobj(&ib_uverbs_qp_idr, qp_handle, context);
+ return uobj ? uobj->object : NULL;
+}
+
static void put_qp_read(struct ib_qp *qp)
{
put_uobj_read(qp->uobject);
}
+static void put_qp_write(struct ib_qp *qp)
+{
+ put_uobj_write(qp->uobject);
+}
+
static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
{
return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
@@ -255,6 +269,18 @@ static void put_srq_read(struct ib_srq *srq)
put_uobj_read(srq->uobject);
}
+static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context,
+ struct ib_uobject **uobj)
+{
+ *uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0);
+ return *uobj ? (*uobj)->object : NULL;
+}
+
+static void put_xrcd_read(struct ib_uobject *uobj)
+{
+ put_uobj_read(uobj);
+}
+
ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
const char __user *buf,
int in_len, int out_len)
@@ -298,6 +324,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&ucontext->qp_list);
INIT_LIST_HEAD(&ucontext->srq_list);
INIT_LIST_HEAD(&ucontext->ah_list);
+ INIT_LIST_HEAD(&ucontext->xrcd_list);
ucontext->closing = 0;
resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -579,6 +606,310 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
return in_len;
}
+struct xrcd_table_entry {
+ struct rb_node node;
+ struct ib_xrcd *xrcd;
+ struct inode *inode;
+};
+
+static int xrcd_table_insert(struct ib_uverbs_device *dev,
+ struct inode *inode,
+ struct ib_xrcd *xrcd)
+{
+ struct xrcd_table_entry *entry, *scan;
+ struct rb_node **p = &dev->xrcd_tree.rb_node;
+ struct rb_node *parent = NULL;
+
+ entry = kmalloc(sizeof *entry, GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->xrcd = xrcd;
+ entry->inode = inode;
+
+ while (*p) {
+ parent = *p;
+ scan = rb_entry(parent, struct xrcd_table_entry, node);
+
+ if (inode < scan->inode) {
+ p = &(*p)->rb_left;
+ } else if (inode > scan->inode) {
+ p = &(*p)->rb_right;
+ } else {
+ kfree(entry);
+ return -EEXIST;
+ }
+ }
+
+ rb_link_node(&entry->node, parent, p);
+ rb_insert_color(&entry->node, &dev->xrcd_tree);
+ igrab(inode);
+ return 0;
+}
+
+static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev,
+ struct inode *inode)
+{
+ struct xrcd_table_entry *entry;
+ struct rb_node *p = dev->xrcd_tree.rb_node;
+
+ while (p) {
+ entry = rb_entry(p, struct xrcd_table_entry, node);
+
+ if (inode < entry->inode)
+ p = p->rb_left;
+ else if (inode > entry->inode)
+ p = p->rb_right;
+ else
+ return entry;
+ }
+
+ return NULL;
+}
+
+static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode)
+{
+ struct xrcd_table_entry *entry;
+
+ entry = xrcd_table_search(dev, inode);
+ if (!entry)
+ return NULL;
+
+ return entry->xrcd;
+}
+
+static void xrcd_table_delete(struct ib_uverbs_device *dev,
+ struct inode *inode)
+{
+ struct xrcd_table_entry *entry;
+
+ entry = xrcd_table_search(dev, inode);
+ if (entry) {
+ iput(inode);
+ rb_erase(&entry->node, &dev->xrcd_tree);
+ kfree(entry);
+ }
+}
+
+ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_open_xrcd cmd;
+ struct ib_uverbs_open_xrcd_resp resp;
+ struct ib_udata udata;
+ struct ib_uxrcd_object *obj;
+ struct ib_xrcd *xrcd = NULL;
+ struct file *f = NULL;
+ struct inode *inode = NULL;
+ int ret = 0;
+ int new_xrcd = 0;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ mutex_lock(&file->device->xrcd_tree_mutex);
+
+ if (cmd.fd != -1) {
+ /* search for file descriptor */
+ f = fget(cmd.fd);
+ if (!f) {
+ ret = -EBADF;
+ goto err_tree_mutex_unlock;
+ }
+
+ inode = f->f_dentry->d_inode;
+ if (!inode) {
+ ret = -EBADF;
+ goto err_tree_mutex_unlock;
+ }
+
+ xrcd = find_xrcd(file->device, inode);
+ if (!xrcd && !(cmd.oflags & O_CREAT)) {
+ /* no file descriptor. Need CREATE flag */
+ ret = -EAGAIN;
+ goto err_tree_mutex_unlock;
+ }
+
+ if (xrcd && cmd.oflags & O_EXCL) {
+ ret = -EINVAL;
+ goto err_tree_mutex_unlock;
+ }
+ }
+
+ obj = kmalloc(sizeof *obj, GFP_KERNEL);
+ if (!obj) {
+ ret = -ENOMEM;
+ goto err_tree_mutex_unlock;
+ }
+
+ init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_key);
+
+ down_write(&obj->uobject.mutex);
+
+ if (!xrcd) {
+ xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev,
+ file->ucontext, &udata);
+ if (IS_ERR(xrcd)) {
+ ret = PTR_ERR(xrcd);
+ goto err;
+ }
+
+ xrcd->inode = inode;
+ xrcd->device = file->device->ib_dev;
+ atomic_set(&xrcd->usecnt, 0);
+ mutex_init(&xrcd->tgt_qp_mutex);
+ INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+ new_xrcd = 1;
+ }
+
+ atomic_set(&obj->refcnt, 0);
+ obj->uobject.object = xrcd;
+ ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+ if (ret)
+ goto err_idr;
+
+ memset(&resp, 0, sizeof resp);
+ resp.xrcd_handle = obj->uobject.id;
+
+ if (inode) {
+ if (new_xrcd) {
+ /* create new inode/xrcd table entry */
+ ret = xrcd_table_insert(file->device, inode, xrcd);
+ if (ret)
+ goto err_insert_xrcd;
+ }
+ atomic_inc(&xrcd->usecnt);
+ }
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_copy;
+ }
+
+ if (f)
+ fput(f);
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uobject.live = 1;
+ up_write(&obj->uobject.mutex);
+
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+ return in_len;
+
+err_copy:
+ if (inode) {
+ if (new_xrcd)
+ xrcd_table_delete(file->device, inode);
+ atomic_dec(&xrcd->usecnt);
+ }
+
+err_insert_xrcd:
+ idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+
+err_idr:
+ ib_dealloc_xrcd(xrcd);
+
+err:
+ put_uobj_write(&obj->uobject);
+
+err_tree_mutex_unlock:
+ if (f)
+ fput(f);
+
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+
+ return ret;
+}
+
+ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_close_xrcd cmd;
+ struct ib_uobject *uobj;
+ struct ib_xrcd *xrcd = NULL;
+ struct inode *inode = NULL;
+ struct ib_uxrcd_object *obj;
+ int live;
+ int ret = 0;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ mutex_lock(&file->device->xrcd_tree_mutex);
+ uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext);
+ if (!uobj) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ xrcd = uobj->object;
+ inode = xrcd->inode;
+ obj = container_of(uobj, struct ib_uxrcd_object, uobject);
+ if (atomic_read(&obj->refcnt)) {
+ put_uobj_write(uobj);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
+ ret = ib_dealloc_xrcd(uobj->object);
+ if (!ret)
+ uobj->live = 0;
+ }
+
+ live = uobj->live;
+ if (inode && ret)
+ atomic_inc(&xrcd->usecnt);
+
+ put_uobj_write(uobj);
+
+ if (ret)
+ goto out;
+
+ if (inode && !live)
+ xrcd_table_delete(file->device, inode);
+
+ idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+ mutex_lock(&file->mutex);
+ list_del(&uobj->list);
+ mutex_unlock(&file->mutex);
+
+ put_uobj(uobj);
+ ret = in_len;
+
+out:
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+ return ret;
+}
+
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
+ struct ib_xrcd *xrcd)
+{
+ struct inode *inode;
+
+ inode = xrcd->inode;
+ if (inode && !atomic_dec_and_test(&xrcd->usecnt))
+ return;
+
+ ib_dealloc_xrcd(xrcd);
+
+ if (inode)
+ xrcd_table_delete(dev, inode);
+}
+
ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -1052,9 +1383,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
struct ib_uverbs_create_qp_resp resp;
struct ib_udata udata;
struct ib_uqp_object *obj;
- struct ib_pd *pd;
- struct ib_cq *scq, *rcq;
- struct ib_srq *srq;
+ struct ib_device *device;
+ struct ib_pd *pd = NULL;
+ struct ib_xrcd *xrcd = NULL;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
+ struct ib_cq *scq = NULL, *rcq = NULL;
+ struct ib_srq *srq = NULL;
struct ib_qp *qp;
struct ib_qp_init_attr attr;
int ret;
@@ -1076,15 +1410,39 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
down_write(&obj->uevent.uobject.mutex);
- srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
- scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
- rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
- scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+ if (cmd.qp_type == IB_QPT_XRC_TGT) {
+ xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+ if (!xrcd) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ device = xrcd->device;
+ } else {
+ pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+ if (!pd || !scq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
- if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
- ret = -EINVAL;
- goto err_put;
+ if (cmd.qp_type == IB_QPT_XRC_INI) {
+ cmd.max_recv_wr = cmd.max_recv_sge = 0;
+ } else {
+ if (cmd.is_srq) {
+ srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+ if (!srq || srq->srq_type != IB_SRQT_BASIC) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ }
+ rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
+ scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+ if (!rcq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ }
+ device = pd->device;
}
attr.event_handler = ib_uverbs_qp_event_handler;
@@ -1092,6 +1450,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.send_cq = scq;
attr.recv_cq = rcq;
attr.srq = srq;
+ attr.xrcd = xrcd;
attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
attr.qp_type = cmd.qp_type;
attr.create_flags = 0;
@@ -1106,26 +1465,35 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&obj->uevent.event_list);
INIT_LIST_HEAD(&obj->mcast_list);
- qp = pd->device->create_qp(pd, &attr, &udata);
+ if (cmd.qp_type == IB_QPT_XRC_TGT)
+ qp = ib_create_qp(pd, &attr);
+ else
+ qp = device->create_qp(pd, &attr, &udata);
+
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
}
- qp->device = pd->device;
- qp->pd = pd;
- qp->send_cq = attr.send_cq;
- qp->recv_cq = attr.recv_cq;
- qp->srq = attr.srq;
- qp->uobject = &obj->uevent.uobject;
- qp->event_handler = attr.event_handler;
- qp->qp_context = attr.qp_context;
- qp->qp_type = attr.qp_type;
- atomic_inc(&pd->usecnt);
- atomic_inc(&attr.send_cq->usecnt);
- atomic_inc(&attr.recv_cq->usecnt);
- if (attr.srq)
- atomic_inc(&attr.srq->usecnt);
+ if (cmd.qp_type != IB_QPT_XRC_TGT) {
+ qp->real_qp = qp;
+ qp->device = device;
+ qp->pd = pd;
+ qp->send_cq = attr.send_cq;
+ qp->recv_cq = attr.recv_cq;
+ qp->srq = attr.srq;
+ qp->event_handler = attr.event_handler;
+ qp->qp_context = attr.qp_context;
+ qp->qp_type = attr.qp_type;
+ atomic_set(&qp->usecnt, 0);
+ atomic_inc(&pd->usecnt);
+ atomic_inc(&attr.send_cq->usecnt);
+ if (attr.recv_cq)
+ atomic_inc(&attr.recv_cq->usecnt);
+ if (attr.srq)
+ atomic_inc(&attr.srq->usecnt);
+ }
+ qp->uobject = &obj->uevent.uobject;
obj->uevent.uobject.object = qp;
ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1147,9 +1515,13 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
goto err_copy;
}
- put_pd_read(pd);
- put_cq_read(scq);
- if (rcq != scq)
+ if (xrcd)
+ put_xrcd_read(xrcd_uobj);
+ if (pd)
+ put_pd_read(pd);
+ if (scq)
+ put_cq_read(scq);
+ if (rcq && rcq != scq)
put_cq_read(rcq);
if (srq)
put_srq_read(srq);
@@ -1171,6 +1543,8 @@ err_destroy:
ib_destroy_qp(qp);
err_put:
+ if (xrcd)
+ put_xrcd_read(xrcd_uobj);
if (pd)
put_pd_read(pd);
if (scq)
@@ -1184,6 +1558,98 @@ err_put:
return ret;
}
+ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len, int out_len)
+{
+ struct ib_uverbs_open_qp cmd;
+ struct ib_uverbs_create_qp_resp resp;
+ struct ib_udata udata;
+ struct ib_uqp_object *obj;
+ struct ib_xrcd *xrcd;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
+ struct ib_qp *qp;
+ struct ib_qp_open_attr attr;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ obj = kmalloc(sizeof *obj, GFP_KERNEL);
+ if (!obj)
+ return -ENOMEM;
+
+ init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+ down_write(&obj->uevent.uobject.mutex);
+
+ xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+ if (!xrcd) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ attr.event_handler = ib_uverbs_qp_event_handler;
+ attr.qp_context = file;
+ attr.qp_num = cmd.qpn;
+ attr.qp_type = cmd.qp_type;
+
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
+ INIT_LIST_HEAD(&obj->mcast_list);
+
+ qp = ib_open_qp(xrcd, &attr);
+ if (IS_ERR(qp)) {
+ ret = PTR_ERR(qp);
+ goto err_put;
+ }
+
+ qp->uobject = &obj->uevent.uobject;
+
+ obj->uevent.uobject.object = qp;
+ ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+ if (ret)
+ goto err_destroy;
+
+ memset(&resp, 0, sizeof resp);
+ resp.qpn = qp->qp_num;
+ resp.qp_handle = obj->uevent.uobject.id;
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_remove;
+ }
+
+ put_xrcd_read(xrcd_uobj);
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uevent.uobject.live = 1;
+
+ up_write(&obj->uevent.uobject.mutex);
+
+ return in_len;
+
+err_remove:
+ idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+
+err_destroy:
+ ib_destroy_qp(qp);
+
+err_put:
+ put_xrcd_read(xrcd_uobj);
+ put_uobj_write(&obj->uevent.uobject);
+ return ret;
+}
+
ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -1284,6 +1750,20 @@ out:
return ret ? ret : in_len;
}
+/* Remove ignored fields set in the attribute mask */
+static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
+{
+ switch (qp_type) {
+ case IB_QPT_XRC_INI:
+ return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
+ case IB_QPT_XRC_TGT:
+ return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY);
+ default:
+ return mask;
+ }
+}
+
ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -1356,7 +1836,12 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
- ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
+ if (qp->real_qp == qp) {
+ ret = qp->device->modify_qp(qp, attr,
+ modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+ } else {
+ ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+ }
put_qp_read(qp);
@@ -1494,6 +1979,12 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
next->send_flags = user_wr->send_flags;
if (is_ud) {
+ if (next->opcode != IB_WR_SEND &&
+ next->opcode != IB_WR_SEND_WITH_IMM) {
+ ret = -EINVAL;
+ goto out_put;
+ }
+
next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
file->ucontext);
if (!next->wr.ud.ah) {
@@ -1530,9 +2021,11 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
user_wr->wr.atomic.compare_add;
next->wr.atomic.swap = user_wr->wr.atomic.swap;
next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
+ case IB_WR_SEND:
break;
default:
- break;
+ ret = -EINVAL;
+ goto out_put;
}
}
@@ -1553,7 +2046,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
}
resp.bad_wr = 0;
- ret = qp->device->post_send(qp, wr, &bad_wr);
+ ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
if (ret)
for (next = wr; next; next = next->next) {
++resp.bad_wr;
@@ -1691,7 +2184,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
goto out;
resp.bad_wr = 0;
- ret = qp->device->post_recv(qp, wr, &bad_wr);
+ ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
put_qp_read(qp);
@@ -1904,7 +2397,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+ qp = idr_write_qp(cmd.qp_handle, file->ucontext);
if (!qp)
return -EINVAL;
@@ -1933,7 +2426,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
kfree(mcast);
out_put:
- put_qp_read(qp);
+ put_qp_write(qp);
return ret ? ret : in_len;
}
@@ -1951,7 +2444,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+ qp = idr_write_qp(cmd.qp_handle, file->ucontext);
if (!qp)
return -EINVAL;
@@ -1970,112 +2463,204 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
}
out_put:
- put_qp_read(qp);
+ put_qp_write(qp);
return ret ? ret : in_len;
}
-ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
- const char __user *buf, int in_len,
- int out_len)
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
+ struct ib_uverbs_create_xsrq *cmd,
+ struct ib_udata *udata)
{
- struct ib_uverbs_create_srq cmd;
struct ib_uverbs_create_srq_resp resp;
- struct ib_udata udata;
- struct ib_uevent_object *obj;
+ struct ib_usrq_object *obj;
struct ib_pd *pd;
struct ib_srq *srq;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
struct ib_srq_init_attr attr;
int ret;
- if (out_len < sizeof resp)
- return -ENOSPC;
-
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
-
- INIT_UDATA(&udata, buf + sizeof cmd,
- (unsigned long) cmd.response + sizeof resp,
- in_len - sizeof cmd, out_len - sizeof resp);
-
obj = kmalloc(sizeof *obj, GFP_KERNEL);
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
- down_write(&obj->uobject.mutex);
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+ down_write(&obj->uevent.uobject.mutex);
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
if (!pd) {
ret = -EINVAL;
goto err;
}
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+ if (!attr.ext.xrc.cq) {
+ ret = -EINVAL;
+ goto err_put_pd;
+ }
+
+ attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
+ if (!attr.ext.xrc.xrcd) {
+ ret = -EINVAL;
+ goto err_put_cq;
+ }
+
+ obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
+ atomic_inc(&obj->uxrcd->refcnt);
+ }
+
attr.event_handler = ib_uverbs_srq_event_handler;
attr.srq_context = file;
- attr.attr.max_wr = cmd.max_wr;
- attr.attr.max_sge = cmd.max_sge;
- attr.attr.srq_limit = cmd.srq_limit;
+ attr.srq_type = cmd->srq_type;
+ attr.attr.max_wr = cmd->max_wr;
+ attr.attr.max_sge = cmd->max_sge;
+ attr.attr.srq_limit = cmd->srq_limit;
- obj->events_reported = 0;
- INIT_LIST_HEAD(&obj->event_list);
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
- srq = pd->device->create_srq(pd, &attr, &udata);
+ srq = pd->device->create_srq(pd, &attr, udata);
if (IS_ERR(srq)) {
ret = PTR_ERR(srq);
goto err_put;
}
- srq->device = pd->device;
- srq->pd = pd;
- srq->uobject = &obj->uobject;
+ srq->device = pd->device;
+ srq->pd = pd;
+ srq->srq_type = cmd->srq_type;
+ srq->uobject = &obj->uevent.uobject;
srq->event_handler = attr.event_handler;
srq->srq_context = attr.srq_context;
+
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ srq->ext.xrc.cq = attr.ext.xrc.cq;
+ srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
+ atomic_inc(&attr.ext.xrc.cq->usecnt);
+ atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+ }
+
atomic_inc(&pd->usecnt);
atomic_set(&srq->usecnt, 0);
- obj->uobject.object = srq;
- ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+ obj->uevent.uobject.object = srq;
+ ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
if (ret)
goto err_destroy;
memset(&resp, 0, sizeof resp);
- resp.srq_handle = obj->uobject.id;
+ resp.srq_handle = obj->uevent.uobject.id;
resp.max_wr = attr.attr.max_wr;
resp.max_sge = attr.attr.max_sge;
+ if (cmd->srq_type == IB_SRQT_XRC)
+ resp.srqn = srq->ext.xrc.srq_num;
- if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ if (copy_to_user((void __user *) (unsigned long) cmd->response,
&resp, sizeof resp)) {
ret = -EFAULT;
goto err_copy;
}
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ put_uobj_read(xrcd_uobj);
+ put_cq_read(attr.ext.xrc.cq);
+ }
put_pd_read(pd);
mutex_lock(&file->mutex);
- list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
mutex_unlock(&file->mutex);
- obj->uobject.live = 1;
+ obj->uevent.uobject.live = 1;
- up_write(&obj->uobject.mutex);
+ up_write(&obj->uevent.uobject.mutex);
- return in_len;
+ return 0;
err_copy:
- idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+ idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
err_destroy:
ib_destroy_srq(srq);
err_put:
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ atomic_dec(&obj->uxrcd->refcnt);
+ put_uobj_read(xrcd_uobj);
+ }
+
+err_put_cq:
+ if (cmd->srq_type == IB_SRQT_XRC)
+ put_cq_read(attr.ext.xrc.cq);
+
+err_put_pd:
put_pd_read(pd);
err:
- put_uobj_write(&obj->uobject);
+ put_uobj_write(&obj->uevent.uobject);
return ret;
}
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_srq cmd;
+ struct ib_uverbs_create_xsrq xcmd;
+ struct ib_uverbs_create_srq_resp resp;
+ struct ib_udata udata;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ xcmd.response = cmd.response;
+ xcmd.user_handle = cmd.user_handle;
+ xcmd.srq_type = IB_SRQT_BASIC;
+ xcmd.pd_handle = cmd.pd_handle;
+ xcmd.max_wr = cmd.max_wr;
+ xcmd.max_sge = cmd.max_sge;
+ xcmd.srq_limit = cmd.srq_limit;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ ret = __uverbs_create_xsrq(file, &xcmd, &udata);
+ if (ret)
+ return ret;
+
+ return in_len;
+}
+
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len, int out_len)
+{
+ struct ib_uverbs_create_xsrq cmd;
+ struct ib_uverbs_create_srq_resp resp;
+ struct ib_udata udata;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ ret = __uverbs_create_xsrq(file, &cmd, &udata);
+ if (ret)
+ return ret;
+
+ return in_len;
+}
+
ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 56898b6..f07c6e3 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr);
DEFINE_IDR(ib_uverbs_cq_idr);
DEFINE_IDR(ib_uverbs_qp_idr);
DEFINE_IDR(ib_uverbs_srq_idr);
+DEFINE_IDR(ib_uverbs_xrcd_idr);
static DEFINE_SPINLOCK(map_lock);
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -107,19 +108,27 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
[IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq,
[IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
+ [IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd,
+ [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd,
+ [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq,
+ [IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp
};
static void ib_uverbs_add_one(struct ib_device *device);
static void ib_uverbs_remove_one(struct ib_device *device);
-static void ib_uverbs_release_dev(struct kref *ref)
+static void ib_uverbs_release_dev(struct kobject *kobj)
{
struct ib_uverbs_device *dev =
- container_of(ref, struct ib_uverbs_device, ref);
+ container_of(kobj, struct ib_uverbs_device, kobj);
- complete(&dev->comp);
+ kfree(dev);
}
+static struct kobj_type ib_uverbs_dev_ktype = {
+ .release = ib_uverbs_release_dev,
+};
+
static void ib_uverbs_release_event_file(struct kref *ref)
{
struct ib_uverbs_event_file *file =
@@ -202,8 +211,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
container_of(uobj, struct ib_uqp_object, uevent.uobject);
idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
- ib_uverbs_detach_umcast(qp, uqp);
- ib_destroy_qp(qp);
+ if (qp != qp->real_qp) {
+ ib_close_qp(qp);
+ } else {
+ ib_uverbs_detach_umcast(qp, uqp);
+ ib_destroy_qp(qp);
+ }
ib_uverbs_release_uevent(file, &uqp->uevent);
kfree(uqp);
}
@@ -241,6 +254,18 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uobj);
}
+ mutex_lock(&file->device->xrcd_tree_mutex);
+ list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
+ struct ib_xrcd *xrcd = uobj->object;
+ struct ib_uxrcd_object *uxrcd =
+ container_of(uobj, struct ib_uxrcd_object, uobject);
+
+ idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+ ib_uverbs_dealloc_xrcd(file->device, xrcd);
+ kfree(uxrcd);
+ }
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+
list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
struct ib_pd *pd = uobj->object;
@@ -252,13 +277,19 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
return context->device->dealloc_ucontext(context);
}
+static void ib_uverbs_comp_dev(struct ib_uverbs_device *dev)
+{
+ complete(&dev->comp);
+}
+
static void ib_uverbs_release_file(struct kref *ref)
{
struct ib_uverbs_file *file =
container_of(ref, struct ib_uverbs_file, ref);
module_put(file->device->ib_dev->owner);
- kref_put(&file->device->ref, ib_uverbs_release_dev);
+ if (atomic_dec_and_test(&file->device->refcount))
+ ib_uverbs_comp_dev(file->device);
kfree(file);
}
@@ -430,6 +461,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
entry->desc.async.element = element;
entry->desc.async.event_type = event;
+ entry->desc.async.reserved = 0;
entry->counter = counter;
list_add_tail(&entry->list, &file->async_file->event_list);
@@ -557,8 +589,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (hdr.in_words * 4 != count)
return -EINVAL;
- if (hdr.command < 0 ||
- hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+ if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
!uverbs_cmd_table[hdr.command])
return -EINVAL;
@@ -600,9 +631,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
int ret;
dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
- if (dev)
- kref_get(&dev->ref);
- else
+ if (!atomic_inc_not_zero(&dev->refcount))
return -ENXIO;
if (!try_module_get(dev->ib_dev->owner)) {
@@ -623,6 +652,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
mutex_init(&file->mutex);
filp->private_data = file;
+ kobject_get(&dev->kobj);
return nonseekable_open(inode, filp);
@@ -630,13 +660,16 @@ err_module:
module_put(dev->ib_dev->owner);
err:
- kref_put(&dev->ref, ib_uverbs_release_dev);
+ if (atomic_dec_and_test(&dev->refcount))
+ ib_uverbs_comp_dev(dev);
+
return ret;
}
static int ib_uverbs_close(struct inode *inode, struct file *filp)
{
struct ib_uverbs_file *file = filp->private_data;
+ struct ib_uverbs_device *dev = file->device;
ib_uverbs_cleanup_ucontext(file, file->ucontext);
@@ -644,6 +677,7 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
kref_put(&file->ref, ib_uverbs_release_file);
+ kobject_put(&dev->kobj);
return 0;
}
@@ -739,8 +773,11 @@ static void ib_uverbs_add_one(struct ib_device *device)
if (!uverbs_dev)
return;
- kref_init(&uverbs_dev->ref);
+ atomic_set(&uverbs_dev->refcount, 1);
init_completion(&uverbs_dev->comp);
+ uverbs_dev->xrcd_tree = RB_ROOT;
+ mutex_init(&uverbs_dev->xrcd_tree_mutex);
+ kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
spin_lock(&map_lock);
devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -767,6 +804,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
cdev_init(&uverbs_dev->cdev, NULL);
uverbs_dev->cdev.owner = THIS_MODULE;
uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+ uverbs_dev->cdev.kobj.parent = &uverbs_dev->kobj;
kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
if (cdev_add(&uverbs_dev->cdev, base, 1))
goto err_cdev;
@@ -797,9 +835,10 @@ err_cdev:
clear_bit(devnum, overflow_map);
err:
- kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+ if (atomic_dec_and_test(&uverbs_dev->refcount))
+ ib_uverbs_comp_dev(uverbs_dev);
wait_for_completion(&uverbs_dev->comp);
- kfree(uverbs_dev);
+ kobject_put(&uverbs_dev->kobj);
return;
}
@@ -819,9 +858,10 @@ static void ib_uverbs_remove_one(struct ib_device *device)
else
clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
- kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+ if (atomic_dec_and_test(&uverbs_dev->refcount))
+ ib_uverbs_comp_dev(uverbs_dev);
wait_for_completion(&uverbs_dev->comp);
- kfree(uverbs_dev);
+ kobject_put(&uverbs_dev->kobj);
}
static char *uverbs_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
index 1b1146f..e7bee46 100644
--- a/drivers/infiniband/core/uverbs_marshall.c
+++ b/drivers/infiniband/core/uverbs_marshall.c
@@ -30,6 +30,7 @@
* SOFTWARE.
*/
+#include <linux/export.h>
#include <rdma/ib_marshall.h>
void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index af7a8b0..575b780 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -38,7 +38,9 @@
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <linux/string.h>
+#include <linux/slab.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
@@ -77,6 +79,31 @@ enum ib_rate mult_to_ib_rate(int mult)
}
EXPORT_SYMBOL(mult_to_ib_rate);
+int ib_rate_to_mbps(enum ib_rate rate)
+{
+ switch (rate) {
+ case IB_RATE_2_5_GBPS: return 2500;
+ case IB_RATE_5_GBPS: return 5000;
+ case IB_RATE_10_GBPS: return 10000;
+ case IB_RATE_20_GBPS: return 20000;
+ case IB_RATE_30_GBPS: return 30000;
+ case IB_RATE_40_GBPS: return 40000;
+ case IB_RATE_60_GBPS: return 60000;
+ case IB_RATE_80_GBPS: return 80000;
+ case IB_RATE_120_GBPS: return 120000;
+ case IB_RATE_14_GBPS: return 14062;
+ case IB_RATE_56_GBPS: return 56250;
+ case IB_RATE_112_GBPS: return 112500;
+ case IB_RATE_168_GBPS: return 168750;
+ case IB_RATE_25_GBPS: return 25781;
+ case IB_RATE_100_GBPS: return 103125;
+ case IB_RATE_200_GBPS: return 206250;
+ case IB_RATE_300_GBPS: return 309375;
+ default: return -1;
+ }
+}
+EXPORT_SYMBOL(ib_rate_to_mbps);
+
enum rdma_transport_type
rdma_node_get_transport(enum rdma_node_type node_type)
{
@@ -250,6 +277,13 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
srq->uobject = NULL;
srq->event_handler = srq_init_attr->event_handler;
srq->srq_context = srq_init_attr->srq_context;
+ srq->srq_type = srq_init_attr->srq_type;
+ if (srq->srq_type == IB_SRQT_XRC) {
+ srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
+ srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq;
+ atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+ atomic_inc(&srq->ext.xrc.cq->usecnt);
+ }
atomic_inc(&pd->usecnt);
atomic_set(&srq->usecnt, 0);
}
@@ -279,16 +313,29 @@ EXPORT_SYMBOL(ib_query_srq);
int ib_destroy_srq(struct ib_srq *srq)
{
struct ib_pd *pd;
+ enum ib_srq_type srq_type;
+ struct ib_xrcd *uninitialized_var(xrcd);
+ struct ib_cq *uninitialized_var(cq);
int ret;
if (atomic_read(&srq->usecnt))
return -EBUSY;
pd = srq->pd;
+ srq_type = srq->srq_type;
+ if (srq_type == IB_SRQT_XRC) {
+ xrcd = srq->ext.xrc.xrcd;
+ cq = srq->ext.xrc.cq;
+ }
ret = srq->device->destroy_srq(srq);
- if (!ret)
+ if (!ret) {
atomic_dec(&pd->usecnt);
+ if (srq_type == IB_SRQT_XRC) {
+ atomic_dec(&xrcd->usecnt);
+ atomic_dec(&cq->usecnt);
+ }
+ }
return ret;
}
@@ -296,28 +343,123 @@ EXPORT_SYMBOL(ib_destroy_srq);
/* Queue pairs */
+static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
+{
+ struct ib_qp *qp = context;
+
+ list_for_each_entry(event->element.qp, &qp->open_list, open_list)
+ event->element.qp->event_handler(event, event->element.qp->qp_context);
+}
+
+static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp)
+{
+ mutex_lock(&xrcd->tgt_qp_mutex);
+ list_add(&qp->xrcd_list, &xrcd->tgt_qp_list);
+ mutex_unlock(&xrcd->tgt_qp_mutex);
+}
+
+static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
+ void (*event_handler)(struct ib_event *, void *),
+ void *qp_context)
+{
+ struct ib_qp *qp;
+ unsigned long flags;
+
+ qp = kzalloc(sizeof *qp, GFP_KERNEL);
+ if (!qp)
+ return ERR_PTR(-ENOMEM);
+
+ qp->real_qp = real_qp;
+ atomic_inc(&real_qp->usecnt);
+ qp->device = real_qp->device;
+ qp->event_handler = event_handler;
+ qp->qp_context = qp_context;
+ qp->qp_num = real_qp->qp_num;
+ qp->qp_type = real_qp->qp_type;
+
+ spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+ list_add(&qp->open_list, &real_qp->open_list);
+ spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+ return qp;
+}
+
+struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
+ struct ib_qp_open_attr *qp_open_attr)
+{
+ struct ib_qp *qp, *real_qp;
+
+ if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
+ return ERR_PTR(-EINVAL);
+
+ qp = ERR_PTR(-EINVAL);
+ mutex_lock(&xrcd->tgt_qp_mutex);
+ list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) {
+ if (real_qp->qp_num == qp_open_attr->qp_num) {
+ qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
+ qp_open_attr->qp_context);
+ break;
+ }
+ }
+ mutex_unlock(&xrcd->tgt_qp_mutex);
+ return qp;
+}
+EXPORT_SYMBOL(ib_open_qp);
+
struct ib_qp *ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *qp_init_attr)
{
- struct ib_qp *qp;
+ struct ib_qp *qp, *real_qp;
+ struct ib_device *device;
- qp = pd->device->create_qp(pd, qp_init_attr, NULL);
+ device = pd ? pd->device : qp_init_attr->xrcd->device;
+ qp = device->create_qp(pd, qp_init_attr, NULL);
if (!IS_ERR(qp)) {
- qp->device = pd->device;
- qp->pd = pd;
- qp->send_cq = qp_init_attr->send_cq;
- qp->recv_cq = qp_init_attr->recv_cq;
- qp->srq = qp_init_attr->srq;
- qp->uobject = NULL;
- qp->event_handler = qp_init_attr->event_handler;
- qp->qp_context = qp_init_attr->qp_context;
- qp->qp_type = qp_init_attr->qp_type;
- atomic_inc(&pd->usecnt);
- atomic_inc(&qp_init_attr->send_cq->usecnt);
- atomic_inc(&qp_init_attr->recv_cq->usecnt);
- if (qp_init_attr->srq)
- atomic_inc(&qp_init_attr->srq->usecnt);
+ qp->device = device;
+ qp->real_qp = qp;
+ qp->uobject = NULL;
+ qp->qp_type = qp_init_attr->qp_type;
+
+ atomic_set(&qp->usecnt, 0);
+ if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
+ qp->event_handler = __ib_shared_qp_event_handler;
+ qp->qp_context = qp;
+ qp->pd = NULL;
+ qp->send_cq = qp->recv_cq = NULL;
+ qp->srq = NULL;
+ qp->xrcd = qp_init_attr->xrcd;
+ atomic_inc(&qp_init_attr->xrcd->usecnt);
+ INIT_LIST_HEAD(&qp->open_list);
+
+ real_qp = qp;
+ qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
+ qp_init_attr->qp_context);
+ if (!IS_ERR(qp))
+ __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
+ else
+ real_qp->device->destroy_qp(real_qp);
+ } else {
+ qp->event_handler = qp_init_attr->event_handler;
+ qp->qp_context = qp_init_attr->qp_context;
+ if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
+ qp->recv_cq = NULL;
+ qp->srq = NULL;
+ } else {
+ qp->recv_cq = qp_init_attr->recv_cq;
+ atomic_inc(&qp_init_attr->recv_cq->usecnt);
+ qp->srq = qp_init_attr->srq;
+ if (qp->srq)
+ atomic_inc(&qp_init_attr->srq->usecnt);
+ }
+
+ qp->pd = pd;
+ qp->send_cq = qp_init_attr->send_cq;
+ qp->xrcd = NULL;
+
+ atomic_inc(&pd->usecnt);
+ atomic_inc(&qp_init_attr->send_cq->usecnt);
+ }
}
return qp;
@@ -326,8 +468,8 @@ EXPORT_SYMBOL(ib_create_qp);
static const struct {
int valid;
- enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETHERTYPE + 1];
- enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETHERTYPE + 1];
+ enum ib_qp_attr_mask req_param[IB_QPT_MAX];
+ enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = {
[IB_QPS_RESET] = { .valid = 1 },
@@ -343,6 +485,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -365,6 +513,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -384,6 +538,16 @@ static const struct {
IB_QP_RQ_PSN |
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER),
+ [IB_QPT_XRC_INI] = (IB_QP_AV |
+ IB_QP_PATH_MTU |
+ IB_QP_DEST_QPN |
+ IB_QP_RQ_PSN),
+ [IB_QPT_XRC_TGT] = (IB_QP_AV |
+ IB_QP_PATH_MTU |
+ IB_QP_DEST_QPN |
+ IB_QP_RQ_PSN |
+ IB_QP_MAX_DEST_RD_ATOMIC |
+ IB_QP_MIN_RNR_TIMER),
},
.opt_param = {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
@@ -394,6 +558,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
+ [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX),
+ [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -414,6 +584,13 @@ static const struct {
IB_QP_RNR_RETRY |
IB_QP_SQ_PSN |
IB_QP_MAX_QP_RD_ATOMIC),
+ [IB_QPT_XRC_INI] = (IB_QP_TIMEOUT |
+ IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_SQ_PSN |
+ IB_QP_MAX_QP_RD_ATOMIC),
+ [IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT |
+ IB_QP_SQ_PSN),
[IB_QPT_SMI] = IB_QP_SQ_PSN,
[IB_QPT_GSI] = IB_QP_SQ_PSN,
},
@@ -429,6 +606,15 @@ static const struct {
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE |
@@ -453,6 +639,15 @@ static const struct {
IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE |
IB_QP_MIN_RNR_TIMER),
+ [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_ALT_PATH |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_ALT_PATH |
+ IB_QP_PATH_MIG_STATE |
+ IB_QP_MIN_RNR_TIMER),
[IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE |
@@ -465,6 +660,8 @@ static const struct {
[IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+ [IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+ [IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
}
@@ -487,6 +684,15 @@ static const struct {
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE |
@@ -515,6 +721,25 @@ static const struct {
IB_QP_PKEY_INDEX |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_INI] = (IB_QP_PORT |
+ IB_QP_AV |
+ IB_QP_TIMEOUT |
+ IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_MAX_QP_RD_ATOMIC |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_PORT |
+ IB_QP_AV |
+ IB_QP_TIMEOUT |
+ IB_QP_MAX_DEST_RD_ATOMIC |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -579,7 +804,7 @@ int ib_modify_qp(struct ib_qp *qp,
struct ib_qp_attr *qp_attr,
int qp_attr_mask)
{
- return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL);
+ return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
}
EXPORT_SYMBOL(ib_modify_qp);
@@ -589,11 +814,59 @@ int ib_query_qp(struct ib_qp *qp,
struct ib_qp_init_attr *qp_init_attr)
{
return qp->device->query_qp ?
- qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
+ qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
-ENOSYS;
}
EXPORT_SYMBOL(ib_query_qp);
+int ib_close_qp(struct ib_qp *qp)
+{
+ struct ib_qp *real_qp;
+ unsigned long flags;
+
+ real_qp = qp->real_qp;
+ if (real_qp == qp)
+ return -EINVAL;
+
+ spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+ list_del(&qp->open_list);
+ spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+ atomic_dec(&real_qp->usecnt);
+ kfree(qp);
+
+ return 0;
+}
+EXPORT_SYMBOL(ib_close_qp);
+
+static int __ib_destroy_shared_qp(struct ib_qp *qp)
+{
+ struct ib_xrcd *xrcd;
+ struct ib_qp *real_qp;
+ int ret;
+
+ real_qp = qp->real_qp;
+ xrcd = real_qp->xrcd;
+
+ mutex_lock(&xrcd->tgt_qp_mutex);
+ ib_close_qp(qp);
+ if (atomic_read(&real_qp->usecnt) == 0)
+ list_del(&real_qp->xrcd_list);
+ else
+ real_qp = NULL;
+ mutex_unlock(&xrcd->tgt_qp_mutex);
+
+ if (real_qp) {
+ ret = ib_destroy_qp(real_qp);
+ if (!ret)
+ atomic_dec(&xrcd->usecnt);
+ else
+ __ib_insert_xrcd_qp(xrcd, real_qp);
+ }
+
+ return 0;
+}
+
int ib_destroy_qp(struct ib_qp *qp)
{
struct ib_pd *pd;
@@ -601,16 +874,25 @@ int ib_destroy_qp(struct ib_qp *qp)
struct ib_srq *srq;
int ret;
- pd = qp->pd;
- scq = qp->send_cq;
- rcq = qp->recv_cq;
- srq = qp->srq;
+ if (atomic_read(&qp->usecnt))
+ return -EBUSY;
+
+ if (qp->real_qp != qp)
+ return __ib_destroy_shared_qp(qp);
+
+ pd = qp->pd;
+ scq = qp->send_cq;
+ rcq = qp->recv_cq;
+ srq = qp->srq;
ret = qp->device->destroy_qp(qp);
if (!ret) {
- atomic_dec(&pd->usecnt);
- atomic_dec(&scq->usecnt);
- atomic_dec(&rcq->usecnt);
+ if (pd)
+ atomic_dec(&pd->usecnt);
+ if (scq)
+ atomic_dec(&scq->usecnt);
+ if (rcq)
+ atomic_dec(&rcq->usecnt);
if (srq)
atomic_dec(&srq->usecnt);
}
@@ -920,3 +1202,42 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
return qp->device->detach_mcast(qp, gid, lid);
}
EXPORT_SYMBOL(ib_detach_mcast);
+
+struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
+{
+ struct ib_xrcd *xrcd;
+
+ if (!device->alloc_xrcd)
+ return ERR_PTR(-ENOSYS);
+
+ xrcd = device->alloc_xrcd(device, NULL, NULL);
+ if (!IS_ERR(xrcd)) {
+ xrcd->device = device;
+ xrcd->inode = NULL;
+ atomic_set(&xrcd->usecnt, 0);
+ mutex_init(&xrcd->tgt_qp_mutex);
+ INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+ }
+
+ return xrcd;
+}
+EXPORT_SYMBOL(ib_alloc_xrcd);
+
+int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+ struct ib_qp *qp;
+ int ret;
+
+ if (atomic_read(&xrcd->usecnt))
+ return -EBUSY;
+
+ while (!list_empty(&xrcd->tgt_qp_list)) {
+ qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list);
+ ret = ib_destroy_qp(qp);
+ if (ret)
+ return ret;
+ }
+
+ return xrcd->device->dealloc_xrcd(xrcd);
+}
+EXPORT_SYMBOL(ib_dealloc_xrcd);
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 0cfc455..5ce7b9e 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/inetdevice.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
@@ -799,13 +800,10 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* Loop thru additional data fragments and queue them */
if (skb_shinfo(skb)->nr_frags) {
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- maplen = frag->size;
- mapaddr =
- pci_map_page(c2dev->pcidev, frag->page,
- frag->page_offset, maplen,
- PCI_DMA_TODEVICE);
-
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ maplen = skb_frag_size(frag);
+ mapaddr = skb_frag_dma_map(&c2dev->pcidev->dev, frag,
+ 0, maplen, DMA_TO_DEVICE);
elem = elem->next;
elem->skb = NULL;
elem->mapaddr = mapaddr;
diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
index 24f9e3a..32d34e8 100644
--- a/drivers/infiniband/hw/amso1100/c2_ae.c
+++ b/drivers/infiniband/hw/amso1100/c2_ae.c
@@ -288,6 +288,11 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
cm_event.private_data_len =
be32_to_cpu(req->private_data_length);
cm_event.private_data = req->private_data;
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send
+ * max supported values
+ */
+ cm_event.ird = cm_event.ord = 128;
if (cm_id->event_handler)
cm_id->event_handler(cm_id, &cm_event);
diff --git a/drivers/infiniband/hw/amso1100/c2_intr.c b/drivers/infiniband/hw/amso1100/c2_intr.c
index 0ebe4e8..8951db4 100644
--- a/drivers/infiniband/hw/amso1100/c2_intr.c
+++ b/drivers/infiniband/hw/amso1100/c2_intr.c
@@ -183,6 +183,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
case IW_CM_EVENT_ESTABLISHED:
c2_set_qp_state(req->qp,
C2_QP_STATE_RTS);
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send
+ * max supported values
+ */
+ cm_event.ird = cm_event.ord = 128;
case IW_CM_EVENT_CLOSE:
/*
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index aeebc4d..12f923d 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -99,14 +99,6 @@ static int c2_query_port(struct ib_device *ibdev,
return 0;
}
-static int c2_modify_port(struct ib_device *ibdev,
- u8 port, int port_modify_mask,
- struct ib_port_modify *props)
-{
- pr_debug("%s:%u\n", __func__, __LINE__);
- return 0;
-}
-
static int c2_query_pkey(struct ib_device *ibdev,
u8 port, u16 index, u16 * pkey)
{
@@ -761,10 +753,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);
/* Print out the MAC address */
- pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
- netdev->name,
- netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
- netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+ pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
#if 0
/* Disable network packets */
@@ -817,7 +806,6 @@ int c2_register_device(struct c2_dev *dev)
dev->ibdev.dma_device = &dev->pcidev->dev;
dev->ibdev.query_device = c2_query_device;
dev->ibdev.query_port = c2_query_port;
- dev->ibdev.modify_port = c2_modify_port;
dev->ibdev.query_pkey = c2_query_pkey;
dev->ibdev.query_gid = c2_query_gid;
dev->ibdev.alloc_ucontext = c2_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile
index 621619c..2761364 100644
--- a/drivers/infiniband/hw/cxgb3/Makefile
+++ b/drivers/infiniband/hw/cxgb3/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb3
obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index e55ce7a..c88b12b 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -753,6 +753,11 @@ static void connect_request_upcall(struct iwch_ep *ep)
event.private_data_len = ep->plen;
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
event.provider_data = ep;
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send max
+ * supported values
+ */
+ event.ird = event.ord = 8;
if (state_read(&ep->parent_ep->com) != DEAD) {
get_ep(&ep->com);
ep->parent_ep->com.cm_id->event_handler(
@@ -770,6 +775,11 @@ static void established_upcall(struct iwch_ep *ep)
PDBG("%s ep %p\n", __func__, ep);
memset(&event, 0, sizeof(event));
event.event = IW_CM_EVENT_ESTABLISHED;
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send max
+ * supported values
+ */
+ event.ird = event.ord = 8;
if (ep->com.cm_id) {
PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index 71e0d84..abcc9e7 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -46,6 +46,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
struct ib_event event;
struct iwch_qp_attributes attrs;
struct iwch_qp *qhp;
+ unsigned long flag;
spin_lock(&rnicp->lock);
qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
@@ -94,7 +95,9 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
if (atomic_dec_and_test(&qhp->refcnt))
wake_up(&qhp->wait);
@@ -107,6 +110,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
struct iwch_cq *chp;
struct iwch_qp *qhp;
u32 cqid = RSPQ_CQID(rsp_msg);
+ unsigned long flag;
rnicp = (struct iwch_dev *) rdev_p->ulp;
spin_lock(&rnicp->lock);
@@ -170,7 +174,9 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
*/
if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
dst_confirm(qhp->ep->dst);
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
break;
case TPT_ERR_STAG:
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 2e27413..37c224f 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -61,13 +61,6 @@
#include "iwch_user.h"
#include "common.h"
-static int iwch_modify_port(struct ib_device *ibdev,
- u8 port, int port_modify_mask,
- struct ib_port_modify *props)
-{
- return -ENOSYS;
-}
-
static struct ib_ah *iwch_ah_create(struct ib_pd *pd,
struct ib_ah_attr *ah_attr)
{
@@ -197,6 +190,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
chp->rhp = rhp;
chp->ibcq.cqe = 1 << chp->cq.size_log2;
spin_lock_init(&chp->lock);
+ spin_lock_init(&chp->comp_handler_lock);
atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait);
if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
@@ -1392,7 +1386,6 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.dma_device = &(dev->rdev.rnic_info.pdev->dev);
dev->ibdev.query_device = iwch_query_device;
dev->ibdev.query_port = iwch_query_port;
- dev->ibdev.modify_port = iwch_modify_port;
dev->ibdev.query_pkey = iwch_query_pkey;
dev->ibdev.query_gid = iwch_query_gid;
dev->ibdev.alloc_ucontext = iwch_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index 9a342c9..87c14b0 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -103,6 +103,7 @@ struct iwch_cq {
struct iwch_dev *rhp;
struct t3_cq cq;
spinlock_t lock;
+ spinlock_t comp_handler_lock;
atomic_t refcnt;
wait_queue_head_t wait;
u32 __user *user_rptr_addr;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index ecd313f..bea5839 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -822,8 +822,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, *flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
+ }
/* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, *flag);
@@ -833,8 +836,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, *flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&schp->comp_handler_lock, *flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
+ }
/* deref */
if (atomic_dec_and_test(&qhp->refcnt))
@@ -853,11 +859,15 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
if (qhp->ibqp.uobject) {
cxio_set_wq_in_error(&qhp->wq);
cxio_set_cq_in_error(&rchp->cq);
+ spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
if (schp != rchp) {
cxio_set_cq_in_error(&schp->cq);
+ spin_lock_irqsave(&schp->comp_handler_lock, *flag);
(*schp->ibcq.comp_handler)(&schp->ibcq,
schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
}
return;
}
diff --git a/drivers/infiniband/hw/cxgb4/Makefile b/drivers/infiniband/hw/cxgb4/Makefile
index cd20b13..46b878c 100644
--- a/drivers/infiniband/hw/cxgb4/Makefile
+++ b/drivers/infiniband/hw/cxgb4/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 267005d..2e6a538 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -103,7 +103,8 @@ MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
static int mpa_rev = 1;
module_param(mpa_rev, int, 0644);
MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
- "1 is spec compliant. (default=1)");
+ "1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
+ " compliant (default=1)");
static int markers_enabled;
module_param(markers_enabled, int, 0644);
@@ -497,17 +498,21 @@ static int send_connect(struct c4iw_ep *ep)
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
}
-static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
+static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
+ u8 mpa_rev_to_use)
{
int mpalen, wrlen;
struct fw_ofld_tx_data_wr *req;
struct mpa_message *mpa;
+ struct mpa_v2_conn_params mpa_v2_params;
PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
BUG_ON(skb_cloned(skb));
mpalen = sizeof(*mpa) + ep->plen;
+ if (mpa_rev_to_use == 2)
+ mpalen += sizeof(struct mpa_v2_conn_params);
wrlen = roundup(mpalen + sizeof *req, 16);
skb = get_skb(skb, wrlen, GFP_KERNEL);
if (!skb) {
@@ -533,12 +538,41 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
mpa = (struct mpa_message *)(req + 1);
memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
mpa->flags = (crc_enabled ? MPA_CRC : 0) |
- (markers_enabled ? MPA_MARKERS : 0);
+ (markers_enabled ? MPA_MARKERS : 0) |
+ (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
mpa->private_data_size = htons(ep->plen);
- mpa->revision = mpa_rev;
+ mpa->revision = mpa_rev_to_use;
+ if (mpa_rev_to_use == 1) {
+ ep->tried_with_mpa_v1 = 1;
+ ep->retry_with_mpa_v1 = 0;
+ }
+
+ if (mpa_rev_to_use == 2) {
+ mpa->private_data_size +=
+ htons(sizeof(struct mpa_v2_conn_params));
+ mpa_v2_params.ird = htons((u16)ep->ird);
+ mpa_v2_params.ord = htons((u16)ep->ord);
+
+ if (peer2peer) {
+ mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+ if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_WRITE_RTR);
+ else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_READ_RTR);
+ }
+ memcpy(mpa->private_data, &mpa_v2_params,
+ sizeof(struct mpa_v2_conn_params));
- if (ep->plen)
- memcpy(mpa->private_data, ep->mpa_pkt + sizeof(*mpa), ep->plen);
+ if (ep->plen)
+ memcpy(mpa->private_data +
+ sizeof(struct mpa_v2_conn_params),
+ ep->mpa_pkt + sizeof(*mpa), ep->plen);
+ } else
+ if (ep->plen)
+ memcpy(mpa->private_data,
+ ep->mpa_pkt + sizeof(*mpa), ep->plen);
/*
* Reference the mpa skb. This ensures the data area
@@ -562,10 +596,13 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
struct fw_ofld_tx_data_wr *req;
struct mpa_message *mpa;
struct sk_buff *skb;
+ struct mpa_v2_conn_params mpa_v2_params;
PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
mpalen = sizeof(*mpa) + plen;
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+ mpalen += sizeof(struct mpa_v2_conn_params);
wrlen = roundup(mpalen + sizeof *req, 16);
skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -595,8 +632,29 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
mpa->flags = MPA_REJECT;
mpa->revision = mpa_rev;
mpa->private_data_size = htons(plen);
- if (plen)
- memcpy(mpa->private_data, pdata, plen);
+
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+ mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+ mpa->private_data_size +=
+ htons(sizeof(struct mpa_v2_conn_params));
+ mpa_v2_params.ird = htons(((u16)ep->ird) |
+ (peer2peer ? MPA_V2_PEER2PEER_MODEL :
+ 0));
+ mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ?
+ (p2p_type ==
+ FW_RI_INIT_P2PTYPE_RDMA_WRITE ?
+ MPA_V2_RDMA_WRITE_RTR : p2p_type ==
+ FW_RI_INIT_P2PTYPE_READ_REQ ?
+ MPA_V2_RDMA_READ_RTR : 0) : 0));
+ memcpy(mpa->private_data, &mpa_v2_params,
+ sizeof(struct mpa_v2_conn_params));
+
+ if (ep->plen)
+ memcpy(mpa->private_data +
+ sizeof(struct mpa_v2_conn_params), pdata, plen);
+ } else
+ if (plen)
+ memcpy(mpa->private_data, pdata, plen);
/*
* Reference the mpa skb again. This ensures the data area
@@ -617,10 +675,13 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
struct fw_ofld_tx_data_wr *req;
struct mpa_message *mpa;
struct sk_buff *skb;
+ struct mpa_v2_conn_params mpa_v2_params;
PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
mpalen = sizeof(*mpa) + plen;
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+ mpalen += sizeof(struct mpa_v2_conn_params);
wrlen = roundup(mpalen + sizeof *req, 16);
skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -649,10 +710,36 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
(markers_enabled ? MPA_MARKERS : 0);
- mpa->revision = mpa_rev;
+ mpa->revision = ep->mpa_attr.version;
mpa->private_data_size = htons(plen);
- if (plen)
- memcpy(mpa->private_data, pdata, plen);
+
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+ mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+ mpa->private_data_size +=
+ htons(sizeof(struct mpa_v2_conn_params));
+ mpa_v2_params.ird = htons((u16)ep->ird);
+ mpa_v2_params.ord = htons((u16)ep->ord);
+ if (peer2peer && (ep->mpa_attr.p2p_type !=
+ FW_RI_INIT_P2PTYPE_DISABLED)) {
+ mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+
+ if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_WRITE_RTR);
+ else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_READ_RTR);
+ }
+
+ memcpy(mpa->private_data, &mpa_v2_params,
+ sizeof(struct mpa_v2_conn_params));
+
+ if (ep->plen)
+ memcpy(mpa->private_data +
+ sizeof(struct mpa_v2_conn_params), pdata, plen);
+ } else
+ if (plen)
+ memcpy(mpa->private_data, pdata, plen);
/*
* Reference the mpa skb. This ensures the data area
@@ -695,7 +782,10 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
/* start MPA negotiation */
send_flowc(ep, NULL);
- send_mpa_req(ep, skb);
+ if (ep->retry_with_mpa_v1)
+ send_mpa_req(ep, skb, 1);
+ else
+ send_mpa_req(ep, skb, mpa_rev);
return 0;
}
@@ -769,8 +859,19 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
event.remote_addr = ep->com.remote_addr;
if ((status == 0) || (status == -ECONNREFUSED)) {
- event.private_data_len = ep->plen;
- event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+ if (!ep->tried_with_mpa_v1) {
+ /* this means MPA_v2 is used */
+ event.private_data_len = ep->plen -
+ sizeof(struct mpa_v2_conn_params);
+ event.private_data = ep->mpa_pkt +
+ sizeof(struct mpa_message) +
+ sizeof(struct mpa_v2_conn_params);
+ } else {
+ /* this means MPA_v1 is used */
+ event.private_data_len = ep->plen;
+ event.private_data = ep->mpa_pkt +
+ sizeof(struct mpa_message);
+ }
}
PDBG("%s ep %p tid %u status %d\n", __func__, ep,
@@ -793,9 +894,22 @@ static void connect_request_upcall(struct c4iw_ep *ep)
event.event = IW_CM_EVENT_CONNECT_REQUEST;
event.local_addr = ep->com.local_addr;
event.remote_addr = ep->com.remote_addr;
- event.private_data_len = ep->plen;
- event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
event.provider_data = ep;
+ if (!ep->tried_with_mpa_v1) {
+ /* this means MPA_v2 is used */
+ event.ord = ep->ord;
+ event.ird = ep->ird;
+ event.private_data_len = ep->plen -
+ sizeof(struct mpa_v2_conn_params);
+ event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) +
+ sizeof(struct mpa_v2_conn_params);
+ } else {
+ /* this means MPA_v1 is used. Send max supported */
+ event.ord = c4iw_max_read_depth;
+ event.ird = c4iw_max_read_depth;
+ event.private_data_len = ep->plen;
+ event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+ }
if (state_read(&ep->parent_ep->com) != DEAD) {
c4iw_get_ep(&ep->com);
ep->parent_ep->com.cm_id->event_handler(
@@ -813,6 +927,8 @@ static void established_upcall(struct c4iw_ep *ep)
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
memset(&event, 0, sizeof(event));
event.event = IW_CM_EVENT_ESTABLISHED;
+ event.ird = ep->ird;
+ event.ord = ep->ord;
if (ep->com.cm_id) {
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -848,7 +964,10 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
{
struct mpa_message *mpa;
+ struct mpa_v2_conn_params *mpa_v2_params;
u16 plen;
+ u16 resp_ird, resp_ord;
+ u8 rtr_mismatch = 0, insuff_ird = 0;
struct c4iw_qp_attributes attrs;
enum c4iw_qp_attr_mask mask;
int err;
@@ -888,7 +1007,9 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
mpa = (struct mpa_message *) ep->mpa_pkt;
/* Validate MPA header. */
- if (mpa->revision != mpa_rev) {
+ if (mpa->revision > mpa_rev) {
+ printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+ " Received = %d\n", __func__, mpa_rev, mpa->revision);
err = -EPROTO;
goto err;
}
@@ -938,13 +1059,66 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
ep->mpa_attr.recv_marker_enabled = markers_enabled;
ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
- ep->mpa_attr.version = mpa_rev;
- ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
- FW_RI_INIT_P2PTYPE_DISABLED;
+ ep->mpa_attr.version = mpa->revision;
+ ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+ if (mpa->revision == 2) {
+ ep->mpa_attr.enhanced_rdma_conn =
+ mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+ if (ep->mpa_attr.enhanced_rdma_conn) {
+ mpa_v2_params = (struct mpa_v2_conn_params *)
+ (ep->mpa_pkt + sizeof(*mpa));
+ resp_ird = ntohs(mpa_v2_params->ird) &
+ MPA_V2_IRD_ORD_MASK;
+ resp_ord = ntohs(mpa_v2_params->ord) &
+ MPA_V2_IRD_ORD_MASK;
+
+ /*
+ * This is a double-check. Ideally, below checks are
+ * not required since ird/ord stuff has been taken
+ * care of in c4iw_accept_cr
+ */
+ if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+ err = -ENOMEM;
+ ep->ird = resp_ord;
+ ep->ord = resp_ird;
+ insuff_ird = 1;
+ }
+
+ if (ntohs(mpa_v2_params->ird) &
+ MPA_V2_PEER2PEER_MODEL) {
+ if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_WRITE_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+ else if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_READ_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_READ_REQ;
+ }
+ }
+ } else if (mpa->revision == 1)
+ if (peer2peer)
+ ep->mpa_attr.p2p_type = p2p_type;
+
PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
- "xmit_marker_enabled=%d, version=%d\n", __func__,
- ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
- ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+ "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = "
+ "%d\n", __func__, ep->mpa_attr.crc_enabled,
+ ep->mpa_attr.recv_marker_enabled,
+ ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
+ ep->mpa_attr.p2p_type, p2p_type);
+
+ /*
+ * If responder's RTR does not match with that of initiator, assign
+ * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not
+ * generated when moving QP to RTS state.
+ * A TERM message will be sent after QP has moved to RTS state
+ */
+ if ((ep->mpa_attr.version == 2) &&
+ (ep->mpa_attr.p2p_type != p2p_type)) {
+ ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+ rtr_mismatch = 1;
+ }
attrs.mpa_attr = ep->mpa_attr;
attrs.max_ird = ep->ird;
@@ -961,6 +1135,39 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
ep->com.qp, mask, &attrs, 1);
if (err)
goto err;
+
+ /*
+ * If responder's RTR requirement did not match with what initiator
+ * supports, generate TERM message
+ */
+ if (rtr_mismatch) {
+ printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__);
+ attrs.layer_etype = LAYER_MPA | DDP_LLP;
+ attrs.ecode = MPA_NOMATCH_RTR;
+ attrs.next_state = C4IW_QP_STATE_TERMINATE;
+ err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+ C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Generate TERM if initiator IRD is not sufficient for responder
+ * provided ORD. Currently, we do the same behaviour even when
+ * responder provided IRD is also not sufficient as regards to
+ * initiator ORD.
+ */
+ if (insuff_ird) {
+ printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n",
+ __func__);
+ attrs.layer_etype = LAYER_MPA | DDP_LLP;
+ attrs.ecode = MPA_INSUFF_IRD;
+ attrs.next_state = C4IW_QP_STATE_TERMINATE;
+ err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+ C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+ err = -ENOMEM;
+ goto out;
+ }
goto out;
err:
state_set(&ep->com, ABORTING);
@@ -973,6 +1180,7 @@ out:
static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
{
struct mpa_message *mpa;
+ struct mpa_v2_conn_params *mpa_v2_params;
u16 plen;
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1013,7 +1221,9 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
/*
* Validate MPA Header.
*/
- if (mpa->revision != mpa_rev) {
+ if (mpa->revision > mpa_rev) {
+ printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+ " Received = %d\n", __func__, mpa_rev, mpa->revision);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
@@ -1056,9 +1266,37 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
ep->mpa_attr.recv_marker_enabled = markers_enabled;
ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
- ep->mpa_attr.version = mpa_rev;
- ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
- FW_RI_INIT_P2PTYPE_DISABLED;
+ ep->mpa_attr.version = mpa->revision;
+ if (mpa->revision == 1)
+ ep->tried_with_mpa_v1 = 1;
+ ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+ if (mpa->revision == 2) {
+ ep->mpa_attr.enhanced_rdma_conn =
+ mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+ if (ep->mpa_attr.enhanced_rdma_conn) {
+ mpa_v2_params = (struct mpa_v2_conn_params *)
+ (ep->mpa_pkt + sizeof(*mpa));
+ ep->ird = ntohs(mpa_v2_params->ird) &
+ MPA_V2_IRD_ORD_MASK;
+ ep->ord = ntohs(mpa_v2_params->ord) &
+ MPA_V2_IRD_ORD_MASK;
+ if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
+ if (peer2peer) {
+ if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_WRITE_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+ else if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_READ_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_READ_REQ;
+ }
+ }
+ } else if (mpa->revision == 1)
+ if (peer2peer)
+ ep->mpa_attr.p2p_type = p2p_type;
+
PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
"xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__,
ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
@@ -1552,6 +1790,114 @@ static int is_neg_adv_abort(unsigned int status)
status == CPL_ERR_PERSIST_NEG_ADVICE;
}
+static int c4iw_reconnect(struct c4iw_ep *ep)
+{
+ int err = 0;
+ struct rtable *rt;
+ struct net_device *pdev;
+ struct neighbour *neigh;
+ int step;
+
+ PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
+ init_timer(&ep->timer);
+
+ /*
+ * Allocate an active TID to initiate a TCP connection.
+ */
+ ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
+ if (ep->atid == -1) {
+ printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+ err = -ENOMEM;
+ goto fail2;
+ }
+
+ /* find a route */
+ rt = find_route(ep->com.dev,
+ ep->com.cm_id->local_addr.sin_addr.s_addr,
+ ep->com.cm_id->remote_addr.sin_addr.s_addr,
+ ep->com.cm_id->local_addr.sin_port,
+ ep->com.cm_id->remote_addr.sin_port, 0);
+ if (!rt) {
+ printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+ err = -EHOSTUNREACH;
+ goto fail3;
+ }
+ ep->dst = &rt->dst;
+
+ rcu_read_lock();
+ neigh = dst_get_neighbour(ep->dst);
+
+ /* get a l2t entry */
+ if (neigh->dev->flags & IFF_LOOPBACK) {
+ PDBG("%s LOOPBACK\n", __func__);
+ pdev = ip_dev_find(&init_net,
+ ep->com.cm_id->remote_addr.sin_addr.s_addr);
+ ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+ neigh, pdev, 0);
+ ep->mtu = pdev->mtu;
+ ep->tx_chan = cxgb4_port_chan(pdev);
+ ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+ step = ep->com.dev->rdev.lldi.ntxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->txq_idx = cxgb4_port_idx(pdev) * step;
+ step = ep->com.dev->rdev.lldi.nrxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->ctrlq_idx = cxgb4_port_idx(pdev);
+ ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+ cxgb4_port_idx(pdev) * step];
+ dev_put(pdev);
+ } else {
+ ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+ neigh, neigh->dev, 0);
+ ep->mtu = dst_mtu(ep->dst);
+ ep->tx_chan = cxgb4_port_chan(neigh->dev);
+ ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+ step = ep->com.dev->rdev.lldi.ntxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
+ step = ep->com.dev->rdev.lldi.nrxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+ cxgb4_port_idx(neigh->dev) * step];
+ }
+ rcu_read_unlock();
+ if (!ep->l2t) {
+ printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+ err = -ENOMEM;
+ goto fail4;
+ }
+
+ PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
+ __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
+ ep->l2t->idx);
+
+ state_set(&ep->com, CONNECTING);
+ ep->tos = 0;
+
+ /* send connect request to rnic */
+ err = send_connect(ep);
+ if (!err)
+ goto out;
+
+ cxgb4_l2t_release(ep->l2t);
+fail4:
+ dst_release(ep->dst);
+fail3:
+ cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
+fail2:
+ /*
+ * remember to send notification to upper layer.
+ * We are in here so the upper layer is not aware that this is
+ * re-connect attempt and so, upper layer is still waiting for
+ * response of 1st connect request.
+ */
+ connect_reply_upcall(ep, -ECONNRESET);
+ c4iw_put_ep(&ep->com);
+out:
+ return err;
+}
+
static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
{
struct cpl_abort_req_rss *req = cplhdr(skb);
@@ -1575,8 +1921,11 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
/*
* Wake up any threads in rdma_init() or rdma_fini().
+ * However, this is not needed if com state is just
+ * MPA_REQ_SENT
*/
- c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+ if (ep->com.state != MPA_REQ_SENT)
+ c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
mutex_lock(&ep->com.mutex);
switch (ep->com.state) {
@@ -1587,7 +1936,21 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
break;
case MPA_REQ_SENT:
stop_ep_timer(ep);
- connect_reply_upcall(ep, -ECONNRESET);
+ if (mpa_rev == 2 && ep->tried_with_mpa_v1)
+ connect_reply_upcall(ep, -ECONNRESET);
+ else {
+ /*
+ * we just don't send notification upwards because we
+ * want to retry with mpa_v1 without upper layers even
+ * knowing it.
+ *
+ * do some housekeeping so as to re-initiate the
+ * connection
+ */
+ PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__,
+ mpa_rev);
+ ep->retry_with_mpa_v1 = 1;
+ }
break;
case MPA_REP_SENT:
break;
@@ -1623,7 +1986,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
dst_confirm(ep->dst);
if (ep->com.state != ABORTING) {
__state_set(&ep->com, DEAD);
- release = 1;
+ /* we don't release if we want to retry with mpa_v1 */
+ if (!ep->retry_with_mpa_v1)
+ release = 1;
}
mutex_unlock(&ep->com.mutex);
@@ -1643,6 +2008,15 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
out:
if (release)
release_ep_resources(ep);
+
+ /* retry with mpa-v1 */
+ if (ep && ep->retry_with_mpa_v1) {
+ cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
+ dst_release(ep->dst);
+ cxgb4_l2t_release(ep->l2t);
+ c4iw_reconnect(ep);
+ }
+
return 0;
}
@@ -1794,18 +2168,40 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
goto err;
}
- cm_id->add_ref(cm_id);
- ep->com.cm_id = cm_id;
- ep->com.qp = qp;
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+ if (conn_param->ord > ep->ird) {
+ ep->ird = conn_param->ird;
+ ep->ord = conn_param->ord;
+ send_mpa_reject(ep, conn_param->private_data,
+ conn_param->private_data_len);
+ abort_connection(ep, NULL, GFP_KERNEL);
+ err = -ENOMEM;
+ goto err;
+ }
+ if (conn_param->ird > ep->ord) {
+ if (!ep->ord)
+ conn_param->ird = 1;
+ else {
+ abort_connection(ep, NULL, GFP_KERNEL);
+ err = -ENOMEM;
+ goto err;
+ }
+ }
+ }
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
- if (peer2peer && ep->ird == 0)
- ep->ird = 1;
+ if (ep->mpa_attr.version != 2)
+ if (peer2peer && ep->ird == 0)
+ ep->ird = 1;
PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
+ cm_id->add_ref(cm_id);
+ ep->com.cm_id = cm_id;
+ ep->com.qp = qp;
+
/* bind QP to EP and move to RTS */
attrs.mpa_attr = ep->mpa_attr;
attrs.max_ird = ep->ird;
@@ -1947,6 +2343,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->com.dev->rdev.lldi.nchan;
ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
cxgb4_port_idx(neigh->dev) * step];
+ ep->retry_with_mpa_v1 = 0;
+ ep->tried_with_mpa_v1 = 0;
}
rcu_read_unlock();
if (!ep->l2t) {
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 1720dc7..3bd6b69 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -185,7 +185,7 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
V_CQE_OPCODE(FW_RI_SEND) |
V_CQE_TYPE(0) |
V_CQE_SWCQE(1) |
- V_CQE_QPID(wq->rq.qid));
+ V_CQE_QPID(wq->sq.qid));
cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
cq->sw_queue[cq->sw_pidx] = cqe;
t4_swcq_produce(cq);
@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
while (ptr != cq->sw_pidx) {
cqe = &cq->sw_queue[ptr];
if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) &&
- (CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq))
+ (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq))
(*count)++;
if (++ptr == cq->size)
ptr = 0;
@@ -818,6 +818,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
chp->cq.size--; /* status page */
chp->ibcq.cqe = entries - 2;
spin_lock_init(&chp->lock);
+ spin_lock_init(&chp->comp_handler_lock);
atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait);
ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
@@ -842,7 +843,8 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
uresp.gts_key = ucontext->key;
ucontext->key += PAGE_SIZE;
spin_unlock(&ucontext->mmap_lock);
- ret = ib_copy_to_udata(udata, &uresp, sizeof uresp);
+ ret = ib_copy_to_udata(udata, &uresp,
+ sizeof(uresp) - sizeof(uresp.reserved));
if (ret)
goto err5;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 40a13cc..6d0df6e 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -376,10 +376,8 @@ struct uld_ctx {
struct c4iw_dev *dev;
};
-static void c4iw_remove(struct uld_ctx *ctx)
+static void c4iw_dealloc(struct uld_ctx *ctx)
{
- PDBG("%s c4iw_dev %p\n", __func__, ctx->dev);
- c4iw_unregister_device(ctx->dev);
c4iw_rdev_close(&ctx->dev->rdev);
idr_destroy(&ctx->dev->cqidr);
idr_destroy(&ctx->dev->qpidr);
@@ -389,11 +387,30 @@ static void c4iw_remove(struct uld_ctx *ctx)
ctx->dev = NULL;
}
+static void c4iw_remove(struct uld_ctx *ctx)
+{
+ PDBG("%s c4iw_dev %p\n", __func__, ctx->dev);
+ c4iw_unregister_device(ctx->dev);
+ c4iw_dealloc(ctx);
+}
+
+static int rdma_supported(const struct cxgb4_lld_info *infop)
+{
+ return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
+ infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
+ infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
+}
+
static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
{
struct c4iw_dev *devp;
int ret;
+ if (!rdma_supported(infop)) {
+ printk(KERN_INFO MOD "%s: RDMA not supported on this device.\n",
+ pci_name(infop->pdev));
+ return ERR_PTR(-ENOSYS);
+ }
devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
if (!devp) {
printk(KERN_ERR MOD "Cannot allocate ib device\n");
@@ -414,7 +431,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
ret = c4iw_rdev_open(&devp->rdev);
if (ret) {
- mutex_unlock(&dev_mutex);
printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
ib_dealloc_device(&devp->ibdev);
return ERR_PTR(ret);
@@ -519,15 +535,24 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
case CXGB4_STATE_UP:
printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
if (!ctx->dev) {
- int ret = 0;
+ int ret;
ctx->dev = c4iw_alloc(&ctx->lldi);
- if (!IS_ERR(ctx->dev))
- ret = c4iw_register_device(ctx->dev);
- if (IS_ERR(ctx->dev) || ret)
+ if (IS_ERR(ctx->dev)) {
+ printk(KERN_ERR MOD
+ "%s: initialization failed: %ld\n",
+ pci_name(ctx->lldi.pdev),
+ PTR_ERR(ctx->dev));
+ ctx->dev = NULL;
+ break;
+ }
+ ret = c4iw_register_device(ctx->dev);
+ if (ret) {
printk(KERN_ERR MOD
"%s: RDMA registration failed: %d\n",
pci_name(ctx->lldi.pdev), ret);
+ c4iw_dealloc(ctx);
+ }
}
break;
case CXGB4_STATE_DOWN:
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index c13041a..397cb36 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -42,6 +42,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
{
struct ib_event event;
struct c4iw_qp_attributes attrs;
+ unsigned long flag;
if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
(qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
@@ -72,7 +73,9 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
}
void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
@@ -183,11 +186,14 @@ out:
int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
{
struct c4iw_cq *chp;
+ unsigned long flag;
chp = get_chp(dev, qid);
- if (chp)
+ if (chp) {
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
- else
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
+ } else
PDBG("%s unknown cqid 0x%x\n", __func__, qid);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 4f04537..1357c5b 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -309,6 +309,7 @@ struct c4iw_cq {
struct c4iw_dev *rhp;
struct t4_cq cq;
spinlock_t lock;
+ spinlock_t comp_handler_lock;
atomic_t refcnt;
wait_queue_head_t wait;
};
@@ -323,6 +324,7 @@ struct c4iw_mpa_attributes {
u8 recv_marker_enabled;
u8 xmit_marker_enabled;
u8 crc_enabled;
+ u8 enhanced_rdma_conn;
u8 version;
u8 p2p_type;
};
@@ -349,6 +351,8 @@ struct c4iw_qp_attributes {
u8 is_terminate_local;
struct c4iw_mpa_attributes mpa_attr;
struct c4iw_ep *llp_stream_handle;
+ u8 layer_etype;
+ u8 ecode;
};
struct c4iw_qp {
@@ -501,11 +505,18 @@ enum c4iw_mmid_state {
#define MPA_KEY_REP "MPA ID Rep Frame"
#define MPA_MAX_PRIVATE_DATA 256
+#define MPA_ENHANCED_RDMA_CONN 0x10
#define MPA_REJECT 0x20
#define MPA_CRC 0x40
#define MPA_MARKERS 0x80
#define MPA_FLAGS_MASK 0xE0
+#define MPA_V2_PEER2PEER_MODEL 0x8000
+#define MPA_V2_ZERO_LEN_FPDU_RTR 0x4000
+#define MPA_V2_RDMA_WRITE_RTR 0x8000
+#define MPA_V2_RDMA_READ_RTR 0x4000
+#define MPA_V2_IRD_ORD_MASK 0x3FFF
+
#define c4iw_put_ep(ep) { \
PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \
ep, atomic_read(&((ep)->kref.refcount))); \
@@ -528,6 +539,11 @@ struct mpa_message {
u8 private_data[0];
};
+struct mpa_v2_conn_params {
+ __be16 ird;
+ __be16 ord;
+};
+
struct terminate_message {
u8 layer_etype;
u8 ecode;
@@ -580,7 +596,10 @@ enum c4iw_ddp_ecodes {
enum c4iw_mpa_ecodes {
MPA_CRC_ERR = 0x02,
- MPA_MARKER_ERR = 0x03
+ MPA_MARKER_ERR = 0x03,
+ MPA_LOCAL_CATA = 0x05,
+ MPA_INSUFF_IRD = 0x06,
+ MPA_NOMATCH_RTR = 0x07,
};
enum c4iw_ep_state {
@@ -651,6 +670,8 @@ struct c4iw_ep {
u16 txq_idx;
u16 ctrlq_idx;
u8 tos;
+ u8 retry_with_mpa_v1;
+ u8 tried_with_mpa_v1;
};
static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 0347eed..40c8353 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -31,7 +31,7 @@
*/
#include <rdma/ib_umem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "iw_cxgb4.h"
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 5b9e422..247fe70 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -58,13 +58,6 @@ static int fastreg_support = 1;
module_param(fastreg_support, int, 0644);
MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)");
-static int c4iw_modify_port(struct ib_device *ibdev,
- u8 port, int port_modify_mask,
- struct ib_port_modify *props)
-{
- return -ENOSYS;
-}
-
static struct ib_ah *c4iw_ah_create(struct ib_pd *pd,
struct ib_ah_attr *ah_attr)
{
@@ -456,7 +449,6 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.dma_device = &(dev->rdev.lldi.pdev->dev);
dev->ibdev.query_device = c4iw_query_device;
dev->ibdev.query_port = c4iw_query_port;
- dev->ibdev.modify_port = c4iw_modify_port;
dev->ibdev.query_pkey = c4iw_query_pkey;
dev->ibdev.query_gid = c4iw_query_gid;
dev->ibdev.alloc_ucontext = c4iw_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index a41578e..5f940ae 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -29,6 +29,9 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
+#include <linux/module.h>
+
#include "iw_cxgb4.h"
static int ocqp_support = 1;
@@ -917,7 +920,11 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
wqe->u.terminate.type = FW_RI_TYPE_TERMINATE;
wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term);
term = (struct terminate_message *)wqe->u.terminate.termmsg;
- build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
+ if (qhp->attr.layer_etype == (LAYER_MPA|DDP_LLP)) {
+ term->layer_etype = qhp->attr.layer_etype;
+ term->ecode = qhp->attr.ecode;
+ } else
+ build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
c4iw_ofld_send(&qhp->rhp->rdev, skb);
}
@@ -941,8 +948,11 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&rchp->comp_handler_lock, flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+ }
/* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, flag);
@@ -952,13 +962,17 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&schp->comp_handler_lock, flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+ }
}
static void flush_qp(struct c4iw_qp *qhp)
{
struct c4iw_cq *rchp, *schp;
+ unsigned long flag;
rchp = get_chp(qhp->rhp, qhp->attr.rcq);
schp = get_chp(qhp->rhp, qhp->attr.scq);
@@ -966,8 +980,16 @@ static void flush_qp(struct c4iw_qp *qhp)
if (qhp->ibqp.uobject) {
t4_set_wq_in_error(&qhp->wq);
t4_set_cq_in_error(&rchp->cq);
- if (schp != rchp)
+ spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+ (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+ if (schp != rchp) {
t4_set_cq_in_error(&schp->cq);
+ spin_lock_irqsave(&schp->comp_handler_lock, flag);
+ (*schp->ibcq.comp_handler)(&schp->ibcq,
+ schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+ }
return;
}
__flush_qp(qhp, rchp, schp);
@@ -1012,6 +1034,7 @@ out:
static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init)
{
+ PDBG("%s p2p_type = %d\n", __func__, p2p_type);
memset(&init->u, 0, sizeof init->u);
switch (p2p_type) {
case FW_RI_INIT_P2PTYPE_RDMA_WRITE:
@@ -1206,12 +1229,16 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
disconnect = 1;
c4iw_get_ep(&qhp->ep->com);
}
+ if (qhp->ibqp.uobject)
+ t4_set_wq_in_error(&qhp->wq);
ret = rdma_fini(rhp, qhp, ep);
if (ret)
goto err;
break;
case C4IW_QP_STATE_TERMINATE:
set_state(qhp, C4IW_QP_STATE_TERMINATE);
+ qhp->attr.layer_etype = attrs->layer_etype;
+ qhp->attr.ecode = attrs->ecode;
if (qhp->ibqp.uobject)
t4_set_wq_in_error(&qhp->wq);
ep = qhp->ep;
@@ -1222,6 +1249,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
break;
case C4IW_QP_STATE_ERROR:
set_state(qhp, C4IW_QP_STATE_ERROR);
+ if (qhp->ibqp.uobject)
+ t4_set_wq_in_error(&qhp->wq);
if (!internal) {
abort = 1;
disconnect = 1;
@@ -1334,7 +1363,10 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
rhp = qhp->rhp;
attrs.next_state = C4IW_QP_STATE_ERROR;
- c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+ if (qhp->attr.state == C4IW_QP_STATE_TERMINATE)
+ c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+ else
+ c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
wait_event(qhp->wait, !qhp->ep);
remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 4fb50d5..407ff39 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/genalloc.h>
+#include <linux/ratelimit.h>
#include "iw_cxgb4.h"
#define RANDOM_SIZE 16
@@ -311,8 +312,8 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
{
unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
- if (!addr && printk_ratelimit())
- printk(KERN_WARNING MOD "%s: Out of PBL memory\n",
+ if (!addr)
+ printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
pci_name(rdev->lldi.pdev));
return (u32)addr;
}
@@ -373,8 +374,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
{
unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
- if (!addr && printk_ratelimit())
- printk(KERN_WARNING MOD "%s: Out of RQT memory\n",
+ if (!addr)
+ printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
pci_name(rdev->lldi.pdev));
return (u32)addr;
}
diff --git a/drivers/infiniband/hw/cxgb4/user.h b/drivers/infiniband/hw/cxgb4/user.h
index e6669d5..06e8938 100644
--- a/drivers/infiniband/hw/cxgb4/user.h
+++ b/drivers/infiniband/hw/cxgb4/user.h
@@ -48,6 +48,7 @@ struct c4iw_create_cq_resp {
__u32 cqid;
__u32 size;
__u32 qid_mask;
+ __u32 reserved; /* explicit padding (optional for i386) */
};
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index d9b0ebc..6eeb84d 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -296,6 +296,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
(my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1));
if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
ehca_err(device, "Copy to udata failed.");
+ cq = ERR_PTR(-EFAULT);
goto create_cq_exit4;
}
}
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index d9b1bb4..818d721 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -125,7 +125,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
- IRQF_DISABLED, "ehca_eq",
+ 0, "ehca_eq",
(void *)shca);
if (ret < 0)
ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -133,7 +133,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
- IRQF_DISABLED, "ehca_neq",
+ 0, "ehca_neq",
(void *)shca);
if (ret < 0)
ehca_err(ib_dev, "Can't map interrupt handler.");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 32fb342..964f855 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -977,6 +977,9 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
struct hcp_modify_qp_control_block *mqpcb;
u64 hret, update_mask;
+ if (srq_init_attr->srq_type != IB_SRQT_BASIC)
+ return ERR_PTR(-ENOSYS);
+
/* For common attributes, internal_create_qp() takes its info
* out of qp_init_attr, so copy all common attrs there.
*/
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index f09914c..54c0d23 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -58,7 +58,7 @@
#include <linux/cpu.h>
#include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/abs_addr.h>
#include <asm/ibmebus.h>
#include <asm/io.h>
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index daef61d..45802e9 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -45,6 +45,7 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
+#include <linux/export.h>
#include <asm/uaccess.h>
#include "ipath_kernel.h"
@@ -325,7 +326,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
size_t count, loff_t *off)
{
u32 __iomem *piobuf;
- u32 plen, clen, pbufn;
+ u32 plen, pbufn, maxlen_reserve;
struct ipath_diag_pkt odp;
struct ipath_diag_xpkt dp;
u32 *tmpbuf = NULL;
@@ -334,42 +335,24 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
u64 val;
u32 l_state, lt_state; /* LinkState, LinkTrainingState */
- if (count < sizeof(odp)) {
- ret = -EINVAL;
- goto bail;
- }
if (count == sizeof(dp)) {
if (copy_from_user(&dp, data, sizeof(dp))) {
ret = -EFAULT;
goto bail;
}
- } else if (copy_from_user(&odp, data, sizeof(odp))) {
- ret = -EFAULT;
- goto bail;
- }
-
- /*
- * Due to padding/alignment issues (lessened with new struct)
- * the old and new structs are the same length. We need to
- * disambiguate them, which we can do because odp.len has never
- * been less than the total of LRH+BTH+DETH so far, while
- * dp.unit (same offset) unit is unlikely to get that high.
- * Similarly, dp.data, the pointer to user at the same offset
- * as odp.unit, is almost certainly at least one (512byte)page
- * "above" NULL. The if-block below can be omitted if compatibility
- * between a new driver and older diagnostic code is unimportant.
- * compatibility the other direction (new diags, old driver) is
- * handled in the diagnostic code, with a warning.
- */
- if (dp.unit >= 20 && dp.data < 512) {
- /* very probable version mismatch. Fix it up */
- memcpy(&odp, &dp, sizeof(odp));
- /* We got a legacy dp, copy elements to dp */
+ } else if (count == sizeof(odp)) {
+ if (copy_from_user(&odp, data, sizeof(odp))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ dp.len = odp.len;
dp.unit = odp.unit;
dp.data = odp.data;
- dp.len = odp.len;
- dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */
+ dp.pbc_wd = 0;
+ } else {
+ ret = -EINVAL;
+ goto bail;
}
/* send count must be an exact number of dwords */
@@ -378,7 +361,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
goto bail;
}
- clen = dp.len >> 2;
+ plen = dp.len >> 2;
dd = ipath_lookup(dp.unit);
if (!dd || !(dd->ipath_flags & IPATH_PRESENT) ||
@@ -421,16 +404,22 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
goto bail;
}
- /* need total length before first word written */
- /* +1 word is for the qword padding */
- plen = sizeof(u32) + dp.len;
-
- if ((plen + 4) > dd->ipath_ibmaxlen) {
+ /*
+ * need total length before first word written, plus 2 Dwords. One Dword
+ * is for padding so we get the full user data when not aligned on
+ * a word boundary. The other Dword is to make sure we have room for the
+ * ICRC which gets tacked on later.
+ */
+ maxlen_reserve = 2 * sizeof(u32);
+ if (dp.len > dd->ipath_ibmaxlen - maxlen_reserve) {
ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n",
- plen - 4, dd->ipath_ibmaxlen);
+ dp.len, dd->ipath_ibmaxlen);
ret = -EINVAL;
- goto bail; /* before writing pbc */
+ goto bail;
}
+
+ plen = sizeof(u32) + dp.len;
+
tmpbuf = vmalloc(plen);
if (!tmpbuf) {
dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, "
@@ -472,11 +461,11 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
*/
if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) {
ipath_flush_wc();
- __iowrite32_copy(piobuf + 2, tmpbuf, clen - 1);
+ __iowrite32_copy(piobuf + 2, tmpbuf, plen - 1);
ipath_flush_wc();
- __raw_writel(tmpbuf[clen - 1], piobuf + clen + 1);
+ __raw_writel(tmpbuf[plen - 1], piobuf + plen + 1);
} else
- __iowrite32_copy(piobuf + 2, tmpbuf, clen);
+ __iowrite32_copy(piobuf + 2, tmpbuf, plen);
ipath_flush_wc();
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index be24ac7..bfca37b 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -41,6 +41,7 @@
#include <linux/vmalloc.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "ipath_kernel.h"
#include "ipath_verbs.h"
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index ee79a2d..736d9ed 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -35,11 +35,13 @@
#include <linux/poll.h>
#include <linux/cdev.h>
#include <linux/swap.h>
+#include <linux/export.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/io.h>
#include <linux/jiffies.h>
+#include <linux/cpu.h>
#include <asm/pgtable.h>
#include "ipath_kernel.h"
@@ -1684,17 +1686,19 @@ static int find_best_unit(struct file *fp,
* information. There may be some issues with dual core numbering
* as well. This needs more work prior to release.
*/
- if (!cpumask_empty(&current->cpus_allowed) &&
- !cpumask_full(&current->cpus_allowed)) {
+ if (!cpumask_empty(tsk_cpus_allowed(current)) &&
+ !cpumask_full(tsk_cpus_allowed(current))) {
int ncpus = num_online_cpus(), curcpu = -1, nset = 0;
- for (i = 0; i < ncpus; i++)
- if (cpumask_test_cpu(i, &current->cpus_allowed)) {
+ get_online_cpus();
+ for_each_online_cpu(i)
+ if (cpumask_test_cpu(i, tsk_cpus_allowed(current))) {
ipath_cdbg(PROC, "%s[%u] affinity set for "
"cpu %d/%d\n", current->comm,
current->pid, i, ncpus);
curcpu = i;
nset++;
}
+ put_online_cpus();
if (curcpu != -1 && nset != ncpus) {
if (npresent) {
prefunit = curcpu / (ncpus / npresent);
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 7c1eebe..49b09c6 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -33,7 +33,9 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
+#include <linux/moduleparam.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/vmalloc.h>
#include "ipath_kernel.h"
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index ceb98ee..43f2d04 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -32,6 +32,7 @@
*/
#include <rdma/ib_smi.h>
+#include <rdma/ib_pma.h>
#include "ipath_kernel.h"
#include "ipath_verbs.h"
@@ -789,151 +790,18 @@ static int recv_subn_set_pkeytable(struct ib_smp *smp,
return recv_subn_get_pkeytable(smp, ibdev);
}
-#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001)
-#define IB_PMA_PORT_SAMPLES_CONTROL cpu_to_be16(0x0010)
-#define IB_PMA_PORT_SAMPLES_RESULT cpu_to_be16(0x0011)
-#define IB_PMA_PORT_COUNTERS cpu_to_be16(0x0012)
-#define IB_PMA_PORT_COUNTERS_EXT cpu_to_be16(0x001D)
-#define IB_PMA_PORT_SAMPLES_RESULT_EXT cpu_to_be16(0x001E)
-
-struct ib_perf {
- u8 base_version;
- u8 mgmt_class;
- u8 class_version;
- u8 method;
- __be16 status;
- __be16 unused;
- __be64 tid;
- __be16 attr_id;
- __be16 resv;
- __be32 attr_mod;
- u8 reserved[40];
- u8 data[192];
-} __attribute__ ((packed));
-
-struct ib_pma_classportinfo {
- u8 base_version;
- u8 class_version;
- __be16 cap_mask;
- u8 reserved[3];
- u8 resp_time_value; /* only lower 5 bits */
- union ib_gid redirect_gid;
- __be32 redirect_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 redirect_lid;
- __be16 redirect_pkey;
- __be32 redirect_qp; /* only lower 24 bits */
- __be32 redirect_qkey;
- union ib_gid trap_gid;
- __be32 trap_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 trap_lid;
- __be16 trap_pkey;
- __be32 trap_hl_qp; /* 8, 24 bits respectively */
- __be32 trap_qkey;
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplescontrol {
- u8 opcode;
- u8 port_select;
- u8 tick;
- u8 counter_width; /* only lower 3 bits */
- __be32 counter_mask0_9; /* 2, 10 * 3, bits */
- __be16 counter_mask10_14; /* 1, 5 * 3, bits */
- u8 sample_mechanisms;
- u8 sample_status; /* only lower 2 bits */
- __be64 option_mask;
- __be64 vendor_mask;
- __be32 sample_start;
- __be32 sample_interval;
- __be16 tag;
- __be16 counter_select[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult_ext {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 extended_width; /* only upper 2 bits */
- __be64 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portcounters {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be16 symbol_error_counter;
- u8 link_error_recovery_counter;
- u8 link_downed_counter;
- __be16 port_rcv_errors;
- __be16 port_rcv_remphys_errors;
- __be16 port_rcv_switch_relay_errors;
- __be16 port_xmit_discards;
- u8 port_xmit_constraint_errors;
- u8 port_rcv_constraint_errors;
- u8 reserved1;
- u8 lli_ebor_errors; /* 4, 4, bits */
- __be16 reserved2;
- __be16 vl15_dropped;
- __be32 port_xmit_data;
- __be32 port_rcv_data;
- __be32 port_xmit_packets;
- __be32 port_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SEL_SYMBOL_ERROR cpu_to_be16(0x0001)
-#define IB_PMA_SEL_LINK_ERROR_RECOVERY cpu_to_be16(0x0002)
-#define IB_PMA_SEL_LINK_DOWNED cpu_to_be16(0x0004)
-#define IB_PMA_SEL_PORT_RCV_ERRORS cpu_to_be16(0x0008)
-#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS cpu_to_be16(0x0010)
-#define IB_PMA_SEL_PORT_XMIT_DISCARDS cpu_to_be16(0x0040)
-#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS cpu_to_be16(0x0200)
-#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS cpu_to_be16(0x0400)
-#define IB_PMA_SEL_PORT_VL15_DROPPED cpu_to_be16(0x0800)
-#define IB_PMA_SEL_PORT_XMIT_DATA cpu_to_be16(0x1000)
-#define IB_PMA_SEL_PORT_RCV_DATA cpu_to_be16(0x2000)
-#define IB_PMA_SEL_PORT_XMIT_PACKETS cpu_to_be16(0x4000)
-#define IB_PMA_SEL_PORT_RCV_PACKETS cpu_to_be16(0x8000)
-
-struct ib_pma_portcounters_ext {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be32 reserved1;
- __be64 port_xmit_data;
- __be64 port_rcv_data;
- __be64 port_xmit_packets;
- __be64 port_rcv_packets;
- __be64 port_unicast_xmit_packets;
- __be64 port_unicast_rcv_packets;
- __be64 port_multicast_xmit_packets;
- __be64 port_multicast_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SELX_PORT_XMIT_DATA cpu_to_be16(0x0001)
-#define IB_PMA_SELX_PORT_RCV_DATA cpu_to_be16(0x0002)
-#define IB_PMA_SELX_PORT_XMIT_PACKETS cpu_to_be16(0x0004)
-#define IB_PMA_SELX_PORT_RCV_PACKETS cpu_to_be16(0x0008)
-#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS cpu_to_be16(0x0010)
-#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS cpu_to_be16(0x0020)
-#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS cpu_to_be16(0x0040)
-#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS cpu_to_be16(0x0080)
-
-static int recv_pma_get_classportinfo(struct ib_perf *pmp)
+static int recv_pma_get_classportinfo(struct ib_pma_mad *pmp)
{
- struct ib_pma_classportinfo *p =
- (struct ib_pma_classportinfo *)pmp->data;
+ struct ib_class_port_info *p =
+ (struct ib_class_port_info *)pmp->data;
memset(pmp->data, 0, sizeof(pmp->data));
- if (pmp->attr_mod != 0)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0)
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
/* Indicate AllPortSelect is valid (only one port anyway) */
- p->cap_mask = cpu_to_be16(1 << 8);
+ p->capability_mask = cpu_to_be16(1 << 8);
p->base_version = 1;
p->class_version = 1;
/*
@@ -957,7 +825,7 @@ static int recv_pma_get_classportinfo(struct ib_perf *pmp)
COUNTER_MASK(1, 3) | \
COUNTER_MASK(1, 4))
-static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+static int recv_pma_get_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -970,9 +838,9 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(port_select != port && port_select != 0xFF))
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
/*
* Ticks are 10x the link transfer period which for 2.5Gbs is 4
* nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample
@@ -1006,7 +874,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+static int recv_pma_set_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -1017,9 +885,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
u8 status;
int ret;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(p->port_select != port && p->port_select != 0xFF)) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -1093,7 +961,7 @@ static u64 get_counter(struct ipath_ibdev *dev,
return ret;
}
-static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+static int recv_pma_get_portsamplesresult(struct ib_pma_mad *pmp,
struct ib_device *ibdev)
{
struct ib_pma_portsamplesresult *p =
@@ -1118,7 +986,7 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+static int recv_pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev)
{
struct ib_pma_portsamplesresult_ext *p =
@@ -1145,7 +1013,7 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_get_portcounters(struct ib_perf *pmp,
+static int recv_pma_get_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1179,9 +1047,9 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(port_select != port && port_select != 0xFF))
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
if (cntrs.symbol_error_counter > 0xFFFFUL)
p->symbol_error_counter = cpu_to_be16(0xFFFF);
@@ -1216,7 +1084,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
cntrs.local_link_integrity_errors = 0xFUL;
if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
cntrs.excessive_buffer_overrun_errors = 0xFUL;
- p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1244,7 +1112,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
+static int recv_pma_get_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters_ext *p =
@@ -1265,9 +1133,9 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(port_select != port && port_select != 0xFF))
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
p->port_xmit_data = cpu_to_be64(swords);
p->port_rcv_data = cpu_to_be64(rwords);
@@ -1281,7 +1149,7 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_set_portcounters(struct ib_perf *pmp,
+static int recv_pma_set_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1344,7 +1212,7 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
return recv_pma_get_portcounters(pmp, ibdev, port);
}
-static int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
+static int recv_pma_set_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1518,19 +1386,19 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
struct ib_mad *in_mad,
struct ib_mad *out_mad)
{
- struct ib_perf *pmp = (struct ib_perf *)out_mad;
+ struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
int ret;
*out_mad = *in_mad;
- if (pmp->class_version != 1) {
- pmp->status |= IB_SMP_UNSUP_VERSION;
+ if (pmp->mad_hdr.class_version != 1) {
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
- switch (pmp->method) {
+ switch (pmp->mad_hdr.method) {
case IB_MGMT_METHOD_GET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_CLASS_PORT_INFO:
ret = recv_pma_get_classportinfo(pmp);
goto bail;
@@ -1554,13 +1422,13 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
port_num);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
case IB_MGMT_METHOD_SET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_PORT_SAMPLES_CONTROL:
ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
port_num);
@@ -1574,7 +1442,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
port_num);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -1588,7 +1456,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
ret = IB_MAD_RESULT_SUCCESS;
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METHOD;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;
ret = reply((struct ib_smp *) pmp);
}
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
index 386e2c7..2627198 100644
--- a/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -107,6 +107,11 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
u32 sz;
struct ib_srq *ret;
+ if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+ ret = ERR_PTR(-ENOSYS);
+ goto done;
+ }
+
if (srq_init_attr->attr.max_wr == 0) {
ret = ERR_PTR(-EINVAL);
goto done;
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index 8991677..75558f3 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -32,6 +32,7 @@
*/
#include <linux/ctype.h>
+#include <linux/stat.h>
#include "ipath_kernel.h"
#include "ipath_verbs.h"
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
index cfed539..dc66c45 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_pages.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -79,7 +79,7 @@ static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
goto bail_release;
}
- current->mm->locked_vm += num_pages;
+ current->mm->pinned_vm += num_pages;
ret = 0;
goto bail;
@@ -178,7 +178,7 @@ void ipath_release_user_pages(struct page **p, size_t num_pages)
__ipath_release_user_pages(p, num_pages, 1);
- current->mm->locked_vm -= num_pages;
+ current->mm->pinned_vm -= num_pages;
up_write(&current->mm->mmap_sem);
}
@@ -195,7 +195,7 @@ static void user_pages_account(struct work_struct *_work)
container_of(_work, struct ipath_user_pages_work, work);
down_write(&work->mm->mmap_sem);
- work->mm->locked_vm -= work->num_pages;
+ work->mm->pinned_vm -= work->num_pages;
up_write(&work->mm->mmap_sem);
mmput(work->mm);
kfree(work);
diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
index f5cb13b..cc04b7b 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
@@ -280,9 +280,7 @@ static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd,
int j;
int ret;
- ret = get_user_pages(current, current->mm, addr,
- npages, 0, 1, pages, NULL);
-
+ ret = get_user_pages_fast(addr, npages, 0, pages);
if (ret != npages) {
int i;
@@ -811,10 +809,7 @@ int ipath_user_sdma_writev(struct ipath_devdata *dd,
while (dim) {
const int mxp = 8;
- down_write(&current->mm->mmap_sem);
ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp);
- up_write(&current->mm->mmap_sem);
-
if (ret <= 0)
goto done_unlock;
else {
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index dd7f26d..439c35d 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -35,6 +35,7 @@
#include <rdma/ib_user_verbs.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/utsname.h>
#include <linux/rculist.h>
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index bd995b2..24ab11a 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -1,6 +1,7 @@
config MLX4_INFINIBAND
tristate "Mellanox ConnectX HCA support"
- depends on NETDEVICES && NETDEV_10000 && PCI
+ depends on NETDEVICES && ETHERNET && PCI
+ select NET_VENDOR_MELLANOX
select MLX4_CORE
---help---
This driver provides low-level InfiniBand support for
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 4b8f9c4..5426ccf 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -169,9 +169,13 @@ int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
enum rdma_link_layer ll;
memset(ah_attr, 0, sizeof *ah_attr);
- ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num);
+ if (ll == IB_LINK_LAYER_ETHERNET)
+ ah_attr->sl = be32_to_cpu(ah->av.eth.sl_tclass_flowlabel) >> 29;
+ else
+ ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+
ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0;
if (ah->av.ib.stat_rate)
ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 44fc310..46b291e 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -35,6 +35,7 @@
#include <linux/mlx4/cmd.h>
#include <linux/gfp.h>
+#include <rdma/ib_pma.h>
#include "mlx4_ib.h"
@@ -43,6 +44,14 @@ enum {
MLX4_IB_VENDOR_CLASS2 = 0xa
};
+/* Counters should be saturate once they reach their maximum value */
+#define ASSIGN_32BIT_COUNTER(counter, value) do {\
+ if ((value) > (u32)~0U) \
+ counter = cpu_to_be32((u32)~0U); \
+ else \
+ counter = cpu_to_be32(value); \
+} while (0)
+
int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
void *in_mad, void *response_mad)
@@ -232,7 +241,7 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma
}
}
-int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad)
{
@@ -299,6 +308,75 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
}
+static void edit_counter(struct mlx4_counter *cnt,
+ struct ib_pma_portcounters *pma_cnt)
+{
+ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data,
+ (be64_to_cpu(cnt->tx_bytes) >> 2));
+ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data,
+ (be64_to_cpu(cnt->rx_bytes) >> 2));
+ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets,
+ be64_to_cpu(cnt->tx_frames));
+ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets,
+ be64_to_cpu(cnt->rx_frames));
+}
+
+static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+ struct ib_wc *in_wc, struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ int err;
+ u32 inmod = dev->counters[port_num - 1] & 0xffff;
+ u8 mode;
+
+ if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
+ return -EINVAL;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev->dev);
+ if (IS_ERR(mailbox))
+ return IB_MAD_RESULT_FAILURE;
+
+ err = mlx4_cmd_box(dev->dev, 0, mailbox->dma, inmod, 0,
+ MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C);
+ if (err)
+ err = IB_MAD_RESULT_FAILURE;
+ else {
+ memset(out_mad->data, 0, sizeof out_mad->data);
+ mode = ((struct mlx4_counter *)mailbox->buf)->counter_mode;
+ switch (mode & 0xf) {
+ case 0:
+ edit_counter(mailbox->buf,
+ (void *)(out_mad->data + 40));
+ err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+ break;
+ default:
+ err = IB_MAD_RESULT_FAILURE;
+ }
+ }
+
+ mlx4_free_cmd_mailbox(dev->dev, mailbox);
+
+ return err;
+}
+
+int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+ struct ib_wc *in_wc, struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ switch (rdma_port_get_link_layer(ibdev, port_num)) {
+ case IB_LINK_LAYER_INFINIBAND:
+ return ib_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
+ case IB_LINK_LAYER_ETHERNET:
+ return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
+ default:
+ return -EINVAL;
+ }
+}
+
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc)
{
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index fbe1973..18836cd 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -128,6 +128,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
(dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
(dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+ if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
+ props->device_cap_flags |= IB_DEVICE_XRC;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
@@ -181,8 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
static int ib_link_query_port(struct ib_device *ibdev, u8 port,
struct ib_port_attr *props,
+ struct ib_smp *in_mad,
struct ib_smp *out_mad)
{
+ int ext_active_speed;
+ int err;
+
props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7;
props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -203,6 +209,39 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
props->max_vl_num = out_mad->data[37] >> 4;
props->init_type_reply = out_mad->data[41] >> 4;
+ /* Check if extended speeds (EDR/FDR/...) are supported */
+ if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
+ ext_active_speed = out_mad->data[62] >> 4;
+
+ switch (ext_active_speed) {
+ case 1:
+ props->active_speed = 16; /* FDR */
+ break;
+ case 2:
+ props->active_speed = 32; /* EDR */
+ break;
+ }
+ }
+
+ /* If reported active speed is QDR, check if is FDR-10 */
+ if (props->active_speed == 4) {
+ if (to_mdev(ibdev)->dev->caps.ext_port_cap[port] &
+ MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
+ init_query_mad(in_mad);
+ in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
+ in_mad->attr_mod = cpu_to_be32(port);
+
+ err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
+ NULL, NULL, in_mad, out_mad);
+ if (err)
+ return err;
+
+ /* Checking LinkSpeedActive for FDR-10 */
+ if (out_mad->data[15] & 0x1)
+ props->active_speed = 8;
+ }
+ }
+
return 0;
}
@@ -227,7 +266,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
props->pkey_tbl_len = 1;
props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46));
props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
- props->max_mtu = IB_MTU_2048;
+ props->max_mtu = IB_MTU_4096;
props->subnet_timeout = 0;
props->max_vl_num = out_mad->data[37] >> 4;
props->init_type_reply = 0;
@@ -274,7 +313,7 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
goto out;
err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
- ib_link_query_port(ibdev, port, props, out_mad) :
+ ib_link_query_port(ibdev, port, props, in_mad, out_mad) :
eth_link_query_port(ibdev, port, props, out_mad);
out:
@@ -566,6 +605,57 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
return 0;
}
+static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct mlx4_ib_xrcd *xrcd;
+ int err;
+
+ if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return ERR_PTR(-ENOSYS);
+
+ xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
+ if (!xrcd)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn);
+ if (err)
+ goto err1;
+
+ xrcd->pd = ib_alloc_pd(ibdev);
+ if (IS_ERR(xrcd->pd)) {
+ err = PTR_ERR(xrcd->pd);
+ goto err2;
+ }
+
+ xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0);
+ if (IS_ERR(xrcd->cq)) {
+ err = PTR_ERR(xrcd->cq);
+ goto err3;
+ }
+
+ return &xrcd->ibxrcd;
+
+err3:
+ ib_dealloc_pd(xrcd->pd);
+err2:
+ mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn);
+err1:
+ kfree(xrcd);
+ return ERR_PTR(err);
+}
+
+static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+ ib_destroy_cq(to_mxrcd(xrcd)->cq);
+ ib_dealloc_pd(to_mxrcd(xrcd)->pd);
+ mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
+ kfree(xrcd);
+
+ return 0;
+}
+
static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
{
struct mlx4_ib_qp *mqp = to_mqp(ibqp);
@@ -816,7 +906,7 @@ static void update_gids_task(struct work_struct *work)
memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
event.device = &gw->dev->ib_dev;
event.element.port_num = gw->port;
- event.event = IB_EVENT_LID_CHANGE;
+ event.event = IB_EVENT_GID_CHANGE;
ib_dispatch_event(&event);
}
@@ -1044,7 +1134,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
(1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
- (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+ (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) |
+ (1ull << IB_USER_VERBS_CMD_OPEN_QP);
ibdev->ib_dev.query_device = mlx4_ib_query_device;
ibdev->ib_dev.query_port = mlx4_ib_query_port;
@@ -1093,16 +1185,34 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr;
ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc;
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
+ ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
+ ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
+ ibdev->ib_dev.uverbs_cmd_mask |=
+ (1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
+ (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
+ }
+
spin_lock_init(&iboe->lock);
if (init_node_data(ibdev))
goto err_map;
+ for (i = 0; i < ibdev->num_ports; ++i) {
+ if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) ==
+ IB_LINK_LAYER_ETHERNET) {
+ err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]);
+ if (err)
+ ibdev->counters[i] = -1;
+ } else
+ ibdev->counters[i] = -1;
+ }
+
spin_lock_init(&ibdev->sm_lock);
mutex_init(&ibdev->cap_mask_mutex);
if (ib_register_device(&ibdev->ib_dev, NULL))
- goto err_map;
+ goto err_counter;
if (mlx4_ib_mad_init(ibdev))
goto err_reg;
@@ -1132,6 +1242,11 @@ err_notif:
err_reg:
ib_unregister_device(&ibdev->ib_dev);
+err_counter:
+ for (; i; --i)
+ if (ibdev->counters[i - 1] != -1)
+ mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+
err_map:
iounmap(ibdev->uar_map);
@@ -1160,7 +1275,9 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
ibdev->iboe.nb.notifier_call = NULL;
}
iounmap(ibdev->uar_map);
-
+ for (p = 0; p < ibdev->num_ports; ++p)
+ if (ibdev->counters[p] != -1)
+ mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
mlx4_CLOSE_PORT(dev, p);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 2a322f2..ed80345 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -56,6 +56,13 @@ struct mlx4_ib_pd {
u32 pdn;
};
+struct mlx4_ib_xrcd {
+ struct ib_xrcd ibxrcd;
+ u32 xrcdn;
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+};
+
struct mlx4_ib_cq_buf {
struct mlx4_buf buf;
struct mlx4_mtt mtt;
@@ -138,6 +145,7 @@ struct mlx4_ib_qp {
struct mlx4_mtt mtt;
int buf_size;
struct mutex mutex;
+ u16 xrcdn;
u32 flags;
u8 port;
u8 alt_port;
@@ -193,6 +201,7 @@ struct mlx4_ib_dev {
struct mutex cap_mask_mutex;
bool ib_active;
struct mlx4_ib_iboe iboe;
+ int counters[MLX4_MAX_PORTS];
};
static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
@@ -210,6 +219,11 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd)
return container_of(ibpd, struct mlx4_ib_pd, ibpd);
}
+static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
+{
+ return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
+}
+
static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
{
return container_of(ibcq, struct mlx4_ib_cq, ibcq);
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 23c04ff..2ed14a7 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -302,15 +302,14 @@ static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
}
static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
- int is_user, int has_srq, struct mlx4_ib_qp *qp)
+ int is_user, int has_rq, struct mlx4_ib_qp *qp)
{
/* Sanity check RQ size before proceeding */
if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_recv_sge > dev->dev->caps.max_rq_sg)
return -EINVAL;
- if (has_srq) {
- /* QPs attached to an SRQ should have no RQ */
+ if (!has_rq) {
if (cap->max_recv_wr)
return -EINVAL;
@@ -463,6 +462,14 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev,
return 0;
}
+static int qp_has_rq(struct ib_qp_init_attr *attr)
+{
+ if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
+ return 0;
+
+ return !attr->srq;
+}
+
static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
@@ -479,7 +486,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
- err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
+ err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, qp_has_rq(init_attr), qp);
if (err)
goto err;
@@ -513,7 +520,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_mtt;
- if (!init_attr->srq) {
+ if (qp_has_rq(init_attr)) {
err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
ucmd.db_addr, &qp->db);
if (err)
@@ -532,7 +539,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err;
- if (!init_attr->srq) {
+ if (qp_has_rq(init_attr)) {
err = mlx4_db_alloc(dev->dev, &qp->db, 0);
if (err)
goto err;
@@ -575,6 +582,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_qpn;
+ if (init_attr->qp_type == IB_QPT_XRC_TGT)
+ qp->mqp.qpn |= (1 << 23);
+
/*
* Hardware wants QPN written in big-endian order (after
* shifting) for send doorbell. Precompute this value to save
@@ -592,9 +602,8 @@ err_qpn:
err_wrid:
if (pd->uobject) {
- if (!init_attr->srq)
- mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
- &qp->db);
+ if (qp_has_rq(init_attr))
+ mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
} else {
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
@@ -610,7 +619,7 @@ err_buf:
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
err_db:
- if (!pd->uobject && !init_attr->srq)
+ if (!pd->uobject && qp_has_rq(init_attr))
mlx4_db_free(dev->dev, &qp->db);
err:
@@ -671,6 +680,33 @@ static void del_gid_entries(struct mlx4_ib_qp *qp)
}
}
+static struct mlx4_ib_pd *get_pd(struct mlx4_ib_qp *qp)
+{
+ if (qp->ibqp.qp_type == IB_QPT_XRC_TGT)
+ return to_mpd(to_mxrcd(qp->ibqp.xrcd)->pd);
+ else
+ return to_mpd(qp->ibqp.pd);
+}
+
+static void get_cqs(struct mlx4_ib_qp *qp,
+ struct mlx4_ib_cq **send_cq, struct mlx4_ib_cq **recv_cq)
+{
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_XRC_TGT:
+ *send_cq = to_mcq(to_mxrcd(qp->ibqp.xrcd)->cq);
+ *recv_cq = *send_cq;
+ break;
+ case IB_QPT_XRC_INI:
+ *send_cq = to_mcq(qp->ibqp.send_cq);
+ *recv_cq = *send_cq;
+ break;
+ default:
+ *send_cq = to_mcq(qp->ibqp.send_cq);
+ *recv_cq = to_mcq(qp->ibqp.recv_cq);
+ break;
+ }
+}
+
static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
int is_user)
{
@@ -682,8 +718,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
qp->mqp.qpn);
- send_cq = to_mcq(qp->ibqp.send_cq);
- recv_cq = to_mcq(qp->ibqp.recv_cq);
+ get_cqs(qp, &send_cq, &recv_cq);
mlx4_ib_lock_cqs(send_cq, recv_cq);
@@ -706,7 +741,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
if (is_user) {
- if (!qp->ibqp.srq)
+ if (qp->rq.wqe_cnt)
mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
&qp->db);
ib_umem_release(qp->umem);
@@ -714,7 +749,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
- if (!qp->ibqp.srq)
+ if (qp->rq.wqe_cnt)
mlx4_db_free(dev->dev, &qp->db);
}
@@ -725,10 +760,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata)
{
- struct mlx4_ib_dev *dev = to_mdev(pd->device);
struct mlx4_ib_sqp *sqp;
struct mlx4_ib_qp *qp;
int err;
+ u16 xrcdn = 0;
/*
* We only support LSO and multicast loopback blocking, and
@@ -739,10 +774,20 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
return ERR_PTR(-EINVAL);
if (init_attr->create_flags &&
- (pd->uobject || init_attr->qp_type != IB_QPT_UD))
+ (udata || init_attr->qp_type != IB_QPT_UD))
return ERR_PTR(-EINVAL);
switch (init_attr->qp_type) {
+ case IB_QPT_XRC_TGT:
+ pd = to_mxrcd(init_attr->xrcd)->pd;
+ xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
+ init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq;
+ /* fall through */
+ case IB_QPT_XRC_INI:
+ if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return ERR_PTR(-ENOSYS);
+ init_attr->recv_cq = init_attr->send_cq;
+ /* fall through */
case IB_QPT_RC:
case IB_QPT_UC:
case IB_QPT_UD:
@@ -751,13 +796,14 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
if (!qp)
return ERR_PTR(-ENOMEM);
- err = create_qp_common(dev, pd, init_attr, udata, 0, qp);
+ err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
if (err) {
kfree(qp);
return ERR_PTR(err);
}
qp->ibqp.qp_num = qp->mqp.qpn;
+ qp->xrcdn = xrcdn;
break;
}
@@ -765,7 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
case IB_QPT_GSI:
{
/* Userspace is not allowed to create special QPs: */
- if (pd->uobject)
+ if (udata)
return ERR_PTR(-EINVAL);
sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
@@ -774,8 +820,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
qp = &sqp->qp;
- err = create_qp_common(dev, pd, init_attr, udata,
- dev->dev->caps.sqp_start +
+ err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
+ to_mdev(pd->device)->dev->caps.sqp_start +
(init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
init_attr->port_num - 1,
qp);
@@ -801,11 +847,13 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
{
struct mlx4_ib_dev *dev = to_mdev(qp->device);
struct mlx4_ib_qp *mqp = to_mqp(qp);
+ struct mlx4_ib_pd *pd;
if (is_qp0(dev, mqp))
mlx4_CLOSE_PORT(dev->dev, mqp->port);
- destroy_qp_common(dev, mqp, !!qp->pd->uobject);
+ pd = get_pd(mqp);
+ destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
if (is_sqp(dev, mqp))
kfree(to_msqp(mqp));
@@ -821,6 +869,8 @@ static int to_mlx4_st(enum ib_qp_type type)
case IB_QPT_RC: return MLX4_QP_ST_RC;
case IB_QPT_UC: return MLX4_QP_ST_UC;
case IB_QPT_UD: return MLX4_QP_ST_UD;
+ case IB_QPT_XRC_INI:
+ case IB_QPT_XRC_TGT: return MLX4_QP_ST_XRC;
case IB_QPT_SMI:
case IB_QPT_GSI: return MLX4_QP_ST_MLX;
default: return -1;
@@ -893,7 +943,6 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
--path->static_rate;
} else
path->static_rate = 0;
- path->counter_index = 0xff;
if (ah->ah_flags & IB_AH_GRH) {
if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
@@ -960,6 +1009,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
{
struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ struct mlx4_ib_pd *pd;
+ struct mlx4_ib_cq *send_cq, *recv_cq;
struct mlx4_qp_context *context;
enum mlx4_qp_optpar optpar = 0;
int sqd_event;
@@ -1015,8 +1066,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
context->sq_size_stride |= qp->sq.wqe_shift - 4;
- if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+ context->xrcd = cpu_to_be32((u32) qp->xrcdn);
+ }
if (qp->ibqp.uobject)
context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -1034,6 +1087,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
}
+ if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
+ if (dev->counters[qp->port - 1] != -1) {
+ context->pri_path.counter_index =
+ dev->counters[qp->port - 1];
+ optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX;
+ } else
+ context->pri_path.counter_index = 0xff;
+ }
+
if (attr_mask & IB_QP_PKEY_INDEX) {
context->pri_path.pkey_index = attr->pkey_index;
optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
@@ -1071,8 +1133,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
}
- context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
- context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+ pd = get_pd(qp);
+ get_cqs(qp, &send_cq, &recv_cq);
+ context->pd = cpu_to_be32(pd->pdn);
+ context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
+ context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
+ context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
/* Set "fast registration enabled" for all kernel QPs */
if (!qp->ibqp.uobject)
@@ -1098,8 +1164,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_SQ_PSN)
context->next_send_psn = cpu_to_be32(attr->sq_psn);
- context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn);
-
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
if (attr->max_dest_rd_atomic)
context->params2 |=
@@ -1122,8 +1186,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_RQ_PSN)
context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
- context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn);
-
if (attr_mask & IB_QP_QKEY) {
context->qkey = cpu_to_be32(attr->qkey);
optpar |= MLX4_QP_OPTPAR_Q_KEY;
@@ -1132,7 +1194,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (ibqp->srq)
context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
- if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
context->db_rec_addr = cpu_to_be64(qp->db.dma);
if (cur_state == IB_QPS_INIT &&
@@ -1217,17 +1279,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
* entries and reinitialize the QP.
*/
if (new_state == IB_QPS_RESET && !ibqp->uobject) {
- mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn,
+ mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
ibqp->srq ? to_msrq(ibqp->srq): NULL);
- if (ibqp->send_cq != ibqp->recv_cq)
- mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL);
+ if (send_cq != recv_cq)
+ mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
qp->rq.head = 0;
qp->rq.tail = 0;
qp->sq.head = 0;
qp->sq.tail = 0;
qp->sq_next_wqe = 0;
- if (!ibqp->srq)
+ if (qp->rq.wqe_cnt)
*qp->db.db = 0;
}
@@ -1301,7 +1363,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
int is_eth;
int is_vlan = 0;
int is_grh;
- u16 vlan = 0;
+ u16 vlan;
send_size = 0;
for (i = 0; i < wr->num_sge; ++i)
@@ -1539,14 +1601,13 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
}
static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
- struct ib_send_wr *wr, __be16 *vlan)
+ struct ib_send_wr *wr)
{
memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
- *vlan = dseg->vlan;
}
static void set_mlx_icrc_seg(void *dseg)
@@ -1609,8 +1670,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
- *lso_hdr_sz = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
- wr->wr.ud.hlen);
+ *lso_hdr_sz = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
*lso_seg_len = halign;
return 0;
}
@@ -1649,7 +1709,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
__be32 uninitialized_var(lso_hdr_sz);
__be32 blh;
int i;
- __be16 vlan = cpu_to_be16(0xffff);
spin_lock_irqsave(&qp->sq.lock, flags);
@@ -1753,7 +1812,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case IB_QPT_UD:
- set_datagram_seg(wqe, wr, &vlan);
+ set_datagram_seg(wqe, wr);
wqe += sizeof (struct mlx4_wqe_datagram_seg);
size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
@@ -1816,11 +1875,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
MLX4_WQE_CTRL_FENCE : 0) | size;
- if (be16_to_cpu(vlan) < 0x1000) {
- ctrl->ins_vlan = 1 << 6;
- ctrl->vlan_tag = vlan;
- }
-
/*
* Make sure descriptor is fully written before
* setting ownership bit (because HW can start
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 818b7ec..39542f3 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -76,6 +76,8 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
struct mlx4_ib_srq *srq;
struct mlx4_wqe_srq_next_seg *next;
struct mlx4_wqe_data_seg *scatter;
+ u32 cqn;
+ u16 xrcdn;
int desc_size;
int buf_size;
int err;
@@ -174,12 +176,18 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
}
}
- err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
+ cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
+ to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
+ xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
+ to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
+ (u16) dev->dev->caps.reserved_xrcds;
+ err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
srq->db.dma, &srq->msrq);
if (err)
goto err_wrid;
srq->msrq.event = mlx4_ib_srq_event;
+ srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
if (pd->uobject)
if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
index e4a08c2..712d2a3 100644
--- a/drivers/infiniband/hw/mthca/mthca_catas.c
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -31,6 +31,7 @@
*/
#include <linux/jiffies.h>
+#include <linux/module.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 7bfa2a1..9d3e5c1 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -36,6 +36,7 @@
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <rdma/ib_mad.h>
@@ -301,6 +302,38 @@ static int mthca_cmd_post(struct mthca_dev *dev,
return err;
}
+
+static int mthca_status_to_errno(u8 status)
+{
+ static const int trans_table[] = {
+ [MTHCA_CMD_STAT_INTERNAL_ERR] = -EIO,
+ [MTHCA_CMD_STAT_BAD_OP] = -EPERM,
+ [MTHCA_CMD_STAT_BAD_PARAM] = -EINVAL,
+ [MTHCA_CMD_STAT_BAD_SYS_STATE] = -ENXIO,
+ [MTHCA_CMD_STAT_BAD_RESOURCE] = -EBADF,
+ [MTHCA_CMD_STAT_RESOURCE_BUSY] = -EBUSY,
+ [MTHCA_CMD_STAT_DDR_MEM_ERR] = -ENOMEM,
+ [MTHCA_CMD_STAT_EXCEED_LIM] = -ENOMEM,
+ [MTHCA_CMD_STAT_BAD_RES_STATE] = -EBADF,
+ [MTHCA_CMD_STAT_BAD_INDEX] = -EBADF,
+ [MTHCA_CMD_STAT_BAD_NVMEM] = -EFAULT,
+ [MTHCA_CMD_STAT_BAD_QPEE_STATE] = -EINVAL,
+ [MTHCA_CMD_STAT_BAD_SEG_PARAM] = -EFAULT,
+ [MTHCA_CMD_STAT_REG_BOUND] = -EBUSY,
+ [MTHCA_CMD_STAT_LAM_NOT_PRE] = -EAGAIN,
+ [MTHCA_CMD_STAT_BAD_PKT] = -EBADMSG,
+ [MTHCA_CMD_STAT_BAD_SIZE] = -ENOMEM,
+ };
+
+ if (status >= ARRAY_SIZE(trans_table) ||
+ (status != MTHCA_CMD_STAT_OK
+ && trans_table[status] == 0))
+ return -EINVAL;
+
+ return trans_table[status];
+}
+
+
static int mthca_cmd_poll(struct mthca_dev *dev,
u64 in_param,
u64 *out_param,
@@ -308,11 +341,11 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
int err = 0;
unsigned long end;
+ u8 status;
down(&dev->cmd.poll_sem);
@@ -341,7 +374,12 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
(u64) be32_to_cpu((__force __be32)
__raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
- *status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+ status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+ if (status) {
+ mthca_dbg(dev, "Command %02x completed with status %02x\n",
+ op, status);
+ err = mthca_status_to_errno(status);
+ }
out:
up(&dev->cmd.poll_sem);
@@ -374,8 +412,7 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
int err = 0;
struct mthca_cmd_context *context;
@@ -407,10 +444,11 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
if (err)
goto out;
- *status = context->status;
- if (*status)
+ if (context->status) {
mthca_dbg(dev, "Command %02x completed with status %02x\n",
- op, *status);
+ op, context->status);
+ err = mthca_status_to_errno(context->status);
+ }
if (out_is_imm)
*out_param = context->out_param;
@@ -432,17 +470,16 @@ static int mthca_cmd_box(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
return mthca_cmd_wait(dev, in_param, &out_param, 0,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
else
return mthca_cmd_poll(dev, in_param, &out_param, 0,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
}
/* Invoke a command with no output parameter */
@@ -451,11 +488,10 @@ static int mthca_cmd(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
return mthca_cmd_box(dev, in_param, 0, in_modifier,
- op_modifier, op, timeout, status);
+ op_modifier, op, timeout);
}
/*
@@ -469,17 +505,16 @@ static int mthca_cmd_imm(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
return mthca_cmd_wait(dev, in_param, out_param, 1,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
else
return mthca_cmd_poll(dev, in_param, out_param, 1,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
}
int mthca_cmd_init(struct mthca_dev *dev)
@@ -596,14 +631,14 @@ void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox)
kfree(mailbox);
}
-int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
+int mthca_SYS_EN(struct mthca_dev *dev)
{
u64 out;
int ret;
- ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D, status);
+ ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D);
- if (*status == MTHCA_CMD_STAT_DDR_MEM_ERR)
+ if (ret == -ENOMEM)
mthca_warn(dev, "SYS_EN DDR error: syn=%x, sock=%d, "
"sladdr=%d, SPD source=%s\n",
(int) (out >> 6) & 0xf, (int) (out >> 4) & 3,
@@ -612,13 +647,13 @@ int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
return ret;
}
-int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status)
+int mthca_SYS_DIS(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C);
}
static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
- u64 virt, u8 *status)
+ u64 virt)
{
struct mthca_mailbox *mailbox;
struct mthca_icm_iter iter;
@@ -666,8 +701,8 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
if (++nent == MTHCA_MAILBOX_SIZE / 16) {
err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
- CMD_TIME_CLASS_B, status);
- if (err || *status)
+ CMD_TIME_CLASS_B);
+ if (err)
goto out;
nent = 0;
}
@@ -676,7 +711,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
if (nent)
err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
switch (op) {
case CMD_MAP_FA:
@@ -696,19 +731,19 @@ out:
return err;
}
-int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
+int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm)
{
- return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1, status);
+ return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1);
}
-int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status)
+int mthca_UNMAP_FA(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B);
}
-int mthca_RUN_FW(struct mthca_dev *dev, u8 *status)
+int mthca_RUN_FW(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A);
}
static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
@@ -737,7 +772,7 @@ static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n");
}
-int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
+int mthca_QUERY_FW(struct mthca_dev *dev)
{
struct mthca_mailbox *mailbox;
u32 *outbox;
@@ -771,7 +806,7 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -843,7 +878,7 @@ out:
return err;
}
-int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
+int mthca_ENABLE_LAM(struct mthca_dev *dev)
{
struct mthca_mailbox *mailbox;
u8 info;
@@ -864,14 +899,11 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM,
- CMD_TIME_CLASS_C, status);
+ CMD_TIME_CLASS_C);
if (err)
goto out;
- if (*status == MTHCA_CMD_STAT_LAM_NOT_PRE)
- goto out;
-
MTHCA_GET(dev->ddr_start, outbox, ENABLE_LAM_START_OFFSET);
MTHCA_GET(dev->ddr_end, outbox, ENABLE_LAM_END_OFFSET);
MTHCA_GET(info, outbox, ENABLE_LAM_INFO_OFFSET);
@@ -896,12 +928,12 @@ out:
return err;
}
-int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status)
+int mthca_DISABLE_LAM(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C);
}
-int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
+int mthca_QUERY_DDR(struct mthca_dev *dev)
{
struct mthca_mailbox *mailbox;
u8 info;
@@ -922,7 +954,7 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -952,7 +984,7 @@ out:
}
int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
- struct mthca_dev_lim *dev_lim, u8 *status)
+ struct mthca_dev_lim *dev_lim)
{
struct mthca_mailbox *mailbox;
u32 *outbox;
@@ -1028,7 +1060,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -1232,7 +1264,7 @@ static void get_board_id(void *vsd, char *board_id)
}
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
- struct mthca_adapter *adapter, u8 *status)
+ struct mthca_adapter *adapter)
{
struct mthca_mailbox *mailbox;
u32 *outbox;
@@ -1251,7 +1283,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -1275,8 +1307,7 @@ out:
}
int mthca_INIT_HCA(struct mthca_dev *dev,
- struct mthca_init_hca_param *param,
- u8 *status)
+ struct mthca_init_hca_param *param)
{
struct mthca_mailbox *mailbox;
__be32 *inbox;
@@ -1393,7 +1424,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET);
}
- err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, CMD_TIME_CLASS_D, status);
+ err = mthca_cmd(dev, mailbox->dma, 0, 0,
+ CMD_INIT_HCA, CMD_TIME_CLASS_D);
mthca_free_mailbox(dev, mailbox);
return err;
@@ -1401,7 +1433,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
int mthca_INIT_IB(struct mthca_dev *dev,
struct mthca_init_ib_param *param,
- int port, u8 *status)
+ int port)
{
struct mthca_mailbox *mailbox;
u32 *inbox;
@@ -1445,24 +1477,24 @@ int mthca_INIT_IB(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET);
err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
mthca_free_mailbox(dev, mailbox);
return err;
}
-int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status)
+int mthca_CLOSE_IB(struct mthca_dev *dev, int port)
{
- return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A, status);
+ return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A);
}
-int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status)
+int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic)
{
- return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C, status);
+ return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C);
}
int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
- int port, u8 *status)
+ int port)
{
struct mthca_mailbox *mailbox;
u32 *inbox;
@@ -1491,18 +1523,18 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET);
err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
mthca_free_mailbox(dev, mailbox);
return err;
}
-int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status)
+int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt)
{
- return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt, status);
+ return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt);
}
-int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
+int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt)
{
struct mthca_mailbox *mailbox;
__be64 *inbox;
@@ -1517,7 +1549,7 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
inbox[1] = cpu_to_be64(dma_addr);
err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
mthca_free_mailbox(dev, mailbox);
@@ -1528,31 +1560,31 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
return err;
}
-int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status)
+int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count)
{
mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n",
page_count, (unsigned long long) virt);
- return mthca_cmd(dev, virt, page_count, 0, CMD_UNMAP_ICM, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, virt, page_count, 0,
+ CMD_UNMAP_ICM, CMD_TIME_CLASS_B);
}
-int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
+int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm)
{
- return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1, status);
+ return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1);
}
-int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status)
+int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B);
}
-int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
- u8 *status)
+int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages)
{
- int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0, 0, CMD_SET_ICM_SIZE,
- CMD_TIME_CLASS_A, status);
+ int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0,
+ 0, CMD_SET_ICM_SIZE, CMD_TIME_CLASS_A);
- if (ret || status)
+ if (ret)
return ret;
/*
@@ -1566,74 +1598,73 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
}
int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status)
+ int mpt_index)
{
return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status)
+ int mpt_index)
{
return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index,
!mailbox, CMD_HW2SW_MPT,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int num_mtt, u8 *status)
+ int num_mtt)
{
return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
-int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status)
+int mthca_SYNC_TPT(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B);
}
int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
- int eq_num, u8 *status)
+ int eq_num)
{
mthca_dbg(dev, "%s mask %016llx for eqn %d\n",
unmap ? "Clearing" : "Setting",
(unsigned long long) event_mask, eq_num);
return mthca_cmd(dev, event_mask, (unmap << 31) | eq_num,
- 0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status);
+ 0, CMD_MAP_EQ, CMD_TIME_CLASS_B);
}
int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status)
+ int eq_num)
{
return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status)
+ int eq_num)
{
return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0,
CMD_HW2SW_EQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status)
+ int cq_num)
{
return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status)
+ int cq_num)
{
return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0,
CMD_HW2SW_CQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
-int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
- u8 *status)
+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size)
{
struct mthca_mailbox *mailbox;
__be32 *inbox;
@@ -1657,44 +1688,43 @@ int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET);
err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
mthca_free_mailbox(dev, mailbox);
return err;
}
int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status)
+ int srq_num)
{
return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status)
+ int srq_num)
{
return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
CMD_HW2SW_SRQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd_box(dev, 0, mailbox->dma, num, 0,
- CMD_QUERY_SRQ, CMD_TIME_CLASS_A, status);
+ CMD_QUERY_SRQ, CMD_TIME_CLASS_A);
}
-int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit)
{
return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
enum ib_qp_state next, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u32 optmask,
- u8 *status)
+ struct mthca_mailbox *mailbox, u32 optmask)
{
static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = {
@@ -1755,7 +1785,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
(!!is_ee << 24) | num, op_mod,
- op[cur][next], CMD_TIME_CLASS_C, status);
+ op[cur][next], CMD_TIME_CLASS_C);
if (0 && mailbox) {
int i;
@@ -1789,21 +1819,20 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
}
err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num,
- op_mod, op[cur][next], CMD_TIME_CLASS_C, status);
+ op_mod, op[cur][next], CMD_TIME_CLASS_C);
}
return err;
}
int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0,
- CMD_QUERY_QPEE, CMD_TIME_CLASS_A, status);
+ CMD_QUERY_QPEE, CMD_TIME_CLASS_A);
}
-int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
- u8 *status)
+int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn)
{
u8 op_mod;
@@ -1825,12 +1854,12 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
}
return mthca_cmd(dev, 0, qpn, op_mod, CMD_CONF_SPECIAL_QP,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
- void *in_mad, void *response_mad, u8 *status)
+ void *in_mad, void *response_mad)
{
struct mthca_mailbox *inmailbox, *outmailbox;
void *inbox;
@@ -1897,9 +1926,9 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma,
in_modifier, op_modifier,
- CMD_MAD_IFC, CMD_TIME_CLASS_C, status);
+ CMD_MAD_IFC, CMD_TIME_CLASS_C);
- if (!err && !*status)
+ if (!err)
memcpy(response_mad, outmailbox->buf, 256);
mthca_free_mailbox(dev, inmailbox);
@@ -1908,33 +1937,33 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
}
int mthca_READ_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd_box(dev, 0, mailbox->dma, index, 0,
- CMD_READ_MGM, CMD_TIME_CLASS_A, status);
+ CMD_READ_MGM, CMD_TIME_CLASS_A);
}
int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- u16 *hash, u8 *status)
+ u16 *hash)
{
u64 imm;
int err;
err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
*hash = imm;
return err;
}
-int mthca_NOP(struct mthca_dev *dev, u8 *status)
+int mthca_NOP(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100), status);
+ return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100));
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index 6efd326..f952244 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -252,79 +252,74 @@ struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
gfp_t gfp_mask);
void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
-int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
-int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status);
-int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
-int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status);
-int mthca_RUN_FW(struct mthca_dev *dev, u8 *status);
-int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status);
-int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status);
-int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status);
-int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status);
+int mthca_SYS_EN(struct mthca_dev *dev);
+int mthca_SYS_DIS(struct mthca_dev *dev);
+int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm);
+int mthca_UNMAP_FA(struct mthca_dev *dev);
+int mthca_RUN_FW(struct mthca_dev *dev);
+int mthca_QUERY_FW(struct mthca_dev *dev);
+int mthca_ENABLE_LAM(struct mthca_dev *dev);
+int mthca_DISABLE_LAM(struct mthca_dev *dev);
+int mthca_QUERY_DDR(struct mthca_dev *dev);
int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
- struct mthca_dev_lim *dev_lim, u8 *status);
+ struct mthca_dev_lim *dev_lim);
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
- struct mthca_adapter *adapter, u8 *status);
+ struct mthca_adapter *adapter);
int mthca_INIT_HCA(struct mthca_dev *dev,
- struct mthca_init_hca_param *param,
- u8 *status);
+ struct mthca_init_hca_param *param);
int mthca_INIT_IB(struct mthca_dev *dev,
struct mthca_init_ib_param *param,
- int port, u8 *status);
-int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status);
-int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status);
+ int port);
+int mthca_CLOSE_IB(struct mthca_dev *dev, int port);
+int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic);
int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
- int port, u8 *status);
-int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status);
-int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status);
-int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status);
-int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
-int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status);
-int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
- u8 *status);
+ int port);
+int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt);
+int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt);
+int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count);
+int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm);
+int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev);
+int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages);
int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status);
+ int mpt_index);
int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status);
+ int mpt_index);
int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int num_mtt, u8 *status);
-int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status);
+ int num_mtt);
+int mthca_SYNC_TPT(struct mthca_dev *dev);
int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
- int eq_num, u8 *status);
+ int eq_num);
int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status);
+ int eq_num);
int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status);
+ int eq_num);
int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status);
+ int cq_num);
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status);
-int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
- u8 *status);
+ int cq_num);
+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size);
int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status);
+ int srq_num);
int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status);
+ int srq_num);
int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
- struct mthca_mailbox *mailbox, u8 *status);
-int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
+ struct mthca_mailbox *mailbox);
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit);
int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
enum ib_qp_state next, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u32 optmask,
- u8 *status);
+ struct mthca_mailbox *mailbox, u32 optmask);
int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u8 *status);
-int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
- u8 *status);
+ struct mthca_mailbox *mailbox);
+int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn);
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
- void *in_mad, void *response_mad, u8 *status);
+ void *in_mad, void *response_mad);
int mthca_READ_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status);
+ struct mthca_mailbox *mailbox);
int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status);
+ struct mthca_mailbox *mailbox);
int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- u16 *hash, u8 *status);
-int mthca_NOP(struct mthca_dev *dev, u8 *status);
+ u16 *hash);
+int mthca_NOP(struct mthca_dev *dev);
#endif /* MTHCA_CMD_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 18ee3fa..53157b8 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -779,7 +779,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
struct mthca_mailbox *mailbox;
struct mthca_cq_context *cq_context;
int err = -ENOMEM;
- u8 status;
cq->ibcq.cqe = nent - 1;
cq->is_kernel = !ctx;
@@ -847,19 +846,12 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context->state_db = cpu_to_be32(cq->arm_db_index);
}
- err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn, &status);
+ err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn);
if (err) {
mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err);
goto err_out_free_mr;
}
- if (status) {
- mthca_warn(dev, "SW2HW_CQ returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_free_mr;
- }
-
spin_lock_irq(&dev->cq_table.lock);
if (mthca_array_set(&dev->cq_table.cq,
cq->cqn & (dev->limits.num_cqs - 1),
@@ -915,7 +907,6 @@ void mthca_free_cq(struct mthca_dev *dev,
{
struct mthca_mailbox *mailbox;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox)) {
@@ -923,11 +914,9 @@ void mthca_free_cq(struct mthca_dev *dev,
return;
}
- err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn, &status);
+ err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn);
if (err)
mthca_warn(dev, "HW2SW_CQ failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
if (0) {
__be32 *ctx = mailbox->buf;
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 76785c6..7c9d35f 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -474,7 +474,6 @@ static int mthca_create_eq(struct mthca_dev *dev,
struct mthca_eq_context *eq_context;
int err = -ENOMEM;
int i;
- u8 status;
eq->dev = dev;
eq->nent = roundup_pow_of_two(max(nent, 2));
@@ -543,15 +542,9 @@ static int mthca_create_eq(struct mthca_dev *dev,
eq_context->intr = intr;
eq_context->lkey = cpu_to_be32(eq->mr.ibmr.lkey);
- err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn, &status);
+ err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn);
if (err) {
- mthca_warn(dev, "SW2HW_EQ failed (%d)\n", err);
- goto err_out_free_mr;
- }
- if (status) {
- mthca_warn(dev, "SW2HW_EQ returned status 0x%02x\n",
- status);
- err = -EINVAL;
+ mthca_warn(dev, "SW2HW_EQ returned %d\n", err);
goto err_out_free_mr;
}
@@ -597,7 +590,6 @@ static void mthca_free_eq(struct mthca_dev *dev,
{
struct mthca_mailbox *mailbox;
int err;
- u8 status;
int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
PAGE_SIZE;
int i;
@@ -606,11 +598,9 @@ static void mthca_free_eq(struct mthca_dev *dev,
if (IS_ERR(mailbox))
return;
- err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn, &status);
+ err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn);
if (err)
- mthca_warn(dev, "HW2SW_EQ failed (%d)\n", err);
- if (status)
- mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n", status);
+ mthca_warn(dev, "HW2SW_EQ returned %d\n", err);
dev->eq_table.arm_mask &= ~eq->eqn_mask;
@@ -738,7 +728,6 @@ static void mthca_unmap_eq_regs(struct mthca_dev *dev)
int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
{
int ret;
- u8 status;
/*
* We assume that mapping one page is enough for the whole EQ
@@ -757,9 +746,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
return -ENOMEM;
}
- ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt, &status);
- if (!ret && status)
- ret = -EINVAL;
+ ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt);
if (ret) {
pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
@@ -771,9 +758,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
void mthca_unmap_eq_icm(struct mthca_dev *dev)
{
- u8 status;
-
- mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1, &status);
+ mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1);
pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
__free_page(dev->eq_table.icm_page);
@@ -782,7 +767,6 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev)
int mthca_init_eq_table(struct mthca_dev *dev)
{
int err;
- u8 status;
u8 intr;
int i;
@@ -864,22 +848,16 @@ int mthca_init_eq_table(struct mthca_dev *dev)
}
err = mthca_MAP_EQ(dev, async_mask(dev),
- 0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, &status);
+ 0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
if (err)
mthca_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, err);
- if (status)
- mthca_warn(dev, "MAP_EQ for async EQ %d returned status 0x%02x\n",
- dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, status);
err = mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
- 0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
+ 0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
if (err)
mthca_warn(dev, "MAP_EQ for cmd EQ %d failed (%d)\n",
dev->eq_table.eq[MTHCA_EQ_CMD].eqn, err);
- if (status)
- mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n",
- dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status);
for (i = 0; i < MTHCA_NUM_EQ; ++i)
if (mthca_is_memfree(dev))
@@ -909,15 +887,14 @@ err_out_free:
void mthca_cleanup_eq_table(struct mthca_dev *dev)
{
- u8 status;
int i;
mthca_free_irqs(dev);
mthca_MAP_EQ(dev, async_mask(dev),
- 1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, &status);
+ 1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
- 1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
+ 1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
for (i = 0; i < MTHCA_NUM_EQ; ++i)
mthca_free_eq(dev, &dev->eq_table.eq[i]);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 03a59534..b6f7f45 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -201,7 +201,6 @@ int mthca_process_mad(struct ib_device *ibdev,
struct ib_mad *out_mad)
{
int err;
- u8 status;
u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
u16 prev_lid = 0;
struct ib_port_attr pattr;
@@ -252,17 +251,11 @@ int mthca_process_mad(struct ib_device *ibdev,
err = mthca_MAD_IFC(to_mdev(ibdev),
mad_flags & IB_MAD_IGNORE_MKEY,
mad_flags & IB_MAD_IGNORE_BKEY,
- port_num, in_wc, in_grh, in_mad, out_mad,
- &status);
- if (err) {
- mthca_err(to_mdev(ibdev), "MAD_IFC failed\n");
- return IB_MAD_RESULT_FAILURE;
- }
- if (status == MTHCA_CMD_STAT_BAD_PKT)
+ port_num, in_wc, in_grh, in_mad, out_mad);
+ if (err == -EBADMSG)
return IB_MAD_RESULT_SUCCESS;
- if (status) {
- mthca_err(to_mdev(ibdev), "MAD_IFC returned status %02x\n",
- status);
+ else if (err) {
+ mthca_err(to_mdev(ibdev), "MAD_IFC returned %d\n", err);
return IB_MAD_RESULT_FAILURE;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index f24b79b..aa12a53 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -149,7 +149,7 @@ static int mthca_tune_pci(struct mthca_dev *mdev)
} else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE))
mthca_info(mdev, "No PCI-X capability, not setting RBC.\n");
- if (pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP)) {
+ if (pci_is_pcie(mdev->pdev)) {
if (pcie_set_readrq(mdev->pdev, 4096)) {
mthca_err(mdev, "Couldn't write PCI Express read request, "
"aborting.\n");
@@ -165,19 +165,14 @@ static int mthca_tune_pci(struct mthca_dev *mdev)
static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
{
int err;
- u8 status;
mdev->limits.mtt_seg_size = (1 << log_mtts_per_seg) * 8;
- err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status);
+ err = mthca_QUERY_DEV_LIM(mdev, dev_lim);
if (err) {
- mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_DEV_LIM command returned %d"
+ ", aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "QUERY_DEV_LIM returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
if (dev_lim->min_page_sz > PAGE_SIZE) {
mthca_err(mdev, "HCA minimum page size of %d bigger than "
"kernel PAGE_SIZE of %ld, aborting.\n",
@@ -293,49 +288,32 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
static int mthca_init_tavor(struct mthca_dev *mdev)
{
s64 size;
- u8 status;
int err;
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
- err = mthca_SYS_EN(mdev, &status);
+ err = mthca_SYS_EN(mdev);
if (err) {
- mthca_err(mdev, "SYS_EN command failed, aborting.\n");
+ mthca_err(mdev, "SYS_EN command returned %d, aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "SYS_EN returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
- err = mthca_QUERY_FW(mdev, &status);
+ err = mthca_QUERY_FW(mdev);
if (err) {
- mthca_err(mdev, "QUERY_FW command failed, aborting.\n");
- goto err_disable;
- }
- if (status) {
- mthca_err(mdev, "QUERY_FW returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "QUERY_FW command returned %d,"
+ " aborting.\n", err);
goto err_disable;
}
- err = mthca_QUERY_DDR(mdev, &status);
+ err = mthca_QUERY_DDR(mdev);
if (err) {
- mthca_err(mdev, "QUERY_DDR command failed, aborting.\n");
- goto err_disable;
- }
- if (status) {
- mthca_err(mdev, "QUERY_DDR returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "QUERY_DDR command returned %d, aborting.\n", err);
goto err_disable;
}
err = mthca_dev_lim(mdev, &dev_lim);
if (err) {
- mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_DEV_LIM command returned %d, aborting.\n", err);
goto err_disable;
}
@@ -351,29 +329,22 @@ static int mthca_init_tavor(struct mthca_dev *mdev)
goto err_disable;
}
- err = mthca_INIT_HCA(mdev, &init_hca, &status);
+ err = mthca_INIT_HCA(mdev, &init_hca);
if (err) {
- mthca_err(mdev, "INIT_HCA command failed, aborting.\n");
- goto err_disable;
- }
- if (status) {
- mthca_err(mdev, "INIT_HCA returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
goto err_disable;
}
return 0;
err_disable:
- mthca_SYS_DIS(mdev, &status);
+ mthca_SYS_DIS(mdev);
return err;
}
static int mthca_load_fw(struct mthca_dev *mdev)
{
- u8 status;
int err;
/* FIXME: use HCA-attached memory for FW if present */
@@ -386,31 +357,21 @@ static int mthca_load_fw(struct mthca_dev *mdev)
return -ENOMEM;
}
- err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status);
+ err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm);
if (err) {
- mthca_err(mdev, "MAP_FA command failed, aborting.\n");
- goto err_free;
- }
- if (status) {
- mthca_err(mdev, "MAP_FA returned status 0x%02x, aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "MAP_FA command returned %d, aborting.\n", err);
goto err_free;
}
- err = mthca_RUN_FW(mdev, &status);
+ err = mthca_RUN_FW(mdev);
if (err) {
- mthca_err(mdev, "RUN_FW command failed, aborting.\n");
- goto err_unmap_fa;
- }
- if (status) {
- mthca_err(mdev, "RUN_FW returned status 0x%02x, aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "RUN_FW command returned %d, aborting.\n", err);
goto err_unmap_fa;
}
return 0;
err_unmap_fa:
- mthca_UNMAP_FA(mdev, &status);
+ mthca_UNMAP_FA(mdev);
err_free:
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
@@ -423,19 +384,13 @@ static int mthca_init_icm(struct mthca_dev *mdev,
u64 icm_size)
{
u64 aux_pages;
- u8 status;
int err;
- err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status);
+ err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages);
if (err) {
- mthca_err(mdev, "SET_ICM_SIZE command failed, aborting.\n");
+ mthca_err(mdev, "SET_ICM_SIZE command returned %d, aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "SET_ICM_SIZE returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n",
(unsigned long long) icm_size >> 10,
@@ -448,14 +403,9 @@ static int mthca_init_icm(struct mthca_dev *mdev,
return -ENOMEM;
}
- err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status);
+ err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm);
if (err) {
- mthca_err(mdev, "MAP_ICM_AUX command failed, aborting.\n");
- goto err_free_aux;
- }
- if (status) {
- mthca_err(mdev, "MAP_ICM_AUX returned status 0x%02x, aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "MAP_ICM_AUX returned %d, aborting.\n", err);
goto err_free_aux;
}
@@ -596,7 +546,7 @@ err_unmap_eq:
mthca_unmap_eq_icm(mdev);
err_unmap_aux:
- mthca_UNMAP_ICM_AUX(mdev, &status);
+ mthca_UNMAP_ICM_AUX(mdev);
err_free_aux:
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
@@ -606,7 +556,6 @@ err_free_aux:
static void mthca_free_icms(struct mthca_dev *mdev)
{
- u8 status;
mthca_free_icm_table(mdev, mdev->mcg_table.table);
if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
@@ -619,7 +568,7 @@ static void mthca_free_icms(struct mthca_dev *mdev)
mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
mthca_unmap_eq_icm(mdev);
- mthca_UNMAP_ICM_AUX(mdev, &status);
+ mthca_UNMAP_ICM_AUX(mdev);
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
}
@@ -629,43 +578,32 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
s64 icm_size;
- u8 status;
int err;
- err = mthca_QUERY_FW(mdev, &status);
+ err = mthca_QUERY_FW(mdev);
if (err) {
- mthca_err(mdev, "QUERY_FW command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_FW command failed %d, aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "QUERY_FW returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
- err = mthca_ENABLE_LAM(mdev, &status);
- if (err) {
- mthca_err(mdev, "ENABLE_LAM command failed, aborting.\n");
- return err;
- }
- if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) {
+ err = mthca_ENABLE_LAM(mdev);
+ if (err == -EAGAIN) {
mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n");
mdev->mthca_flags |= MTHCA_FLAG_NO_LAM;
- } else if (status) {
- mthca_err(mdev, "ENABLE_LAM returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
+ } else if (err) {
+ mthca_err(mdev, "ENABLE_LAM returned %d, aborting.\n", err);
+ return err;
}
err = mthca_load_fw(mdev);
if (err) {
- mthca_err(mdev, "Failed to start FW, aborting.\n");
+ mthca_err(mdev, "Loading FW returned %d, aborting.\n", err);
goto err_disable;
}
err = mthca_dev_lim(mdev, &dev_lim);
if (err) {
- mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_DEV_LIM returned %d, aborting.\n", err);
goto err_stop_fw;
}
@@ -685,15 +623,9 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
if (err)
goto err_stop_fw;
- err = mthca_INIT_HCA(mdev, &init_hca, &status);
+ err = mthca_INIT_HCA(mdev, &init_hca);
if (err) {
- mthca_err(mdev, "INIT_HCA command failed, aborting.\n");
- goto err_free_icm;
- }
- if (status) {
- mthca_err(mdev, "INIT_HCA returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
goto err_free_icm;
}
@@ -703,37 +635,34 @@ err_free_icm:
mthca_free_icms(mdev);
err_stop_fw:
- mthca_UNMAP_FA(mdev, &status);
+ mthca_UNMAP_FA(mdev);
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
err_disable:
if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
- mthca_DISABLE_LAM(mdev, &status);
+ mthca_DISABLE_LAM(mdev);
return err;
}
static void mthca_close_hca(struct mthca_dev *mdev)
{
- u8 status;
-
- mthca_CLOSE_HCA(mdev, 0, &status);
+ mthca_CLOSE_HCA(mdev, 0);
if (mthca_is_memfree(mdev)) {
mthca_free_icms(mdev);
- mthca_UNMAP_FA(mdev, &status);
+ mthca_UNMAP_FA(mdev);
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
- mthca_DISABLE_LAM(mdev, &status);
+ mthca_DISABLE_LAM(mdev);
} else
- mthca_SYS_DIS(mdev, &status);
+ mthca_SYS_DIS(mdev);
}
static int mthca_init_hca(struct mthca_dev *mdev)
{
- u8 status;
int err;
struct mthca_adapter adapter;
@@ -745,15 +674,9 @@ static int mthca_init_hca(struct mthca_dev *mdev)
if (err)
return err;
- err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
+ err = mthca_QUERY_ADAPTER(mdev, &adapter);
if (err) {
- mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
- goto err_close;
- }
- if (status) {
- mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "QUERY_ADAPTER command returned %d, aborting.\n", err);
goto err_close;
}
@@ -772,7 +695,6 @@ err_close:
static int mthca_setup_hca(struct mthca_dev *dev)
{
int err;
- u8 status;
MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);
@@ -833,8 +755,8 @@ static int mthca_setup_hca(struct mthca_dev *dev)
goto err_eq_table_free;
}
- err = mthca_NOP(dev, &status);
- if (err || status) {
+ err = mthca_NOP(dev);
+ if (err) {
if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
mthca_warn(dev, "NOP command failed to generate interrupt "
"(IRQ %d).\n",
@@ -1166,7 +1088,6 @@ err_disable_pdev:
static void __mthca_remove_one(struct pci_dev *pdev)
{
struct mthca_dev *mdev = pci_get_drvdata(pdev);
- u8 status;
int p;
if (mdev) {
@@ -1174,7 +1095,7 @@ static void __mthca_remove_one(struct pci_dev *pdev)
mthca_unregister_device(mdev);
for (p = 1; p <= mdev->limits.num_ports; ++p)
- mthca_CLOSE_IB(mdev, p, &status);
+ mthca_CLOSE_IB(mdev, p);
mthca_cleanup_mcg_table(mdev);
mthca_cleanup_av_table(mdev);
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 515790a..6304ae8 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -68,7 +68,6 @@ static int find_mgm(struct mthca_dev *dev,
struct mthca_mgm *mgm = mgm_mailbox->buf;
u8 *mgid;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -77,12 +76,9 @@ static int find_mgm(struct mthca_dev *dev,
memcpy(mgid, gid, 16);
- err = mthca_MGID_HASH(dev, mailbox, hash, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "MGID_HASH returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_MGID_HASH(dev, mailbox, hash);
+ if (err) {
+ mthca_err(dev, "MGID_HASH failed (%d)\n", err);
goto out;
}
@@ -93,12 +89,9 @@ static int find_mgm(struct mthca_dev *dev,
*prev = -1;
do {
- err = mthca_READ_MGM(dev, *index, mgm_mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, *index, mgm_mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM failed (%d)\n", err);
goto out;
}
@@ -134,7 +127,6 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int link = 0;
int i;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -160,12 +152,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- err = mthca_READ_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM failed (%d)\n", err);
goto out;
}
memset(mgm, 0, sizeof *mgm);
@@ -189,11 +178,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
+ err = mthca_WRITE_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM failed %d\n", err);
err = -EINVAL;
goto out;
}
@@ -201,24 +188,17 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (!link)
goto out;
- err = mthca_READ_MGM(dev, prev, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, prev, mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM failed %d\n", err);
goto out;
}
mgm->next_gid_index = cpu_to_be32(index << 6);
- err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, prev, mailbox);
if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
- }
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
out:
if (err && link && index != -1) {
@@ -240,7 +220,6 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int prev, index;
int i, loc;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -275,12 +254,9 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
mgm->qp[loc] = mgm->qp[i - 1];
mgm->qp[i - 1] = 0;
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_WRITE_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
@@ -292,24 +268,17 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
if (amgm_index_to_free) {
err = mthca_READ_MGM(dev, amgm_index_to_free,
- mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n",
- status);
- err = -EINVAL;
+ mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM returned %d\n", err);
goto out;
}
} else
memset(mgm->gid, 0, 16);
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_WRITE_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
if (amgm_index_to_free) {
@@ -319,23 +288,17 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
} else {
/* Remove entry from AMGM */
int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
- err = mthca_READ_MGM(dev, prev, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, prev, mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM returned %d\n", err);
goto out;
}
mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
- err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_WRITE_MGM(dev, prev, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
BUG_ON(index < dev->limits.num_mgms);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 8c2a837..7d2e42d 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -223,7 +223,6 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
{
int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
int ret = 0;
- u8 status;
mutex_lock(&table->mutex);
@@ -240,8 +239,8 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
goto out;
}
- if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
- &status) || status) {
+ if (mthca_MAP_ICM(dev, table->icm[i],
+ table->virt + i * MTHCA_TABLE_CHUNK_SIZE)) {
mthca_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
ret = -ENOMEM;
@@ -258,7 +257,6 @@ out:
void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
{
int i;
- u8 status;
if (!mthca_is_memfree(dev))
return;
@@ -269,8 +267,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
if (--table->icm[i]->refcount == 0) {
mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
- MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
- &status);
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
mthca_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
}
@@ -366,7 +363,6 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
int num_icm;
unsigned chunk_size;
int i;
- u8 status;
obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size;
num_icm = DIV_ROUND_UP(nobj, obj_per_chunk);
@@ -396,8 +392,8 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
__GFP_NOWARN, use_coherent);
if (!table->icm[i])
goto err;
- if (mthca_MAP_ICM(dev, table->icm[i], virt + i * MTHCA_TABLE_CHUNK_SIZE,
- &status) || status) {
+ if (mthca_MAP_ICM(dev, table->icm[i],
+ virt + i * MTHCA_TABLE_CHUNK_SIZE)) {
mthca_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
goto err;
@@ -416,8 +412,7 @@ err:
for (i = 0; i < num_icm; ++i)
if (table->icm[i]) {
mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
- MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
- &status);
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
mthca_free_icm(dev, table->icm[i], table->coherent);
}
@@ -429,13 +424,12 @@ err:
void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table)
{
int i;
- u8 status;
for (i = 0; i < table->num_icm; ++i)
if (table->icm[i]) {
- mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
- MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
- &status);
+ mthca_UNMAP_ICM(dev,
+ table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
mthca_free_icm(dev, table->icm[i], table->coherent);
}
@@ -454,7 +448,6 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
{
struct page *pages[1];
int ret = 0;
- u8 status;
int i;
if (!mthca_is_memfree(dev))
@@ -494,9 +487,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
}
ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
- mthca_uarc_virt(dev, uar, i), &status);
- if (!ret && status)
- ret = -EINVAL;
+ mthca_uarc_virt(dev, uar, i));
if (ret) {
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
put_page(sg_page(&db_tab->page[i].mem));
@@ -557,14 +548,13 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
struct mthca_user_db_table *db_tab)
{
int i;
- u8 status;
if (!mthca_is_memfree(dev))
return;
for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) {
if (db_tab->page[i].uvirt) {
- mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status);
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
put_page(sg_page(&db_tab->page[i].mem));
}
@@ -581,7 +571,6 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
int i, j;
struct mthca_db_page *page;
int ret = 0;
- u8 status;
mutex_lock(&dev->db_tab->mutex);
@@ -644,9 +633,7 @@ alloc:
memset(page->db_rec, 0, MTHCA_ICM_PAGE_SIZE);
ret = mthca_MAP_ICM_page(dev, page->mapping,
- mthca_uarc_virt(dev, &dev->driver_uar, i), &status);
- if (!ret && status)
- ret = -EINVAL;
+ mthca_uarc_virt(dev, &dev->driver_uar, i));
if (ret) {
dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
page->db_rec, page->mapping);
@@ -678,7 +665,6 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
{
int i, j;
struct mthca_db_page *page;
- u8 status;
i = db_index / MTHCA_DB_REC_PER_PAGE;
j = db_index % MTHCA_DB_REC_PER_PAGE;
@@ -694,7 +680,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
i >= dev->db_tab->max_group1 - 1) {
- mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1);
dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
page->db_rec, page->mapping);
@@ -745,7 +731,6 @@ int mthca_init_db_tab(struct mthca_dev *dev)
void mthca_cleanup_db_tab(struct mthca_dev *dev)
{
int i;
- u8 status;
if (!mthca_is_memfree(dev))
return;
@@ -763,7 +748,7 @@ void mthca_cleanup_db_tab(struct mthca_dev *dev)
if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
- mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1);
dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
dev->db_tab->page[i].db_rec,
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 44045c8..ed9a989 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -146,7 +146,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
- buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+ buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
GFP_KERNEL);
if (!buddy->bits || !buddy->num_free)
goto err_out;
@@ -257,7 +257,6 @@ static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
struct mthca_mailbox *mailbox;
__be64 *mtt_entry;
int err = 0;
- u8 status;
int i;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -281,17 +280,11 @@ static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
if (i & 1)
mtt_entry[i + 2] = 0;
- err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1, &status);
+ err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1);
if (err) {
mthca_warn(dev, "WRITE_MTT failed (%d)\n", err);
goto out;
}
- if (status) {
- mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto out;
- }
list_len -= i;
start_index += i;
@@ -441,7 +434,6 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
u32 key;
int i;
int err;
- u8 status;
WARN_ON(buffer_size_shift >= 32);
@@ -497,16 +489,10 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
}
err = mthca_SW2HW_MPT(dev, mailbox,
- key & (dev->limits.num_mpts - 1),
- &status);
+ key & (dev->limits.num_mpts - 1));
if (err) {
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
goto err_out_mailbox;
- } else if (status) {
- mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_mailbox;
}
mthca_free_mailbox(dev, mailbox);
@@ -567,17 +553,12 @@ static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
{
int err;
- u8 status;
err = mthca_HW2SW_MPT(dev, NULL,
key_to_hw_index(dev, mr->ibmr.lkey) &
- (dev->limits.num_mpts - 1),
- &status);
+ (dev->limits.num_mpts - 1));
if (err)
mthca_warn(dev, "HW2SW_MPT failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_MPT returned status 0x%02x\n",
- status);
mthca_free_region(dev, mr->ibmr.lkey);
mthca_free_mtt(dev, mr->mtt);
@@ -590,7 +571,6 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
struct mthca_mailbox *mailbox;
u64 mtt_seg;
u32 key, idx;
- u8 status;
int list_len = mr->attr.max_pages;
int err = -ENOMEM;
int i;
@@ -672,18 +652,11 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
}
err = mthca_SW2HW_MPT(dev, mailbox,
- key & (dev->limits.num_mpts - 1),
- &status);
+ key & (dev->limits.num_mpts - 1));
if (err) {
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
goto err_out_mailbox_free;
}
- if (status) {
- mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_mailbox_free;
- }
mthca_free_mailbox(dev, mailbox);
return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 1e0b4b6..42dde06 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -40,7 +40,9 @@
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/mm.h>
+#include <linux/export.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -63,8 +65,6 @@ static int mthca_query_device(struct ib_device *ibdev,
int err = -ENOMEM;
struct mthca_dev *mdev = to_mdev(ibdev);
- u8 status;
-
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
@@ -78,14 +78,9 @@ static int mthca_query_device(struct ib_device *ibdev,
in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
err = mthca_MAD_IFC(mdev, 1, 1,
- 1, NULL, NULL, in_mad, out_mad,
- &status);
+ 1, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
props->device_cap_flags = mdev->device_cap_flags;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
@@ -141,7 +136,6 @@ static int mthca_query_port(struct ib_device *ibdev,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -155,14 +149,9 @@ static int mthca_query_port(struct ib_device *ibdev,
in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7;
@@ -214,7 +203,6 @@ static int mthca_modify_port(struct ib_device *ibdev,
struct mthca_set_ib_param set_ib;
struct ib_port_attr attr;
int err;
- u8 status;
if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
return -ERESTARTSYS;
@@ -229,14 +217,9 @@ static int mthca_modify_port(struct ib_device *ibdev,
set_ib.cap_mask = (attr.port_cap_flags | props->set_port_cap_mask) &
~props->clr_port_cap_mask;
- err = mthca_SET_IB(to_mdev(ibdev), &set_ib, port, &status);
+ err = mthca_SET_IB(to_mdev(ibdev), &set_ib, port);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
-
out:
mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex);
return err;
@@ -248,7 +231,6 @@ static int mthca_query_pkey(struct ib_device *ibdev,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -260,14 +242,9 @@ static int mthca_query_pkey(struct ib_device *ibdev,
in_mad->attr_mod = cpu_to_be32(index / 32);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
*pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]);
@@ -283,7 +260,6 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -295,14 +271,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
memcpy(gid->raw, out_mad->data + 8, 8);
@@ -311,14 +282,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
in_mad->attr_mod = cpu_to_be32(index / 8);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
@@ -474,6 +440,9 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
struct mthca_srq *srq;
int err;
+ if (init_attr->srq_type != IB_SRQT_BASIC)
+ return ERR_PTR(-ENOSYS);
+
srq = kmalloc(sizeof *srq, GFP_KERNEL);
if (!srq)
return ERR_PTR(-ENOMEM);
@@ -726,6 +695,7 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
if (context && ib_copy_to_udata(udata, &cq->cqn, sizeof (__u32))) {
mthca_free_cq(to_mdev(ibdev), cq);
+ err = -EFAULT;
goto err_free;
}
@@ -800,7 +770,6 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
struct mthca_cq *cq = to_mcq(ibcq);
struct mthca_resize_cq ucmd;
u32 lkey;
- u8 status;
int ret;
if (entries < 1 || entries > dev->limits.max_cqes)
@@ -827,9 +796,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
lkey = ucmd.lkey;
}
- ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status);
- if (status)
- ret = -EINVAL;
+ ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries));
if (ret) {
if (cq->resize_buf) {
@@ -1161,7 +1128,6 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
{
struct ib_fmr *fmr;
int err;
- u8 status;
struct mthca_dev *mdev = NULL;
list_for_each_entry(fmr, fmr_list, list) {
@@ -1182,12 +1148,8 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
list_for_each_entry(fmr, fmr_list, list)
mthca_tavor_fmr_unmap(mdev, to_mfmr(fmr));
- err = mthca_SYNC_TPT(mdev, &status);
- if (err)
- return err;
- if (status)
- return -EINVAL;
- return 0;
+ err = mthca_SYNC_TPT(mdev);
+ return err;
}
static ssize_t show_rev(struct device *device, struct device_attribute *attr,
@@ -1253,7 +1215,6 @@ static int mthca_init_node_data(struct mthca_dev *dev)
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -1264,28 +1225,18 @@ static int mthca_init_node_data(struct mthca_dev *dev)
in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
err = mthca_MAD_IFC(dev, 1, 1,
- 1, NULL, NULL, in_mad, out_mad,
- &status);
+ 1, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
memcpy(dev->ib_dev.node_desc, out_mad->data, 64);
in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
err = mthca_MAD_IFC(dev, 1, 1,
- 1, NULL, NULL, in_mad, out_mad,
- &status);
+ 1, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
if (mthca_is_memfree(dev))
dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index a34c9d3..9601049 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -308,7 +308,6 @@ static void store_attrs(struct mthca_sqp *sqp, const struct ib_qp_attr *attr,
static void init_port(struct mthca_dev *dev, int port)
{
int err;
- u8 status;
struct mthca_init_ib_param param;
memset(&param, 0, sizeof param);
@@ -319,11 +318,9 @@ static void init_port(struct mthca_dev *dev, int port)
param.gid_cap = dev->limits.gid_table_len;
param.pkey_cap = dev->limits.pkey_table_len;
- err = mthca_INIT_IB(dev, &param, port, &status);
+ err = mthca_INIT_IB(dev, &param, port);
if (err)
mthca_warn(dev, "INIT_IB failed, return code %d.\n", err);
- if (status)
- mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
}
static __be32 get_hw_access_flags(struct mthca_qp *qp, const struct ib_qp_attr *attr,
@@ -433,7 +430,6 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
struct mthca_qp_param *qp_param;
struct mthca_qp_context *context;
int mthca_state;
- u8 status;
mutex_lock(&qp->mutex);
@@ -448,12 +444,9 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
goto out;
}
- err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox, &status);
- if (err)
- goto out_mailbox;
- if (status) {
- mthca_warn(dev, "QUERY_QP returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox);
+ if (err) {
+ mthca_warn(dev, "QUERY_QP failed (%d)\n", err);
goto out_mailbox;
}
@@ -555,7 +548,6 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
struct mthca_qp_param *qp_param;
struct mthca_qp_context *qp_context;
u32 sqd_event = 0;
- u8 status;
int err = -EINVAL;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -781,13 +773,10 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
sqd_event = 1 << 31;
err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
- mailbox, sqd_event, &status);
- if (err)
- goto out_mailbox;
- if (status) {
- mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
- cur_state, new_state, status);
- err = -EINVAL;
+ mailbox, sqd_event);
+ if (err) {
+ mthca_warn(dev, "modify QP %d->%d returned %d.\n",
+ cur_state, new_state, err);
goto out_mailbox;
}
@@ -817,7 +806,7 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
cur_state != IB_QPS_ERR &&
(new_state == IB_QPS_RESET ||
new_state == IB_QPS_ERR))
- mthca_CLOSE_IB(dev, qp->port, &status);
+ mthca_CLOSE_IB(dev, qp->port);
}
/*
@@ -1429,7 +1418,6 @@ static inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
void mthca_free_qp(struct mthca_dev *dev,
struct mthca_qp *qp)
{
- u8 status;
struct mthca_cq *send_cq;
struct mthca_cq *recv_cq;
@@ -1454,7 +1442,7 @@ void mthca_free_qp(struct mthca_dev *dev,
if (qp->state != IB_QPS_RESET)
mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
- NULL, 0, &status);
+ NULL, 0);
/*
* If this is a userspace QP, the buffers, MR, CQs and so on
@@ -2263,7 +2251,6 @@ void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
int mthca_init_qp_table(struct mthca_dev *dev)
{
int err;
- u8 status;
int i;
spin_lock_init(&dev->qp_table.lock);
@@ -2290,15 +2277,10 @@ int mthca_init_qp_table(struct mthca_dev *dev)
for (i = 0; i < 2; ++i) {
err = mthca_CONF_SPECIAL_QP(dev, i ? IB_QPT_GSI : IB_QPT_SMI,
- dev->qp_table.sqp_start + i * 2,
- &status);
- if (err)
- goto err_out;
- if (status) {
+ dev->qp_table.sqp_start + i * 2);
+ if (err) {
mthca_warn(dev, "CONF_SPECIAL_QP returned "
- "status %02x, aborting.\n",
- status);
- err = -EINVAL;
+ "%d, aborting.\n", err);
goto err_out;
}
}
@@ -2306,7 +2288,7 @@ int mthca_init_qp_table(struct mthca_dev *dev)
err_out:
for (i = 0; i < 2; ++i)
- mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+ mthca_CONF_SPECIAL_QP(dev, i, 0);
mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
mthca_alloc_cleanup(&dev->qp_table.alloc);
@@ -2317,10 +2299,9 @@ int mthca_init_qp_table(struct mthca_dev *dev)
void mthca_cleanup_qp_table(struct mthca_dev *dev)
{
int i;
- u8 status;
for (i = 0; i < 2; ++i)
- mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+ mthca_CONF_SPECIAL_QP(dev, i, 0);
mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
mthca_alloc_cleanup(&dev->qp_table.alloc);
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 2a13a16..4fa3534 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -113,7 +113,7 @@ int mthca_reset(struct mthca_dev *mdev)
}
hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
- hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);
+ hca_pcie_cap = pci_pcie_cap(mdev->pdev);
if (bridge) {
bridge_header = kmalloc(256, GFP_KERNEL);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 4fabe62..d22f970 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -200,7 +200,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
struct ib_srq_attr *attr, struct mthca_srq *srq)
{
struct mthca_mailbox *mailbox;
- u8 status;
int ds;
int err;
@@ -266,18 +265,12 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
else
mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf);
- err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status);
+ err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn);
if (err) {
mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err);
goto err_out_free_buf;
}
- if (status) {
- mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_free_buf;
- }
spin_lock_irq(&dev->srq_table.lock);
if (mthca_array_set(&dev->srq_table.srq,
@@ -299,11 +292,9 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
return 0;
err_out_free_srq:
- err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn);
if (err)
mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
err_out_free_buf:
if (!pd->ibpd.uobject)
@@ -340,7 +331,6 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
{
struct mthca_mailbox *mailbox;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox)) {
@@ -348,11 +338,9 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
return;
}
- err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn);
if (err)
mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
spin_lock_irq(&dev->srq_table.lock);
mthca_array_clear(&dev->srq_table.srq,
@@ -378,8 +366,7 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
{
struct mthca_dev *dev = to_mdev(ibsrq->device);
struct mthca_srq *srq = to_msrq(ibsrq);
- int ret;
- u8 status;
+ int ret = 0;
/* We don't support resizing SRQs (yet?) */
if (attr_mask & IB_SRQ_MAX_WR)
@@ -391,16 +378,11 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
return -EINVAL;
mutex_lock(&srq->mutex);
- ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+ ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit);
mutex_unlock(&srq->mutex);
-
- if (ret)
- return ret;
- if (status)
- return -EINVAL;
}
- return 0;
+ return ret;
}
int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
@@ -410,14 +392,13 @@ int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
struct mthca_mailbox *mailbox;
struct mthca_arbel_srq_context *arbel_ctx;
struct mthca_tavor_srq_context *tavor_ctx;
- u8 status;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
- err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox, &status);
+ err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox);
if (err)
goto out;
diff --git a/drivers/infiniband/hw/nes/Makefile b/drivers/infiniband/hw/nes/Makefile
index 3514851..97820c2 100644
--- a/drivers/infiniband/hw/nes/Makefile
+++ b/drivers/infiniband/hw/nes/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
-iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
+iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 2d668c6..5965b3d 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -84,7 +84,7 @@ module_param(send_first, int, 0644);
MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
-unsigned int nes_drv_opt = 0;
+unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
module_param(nes_drv_opt, int, 0644);
MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
@@ -130,9 +130,6 @@ static struct notifier_block nes_net_notifier = {
.notifier_call = nes_net_event
};
-
-
-
/**
* nes_inetaddr_event
*/
@@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
}
if (atomic_dec_and_test(&nesqp->refcount)) {
+ if (nesqp->pau_mode)
+ nes_destroy_pau_qp(nesdev, nesqp);
+
/* Destroy the QP */
cqp_request = nes_get_cqp_request(nesdev);
if (cqp_request == NULL) {
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 6e30273..3ade373 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -102,6 +102,7 @@
#define NES_DRV_OPT_NO_INLINE_DATA 0x00000080
#define NES_DRV_OPT_DISABLE_INT_MOD 0x00000100
#define NES_DRV_OPT_DISABLE_VIRT_WQ 0x00000200
+#define NES_DRV_OPT_ENABLE_PAU 0x00000400
#define NES_AEQ_EVENT_TIMEOUT 2500
#define NES_DISCONNECT_EVENT_TIMEOUT 2000
@@ -128,6 +129,7 @@
#define NES_DBG_IW_RX 0x00020000
#define NES_DBG_IW_TX 0x00040000
#define NES_DBG_SHUTDOWN 0x00080000
+#define NES_DBG_PAU 0x00100000
#define NES_DBG_RSVD1 0x10000000
#define NES_DBG_RSVD2 0x20000000
#define NES_DBG_RSVD3 0x40000000
@@ -162,6 +164,7 @@ do { \
#include "nes_context.h"
#include "nes_user.h"
#include "nes_cm.h"
+#include "nes_mgt.h"
extern int max_mtu;
#define max_frame_len (max_mtu+ETH_HLEN)
@@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created;
extern atomic_t cm_nodes_destroyed;
extern atomic_t cm_accel_dropped_pkts;
extern atomic_t cm_resets_recvd;
+extern atomic_t pau_qps_created;
+extern atomic_t pau_qps_destroyed;
extern u32 int_mod_timer_init;
extern u32 int_mod_cq_depth_256;
@@ -273,6 +278,14 @@ struct nes_device {
u8 link_recheck;
};
+/* Receive skb private area - must fit in skb->cb area */
+struct nes_rskb_cb {
+ u64 busaddr;
+ u32 maplen;
+ u32 seqnum;
+ u8 *data_start;
+ struct nes_qp *nesqp;
+};
static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
{
@@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value)
static inline void
nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
{
- set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
- (u64)((unsigned long) &nesdev->cqp));
+ cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX] = 0;
+ cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index a1f74f6..0a52d72 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -34,7 +34,7 @@
#define TCPOPT_TIMESTAMP 8
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
@@ -77,26 +77,19 @@ atomic_t cm_nodes_destroyed;
atomic_t cm_accel_dropped_pkts;
atomic_t cm_resets_recvd;
-static inline int mini_cm_accelerated(struct nes_cm_core *,
- struct nes_cm_node *);
-static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
- struct nes_vnic *, struct nes_cm_info *);
+static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
+static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *);
static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
-static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
- struct nes_vnic *, u16, void *, struct nes_cm_info *);
+static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *);
static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
-static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
-static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
-static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
- struct sk_buff *);
+static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
static int mini_cm_dealloc_core(struct nes_cm_core *);
static int mini_cm_get(struct nes_cm_core *);
static int mini_cm_set(struct nes_cm_core *, u32, u32);
-static void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
- void *, u32, void *, u32, u8);
+static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8);
static int add_ref_cm_node(struct nes_cm_node *);
static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
@@ -111,16 +104,14 @@ static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
static int send_reset(struct nes_cm_node *, struct sk_buff *);
static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
-static void process_packet(struct nes_cm_node *, struct sk_buff *,
- struct nes_cm_core *);
+static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
static void cleanup_retrans_entry(struct nes_cm_node *);
static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
static void free_retrans_entry(struct nes_cm_node *cm_node);
-static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb, int optionsize, int passive);
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive);
/* CM event handler functions */
static void cm_event_connected(struct nes_cm_event *);
@@ -130,6 +121,12 @@ static void cm_event_mpa_req(struct nes_cm_event *);
static void cm_event_mpa_reject(struct nes_cm_event *);
static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
+/* MPA build functions */
+static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8);
+static void build_mpa_v2(struct nes_cm_node *, void *, u8);
+static void build_mpa_v1(struct nes_cm_node *, void *, u8);
+static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **);
+
static void print_core(struct nes_cm_core *core);
/* External CM API Interface */
@@ -159,12 +156,21 @@ atomic_t cm_connecteds;
atomic_t cm_connect_reqs;
atomic_t cm_rejects;
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node)
+{
+ return add_ref_cm_node(cm_node);
+}
+
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node)
+{
+ return rem_ref_cm_node(cm_node->cm_core, cm_node);
+}
/**
* create_event
*/
-static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
- enum nes_cm_event_type type)
+static struct nes_cm_event *create_event(struct nes_cm_node * cm_node,
+ enum nes_cm_event_type type)
{
struct nes_cm_event *event;
@@ -186,10 +192,10 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
event->cm_info.cm_id = cm_node->cm_id;
nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
- "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
- cm_node, event, type, event->cm_info.loc_addr,
- event->cm_info.loc_port, event->cm_info.rem_addr,
- event->cm_info.rem_port);
+ "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
+ cm_node, event, type, event->cm_info.loc_addr,
+ event->cm_info.loc_port, event->cm_info.rem_addr,
+ event->cm_info.rem_port);
nes_cm_post_event(event);
return event;
@@ -201,14 +207,19 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
*/
static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
{
+ u8 start_addr = 0;
+ u8 *start_ptr = &start_addr;
+ u8 **start_buff = &start_ptr;
+ u16 buff_len = 0;
+
if (!skb) {
nes_debug(NES_DBG_CM, "skb set to NULL\n");
return -1;
}
/* send an MPA Request frame */
- form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
- cm_node->mpa_frame_size, SET_ACK);
+ cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST);
+ form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK);
return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
}
@@ -217,7 +228,11 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
static int send_mpa_reject(struct nes_cm_node *cm_node)
{
- struct sk_buff *skb = NULL;
+ struct sk_buff *skb = NULL;
+ u8 start_addr = 0;
+ u8 *start_ptr = &start_addr;
+ u8 **start_buff = &start_ptr;
+ u16 buff_len = 0;
skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
@@ -226,8 +241,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
}
/* send an MPA reject frame */
- form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
- cm_node->mpa_frame_size, SET_ACK | SET_FIN);
+ cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+ form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
cm_node->state = NES_CM_STATE_FIN_WAIT1;
return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
@@ -239,24 +254,31 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
* IETF MPA frame
*/
static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
- u32 len)
+ u32 len)
{
- struct ietf_mpa_frame *mpa_frame;
+ struct ietf_mpa_v1 *mpa_frame;
+ struct ietf_mpa_v2 *mpa_v2_frame;
+ struct ietf_rtr_msg *rtr_msg;
+ int mpa_hdr_len;
+ int priv_data_len;
*type = NES_MPA_REQUEST_ACCEPT;
/* assume req frame is in tcp data payload */
- if (len < sizeof(struct ietf_mpa_frame)) {
+ if (len < sizeof(struct ietf_mpa_v1)) {
nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
return -EINVAL;
}
- mpa_frame = (struct ietf_mpa_frame *)buffer;
- cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
+ /* points to the beginning of the frame, which could be MPA V1 or V2 */
+ mpa_frame = (struct ietf_mpa_v1 *)buffer;
+ mpa_hdr_len = sizeof(struct ietf_mpa_v1);
+ priv_data_len = ntohs(mpa_frame->priv_data_len);
+
/* make sure mpa private data len is less than 512 bytes */
- if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) {
+ if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) {
nes_debug(NES_DBG_CM, "The received Length of Private"
- " Data field exceeds 512 octets\n");
+ " Data field exceeds 512 octets\n");
return -EINVAL;
}
/*
@@ -264,11 +286,22 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
* received MPA version and MPA key information
*
*/
- if (mpa_frame->rev != mpa_version) {
+ if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) {
+ nes_debug(NES_DBG_CM, "The received mpa version"
+ " is not supported\n");
+ return -EINVAL;
+ }
+ /*
+ * backwards compatibility only
+ */
+ if (mpa_frame->rev > cm_node->mpa_frame_rev) {
nes_debug(NES_DBG_CM, "The received mpa version"
- " can not be interoperated\n");
+ " can not be interoperated\n");
return -EINVAL;
+ } else {
+ cm_node->mpa_frame_rev = mpa_frame->rev;
}
+
if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {
nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
@@ -281,25 +314,75 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
}
}
- if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
+
+ if (priv_data_len + mpa_hdr_len != len) {
nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
- " complete (%x + %x != %x)\n",
- cm_node->mpa_frame_size,
- (u32)sizeof(struct ietf_mpa_frame), len);
+ " complete (%x + %x != %x)\n",
+ priv_data_len, mpa_hdr_len, len);
return -EINVAL;
}
/* make sure it does not exceed the max size */
if (len > MAX_CM_BUFFER) {
nes_debug(NES_DBG_CM, "The received ietf buffer was too large"
- " (%x + %x != %x)\n",
- cm_node->mpa_frame_size,
- (u32)sizeof(struct ietf_mpa_frame), len);
+ " (%x + %x != %x)\n",
+ priv_data_len, mpa_hdr_len, len);
return -EINVAL;
}
+ cm_node->mpa_frame_size = priv_data_len;
+
+ switch (mpa_frame->rev) {
+ case IETF_MPA_V2: {
+ u16 ird_size;
+ u16 ord_size;
+ mpa_v2_frame = (struct ietf_mpa_v2 *)buffer;
+ mpa_hdr_len += IETF_RTR_MSG_SIZE;
+ cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE;
+ rtr_msg = &mpa_v2_frame->rtr_msg;
+
+ /* parse rtr message */
+ rtr_msg->ctrl_ird = ntohs(rtr_msg->ctrl_ird);
+ rtr_msg->ctrl_ord = ntohs(rtr_msg->ctrl_ord);
+ ird_size = rtr_msg->ctrl_ird & IETF_NO_IRD_ORD;
+ ord_size = rtr_msg->ctrl_ord & IETF_NO_IRD_ORD;
+
+ if (!(rtr_msg->ctrl_ird & IETF_PEER_TO_PEER)) {
+ /* send reset */
+ return -EINVAL;
+ }
+
+ if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
+ /* responder */
+ if (cm_node->ord_size > ird_size)
+ cm_node->ord_size = ird_size;
+ } else {
+ /* initiator */
+ if (cm_node->ord_size > ird_size)
+ cm_node->ord_size = ird_size;
+
+ if (cm_node->ird_size < ord_size) {
+ /* no resources available */
+ /* send terminate message */
+ return -EINVAL;
+ }
+ }
+
+ if (rtr_msg->ctrl_ord & IETF_RDMA0_READ) {
+ cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+ } else if (rtr_msg->ctrl_ord & IETF_RDMA0_WRITE) {
+ cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO;
+ } else { /* Not supported RDMA0 operation */
+ return -EINVAL;
+ }
+ break;
+ }
+ case IETF_MPA_V1:
+ default:
+ break;
+ }
+
/* copy entire MPA frame to our cm_node's frame */
- memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
- cm_node->mpa_frame_size);
+ memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size);
if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)
*type = NES_MPA_REQUEST_REJECT;
@@ -312,8 +395,8 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
* node info to build.
*/
static void form_cm_frame(struct sk_buff *skb,
- struct nes_cm_node *cm_node, void *options, u32 optionsize,
- void *data, u32 datasize, u8 flags)
+ struct nes_cm_node *cm_node, void *options, u32 optionsize,
+ void *data, u32 datasize, u8 flags)
{
struct tcphdr *tcph;
struct iphdr *iph;
@@ -322,14 +405,14 @@ static void form_cm_frame(struct sk_buff *skb,
u16 packetsize = sizeof(*iph);
packetsize += sizeof(*tcph);
- packetsize += optionsize + datasize;
+ packetsize += optionsize + datasize;
+ skb_trim(skb, 0);
memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph));
- skb->len = 0;
buf = skb_put(skb, packetsize + ETH_HLEN);
- ethh = (struct ethhdr *) buf;
+ ethh = (struct ethhdr *)buf;
buf += ETH_HLEN;
iph = (struct iphdr *)buf;
@@ -337,7 +420,7 @@ static void form_cm_frame(struct sk_buff *skb,
tcph = (struct tcphdr *)buf;
skb_reset_mac_header(skb);
skb_set_network_header(skb, ETH_HLEN);
- skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph));
+ skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph));
buf += sizeof(*tcph);
skb->ip_summed = CHECKSUM_PARTIAL;
@@ -350,14 +433,14 @@ static void form_cm_frame(struct sk_buff *skb,
ethh->h_proto = htons(0x0800);
iph->version = IPVERSION;
- iph->ihl = 5; /* 5 * 4Byte words, IP headr len */
+ iph->ihl = 5; /* 5 * 4Byte words, IP headr len */
iph->tos = 0;
iph->tot_len = htons(packetsize);
iph->id = htons(++cm_node->tcp_cntxt.loc_id);
iph->frag_off = htons(0x4000);
iph->ttl = 0x40;
- iph->protocol = 0x06; /* IPPROTO_TCP */
+ iph->protocol = 0x06; /* IPPROTO_TCP */
iph->saddr = htonl(cm_node->loc_addr);
iph->daddr = htonl(cm_node->rem_addr);
@@ -370,14 +453,16 @@ static void form_cm_frame(struct sk_buff *skb,
cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;
tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);
tcph->ack = 1;
- } else
+ } else {
tcph->ack_seq = 0;
+ }
if (flags & SET_SYN) {
cm_node->tcp_cntxt.loc_seq_num++;
tcph->syn = 1;
- } else
+ } else {
cm_node->tcp_cntxt.loc_seq_num += datasize;
+ }
if (flags & SET_FIN) {
cm_node->tcp_cntxt.loc_seq_num++;
@@ -398,10 +483,8 @@ static void form_cm_frame(struct sk_buff *skb,
skb_shinfo(skb)->nr_frags = 0;
cm_packets_created++;
-
}
-
/**
* print_core - dump a cm core
*/
@@ -413,7 +496,7 @@ static void print_core(struct nes_cm_core *core)
return;
nes_debug(NES_DBG_CM, "---------------------------------------------\n");
- nes_debug(NES_DBG_CM, "State : %u \n", core->state);
+ nes_debug(NES_DBG_CM, "State : %u \n", core->state);
nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt));
nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt));
@@ -423,6 +506,147 @@ static void print_core(struct nes_cm_core *core)
nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");
}
+/**
+ * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame
+ */
+static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff,
+ u16 *buff_len, u8 *pci_mem, u8 mpa_key)
+{
+ int ret = 0;
+
+ *start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0];
+
+ switch (cm_node->mpa_frame_rev) {
+ case IETF_MPA_V1:
+ *start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg);
+ *buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size;
+ build_mpa_v1(cm_node, *start_buff, mpa_key);
+ break;
+ case IETF_MPA_V2:
+ *buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size;
+ build_mpa_v2(cm_node, *start_buff, mpa_key);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+/**
+ * build_mpa_v2 - build a MPA V2 frame
+ */
+static void build_mpa_v2(struct nes_cm_node *cm_node,
+ void *start_addr, u8 mpa_key)
+{
+ struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr;
+ struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg;
+
+ /* initialize the upper 5 bytes of the frame */
+ build_mpa_v1(cm_node, start_addr, mpa_key);
+ mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */
+ mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE);
+
+ /* initialize RTR msg */
+ rtr_msg->ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ?
+ IETF_NO_IRD_ORD : cm_node->ird_size;
+ rtr_msg->ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ?
+ IETF_NO_IRD_ORD : cm_node->ord_size;
+
+ rtr_msg->ctrl_ird |= IETF_PEER_TO_PEER;
+ rtr_msg->ctrl_ird |= IETF_FLPDU_ZERO_LEN;
+
+ switch (mpa_key) {
+ case MPA_KEY_REQUEST:
+ rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+ rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+ break;
+ case MPA_KEY_REPLY:
+ switch (cm_node->send_rdma0_op) {
+ case SEND_RDMA_WRITE_ZERO:
+ rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+ break;
+ case SEND_RDMA_READ_ZERO:
+ rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+ break;
+ }
+ }
+ rtr_msg->ctrl_ird = htons(rtr_msg->ctrl_ird);
+ rtr_msg->ctrl_ord = htons(rtr_msg->ctrl_ord);
+}
+
+/**
+ * build_mpa_v1 - build a MPA V1 frame
+ */
+static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key)
+{
+ struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr;
+
+ switch (mpa_key) {
+ case MPA_KEY_REQUEST:
+ memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
+ break;
+ case MPA_KEY_REPLY:
+ memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
+ break;
+ }
+ mpa_frame->flags = IETF_MPA_FLAGS_CRC;
+ mpa_frame->rev = cm_node->mpa_frame_rev;
+ mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size);
+}
+
+static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr)
+{
+ u64 u64temp;
+ struct nes_qp *nesqp = *nesqp_addr;
+ struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0];
+
+ u64temp = (unsigned long)nesqp;
+ u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
+ set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
+
+ wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
+
+ switch (cm_node->send_rdma0_op) {
+ case SEND_RDMA_WRITE_ZERO:
+ nes_debug(NES_DBG_CM, "Sending first write.\n");
+ wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+ cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
+ wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+ break;
+
+ case SEND_RDMA_READ_ZERO:
+ default:
+ if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
+ printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
+ __func__, __LINE__, cm_node->send_rdma0_op);
+ WARN_ON(1);
+ }
+ nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
+ wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+ cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1;
+ break;
+ }
+
+ if (nesqp->sq_kmapped) {
+ nesqp->sq_kmapped = 0;
+ kunmap(nesqp->page);
+ }
+
+ /*use the reserved spot on the WQ for the extra first WQE*/
+ nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+ NES_QPCONTEXT_ORDIRD_WRPDU |
+ NES_QPCONTEXT_ORDIRD_ALSMM));
+ nesqp->skip_lsmm = 1;
+ nesqp->hwqp.sq_tail = 0;
+}
/**
* schedule_nes_timer
@@ -430,10 +654,10 @@ static void print_core(struct nes_cm_core *core)
* rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);
*/
int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
- enum nes_timer_type type, int send_retrans,
- int close_when_complete)
+ enum nes_timer_type type, int send_retrans,
+ int close_when_complete)
{
- unsigned long flags;
+ unsigned long flags;
struct nes_cm_core *cm_core = cm_node->cm_core;
struct nes_timer_entry *new_send;
int ret = 0;
@@ -454,7 +678,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
new_send->close_when_complete = close_when_complete;
if (type == NES_TIMER_TYPE_CLOSE) {
- new_send->timetosend += (HZ/10);
+ new_send->timetosend += (HZ / 10);
if (cm_node->recv_entry) {
kfree(new_send);
WARN_ON(1);
@@ -475,7 +699,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
if (ret != NETDEV_TX_OK) {
nes_debug(NES_DBG_CM, "Error sending packet %p "
- "(jiffies = %lu)\n", new_send, jiffies);
+ "(jiffies = %lu)\n", new_send, jiffies);
new_send->timetosend = jiffies;
ret = NETDEV_TX_OK;
} else {
@@ -504,6 +728,7 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node)
struct iw_cm_id *cm_id = cm_node->cm_id;
enum nes_cm_node_state state = cm_node->state;
cm_node->state = NES_CM_STATE_CLOSED;
+
switch (state) {
case NES_CM_STATE_SYN_RCVD:
case NES_CM_STATE_CLOSING:
@@ -536,10 +761,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
spin_lock_irqsave(&nesqp->lock, qplockflags);
if (nesqp->cm_id) {
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
- "refcount = %d: HIT A "
- "NES_TIMER_TYPE_CLOSE with something "
- "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
- atomic_read(&nesqp->refcount));
+ "refcount = %d: HIT A "
+ "NES_TIMER_TYPE_CLOSE with something "
+ "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+ atomic_read(&nesqp->refcount));
nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
nesqp->ibqp_state = IB_QPS_ERR;
@@ -548,10 +773,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
} else {
spin_unlock_irqrestore(&nesqp->lock, qplockflags);
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
- "refcount = %d: HIT A "
- "NES_TIMER_TYPE_CLOSE with nothing "
- "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
- atomic_read(&nesqp->refcount));
+ "refcount = %d: HIT A "
+ "NES_TIMER_TYPE_CLOSE with nothing "
+ "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+ atomic_read(&nesqp->refcount));
}
} else if (rem_node) {
/* TIME_WAIT state */
@@ -580,11 +805,12 @@ static void nes_cm_timer_tick(unsigned long pass)
int ret = NETDEV_TX_OK;
struct list_head timer_list;
+
INIT_LIST_HEAD(&timer_list);
spin_lock_irqsave(&cm_core->ht_lock, flags);
list_for_each_safe(list_node, list_core_temp,
- &cm_core->connected_nodes) {
+ &cm_core->connected_nodes) {
cm_node = container_of(list_node, struct nes_cm_node, list);
if ((cm_node->recv_entry) || (cm_node->send_entry)) {
add_ref_cm_node(cm_node);
@@ -595,18 +821,19 @@ static void nes_cm_timer_tick(unsigned long pass)
list_for_each_safe(list_node, list_core_temp, &timer_list) {
cm_node = container_of(list_node, struct nes_cm_node,
- timer_entry);
+ timer_entry);
recv_entry = cm_node->recv_entry;
if (recv_entry) {
if (time_after(recv_entry->timetosend, jiffies)) {
if (nexttimeout > recv_entry->timetosend ||
- !settimer) {
+ !settimer) {
nexttimeout = recv_entry->timetosend;
settimer = 1;
}
- } else
+ } else {
handle_recv_entry(cm_node, 1);
+ }
}
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
@@ -617,8 +844,8 @@ static void nes_cm_timer_tick(unsigned long pass)
if (time_after(send_entry->timetosend, jiffies)) {
if (cm_node->state != NES_CM_STATE_TSA) {
if ((nexttimeout >
- send_entry->timetosend) ||
- !settimer) {
+ send_entry->timetosend) ||
+ !settimer) {
nexttimeout =
send_entry->timetosend;
settimer = 1;
@@ -630,13 +857,13 @@ static void nes_cm_timer_tick(unsigned long pass)
}
if ((cm_node->state == NES_CM_STATE_TSA) ||
- (cm_node->state == NES_CM_STATE_CLOSED)) {
+ (cm_node->state == NES_CM_STATE_CLOSED)) {
free_retrans_entry(cm_node);
break;
}
if (!send_entry->retranscount ||
- !send_entry->retrycount) {
+ !send_entry->retrycount) {
cm_packets_dropped++;
free_retrans_entry(cm_node);
@@ -645,28 +872,28 @@ static void nes_cm_timer_tick(unsigned long pass)
nes_retrans_expired(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
spin_lock_irqsave(&cm_node->retrans_list_lock,
- flags);
+ flags);
break;
}
atomic_inc(&send_entry->skb->users);
cm_packets_retrans++;
nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
- "for node %p, jiffies = %lu, time to send = "
- "%lu, retranscount = %u, send_entry->seq_num = "
- "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
- "0x%08X\n", send_entry, cm_node, jiffies,
- send_entry->timetosend,
- send_entry->retranscount,
- send_entry->seq_num,
- cm_node->tcp_cntxt.rem_ack_num);
+ "for node %p, jiffies = %lu, time to send = "
+ "%lu, retranscount = %u, send_entry->seq_num = "
+ "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
+ "0x%08X\n", send_entry, cm_node, jiffies,
+ send_entry->timetosend,
+ send_entry->retranscount,
+ send_entry->seq_num,
+ cm_node->tcp_cntxt.rem_ack_num);
spin_unlock_irqrestore(&cm_node->retrans_list_lock,
- flags);
+ flags);
ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
if (ret != NETDEV_TX_OK) {
nes_debug(NES_DBG_CM, "rexmit failed for "
- "node=%p\n", cm_node);
+ "node=%p\n", cm_node);
cm_packets_bounced++;
send_entry->retrycount--;
nexttimeout = jiffies + NES_SHORT_TIME;
@@ -676,18 +903,18 @@ static void nes_cm_timer_tick(unsigned long pass)
cm_packets_sent++;
}
nes_debug(NES_DBG_CM, "Packet Sent: retrans count = "
- "%u, retry count = %u.\n",
- send_entry->retranscount,
- send_entry->retrycount);
+ "%u, retry count = %u.\n",
+ send_entry->retranscount,
+ send_entry->retrycount);
if (send_entry->send_retrans) {
send_entry->retranscount--;
timetosend = (NES_RETRY_TIMEOUT <<
- (NES_DEFAULT_RETRANS - send_entry->retranscount));
+ (NES_DEFAULT_RETRANS - send_entry->retranscount));
send_entry->timetosend = jiffies +
- min(timetosend, NES_MAX_TIMEOUT);
+ min(timetosend, NES_MAX_TIMEOUT);
if (nexttimeout > send_entry->timetosend ||
- !settimer) {
+ !settimer) {
nexttimeout = send_entry->timetosend;
settimer = 1;
}
@@ -696,11 +923,11 @@ static void nes_cm_timer_tick(unsigned long pass)
close_when_complete =
send_entry->close_when_complete;
nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n",
- cm_node, cm_node->state);
+ cm_node, cm_node->state);
free_retrans_entry(cm_node);
if (close_when_complete)
rem_ref_cm_node(cm_node->cm_core,
- cm_node);
+ cm_node);
}
} while (0);
@@ -710,7 +937,7 @@ static void nes_cm_timer_tick(unsigned long pass)
if (settimer) {
if (!timer_pending(&cm_core->tcp_timer)) {
- cm_core->tcp_timer.expires = nexttimeout;
+ cm_core->tcp_timer.expires = nexttimeout;
add_timer(&cm_core->tcp_timer);
}
}
@@ -721,13 +948,13 @@ static void nes_cm_timer_tick(unsigned long pass)
* send_syn
*/
static int send_syn(struct nes_cm_node *cm_node, u32 sendack,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
int ret;
int flags = SET_SYN;
char optionsbuffer[sizeof(struct option_mss) +
- sizeof(struct option_windowscale) + sizeof(struct option_base) +
- TCP_OPTIONS_PADDING];
+ sizeof(struct option_windowscale) + sizeof(struct option_base) +
+ TCP_OPTIONS_PADDING];
int optionssize = 0;
/* Sending MSS option */
@@ -854,7 +1081,7 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
* find_node - find a cm node that matches the reference cm node
*/
static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
- u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
+ u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
{
unsigned long flags;
struct list_head *hte;
@@ -868,12 +1095,12 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
list_for_each_entry(cm_node, hte, list) {
/* compare quad, return node handle if a match */
nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
- cm_node->loc_addr, cm_node->loc_port,
- loc_addr, loc_port,
- cm_node->rem_addr, cm_node->rem_port,
- rem_addr, rem_port);
+ cm_node->loc_addr, cm_node->loc_port,
+ loc_addr, loc_port,
+ cm_node->rem_addr, cm_node->rem_port,
+ rem_addr, rem_port);
if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) &&
- (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
+ (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
add_ref_cm_node(cm_node);
spin_unlock_irqrestore(&cm_core->ht_lock, flags);
return cm_node;
@@ -890,7 +1117,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
* find_listener - find a cm node listening on this addr-port pair
*/
static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
- nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+ nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
{
unsigned long flags;
struct nes_cm_listener *listen_node;
@@ -900,9 +1127,9 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
/* compare node pair, return node handle if a match */
if (((listen_node->loc_addr == dst_addr) ||
- listen_node->loc_addr == 0x00000000) &&
- (listen_node->loc_port == dst_port) &&
- (listener_state & listen_node->listener_state)) {
+ listen_node->loc_addr == 0x00000000) &&
+ (listen_node->loc_port == dst_port) &&
+ (listener_state & listen_node->listener_state)) {
atomic_inc(&listen_node->ref_count);
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
return listen_node;
@@ -927,7 +1154,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
return -EINVAL;
nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
- cm_node);
+ cm_node);
spin_lock_irqsave(&cm_core->ht_lock, flags);
@@ -946,7 +1173,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
* mini_cm_dec_refcnt_listen
*/
static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
- struct nes_cm_listener *listener, int free_hanging_nodes)
+ struct nes_cm_listener *listener, int free_hanging_nodes)
{
int ret = -EINVAL;
int err = 0;
@@ -957,8 +1184,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
struct list_head reset_list;
nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
- "refcnt=%d\n", listener, free_hanging_nodes,
- atomic_read(&listener->ref_count));
+ "refcnt=%d\n", listener, free_hanging_nodes,
+ atomic_read(&listener->ref_count));
/* free non-accelerated child nodes for this listener */
INIT_LIST_HEAD(&reset_list);
if (free_hanging_nodes) {
@@ -966,7 +1193,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
list_for_each_safe(list_pos, list_temp,
&g_cm_core->connected_nodes) {
cm_node = container_of(list_pos, struct nes_cm_node,
- list);
+ list);
if ((cm_node->listener == listener) &&
(!cm_node->accelerated)) {
add_ref_cm_node(cm_node);
@@ -978,7 +1205,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
list_for_each_safe(list_pos, list_temp, &reset_list) {
cm_node = container_of(list_pos, struct nes_cm_node,
- reset_entry);
+ reset_entry);
{
struct nes_cm_node *loopback = cm_node->loopbackpartner;
enum nes_cm_node_state old_state;
@@ -990,7 +1217,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
err = send_reset(cm_node, NULL);
if (err) {
cm_node->state =
- NES_CM_STATE_CLOSED;
+ NES_CM_STATE_CLOSED;
WARN_ON(1);
} else {
old_state = cm_node->state;
@@ -1035,10 +1262,9 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
- if (listener->nesvnic) {
+ if (listener->nesvnic)
nes_manage_apbvt(listener->nesvnic, listener->loc_port,
- PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
- }
+ PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener);
@@ -1052,8 +1278,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
if (listener) {
if (atomic_read(&listener->pend_accepts_cnt) > 0)
nes_debug(NES_DBG_CM, "destroying listener (%p)"
- " with non-zero pending accepts=%u\n",
- listener, atomic_read(&listener->pend_accepts_cnt));
+ " with non-zero pending accepts=%u\n",
+ listener, atomic_read(&listener->pend_accepts_cnt));
}
return ret;
@@ -1064,7 +1290,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
* mini_cm_del_listen
*/
static int mini_cm_del_listen(struct nes_cm_core *cm_core,
- struct nes_cm_listener *listener)
+ struct nes_cm_listener *listener)
{
listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;
listener->cm_id = NULL; /* going to be destroyed pretty soon */
@@ -1076,9 +1302,10 @@ static int mini_cm_del_listen(struct nes_cm_core *cm_core,
* mini_cm_accelerated
*/
static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
- struct nes_cm_node *cm_node)
+ struct nes_cm_node *cm_node)
{
u32 was_timer_set;
+
cm_node->accelerated = 1;
if (cm_node->accept_pend) {
@@ -1112,7 +1339,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
if (IS_ERR(rt)) {
printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
- __func__, dst_ip);
+ __func__, dst_ip);
return rc;
}
@@ -1130,7 +1357,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
if (arpindex >= 0) {
if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
- neigh->ha, ETH_ALEN)){
+ neigh->ha, ETH_ALEN)) {
/* Mac address same as in nes_arp_table */
neigh_release(neigh);
ip_rt_put(rt);
@@ -1138,8 +1365,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
}
nes_manage_arp_cache(nesvnic->netdev,
- nesadapter->arp_table[arpindex].mac_addr,
- dst_ip, NES_ARP_DELETE);
+ nesadapter->arp_table[arpindex].mac_addr,
+ dst_ip, NES_ARP_DELETE);
}
nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
@@ -1163,8 +1390,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
* make_cm_node - create a new instance of a cm node
*/
static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
- struct nes_cm_listener *listener)
+ struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
+ struct nes_cm_listener *listener)
{
struct nes_cm_node *cm_node;
struct timespec ts;
@@ -1183,7 +1410,12 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
cm_node->rem_addr = cm_info->rem_addr;
cm_node->loc_port = cm_info->loc_port;
cm_node->rem_port = cm_info->rem_port;
- cm_node->send_write0 = send_first;
+
+ cm_node->mpa_frame_rev = mpa_version;
+ cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+ cm_node->ird_size = IETF_NO_IRD_ORD;
+ cm_node->ord_size = IETF_NO_IRD_ORD;
+
nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
&cm_node->loc_addr, cm_node->loc_port,
&cm_node->rem_addr, cm_node->rem_port);
@@ -1193,7 +1425,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener,
- cm_node->cm_id);
+ cm_node->cm_id);
spin_lock_init(&cm_node->retrans_list_lock);
@@ -1204,11 +1436,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >>
- NES_CM_DEFAULT_RCV_WND_SCALE;
+ NES_CM_DEFAULT_RCV_WND_SCALE;
ts = current_kernel_time();
cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);
cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) -
- sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
+ sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
cm_node->tcp_cntxt.rcv_nxt = 0;
/* get a unique session ID , add thread_id to an upcounter to handle race */
atomic_inc(&cm_core->node_cnt);
@@ -1224,12 +1456,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
cm_node->loopbackpartner = NULL;
/* get the mac addr for the remote node */
- if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
+ if (ipv4_is_loopback(htonl(cm_node->rem_addr))) {
arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
- else {
+ } else {
oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
-
}
if (arpindex < 0) {
kfree(cm_node);
@@ -1262,7 +1493,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node)
* rem_ref_cm_node - destroy an instance of a cm node
*/
static int rem_ref_cm_node(struct nes_cm_core *cm_core,
- struct nes_cm_node *cm_node)
+ struct nes_cm_node *cm_node)
{
unsigned long flags;
struct nes_qp *nesqp;
@@ -1293,9 +1524,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
} else {
if (cm_node->apbvt_set && cm_node->nesvnic) {
nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
- PCI_FUNC(
- cm_node->nesvnic->nesdev->pcidev->devfn),
- NES_MANAGE_APBVT_DEL);
+ PCI_FUNC(
+ cm_node->nesvnic->nesdev->pcidev->devfn),
+ NES_MANAGE_APBVT_DEL);
}
}
@@ -1316,7 +1547,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
* process_options
*/
static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
- u32 optionsize, u32 syn_packet)
+ u32 optionsize, u32 syn_packet)
{
u32 tmp;
u32 offset = 0;
@@ -1334,15 +1565,15 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
continue;
case OPTION_NUMBER_MSS:
nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d "
- "Size: %d\n", __func__,
- all_options->as_mss.length, offset, optionsize);
+ "Size: %d\n", __func__,
+ all_options->as_mss.length, offset, optionsize);
got_mss_option = 1;
if (all_options->as_mss.length != 4) {
return 1;
} else {
tmp = ntohs(all_options->as_mss.mss);
if (tmp > 0 && tmp <
- cm_node->tcp_cntxt.mss)
+ cm_node->tcp_cntxt.mss)
cm_node->tcp_cntxt.mss = tmp;
}
break;
@@ -1350,12 +1581,9 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
cm_node->tcp_cntxt.snd_wscale =
all_options->as_windowscale.shiftcount;
break;
- case OPTION_NUMBER_WRITE0:
- cm_node->send_write0 = 1;
- break;
default:
nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
- all_options->as_base.optionnum);
+ all_options->as_base.optionnum);
break;
}
offset += all_options->as_base.length;
@@ -1374,8 +1602,8 @@ static void drop_packet(struct sk_buff *skb)
static void handle_fin_pkt(struct nes_cm_node *cm_node)
{
nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
- "refcnt=%d\n", cm_node, cm_node->state,
- atomic_read(&cm_node->ref_count));
+ "refcnt=%d\n", cm_node, cm_node->state,
+ atomic_read(&cm_node->ref_count));
switch (cm_node->state) {
case NES_CM_STATE_SYN_RCVD:
case NES_CM_STATE_SYN_SENT:
@@ -1441,7 +1669,20 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
"listener=%p state=%d\n", __func__, __LINE__, cm_node,
cm_node->listener, cm_node->state);
- active_open_err(cm_node, skb, reset);
+ switch (cm_node->mpa_frame_rev) {
+ case IETF_MPA_V2:
+ cm_node->mpa_frame_rev = IETF_MPA_V1;
+ /* send a syn and goto syn sent state */
+ cm_node->state = NES_CM_STATE_SYN_SENT;
+ if (send_syn(cm_node, 0, NULL)) {
+ active_open_err(cm_node, skb, reset);
+ }
+ break;
+ case IETF_MPA_V1:
+ default:
+ active_open_err(cm_node, skb, reset);
+ break;
+ }
break;
case NES_CM_STATE_MPAREQ_RCVD:
atomic_inc(&cm_node->passive_state);
@@ -1477,21 +1718,21 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
{
-
- int ret = 0;
+ int ret = 0;
int datasize = skb->len;
u8 *dataloc = skb->data;
enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN;
- u32 res_type;
+ u32 res_type;
+
ret = parse_mpa(cm_node, dataloc, &res_type, datasize);
if (ret) {
nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {
nes_debug(NES_DBG_CM, "%s[%u] create abort for "
- "cm_node=%p listener=%p state=%d\n", __func__,
- __LINE__, cm_node, cm_node->listener,
- cm_node->state);
+ "cm_node=%p listener=%p state=%d\n", __func__,
+ __LINE__, cm_node, cm_node->listener,
+ cm_node->state);
active_open_err(cm_node, skb, 1);
} else {
passive_open_err(cm_node, skb, 1);
@@ -1501,16 +1742,15 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
switch (cm_node->state) {
case NES_CM_STATE_ESTABLISHED:
- if (res_type == NES_MPA_REQUEST_REJECT) {
+ if (res_type == NES_MPA_REQUEST_REJECT)
/*BIG problem as we are receiving the MPA.. So should
- * not be REJECT.. This is Passive Open.. We can
- * only receive it Reject for Active Open...*/
+ * not be REJECT.. This is Passive Open.. We can
+ * only receive it Reject for Active Open...*/
WARN_ON(1);
- }
cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
type = NES_CM_EVENT_MPA_REQ;
atomic_set(&cm_node->passive_state,
- NES_PASSIVE_STATE_INDICATED);
+ NES_PASSIVE_STATE_INDICATED);
break;
case NES_CM_STATE_MPAREQ_SENT:
cleanup_retrans_entry(cm_node);
@@ -1537,8 +1777,8 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
case NES_CM_STATE_SYN_SENT:
case NES_CM_STATE_MPAREQ_SENT:
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
- "listener=%p state=%d\n", __func__, __LINE__, cm_node,
- cm_node->listener, cm_node->state);
+ "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+ cm_node->listener, cm_node->state);
active_open_err(cm_node, skb, 1);
break;
case NES_CM_STATE_ESTABLISHED:
@@ -1552,11 +1792,11 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
}
static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
int err;
- err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1;
+ err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1;
if (err)
active_open_err(cm_node, skb, 1);
@@ -1564,7 +1804,7 @@ static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
}
static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
int err = 0;
u32 seq;
@@ -1572,21 +1812,22 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;
u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;
u32 rcv_wnd;
+
seq = ntohl(tcph->seq);
ack_seq = ntohl(tcph->ack_seq);
rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
if (ack_seq != loc_seq_num)
err = 1;
- else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd)))
+ else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd)))
err = 1;
if (err) {
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
- "listener=%p state=%d\n", __func__, __LINE__, cm_node,
- cm_node->listener, cm_node->state);
+ "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+ cm_node->listener, cm_node->state);
indicate_pkt_err(cm_node, skb);
nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X "
- "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
- rcv_wnd);
+ "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
+ rcv_wnd);
}
return err;
}
@@ -1596,9 +1837,8 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
* is created with a listener or it may comein as rexmitted packet which in
* that case will be just dropped.
*/
-
static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct tcphdr *tcph)
+ struct tcphdr *tcph)
{
int ret;
u32 inc_sequence;
@@ -1617,15 +1857,15 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
case NES_CM_STATE_LISTENING:
/* Passive OPEN */
if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
- cm_node->listener->backlog) {
+ cm_node->listener->backlog) {
nes_debug(NES_DBG_CM, "drop syn due to backlog "
- "pressure \n");
+ "pressure \n");
cm_backlog_drops++;
passive_open_err(cm_node, skb, 0);
break;
}
ret = handle_tcp_options(cm_node, tcph, skb, optionsize,
- 1);
+ 1);
if (ret) {
passive_open_err(cm_node, skb, 0);
/* drop pkt */
@@ -1659,9 +1899,8 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
}
static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct tcphdr *tcph)
+ struct tcphdr *tcph)
{
-
int ret;
u32 inc_sequence;
int optionsize;
@@ -1680,7 +1919,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);
if (ret) {
nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n",
- cm_node);
+ cm_node);
break;
}
cleanup_retrans_entry(cm_node);
@@ -1719,12 +1958,13 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
}
static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct tcphdr *tcph)
+ struct tcphdr *tcph)
{
int datasize = 0;
u32 inc_sequence;
int ret = 0;
int optionsize;
+
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
if (check_seq(cm_node, tcph, skb))
@@ -1745,8 +1985,9 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else /* rcvd ACK only */
+ } else { /* rcvd ACK only */
dev_kfree_skb_any(skb);
+ }
break;
case NES_CM_STATE_ESTABLISHED:
/* Passive OPEN */
@@ -1754,16 +1995,18 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else
+ } else {
drop_packet(skb);
+ }
break;
case NES_CM_STATE_MPAREQ_SENT:
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else /* Could be just an ack pkt.. */
+ } else { /* Could be just an ack pkt.. */
dev_kfree_skb_any(skb);
+ }
break;
case NES_CM_STATE_LISTENING:
cleanup_retrans_entry(cm_node);
@@ -1804,14 +2047,15 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb, int optionsize, int passive)
+ struct sk_buff *skb, int optionsize, int passive)
{
u8 *optionsloc = (u8 *)&tcph[1];
+
if (optionsize) {
if (process_options(cm_node, optionsloc, optionsize,
- (u32)tcph->syn)) {
+ (u32)tcph->syn)) {
nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
- __func__, cm_node);
+ __func__, cm_node);
if (passive)
passive_open_err(cm_node, skb, 1);
else
@@ -1821,7 +2065,7 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
}
cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
- cm_node->tcp_cntxt.snd_wscale;
+ cm_node->tcp_cntxt.snd_wscale;
if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)
cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
@@ -1832,18 +2076,18 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
* active_open_err() will send reset() if flag set..
* It will also send ABORT event.
*/
-
static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
- int reset)
+ int reset)
{
cleanup_retrans_entry(cm_node);
if (reset) {
nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, "
- "state=%d\n", cm_node, cm_node->state);
+ "state=%d\n", cm_node, cm_node->state);
add_ref_cm_node(cm_node);
send_reset(cm_node, skb);
- } else
+ } else {
dev_kfree_skb_any(skb);
+ }
cm_node->state = NES_CM_STATE_CLOSED;
create_event(cm_node, NES_CM_EVENT_ABORTED);
@@ -1853,15 +2097,14 @@ static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
* passive_open_err() will either do a reset() or will free up the skb and
* remove the cm_node.
*/
-
static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
- int reset)
+ int reset)
{
cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
if (reset) {
nes_debug(NES_DBG_CM, "passive_open_err sending RST for "
- "cm_node=%p state =%d\n", cm_node, cm_node->state);
+ "cm_node=%p state =%d\n", cm_node, cm_node->state);
send_reset(cm_node, skb);
} else {
dev_kfree_skb_any(skb);
@@ -1876,6 +2119,7 @@ static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
static void free_retrans_entry(struct nes_cm_node *cm_node)
{
struct nes_timer_entry *send_entry;
+
send_entry = cm_node->send_entry;
if (send_entry) {
cm_node->send_entry = NULL;
@@ -1899,26 +2143,28 @@ static void cleanup_retrans_entry(struct nes_cm_node *cm_node)
* Returns skb if to be freed, else it will return NULL if already used..
*/
static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct nes_cm_core *cm_core)
+ struct nes_cm_core *cm_core)
{
- enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
+ enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
struct tcphdr *tcph = tcp_hdr(skb);
- u32 fin_set = 0;
+ u32 fin_set = 0;
int ret = 0;
+
skb_pull(skb, ip_hdr(skb)->ihl << 2);
nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
- "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
- tcph->ack, tcph->rst, tcph->fin);
+ "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
+ tcph->ack, tcph->rst, tcph->fin);
- if (tcph->rst)
+ if (tcph->rst) {
pkt_type = NES_PKT_TYPE_RST;
- else if (tcph->syn) {
+ } else if (tcph->syn) {
pkt_type = NES_PKT_TYPE_SYN;
if (tcph->ack)
pkt_type = NES_PKT_TYPE_SYNACK;
- } else if (tcph->ack)
+ } else if (tcph->ack) {
pkt_type = NES_PKT_TYPE_ACK;
+ }
if (tcph->fin)
fin_set = 1;
@@ -1949,17 +2195,17 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
* mini_cm_listen - create a listen node with params
*/
static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
+ struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
{
struct nes_cm_listener *listener;
unsigned long flags;
nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n",
- cm_info->loc_addr, cm_info->loc_port);
+ cm_info->loc_addr, cm_info->loc_port);
/* cannot have multiple matching listeners */
listener = find_listener(cm_core, htonl(cm_info->loc_addr),
- htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
+ htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
/* find automatically incs ref count ??? */
atomic_dec(&listener->ref_count);
@@ -2005,9 +2251,9 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
}
nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x,"
- " listener = %p, backlog = %d, cm_id = %p.\n",
- cm_info->loc_addr, cm_info->loc_port,
- listener, listener->backlog, listener->cm_id);
+ " listener = %p, backlog = %d, cm_id = %p.\n",
+ cm_info->loc_addr, cm_info->loc_port,
+ listener, listener->backlog, listener->cm_id);
return listener;
}
@@ -2017,26 +2263,20 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
* mini_cm_connect - make a connection node with params
*/
static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, u16 private_data_len,
- void *private_data, struct nes_cm_info *cm_info)
+ struct nes_vnic *nesvnic, u16 private_data_len,
+ void *private_data, struct nes_cm_info *cm_info)
{
int ret = 0;
struct nes_cm_node *cm_node;
struct nes_cm_listener *loopbackremotelistener;
struct nes_cm_node *loopbackremotenode;
struct nes_cm_info loopback_cm_info;
- u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len;
- struct ietf_mpa_frame *mpa_frame = NULL;
+ u8 *start_buff;
/* create a CM connection node */
cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
if (!cm_node)
return NULL;
- mpa_frame = &cm_node->mpa_frame;
- memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
- mpa_frame->flags = IETF_MPA_FLAGS_CRC;
- mpa_frame->rev = IETF_MPA_VERSION;
- mpa_frame->priv_data_len = htons(private_data_len);
/* set our node side to client (active) side */
cm_node->tcp_cntxt.client = 1;
@@ -2044,8 +2284,8 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
if (cm_info->loc_addr == cm_info->rem_addr) {
loopbackremotelistener = find_listener(cm_core,
- ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
- NES_CM_LISTENER_ACTIVE_STATE);
+ ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
+ NES_CM_LISTENER_ACTIVE_STATE);
if (loopbackremotelistener == NULL) {
create_event(cm_node, NES_CM_EVENT_ABORTED);
} else {
@@ -2054,7 +2294,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
loopback_cm_info.rem_port = cm_info->loc_port;
loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
loopbackremotenode = make_cm_node(cm_core, nesvnic,
- &loopback_cm_info, loopbackremotelistener);
+ &loopback_cm_info, loopbackremotelistener);
if (!loopbackremotenode) {
rem_ref_cm_node(cm_node->cm_core, cm_node);
return NULL;
@@ -2065,7 +2305,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
NES_CM_DEFAULT_RCV_WND_SCALE;
cm_node->loopbackpartner = loopbackremotenode;
memcpy(loopbackremotenode->mpa_frame_buf, private_data,
- private_data_len);
+ private_data_len);
loopbackremotenode->mpa_frame_size = private_data_len;
/* we are done handling this state. */
@@ -2093,12 +2333,10 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
return cm_node;
}
- /* set our node side to client (active) side */
- cm_node->tcp_cntxt.client = 1;
- /* init our MPA frame ptr */
- memcpy(mpa_frame->priv_data, private_data, private_data_len);
+ start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+ cm_node->mpa_frame_size = private_data_len;
- cm_node->mpa_frame_size = mpa_frame_size;
+ memcpy(start_buff, private_data, private_data_len);
/* send a syn and goto syn sent state */
cm_node->state = NES_CM_STATE_SYN_SENT;
@@ -2107,18 +2345,19 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
if (ret) {
/* error in sending the syn free up the cm_node struct */
nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest "
- "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
- cm_node->rem_addr, cm_node->rem_port, cm_node,
- cm_node->cm_id);
+ "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
+ cm_node->rem_addr, cm_node->rem_port, cm_node,
+ cm_node->cm_id);
rem_ref_cm_node(cm_node->cm_core, cm_node);
cm_node = NULL;
}
- if (cm_node)
+ if (cm_node) {
nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X,"
- "port=0x%04x, cm_node=%p, cm_id = %p.\n",
- cm_node->rem_addr, cm_node->rem_port, cm_node,
- cm_node->cm_id);
+ "port=0x%04x, cm_node=%p, cm_id = %p.\n",
+ cm_node->rem_addr, cm_node->rem_port, cm_node,
+ cm_node->cm_id);
+ }
return cm_node;
}
@@ -2128,8 +2367,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
* mini_cm_accept - accept a connection
* This function is never called
*/
-static int mini_cm_accept(struct nes_cm_core *cm_core,
- struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
{
return 0;
}
@@ -2138,8 +2376,7 @@ static int mini_cm_accept(struct nes_cm_core *cm_core,
/**
* mini_cm_reject - reject and teardown a connection
*/
-static int mini_cm_reject(struct nes_cm_core *cm_core,
- struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
{
int ret = 0;
int err = 0;
@@ -2149,7 +2386,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
struct nes_cm_node *loopback = cm_node->loopbackpartner;
nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
- __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
+ __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
if (cm_node->tcp_cntxt.client)
return ret;
@@ -2170,8 +2407,9 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
err = send_reset(cm_node, NULL);
if (err)
WARN_ON(1);
- } else
+ } else {
cm_id->add_ref(cm_id);
+ }
}
}
} else {
@@ -2246,7 +2484,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
case NES_CM_STATE_TSA:
if (cm_node->send_entry)
printk(KERN_ERR "ERROR Close got called from STATE_TSA "
- "send_entry=%p\n", cm_node->send_entry);
+ "send_entry=%p\n", cm_node->send_entry);
ret = rem_ref_cm_node(cm_core, cm_node);
break;
}
@@ -2259,7 +2497,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
* node state machine
*/
static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, struct sk_buff *skb)
+ struct nes_vnic *nesvnic, struct sk_buff *skb)
{
struct nes_cm_node *cm_node = NULL;
struct nes_cm_listener *listener = NULL;
@@ -2271,9 +2509,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
if (!skb)
return 0;
- if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
+ if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr))
return 0;
- }
iph = (struct iphdr *)skb->data;
tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
@@ -2291,8 +2528,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
do {
cm_node = find_node(cm_core,
- nfo.rem_port, nfo.rem_addr,
- nfo.loc_port, nfo.loc_addr);
+ nfo.rem_port, nfo.rem_addr,
+ nfo.loc_port, nfo.loc_addr);
if (!cm_node) {
/* Only type of packet accepted are for */
@@ -2302,8 +2539,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
break;
}
listener = find_listener(cm_core, nfo.loc_addr,
- nfo.loc_port,
- NES_CM_LISTENER_ACTIVE_STATE);
+ nfo.loc_port,
+ NES_CM_LISTENER_ACTIVE_STATE);
if (!listener) {
nfo.cm_id = NULL;
nfo.conn_type = 0;
@@ -2314,10 +2551,10 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
nfo.cm_id = listener->cm_id;
nfo.conn_type = listener->conn_type;
cm_node = make_cm_node(cm_core, nesvnic, &nfo,
- listener);
+ listener);
if (!cm_node) {
nes_debug(NES_DBG_CM, "Unable to allocate "
- "node\n");
+ "node\n");
cm_packets_dropped++;
atomic_dec(&listener->ref_count);
dev_kfree_skb_any(skb);
@@ -2333,9 +2570,13 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
}
add_ref_cm_node(cm_node);
} else if (cm_node->state == NES_CM_STATE_TSA) {
- rem_ref_cm_node(cm_core, cm_node);
- atomic_inc(&cm_accel_dropped_pkts);
- dev_kfree_skb_any(skb);
+ if (cm_node->nesqp->pau_mode)
+ nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp);
+ else {
+ rem_ref_cm_node(cm_core, cm_node);
+ atomic_inc(&cm_accel_dropped_pkts);
+ dev_kfree_skb_any(skb);
+ }
break;
}
skb_reset_network_header(skb);
@@ -2365,7 +2606,7 @@ static struct nes_cm_core *nes_cm_alloc_core(void)
init_timer(&cm_core->tcp_timer);
cm_core->tcp_timer.function = nes_cm_timer_tick;
- cm_core->mtu = NES_CM_DEFAULT_MTU;
+ cm_core->mtu = NES_CM_DEFAULT_MTU;
cm_core->state = NES_CM_STATE_INITED;
cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
@@ -2403,9 +2644,8 @@ static int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
barrier();
- if (timer_pending(&cm_core->tcp_timer)) {
+ if (timer_pending(&cm_core->tcp_timer))
del_timer(&cm_core->tcp_timer);
- }
destroy_workqueue(cm_core->event_wq);
destroy_workqueue(cm_core->disconn_wq);
@@ -2460,8 +2700,8 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
return -EINVAL;
nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 |
- NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
- NES_QPCONTEXT_MISC_DROS);
+ NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
+ NES_QPCONTEXT_MISC_DROS);
if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)
nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE);
@@ -2471,15 +2711,15 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
- (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
+ (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
- (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
- NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
+ (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
+ NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
- (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
- NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
+ (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
+ NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);
nesqp->nesqp_context->ts_recent = 0;
@@ -2488,24 +2728,24 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);
nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd <<
- cm_node->tcp_cntxt.rcv_wscale);
+ cm_node->tcp_cntxt.rcv_wscale);
nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
nesqp->nesqp_context->srtt = 0;
nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);
nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000);
- nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss);
+ nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss);
nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);
nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X,"
- " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
- nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
- le32_to_cpu(nesqp->nesqp_context->snd_nxt),
- cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
- le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
- le32_to_cpu(nesqp->nesqp_context->misc));
+ " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
+ nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+ le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+ cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
+ le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
+ le32_to_cpu(nesqp->nesqp_context->misc));
nes_debug(NES_DBG_CM, " snd_wnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));
nes_debug(NES_DBG_CM, " snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));
nes_debug(NES_DBG_CM, " max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd));
@@ -2526,7 +2766,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)
work = kzalloc(sizeof *work, GFP_ATOMIC);
if (!work)
- return -ENOMEM; /* Timer will clean up */
+ return -ENOMEM; /* Timer will clean up */
nes_add_ref(&nesqp->ibqp);
work->nesqp = nesqp;
@@ -2546,7 +2786,7 @@ static void nes_disconnect_worker(struct work_struct *work)
kfree(dwork);
nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
- nesqp->last_aeq, nesqp->hwqp.qp_id);
+ nesqp->last_aeq, nesqp->hwqp.qp_id);
nes_cm_disconn_true(nesqp);
nes_rem_ref(&nesqp->ibqp);
}
@@ -2582,7 +2822,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
/* make sure we havent already closed this connection */
if (!cm_id) {
nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
- nesqp->hwqp.qp_id);
+ nesqp->hwqp.qp_id);
spin_unlock_irqrestore(&nesqp->lock, flags);
return -1;
}
@@ -2591,7 +2831,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);
original_hw_tcp_state = nesqp->hw_tcp_state;
- original_ibqp_state = nesqp->ibqp_state;
+ original_ibqp_state = nesqp->ibqp_state;
last_ae = nesqp->last_aeq;
if (nesqp->term_flags) {
@@ -2649,16 +2889,16 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
cm_event.private_data_len = 0;
nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event"
- " for QP%u, SQ Head = %u, SQ Tail = %u. "
- "cm_id = %p, refcount = %u.\n",
- nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
- nesqp->hwqp.sq_tail, cm_id,
- atomic_read(&nesqp->refcount));
+ " for QP%u, SQ Head = %u, SQ Tail = %u. "
+ "cm_id = %p, refcount = %u.\n",
+ nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
+ nesqp->hwqp.sq_tail, cm_id,
+ atomic_read(&nesqp->refcount));
ret = cm_id->event_handler(cm_id, &cm_event);
if (ret)
nes_debug(NES_DBG_CM, "OFA CM event_handler "
- "returned, ret=%d\n", ret);
+ "returned, ret=%d\n", ret);
}
if (issue_close) {
@@ -2676,9 +2916,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
cm_event.private_data_len = 0;
ret = cm_id->event_handler(cm_id, &cm_event);
- if (ret) {
+ if (ret)
nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
- }
cm_id->rem_ref(cm_id);
}
@@ -2718,8 +2957,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
if (nesqp->lsmm_mr)
nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
pci_free_consistent(nesdev->pcidev,
- nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
- nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+ nesqp->private_data_len + nesqp->ietf_frame_size,
+ nesqp->ietf_frame, nesqp->ietf_frame_pbase);
}
}
@@ -2758,6 +2997,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct ib_phys_buf ibphysbuf;
struct nes_pd *nespd;
u64 tagged_offset;
+ u8 mpa_frame_offset = 0;
+ struct ietf_mpa_v2 *mpa_v2_frame;
+ u8 start_addr = 0;
+ u8 *start_ptr = &start_addr;
+ u8 **start_buff = &start_ptr;
+ u16 buff_len = 0;
ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
if (!ibqp)
@@ -2798,53 +3043,49 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
netdev_refcnt_read(nesvnic->netdev));
+ nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2);
/* allocate the ietf frame and space for private data */
nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
- sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
- &nesqp->ietf_frame_pbase);
+ nesqp->ietf_frame_size + conn_param->private_data_len,
+ &nesqp->ietf_frame_pbase);
if (!nesqp->ietf_frame) {
- nes_debug(NES_DBG_CM, "Unable to allocate memory for private "
- "data\n");
+ nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
return -ENOMEM;
}
+ mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame;
+ if (cm_node->mpa_frame_rev == IETF_MPA_V1)
+ mpa_frame_offset = 4;
- /* setup the MPA frame */
- nesqp->private_data_len = conn_param->private_data_len;
- memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
-
- memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
- conn_param->private_data_len);
+ memcpy(mpa_v2_frame->priv_data, conn_param->private_data,
+ conn_param->private_data_len);
- nesqp->ietf_frame->priv_data_len =
- cpu_to_be16(conn_param->private_data_len);
- nesqp->ietf_frame->rev = mpa_version;
- nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
+ cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY);
+ nesqp->private_data_len = conn_param->private_data_len;
/* setup our first outgoing iWarp send WQE (the IETF frame response) */
wqe = &nesqp->hwqp.sq_vbase[0];
if (cm_id->remote_addr.sin_addr.s_addr !=
- cm_id->local_addr.sin_addr.s_addr) {
+ cm_id->local_addr.sin_addr.s_addr) {
u64temp = (unsigned long)nesqp;
nesibdev = nesvnic->nesibdev;
nespd = nesqp->nespd;
- ibphysbuf.addr = nesqp->ietf_frame_pbase;
- ibphysbuf.size = conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame);
- tagged_offset = (u64)(unsigned long)nesqp->ietf_frame;
+ ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset;
+ ibphysbuf.size = buff_len;
+ tagged_offset = (u64)(unsigned long)*start_buff;
ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd,
- &ibphysbuf, 1,
- IB_ACCESS_LOCAL_WRITE,
- &tagged_offset);
+ &ibphysbuf, 1,
+ IB_ACCESS_LOCAL_WRITE,
+ &tagged_offset);
if (!ibmr) {
nes_debug(NES_DBG_CM, "Unable to register memory region"
- "for lSMM for cm_node = %p \n",
- cm_node);
+ "for lSMM for cm_node = %p \n",
+ cm_node);
pci_free_consistent(nesdev->pcidev,
- nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
- nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+ nesqp->private_data_len + nesqp->ietf_frame_size,
+ nesqp->ietf_frame, nesqp->ietf_frame_pbase);
return -ENOMEM;
}
@@ -2852,22 +3093,20 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ibmr->device = nespd->ibpd.device;
nesqp->lsmm_mr = ibmr;
- u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+ u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
set_wqe_64bit_value(wqe->wqe_words,
- NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
- u64temp);
+ NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
+ u64temp);
wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING |
- NES_IWARP_SQ_WQE_WRPDU);
+ NES_IWARP_SQ_WQE_WRPDU);
wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
- cpu_to_le32(conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame));
+ cpu_to_le32(buff_len);
set_wqe_64bit_value(wqe->wqe_words,
- NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
- (u64)(unsigned long)nesqp->ietf_frame);
+ NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+ (u64)(unsigned long)(*start_buff));
wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
- cpu_to_le32(conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame));
+ cpu_to_le32(buff_len);
wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
if (nesqp->sq_kmapped) {
nesqp->sq_kmapped = 0;
@@ -2876,7 +3115,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->nesqp_context->ird_ord_sizes |=
cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
- NES_QPCONTEXT_ORDIRD_WRPDU);
+ NES_QPCONTEXT_ORDIRD_WRPDU);
} else {
nesqp->nesqp_context->ird_ord_sizes |=
cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);
@@ -2890,11 +3129,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
/* nesqp->cm_node = (void *)cm_id->provider_data; */
cm_id->provider_data = nesqp;
- nesqp->active_conn = 0;
+ nesqp->active_conn = 0;
if (cm_node->state == NES_CM_STATE_TSA)
nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n",
- cm_node);
+ cm_node);
nes_cm_init_tsa_conn(nesqp, cm_node);
@@ -2911,13 +3150,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
nesqp->nesqp_context->misc2 |= cpu_to_le32(
- (u32)PCI_FUNC(nesdev->pcidev->devfn) <<
- NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+ (u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+ NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
nesqp->nesqp_context->arp_index_vlan |=
cpu_to_le32(nes_arp_table(nesdev,
- le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
- NES_ARP_RESOLVE) << 16);
+ le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
+ NES_ARP_RESOLVE) << 16);
nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
@@ -2943,7 +3182,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
crc_value = get_crc_value(&nes_quad);
nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
- nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
+ nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
nesqp->hte_index &= adapter->hte_index_mask;
nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
@@ -2951,17 +3190,15 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = "
- "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
- "private data length=%zu.\n", nesqp->hwqp.qp_id,
- ntohl(cm_id->remote_addr.sin_addr.s_addr),
- ntohs(cm_id->remote_addr.sin_port),
- ntohl(cm_id->local_addr.sin_addr.s_addr),
- ntohs(cm_id->local_addr.sin_port),
- le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
- le32_to_cpu(nesqp->nesqp_context->snd_nxt),
- conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame));
-
+ "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
+ "private data length=%u.\n", nesqp->hwqp.qp_id,
+ ntohl(cm_id->remote_addr.sin_addr.s_addr),
+ ntohs(cm_id->remote_addr.sin_port),
+ ntohl(cm_id->local_addr.sin_addr.s_addr),
+ ntohs(cm_id->local_addr.sin_port),
+ le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+ le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+ buff_len);
/* notify OF layer that accept event was successful */
cm_id->add_ref(cm_id);
@@ -2982,12 +3219,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->private_data_len;
/* copy entire MPA frame to our cm_node's frame */
memcpy(cm_node->loopbackpartner->mpa_frame_buf,
- nesqp->ietf_frame->priv_data, nesqp->private_data_len);
+ conn_param->private_data, conn_param->private_data_len);
create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
}
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
- "ret=%d\n", __func__, __LINE__, ret);
+ "ret=%d\n", __func__, __LINE__, ret);
return 0;
}
@@ -3000,34 +3237,28 @@ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{
struct nes_cm_node *cm_node;
struct nes_cm_node *loopback;
-
struct nes_cm_core *cm_core;
+ u8 *start_buff;
atomic_inc(&cm_rejects);
- cm_node = (struct nes_cm_node *) cm_id->provider_data;
+ cm_node = (struct nes_cm_node *)cm_id->provider_data;
loopback = cm_node->loopbackpartner;
cm_core = cm_node->cm_core;
cm_node->cm_id = cm_id;
- cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
- if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
+ if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER)
return -EINVAL;
- memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
if (loopback) {
memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
loopback->mpa_frame.priv_data_len = pdata_len;
- loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) +
- pdata_len;
+ loopback->mpa_frame_size = pdata_len;
} else {
- memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
- cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
+ start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+ cm_node->mpa_frame_size = pdata_len;
+ memcpy(start_buff, pdata, pdata_len);
}
-
- cm_node->mpa_frame.rev = mpa_version;
- cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
-
- return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
+ return cm_core->api->reject(cm_core, cm_node);
}
@@ -3054,7 +3285,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesvnic = to_nesvnic(nesqp->ibqp.device);
if (!nesvnic)
return -EINVAL;
- nesdev = nesvnic->nesdev;
+ nesdev = nesvnic->nesdev;
if (!nesdev)
return -EINVAL;
@@ -3062,12 +3293,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
return -EINVAL;
nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
- "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
- ntohl(nesvnic->local_ipaddr),
- ntohl(cm_id->remote_addr.sin_addr.s_addr),
- ntohs(cm_id->remote_addr.sin_port),
- ntohl(cm_id->local_addr.sin_addr.s_addr),
- ntohs(cm_id->local_addr.sin_port));
+ "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
+ ntohl(nesvnic->local_ipaddr),
+ ntohl(cm_id->remote_addr.sin_addr.s_addr),
+ ntohs(cm_id->remote_addr.sin_port),
+ ntohl(cm_id->local_addr.sin_addr.s_addr),
+ ntohs(cm_id->local_addr.sin_port));
atomic_inc(&cm_connects);
nesqp->active_conn = 1;
@@ -3081,12 +3312,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
- conn_param->private_data_len);
+ conn_param->private_data_len);
if (cm_id->local_addr.sin_addr.s_addr !=
- cm_id->remote_addr.sin_addr.s_addr) {
+ cm_id->remote_addr.sin_addr.s_addr) {
nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
- PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+ PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
apbvt_set = 1;
}
@@ -3102,13 +3333,13 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
/* create a connect CM node connection */
cm_node = g_cm_core->api->connect(g_cm_core, nesvnic,
- conn_param->private_data_len, (void *)conn_param->private_data,
- &cm_info);
+ conn_param->private_data_len, (void *)conn_param->private_data,
+ &cm_info);
if (!cm_node) {
if (apbvt_set)
nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
- PCI_FUNC(nesdev->pcidev->devfn),
- NES_MANAGE_APBVT_DEL);
+ PCI_FUNC(nesdev->pcidev->devfn),
+ NES_MANAGE_APBVT_DEL);
cm_id->rem_ref(cm_id);
return -ENOMEM;
@@ -3158,7 +3389,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
if (!cm_node) {
printk(KERN_ERR "%s[%u] Error returned from listen API call\n",
- __func__, __LINE__);
+ __func__, __LINE__);
return -ENOMEM;
}
@@ -3166,12 +3397,12 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
if (!cm_node->reused_node) {
err = nes_manage_apbvt(nesvnic,
- ntohs(cm_id->local_addr.sin_port),
- PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
- NES_MANAGE_APBVT_ADD);
+ ntohs(cm_id->local_addr.sin_port),
+ PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
+ NES_MANAGE_APBVT_ADD);
if (err) {
printk(KERN_ERR "nes_manage_apbvt call returned %d.\n",
- err);
+ err);
g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
return err;
}
@@ -3208,13 +3439,13 @@ int nes_destroy_listen(struct iw_cm_id *cm_id)
int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
{
int rc = 0;
+
cm_packets_received++;
- if ((g_cm_core) && (g_cm_core->api)) {
+ if ((g_cm_core) && (g_cm_core->api))
rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
- } else {
+ else
nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
- " cm is not setup properly.\n");
- }
+ " cm is not setup properly.\n");
return rc;
}
@@ -3229,11 +3460,10 @@ int nes_cm_start(void)
nes_debug(NES_DBG_CM, "\n");
/* create the primary CM core, pass this handle to subsequent core inits */
g_cm_core = nes_cm_alloc_core();
- if (g_cm_core) {
+ if (g_cm_core)
return 0;
- } else {
+ else
return -ENOMEM;
- }
}
@@ -3254,7 +3484,6 @@ int nes_cm_stop(void)
*/
static void cm_event_connected(struct nes_cm_event *event)
{
- u64 u64temp;
struct nes_qp *nesqp;
struct nes_vnic *nesvnic;
struct nes_device *nesdev;
@@ -3263,7 +3492,6 @@ static void cm_event_connected(struct nes_cm_event *event)
struct ib_qp_attr attr;
struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
- struct nes_hw_qp_wqe *wqe;
struct nes_v4_quad nes_quad;
u32 crc_value;
int ret;
@@ -3277,17 +3505,16 @@ static void cm_event_connected(struct nes_cm_event *event)
nesdev = nesvnic->nesdev;
nesadapter = nesdev->nesadapter;
- if (nesqp->destroyed) {
+ if (nesqp->destroyed)
return;
- }
atomic_inc(&cm_connecteds);
nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on"
- " local port 0x%04X. jiffies = %lu.\n",
- nesqp->hwqp.qp_id,
- ntohl(cm_id->remote_addr.sin_addr.s_addr),
- ntohs(cm_id->remote_addr.sin_port),
- ntohs(cm_id->local_addr.sin_port),
- jiffies);
+ " local port 0x%04X. jiffies = %lu.\n",
+ nesqp->hwqp.qp_id,
+ ntohl(cm_id->remote_addr.sin_addr.s_addr),
+ ntohs(cm_id->remote_addr.sin_port),
+ ntohs(cm_id->local_addr.sin_port),
+ jiffies);
nes_cm_init_tsa_conn(nesqp, cm_node);
@@ -3318,40 +3545,12 @@ static void cm_event_connected(struct nes_cm_event *event)
NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
/* Adjust tail for not having a LSMM */
- nesqp->hwqp.sq_tail = 1;
+ /*nesqp->hwqp.sq_tail = 1;*/
-#if defined(NES_SEND_FIRST_WRITE)
- if (cm_node->send_write0) {
- nes_debug(NES_DBG_CM, "Sending first write.\n");
- wqe = &nesqp->hwqp.sq_vbase[0];
- u64temp = (unsigned long)nesqp;
- u64temp |= NES_SW_CONTEXT_ALIGN>>1;
- set_wqe_64bit_value(wqe->wqe_words,
- NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
- wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
- cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
- wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+ build_rdma0_msg(cm_node, &nesqp);
- if (nesqp->sq_kmapped) {
- nesqp->sq_kmapped = 0;
- kunmap(nesqp->page);
- }
-
- /* use the reserved spot on the WQ for the extra first WQE */
- nesqp->nesqp_context->ird_ord_sizes &=
- cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
- NES_QPCONTEXT_ORDIRD_WRPDU |
- NES_QPCONTEXT_ORDIRD_ALSMM));
- nesqp->skip_lsmm = 1;
- nesqp->hwqp.sq_tail = 0;
- nes_write32(nesdev->regs + NES_WQE_ALLOC,
- (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
- }
-#endif
+ nes_write32(nesdev->regs + NES_WQE_ALLOC,
+ (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
memset(&nes_quad, 0, sizeof(nes_quad));
@@ -3368,13 +3567,13 @@ static void cm_event_connected(struct nes_cm_event *event)
crc_value = get_crc_value(&nes_quad);
nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n",
- nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+ nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
nesqp->hte_index &= nesadapter->hte_index_mask;
nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
nesqp->ietf_frame = &cm_node->mpa_frame;
- nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
+ nesqp->private_data_len = (u8)cm_node->mpa_frame_size;
cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
/* notify OF layer we successfully created the requested connection */
@@ -3386,7 +3585,9 @@ static void cm_event_connected(struct nes_cm_event *event)
cm_event.remote_addr = cm_id->remote_addr;
cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
- cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
+ cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size;
+ cm_event.ird = cm_node->ird_size;
+ cm_event.ord = cm_node->ord_size;
cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
ret = cm_id->event_handler(cm_id, &cm_event);
@@ -3394,12 +3595,12 @@ static void cm_event_connected(struct nes_cm_event *event)
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
- "ret=%d\n", __func__, __LINE__, ret);
+ "ret=%d\n", __func__, __LINE__, ret);
attr.qp_state = IB_QPS_RTS;
nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = "
- "%lu\n", nesqp->hwqp.qp_id, jiffies);
+ "%lu\n", nesqp->hwqp.qp_id, jiffies);
return;
}
@@ -3420,16 +3621,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)
return;
cm_id = event->cm_node->cm_id;
- if (!cm_id) {
+ if (!cm_id)
return;
- }
nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);
nesqp = cm_id->provider_data;
- if (!nesqp) {
+ if (!nesqp)
return;
- }
/* notify OF layer about this connection error event */
/* cm_id->rem_ref(cm_id); */
@@ -3444,14 +3643,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)
cm_event.private_data_len = 0;
nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, "
- "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
- cm_event.remote_addr.sin_addr.s_addr);
+ "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
+ cm_event.remote_addr.sin_addr.s_addr);
ret = cm_id->event_handler(cm_id, &cm_event);
nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
- "ret=%d\n", __func__, __LINE__, ret);
+ "ret=%d\n", __func__, __LINE__, ret);
cm_id->rem_ref(cm_id);
rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
@@ -3521,7 +3720,7 @@ static void cm_event_reset(struct nes_cm_event *event)
*/
static void cm_event_mpa_req(struct nes_cm_event *event)
{
- struct iw_cm_id *cm_id;
+ struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
int ret;
struct nes_cm_node *cm_node;
@@ -3533,7 +3732,7 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
atomic_inc(&cm_connect_reqs);
nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
- cm_node, cm_id, jiffies);
+ cm_node, cm_id, jiffies);
cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
cm_event.status = 0;
@@ -3547,19 +3746,21 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
cm_event.private_data = cm_node->mpa_frame_buf;
- cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+ cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
+ cm_event.ird = cm_node->ird_size;
+ cm_event.ord = cm_node->ord_size;
ret = cm_id->event_handler(cm_id, &cm_event);
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
- __func__, __LINE__, ret);
+ __func__, __LINE__, ret);
return;
}
static void cm_event_mpa_reject(struct nes_cm_event *event)
{
- struct iw_cm_id *cm_id;
+ struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
struct nes_cm_node *cm_node;
int ret;
@@ -3571,7 +3772,7 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)
atomic_inc(&cm_connect_reqs);
nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
- cm_node, cm_id, jiffies);
+ cm_node, cm_id, jiffies);
cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
cm_event.status = -ECONNREFUSED;
@@ -3586,17 +3787,17 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
cm_event.private_data = cm_node->mpa_frame_buf;
- cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+ cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, "
- "remove_addr=%08x\n",
- cm_event.local_addr.sin_addr.s_addr,
- cm_event.remote_addr.sin_addr.s_addr);
+ "remove_addr=%08x\n",
+ cm_event.local_addr.sin_addr.s_addr,
+ cm_event.remote_addr.sin_addr.s_addr);
ret = cm_id->event_handler(cm_id, &cm_event);
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
- __func__, __LINE__, ret);
+ __func__, __LINE__, ret);
return;
}
@@ -3615,7 +3816,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)
event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
INIT_WORK(&event->event_work, nes_cm_event_handler);
nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
- event->cm_node, event);
+ event->cm_node, event);
queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
@@ -3632,7 +3833,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)
static void nes_cm_event_handler(struct work_struct *work)
{
struct nes_cm_event *event = container_of(work, struct nes_cm_event,
- event_work);
+ event_work);
struct nes_cm_core *cm_core;
if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core))
@@ -3640,29 +3841,29 @@ static void nes_cm_event_handler(struct work_struct *work)
cm_core = event->cm_node->cm_core;
nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
- event, event->type, atomic_read(&cm_core->events_posted));
+ event, event->type, atomic_read(&cm_core->events_posted));
switch (event->type) {
case NES_CM_EVENT_MPA_REQ:
cm_event_mpa_req(event);
nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n",
- event->cm_node);
+ event->cm_node);
break;
case NES_CM_EVENT_RESET:
nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n",
- event->cm_node);
+ event->cm_node);
cm_event_reset(event);
break;
case NES_CM_EVENT_CONNECTED:
if ((!event->cm_node->cm_id) ||
- (event->cm_node->state != NES_CM_STATE_TSA))
+ (event->cm_node->state != NES_CM_STATE_TSA))
break;
cm_event_connected(event);
nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
break;
case NES_CM_EVENT_MPA_REJECT:
if ((!event->cm_node->cm_id) ||
- (event->cm_node->state == NES_CM_STATE_TSA))
+ (event->cm_node->state == NES_CM_STATE_TSA))
break;
cm_event_mpa_reject(event);
nes_debug(NES_DBG_CM, "CM Event: REJECT\n");
@@ -3670,7 +3871,7 @@ static void nes_cm_event_handler(struct work_struct *work)
case NES_CM_EVENT_ABORTED:
if ((!event->cm_node->cm_id) ||
- (event->cm_node->state == NES_CM_STATE_TSA))
+ (event->cm_node->state == NES_CM_STATE_TSA))
break;
cm_event_connect_error(event);
nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index d9825fd..bdfa1fb 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -48,7 +48,16 @@
#define IETF_MPA_KEY_SIZE 16
#define IETF_MPA_VERSION 1
#define IETF_MAX_PRIV_DATA_LEN 512
-#define IETF_MPA_FRAME_SIZE 20
+#define IETF_MPA_FRAME_SIZE 20
+#define IETF_RTR_MSG_SIZE 4
+#define IETF_MPA_V2_FLAG 0x10
+
+/* IETF RTR MSG Fields */
+#define IETF_PEER_TO_PEER 0x8000
+#define IETF_FLPDU_ZERO_LEN 0x4000
+#define IETF_RDMA0_WRITE 0x8000
+#define IETF_RDMA0_READ 0x4000
+#define IETF_NO_IRD_ORD 0x3FFF
enum ietf_mpa_flags {
IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */
@@ -56,7 +65,7 @@ enum ietf_mpa_flags {
IETF_MPA_FLAGS_REJECT = 0x20, /* Reject */
};
-struct ietf_mpa_frame {
+struct ietf_mpa_v1 {
u8 key[IETF_MPA_KEY_SIZE];
u8 flags;
u8 rev;
@@ -66,6 +75,20 @@ struct ietf_mpa_frame {
#define ietf_mpa_req_resp_frame ietf_mpa_frame
+struct ietf_rtr_msg {
+ __be16 ctrl_ird;
+ __be16 ctrl_ord;
+};
+
+struct ietf_mpa_v2 {
+ u8 key[IETF_MPA_KEY_SIZE];
+ u8 flags;
+ u8 rev;
+ __be16 priv_data_len;
+ struct ietf_rtr_msg rtr_msg;
+ u8 priv_data[0];
+};
+
struct nes_v4_quad {
u32 rsvd0;
__le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */
@@ -171,8 +194,7 @@ struct nes_timer_entry {
#define NES_CM_DEF_SEQ2 0x18ed5740
#define NES_CM_DEF_LOCAL_ID2 0xb807
-#define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN)
-
+#define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN)
typedef u32 nes_addr_t;
@@ -204,6 +226,21 @@ enum nes_cm_node_state {
NES_CM_STATE_CLOSED
};
+enum mpa_frame_version {
+ IETF_MPA_V1 = 1,
+ IETF_MPA_V2 = 2
+};
+
+enum mpa_frame_key {
+ MPA_KEY_REQUEST,
+ MPA_KEY_REPLY
+};
+
+enum send_rdma0 {
+ SEND_RDMA_READ_ZERO = 1,
+ SEND_RDMA_WRITE_ZERO = 2
+};
+
enum nes_tcpip_pkt_type {
NES_PKT_TYPE_UNKNOWN,
NES_PKT_TYPE_SYN,
@@ -245,9 +282,9 @@ struct nes_cm_tcp_context {
enum nes_cm_listener_state {
- NES_CM_LISTENER_PASSIVE_STATE=1,
- NES_CM_LISTENER_ACTIVE_STATE=2,
- NES_CM_LISTENER_EITHER_STATE=3
+ NES_CM_LISTENER_PASSIVE_STATE = 1,
+ NES_CM_LISTENER_ACTIVE_STATE = 2,
+ NES_CM_LISTENER_EITHER_STATE = 3
};
struct nes_cm_listener {
@@ -283,16 +320,20 @@ struct nes_cm_node {
struct nes_cm_node *loopbackpartner;
- struct nes_timer_entry *send_entry;
-
+ struct nes_timer_entry *send_entry;
+ struct nes_timer_entry *recv_entry;
spinlock_t retrans_list_lock;
- struct nes_timer_entry *recv_entry;
+ enum send_rdma0 send_rdma0_op;
- int send_write0;
union {
- struct ietf_mpa_frame mpa_frame;
- u8 mpa_frame_buf[MAX_CM_BUFFER];
+ struct ietf_mpa_v1 mpa_frame;
+ struct ietf_mpa_v2 mpa_v2_frame;
+ u8 mpa_frame_buf[MAX_CM_BUFFER];
};
+ enum mpa_frame_version mpa_frame_rev;
+ u16 ird_size;
+ u16 ord_size;
+
u16 mpa_frame_size;
struct iw_cm_id *cm_id;
struct list_head list;
@@ -399,10 +440,8 @@ struct nes_cm_ops {
struct nes_vnic *, u16, void *,
struct nes_cm_info *);
int (*close)(struct nes_cm_core *, struct nes_cm_node *);
- int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
- int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
+ int (*accept)(struct nes_cm_core *, struct nes_cm_node *);
+ int (*reject)(struct nes_cm_core *, struct nes_cm_node *);
int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
struct sk_buff *);
int (*destroy_cm_core)(struct nes_cm_core *);
@@ -422,5 +461,7 @@ int nes_destroy_listen(struct iw_cm_id *);
int nes_cm_recv(struct sk_buff *, struct net_device *);
int nes_cm_start(void);
int nes_cm_stop(void);
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
#endif /* NES_CM_H */
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index ba4814a..4cd1bf7 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -109,6 +109,14 @@ static unsigned char *nes_tcp_state_str[] = {
};
#endif
+static inline void print_ip(struct nes_cm_node *cm_node)
+{
+ unsigned char *rem_addr;
+ if (cm_node) {
+ rem_addr = (unsigned char *)&cm_node->rem_addr;
+ printk(KERN_ERR PFX "Remote IP addr: %pI4\n", rem_addr);
+ }
+}
/**
* nes_nic_init_timer_defaults
@@ -1554,6 +1562,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
struct nes_hw_nic_rq_wqe *nic_rqe;
struct nes_hw_nic *nesnic;
struct nes_device *nesdev;
+ struct nes_rskb_cb *cb;
u32 rx_wqes_posted = 0;
nesnic = &nesvnic->nic;
@@ -1579,6 +1588,9 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
bus_address = pci_map_single(nesdev->pcidev,
skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->busaddr = bus_address;
+ cb->maplen = nesvnic->max_frame_size;
nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
@@ -1668,6 +1680,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
u32 cqp_head;
u32 counter;
u32 wqe_count;
+ struct nes_rskb_cb *cb;
u8 jumbomode=0;
/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
@@ -1844,6 +1857,9 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
pmem = pci_map_single(nesdev->pcidev, skb->data,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->busaddr = pmem;
+ cb->maplen = nesvnic->max_frame_size;
nic_rqe = &nesvnic->nic.rq_vbase[counter];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
@@ -1872,6 +1888,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
jumbomode = 1;
nes_nic_init_timer_defaults(nesdev, jumbomode);
}
+ if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
+ (nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
+ nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
+ nes_destroy_nic_qp(nesvnic);
+ return -ENOMEM;
+ }
+
nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
@@ -1894,28 +1917,29 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
struct nes_device *nesdev = nesvnic->nesdev;
struct nes_hw_cqp_wqe *cqp_wqe;
struct nes_hw_nic_sq_wqe *nic_sqe;
- struct nes_hw_nic_rq_wqe *nic_rqe;
__le16 *wqe_fragment_length;
u16 wqe_fragment_index;
- u64 wqe_frag;
u32 cqp_head;
u32 wqm_cfg0;
unsigned long flags;
+ struct sk_buff *rx_skb;
+ struct nes_rskb_cb *cb;
int ret;
+ if (nesdev->nesadapter->allow_unaligned_fpdus)
+ nes_destroy_mgt(nesvnic);
+
/* clear wqe stall before destroying NIC QP */
wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
/* Free remaining NIC receive buffers */
while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
- nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
- wqe_frag = (u64)le32_to_cpu(
- nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
- wqe_frag |= ((u64)le32_to_cpu(
- nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
- pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
- nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
+ cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+ pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
+ PCI_DMA_FROMDEVICE);
+
dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
}
@@ -2774,6 +2798,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
struct nes_hw_nic_sq_wqe *nic_sqe;
struct sk_buff *skb;
struct sk_buff *rx_skb;
+ struct nes_rskb_cb *cb;
__le16 *wqe_fragment_length;
u32 head;
u32 cq_size;
@@ -2858,6 +2883,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
pci_unmap_single(nesdev->pcidev, bus_address,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+ cb->busaddr = 0;
/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
/* rx_skb->len = rx_pkt_size; */
rx_skb->len = 0; /* TODO: see if this is necessary */
@@ -2916,24 +2943,19 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
goto skip_rx_indicate0;
- if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
- (nesvnic->vlan_grp != NULL)) {
+ if (cqe_misc & NES_NIC_CQE_TAG_VALID) {
vlan_tag = (u16)(le32_to_cpu(
cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
>> 16);
nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
nesvnic->netdev->name, vlan_tag);
- if (nes_use_lro)
- lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
- nesvnic->vlan_grp, vlan_tag, NULL);
- else
- nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
- } else {
- if (nes_use_lro)
- lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
- else
- nes_netif_rx(rx_skb);
+
+ __vlan_hwaccel_put_tag(rx_skb, vlan_tag);
}
+ if (nes_use_lro)
+ lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
+ else
+ netif_receive_skb(rx_skb);
skip_rx_indicate0:
;
@@ -2987,6 +3009,7 @@ skip_rx_indicate0:
}
+
/**
* nes_cqp_ce_handler
*/
@@ -3001,6 +3024,8 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
u32 cq_size;
u32 cqe_count=0;
u32 error_code;
+ u32 opcode;
+ u32 ctx_index;
/* u32 counter; */
head = cq->cq_head;
@@ -3011,12 +3036,9 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
- if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
- u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
- cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
- ((u64)(le32_to_cpu(cq->cq_vbase[head].
- cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
- cqp = *((struct nes_hw_cqp **)&u64temp);
+ opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
+ if (opcode & NES_CQE_VALID) {
+ cqp = &nesdev->cqp;
error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
if (error_code) {
@@ -3025,15 +3047,14 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
(u16)(error_code >> 16),
(u16)error_code);
- nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
- cqp->qp_id, cqp->sq_head, cqp->sq_tail);
}
- u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
- wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
- ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
- wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
- cqp_request = *((struct nes_cqp_request **)&u64temp);
+ u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
+ cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
+ ((u64)(le32_to_cpu(cq->cq_vbase[head].
+ cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
+
+ cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
if (cqp_request) {
if (cqp_request->waiting) {
/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
@@ -3079,9 +3100,15 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
cqp_wqe = &nesdev->cqp.sq_vbase[head];
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
barrier();
- cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
+
+ opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
+ if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+ ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
+ else
+ ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
+ cqp_wqe->wqe_words[ctx_index] =
cpu_to_le32((u32)((unsigned long)cqp_request));
- cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
+ cqp_wqe->wqe_words[ctx_index + 1] =
cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
@@ -3097,7 +3124,6 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
nes_read32(nesdev->regs+NES_CQE_ALLOC);
}
-
static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
{
if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
@@ -3553,9 +3579,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
if (aeq_info & NES_AEQE_QP) {
- if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps,
- aeqe_cq_id)) ||
- (atomic_read(&nesqp->close_timer_started)))
+ if (!nes_is_resource_allocated(nesadapter,
+ nesadapter->allocated_qps,
+ aeqe_cq_id))
return;
}
@@ -3566,8 +3592,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
- (nesqp->ibqp_state == IB_QPS_RTS) &&
- ((nesadapter->eeprom_version >> 16) != NES_A0)) {
+ (nesqp->ibqp_state == IB_QPS_RTS)) {
spin_lock_irqsave(&nesqp->lock, flags);
nesqp->hw_iwarp_state = iwarp_state;
nesqp->hw_tcp_state = tcp_state;
@@ -3594,9 +3619,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
return;
}
spin_lock_irqsave(&nesqp->lock, flags);
- nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+ nesqp->hw_iwarp_state = iwarp_state;
+ nesqp->hw_tcp_state = tcp_state;
+ nesqp->last_aeq = async_event_id;
spin_unlock_irqrestore(&nesqp->lock, flags);
- nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
nes_cm_disconn(nesqp);
break;
@@ -3694,7 +3720,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
nesqp->hwqp.qp_id, async_event_id);
- nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
+ print_ip(nesqp->cm_node);
+ if (!atomic_read(&nesqp->close_timer_started))
+ nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
break;
case NES_AEQE_AEID_CQ_OPERATION_ERROR:
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 9159411..0b590e1 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -47,6 +47,11 @@
#define NES_MULTICAST_PF_MAX 8
#define NES_A0 3
+#define NES_ENABLE_PAU 0x07000001
+#define NES_DISABLE_PAU 0x07000000
+#define NES_PAU_COUNTER 10
+#define NES_CQP_OPCODE_MASK 0x3f
+
enum pci_regs {
NES_INT_STAT = 0x0000,
NES_INT_MASK = 0x0004,
@@ -73,8 +78,10 @@ enum indexed_regs {
NES_IDX_QP_CONTROL = 0x0040,
NES_IDX_FLM_CONTROL = 0x0080,
NES_IDX_INT_CPU_STATUS = 0x00a0,
+ NES_IDX_GPR_TRIGGER = 0x00bc,
NES_IDX_GPIO_CONTROL = 0x00f0,
NES_IDX_GPIO_DATA = 0x00f4,
+ NES_IDX_GPR2 = 0x010c,
NES_IDX_TCP_CONFIG0 = 0x01e4,
NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
NES_IDX_TCP_NOW = 0x01f0,
@@ -202,6 +209,7 @@ enum nes_cqp_opcodes {
NES_CQP_REGISTER_SHARED_STAG = 0x0c,
NES_CQP_DEALLOCATE_STAG = 0x0d,
NES_CQP_MANAGE_ARP_CACHE = 0x0f,
+ NES_CQP_DOWNLOAD_SEGMENT = 0x10,
NES_CQP_SUSPEND_QPS = 0x11,
NES_CQP_UPLOAD_CONTEXT = 0x13,
NES_CQP_CREATE_CEQ = 0x16,
@@ -210,7 +218,8 @@ enum nes_cqp_opcodes {
NES_CQP_DESTROY_AEQ = 0x1b,
NES_CQP_LMI_ACCESS = 0x20,
NES_CQP_FLUSH_WQES = 0x22,
- NES_CQP_MANAGE_APBVT = 0x23
+ NES_CQP_MANAGE_APBVT = 0x23,
+ NES_CQP_MANAGE_QUAD_HASH = 0x25
};
enum nes_cqp_wqe_word_idx {
@@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx {
NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
};
+enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
+ NES_CQP_WQE_DL_OPCODE_IDX = 0,
+ NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
+ NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
+ NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
+ /* For index values 4-15 use NES_NIC_SQ_WQE_ values */
+};
+
enum nes_cqp_cq_wqeword_idx {
NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
@@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx {
NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
};
+#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
#define NES_CQP_OP_IWARP_STATE_SHIFT 28
#define NES_CQP_OP_TERMLEN_SHIFT 28
@@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits {
enum nes_nic_cqe_word_idx {
NES_NIC_CQE_ACCQP_ID_IDX = 0,
+ NES_NIC_CQE_HASH_RCVNXT = 1,
NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
NES_NIC_CQE_MISC_IDX = 3,
};
@@ -1005,6 +1024,11 @@ struct nes_arp_entry {
#define NES_NIC_CQ_DOWNWARD_TREND 16
#define NES_PFT_SIZE 48
+#define NES_MGT_WQ_COUNT 32
+#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
+#define NES_MGT_QP_OFFSET 36
+#define NES_MGT_QP_COUNT 4
+
struct nes_hw_tune_timer {
/* u16 cq_count; */
u16 threshold_low;
@@ -1118,6 +1142,7 @@ struct nes_adapter {
u32 et_rate_sample_interval;
u32 timer_int_limit;
u32 wqm_quanta;
+ u8 allow_unaligned_fpdus;
/* Adapter base MAC address */
u32 mac_addr_low;
@@ -1211,7 +1236,6 @@ struct nes_vnic {
/* void *mem; */
struct nes_device *nesdev;
struct net_device *netdev;
- struct vlan_group *vlan_grp;
atomic_t rx_skbs_needed;
atomic_t rx_skb_timer_running;
int budget;
@@ -1252,6 +1276,14 @@ struct nes_vnic {
enum ib_event_type delayed_event;
enum ib_event_type last_dispatched_event;
spinlock_t port_ibevent_lock;
+ u32 mgt_mem_size;
+ void *mgt_vbase;
+ dma_addr_t mgt_pbase;
+ struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
+ struct task_struct *mgt_thread;
+ wait_queue_head_t mgt_wait_queue;
+ struct sk_buff_head mgt_skb_list;
+
};
struct nes_ib_device {
@@ -1357,7 +1389,4 @@ struct nes_terminate_hdr {
#define NES_LINK_RECHECK_DELAY msecs_to_jiffies(50)
#define NES_LINK_RECHECK_MAX 60
-#define nes_vlan_rx vlan_hwaccel_receive_skb
-#define nes_netif_rx netif_receive_skb
-
#endif /* __NES_HW_H */
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index d3a1c41..c00d2f3 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -441,13 +441,13 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
nesnic->tx_skb[nesnic->sq_head] = skb;
for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
skb_fragment_index++) {
- bus_address = pci_map_page( nesdev->pcidev,
- skb_shinfo(skb)->frags[skb_fragment_index].page,
- skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
- skb_shinfo(skb)->frags[skb_fragment_index].size,
- PCI_DMA_TODEVICE);
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[skb_fragment_index];
+ bus_address = skb_frag_dma_map(&nesdev->pcidev->dev,
+ frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
wqe_fragment_length[wqe_fragment_index] =
- cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
+ cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[skb_fragment_index]));
set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
bus_address);
wqe_fragment_index++;
@@ -561,11 +561,12 @@ tso_sq_no_longer_full:
/* Map all the buffers */
for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
tso_frag_count++) {
- tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
- skb_shinfo(skb)->frags[tso_frag_count].page,
- skb_shinfo(skb)->frags[tso_frag_count].page_offset,
- skb_shinfo(skb)->frags[tso_frag_count].size,
- PCI_DMA_TODEVICE);
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[tso_frag_count];
+ tso_bus_address[tso_frag_count] =
+ skb_frag_dma_map(&nesdev->pcidev->dev,
+ frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
}
tso_frag_index = 0;
@@ -636,11 +637,11 @@ tso_sq_no_longer_full:
}
while (wqe_fragment_index < 5) {
wqe_fragment_length[wqe_fragment_index] =
- cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
+ cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index]));
set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
(u64)tso_bus_address[tso_frag_index]);
wqe_fragment_index++;
- tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;
+ tso_wqe_length += skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index++]);
if (wqe_fragment_index < 5)
wqe_fragment_length[wqe_fragment_index] = 0;
if (tso_frag_index == tso_frag_count)
@@ -1090,6 +1091,8 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
"LRO aggregated",
"LRO flushed",
"LRO no_desc",
+ "PAU CreateQPs",
+ "PAU DestroyQPs",
};
#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
@@ -1305,6 +1308,8 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
+ target_stat_values[++index] = atomic_read(&pau_qps_created);
+ target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
}
/**
@@ -1584,23 +1589,19 @@ static const struct ethtool_ops nes_ethtool_ops = {
.set_pauseparam = nes_netdev_set_pauseparam,
};
-
-static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+static void nes_vlan_mode(struct net_device *netdev, struct nes_device *nesdev, u32 features)
{
- struct nes_vnic *nesvnic = netdev_priv(netdev);
- struct nes_device *nesdev = nesvnic->nesdev;
struct nes_adapter *nesadapter = nesdev->nesadapter;
u32 u32temp;
unsigned long flags;
spin_lock_irqsave(&nesadapter->phy_lock, flags);
- nesvnic->vlan_grp = grp;
nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name);
/* Enable/Disable VLAN Stripping */
u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG);
- if (grp)
+ if (features & NETIF_F_HW_VLAN_RX)
u32temp &= 0xfdffffff;
else
u32temp |= 0x02000000;
@@ -1609,17 +1610,44 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g
spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
}
+static u32 nes_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int nes_set_features(struct net_device *netdev, u32 features)
+{
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+ u32 changed = netdev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ nes_vlan_mode(netdev, nesdev, features);
+
+ return 0;
+}
+
static const struct net_device_ops nes_netdev_ops = {
- .ndo_open = nes_netdev_open,
+ .ndo_open = nes_netdev_open,
.ndo_stop = nes_netdev_stop,
- .ndo_start_xmit = nes_netdev_start_xmit,
+ .ndo_start_xmit = nes_netdev_start_xmit,
.ndo_get_stats = nes_netdev_get_stats,
- .ndo_tx_timeout = nes_netdev_tx_timeout,
+ .ndo_tx_timeout = nes_netdev_tx_timeout,
.ndo_set_mac_address = nes_netdev_set_mac_address,
- .ndo_set_multicast_list = nes_netdev_set_multicast_list,
+ .ndo_set_rx_mode = nes_netdev_set_multicast_list,
.ndo_change_mtu = nes_netdev_change_mtu,
.ndo_validate_addr = eth_validate_addr,
- .ndo_vlan_rx_register = nes_netdev_vlan_rx_register,
+ .ndo_fix_features = nes_fix_features,
+ .ndo_set_features = nes_set_features,
};
/**
@@ -1656,7 +1684,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->ethtool_ops = &nes_ethtool_ops;
netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
- netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ netdev->features |= NETIF_F_HW_VLAN_TX;
/* Fill in the port structure */
nesvnic->netdev = netdev;
@@ -1683,7 +1711,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->dev_addr[5] = (u8)u64temp;
memcpy(netdev->perm_addr, netdev->dev_addr, 6);
- netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
+ netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_HW_VLAN_RX;
if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
netdev->hw_features |= NETIF_F_TSO;
netdev->features |= netdev->hw_features;
@@ -1815,6 +1844,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
nes_init_phy(nesdev);
}
+ nes_vlan_mode(netdev, nesdev, netdev->features);
+
return netdev;
}
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index f9c417c..cd10968 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -51,13 +51,34 @@
#include "nes.h"
-
-
static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
u32 mh_detected;
u32 mh_pauses_sent;
+u32 nes_set_pau(struct nes_device *nesdev)
+{
+ u32 ret = 0;
+ u32 counter;
+
+ nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
+ nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+
+ for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
+ udelay(30);
+ if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
+ printk(KERN_INFO PFX "PAU is supported.\n");
+ break;
+ }
+ nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+ }
+ if (counter == NES_PAU_COUNTER) {
+ printk(KERN_INFO PFX "PAU is not supported.\n");
+ return -EPERM;
+ }
+ return ret;
+}
+
/**
* nes_read_eeprom_values -
*/
@@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada
if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
nesadapter->send_term_ok = 1;
+ if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
+ if (!nes_set_pau(nesdev))
+ nesadapter->allow_unaligned_fpdus = 1;
+ }
+
nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) +
(u32)((u8)eeprom_data);
@@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_device *nesdev,
nes_free_cqp_request(nesdev, cqp_request);
}
+
/**
* nes_post_cqp_request
*/
@@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_device *nesdev,
unsigned long flags;
u32 cqp_head;
u64 u64temp;
+ u32 opcode;
+ int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
spin_lock_irqsave(&nesdev->cqp.lock, flags);
@@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_device *nesdev,
nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
+ opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
+ if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+ ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
barrier();
u64temp = (unsigned long)cqp_request;
- set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
- u64temp);
+ set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
- " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
- " waiting = %d, refcount = %d.\n",
- le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
- le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
- nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
- cqp_request->waiting, atomic_read(&cqp_request->refcount));
+ " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
+ " waiting = %d, refcount = %d.\n",
+ opcode & NES_CQP_OPCODE_MASK,
+ le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
+ nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
+ cqp_request->waiting, atomic_read(&cqp_request->refcount));
+
barrier();
/* Ring doorbell (1 WQEs) */
@@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_device *nesdev,
return;
}
-
/**
* nes_arp_table
*/
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 59db49f..330eb6e 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -605,16 +605,6 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr
/**
- * nes_modify_port
- */
-static int nes_modify_port(struct ib_device *ibdev, u8 port,
- int port_modify_mask, struct ib_port_modify *props)
-{
- return 0;
-}
-
-
-/**
* nes_query_pkey
*/
static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
@@ -1193,7 +1183,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
kfree(nesqp->allocated_buffer);
nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n");
- return NULL;
+ return ERR_PTR(-EFAULT);
}
if (req.user_wqe_buffers) {
virt_wqs = 1;
@@ -1470,7 +1460,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
struct ib_qp_attr attr;
struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
- int ret;
+ int ret = 0;
atomic_inc(&sw_qps_destroyed);
nesqp->destroyed = 1;
@@ -1523,7 +1513,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
nes_clean_cq(nesqp, nesqp->nesrcq);
}
-
nes_rem_ref(&nesqp->ibqp);
return 0;
}
@@ -2350,8 +2339,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
skip_pages = ((u32)region->offset) >> 12;
- if (ib_copy_from_udata(&req, udata, sizeof(req)))
+ if (ib_copy_from_udata(&req, udata, sizeof(req))) {
+ ib_umem_release(region);
return ERR_PTR(-EFAULT);
+ }
nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
switch (req.reg_type) {
@@ -2648,6 +2639,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
return &nesmr->ibmr;
}
+ ib_umem_release(region);
return ERR_PTR(-ENOSYS);
}
@@ -3889,7 +3881,6 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;
nesibdev->ibdev.query_device = nes_query_device;
nesibdev->ibdev.query_port = nes_query_port;
- nesibdev->ibdev.modify_port = nes_modify_port;
nesibdev->ibdev.query_pkey = nes_query_pkey;
nesibdev->ibdev.query_gid = nes_query_gid;
nesibdev->ibdev.alloc_ucontext = nes_alloc_ucontext;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 2df9993e..fe6b6e9 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -139,7 +139,8 @@ struct nes_qp {
struct nes_cq *nesrcq;
struct nes_pd *nespd;
void *cm_node; /* handle of the node this QP is associated with */
- struct ietf_mpa_frame *ietf_frame;
+ void *ietf_frame;
+ u8 ietf_frame_size;
dma_addr_t ietf_frame_pbase;
struct ib_mr *lsmm_mr;
struct nes_hw_qp hwqp;
@@ -154,6 +155,7 @@ struct nes_qp {
u32 mmap_sq_db_index;
u32 mmap_rq_db_index;
spinlock_t lock;
+ spinlock_t pau_lock;
struct nes_qp_context *nesqp_context;
dma_addr_t nesqp_context_pbase;
void *pbl_vbase;
@@ -161,6 +163,8 @@ struct nes_qp {
struct page *page;
struct timer_list terminate_timer;
enum ib_event_type terminate_eventtype;
+ struct sk_buff_head pau_list;
+ u32 pau_rcv_nxt;
u16 active_conn:1;
u16 skip_lsmm:1;
u16 user_mode:1;
@@ -168,7 +172,8 @@ struct nes_qp {
u16 flush_issued:1;
u16 destroyed:1;
u16 sig_all:1;
- u16 rsvd:9;
+ u16 pau_mode:1;
+ u16 rsvd:8;
u16 private_data_len;
u16 term_sq_flush_code;
u16 term_rq_flush_code;
@@ -176,5 +181,8 @@ struct nes_qp {
u8 hw_tcp_state;
u8 term_flags;
u8 sq_kmapped;
+ u8 pau_busy;
+ u8 pau_pending;
+ u8 pau_state;
};
#endif /* NES_VERBS_H */
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 769a1d9..c0b72a6 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -171,7 +171,9 @@ struct qib_ctxtdata {
/* how many alloc_pages() chunks in rcvegrbuf_pages */
u32 rcvegrbuf_chunks;
/* how many egrbufs per chunk */
- u32 rcvegrbufs_perchunk;
+ u16 rcvegrbufs_perchunk;
+ /* ilog2 of above */
+ u16 rcvegrbufs_perchunk_shift;
/* order for rcvegrbuf_pages */
size_t rcvegrbuf_size;
/* rcvhdrq size (for freeing) */
@@ -221,6 +223,9 @@ struct qib_ctxtdata {
/* ctxt rcvhdrq head offset */
u32 head;
u32 pkt_count;
+ /* lookaside fields */
+ struct qib_qp *lookaside_qp;
+ u32 lookaside_qpn;
/* QPs waiting for context processing */
struct list_head qp_wait_list;
};
@@ -807,6 +812,10 @@ struct qib_devdata {
* supports, less gives more pio bufs/ctxt, etc.
*/
u32 cfgctxts;
+ /*
+ * number of ctxts available for PSM open
+ */
+ u32 freectxts;
/*
* hint that we should update pioavailshadow before
@@ -936,7 +945,9 @@ struct qib_devdata {
/* chip address space used by 4k pio buffers */
u32 align4k;
/* size of each rcvegrbuffer */
- u32 rcvegrbufsize;
+ u16 rcvegrbufsize;
+ /* log2 of above */
+ u16 rcvegrbufsize_shift;
/* localbus width (1, 2,4,8,16,32) from config space */
u32 lbus_width;
/* localbus speed in MHz */
@@ -994,12 +1005,6 @@ struct qib_devdata {
/* control high-level access to EEPROM */
struct mutex eep_lock;
uint64_t traffic_wds;
- /* active time is kept in seconds, but logged in hours */
- atomic_t active_time;
- /* Below are nominal shadow of EEPROM, new since last EEPROM update */
- uint8_t eep_st_errs[QIB_EEP_LOG_CNT];
- uint8_t eep_st_new_errs[QIB_EEP_LOG_CNT];
- uint16_t eep_hrs;
/*
* masks for which bits of errs, hwerrs that cause
* each of the counters to increment.
@@ -1012,6 +1017,8 @@ struct qib_devdata {
u8 psxmitwait_supported;
/* cycle length of PS* counters in HW (in picoseconds) */
u16 psxmitwait_check_rate;
+ /* high volume overflow errors defered to tasklet */
+ struct tasklet_struct error_tasklet;
};
/* hol_state values */
@@ -1214,8 +1221,7 @@ int qib_twsi_blk_rd(struct qib_devdata *dd, int dev, int addr, void *buffer,
int qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr,
const void *buffer, int len);
void qib_get_eeprom_info(struct qib_devdata *);
-int qib_update_eeprom_log(struct qib_devdata *dd);
-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr);
+#define qib_inc_eeprom_err(dd, eidx, incr)
void qib_dump_lookup_output_queue(struct qib_devdata *);
void qib_force_pio_avail_update(struct qib_devdata *);
void qib_clear_symerror_on_linkup(unsigned long opaque);
@@ -1415,6 +1421,10 @@ extern struct mutex qib_mutex;
qib_get_unit_name((dd)->unit), ##__VA_ARGS__); \
} while (0)
+#define qib_dev_warn(dd, fmt, ...) \
+ dev_warn(&(dd)->pcidev->dev, "%s: " fmt, \
+ qib_get_unit_name((dd)->unit), ##__VA_ARGS__)
+
#define qib_dev_porterr(dd, port, fmt, ...) \
do { \
dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \
@@ -1433,6 +1443,7 @@ extern struct mutex qib_mutex;
struct qib_hwerror_msgs {
u64 mask;
const char *msg;
+ size_t sz;
};
#define QLOGIC_IB_HWE_MSG(a, b) { .mask = a, .msg = b }
diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c
index 204c4dd..9892456 100644
--- a/drivers/infiniband/hw/qib/qib_diag.c
+++ b/drivers/infiniband/hw/qib/qib_diag.c
@@ -46,6 +46,7 @@
#include <linux/pci.h>
#include <linux/poll.h>
#include <linux/vmalloc.h>
+#include <linux/export.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c
index 23e584f..c90a55f 100644
--- a/drivers/infiniband/hw/qib/qib_driver.c
+++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
+#include <linux/module.h>
#include "qib.h"
@@ -279,10 +280,10 @@ bail:
*/
static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
{
- const u32 chunk = etail / rcd->rcvegrbufs_perchunk;
- const u32 idx = etail % rcd->rcvegrbufs_perchunk;
+ const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
+ const u32 idx = etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
- return rcd->rcvegrbuf[chunk] + idx * rcd->dd->rcvegrbufsize;
+ return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
}
/*
@@ -310,7 +311,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
u32 opcode;
u32 psn;
int diff;
- unsigned long flags;
/* Sanity check packet */
if (tlen < 24)
@@ -365,7 +365,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
switch (qp->ibqp.qp_type) {
case IB_QPT_RC:
- spin_lock_irqsave(&qp->s_lock, flags);
ruc_res =
qib_ruc_check_hdr(
ibp, hdr,
@@ -373,11 +372,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
qp,
be32_to_cpu(ohdr->bth[0]));
if (ruc_res) {
- spin_unlock_irqrestore(&qp->s_lock,
- flags);
goto unlock;
}
- spin_unlock_irqrestore(&qp->s_lock, flags);
/* Only deal with RDMA Writes for now */
if (opcode <
@@ -547,6 +543,15 @@ move_along:
updegr = 0;
}
}
+ /*
+ * Notify qib_destroy_qp() if it is waiting
+ * for lookaside_qp to finish.
+ */
+ if (rcd->lookaside_qp) {
+ if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
+ wake_up(&rcd->lookaside_qp->wait);
+ rcd->lookaside_qp = NULL;
+ }
rcd->head = l;
rcd->pkt_count += i;
diff --git a/drivers/infiniband/hw/qib/qib_eeprom.c b/drivers/infiniband/hw/qib/qib_eeprom.c
index 92d9cfe..6359c2f 100644
--- a/drivers/infiniband/hw/qib/qib_eeprom.c
+++ b/drivers/infiniband/hw/qib/qib_eeprom.c
@@ -263,189 +263,9 @@ void qib_get_eeprom_info(struct qib_devdata *dd)
qib_dev_err(dd, "Board SN %s did not pass functional "
"test: %s\n", dd->serial, ifp->if_comment);
- memcpy(&dd->eep_st_errs, &ifp->if_errcntp, QIB_EEP_LOG_CNT);
- /*
- * Power-on (actually "active") hours are kept as little-endian value
- * in EEPROM, but as seconds in a (possibly as small as 24-bit)
- * atomic_t while running.
- */
- atomic_set(&dd->active_time, 0);
- dd->eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
-
done:
vfree(buf);
bail:;
}
-/**
- * qib_update_eeprom_log - copy active-time and error counters to eeprom
- * @dd: the qlogic_ib device
- *
- * Although the time is kept as seconds in the qib_devdata struct, it is
- * rounded to hours for re-write, as we have only 16 bits in EEPROM.
- * First-cut code reads whole (expected) struct qib_flash, modifies,
- * re-writes. Future direction: read/write only what we need, assuming
- * that the EEPROM had to have been "good enough" for driver init, and
- * if not, we aren't making it worse.
- *
- */
-int qib_update_eeprom_log(struct qib_devdata *dd)
-{
- void *buf;
- struct qib_flash *ifp;
- int len, hi_water;
- uint32_t new_time, new_hrs;
- u8 csum;
- int ret, idx;
- unsigned long flags;
-
- /* first, check if we actually need to do anything. */
- ret = 0;
- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
- if (dd->eep_st_new_errs[idx]) {
- ret = 1;
- break;
- }
- }
- new_time = atomic_read(&dd->active_time);
-
- if (ret == 0 && new_time < 3600)
- goto bail;
-
- /*
- * The quick-check above determined that there is something worthy
- * of logging, so get current contents and do a more detailed idea.
- * read full flash, not just currently used part, since it may have
- * been written with a newer definition
- */
- len = sizeof(struct qib_flash);
- buf = vmalloc(len);
- ret = 1;
- if (!buf) {
- qib_dev_err(dd, "Couldn't allocate memory to read %u "
- "bytes from eeprom for logging\n", len);
- goto bail;
- }
-
- /* Grab semaphore and read current EEPROM. If we get an
- * error, let go, but if not, keep it until we finish write.
- */
- ret = mutex_lock_interruptible(&dd->eep_lock);
- if (ret) {
- qib_dev_err(dd, "Unable to acquire EEPROM for logging\n");
- goto free_bail;
- }
- ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 0, buf, len);
- if (ret) {
- mutex_unlock(&dd->eep_lock);
- qib_dev_err(dd, "Unable read EEPROM for logging\n");
- goto free_bail;
- }
- ifp = (struct qib_flash *)buf;
-
- csum = flash_csum(ifp, 0);
- if (csum != ifp->if_csum) {
- mutex_unlock(&dd->eep_lock);
- qib_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
- csum, ifp->if_csum);
- ret = 1;
- goto free_bail;
- }
- hi_water = 0;
- spin_lock_irqsave(&dd->eep_st_lock, flags);
- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
- int new_val = dd->eep_st_new_errs[idx];
- if (new_val) {
- /*
- * If we have seen any errors, add to EEPROM values
- * We need to saturate at 0xFF (255) and we also
- * would need to adjust the checksum if we were
- * trying to minimize EEPROM traffic
- * Note that we add to actual current count in EEPROM,
- * in case it was altered while we were running.
- */
- new_val += ifp->if_errcntp[idx];
- if (new_val > 0xFF)
- new_val = 0xFF;
- if (ifp->if_errcntp[idx] != new_val) {
- ifp->if_errcntp[idx] = new_val;
- hi_water = offsetof(struct qib_flash,
- if_errcntp) + idx;
- }
- /*
- * update our shadow (used to minimize EEPROM
- * traffic), to match what we are about to write.
- */
- dd->eep_st_errs[idx] = new_val;
- dd->eep_st_new_errs[idx] = 0;
- }
- }
- /*
- * Now update active-time. We would like to round to the nearest hour
- * but unless atomic_t are sure to be proper signed ints we cannot,
- * because we need to account for what we "transfer" to EEPROM and
- * if we log an hour at 31 minutes, then we would need to set
- * active_time to -29 to accurately count the _next_ hour.
- */
- if (new_time >= 3600) {
- new_hrs = new_time / 3600;
- atomic_sub((new_hrs * 3600), &dd->active_time);
- new_hrs += dd->eep_hrs;
- if (new_hrs > 0xFFFF)
- new_hrs = 0xFFFF;
- dd->eep_hrs = new_hrs;
- if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
- ifp->if_powerhour[0] = new_hrs & 0xFF;
- hi_water = offsetof(struct qib_flash, if_powerhour);
- }
- if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
- ifp->if_powerhour[1] = new_hrs >> 8;
- hi_water = offsetof(struct qib_flash, if_powerhour) + 1;
- }
- }
- /*
- * There is a tiny possibility that we could somehow fail to write
- * the EEPROM after updating our shadows, but problems from holding
- * the spinlock too long are a much bigger issue.
- */
- spin_unlock_irqrestore(&dd->eep_st_lock, flags);
- if (hi_water) {
- /* we made some change to the data, uopdate cksum and write */
- csum = flash_csum(ifp, 1);
- ret = eeprom_write_with_enable(dd, 0, buf, hi_water + 1);
- }
- mutex_unlock(&dd->eep_lock);
- if (ret)
- qib_dev_err(dd, "Failed updating EEPROM\n");
-
-free_bail:
- vfree(buf);
-bail:
- return ret;
-}
-
-/**
- * qib_inc_eeprom_err - increment one of the four error counters
- * that are logged to EEPROM.
- * @dd: the qlogic_ib device
- * @eidx: 0..3, the counter to increment
- * @incr: how much to add
- *
- * Each counter is 8-bits, and saturates at 255 (0xFF). They
- * are copied to the EEPROM (aka flash) whenever qib_update_eeprom_log()
- * is called, but it can only be called in a context that allows sleep.
- * This function can be called even at interrupt level.
- */
-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr)
-{
- uint new_val;
- unsigned long flags;
-
- spin_lock_irqsave(&dd->eep_st_lock, flags);
- new_val = dd->eep_st_new_errs[eidx] + incr;
- if (new_val > 255)
- new_val = 255;
- dd->eep_st_new_errs[eidx] = new_val;
- spin_unlock_irqrestore(&dd->eep_st_lock, flags);
-}
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 406fca5..a740324 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -43,6 +43,7 @@
#include <linux/jiffies.h>
#include <asm/pgtable.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "qib.h"
#include "qib_common.h"
@@ -1284,6 +1285,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt,
strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
ctxt_fp(fp) = rcd;
qib_stats.sps_ctxts++;
+ dd->freectxts--;
ret = 0;
goto bail;
@@ -1527,6 +1529,7 @@ done_chk_sdma:
struct qib_filedata *fd = fp->private_data;
const struct qib_ctxtdata *rcd = fd->rcd;
const struct qib_devdata *dd = rcd->dd;
+ unsigned int weight;
if (dd->flags & QIB_HAS_SEND_DMA) {
fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev,
@@ -1545,8 +1548,8 @@ done_chk_sdma:
* it just means that sooner or later we don't recommend
* a cpu, and let the scheduler do it's best.
*/
- if (!ret && cpus_weight(current->cpus_allowed) >=
- qib_cpulist_count) {
+ weight = cpumask_weight(tsk_cpus_allowed(current));
+ if (!ret && weight >= qib_cpulist_count) {
int cpu;
cpu = find_first_zero_bit(qib_cpulist,
qib_cpulist_count);
@@ -1554,13 +1557,13 @@ done_chk_sdma:
__set_bit(cpu, qib_cpulist);
fd->rec_cpu_num = cpu;
}
- } else if (cpus_weight(current->cpus_allowed) == 1 &&
- test_bit(first_cpu(current->cpus_allowed),
+ } else if (weight == 1 &&
+ test_bit(cpumask_first(tsk_cpus_allowed(current)),
qib_cpulist))
qib_devinfo(dd->pcidev, "%s PID %u affinity "
"set to cpu %d; already allocated\n",
current->comm, current->pid,
- first_cpu(current->cpus_allowed));
+ cpumask_first(tsk_cpus_allowed(current)));
}
mutex_unlock(&qib_mutex);
@@ -1791,6 +1794,7 @@ static int qib_close(struct inode *in, struct file *fp)
if (dd->pageshadow)
unlock_expected_tids(rcd);
qib_stats.sps_ctxts--;
+ dd->freectxts++;
}
mutex_unlock(&qib_mutex);
@@ -1904,8 +1908,9 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
struct qib_ctxtdata *rcd;
unsigned ctxt;
int ret = 0;
+ unsigned long flags;
- spin_lock(&ppd->dd->uctxt_lock);
+ spin_lock_irqsave(&ppd->dd->uctxt_lock, flags);
for (ctxt = ppd->dd->first_user_ctxt; ctxt < ppd->dd->cfgctxts;
ctxt++) {
rcd = ppd->dd->rcd[ctxt];
@@ -1924,7 +1929,7 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
ret = 1;
break;
}
- spin_unlock(&ppd->dd->uctxt_lock);
+ spin_unlock_irqrestore(&ppd->dd->uctxt_lock, flags);
return ret;
}
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 65df26c..2a0f7de 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -2674,8 +2674,6 @@ static void qib_get_6120_faststats(unsigned long opaque)
spin_lock_irqsave(&dd->eep_st_lock, flags);
traffic_wds -= dd->traffic_wds;
dd->traffic_wds += traffic_wds;
- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
- atomic_add(5, &dd->active_time); /* S/B #define */
spin_unlock_irqrestore(&dd->eep_st_lock, flags);
qib_chk_6120_errormask(dd);
@@ -3275,6 +3273,8 @@ static int init_6120_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */
ret = ib_mtu_enum_to_int(qib_ibmtu);
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+ BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+ dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_6120_tidtemplate(dd);
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index 759bb63..4dc04e3 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -39,6 +39,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/io.h>
#include <rdma/ib_verbs.h>
@@ -2434,6 +2435,7 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
int lsb, ret = 0, setforce = 0;
u16 lcmd, licmd;
unsigned long flags;
+ u32 tmp = 0;
switch (which) {
case QIB_IB_CFG_LIDLMC:
@@ -2467,9 +2469,6 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
maskr = IBA7220_IBC_WIDTH_MASK;
lsb = IBA7220_IBC_WIDTH_SHIFT;
setforce = 1;
- spin_lock_irqsave(&ppd->lflags_lock, flags);
- ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
- spin_unlock_irqrestore(&ppd->lflags_lock, flags);
break;
case QIB_IB_CFG_SPD_ENB: /* set allowed Link speeds */
@@ -2643,6 +2642,28 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
goto bail;
}
qib_set_ib_7220_lstate(ppd, lcmd, licmd);
+
+ maskr = IBA7220_IBC_WIDTH_MASK;
+ lsb = IBA7220_IBC_WIDTH_SHIFT;
+ tmp = (ppd->cpspec->ibcddrctrl >> lsb) & maskr;
+ /* If the width active on the chip does not match the
+ * width in the shadow register, write the new active
+ * width to the chip.
+ * We don't have to worry about speed as the speed is taken
+ * care of by set_7220_ibspeed_fast called by ib_updown.
+ */
+ if (ppd->link_width_enabled-1 != tmp) {
+ ppd->cpspec->ibcddrctrl &= ~(maskr << lsb);
+ ppd->cpspec->ibcddrctrl |=
+ (((u64)(ppd->link_width_enabled-1) & maskr) <<
+ lsb);
+ qib_write_kreg(dd, kr_ibcddrctrl,
+ ppd->cpspec->ibcddrctrl);
+ qib_write_kreg(dd, kr_scratch, 0);
+ spin_lock_irqsave(&ppd->lflags_lock, flags);
+ ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
+ spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+ }
goto bail;
case QIB_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */
@@ -3271,8 +3292,6 @@ static void qib_get_7220_faststats(unsigned long opaque)
spin_lock_irqsave(&dd->eep_st_lock, flags);
traffic_wds -= dd->traffic_wds;
dd->traffic_wds += traffic_wds;
- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
- atomic_add(5, &dd->active_time); /* S/B #define */
spin_unlock_irqrestore(&dd->eep_st_lock, flags);
done:
mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER);
@@ -4067,6 +4086,8 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */
ret = ib_mtu_enum_to_int(qib_ibmtu);
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+ BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+ dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_7220_tidtemplate(dd);
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 49e4a58..44180c6 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -40,6 +40,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/jiffies.h>
+#include <linux/module.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_smi.h>
@@ -114,6 +115,10 @@ static ushort qib_singleport;
module_param_named(singleport, qib_singleport, ushort, S_IRUGO);
MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space");
+static ushort qib_krcvq01_no_msi;
+module_param_named(krcvq01_no_msi, qib_krcvq01_no_msi, ushort, S_IRUGO);
+MODULE_PARM_DESC(krcvq01_no_msi, "No MSI for kctx < 2");
+
/*
* Receive header queue sizes
*/
@@ -397,7 +402,6 @@ MODULE_PARM_DESC(txselect, \
#define crp_txdroppedpkt CREG_IDX(TxDroppedPktCnt)
#define crp_txhdrerr CREG_IDX(TxHeadersErrCnt)
#define crp_txlenerr CREG_IDX(TxLenErrCnt)
-#define crp_txlenerr CREG_IDX(TxLenErrCnt)
#define crp_txminmaxlenerr CREG_IDX(TxMaxMinLenErrCnt)
#define crp_txsdmadesc CREG_IDX(TxSDmaDescCnt)
#define crp_txunderrun CREG_IDX(TxUnderrunCnt)
@@ -1107,9 +1111,9 @@ static inline u32 read_7322_creg32_port(const struct qib_pportdata *ppd,
#define AUTONEG_TRIES 3 /* sequential retries to negotiate DDR */
#define HWE_AUTO(fldname) { .mask = SYM_MASK(HwErrMask, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname , .sz = sizeof(#fldname) }
#define HWE_AUTO_P(fldname, port) { .mask = SYM_MASK(HwErrMask, \
- fldname##Mask##_##port), .msg = #fldname }
+ fldname##Mask##_##port), .msg = #fldname , .sz = sizeof(#fldname) }
static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
HWE_AUTO_P(IBSerdesPClkNotDetect, 1),
HWE_AUTO_P(IBSerdesPClkNotDetect, 0),
@@ -1127,14 +1131,16 @@ static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
HWE_AUTO_P(IBCBusFromSPCParityErr, 0),
HWE_AUTO(statusValidNoEop),
HWE_AUTO(LATriggered),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
#define E_AUTO(fldname) { .mask = SYM_MASK(ErrMask, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname, .sz = sizeof(#fldname) }
#define E_P_AUTO(fldname) { .mask = SYM_MASK(ErrMask_0, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname, .sz = sizeof(#fldname) }
static const struct qib_hwerror_msgs qib_7322error_msgs[] = {
+ E_AUTO(RcvEgrFullErr),
+ E_AUTO(RcvHdrFullErr),
E_AUTO(ResetNegated),
E_AUTO(HardwareErr),
E_AUTO(InvalidAddrErr),
@@ -1147,9 +1153,7 @@ static const struct qib_hwerror_msgs qib_7322error_msgs[] = {
E_AUTO(SendSpecialTriggerErr),
E_AUTO(SDmaWrongPortErr),
E_AUTO(SDmaBufMaskDuplicateErr),
- E_AUTO(RcvHdrFullErr),
- E_AUTO(RcvEgrFullErr),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
@@ -1159,7 +1163,8 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
/*
* SDmaHaltErr is not really an error, make it clearer;
*/
- {.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted"},
+ {.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted",
+ .sz = 11},
E_P_AUTO(SDmaDescAddrMisalignErr),
E_P_AUTO(SDmaUnexpDataErr),
E_P_AUTO(SDmaMissingDwErr),
@@ -1195,7 +1200,7 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
E_P_AUTO(RcvICRCErr),
E_P_AUTO(RcvVCRCErr),
E_P_AUTO(RcvFormatErr),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
/*
@@ -1203,17 +1208,17 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
* context
*/
#define INTR_AUTO(fldname) { .mask = SYM_MASK(IntMask, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname, .sz = sizeof(#fldname) }
/* Below generates "auto-message" for interrupts specific to a port */
#define INTR_AUTO_P(fldname) { .mask = MASK_ACROSS(\
SYM_LSB(IntMask, fldname##Mask##_0), \
SYM_LSB(IntMask, fldname##Mask##_1)), \
- .msg = #fldname "_P" }
+ .msg = #fldname "_P", .sz = sizeof(#fldname "_P") }
/* For some reason, the SerDesTrimDone bits are reversed */
#define INTR_AUTO_PI(fldname) { .mask = MASK_ACROSS(\
SYM_LSB(IntMask, fldname##Mask##_1), \
SYM_LSB(IntMask, fldname##Mask##_0)), \
- .msg = #fldname "_P" }
+ .msg = #fldname "_P", .sz = sizeof(#fldname "_P") }
/*
* Below generates "auto-message" for interrupts specific to a context,
* with ctxt-number appended
@@ -1221,7 +1226,7 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
#define INTR_AUTO_C(fldname) { .mask = MASK_ACROSS(\
SYM_LSB(IntMask, fldname##0IntMask), \
SYM_LSB(IntMask, fldname##17IntMask)), \
- .msg = #fldname "_C"}
+ .msg = #fldname "_C", .sz = sizeof(#fldname "_C") }
static const struct qib_hwerror_msgs qib_7322_intr_msgs[] = {
INTR_AUTO_P(SDmaInt),
@@ -1235,11 +1240,12 @@ static const struct qib_hwerror_msgs qib_7322_intr_msgs[] = {
INTR_AUTO_P(SendDoneInt),
INTR_AUTO(SendBufAvailInt),
INTR_AUTO_C(RcvAvail),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
#define TXSYMPTOM_AUTO_P(fldname) \
- { .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), .msg = #fldname }
+ { .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), \
+ .msg = #fldname, .sz = sizeof(#fldname) }
static const struct qib_hwerror_msgs hdrchk_msgs[] = {
TXSYMPTOM_AUTO_P(NonKeyPacket),
TXSYMPTOM_AUTO_P(GRHFail),
@@ -1248,7 +1254,7 @@ static const struct qib_hwerror_msgs hdrchk_msgs[] = {
TXSYMPTOM_AUTO_P(SLIDFail),
TXSYMPTOM_AUTO_P(RawIPV6),
TXSYMPTOM_AUTO_P(PacketTooSmall),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
#define IBA7322_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
@@ -1293,7 +1299,7 @@ static void err_decode(char *msg, size_t len, u64 errs,
u64 these, lmask;
int took, multi, n = 0;
- while (msp && msp->mask) {
+ while (errs && msp && msp->mask) {
multi = (msp->mask & (msp->mask - 1));
while (errs & msp->mask) {
these = (errs & msp->mask);
@@ -1304,9 +1310,14 @@ static void err_decode(char *msg, size_t len, u64 errs,
*msg++ = ',';
len--;
}
- took = scnprintf(msg, len, "%s", msp->msg);
+ BUG_ON(!msp->sz);
+ /* msp->sz counts the nul */
+ took = min_t(size_t, msp->sz - (size_t)1, len);
+ memcpy(msg, msp->msg, took);
len -= took;
msg += took;
+ if (len)
+ *msg = '\0';
}
errs &= ~lmask;
if (len && multi) {
@@ -1644,6 +1655,14 @@ done:
return;
}
+static void qib_error_tasklet(unsigned long data)
+{
+ struct qib_devdata *dd = (struct qib_devdata *)data;
+
+ handle_7322_errors(dd);
+ qib_write_kreg(dd, kr_errmask, dd->cspec->errormask);
+}
+
static void reenable_chase(unsigned long opaque)
{
struct qib_pportdata *ppd = (struct qib_pportdata *)opaque;
@@ -2260,6 +2279,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
qib_write_kreg_port(ppd, krp_ibcctrl_a, ppd->cpspec->ibcctrl_a);
qib_write_kreg(dd, kr_scratch, 0ULL);
+ /* ensure previous Tx parameters are not still forced */
+ qib_write_kreg_port(ppd, krp_tx_deemph_override,
+ SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+ reset_tx_deemphasis_override));
+
if (qib_compat_ddr_negotiate) {
ppd->cpspec->ibdeltainprog = 1;
ppd->cpspec->ibsymsnap = read_7322_creg32_port(ppd,
@@ -2288,16 +2312,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
SYM_LSB(IBCCtrlA_0, MaxPktLen);
ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */
- /* initially come up waiting for TS1, without sending anything. */
- val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
- QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
-
/*
* Reset the PCS interface to the serdes (and also ibc, which is still
* in reset from above). Writes new value of ibcctrl_a as last step.
*/
qib_7322_mini_pcs_reset(ppd);
- qib_write_kreg(dd, kr_scratch, 0ULL);
if (!ppd->cpspec->ibcctrl_b) {
unsigned lse = ppd->link_speed_enabled;
@@ -2363,17 +2382,20 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
set_vls(ppd);
+ /* initially come up DISABLED, without sending anything. */
+ val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
+ QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
+ qib_write_kreg_port(ppd, krp_ibcctrl_a, val);
+ qib_write_kreg(dd, kr_scratch, 0ULL);
+ /* clear the linkinit cmds */
+ ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
+
/* be paranoid against later code motion, etc. */
spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl);
spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
- /* Hold the link state machine for mezz boards */
- if (IS_QMH(dd) || IS_QME(dd))
- qib_set_ib_7322_lstate(ppd, 0,
- QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
-
/* Also enable IBSTATUSCHG interrupt. */
val = qib_read_kreg_port(ppd, krp_errmask);
qib_write_kreg_port(ppd, krp_errmask,
@@ -2725,8 +2747,10 @@ static noinline void unlikely_7322_intr(struct qib_devdata *dd, u64 istat)
unknown_7322_ibits(dd, istat);
if (istat & QIB_I_GPIO)
unknown_7322_gpio_intr(dd);
- if (istat & QIB_I_C_ERROR)
- handle_7322_errors(dd);
+ if (istat & QIB_I_C_ERROR) {
+ qib_write_kreg(dd, kr_errmask, 0ULL);
+ tasklet_schedule(&dd->error_tasklet);
+ }
if (istat & INT_MASK_P(Err, 0) && dd->rcd[0])
handle_7322_p_errors(dd->rcd[0]->ppd);
if (istat & INT_MASK_P(Err, 1) && dd->rcd[1])
@@ -2833,9 +2857,8 @@ static irqreturn_t qib_7322intr(int irq, void *data)
for (i = 0; i < dd->first_user_ctxt; i++) {
if (ctxtrbits & rmask) {
ctxtrbits &= ~rmask;
- if (dd->rcd[i]) {
+ if (dd->rcd[i])
qib_kreceive(dd->rcd[i], NULL, &npkts);
- }
}
rmask <<= 1;
}
@@ -3125,6 +3148,8 @@ try_intx:
arg = dd->rcd[ctxt];
if (!arg)
continue;
+ if (qib_krcvq01_no_msi && ctxt < 2)
+ continue;
lsb = QIB_I_RCVAVAIL_LSB + ctxt;
handler = qib_7322pintr;
name = QIB_DRV_NAME " (kctx)";
@@ -3159,6 +3184,8 @@ try_intx:
for (i = 0; i < ARRAY_SIZE(redirect); i++)
qib_write_kreg(dd, kr_intredirect + i, redirect[i]);
dd->cspec->main_int_mask = mask;
+ tasklet_init(&dd->error_tasklet, qib_error_tasklet,
+ (unsigned long)dd);
bail:;
}
@@ -4766,8 +4793,6 @@ static void qib_get_7322_faststats(unsigned long opaque)
spin_lock_irqsave(&ppd->dd->eep_st_lock, flags);
traffic_wds -= ppd->dd->traffic_wds;
ppd->dd->traffic_wds += traffic_wds;
- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
- atomic_add(ACTIVITY_TIMER, &ppd->dd->active_time);
spin_unlock_irqrestore(&ppd->dd->eep_st_lock, flags);
if (ppd->cpspec->qdr_dfe_on && (ppd->link_speed_active &
QIB_IB_QDR) &&
@@ -5208,6 +5233,8 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
QIBL_IB_AUTONEG_INPROG)))
set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
+ struct qib_qsfp_data *qd =
+ &ppd->cpspec->qsfp_data;
/* unlock the Tx settings, speed may change */
qib_write_kreg_port(ppd, krp_tx_deemph_override,
SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
@@ -5215,6 +5242,12 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
qib_cancel_sends(ppd);
/* on link down, ensure sane pcs state */
qib_7322_mini_pcs_reset(ppd);
+ /* schedule the qsfp refresh which should turn the link
+ off */
+ if (ppd->dd->flags & QIB_HAS_QSFP) {
+ qd->t_insert = get_jiffies_64();
+ queue_work(ib_wq, &qd->work);
+ }
spin_lock_irqsave(&ppd->sdma_lock, flags);
if (__qib_sdma_running(ppd))
__qib_sdma_process_event(ppd,
@@ -5565,43 +5598,79 @@ static void qsfp_7322_event(struct work_struct *work)
struct qib_qsfp_data *qd;
struct qib_pportdata *ppd;
u64 pwrup;
+ unsigned long flags;
int ret;
u32 le2;
qd = container_of(work, struct qib_qsfp_data, work);
ppd = qd->ppd;
- pwrup = qd->t_insert + msecs_to_jiffies(QSFP_PWR_LAG_MSEC);
+ pwrup = qd->t_insert +
+ msecs_to_jiffies(QSFP_PWR_LAG_MSEC - QSFP_MODPRS_LAG_MSEC);
- /*
- * Some QSFP's not only do not respond until the full power-up
- * time, but may behave badly if we try. So hold off responding
- * to insertion.
- */
- while (1) {
- u64 now = get_jiffies_64();
- if (time_after64(now, pwrup))
- break;
- msleep(20);
- }
- ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
- /*
- * Need to change LE2 back to defaults if we couldn't
- * read the cable type (to handle cable swaps), so do this
- * even on failure to read cable information. We don't
- * get here for QME, so IS_QME check not needed here.
- */
- if (!ret && !ppd->dd->cspec->r1) {
- if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
- le2 = LE2_QME;
- else if (qd->cache.atten[1] >= qib_long_atten &&
- QSFP_IS_CU(qd->cache.tech))
- le2 = LE2_5m;
- else
+ /* Delay for 20 msecs to allow ModPrs resistor to setup */
+ mdelay(QSFP_MODPRS_LAG_MSEC);
+
+ if (!qib_qsfp_mod_present(ppd)) {
+ ppd->cpspec->qsfp_data.modpresent = 0;
+ /* Set the physical link to disabled */
+ qib_set_ib_7322_lstate(ppd, 0,
+ QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
+ spin_lock_irqsave(&ppd->lflags_lock, flags);
+ ppd->lflags &= ~QIBL_LINKV;
+ spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+ } else {
+ /*
+ * Some QSFP's not only do not respond until the full power-up
+ * time, but may behave badly if we try. So hold off responding
+ * to insertion.
+ */
+ while (1) {
+ u64 now = get_jiffies_64();
+ if (time_after64(now, pwrup))
+ break;
+ msleep(20);
+ }
+
+ ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
+
+ /*
+ * Need to change LE2 back to defaults if we couldn't
+ * read the cable type (to handle cable swaps), so do this
+ * even on failure to read cable information. We don't
+ * get here for QME, so IS_QME check not needed here.
+ */
+ if (!ret && !ppd->dd->cspec->r1) {
+ if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
+ le2 = LE2_QME;
+ else if (qd->cache.atten[1] >= qib_long_atten &&
+ QSFP_IS_CU(qd->cache.tech))
+ le2 = LE2_5m;
+ else
+ le2 = LE2_DEFAULT;
+ } else
le2 = LE2_DEFAULT;
- } else
- le2 = LE2_DEFAULT;
- ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
- init_txdds_table(ppd, 0);
+ ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
+ /*
+ * We always change parameteters, since we can choose
+ * values for cables without eeproms, and the cable may have
+ * changed from a cable with full or partial eeprom content
+ * to one with partial or no content.
+ */
+ init_txdds_table(ppd, 0);
+ /* The physical link is being re-enabled only when the
+ * previous state was DISABLED and the VALID bit is not
+ * set. This should only happen when the cable has been
+ * physically pulled. */
+ if (!ppd->cpspec->qsfp_data.modpresent &&
+ (ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
+ ppd->cpspec->qsfp_data.modpresent = 1;
+ qib_set_ib_7322_lstate(ppd, 0,
+ QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
+ spin_lock_irqsave(&ppd->lflags_lock, flags);
+ ppd->lflags |= QIBL_LINKV;
+ spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+ }
+ }
}
/*
@@ -5705,7 +5774,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
/* now change the IBC and serdes, overriding generic */
init_txdds_table(ppd, 1);
/* Re-enable the physical state machine on mezz boards
- * now that the correct settings have been set. */
+ * now that the correct settings have been set.
+ * QSFP boards are handles by the QSFP event handler */
if (IS_QMH(dd) || IS_QME(dd))
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
@@ -6183,6 +6253,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */
dd->rcvegrbufsize = max(mtu, 2048);
+ BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+ dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_7322_tidtemplate(dd);
@@ -6790,6 +6862,10 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,
(i >= ARRAY_SIZE(irq_table) &&
dd->rcd[i - ARRAY_SIZE(irq_table)]))
actual_cnt++;
+ /* reduce by ctxt's < 2 */
+ if (qib_krcvq01_no_msi)
+ actual_cnt -= dd->num_pports;
+
tabsize = actual_cnt;
dd->cspec->msix_entries = kmalloc(tabsize *
sizeof(struct msix_entry), GFP_KERNEL);
@@ -7121,7 +7197,8 @@ static void find_best_ent(struct qib_pportdata *ppd,
}
}
- /* Lookup serdes setting by cable type and attenuation */
+ /* Active cables don't have attenuation so we only set SERDES
+ * settings to account for the attenuation of the board traces. */
if (!override && QSFP_IS_ACTIVE(qd->tech)) {
*sdr_dds = txdds_sdr + ppd->dd->board_atten;
*ddr_dds = txdds_ddr + ppd->dd->board_atten;
@@ -7438,12 +7515,6 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
u32 le_val, rxcaldone;
int chan, chan_done = (1 << SERDES_CHANS) - 1;
- /*
- * Initialize the Tx DDS tables. Also done every QSFP event,
- * for adapters with QSFP
- */
- init_txdds_table(ppd, 0);
-
/* Clear cmode-override, may be set from older driver */
ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14);
@@ -7629,6 +7700,12 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
/* VGA output common mode */
ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
+ /*
+ * Initialize the Tx DDS tables. Also done every QSFP event,
+ * for adapters with QSFP
+ */
+ init_txdds_table(ppd, 0);
+
return 0;
}
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index a01f3fc..9966ec2 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -37,6 +37,7 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/idr.h>
+#include <linux/module.h>
#include "qib.h"
#include "qib_common.h"
@@ -183,6 +184,9 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt)
rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt +
rcd->rcvegrbufs_perchunk - 1) /
rcd->rcvegrbufs_perchunk;
+ BUG_ON(!is_power_of_2(rcd->rcvegrbufs_perchunk));
+ rcd->rcvegrbufs_perchunk_shift =
+ ilog2(rcd->rcvegrbufs_perchunk);
}
return rcd;
}
@@ -398,6 +402,7 @@ static void enable_chip(struct qib_devdata *dd)
if (rcd)
dd->f_rcvctrl(rcd->ppd, rcvmask, i);
}
+ dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
}
static void verify_interrupt(unsigned long opaque)
@@ -581,10 +586,6 @@ int qib_init(struct qib_devdata *dd, int reinit)
continue;
}
- /* let link come up, and enable IBC */
- spin_lock_irqsave(&ppd->lflags_lock, flags);
- ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
- spin_unlock_irqrestore(&ppd->lflags_lock, flags);
portok++;
}
@@ -764,7 +765,6 @@ static void qib_shutdown_device(struct qib_devdata *dd)
dd->f_quiet_serdes(ppd);
}
- qib_update_eeprom_log(dd);
}
/**
diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c
index 8fd19a4..ca6e6cf 100644
--- a/drivers/infiniband/hw/qib/qib_keys.c
+++ b/drivers/infiniband/hw/qib/qib_keys.c
@@ -69,6 +69,10 @@ int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr)
* unrestricted LKEY.
*/
rkt->gen++;
+ /*
+ * bits are capped in qib_verbs.c to insure enough bits
+ * for generation number
+ */
mr->lkey = (r << (32 - ib_qib_lkey_table_size)) |
((((1 << (24 - ib_qib_lkey_table_size)) - 1) & rkt->gen)
<< 8);
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 8fd3df5..dd2ad6d3 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -1007,7 +1007,7 @@ static int set_pkeys(struct qib_devdata *dd, u8 port, u16 *pkeys)
event.event = IB_EVENT_PKEY_CHANGE;
event.device = &dd->verbs_dev.ibdev;
- event.element.port_num = 1;
+ event.element.port_num = port;
ib_dispatch_event(&event);
}
return 0;
@@ -1125,22 +1125,22 @@ static int subn_trap_repress(struct ib_smp *smp, struct ib_device *ibdev,
return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
}
-static int pma_get_classportinfo(struct ib_perf *pmp,
+static int pma_get_classportinfo(struct ib_pma_mad *pmp,
struct ib_device *ibdev)
{
- struct ib_pma_classportinfo *p =
- (struct ib_pma_classportinfo *)pmp->data;
+ struct ib_class_port_info *p =
+ (struct ib_class_port_info *)pmp->data;
struct qib_devdata *dd = dd_from_ibdev(ibdev);
memset(pmp->data, 0, sizeof(pmp->data));
- if (pmp->attr_mod != 0)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0)
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
/* Note that AllPortSelect is not valid */
p->base_version = 1;
p->class_version = 1;
- p->cap_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
+ p->capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
/*
* Set the most significant bit of CM2 to indicate support for
* congestion statistics
@@ -1154,7 +1154,7 @@ static int pma_get_classportinfo(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portsamplescontrol(struct ib_perf *pmp,
+static int pma_get_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -1169,8 +1169,8 @@ static int pma_get_portsamplescontrol(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 || port_select != port) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || port_select != port) {
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
goto bail;
}
spin_lock_irqsave(&ibp->lock, flags);
@@ -1192,7 +1192,7 @@ bail:
return reply((struct ib_smp *) pmp);
}
-static int pma_set_portsamplescontrol(struct ib_perf *pmp,
+static int pma_set_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -1205,8 +1205,8 @@ static int pma_set_portsamplescontrol(struct ib_perf *pmp,
u8 status, xmit_flags;
int ret;
- if (pmp->attr_mod != 0 || p->port_select != port) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || p->port_select != port) {
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -1321,7 +1321,7 @@ static u64 get_cache_hw_sample_counters(struct qib_pportdata *ppd,
return ret;
}
-static int pma_get_portsamplesresult(struct ib_perf *pmp,
+static int pma_get_portsamplesresult(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplesresult *p =
@@ -1360,7 +1360,7 @@ static int pma_get_portsamplesresult(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+static int pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplesresult_ext *p =
@@ -1402,7 +1402,7 @@ static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portcounters(struct ib_perf *pmp,
+static int pma_get_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1436,8 +1436,8 @@ static int pma_get_portcounters(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 || port_select != port)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || port_select != port)
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
if (cntrs.symbol_error_counter > 0xFFFFUL)
p->symbol_error_counter = cpu_to_be16(0xFFFF);
@@ -1472,7 +1472,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,
cntrs.local_link_integrity_errors = 0xFUL;
if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
cntrs.excessive_buffer_overrun_errors = 0xFUL;
- p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1500,7 +1500,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portcounters_cong(struct ib_perf *pmp,
+static int pma_get_portcounters_cong(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
/* Congestion PMA packets start at offset 24 not 64 */
@@ -1510,7 +1510,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
struct qib_ibport *ibp = to_iport(ibdev, port);
struct qib_pportdata *ppd = ppd_from_ibp(ibp);
struct qib_devdata *dd = dd_from_ppd(ppd);
- u32 port_select = be32_to_cpu(pmp->attr_mod) & 0xFF;
+ u32 port_select = be32_to_cpu(pmp->mad_hdr.attr_mod) & 0xFF;
u64 xmit_wait_counter;
unsigned long flags;
@@ -1519,9 +1519,9 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
* SET method ends up calling this anyway.
*/
if (!dd->psxmitwait_supported)
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
if (port_select != port)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
qib_get_counters(ppd, &cntrs);
spin_lock_irqsave(&ppd->ibport_data.lock, flags);
@@ -1603,7 +1603,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
cntrs.local_link_integrity_errors = 0xFUL;
if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
cntrs.excessive_buffer_overrun_errors = 0xFUL;
- p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1613,7 +1613,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
return reply((struct ib_smp *)pmp);
}
-static int pma_get_portcounters_ext(struct ib_perf *pmp,
+static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters_ext *p =
@@ -1626,8 +1626,8 @@ static int pma_get_portcounters_ext(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 || port_select != port) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || port_select != port) {
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
goto bail;
}
@@ -1652,7 +1652,7 @@ bail:
return reply((struct ib_smp *) pmp);
}
-static int pma_set_portcounters(struct ib_perf *pmp,
+static int pma_set_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1715,14 +1715,14 @@ static int pma_set_portcounters(struct ib_perf *pmp,
return pma_get_portcounters(pmp, ibdev, port);
}
-static int pma_set_portcounters_cong(struct ib_perf *pmp,
+static int pma_set_portcounters_cong(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct qib_ibport *ibp = to_iport(ibdev, port);
struct qib_pportdata *ppd = ppd_from_ibp(ibp);
struct qib_devdata *dd = dd_from_ppd(ppd);
struct qib_verbs_counters cntrs;
- u32 counter_select = (be32_to_cpu(pmp->attr_mod) >> 24) & 0xFF;
+ u32 counter_select = (be32_to_cpu(pmp->mad_hdr.attr_mod) >> 24) & 0xFF;
int ret = 0;
unsigned long flags;
@@ -1766,7 +1766,7 @@ static int pma_set_portcounters_cong(struct ib_perf *pmp,
return ret;
}
-static int pma_set_portcounters_ext(struct ib_perf *pmp,
+static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1959,19 +1959,19 @@ static int process_perf(struct ib_device *ibdev, u8 port,
struct ib_mad *in_mad,
struct ib_mad *out_mad)
{
- struct ib_perf *pmp = (struct ib_perf *)out_mad;
+ struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
int ret;
*out_mad = *in_mad;
- if (pmp->class_version != 1) {
- pmp->status |= IB_SMP_UNSUP_VERSION;
+ if (pmp->mad_hdr.class_version != 1) {
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
- switch (pmp->method) {
+ switch (pmp->mad_hdr.method) {
case IB_MGMT_METHOD_GET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_CLASS_PORT_INFO:
ret = pma_get_classportinfo(pmp, ibdev);
goto bail;
@@ -1994,13 +1994,13 @@ static int process_perf(struct ib_device *ibdev, u8 port,
ret = pma_get_portcounters_cong(pmp, ibdev, port);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
case IB_MGMT_METHOD_SET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_PORT_SAMPLES_CONTROL:
ret = pma_set_portsamplescontrol(pmp, ibdev, port);
goto bail;
@@ -2014,7 +2014,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,
ret = pma_set_portcounters_cong(pmp, ibdev, port);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -2030,7 +2030,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METHOD;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;
ret = reply((struct ib_smp *) pmp);
}
diff --git a/drivers/infiniband/hw/qib/qib_mad.h b/drivers/infiniband/hw/qib/qib_mad.h
index 7840ab5..ecc416c 100644
--- a/drivers/infiniband/hw/qib/qib_mad.h
+++ b/drivers/infiniband/hw/qib/qib_mad.h
@@ -32,6 +32,8 @@
* SOFTWARE.
*/
+#include <rdma/ib_pma.h>
+
#define IB_SMP_UNSUP_VERSION cpu_to_be16(0x0004)
#define IB_SMP_UNSUP_METHOD cpu_to_be16(0x0008)
#define IB_SMP_UNSUP_METH_ATTR cpu_to_be16(0x000C)
@@ -180,109 +182,8 @@ struct ib_vl_weight_elem {
#define IB_VLARB_HIGHPRI_0_31 3
#define IB_VLARB_HIGHPRI_32_63 4
-/*
- * PMA class portinfo capability mask bits
- */
-#define IB_PMA_CLASS_CAP_ALLPORTSELECT cpu_to_be16(1 << 8)
-#define IB_PMA_CLASS_CAP_EXT_WIDTH cpu_to_be16(1 << 9)
-#define IB_PMA_CLASS_CAP_XMIT_WAIT cpu_to_be16(1 << 12)
-
-#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001)
-#define IB_PMA_PORT_SAMPLES_CONTROL cpu_to_be16(0x0010)
-#define IB_PMA_PORT_SAMPLES_RESULT cpu_to_be16(0x0011)
-#define IB_PMA_PORT_COUNTERS cpu_to_be16(0x0012)
-#define IB_PMA_PORT_COUNTERS_EXT cpu_to_be16(0x001D)
-#define IB_PMA_PORT_SAMPLES_RESULT_EXT cpu_to_be16(0x001E)
#define IB_PMA_PORT_COUNTERS_CONG cpu_to_be16(0xFF00)
-struct ib_perf {
- u8 base_version;
- u8 mgmt_class;
- u8 class_version;
- u8 method;
- __be16 status;
- __be16 unused;
- __be64 tid;
- __be16 attr_id;
- __be16 resv;
- __be32 attr_mod;
- u8 reserved[40];
- u8 data[192];
-} __attribute__ ((packed));
-
-struct ib_pma_classportinfo {
- u8 base_version;
- u8 class_version;
- __be16 cap_mask;
- u8 reserved[3];
- u8 resp_time_value; /* only lower 5 bits */
- union ib_gid redirect_gid;
- __be32 redirect_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 redirect_lid;
- __be16 redirect_pkey;
- __be32 redirect_qp; /* only lower 24 bits */
- __be32 redirect_qkey;
- union ib_gid trap_gid;
- __be32 trap_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 trap_lid;
- __be16 trap_pkey;
- __be32 trap_hl_qp; /* 8, 24 bits respectively */
- __be32 trap_qkey;
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplescontrol {
- u8 opcode;
- u8 port_select;
- u8 tick;
- u8 counter_width; /* only lower 3 bits */
- __be32 counter_mask0_9; /* 2, 10 * 3, bits */
- __be16 counter_mask10_14; /* 1, 5 * 3, bits */
- u8 sample_mechanisms;
- u8 sample_status; /* only lower 2 bits */
- __be64 option_mask;
- __be64 vendor_mask;
- __be32 sample_start;
- __be32 sample_interval;
- __be16 tag;
- __be16 counter_select[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult_ext {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 extended_width; /* only upper 2 bits */
- __be64 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portcounters {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be16 symbol_error_counter;
- u8 link_error_recovery_counter;
- u8 link_downed_counter;
- __be16 port_rcv_errors;
- __be16 port_rcv_remphys_errors;
- __be16 port_rcv_switch_relay_errors;
- __be16 port_xmit_discards;
- u8 port_xmit_constraint_errors;
- u8 port_rcv_constraint_errors;
- u8 reserved1;
- u8 lli_ebor_errors; /* 4, 4, bits */
- __be16 reserved2;
- __be16 vl15_dropped;
- __be32 port_xmit_data;
- __be32 port_rcv_data;
- __be32 port_xmit_packets;
- __be32 port_rcv_packets;
-} __attribute__ ((packed));
-
struct ib_pma_portcounters_cong {
u8 reserved;
u8 reserved1;
@@ -297,7 +198,7 @@ struct ib_pma_portcounters_cong {
u8 port_xmit_constraint_errors;
u8 port_rcv_constraint_errors;
u8 reserved2;
- u8 lli_ebor_errors; /* 4, 4, bits */
+ u8 link_overrun_errors; /* LocalLink: 7:4, BufferOverrun: 3:0 */
__be16 reserved3;
__be16 vl15_dropped;
__be64 port_xmit_data;
@@ -316,49 +217,11 @@ struct ib_pma_portcounters_cong {
/* number of 4nsec cycles equaling 2secs */
#define QIB_CONG_TIMER_PSINTERVAL 0x1DCD64EC
-#define IB_PMA_SEL_SYMBOL_ERROR cpu_to_be16(0x0001)
-#define IB_PMA_SEL_LINK_ERROR_RECOVERY cpu_to_be16(0x0002)
-#define IB_PMA_SEL_LINK_DOWNED cpu_to_be16(0x0004)
-#define IB_PMA_SEL_PORT_RCV_ERRORS cpu_to_be16(0x0008)
-#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS cpu_to_be16(0x0010)
-#define IB_PMA_SEL_PORT_XMIT_DISCARDS cpu_to_be16(0x0040)
-#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS cpu_to_be16(0x0200)
-#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS cpu_to_be16(0x0400)
-#define IB_PMA_SEL_PORT_VL15_DROPPED cpu_to_be16(0x0800)
-#define IB_PMA_SEL_PORT_XMIT_DATA cpu_to_be16(0x1000)
-#define IB_PMA_SEL_PORT_RCV_DATA cpu_to_be16(0x2000)
-#define IB_PMA_SEL_PORT_XMIT_PACKETS cpu_to_be16(0x4000)
-#define IB_PMA_SEL_PORT_RCV_PACKETS cpu_to_be16(0x8000)
-
#define IB_PMA_SEL_CONG_ALL 0x01
#define IB_PMA_SEL_CONG_PORT_DATA 0x02
#define IB_PMA_SEL_CONG_XMIT 0x04
#define IB_PMA_SEL_CONG_ROUTING 0x08
-struct ib_pma_portcounters_ext {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be32 reserved1;
- __be64 port_xmit_data;
- __be64 port_rcv_data;
- __be64 port_xmit_packets;
- __be64 port_rcv_packets;
- __be64 port_unicast_xmit_packets;
- __be64 port_unicast_rcv_packets;
- __be64 port_multicast_xmit_packets;
- __be64 port_multicast_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SELX_PORT_XMIT_DATA cpu_to_be16(0x0001)
-#define IB_PMA_SELX_PORT_RCV_DATA cpu_to_be16(0x0002)
-#define IB_PMA_SELX_PORT_XMIT_PACKETS cpu_to_be16(0x0004)
-#define IB_PMA_SELX_PORT_RCV_PACKETS cpu_to_be16(0x0008)
-#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS cpu_to_be16(0x0010)
-#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS cpu_to_be16(0x0020)
-#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS cpu_to_be16(0x0040)
-#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS cpu_to_be16(0x0080)
-
/*
* The PortSamplesControl.CounterMasks field is an array of 3 bit fields
* which specify the N'th counter's capabilities. See ch. 16.1.3.2.
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index 891cc2f..97a8bdf 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -35,6 +35,7 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/aer.h>
+#include <linux/module.h>
#include "qib.h"
@@ -255,7 +256,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
u16 linkstat, speed;
int pos = 0, pose, ret = 1;
- pose = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
+ pose = pci_pcie_cap(dd->pcidev);
if (!pose) {
qib_dev_err(dd, "Can't find PCI Express capability!\n");
/* set up something... */
@@ -509,7 +510,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
qib_devinfo(dd->pcidev, "Parent not root\n");
return 1;
}
- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+ ppos = pci_pcie_cap(parent);
if (!ppos)
return 1;
if (parent->vendor != 0x8086)
@@ -578,14 +579,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
qib_devinfo(dd->pcidev, "Parent not root\n");
goto bail;
}
- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+ ppos = pci_pcie_cap(parent);
if (ppos) {
pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps);
pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
} else
goto bail;
/* Find out supported and configured values for endpoint (us) */
- epos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
+ epos = pci_pcie_cap(dd->pcidev);
if (epos) {
pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps);
pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl);
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index e16751f..7e7e16f 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -34,6 +34,7 @@
#include <linux/err.h>
#include <linux/vmalloc.h>
+#include <linux/jhash.h>
#include "qib.h"
@@ -204,6 +205,13 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
}
+static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
+{
+ return jhash_1word(qpn, dev->qp_rnd) &
+ (dev->qp_table_size - 1);
+}
+
+
/*
* Put the QP into the hash table.
* The hash table holds a reference to the QP.
@@ -211,22 +219,23 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
{
struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
unsigned long flags;
+ unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
spin_lock_irqsave(&dev->qpt_lock, flags);
+ atomic_inc(&qp->refcount);
if (qp->ibqp.qp_num == 0)
- ibp->qp0 = qp;
+ rcu_assign_pointer(ibp->qp0, qp);
else if (qp->ibqp.qp_num == 1)
- ibp->qp1 = qp;
+ rcu_assign_pointer(ibp->qp1, qp);
else {
qp->next = dev->qp_table[n];
- dev->qp_table[n] = qp;
+ rcu_assign_pointer(dev->qp_table[n], qp);
}
- atomic_inc(&qp->refcount);
spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ synchronize_rcu();
}
/*
@@ -236,29 +245,32 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
{
struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct qib_qp *q, **qpp;
+ unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
unsigned long flags;
- qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
-
spin_lock_irqsave(&dev->qpt_lock, flags);
if (ibp->qp0 == qp) {
- ibp->qp0 = NULL;
atomic_dec(&qp->refcount);
+ rcu_assign_pointer(ibp->qp0, NULL);
} else if (ibp->qp1 == qp) {
- ibp->qp1 = NULL;
atomic_dec(&qp->refcount);
- } else
+ rcu_assign_pointer(ibp->qp1, NULL);
+ } else {
+ struct qib_qp *q, **qpp;
+
+ qpp = &dev->qp_table[n];
for (; (q = *qpp) != NULL; qpp = &q->next)
if (q == qp) {
- *qpp = qp->next;
- qp->next = NULL;
atomic_dec(&qp->refcount);
+ rcu_assign_pointer(*qpp, qp->next);
+ qp->next = NULL;
break;
}
+ }
spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ synchronize_rcu();
}
/**
@@ -280,21 +292,24 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
if (!qib_mcast_tree_empty(ibp))
qp_inuse++;
- if (ibp->qp0)
+ rcu_read_lock();
+ if (rcu_dereference(ibp->qp0))
qp_inuse++;
- if (ibp->qp1)
+ if (rcu_dereference(ibp->qp1))
qp_inuse++;
+ rcu_read_unlock();
}
spin_lock_irqsave(&dev->qpt_lock, flags);
for (n = 0; n < dev->qp_table_size; n++) {
qp = dev->qp_table[n];
- dev->qp_table[n] = NULL;
+ rcu_assign_pointer(dev->qp_table[n], NULL);
for (; qp; qp = qp->next)
qp_inuse++;
}
spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ synchronize_rcu();
return qp_inuse;
}
@@ -309,25 +324,28 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
*/
struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
{
- struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
- unsigned long flags;
- struct qib_qp *qp;
+ struct qib_qp *qp = NULL;
- spin_lock_irqsave(&dev->qpt_lock, flags);
+ if (unlikely(qpn <= 1)) {
+ rcu_read_lock();
+ if (qpn == 0)
+ qp = rcu_dereference(ibp->qp0);
+ else
+ qp = rcu_dereference(ibp->qp1);
+ } else {
+ struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
+ unsigned n = qpn_hash(dev, qpn);
- if (qpn == 0)
- qp = ibp->qp0;
- else if (qpn == 1)
- qp = ibp->qp1;
- else
- for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
- qp = qp->next)
+ rcu_read_lock();
+ for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
if (qp->ibqp.qp_num == qpn)
break;
+ }
if (qp)
- atomic_inc(&qp->refcount);
+ if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
+ qp = NULL;
- spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ rcu_read_unlock();
return qp;
}
@@ -765,8 +783,10 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
}
}
- if (attr_mask & IB_QP_PATH_MTU)
+ if (attr_mask & IB_QP_PATH_MTU) {
qp->path_mtu = pmtu;
+ qp->pmtu = ib_mtu_enum_to_int(pmtu);
+ }
if (attr_mask & IB_QP_RETRY_CNT) {
qp->s_retry_cnt = attr->retry_cnt;
@@ -781,8 +801,12 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (attr_mask & IB_QP_MIN_RNR_TIMER)
qp->r_min_rnr_timer = attr->min_rnr_timer;
- if (attr_mask & IB_QP_TIMEOUT)
+ if (attr_mask & IB_QP_TIMEOUT) {
qp->timeout = attr->timeout;
+ qp->timeout_jiffies =
+ usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+ 1000UL);
+ }
if (attr_mask & IB_QP_QKEY)
qp->qkey = attr->qkey;
@@ -1013,6 +1037,10 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd,
ret = ERR_PTR(-ENOMEM);
goto bail_swq;
}
+ RCU_INIT_POINTER(qp->next, NULL);
+ qp->timeout_jiffies =
+ usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+ 1000UL);
if (init_attr->srq)
sz = 0;
else {
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.c b/drivers/infiniband/hw/qib/qib_qsfp.c
index 3374a52..fa71b1e 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.c
+++ b/drivers/infiniband/hw/qib/qib_qsfp.c
@@ -273,18 +273,12 @@ int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
int ret;
int idx;
u16 cks;
- u32 mask;
u8 peek[4];
/* ensure sane contents on invalid reads, for cable swaps */
memset(cp, 0, sizeof(*cp));
- mask = QSFP_GPIO_MOD_PRS_N;
- if (ppd->hw_pidx)
- mask <<= QSFP_GPIO_PORT2_SHIFT;
-
- ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
- if (ret & mask) {
+ if (!qib_qsfp_mod_present(ppd)) {
ret = -ENODEV;
goto bail;
}
@@ -444,6 +438,19 @@ const char * const qib_qsfp_devtech[16] = {
static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
+int qib_qsfp_mod_present(struct qib_pportdata *ppd)
+{
+ u32 mask;
+ int ret;
+
+ mask = QSFP_GPIO_MOD_PRS_N <<
+ (ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
+ ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
+
+ return !((ret & mask) >>
+ ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
+}
+
/*
* Initialize structures that control access to QSFP. Called once per port
* on cards that support QSFP.
@@ -452,7 +459,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
void (*fevent)(struct work_struct *))
{
u32 mask, highs;
- int pins;
struct qib_devdata *dd = qd->ppd->dd;
@@ -474,19 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
udelay(20); /* Generous RST dwell */
dd->f_gpio_mod(dd, mask, mask, mask);
- /* Spec says module can take up to two seconds! */
- mask = QSFP_GPIO_MOD_PRS_N;
- if (qd->ppd->hw_pidx)
- mask <<= QSFP_GPIO_PORT2_SHIFT;
-
- /* Do not try to wait here. Better to let event handle it */
- pins = dd->f_gpio_mod(dd, 0, 0, 0);
- if (pins & mask)
- goto bail;
- /* We see a module, but it may be unwise to look yet. Just schedule */
- qd->t_insert = get_jiffies_64();
- queue_work(ib_wq, &qd->work);
-bail:
return;
}
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.h b/drivers/infiniband/hw/qib/qib_qsfp.h
index c109bbd..46002a9 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.h
+++ b/drivers/infiniband/hw/qib/qib_qsfp.h
@@ -34,6 +34,7 @@
#define QSFP_DEV 0xA0
#define QSFP_PWR_LAG_MSEC 2000
+#define QSFP_MODPRS_LAG_MSEC 20
/*
* Below are masks for various QSFP signals, for Port 1.
@@ -177,10 +178,12 @@ struct qib_qsfp_data {
struct work_struct work;
struct qib_qsfp_cache cache;
u64 t_insert;
+ u8 modpresent;
};
extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
struct qib_qsfp_cache *cp);
+extern int qib_qsfp_mod_present(struct qib_pportdata *ppd);
extern void qib_qsfp_init(struct qib_qsfp_data *qd,
void (*fevent)(struct work_struct *));
extern void qib_qsfp_deinit(struct qib_qsfp_data *qd);
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index eca0c41..894afac 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -59,8 +59,7 @@ static void start_timer(struct qib_qp *qp)
qp->s_flags |= QIB_S_TIMER;
qp->s_timer.function = rc_timeout;
/* 4.096 usec. * (1 << qp->timeout) */
- qp->s_timer.expires = jiffies +
- usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL);
+ qp->s_timer.expires = jiffies + qp->timeout_jiffies;
add_timer(&qp->s_timer);
}
@@ -239,7 +238,7 @@ int qib_make_rc_req(struct qib_qp *qp)
u32 len;
u32 bth0;
u32 bth2;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
char newreq;
unsigned long flags;
int ret = 0;
@@ -272,13 +271,9 @@ int qib_make_rc_req(struct qib_qp *qp)
goto bail;
}
wqe = get_swqe_ptr(qp, qp->s_last);
- while (qp->s_last != qp->s_acked) {
- qib_send_complete(qp, wqe, IB_WC_SUCCESS);
- if (++qp->s_last >= qp->s_size)
- qp->s_last = 0;
- wqe = get_swqe_ptr(qp, qp->s_last);
- }
- qib_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);
+ qib_send_complete(qp, wqe, qp->s_last != qp->s_acked ?
+ IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR);
+ /* will get called again */
goto done;
}
@@ -1519,9 +1514,7 @@ read_middle:
* 4.096 usec. * (1 << qp->timeout)
*/
qp->s_flags |= QIB_S_TIMER;
- mod_timer(&qp->s_timer, jiffies +
- usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
- 1000UL));
+ mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies);
if (qp->s_flags & QIB_S_WAIT_ACK) {
qp->s_flags &= ~QIB_S_WAIT_ACK;
qib_schedule_send(qp);
@@ -1732,7 +1725,7 @@ static int qib_rc_rcv_error(struct qib_other_headers *ohdr,
* same request.
*/
offset = ((psn - e->psn) & QIB_PSN_MASK) *
- ib_mtu_enum_to_int(qp->path_mtu);
+ qp->pmtu;
len = be32_to_cpu(reth->length);
if (unlikely(offset + len != e->rdma_sge.sge_length))
goto unlock_done;
@@ -1876,7 +1869,7 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
u32 psn;
u32 pad;
struct ib_wc wc;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
int diff;
struct ib_reth *reth;
unsigned long flags;
@@ -1892,10 +1885,8 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
}
opcode = be32_to_cpu(ohdr->bth[0]);
- spin_lock_irqsave(&qp->s_lock, flags);
if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
- goto sunlock;
- spin_unlock_irqrestore(&qp->s_lock, flags);
+ return;
psn = be32_to_cpu(ohdr->bth[2]);
opcode >>= 24;
@@ -1955,8 +1946,6 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
break;
}
- memset(&wc, 0, sizeof wc);
-
if (qp->state == IB_QPS_RTR && !(qp->r_flags & QIB_R_COMM_EST)) {
qp->r_flags |= QIB_R_COMM_EST;
if (qp->ibqp.event_handler) {
@@ -2009,16 +1998,19 @@ send_middle:
goto rnr_nak;
qp->r_rcv_len = 0;
if (opcode == OP(SEND_ONLY))
- goto send_last;
- /* FALLTHROUGH */
+ goto no_immediate_data;
+ /* FALLTHROUGH for SEND_ONLY_WITH_IMMEDIATE */
case OP(SEND_LAST_WITH_IMMEDIATE):
send_last_imm:
wc.ex.imm_data = ohdr->u.imm_data;
hdrsize += 4;
wc.wc_flags = IB_WC_WITH_IMM;
- /* FALLTHROUGH */
+ goto send_last;
case OP(SEND_LAST):
case OP(RDMA_WRITE_LAST):
+no_immediate_data:
+ wc.wc_flags = 0;
+ wc.ex.imm_data = 0;
send_last:
/* Get the number of bytes the message was padded by. */
pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -2051,6 +2043,12 @@ send_last:
wc.src_qp = qp->remote_qpn;
wc.slid = qp->remote_ah_attr.dlid;
wc.sl = qp->remote_ah_attr.sl;
+ /* zero fields that are N/A */
+ wc.vendor_err = 0;
+ wc.pkey_index = 0;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ wc.csum_ok = 0;
/* Signal completion event if the solicited bit is set. */
qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
(ohdr->bth[0] &
@@ -2089,7 +2087,7 @@ send_last:
if (opcode == OP(RDMA_WRITE_FIRST))
goto send_middle;
else if (opcode == OP(RDMA_WRITE_ONLY))
- goto send_last;
+ goto no_immediate_data;
ret = qib_get_rwqe(qp, 1);
if (ret < 0)
goto nack_op_err;
diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index eb78d93..b4b37e4 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -260,12 +260,15 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
/*
*
- * This should be called with the QP s_lock held.
+ * This should be called with the QP r_lock held.
+ *
+ * The s_lock will be acquired around the qib_migrate_qp() call.
*/
int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
int has_grh, struct qib_qp *qp, u32 bth0)
{
__be64 guid;
+ unsigned long flags;
if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
if (!has_grh) {
@@ -295,7 +298,9 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid ||
ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num)
goto err;
+ spin_lock_irqsave(&qp->s_lock, flags);
qib_migrate_qp(qp);
+ spin_unlock_irqrestore(&qp->s_lock, flags);
} else {
if (!has_grh) {
if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c
index e9f9f8b..de1a4b2 100644
--- a/drivers/infiniband/hw/qib/qib_sd7220.c
+++ b/drivers/infiniband/hw/qib/qib_sd7220.c
@@ -38,6 +38,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include "qib.h"
diff --git a/drivers/infiniband/hw/qib/qib_sdma.c b/drivers/infiniband/hw/qib/qib_sdma.c
index cad4449..12a9604 100644
--- a/drivers/infiniband/hw/qib/qib_sdma.c
+++ b/drivers/infiniband/hw/qib/qib_sdma.c
@@ -32,6 +32,7 @@
#include <linux/spinlock.h>
#include <linux/netdevice.h>
+#include <linux/moduleparam.h>
#include "qib.h"
#include "qib_common.h"
diff --git a/drivers/infiniband/hw/qib/qib_srq.c b/drivers/infiniband/hw/qib/qib_srq.c
index c3ec8ef..d623593 100644
--- a/drivers/infiniband/hw/qib/qib_srq.c
+++ b/drivers/infiniband/hw/qib/qib_srq.c
@@ -107,6 +107,11 @@ struct ib_srq *qib_create_srq(struct ib_pd *ibpd,
u32 sz;
struct ib_srq *ret;
+ if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+ ret = ERR_PTR(-ENOSYS);
+ goto done;
+ }
+
if (srq_init_attr->attr.max_sge == 0 ||
srq_init_attr->attr.max_sge > ib_qib_max_srq_sges ||
srq_init_attr->attr.max_wr == 0 ||
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index d50a33f..c97224a 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -507,6 +507,17 @@ static ssize_t show_nctxts(struct device *device,
dd->first_user_ctxt);
}
+static ssize_t show_nfreectxts(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct qib_ibdev *dev =
+ container_of(device, struct qib_ibdev, ibdev.dev);
+ struct qib_devdata *dd = dd_from_dev(dev);
+
+ /* Return the number of free user ports (contexts) available. */
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
+}
+
static ssize_t show_serial(struct device *device,
struct device_attribute *attr, char *buf)
{
@@ -539,28 +550,6 @@ bail:
return ret < 0 ? ret : count;
}
-static ssize_t show_logged_errs(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- struct qib_ibdev *dev =
- container_of(device, struct qib_ibdev, ibdev.dev);
- struct qib_devdata *dd = dd_from_dev(dev);
- int idx, count;
-
- /* force consistency with actual EEPROM */
- if (qib_update_eeprom_log(dd) != 0)
- return -ENXIO;
-
- count = 0;
- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
- count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
- dd->eep_st_errs[idx],
- idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' ');
- }
-
- return count;
-}
-
/*
* Dump tempsense regs. in decimal, to ease shell-scripts.
*/
@@ -604,9 +593,9 @@ static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
+static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
-static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
@@ -617,9 +606,9 @@ static struct device_attribute *qib_attributes[] = {
&dev_attr_board_id,
&dev_attr_version,
&dev_attr_nctxts,
+ &dev_attr_nfreectxts,
&dev_attr_serial,
&dev_attr_boardversion,
- &dev_attr_logged_errors,
&dev_attr_tempsense,
&dev_attr_localbus_info,
&dev_attr_chip_reset,
diff --git a/drivers/infiniband/hw/qib/qib_tx.c b/drivers/infiniband/hw/qib/qib_tx.c
index 7f36454..1bf626c 100644
--- a/drivers/infiniband/hw/qib/qib_tx.c
+++ b/drivers/infiniband/hw/qib/qib_tx.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
#include "qib.h"
diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c
index 32ccf3c..847e7af 100644
--- a/drivers/infiniband/hw/qib/qib_uc.c
+++ b/drivers/infiniband/hw/qib/qib_uc.c
@@ -51,7 +51,7 @@ int qib_make_uc_req(struct qib_qp *qp)
u32 hwords;
u32 bth0;
u32 len;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
int ret = 0;
spin_lock_irqsave(&qp->s_lock, flags);
@@ -243,13 +243,12 @@ void qib_uc_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr,
int has_grh, void *data, u32 tlen, struct qib_qp *qp)
{
struct qib_other_headers *ohdr;
- unsigned long flags;
u32 opcode;
u32 hdrsize;
u32 psn;
u32 pad;
struct ib_wc wc;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
struct ib_reth *reth;
int ret;
@@ -263,14 +262,11 @@ void qib_uc_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr,
}
opcode = be32_to_cpu(ohdr->bth[0]);
- spin_lock_irqsave(&qp->s_lock, flags);
if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
- goto sunlock;
- spin_unlock_irqrestore(&qp->s_lock, flags);
+ return;
psn = be32_to_cpu(ohdr->bth[2]);
opcode >>= 24;
- memset(&wc, 0, sizeof wc);
/* Compare the PSN verses the expected PSN. */
if (unlikely(qib_cmp24(psn, qp->r_psn) != 0)) {
@@ -370,7 +366,7 @@ send_first:
}
qp->r_rcv_len = 0;
if (opcode == OP(SEND_ONLY))
- goto send_last;
+ goto no_immediate_data;
else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
goto send_last_imm;
/* FALLTHROUGH */
@@ -389,8 +385,11 @@ send_last_imm:
wc.ex.imm_data = ohdr->u.imm_data;
hdrsize += 4;
wc.wc_flags = IB_WC_WITH_IMM;
- /* FALLTHROUGH */
+ goto send_last;
case OP(SEND_LAST):
+no_immediate_data:
+ wc.ex.imm_data = 0;
+ wc.wc_flags = 0;
send_last:
/* Get the number of bytes the message was padded by. */
pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -418,6 +417,12 @@ last_imm:
wc.src_qp = qp->remote_qpn;
wc.slid = qp->remote_ah_attr.dlid;
wc.sl = qp->remote_ah_attr.sl;
+ /* zero fields that are N/A */
+ wc.vendor_err = 0;
+ wc.pkey_index = 0;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ wc.csum_ok = 0;
/* Signal completion event if the solicited bit is set. */
qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
(ohdr->bth[0] &
@@ -546,6 +551,4 @@ op_err:
qib_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
return;
-sunlock:
- spin_unlock_irqrestore(&qp->s_lock, flags);
}
diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c
index 828609f..c0d93d4 100644
--- a/drivers/infiniband/hw/qib/qib_ud.c
+++ b/drivers/infiniband/hw/qib/qib_ud.c
@@ -57,13 +57,20 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe)
struct qib_sge *sge;
struct ib_wc wc;
u32 length;
+ enum ib_qp_type sqptype, dqptype;
qp = qib_lookup_qpn(ibp, swqe->wr.wr.ud.remote_qpn);
if (!qp) {
ibp->n_pkt_drops++;
return;
}
- if (qp->ibqp.qp_type != sqp->ibqp.qp_type ||
+
+ sqptype = sqp->ibqp.qp_type == IB_QPT_GSI ?
+ IB_QPT_UD : sqp->ibqp.qp_type;
+ dqptype = qp->ibqp.qp_type == IB_QPT_GSI ?
+ IB_QPT_UD : qp->ibqp.qp_type;
+
+ if (dqptype != sqptype ||
!(ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK)) {
ibp->n_pkt_drops++;
goto drop;
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index 7689e49..2bc1d2b 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -74,7 +74,7 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
goto bail_release;
}
- current->mm->locked_vm += num_pages;
+ current->mm->pinned_vm += num_pages;
ret = 0;
goto bail;
@@ -151,7 +151,7 @@ void qib_release_user_pages(struct page **p, size_t num_pages)
__qib_release_user_pages(p, num_pages, 1);
if (current->mm) {
- current->mm->locked_vm -= num_pages;
+ current->mm->pinned_vm -= num_pages;
up_write(&current->mm->mmap_sem);
}
}
diff --git a/drivers/infiniband/hw/qib/qib_user_sdma.c b/drivers/infiniband/hw/qib/qib_user_sdma.c
index 8244208..573b460 100644
--- a/drivers/infiniband/hw/qib/qib_user_sdma.c
+++ b/drivers/infiniband/hw/qib/qib_user_sdma.c
@@ -284,8 +284,7 @@ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd,
int j;
int ret;
- ret = get_user_pages(current, current->mm, addr,
- npages, 0, 1, pages, NULL);
+ ret = get_user_pages_fast(addr, npages, 0, pages);
if (ret != npages) {
int i;
@@ -830,10 +829,7 @@ int qib_user_sdma_writev(struct qib_ctxtdata *rcd,
while (dim) {
const int mxp = 8;
- down_write(&current->mm->mmap_sem);
ret = qib_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp);
- up_write(&current->mm->mmap_sem);
-
if (ret <= 0)
goto done_unlock;
else {
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index 9fab404..c51a6f9 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -35,14 +35,17 @@
#include <rdma/ib_mad.h>
#include <rdma/ib_user_verbs.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/utsname.h>
#include <linux/rculist.h>
#include <linux/mm.h>
+#include <linux/random.h>
+#include <linux/vmalloc.h>
#include "qib.h"
#include "qib_common.h"
-static unsigned int ib_qib_qp_table_size = 251;
+static unsigned int ib_qib_qp_table_size = 256;
module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO);
MODULE_PARM_DESC(qp_table_size, "QP table size");
@@ -659,17 +662,25 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
if (atomic_dec_return(&mcast->refcount) <= 1)
wake_up(&mcast->wait);
} else {
- qp = qib_lookup_qpn(ibp, qp_num);
- if (!qp)
- goto drop;
+ if (rcd->lookaside_qp) {
+ if (rcd->lookaside_qpn != qp_num) {
+ if (atomic_dec_and_test(
+ &rcd->lookaside_qp->refcount))
+ wake_up(
+ &rcd->lookaside_qp->wait);
+ rcd->lookaside_qp = NULL;
+ }
+ }
+ if (!rcd->lookaside_qp) {
+ qp = qib_lookup_qpn(ibp, qp_num);
+ if (!qp)
+ goto drop;
+ rcd->lookaside_qp = qp;
+ rcd->lookaside_qpn = qp_num;
+ } else
+ qp = rcd->lookaside_qp;
ibp->n_unicast_rcv++;
qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);
- /*
- * Notify qib_destroy_qp() if it is waiting
- * for us to finish.
- */
- if (atomic_dec_and_test(&qp->refcount))
- wake_up(&qp->wait);
}
return;
@@ -1974,6 +1985,8 @@ static void init_ibport(struct qib_pportdata *ppd)
ibp->z_excessive_buffer_overrun_errors =
cntrs.excessive_buffer_overrun_errors;
ibp->z_vl15_dropped = cntrs.vl15_dropped;
+ RCU_INIT_POINTER(ibp->qp0, NULL);
+ RCU_INIT_POINTER(ibp->qp1, NULL);
}
/**
@@ -1990,12 +2003,15 @@ int qib_register_ib_device(struct qib_devdata *dd)
int ret;
dev->qp_table_size = ib_qib_qp_table_size;
- dev->qp_table = kzalloc(dev->qp_table_size * sizeof *dev->qp_table,
+ get_random_bytes(&dev->qp_rnd, sizeof(dev->qp_rnd));
+ dev->qp_table = kmalloc(dev->qp_table_size * sizeof *dev->qp_table,
GFP_KERNEL);
if (!dev->qp_table) {
ret = -ENOMEM;
goto err_qpt;
}
+ for (i = 0; i < dev->qp_table_size; i++)
+ RCU_INIT_POINTER(dev->qp_table[i], NULL);
for (i = 0; i < dd->num_pports; i++)
init_ibport(ppd + i);
@@ -2020,10 +2036,16 @@ int qib_register_ib_device(struct qib_devdata *dd)
* the LKEY). The remaining bits act as a generation number or tag.
*/
spin_lock_init(&dev->lk_table.lock);
+ /* insure generation is at least 4 bits see keys.c */
+ if (ib_qib_lkey_table_size > MAX_LKEY_TABLE_BITS) {
+ qib_dev_warn(dd, "lkey bits %u too large, reduced to %u\n",
+ ib_qib_lkey_table_size, MAX_LKEY_TABLE_BITS);
+ ib_qib_lkey_table_size = MAX_LKEY_TABLE_BITS;
+ }
dev->lk_table.max = 1 << ib_qib_lkey_table_size;
lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
dev->lk_table.table = (struct qib_mregion **)
- __get_free_pages(GFP_KERNEL, get_order(lk_tab_size));
+ vmalloc(lk_tab_size);
if (dev->lk_table.table == NULL) {
ret = -ENOMEM;
goto err_lk;
@@ -2193,7 +2215,7 @@ err_tx:
sizeof(struct qib_pio_header),
dev->pio_hdrs, dev->pio_hdrs_phys);
err_hdrs:
- free_pages((unsigned long) dev->lk_table.table, get_order(lk_tab_size));
+ vfree(dev->lk_table.table);
err_lk:
kfree(dev->qp_table);
err_qpt:
@@ -2247,7 +2269,6 @@ void qib_unregister_ib_device(struct qib_devdata *dd)
sizeof(struct qib_pio_header),
dev->pio_hdrs, dev->pio_hdrs_phys);
lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
- free_pages((unsigned long) dev->lk_table.table,
- get_order(lk_tab_size));
+ vfree(dev->lk_table.table);
kfree(dev->qp_table);
}
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index 95e5b47..66f7f62 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -485,6 +485,7 @@ struct qib_qp {
u8 alt_timeout; /* Alternate path timeout for this QP */
u8 port_num;
enum ib_mtu path_mtu;
+ u32 pmtu; /* decoded from path_mtu */
u32 remote_qpn;
u32 qkey; /* QKEY for this QP (for UD or RD) */
u32 s_size; /* send work queue size */
@@ -495,6 +496,7 @@ struct qib_qp {
u32 s_last; /* last completed entry */
u32 s_ssn; /* SSN of tail entry */
u32 s_lsn; /* limit sequence number (credit) */
+ unsigned long timeout_jiffies; /* computed from timeout */
struct qib_swqe *s_wq; /* send work queue */
struct qib_swqe *s_wqe;
struct qib_rq r_rq; /* receive work queue */
@@ -620,6 +622,8 @@ struct qib_qpn_table {
struct qpn_map map[QPNMAP_ENTRIES];
};
+#define MAX_LKEY_TABLE_BITS 23
+
struct qib_lkey_table {
spinlock_t lock; /* protect changes in this struct */
u32 next; /* next unused index (speeds search) */
@@ -723,7 +727,8 @@ struct qib_ibdev {
dma_addr_t pio_hdrs_phys;
/* list of QPs waiting for RNR timer */
spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
- unsigned qp_table_size; /* size of the hash table */
+ u32 qp_table_size; /* size of the hash table */
+ u32 qp_rnd; /* random bytes for hash */
spinlock_t qpt_lock;
u32 n_piowait;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 936804e..86df632 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -46,7 +46,7 @@
#include <net/neighbour.h>
#include <net/sch_generic.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 073acdf..3767853 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
#include "ipoib.h"
@@ -84,7 +85,7 @@ static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, int frags,
ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
for (i = 0; i < frags; ++i)
- ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_page(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
}
static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
@@ -169,7 +170,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
goto partial_error;
skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
- mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
+ mapping[i + 1] = ib_dma_map_page(priv->ca, page,
0, PAGE_SIZE, DMA_FROM_DEVICE);
if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
goto partial_error;
@@ -183,7 +184,7 @@ partial_error:
ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
for (; i > 0; --i)
- ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_page(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
return NULL;
@@ -537,12 +538,13 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
if (length == 0) {
/* don't need this page */
- skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
+ skb_fill_page_desc(toskb, i, skb_frag_page(frag),
+ 0, PAGE_SIZE);
--skb_shinfo(skb)->nr_frags;
} else {
size = min(length, (unsigned) PAGE_SIZE);
- frag->size = size;
+ skb_frag_size_set(frag, size);
skb->data_len += size;
skb->truesize += size;
skb->len += size;
@@ -1500,6 +1502,7 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_srq_init_attr srq_init_attr = {
+ .srq_type = IB_SRQT_BASIC,
.attr = {
.max_wr = ipoib_recvq_size,
.max_sge = max_sge
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 86eae22..5006185 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -37,6 +37,7 @@
struct file_operations;
#include <linux/debugfs.h>
+#include <linux/export.h>
#include "ipoib.h"
@@ -212,16 +213,15 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
gid_buf, path.pathrec.dlid ? "yes" : "no");
if (path.pathrec.dlid) {
- rate = ib_rate_to_mult(path.pathrec.rate) * 25;
+ rate = ib_rate_to_mbps(path.pathrec.rate);
seq_printf(file,
" DLID: 0x%04x\n"
" SL: %12d\n"
- " rate: %*d%s Gb/sec\n",
+ " rate: %8d.%d Gb/sec\n",
be16_to_cpu(path.pathrec.dlid),
path.pathrec.sl,
- 10 - ((rate % 10) ? 2 : 0),
- rate / 10, rate % 10 ? ".5" : "");
+ rate / 1000, rate % 1000);
}
seq_putc(file, '\n');
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 81ae61d..4115be5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -34,6 +34,7 @@
*/
#include <linux/delay.h>
+#include <linux/moduleparam.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
@@ -56,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
struct ib_pd *pd, struct ib_ah_attr *attr)
{
struct ipoib_ah *ah;
+ struct ib_ah *vah;
ah = kmalloc(sizeof *ah, GFP_KERNEL);
if (!ah)
- return NULL;
+ return ERR_PTR(-ENOMEM);
ah->dev = dev;
ah->last_send = 0;
kref_init(&ah->ref);
- ah->ah = ib_create_ah(pd, attr);
- if (IS_ERR(ah->ah)) {
+ vah = ib_create_ah(pd, attr);
+ if (IS_ERR(vah)) {
kfree(ah);
- ah = NULL;
- } else
+ ah = (struct ipoib_ah *)vah;
+ } else {
+ ah->ah = vah;
ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
+ }
return ah;
}
@@ -117,7 +121,7 @@ static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
size = length - IPOIB_UD_HEAD_SIZE;
- frag->size = size;
+ skb_frag_size_set(frag, size);
skb->data_len += size;
skb->truesize += size;
} else
@@ -182,7 +186,7 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
goto partial_error;
skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
mapping[1] =
- ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
+ ib_dma_map_page(priv->ca, page,
0, PAGE_SIZE, DMA_FROM_DEVICE);
if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
goto partial_error;
@@ -322,9 +326,10 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
off = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- mapping[i + off] = ib_dma_map_page(ca, frag->page,
- frag->page_offset, frag->size,
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ mapping[i + off] = ib_dma_map_page(ca,
+ skb_frag_page(frag),
+ frag->page_offset, skb_frag_size(frag),
DMA_TO_DEVICE);
if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
goto partial_error;
@@ -333,8 +338,9 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
partial_error:
for (; i > 0; --i) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
- ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE);
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+
+ ib_dma_unmap_page(ca, mapping[i - !off], skb_frag_size(frag), DMA_TO_DEVICE);
}
if (off)
@@ -358,8 +364,9 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca,
off = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- ib_dma_unmap_page(ca, mapping[i + off], frag->size,
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag),
DMA_TO_DEVICE);
}
}
@@ -509,7 +516,7 @@ static inline int post_send(struct ipoib_dev_priv *priv,
for (i = 0; i < nr_frags; ++i) {
priv->tx_sge[i + off].addr = mapping[i + off];
- priv->tx_sge[i + off].length = frags[i].size;
+ priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
}
priv->tx_wr.num_sge = nr_frags + off;
priv->tx_wr.wr_id = wr_id;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 6ea9600..1740b82 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -432,7 +432,7 @@ static void path_rec_completion(int status,
spin_lock_irqsave(&priv->lock, flags);
- if (ah) {
+ if (!IS_ERR_OR_NULL(ah)) {
path->pathrec = *pathrec;
old_ah = path->ah;
@@ -989,7 +989,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
.ndo_fix_features = ipoib_fix_features,
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
- .ndo_set_multicast_list = ipoib_set_mcast_list,
+ .ndo_set_rx_mode = ipoib_set_mcast_list,
.ndo_neigh_setup = ipoib_neigh_setup_dev,
};
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index fc04594..80799c0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -34,6 +34,7 @@
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
+#include <linux/moduleparam.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/igmp.h>
@@ -248,8 +249,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
av.grh.dgid = mcast->mcmember.mgid;
ah = ipoib_create_ah(dev, priv->pd, &av);
- if (!ah) {
- ipoib_warn(priv, "ib_address_create failed\n");
+ if (IS_ERR(ah)) {
+ ipoib_warn(priv, "ib_address_create failed %ld\n",
+ -PTR_ERR(ah));
+ /* use original error */
+ return PTR_ERR(ah);
} else {
spin_lock_irq(&priv->lock);
mcast->ah = ah;
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index f8f5758..d5f3b69 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -57,6 +57,7 @@
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <net/sock.h>
@@ -101,13 +102,17 @@ iscsi_iser_recv(struct iscsi_conn *conn,
/* verify PDU length */
datalen = ntoh24(hdr->dlength);
- if (datalen != rx_data_len) {
- printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n",
- datalen, rx_data_len);
+ if (datalen > rx_data_len || (datalen + 4) < rx_data_len) {
+ iser_err("wrong datalen %d (hdr), %d (IB)\n",
+ datalen, rx_data_len);
rc = ISCSI_ERR_DATALEN;
goto error;
}
+ if (datalen != rx_data_len)
+ iser_dbg("aligned datalen (%d) hdr, %d (IB)\n",
+ datalen, rx_data_len);
+
/* read AHS */
ahslen = hdr->hlength * 4;
@@ -147,7 +152,6 @@ int iser_initialize_task_headers(struct iscsi_task *task,
tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
tx_desc->tx_sg[0].lkey = device->mr->lkey;
- iser_task->headers_initialized = 1;
iser_task->iser_conn = iser_conn;
return 0;
}
@@ -162,8 +166,7 @@ iscsi_iser_task_init(struct iscsi_task *task)
{
struct iscsi_iser_task *iser_task = task->dd_data;
- if (!iser_task->headers_initialized)
- if (iser_initialize_task_headers(task, &iser_task->desc))
+ if (iser_initialize_task_headers(task, &iser_task->desc))
return -ENOMEM;
/* mgmt task */
@@ -274,6 +277,13 @@ iscsi_iser_task_xmit(struct iscsi_task *task)
static void iscsi_iser_cleanup_task(struct iscsi_task *task)
{
struct iscsi_iser_task *iser_task = task->dd_data;
+ struct iser_tx_desc *tx_desc = &iser_task->desc;
+
+ struct iscsi_iser_conn *iser_conn = task->conn->dd_data;
+ struct iser_device *device = iser_conn->ib_conn->device;
+
+ ib_dma_unmap_single(device->ib_device,
+ tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
/* mgmt tasks do not need special cleanup */
if (!task->sc)
@@ -618,6 +628,59 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
iser_conn_terminate(ib_conn);
}
+static mode_t iser_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
static struct scsi_host_template iscsi_iser_sht = {
.module = THIS_MODULE,
.name = "iSCSI Initiator over iSER, v." DRV_VER,
@@ -639,32 +702,6 @@ static struct iscsi_transport iscsi_iser_transport = {
.owner = THIS_MODULE,
.name = "iser",
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS |
- ISCSI_HOST_NETDEV_NAME |
- ISCSI_HOST_INITIATOR_NAME,
/* session management */
.create_session = iscsi_iser_session_create,
.destroy_session = iscsi_iser_session_destroy,
@@ -672,6 +709,7 @@ static struct iscsi_transport iscsi_iser_transport = {
.create_conn = iscsi_iser_conn_create,
.bind_conn = iscsi_iser_conn_bind,
.destroy_conn = iscsi_iser_conn_destroy,
+ .attr_is_visible = iser_attr_is_visible,
.set_param = iscsi_iser_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_ep_param = iscsi_iser_get_ep_param,
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 634aef0..296be43 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -45,6 +45,7 @@
#include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h>
+#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/list.h>
@@ -88,7 +89,7 @@
} while (0)
#define SHIFT_4K 12
-#define SIZE_4K (1UL << SHIFT_4K)
+#define SIZE_4K (1ULL << SHIFT_4K)
#define MASK_4K (~(SIZE_4K-1))
/* support up to 512KB in one RDMA */
@@ -256,7 +257,8 @@ struct iser_conn {
struct list_head conn_list; /* entry in ig conn list */
char *login_buf;
- u64 login_dma;
+ char *login_req_buf, *login_resp_buf;
+ u64 login_req_dma, login_resp_dma;
unsigned int rx_desc_head;
struct iser_rx_desc *rx_descs;
struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX];
@@ -276,7 +278,6 @@ struct iscsi_iser_task {
struct iser_regd_buf rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
struct iser_data_buf data[ISER_DIRS_NUM]; /* orig. data des*/
struct iser_data_buf data_copy[ISER_DIRS_NUM];/* contig. copy */
- int headers_initialized;
};
struct iser_page_vec {
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index eb1ee6f..738a149 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -221,8 +221,14 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn)
struct iser_device *device = ib_conn->device;
if (ib_conn->login_buf) {
- ib_dma_unmap_single(device->ib_device, ib_conn->login_dma,
- ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+ if (ib_conn->login_req_dma)
+ ib_dma_unmap_single(device->ib_device,
+ ib_conn->login_req_dma,
+ ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+ if (ib_conn->login_resp_dma)
+ ib_dma_unmap_single(device->ib_device,
+ ib_conn->login_resp_dma,
+ ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
kfree(ib_conn->login_buf);
}
@@ -272,7 +278,7 @@ int iser_send_command(struct iscsi_conn *conn,
unsigned long edtl;
int err;
struct iser_data_buf *data_buf;
- struct iscsi_cmd *hdr = (struct iscsi_cmd *)task->hdr;
+ struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
struct scsi_cmnd *sc = task->sc;
struct iser_tx_desc *tx_desc = &iser_task->desc;
@@ -395,6 +401,7 @@ int iser_send_control(struct iscsi_conn *conn,
unsigned long data_seg_len;
int err = 0;
struct iser_device *device;
+ struct iser_conn *ib_conn = iser_conn->ib_conn;
/* build the tx desc regd header and add it to the tx desc dto */
mdesc->type = ISCSI_TX_CONTROL;
@@ -410,10 +417,20 @@ int iser_send_control(struct iscsi_conn *conn,
iser_err("data present on non login task!!!\n");
goto send_control_error;
}
- memcpy(iser_conn->ib_conn->login_buf, task->data,
+
+ ib_dma_sync_single_for_cpu(device->ib_device,
+ ib_conn->login_req_dma, task->data_count,
+ DMA_TO_DEVICE);
+
+ memcpy(iser_conn->ib_conn->login_req_buf, task->data,
task->data_count);
- tx_dsg->addr = iser_conn->ib_conn->login_dma;
- tx_dsg->length = data_seg_len;
+
+ ib_dma_sync_single_for_device(device->ib_device,
+ ib_conn->login_req_dma, task->data_count,
+ DMA_TO_DEVICE);
+
+ tx_dsg->addr = iser_conn->ib_conn->login_req_dma;
+ tx_dsg->length = task->data_count;
tx_dsg->lkey = device->mr->lkey;
mdesc->num_sge = 2;
}
@@ -449,8 +466,8 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
int rx_buflen, outstanding, count, err;
/* differentiate between login to all other PDUs */
- if ((char *)rx_desc == ib_conn->login_buf) {
- rx_dma = ib_conn->login_dma;
+ if ((char *)rx_desc == ib_conn->login_resp_buf) {
+ rx_dma = ib_conn->login_resp_dma;
rx_buflen = ISER_RX_LOGIN_SIZE;
} else {
rx_dma = rx_desc->dma_addr;
@@ -477,7 +494,7 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
* for the posted rx bufs refcount to become zero handles everything */
conn->ib_conn->post_recv_buf_count--;
- if (rx_dma == ib_conn->login_dma)
+ if (rx_dma == ib_conn->login_resp_dma)
return;
outstanding = ib_conn->post_recv_buf_count;
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index ede1475..e28877c 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -155,20 +155,39 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
{
struct iser_device *device;
struct ib_qp_init_attr init_attr;
- int ret = -ENOMEM;
+ int req_err, resp_err, ret = -ENOMEM;
struct ib_fmr_pool_param params;
BUG_ON(ib_conn->device == NULL);
device = ib_conn->device;
- ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL);
+ ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
+ ISER_RX_LOGIN_SIZE, GFP_KERNEL);
if (!ib_conn->login_buf)
goto out_err;
- ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device,
- (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
- DMA_FROM_DEVICE);
+ ib_conn->login_req_buf = ib_conn->login_buf;
+ ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN;
+
+ ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device,
+ (void *)ib_conn->login_req_buf,
+ ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+
+ ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device,
+ (void *)ib_conn->login_resp_buf,
+ ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+
+ req_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_req_dma);
+ resp_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_resp_dma);
+
+ if (req_err || resp_err) {
+ if (req_err)
+ ib_conn->login_req_dma = 0;
+ if (resp_err)
+ ib_conn->login_resp_dma = 0;
+ goto out_err;
+ }
ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
(sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
@@ -658,11 +677,11 @@ int iser_post_recvl(struct iser_conn *ib_conn)
struct ib_sge sge;
int ib_ret;
- sge.addr = ib_conn->login_dma;
+ sge.addr = ib_conn->login_resp_dma;
sge.length = ISER_RX_LOGIN_SIZE;
sge.lkey = ib_conn->device->mr->lkey;
- rx_wr.wr_id = (unsigned long)ib_conn->login_buf;
+ rx_wr.wr_id = (unsigned long)ib_conn->login_resp_buf;
rx_wr.sg_list = &sge;
rx_wr.num_sge = 1;
rx_wr.next = NULL;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index aa5eafa..8770d44 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -39,7 +39,7 @@
#include <linux/random.h>
#include <linux/jiffies.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -1353,6 +1353,12 @@ err_unmap:
err_iu:
srp_put_tx_iu(target, iu, SRP_IU_CMD);
+ /*
+ * Avoid that the loops that iterate over the request ring can
+ * encounter a dangling SCSI command pointer.
+ */
+ req->scmnd = NULL;
+
spin_lock_irqsave(&target->lock, flags);
list_add(&req->list, &target->free_reqs);
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 5b8f59d..c351aa4 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -47,7 +47,7 @@ static void gameport_disconnect_port(struct gameport *gameport);
#if defined(__i386__)
-#include <asm/i8253.h>
+#include <linux/i8253.h>
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
#define GET_TIME(x) do { x = get_time_pit(); } while (0)
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 4afe0a3..358cd7e 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -136,10 +136,10 @@ struct analog_port {
#ifdef __i386__
-#include <asm/i8253.h>
+#include <linux/i8253.h>
#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
-#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
+#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0)))
#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
static unsigned int get_time_pit(void)
{
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index f6732b5..6d6e741 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/input/as5011.h>
#include <linux/slab.h>
+#include <linux/module.h>
#define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick"
#define MODULE_DEVICE_ALIAS "as5011"
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 92c7be1..0c4c556 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -155,13 +155,17 @@ static const struct xpad_device {
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
+ { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+ { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
+ { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
};
@@ -236,11 +240,14 @@ static struct usb_device_id xpad_table [] = {
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
+ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
+ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
- XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */
- XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
+ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
+ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
+ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
{ }
};
@@ -546,7 +553,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
struct usb_endpoint_descriptor *ep_irq_out;
int error;
- if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+ if (xpad->xtype == XTYPE_UNKNOWN)
return 0;
xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
@@ -580,13 +587,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
static void xpad_stop_output(struct usb_xpad *xpad)
{
- if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX)
+ if (xpad->xtype != XTYPE_UNKNOWN)
usb_kill_urb(xpad->irq_out);
}
static void xpad_deinit_output(struct usb_xpad *xpad)
{
- if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
+ if (xpad->xtype != XTYPE_UNKNOWN) {
usb_free_urb(xpad->irq_out);
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->odata, xpad->odata_dma);
@@ -633,6 +640,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+ case XTYPE_XBOX360W:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x01;
+ xpad->odata[2] = 0x0F;
+ xpad->odata[3] = 0xC0;
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = strong / 256;
+ xpad->odata[6] = weak / 256;
+ xpad->odata[7] = 0x00;
+ xpad->odata[8] = 0x00;
+ xpad->odata[9] = 0x00;
+ xpad->odata[10] = 0x00;
+ xpad->odata[11] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 12;
+
+ return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
default:
dbg("%s - rumble command sent to unsupported xpad type: %d",
__func__, xpad->xtype);
@@ -645,7 +669,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
static int xpad_init_ff(struct usb_xpad *xpad)
{
- if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+ if (xpad->xtype == XTYPE_UNKNOWN)
return 0;
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
@@ -955,9 +979,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
}
ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
- usb_fill_bulk_urb(xpad->bulk_out, udev,
- usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
- xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
+ if (usb_endpoint_is_bulk_out(ep_irq_in)) {
+ usb_fill_bulk_urb(xpad->bulk_out, udev,
+ usb_sndbulkpipe(udev,
+ ep_irq_in->bEndpointAddress),
+ xpad->bdata, XPAD_PKT_LEN,
+ xpad_bulk_out, xpad);
+ } else {
+ usb_fill_int_urb(xpad->bulk_out, udev,
+ usb_sndintpipe(udev,
+ ep_irq_in->bEndpointAddress),
+ xpad->bdata, XPAD_PKT_LEN,
+ xpad_bulk_out, xpad, 0);
+ }
/*
* Submit the int URB immediately rather than waiting for open
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0b99443..64ce6d9 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -23,13 +23,6 @@
#include "psmouse.h"
#include "alps.h"
-#undef DEBUG
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-
#define ALPS_OLDPROTO 0x01 /* old style input */
#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
#define ALPS_PASS 0x04 /* device has a pass-through port */
@@ -297,10 +290,10 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
psmouse->packet[4] |
psmouse->packet[5]) & 0x80) ||
(!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
- dbg("refusing packet %x %x %x %x "
- "(suspected interleaved ps/2)\n",
- psmouse->packet[3], psmouse->packet[4],
- psmouse->packet[5], psmouse->packet[6]);
+ psmouse_dbg(psmouse,
+ "refusing packet %x %x %x %x (suspected interleaved ps/2)\n",
+ psmouse->packet[3], psmouse->packet[4],
+ psmouse->packet[5], psmouse->packet[6]);
return PSMOUSE_BAD_DATA;
}
@@ -319,13 +312,13 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
* There is also possibility that we got 6-byte ALPS
* packet followed by 3-byte packet from trackpoint. We
* can not distinguish between these 2 scenarios but
- * becase the latter is unlikely to happen in course of
+ * because the latter is unlikely to happen in course of
* normal operation (user would need to press all
* buttons on the pad and start moving trackpoint
* without touching the pad surface) we assume former.
* Even if we are wrong the wost thing that would happen
* the cursor would jump but we should not get protocol
- * desynchronization.
+ * de-synchronization.
*/
alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
@@ -361,10 +354,10 @@ static void alps_flush_packet(unsigned long data)
if ((psmouse->packet[3] |
psmouse->packet[4] |
psmouse->packet[5]) & 0x80) {
- dbg("refusing packet %x %x %x "
- "(suspected interleaved ps/2)\n",
- psmouse->packet[3], psmouse->packet[4],
- psmouse->packet[5]);
+ psmouse_dbg(psmouse,
+ "refusing packet %x %x %x (suspected interleaved ps/2)\n",
+ psmouse->packet[3], psmouse->packet[4],
+ psmouse->packet[5]);
} else {
alps_process_packet(psmouse);
}
@@ -379,7 +372,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
struct alps_data *priv = psmouse->private;
const struct alps_model_info *model = priv->i;
- if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
+ /*
+ * Check if we are dealing with a bare PS/2 packet, presumably from
+ * a device connected to the external PS/2 port. Because bare PS/2
+ * protocol does not have enough constant bits to self-synchronize
+ * properly we only do this if the device is fully synchronized.
+ */
+ if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) {
if (psmouse->pktcnt == 3) {
alps_report_bare_ps2_packet(psmouse, psmouse->packet,
true);
@@ -396,16 +395,18 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
}
if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
- dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
- psmouse->packet[0], model->mask0, model->byte0);
+ psmouse_dbg(psmouse,
+ "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+ psmouse->packet[0], model->mask0, model->byte0);
return PSMOUSE_BAD_DATA;
}
/* Bytes 2 - 6 should have 0 in the highest bit */
if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
(psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
- dbg("refusing packet[%i] = %x\n",
- psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
+ psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+ psmouse->pktcnt - 1,
+ psmouse->packet[psmouse->pktcnt - 1]);
return PSMOUSE_BAD_DATA;
}
@@ -441,7 +442,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
return NULL;
- dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x",
+ param[0], param[1], param[2]);
if ((param[0] & 0xf8) != 0 || param[1] != 0 ||
(param[2] != 10 && param[2] != 100))
@@ -462,7 +464,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
return NULL;
- dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x",
+ param[0], param[1], param[2]);
if (version) {
for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
@@ -530,7 +533,8 @@ static int alps_get_status(struct psmouse *psmouse, char *param)
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
return -1;
- dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x",
+ param[0], param[1], param[2]);
return 0;
}
@@ -608,12 +612,12 @@ static int alps_hw_init(struct psmouse *psmouse)
}
if (alps_tap_mode(psmouse, true)) {
- printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
+ psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
return -1;
}
if (alps_absolute_mode(psmouse)) {
- printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
+ psmouse_err(psmouse, "Failed to enable absolute mode\n");
return -1;
}
@@ -624,7 +628,7 @@ static int alps_hw_init(struct psmouse *psmouse)
/* ALPS needs stream mode, otherwise it won't report any data */
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
- printk(KERN_ERR "alps.c: Failed to enable stream mode\n");
+ psmouse_err(psmouse, "Failed to enable stream mode\n");
return -1;
}
@@ -747,6 +751,9 @@ int alps_init(struct psmouse *psmouse)
/* We are having trouble resyncing ALPS touchpads so disable it for now */
psmouse->resync_time = 0;
+ /* Allow 2 invalid packets without resetting device */
+ psmouse->resetafter = psmouse->pktsize * 2;
+
return 0;
init_fail:
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 13e38ff..1512bd8 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -67,6 +67,22 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245
#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246
#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247
+/* MacbookAir4,1 (unibody, July 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b
+/* MacbookAir4,2 (unibody, July 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e
+/* Macbook8,2 (unibody) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
+/* MacbookPro10,1 (unibody, June 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264
#define BCM5974_DEVICE(prod) { \
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
@@ -104,6 +120,22 @@ static const struct usb_device_id bcm5974_table[] = {
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
+ /* MacbookAir4,1 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
+ /* MacbookAir4,2 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
+ /* MacbookPro8,2 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
+ /* MacbookPro10,1 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
/* Terminating entry */
{}
};
@@ -294,6 +326,54 @@ static const struct bcm5974_config bcm5974_config_table[] = {
{ DIM_X, DIM_X / SN_COORD, -4415, 5050 },
{ DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
},
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING6_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING6_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4620, 5140 },
+ { DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+ },
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4750, 5280 },
+ { DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+ },
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4620, 5140 },
+ { DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+ },
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING7_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4750, 5280 },
+ { DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+ },
{}
};
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 3250356..548ea99 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -10,9 +10,8 @@
* Trademarks are the property of their respective owners.
*/
-#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
-
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/input.h>
@@ -25,13 +24,10 @@
#define elantech_debug(fmt, ...) \
do { \
if (etd->debug) \
- printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \
+ psmouse_printk(KERN_DEBUG, psmouse, \
+ fmt, ##__VA_ARGS__); \
} while (0)
-static bool force_elantech;
-module_param_named(force_elantech, force_elantech, bool, 0644);
-MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default).");
-
/*
* Send a Synaptics style sliced query command
*/
@@ -40,7 +36,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
{
if (psmouse_sliced_command(psmouse, c) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
- pr_err("synaptics_send_cmd query 0x%02x failed.\n", c);
+ psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
return -1;
}
@@ -69,7 +65,7 @@ static int elantech_ps2_command(struct psmouse *psmouse,
} while (tries > 0);
if (rc)
- pr_err("ps2 command 0x%02x failed.\n", command);
+ psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command);
return rc;
}
@@ -84,7 +80,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
unsigned char param[3];
int rc = 0;
- if (reg < 0x10 || reg > 0x26)
+ if (reg < 0x07 || reg > 0x26)
return -1;
if (reg > 0x11 && reg < 0x20)
@@ -108,12 +104,24 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
rc = -1;
}
break;
+
+ case 3 ... 4:
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, reg) ||
+ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
+ rc = -1;
+ }
+ break;
}
if (rc)
- pr_err("failed to read register 0x%02x.\n", reg);
- else
+ psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
+ else if (etd->hw_version != 4)
*val = param[0];
+ else
+ *val = param[1];
return rc;
}
@@ -127,7 +135,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
struct elantech_data *etd = psmouse->private;
int rc = 0;
- if (reg < 0x10 || reg > 0x26)
+ if (reg < 0x07 || reg > 0x26)
return -1;
if (reg > 0x11 && reg < 0x20)
@@ -154,11 +162,38 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
rc = -1;
}
break;
+
+ case 3:
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, reg) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, val) ||
+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+ rc = -1;
+ }
+ break;
+
+ case 4:
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, reg) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, val) ||
+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+ rc = -1;
+ }
+ break;
}
if (rc)
- pr_err("failed to write register 0x%02x with value 0x%02x.\n",
- reg, val);
+ psmouse_err(psmouse,
+ "failed to write register 0x%02x with value 0x%02x.\n",
+ reg, val);
return rc;
}
@@ -166,13 +201,13 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
/*
* Dump a complete mouse movement packet to the syslog
*/
-static void elantech_packet_dump(unsigned char *packet, int size)
+static void elantech_packet_dump(struct psmouse *psmouse)
{
int i;
- printk(KERN_DEBUG pr_fmt("PS/2 packet ["));
- for (i = 0; i < size; i++)
- printk("%s0x%02x ", (i) ? ", " : " ", packet[i]);
+ psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [");
+ for (i = 0; i < psmouse->pktsize; i++)
+ printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]);
printk("]\n");
}
@@ -223,7 +258,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_abs(dev, ABS_X,
((packet[1] & 0x0c) << 6) | packet[2]);
input_report_abs(dev, ABS_Y,
- ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
+ etd->y_max - (((packet[1] & 0x03) << 8) | packet[3]));
}
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
@@ -233,7 +268,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
if (etd->fw_version < 0x020000 &&
- (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
/* rocker down */
@@ -261,7 +296,7 @@ static void elantech_report_semi_mt_data(struct input_dev *dev,
unsigned int x2, unsigned int y2)
{
elantech_set_slot(dev, 0, num_fingers != 0, x1, y1);
- elantech_set_slot(dev, 1, num_fingers == 2, x2, y2);
+ elantech_set_slot(dev, 1, num_fingers >= 2, x2, y2);
}
/*
@@ -273,11 +308,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
struct elantech_data *etd = psmouse->private;
struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
- unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0;
+ unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ unsigned int width = 0, pres = 0;
/* byte 0: n1 n0 . . . . R L */
fingers = (packet[0] & 0xc0) >> 6;
- input_report_key(dev, BTN_TOUCH, fingers != 0);
switch (fingers) {
case 3:
@@ -290,18 +325,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
/* pass through... */
case 1:
/*
- * byte 1: . . . . . x10 x9 x8
+ * byte 1: . . . . x11 x10 x9 x8
* byte 2: x7 x6 x5 x4 x4 x2 x1 x0
*/
- x1 = ((packet[1] & 0x07) << 8) | packet[2];
+ x1 = ((packet[1] & 0x0f) << 8) | packet[2];
/*
- * byte 4: . . . . . . y9 y8
+ * byte 4: . . . . y11 y10 y9 y8
* byte 5: y7 y6 y5 y4 y3 y2 y1 y0
*/
- y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]);
-
- input_report_abs(dev, ABS_X, x1);
- input_report_abs(dev, ABS_Y, y1);
+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
@@ -314,22 +346,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
* byte 0: . . ay8 ax8 . . . .
* byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
*/
- x1 = ((packet[0] & 0x10) << 4) | packet[1];
+ x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2;
/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
- y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
+ y1 = etd->y_max -
+ ((((packet[0] & 0x20) << 3) | packet[2]) << 2);
/*
* byte 3: . . by8 bx8 . . . .
* byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
*/
- x2 = ((packet[3] & 0x10) << 4) | packet[4];
+ x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2;
/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
- y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
- /*
- * For compatibility with the X Synaptics driver scale up
- * one coordinate and report as ordinary mouse movent
- */
- input_report_abs(dev, ABS_X, x1 << 2);
- input_report_abs(dev, ABS_Y, y1 << 2);
+ y2 = etd->y_max -
+ ((((packet[3] & 0x20) << 3) | packet[5]) << 2);
/* Unknown so just report sensible values */
pres = 127;
@@ -337,6 +365,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
break;
}
+ input_report_key(dev, BTN_TOUCH, fingers != 0);
+ if (fingers != 0) {
+ input_report_abs(dev, ABS_X, x1);
+ input_report_abs(dev, ABS_Y, y1);
+ }
elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
@@ -352,7 +385,222 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
input_sync(dev);
}
-static int elantech_check_parity_v1(struct psmouse *psmouse)
+/*
+ * Interpret complete data packets and report absolute mode input events for
+ * hardware version 3. (12 byte packets for two fingers)
+ */
+static void elantech_report_absolute_v3(struct psmouse *psmouse,
+ int packet_type)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ unsigned int width = 0, pres = 0;
+
+ /* byte 0: n1 n0 . . . . R L */
+ fingers = (packet[0] & 0xc0) >> 6;
+
+ switch (fingers) {
+ case 3:
+ case 1:
+ /*
+ * byte 1: . . . . x11 x10 x9 x8
+ * byte 2: x7 x6 x5 x4 x4 x2 x1 x0
+ */
+ x1 = ((packet[1] & 0x0f) << 8) | packet[2];
+ /*
+ * byte 4: . . . . y11 y10 y9 y8
+ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0
+ */
+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+ break;
+
+ case 2:
+ if (packet_type == PACKET_V3_HEAD) {
+ /*
+ * byte 1: . . . . ax11 ax10 ax9 ax8
+ * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
+ */
+ etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2];
+ /*
+ * byte 4: . . . . ay11 ay10 ay9 ay8
+ * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0
+ */
+ etd->mt[0].y = etd->y_max -
+ (((packet[4] & 0x0f) << 8) | packet[5]);
+ /*
+ * wait for next packet
+ */
+ return;
+ }
+
+ /* packet_type == PACKET_V3_TAIL */
+ x1 = etd->mt[0].x;
+ y1 = etd->mt[0].y;
+ x2 = ((packet[1] & 0x0f) << 8) | packet[2];
+ y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+ break;
+ }
+
+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+ width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
+
+ input_report_key(dev, BTN_TOUCH, fingers != 0);
+ if (fingers != 0) {
+ input_report_abs(dev, ABS_X, x1);
+ input_report_abs(dev, ABS_Y, y1);
+ }
+ elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
+
+ /* For clickpads map both buttons to BTN_LEFT */
+ if (etd->fw_version & 0x001000) {
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
+ } else {
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+ }
+
+ input_report_abs(dev, ABS_PRESSURE, pres);
+ input_report_abs(dev, ABS_TOOL_WIDTH, width);
+
+ input_sync(dev);
+}
+
+static void elantech_input_sync_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+
+ /* For clickpads map both buttons to BTN_LEFT */
+ if (etd->fw_version & 0x001000) {
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
+ } else {
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+ }
+
+ input_mt_report_pointer_emulation(dev, true);
+ input_sync(dev);
+}
+
+static void process_packet_status_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ unsigned char *packet = psmouse->packet;
+ unsigned fingers;
+ int i;
+
+ /* notify finger state change */
+ fingers = packet[1] & 0x1f;
+ for (i = 0; i < ETP_MAX_FINGERS; i++) {
+ if ((fingers & (1 << i)) == 0) {
+ input_mt_slot(dev, i);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+ }
+ }
+
+ elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_head_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ int id = ((packet[3] & 0xe0) >> 5) - 1;
+ int pres, traces;
+
+ if (id < 0)
+ return;
+
+ etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
+ etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+ traces = (packet[0] & 0xf0) >> 4;
+
+ input_mt_slot(dev, id);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+
+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+ input_report_abs(dev, ABS_MT_PRESSURE, pres);
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
+ /* report this for backwards compatibility */
+ input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+
+ elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_motion_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0;
+ int id, sid;
+
+ id = ((packet[0] & 0xe0) >> 5) - 1;
+ if (id < 0)
+ return;
+
+ sid = ((packet[3] & 0xe0) >> 5) - 1;
+ weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1;
+ /*
+ * Motion packets give us the delta of x, y values of specific fingers,
+ * but in two's complement. Let the compiler do the conversion for us.
+ * Also _enlarge_ the numbers to int, in case of overflow.
+ */
+ delta_x1 = (signed char)packet[1];
+ delta_y1 = (signed char)packet[2];
+ delta_x2 = (signed char)packet[4];
+ delta_y2 = (signed char)packet[5];
+
+ etd->mt[id].x += delta_x1 * weight;
+ etd->mt[id].y -= delta_y1 * weight;
+ input_mt_slot(dev, id);
+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+
+ if (sid >= 0) {
+ etd->mt[sid].x += delta_x2 * weight;
+ etd->mt[sid].y -= delta_y2 * weight;
+ input_mt_slot(dev, sid);
+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y);
+ }
+
+ elantech_input_sync_v4(psmouse);
+}
+
+static void elantech_report_absolute_v4(struct psmouse *psmouse,
+ int packet_type)
+{
+ switch (packet_type) {
+ case PACKET_V4_STATUS:
+ process_packet_status_v4(psmouse);
+ break;
+
+ case PACKET_V4_HEAD:
+ process_packet_head_v4(psmouse);
+ break;
+
+ case PACKET_V4_MOTION:
+ process_packet_motion_v4(psmouse);
+ break;
+
+ case PACKET_UNKNOWN:
+ default:
+ /* impossible to get here */
+ break;
+ }
+}
+
+static int elantech_packet_check_v1(struct psmouse *psmouse)
{
struct elantech_data *etd = psmouse->private;
unsigned char *packet = psmouse->packet;
@@ -376,37 +624,163 @@ static int elantech_check_parity_v1(struct psmouse *psmouse)
etd->parity[packet[3]] == p3;
}
+static int elantech_debounce_check_v2(struct psmouse *psmouse)
+{
+ /*
+ * When we encounter packet that matches this exactly, it means the
+ * hardware is in debounce status. Just ignore the whole packet.
+ */
+ const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
+ unsigned char *packet = psmouse->packet;
+
+ return !memcmp(packet, debounce_packet, sizeof(debounce_packet));
+}
+
+static int elantech_packet_check_v2(struct psmouse *psmouse)
+{
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+
+ /*
+ * V2 hardware has two flavors. Older ones that do not report pressure,
+ * and newer ones that reports pressure and width. With newer ones, all
+ * packets (1, 2, 3 finger touch) have the same constant bits. With
+ * older ones, 1/3 finger touch packets and 2 finger touch packets
+ * have different constant bits.
+ * With all three cases, if the constant bits are not exactly what I
+ * expected, I consider them invalid.
+ */
+ if (etd->reports_pressure)
+ return (packet[0] & 0x0c) == 0x04 &&
+ (packet[3] & 0x0f) == 0x02;
+
+ if ((packet[0] & 0xc0) == 0x80)
+ return (packet[0] & 0x0c) == 0x0c &&
+ (packet[3] & 0x0e) == 0x08;
+
+ return (packet[0] & 0x3c) == 0x3c &&
+ (packet[1] & 0xf0) == 0x00 &&
+ (packet[3] & 0x3e) == 0x38 &&
+ (packet[4] & 0xf0) == 0x00;
+}
+
+/*
+ * We check the constant bits to determine what packet type we get,
+ * so packet checking is mandatory for v3 and later hardware.
+ */
+static int elantech_packet_check_v3(struct psmouse *psmouse)
+{
+ const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
+ unsigned char *packet = psmouse->packet;
+
+ /*
+ * check debounce first, it has the same signature in byte 0
+ * and byte 3 as PACKET_V3_HEAD.
+ */
+ if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
+ return PACKET_DEBOUNCE;
+
+ if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
+ return PACKET_V3_HEAD;
+
+ if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
+ return PACKET_V3_TAIL;
+
+ return PACKET_UNKNOWN;
+}
+
+static int elantech_packet_check_v4(struct psmouse *psmouse)
+{
+ unsigned char *packet = psmouse->packet;
+ unsigned char packet_type = packet[3] & 0x03;
+
+ switch (packet_type) {
+ case 0:
+ return PACKET_V4_STATUS;
+
+ case 1:
+ return PACKET_V4_HEAD;
+
+ case 2:
+ return PACKET_V4_MOTION;
+ }
+
+ return PACKET_UNKNOWN;
+}
+
/*
* Process byte stream from mouse and handle complete packets
*/
static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
{
struct elantech_data *etd = psmouse->private;
+ int packet_type;
if (psmouse->pktcnt < psmouse->pktsize)
return PSMOUSE_GOOD_DATA;
if (etd->debug > 1)
- elantech_packet_dump(psmouse->packet, psmouse->pktsize);
+ elantech_packet_dump(psmouse);
switch (etd->hw_version) {
case 1:
- if (etd->paritycheck && !elantech_check_parity_v1(psmouse))
+ if (etd->paritycheck && !elantech_packet_check_v1(psmouse))
return PSMOUSE_BAD_DATA;
elantech_report_absolute_v1(psmouse);
break;
case 2:
- /* We don't know how to check parity in protocol v2 */
+ /* ignore debounce */
+ if (elantech_debounce_check_v2(psmouse))
+ return PSMOUSE_FULL_PACKET;
+
+ if (etd->paritycheck && !elantech_packet_check_v2(psmouse))
+ return PSMOUSE_BAD_DATA;
+
elantech_report_absolute_v2(psmouse);
break;
+
+ case 3:
+ packet_type = elantech_packet_check_v3(psmouse);
+ /* ignore debounce */
+ if (packet_type == PACKET_DEBOUNCE)
+ return PSMOUSE_FULL_PACKET;
+
+ if (packet_type == PACKET_UNKNOWN)
+ return PSMOUSE_BAD_DATA;
+
+ elantech_report_absolute_v3(psmouse, packet_type);
+ break;
+
+ case 4:
+ packet_type = elantech_packet_check_v4(psmouse);
+ if (packet_type == PACKET_UNKNOWN)
+ return PSMOUSE_BAD_DATA;
+
+ elantech_report_absolute_v4(psmouse, packet_type);
+ break;
}
return PSMOUSE_FULL_PACKET;
}
/*
+ * This writes the reg_07 value again to the hardware at the end of every
+ * set_rate call because the register loses its value. reg_07 allows setting
+ * absolute mode on v4 hardware
+ */
+static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse,
+ unsigned int rate)
+{
+ struct elantech_data *etd = psmouse->private;
+
+ etd->original_set_rate(psmouse, rate);
+ if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+ psmouse_err(psmouse, "restoring reg_07 failed\n");
+}
+
+/*
* Put the touchpad into absolute mode
*/
static int elantech_set_absolute_mode(struct psmouse *psmouse)
@@ -435,15 +809,33 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
rc = -1;
- break;
}
+ break;
+
+ case 3:
+ if (etd->set_hw_resolution)
+ etd->reg_10 = 0x0b;
+ else
+ etd->reg_10 = 0x01;
+
+ if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
+ rc = -1;
+
+ break;
+
+ case 4:
+ etd->reg_07 = 0x01;
+ if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+ rc = -1;
+
+ goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */
}
if (rc == 0) {
/*
* Read back reg 0x10. For hardware version 1 we must make
* sure the absolute mode bit is set. For hardware version 2
- * the touchpad is probably initalising and not ready until
+ * the touchpad is probably initializing and not ready until
* we read back the value we just wrote.
*/
do {
@@ -456,27 +848,115 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
} while (tries > 0);
if (rc) {
- pr_err("failed to read back register 0x10.\n");
+ psmouse_err(psmouse,
+ "failed to read back register 0x10.\n");
} else if (etd->hw_version == 1 &&
!(val & ETP_R10_ABSOLUTE_MODE)) {
- pr_err("touchpad refuses to switch to absolute mode.\n");
+ psmouse_err(psmouse,
+ "touchpad refuses to switch to absolute mode.\n");
rc = -1;
}
}
+ skip_readback_reg_10:
if (rc)
- pr_err("failed to initialise registers.\n");
+ psmouse_err(psmouse, "failed to initialise registers.\n");
return rc;
}
+static int elantech_set_range(struct psmouse *psmouse,
+ unsigned int *x_min, unsigned int *y_min,
+ unsigned int *x_max, unsigned int *y_max,
+ unsigned int *width)
+{
+ struct elantech_data *etd = psmouse->private;
+ unsigned char param[3];
+ unsigned char traces;
+
+ switch (etd->hw_version) {
+ case 1:
+ *x_min = ETP_XMIN_V1;
+ *y_min = ETP_YMIN_V1;
+ *x_max = ETP_XMAX_V1;
+ *y_max = ETP_YMAX_V1;
+ break;
+
+ case 2:
+ if (etd->fw_version == 0x020800 ||
+ etd->fw_version == 0x020b00 ||
+ etd->fw_version == 0x020030) {
+ *x_min = ETP_XMIN_V2;
+ *y_min = ETP_YMIN_V2;
+ *x_max = ETP_XMAX_V2;
+ *y_max = ETP_YMAX_V2;
+ } else {
+ int i;
+ int fixed_dpi;
+
+ i = (etd->fw_version > 0x020800 &&
+ etd->fw_version < 0x020900) ? 1 : 2;
+
+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -1;
+
+ fixed_dpi = param[1] & 0x10;
+
+ if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
+ if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+ return -1;
+
+ *x_max = (etd->capabilities[1] - i) * param[1] / 2;
+ *y_max = (etd->capabilities[2] - i) * param[2] / 2;
+ } else if (etd->fw_version == 0x040216) {
+ *x_max = 819;
+ *y_max = 405;
+ } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) {
+ *x_max = 900;
+ *y_max = 500;
+ } else {
+ *x_max = (etd->capabilities[1] - i) * 64;
+ *y_max = (etd->capabilities[2] - i) * 64;
+ }
+ }
+ break;
+
+ case 3:
+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -1;
+
+ *x_max = (0x0f & param[0]) << 8 | param[1];
+ *y_max = (0xf0 & param[0]) << 4 | param[2];
+ break;
+
+ case 4:
+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -1;
+
+ *x_max = (0x0f & param[0]) << 8 | param[1];
+ *y_max = (0xf0 & param[0]) << 4 | param[2];
+ traces = etd->capabilities[1];
+ if ((traces < 2) || (traces > *x_max))
+ return -1;
+
+ *width = *x_max / (traces - 1);
+ break;
+ }
+
+ return 0;
+}
+
/*
* Set the appropriate event bits for the input subsystem
*/
-static void elantech_set_input_params(struct psmouse *psmouse)
+static int elantech_set_input_params(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
+ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
+
+ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
+ return -1;
__set_bit(EV_KEY, dev->evbit);
__set_bit(EV_ABS, dev->evbit);
@@ -494,30 +974,64 @@ static void elantech_set_input_params(struct psmouse *psmouse)
case 1:
/* Rocker button */
if (etd->fw_version < 0x020000 &&
- (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
__set_bit(BTN_FORWARD, dev->keybit);
__set_bit(BTN_BACK, dev->keybit);
}
- input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0);
- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0);
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
break;
case 2:
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
- input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+ /* fall through */
+ case 3:
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
if (etd->reports_pressure) {
input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
ETP_PMAX_V2, 0, 0);
input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
ETP_WMAX_V2, 0, 0);
}
- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2);
- input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
- input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+ break;
+
+ case 4:
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ /* For X to recognize me as touchpad. */
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+ /*
+ * range of pressure and width is the same as v2,
+ * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
+ */
+ input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
+ ETP_PMAX_V2, 0, 0);
+ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+ ETP_WMAX_V2, 0, 0);
+ /* Multitouch capable pad, up to 5 fingers. */
+ input_mt_init_slots(dev, ETP_MAX_FINGERS);
+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
+ ETP_PMAX_V2, 0, 0);
+ /*
+ * The firmware reports how many trace lines the finger spans,
+ * convert to surface unit as Protocol-B requires.
+ */
+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+ ETP_WMAX_V2 * width, 0, 0);
break;
}
+
+ etd->y_max = y_max;
+ etd->width = width;
+
+ return 0;
}
struct elantech_attr_data {
@@ -587,6 +1101,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse,
elantech_show_int_attr, \
elantech_set_int_attr)
+ELANTECH_INT_ATTR(reg_07, 0x07);
ELANTECH_INT_ATTR(reg_10, 0x10);
ELANTECH_INT_ATTR(reg_11, 0x11);
ELANTECH_INT_ATTR(reg_20, 0x20);
@@ -600,6 +1115,7 @@ ELANTECH_INT_ATTR(debug, 0);
ELANTECH_INT_ATTR(paritycheck, 0);
static struct attribute *elantech_attrs[] = {
+ &psmouse_attr_reg_07.dattr.attr,
&psmouse_attr_reg_10.dattr.attr,
&psmouse_attr_reg_11.dattr.attr,
&psmouse_attr_reg_20.dattr.attr,
@@ -629,6 +1145,14 @@ static bool elantech_is_signature_valid(const unsigned char *param)
if (param[1] == 0)
return true;
+ /*
+ * Some hw_version >= 4 models have a revision higher then 20. Meaning
+ * that param[2] may be 10 or 20, skip the rates check for these.
+ */
+ if ((param[0] & 0x0f) >= 0x06 && (param[1] & 0xaf) == 0x0f &&
+ param[2] < 40)
+ return true;
+
for (i = 0; i < ARRAY_SIZE(rates); i++)
if (param[2] == rates[i])
return false;
@@ -651,7 +1175,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
- pr_debug("sending Elantech magic knock failed.\n");
+ psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n");
return -1;
}
@@ -659,9 +1183,11 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
* Report this in case there are Elantech models that use a different
* set of magic numbers
*/
- if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
- pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
- param[0], param[1], param[2]);
+ if (param[0] != 0x3c || param[1] != 0x03 ||
+ (param[2] != 0xc8 && param[2] != 0x00)) {
+ psmouse_dbg(psmouse,
+ "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
+ param[0], param[1], param[2]);
return -1;
}
@@ -671,20 +1197,18 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
* to Elantech magic knock and there might be more.
*/
if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
- pr_debug("failed to query firmware version.\n");
+ psmouse_dbg(psmouse, "failed to query firmware version.\n");
return -1;
}
- pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
- param[0], param[1], param[2]);
+ psmouse_dbg(psmouse,
+ "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
+ param[0], param[1], param[2]);
if (!elantech_is_signature_valid(param)) {
- if (!force_elantech) {
- pr_debug("Probably not a real Elantech touchpad. Aborting.\n");
- return -1;
- }
-
- pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
+ psmouse_dbg(psmouse,
+ "Probably not a real Elantech touchpad. Aborting.\n");
+ return -1;
}
if (set_properties) {
@@ -715,7 +1239,8 @@ static int elantech_reconnect(struct psmouse *psmouse)
return -1;
if (elantech_set_absolute_mode(psmouse)) {
- pr_err("failed to put touchpad back into absolute mode.\n");
+ psmouse_err(psmouse,
+ "failed to put touchpad back into absolute mode.\n");
return -1;
}
@@ -723,6 +1248,84 @@ static int elantech_reconnect(struct psmouse *psmouse)
}
/*
+ * Some hw_version 3 models go into error state when we try to set
+ * bit 3 and/or bit 1 of r10.
+ */
+static const struct dmi_system_id no_hw_res_dmi_table[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ /* Gigabyte U2442 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "U2442"),
+ },
+ },
+#endif
+ { }
+};
+
+/*
+ * determine hardware version and set some properties according to it.
+ */
+static int elantech_set_properties(struct elantech_data *etd)
+{
+ /* This represents the version of IC body. */
+ int ver = (etd->fw_version & 0x0f0000) >> 16;
+
+ /* Early version of Elan touchpads doesn't obey the rule. */
+ if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
+ etd->hw_version = 1;
+ else {
+ switch (ver) {
+ case 2:
+ case 4:
+ etd->hw_version = 2;
+ break;
+ case 5:
+ etd->hw_version = 3;
+ break;
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 13:
+ case 14:
+ etd->hw_version = 4;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ /*
+ * Turn on packet checking by default.
+ */
+ etd->paritycheck = 1;
+
+ /*
+ * This firmware suffers from misreporting coordinates when
+ * a touch action starts causing the mouse cursor or scrolled page
+ * to jump. Enable a workaround.
+ */
+ etd->jumpy_cursor =
+ (etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
+
+ if (etd->hw_version > 1) {
+ /* For now show extra debug information */
+ etd->debug = 1;
+
+ if (etd->fw_version >= 0x020800)
+ etd->reports_pressure = true;
+ }
+
+ /* Enable real hardware resolution on hw_version 3 ? */
+ etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
+
+ return 0;
+}
+
+/*
* Initialize the touchpad and create sysfs entries
*/
int elantech_init(struct psmouse *psmouse)
@@ -743,70 +1346,58 @@ int elantech_init(struct psmouse *psmouse)
* Do the version query again so we can store the result
*/
if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
- pr_err("failed to query firmware version.\n");
+ psmouse_err(psmouse, "failed to query firmware version.\n");
goto init_fail;
}
-
etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
- /*
- * Assume every version greater than this is new EeePC style
- * hardware with 6 byte packets
- */
- if (etd->fw_version >= 0x020030) {
- etd->hw_version = 2;
- /* For now show extra debug information */
- etd->debug = 1;
- /* Don't know how to do parity checking for version 2 */
- etd->paritycheck = 0;
-
- if (etd->fw_version >= 0x020800)
- etd->reports_pressure = true;
-
- } else {
- etd->hw_version = 1;
- etd->paritycheck = 1;
+ if (elantech_set_properties(etd)) {
+ psmouse_err(psmouse, "unknown hardware version, aborting...\n");
+ goto init_fail;
}
+ psmouse_info(psmouse,
+ "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
+ etd->hw_version, param[0], param[1], param[2]);
- pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
- etd->hw_version, param[0], param[1], param[2]);
+ if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+ etd->capabilities)) {
+ psmouse_err(psmouse, "failed to query capabilities.\n");
+ goto init_fail;
+ }
+ psmouse_info(psmouse,
+ "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
+ etd->capabilities[0], etd->capabilities[1],
+ etd->capabilities[2]);
- if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
- pr_err("failed to query capabilities.\n");
+ if (elantech_set_absolute_mode(psmouse)) {
+ psmouse_err(psmouse,
+ "failed to put touchpad into absolute mode.\n");
goto init_fail;
}
- pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
- param[0], param[1], param[2]);
- etd->capabilities = param[0];
- /*
- * This firmware suffers from misreporting coordinates when
- * a touch action starts causing the mouse cursor or scrolled page
- * to jump. Enable a workaround.
- */
- if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) {
- pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n");
- etd->jumpy_cursor = true;
+ if (etd->fw_version == 0x381f17) {
+ etd->original_set_rate = psmouse->set_rate;
+ psmouse->set_rate = elantech_set_rate_restore_reg_07;
}
- if (elantech_set_absolute_mode(psmouse)) {
- pr_err("failed to put touchpad into absolute mode.\n");
+ if (elantech_set_input_params(psmouse)) {
+ psmouse_err(psmouse, "failed to query touchpad range.\n");
goto init_fail;
}
- elantech_set_input_params(psmouse);
-
error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
&elantech_attr_group);
if (error) {
- pr_err("failed to create sysfs attributes, error: %d.\n", error);
+ psmouse_err(psmouse,
+ "failed to create sysfs attributes, error: %d.\n",
+ error);
goto init_fail;
}
psmouse->protocol_handler = elantech_process_byte;
psmouse->disconnect = elantech_disconnect;
psmouse->reconnect = elantech_reconnect;
- psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
+ psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
return 0;
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index fabb2b9..092ac72 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -16,14 +16,17 @@
/*
* Command values for Synaptics style queries
*/
+#define ETP_FW_ID_QUERY 0x00
#define ETP_FW_VERSION_QUERY 0x01
#define ETP_CAPABILITIES_QUERY 0x02
+#define ETP_SAMPLE_QUERY 0x03
/*
* Command values for register reading or writing
*/
#define ETP_REGISTER_READ 0x10
#define ETP_REGISTER_WRITE 0x11
+#define ETP_REGISTER_READWRITE 0x00
/*
* Hardware version 2 custom PS/2 command value
@@ -66,16 +69,13 @@
#define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1)
/*
- * It seems the resolution for hardware version 2 doubled.
- * Hence the X and Y ranges are doubled too.
- * The bezel around the pad also appears to be smaller
+ * The resolution for older v2 hardware doubled.
+ * (newer v2's firmware provides command so we can query)
*/
-#define ETP_EDGE_FUZZ_V2 8
-
-#define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2)
-#define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2)
-#define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2)
-#define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2)
+#define ETP_XMIN_V2 0
+#define ETP_XMAX_V2 1152
+#define ETP_YMIN_V2 0
+#define ETP_YMAX_V2 768
#define ETP_PMIN_V2 0
#define ETP_PMAX_V2 255
@@ -83,17 +83,37 @@
#define ETP_WMAX_V2 15
/*
- * For two finger touches the coordinate of each finger gets reported
- * separately but with reduced resolution.
+ * v3 hardware has 2 kinds of packet types,
+ * v4 hardware has 3.
+ */
+#define PACKET_UNKNOWN 0x01
+#define PACKET_DEBOUNCE 0x02
+#define PACKET_V3_HEAD 0x03
+#define PACKET_V3_TAIL 0x04
+#define PACKET_V4_HEAD 0x05
+#define PACKET_V4_MOTION 0x06
+#define PACKET_V4_STATUS 0x07
+
+/*
+ * track up to 5 fingers for v4 hardware
+ */
+#define ETP_MAX_FINGERS 5
+
+/*
+ * weight value for v4 hardware
*/
-#define ETP_2FT_FUZZ 4
+#define ETP_WEIGHT_VALUE 5
-#define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ)
-#define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ)
-#define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ)
-#define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ)
+/*
+ * The base position for one finger, v4 hardware
+ */
+struct finger_pos {
+ unsigned int x;
+ unsigned int y;
+};
struct elantech_data {
+ unsigned char reg_07;
unsigned char reg_10;
unsigned char reg_11;
unsigned char reg_20;
@@ -104,14 +124,19 @@ struct elantech_data {
unsigned char reg_25;
unsigned char reg_26;
unsigned char debug;
- unsigned char capabilities;
+ unsigned char capabilities[3];
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
+ bool set_hw_resolution;
unsigned char hw_version;
unsigned int fw_version;
unsigned int single_finger_reports;
+ unsigned int y_max;
+ unsigned int width;
+ struct finger_pos mt[ETP_MAX_FINGERS];
unsigned char parity[256];
+ void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
};
#ifdef CONFIG_MOUSE_PS2_ELANTECH
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index 7b6ce17..58902fb 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void)
}
module_exit(gpio_mouse_exit);
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("GPIO mouse driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 95577c1..0470dd4 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -32,6 +32,7 @@
#define DEBUG
#include <linux/slab.h>
#include <linux/input.h>
+#include <linux/module.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include <linux/delay.h>
@@ -135,10 +136,10 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
/* discard if too big, or half that but > 4 times the prev delta */
if (avx > recalib_delta ||
(avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
- hgpk_err(psmouse, "detected %dpx jump in x\n", x);
+ psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
priv->xbigj = avx;
} else if (approx_half(avx, priv->xbigj)) {
- hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
+ psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
priv->xbigj = avx;
priv->xsaw_secondary++;
} else {
@@ -150,10 +151,10 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
if (avy > recalib_delta ||
(avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
- hgpk_err(psmouse, "detected %dpx jump in y\n", y);
+ psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
priv->ybigj = avy;
} else if (approx_half(avy, priv->ybigj)) {
- hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y);
+ psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
priv->ybigj = avy;
priv->ysaw_secondary++;
} else {
@@ -167,7 +168,7 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
priv->ylast = avy;
if (do_recal && jumpy_delay) {
- hgpk_err(psmouse, "scheduling recalibration\n");
+ psmouse_warn(psmouse, "scheduling recalibration\n");
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(jumpy_delay));
}
@@ -259,8 +260,8 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
* movement, it is probably a case of the user moving the
* cursor very slowly across the screen. */
if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
- hgpk_err(psmouse, "packet spew detected (%d,%d)\n",
- priv->x_tally, priv->y_tally);
+ psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
+ priv->x_tally, priv->y_tally);
priv->spew_flag = RECALIBRATING;
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(spew_delay));
@@ -332,12 +333,12 @@ static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
}
if (!valid)
- hgpk_dbg(psmouse,
- "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
- priv->mode, pktcnt,
- psmouse->packet[0], psmouse->packet[1],
- psmouse->packet[2], psmouse->packet[3],
- psmouse->packet[4], psmouse->packet[5]);
+ psmouse_dbg(psmouse,
+ "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
+ priv->mode, pktcnt,
+ psmouse->packet[0], psmouse->packet[1],
+ psmouse->packet[2], psmouse->packet[3],
+ psmouse->packet[4], psmouse->packet[5]);
return valid;
}
@@ -360,19 +361,20 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
input_report_abs(idev, ABS_PRESSURE, z);
if (tpdebug)
- hgpk_dbg(psmouse, "pd=%d fd=%d z=%d",
- pt_down, finger_down, z);
+ psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
+ pt_down, finger_down, z);
} else {
/*
* PenTablet mode does not report pressure, so we don't
* report it here
*/
if (tpdebug)
- hgpk_dbg(psmouse, "pd=%d ", down);
+ psmouse_dbg(psmouse, "pd=%d ", down);
}
if (tpdebug)
- hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+ psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+ left, right, x, y);
input_report_key(idev, BTN_TOUCH, down);
input_report_key(idev, BTN_LEFT, left);
@@ -394,7 +396,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
if (x == priv->abs_x && y == priv->abs_y) {
if (++priv->dupe_count > SPEW_WATCH_COUNT) {
if (tpdebug)
- hgpk_dbg(psmouse, "hard spew detected\n");
+ psmouse_dbg(psmouse, "hard spew detected\n");
priv->spew_flag = RECALIBRATING;
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(spew_delay));
@@ -411,7 +413,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
int y_diff = priv->abs_y - y;
if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
if (tpdebug)
- hgpk_dbg(psmouse, "discarding\n");
+ psmouse_dbg(psmouse, "discarding\n");
goto done;
}
hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
@@ -436,20 +438,21 @@ static void hgpk_process_simple_packet(struct psmouse *psmouse)
int y = ((packet[0] << 3) & 0x100) - packet[2];
if (packet[0] & 0xc0)
- hgpk_dbg(psmouse,
- "overflow -- 0x%02x 0x%02x 0x%02x\n",
- packet[0], packet[1], packet[2]);
+ psmouse_dbg(psmouse,
+ "overflow -- 0x%02x 0x%02x 0x%02x\n",
+ packet[0], packet[1], packet[2]);
if (hgpk_discard_decay_hack(psmouse, x, y)) {
if (tpdebug)
- hgpk_dbg(psmouse, "discarding\n");
+ psmouse_dbg(psmouse, "discarding\n");
return;
}
hgpk_spewing_hack(psmouse, left, right, x, y);
if (tpdebug)
- hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+ psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+ left, right, x, y);
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
@@ -481,9 +484,8 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
* ugh, got a packet inside our recalibration
* window, schedule another recalibration.
*/
- hgpk_dbg(psmouse,
- "packet inside calibration window, "
- "queueing another recalibration\n");
+ psmouse_dbg(psmouse,
+ "packet inside calibration window, queueing another recalibration\n");
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(post_interrupt_delay));
}
@@ -627,7 +629,7 @@ static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
err = hgpk_select_mode(psmouse);
if (err) {
- hgpk_err(psmouse, "failed to select mode\n");
+ psmouse_err(psmouse, "failed to select mode\n");
return err;
}
@@ -647,11 +649,11 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
return 0;
if (!autorecal) {
- hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n");
+ psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
return 0;
}
- hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+ psmouse_dbg(psmouse, "recalibrating touchpad..\n");
/* we don't want to race with the irq handler, nor with resyncs */
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -674,7 +676,7 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
if (tpdebug)
- hgpk_dbg(psmouse, "touchpad reactivated\n");
+ psmouse_dbg(psmouse, "touchpad reactivated\n");
/*
* If we get packets right away after recalibrating, it's likely
@@ -726,16 +728,16 @@ static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
err = hgpk_reset_device(psmouse, false);
if (err) {
- hgpk_err(psmouse, "Failed to reset device!\n");
+ psmouse_err(psmouse, "Failed to reset device!\n");
return err;
}
/* should be all set, enable the touchpad */
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
- hgpk_dbg(psmouse, "Touchpad powered up.\n");
+ psmouse_dbg(psmouse, "Touchpad powered up.\n");
} else {
- hgpk_dbg(psmouse, "Powering off touchpad.\n");
+ psmouse_dbg(psmouse, "Powering off touchpad.\n");
if (ps2_command(ps2dev, NULL, 0xec) ||
ps2_command(ps2dev, NULL, 0xec) ||
@@ -922,7 +924,7 @@ static void hgpk_recalib_work(struct work_struct *work)
struct psmouse *psmouse = priv->psmouse;
if (hgpk_force_recalibrate(psmouse))
- hgpk_err(psmouse, "recalibration failed!\n");
+ psmouse_err(psmouse, "recalibration failed!\n");
}
static int hgpk_register(struct psmouse *psmouse)
@@ -946,14 +948,15 @@ static int hgpk_register(struct psmouse *psmouse)
err = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_powered.dattr);
if (err) {
- hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n");
+ psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
return err;
}
err = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_hgpk_mode.dattr);
if (err) {
- hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n");
+ psmouse_err(psmouse,
+ "Failed creating 'hgpk_mode' sysfs node\n");
goto err_remove_powered;
}
@@ -962,8 +965,8 @@ static int hgpk_register(struct psmouse *psmouse)
err = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_recalibrate.dattr);
if (err) {
- hgpk_err(psmouse,
- "Failed creating 'recalibrate' sysfs node\n");
+ psmouse_err(psmouse,
+ "Failed creating 'recalibrate' sysfs node\n");
goto err_remove_mode;
}
}
@@ -1026,13 +1029,13 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
return -EIO;
}
- hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
/* HGPK signature: 0x67, 0x00, 0x<model> */
if (param[0] != 0x67 || param[1] != 0x00)
return -ENODEV;
- hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
+ psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
return param[2];
}
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
index 311c0e8..dd68677 100644
--- a/drivers/input/mouse/hgpk.h
+++ b/drivers/input/mouse/hgpk.h
@@ -46,17 +46,6 @@ struct hgpk_data {
int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
};
-#define hgpk_dbg(psmouse, format, arg...) \
- dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_err(psmouse, format, arg...) \
- dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_info(psmouse, format, arg...) \
- dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_warn(psmouse, format, arg...) \
- dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_notice(psmouse, format, arg...) \
- dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-
#ifdef CONFIG_MOUSE_PS2_OLPC
void hgpk_module_init(void);
int hgpk_detect(struct psmouse *psmouse, bool set_properties);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index c31ad11..2c4db63 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -33,7 +33,7 @@ static const char *desired_serio_phys;
static int lifebook_limit_serio3(const struct dmi_system_id *d)
{
desired_serio_phys = "isa0060/serio3";
- return 0;
+ return 1;
}
static bool lifebook_use_6byte_proto;
@@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto;
static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
{
lifebook_use_6byte_proto = true;
- return 0;
+ return 1;
}
static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
@@ -169,8 +169,8 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
if (relative_packet) {
if (!dev2)
- printk(KERN_WARNING "lifebook.c: got relative packet "
- "but no relative device set up\n");
+ psmouse_warn(psmouse,
+ "got relative packet but no relative device set up\n");
} else {
if (lifebook_use_6byte_proto) {
input_report_abs(dev1, ABS_X,
@@ -212,7 +212,7 @@ static int lifebook_absolute_mode(struct psmouse *psmouse)
/*
* Enable absolute output -- ps2_command fails always but if
- * you leave this call out the touchsreen will never send
+ * you leave this call out the touchscreen will never send
* absolute coordinates
*/
param = lifebook_use_6byte_proto ? 0x08 : 0x07;
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index c9983ae..faac2c3 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -82,11 +82,11 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
packet[0] = packet[2] | 0x08;
break;
-#ifdef DEBUG
default:
- printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
- (packet[1] >> 4) | (packet[0] & 0x30));
-#endif
+ psmouse_dbg(psmouse,
+ "Received PS2++ packet #%x, but don't know how to handle.\n",
+ (packet[1] >> 4) | (packet[0] & 0x30));
+ break;
}
} else {
/* Standard PS/2 motion data */
@@ -382,7 +382,7 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties)
}
} else {
- printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
+ psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model);
}
if (set_properties) {
@@ -400,9 +400,9 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties)
error = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_smartscroll.dattr);
if (error) {
- printk(KERN_ERR
- "logips2pp.c: failed to create smartscroll "
- "sysfs attribute, error: %d\n", error);
+ psmouse_err(psmouse,
+ "failed to create smartscroll sysfs attribute, error: %d\n",
+ error);
return -1;
}
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 3f74bae..9f352fb 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -11,6 +11,9 @@
* the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define psmouse_fmt(fmt) fmt
+
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -251,11 +254,14 @@ static int psmouse_handle_byte(struct psmouse *psmouse)
switch (rc) {
case PSMOUSE_BAD_DATA:
if (psmouse->state == PSMOUSE_ACTIVATED) {
- printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
- psmouse->name, psmouse->phys, psmouse->pktcnt);
+ psmouse_warn(psmouse,
+ "%s at %s lost sync at byte %d\n",
+ psmouse->name, psmouse->phys,
+ psmouse->pktcnt);
if (++psmouse->out_of_sync_cnt == psmouse->resetafter) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+ psmouse_notice(psmouse,
+ "issuing reconnect request\n");
serio_reconnect(psmouse->ps2dev.serio);
return -1;
}
@@ -267,8 +273,9 @@ static int psmouse_handle_byte(struct psmouse *psmouse)
psmouse->pktcnt = 0;
if (psmouse->out_of_sync_cnt) {
psmouse->out_of_sync_cnt = 0;
- printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
- psmouse->name, psmouse->phys);
+ psmouse_notice(psmouse,
+ "%s at %s - driver resynced.\n",
+ psmouse->name, psmouse->phys);
}
break;
@@ -295,9 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
if (psmouse->state == PSMOUSE_ACTIVATED)
- printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
- flags & SERIO_TIMEOUT ? " timeout" : "",
- flags & SERIO_PARITY ? " bad parity" : "");
+ psmouse_warn(psmouse,
+ "bad data from KBC -%s%s\n",
+ flags & SERIO_TIMEOUT ? " timeout" : "",
+ flags & SERIO_PARITY ? " bad parity" : "");
ps2_cmd_aborted(&psmouse->ps2dev);
goto out;
}
@@ -315,8 +323,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (psmouse->state == PSMOUSE_ACTIVATED &&
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
- printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
- psmouse->name, psmouse->phys, psmouse->pktcnt);
+ psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n",
+ psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
@@ -943,7 +951,8 @@ static int psmouse_probe(struct psmouse *psmouse)
*/
if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
- printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys);
+ psmouse_warn(psmouse, "Failed to reset mouse on %s\n",
+ ps2dev->serio->phys);
return 0;
}
@@ -1005,8 +1014,8 @@ static void psmouse_initialize(struct psmouse *psmouse)
static void psmouse_activate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
- printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "Failed to enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
}
@@ -1020,14 +1029,14 @@ static void psmouse_activate(struct psmouse *psmouse)
static void psmouse_deactivate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
- printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
}
/*
- * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
+ * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
*/
static int psmouse_poll(struct psmouse *psmouse)
@@ -1115,14 +1124,15 @@ static void psmouse_resync(struct work_struct *work)
}
if (!enabled) {
- printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "failed to re-enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
failed = true;
}
if (failed) {
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
+ psmouse_info(psmouse,
+ "resync failed, issuing reconnect request\n");
serio_reconnect(serio);
} else
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
@@ -1155,8 +1165,8 @@ static void psmouse_cleanup(struct serio *serio)
* Disable stream mode so cleanup routine can proceed undisturbed.
*/
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
- printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "Failed to disable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
if (psmouse->cleanup)
psmouse->cleanup(psmouse);
@@ -1400,7 +1410,8 @@ static int psmouse_reconnect(struct serio *serio)
int rc = -1;
if (!drv || !psmouse) {
- printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
+ psmouse_dbg(psmouse,
+ "reconnect request, but serio is disconnected, ignoring...\n");
return -1;
}
@@ -1427,8 +1438,9 @@ static int psmouse_reconnect(struct serio *serio)
goto out;
}
- /* ok, the device type (and capabilities) match the old one,
- * we can continue using it, complete intialization
+ /*
+ * OK, the device type (and capabilities) match the old one,
+ * we can continue using it, complete initialization
*/
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
@@ -1586,9 +1598,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
while (!list_empty(&serio->children)) {
if (++retry > 3) {
- printk(KERN_WARNING
- "psmouse: failed to destroy children ports, "
- "protocol change aborted.\n");
+ psmouse_warn(psmouse,
+ "failed to destroy children ports, protocol change aborted.\n");
input_free_device(new_dev);
return -EIO;
}
@@ -1715,7 +1726,7 @@ static int __init psmouse_init(void)
kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
if (!kpsmoused_wq) {
- printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
+ pr_err("failed to create kpsmoused workqueue\n");
return -ENOMEM;
}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 593e910..9b84b0c 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -150,4 +150,29 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
static ssize_t _set(struct psmouse *, void *, const char *, size_t); \
__PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true)
+#ifndef psmouse_fmt
+#define psmouse_fmt(fmt) KBUILD_BASENAME ": " fmt
+#endif
+
+#define psmouse_dbg(psmouse, format, ...) \
+ dev_dbg(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_info(psmouse, format, ...) \
+ dev_info(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_warn(psmouse, format, ...) \
+ dev_warn(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_err(psmouse, format, ...) \
+ dev_err(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_notice(psmouse, format, ...) \
+ dev_notice(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_printk(level, psmouse, format, ...) \
+ dev_printk(level, \
+ &(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+
+
#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
index 943cfec..ee3b0ca 100644
--- a/drivers/input/mouse/pxa930_trkball.c
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -12,7 +12,6 @@
#include <linux/init.h>
#include <linux/input.h>
-#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -184,7 +183,7 @@ static int __devinit pxa930_trkball_probe(struct platform_device *pdev)
/* held the module in reset, will be enabled in open() */
pxa930_trkball_disable(trkball);
- error = request_irq(irq, pxa930_trkball_interrupt, IRQF_DISABLED,
+ error = request_irq(irq, pxa930_trkball_interrupt, 0,
pdev->name, trkball);
if (error) {
dev_err(&pdev->dev, "failed to request irq: %d\n", error);
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 1242775..86d6f39 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -2,7 +2,7 @@
* Finger Sensing Pad PS/2 mouse driver.
*
* Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
- * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation.
+ * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,7 +20,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/input.h>
#include <linux/ctype.h>
#include <linux/libps2.h>
@@ -163,7 +162,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val)
ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
- return -1;
+ goto out;
if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
/* inversion is required */
@@ -262,7 +261,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val)
ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
- return -1;
+ goto out;
if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
@@ -310,7 +309,7 @@ static int fsp_get_buttons(struct psmouse *psmouse, int *btn)
};
int val;
- if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1)
+ if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1)
return -EIO;
*btn = buttons[(val & 0x30) >> 4];
@@ -608,11 +607,12 @@ static void fsp_packet_debug(unsigned char packet[])
ps2_packet_cnt++;
jiffies_msec = jiffies_to_msecs(jiffies);
- printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
- jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
+ psmouse_dbg(psmouse,
+ "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
+ jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
if (jiffies_msec - ps2_last_second > 1000) {
- printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt);
+ psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
ps2_packet_cnt = 0;
ps2_last_second = jiffies_msec;
}
@@ -821,9 +821,9 @@ int fsp_init(struct psmouse *psmouse)
return -ENODEV;
}
- printk(KERN_INFO
- "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
- ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
+ psmouse_info(psmouse,
+ "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
+ ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
if (!priv)
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h
index ed1395a..2e4af24 100644
--- a/drivers/input/mouse/sentelic.h
+++ b/drivers/input/mouse/sentelic.h
@@ -2,7 +2,7 @@
* Finger Sensing Pad PS/2 mouse driver.
*
* Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
- * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation.
+ * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -33,6 +33,7 @@
/* Finger-sensing Pad control registers */
#define FSP_REG_SYSCTL1 0x10
#define FSP_BIT_EN_REG_CLK BIT(5)
+#define FSP_REG_TMOD_STATUS 0x20
#define FSP_REG_OPC_QDOWN 0x31
#define FSP_BIT_EN_OPC_TAG BIT(7)
#define FSP_REG_OPTZ_XLO 0x34
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 6ad728f..91e94ad 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -40,11 +40,43 @@
* Note that newer firmware allows querying device for maximum useable
* coordinates.
*/
+#define XMIN 0
+#define XMAX 6143
+#define YMIN 0
+#define YMAX 6143
#define XMIN_NOMINAL 1472
#define XMAX_NOMINAL 5472
#define YMIN_NOMINAL 1408
#define YMAX_NOMINAL 4448
+/* Size in bits of absolute position values reported by the hardware */
+#define ABS_POS_BITS 13
+
+/*
+ * These values should represent the absolute maximum value that will
+ * be reported for a positive position value. Some Synaptics firmware
+ * uses this value to indicate a finger near the edge of the touchpad
+ * whose precise position cannot be determined.
+ *
+ * At least one touchpad is known to report positions in excess of this
+ * value which are actually negative values truncated to the 13-bit
+ * reporting range. These values have never been observed to be lower
+ * than 8184 (i.e. -8), so we treat all values greater than 8176 as
+ * negative and any other value as positive.
+ */
+#define X_MAX_POSITIVE 8176
+#define Y_MAX_POSITIVE 8176
+
+/*
+ * Synaptics touchpads report the y coordinate from bottom to top, which is
+ * opposite from what userspace expects.
+ * This function is used to invert y before reporting.
+ */
+static int synaptics_invert_y(int y)
+{
+ return YMAX_NOMINAL + YMIN_NOMINAL - y;
+}
+
/*****************************************************************************
* Stuff we need even when we do not want native Synaptics support
@@ -158,8 +190,8 @@ static int synaptics_capability(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
- printk(KERN_ERR "Synaptics claims to have extended capabilities,"
- " but I'm not able to read them.\n");
+ psmouse_warn(psmouse,
+ "device claims to have extended capabilities, but I'm not able to read them.\n");
} else {
priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
@@ -174,8 +206,8 @@ static int synaptics_capability(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
- printk(KERN_ERR "Synaptics claims to have extended capability 0x0c,"
- " but I'm not able to read it.\n");
+ psmouse_warn(psmouse,
+ "device claims to have extended capability 0x0c, but I'm not able to read it.\n");
} else {
priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
}
@@ -205,30 +237,57 @@ static int synaptics_identify(struct psmouse *psmouse)
* Read touchpad resolution and maximum reported coordinates
* Resolution is left zero if touchpad does not support the query
*/
+
+static const int *quirk_min_max;
+
static int synaptics_resolution(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
- unsigned char res[3];
- unsigned char max[3];
+ unsigned char resp[3];
if (SYN_ID_MAJOR(priv->identity) < 4)
return 0;
- if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) {
- if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) {
- priv->x_res = res[0]; /* x resolution in units/mm */
- priv->y_res = res[2]; /* y resolution in units/mm */
+ if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
+ if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
+ priv->x_res = resp[0]; /* x resolution in units/mm */
+ priv->y_res = resp[2]; /* y resolution in units/mm */
}
}
+ if (quirk_min_max) {
+ priv->x_min = quirk_min_max[0];
+ priv->x_max = quirk_min_max[1];
+ priv->y_min = quirk_min_max[2];
+ priv->y_max = quirk_min_max[3];
+ return 0;
+ }
+
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
- if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) {
- printk(KERN_ERR "Synaptics claims to have dimensions query,"
- " but I'm not able to read it.\n");
+ if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
+ psmouse_warn(psmouse,
+ "device claims to have max coordinates query, but I'm not able to read it.\n");
} else {
- priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1);
- priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3);
+ priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+ priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+ }
+ }
+
+ if (SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c) &&
+ (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 ||
+ /*
+ * Firmware v8.1 does not report proper number of extended
+ * capabilities, but has been proven to report correct min
+ * coordinates.
+ */
+ SYN_ID_FULL(priv->identity) == 0x801)) {
+ if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
+ psmouse_warn(psmouse,
+ "device claims to have min coordinates query, but I'm not able to read it.\n");
+ } else {
+ priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+ priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
}
}
@@ -285,7 +344,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
static unsigned char param = 0xc8;
struct synaptics_data *priv = psmouse->private;
- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
return 0;
if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
@@ -368,7 +428,8 @@ static void synaptics_pt_activate(struct psmouse *psmouse)
priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
if (synaptics_mode_cmd(psmouse, priv->mode))
- printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
+ psmouse_warn(psmouse,
+ "failed to switch guest protocol\n");
}
}
@@ -378,7 +439,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio) {
- printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
+ psmouse_err(psmouse,
+ "not enough memory for pass-through port\n");
return;
}
@@ -392,7 +454,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
psmouse->pt_activate = synaptics_pt_activate;
- printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
+ psmouse_info(psmouse, "serio: %s port at %s\n",
+ serio->name, psmouse->phys);
serio_register_port(serio);
}
@@ -400,6 +463,58 @@ static void synaptics_pt_create(struct psmouse *psmouse)
* Functions to interpret the absolute mode packets
****************************************************************************/
+static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
+ int sgm, int agm)
+{
+ state->count = count;
+ state->sgm = sgm;
+ state->agm = agm;
+}
+
+static void synaptics_parse_agm(const unsigned char buf[],
+ struct synaptics_data *priv,
+ struct synaptics_hw_state *hw)
+{
+ struct synaptics_hw_state *agm = &priv->agm;
+ int agm_packet_type;
+
+ agm_packet_type = (buf[5] & 0x30) >> 4;
+ switch (agm_packet_type) {
+ case 1:
+ /* Gesture packet: (x, y, z) half resolution */
+ agm->w = hw->w;
+ agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+ agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+ agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+ break;
+
+ case 2:
+ /* AGM-CONTACT packet: (count, sgm, agm) */
+ synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Record that at least one AGM has been received since last SGM */
+ priv->agm_pending = true;
+}
+
+static void synaptics_parse_ext_buttons(const unsigned char buf[],
+ struct synaptics_data *priv,
+ struct synaptics_hw_state *hw)
+{
+ unsigned int ext_bits =
+ (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
+ unsigned int ext_mask = (1U << ext_bits) - 1;
+
+ hw->ext_buttons = buf[4] & ext_mask;
+ hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits;
+}
+
+static bool is_forcepad;
+
static int synaptics_parse_hw_state(const unsigned char buf[],
struct synaptics_data *priv,
struct synaptics_hw_state *hw)
@@ -407,30 +522,65 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
memset(hw, 0, sizeof(struct synaptics_hw_state));
if (SYN_MODEL_NEWABS(priv->model_id)) {
+ hw->w = (((buf[0] & 0x30) >> 2) |
+ ((buf[0] & 0x04) >> 1) |
+ ((buf[3] & 0x04) >> 2));
+
+ if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
+ hw->w == 2) {
+ synaptics_parse_agm(buf, priv, hw);
+ return 1;
+ }
+
hw->x = (((buf[3] & 0x10) << 8) |
((buf[1] & 0x0f) << 8) |
buf[4]);
hw->y = (((buf[3] & 0x20) << 7) |
((buf[1] & 0xf0) << 4) |
buf[5]);
-
hw->z = buf[2];
- hw->w = (((buf[0] & 0x30) >> 2) |
- ((buf[0] & 0x04) >> 1) |
- ((buf[3] & 0x04) >> 2));
-
- if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
- /* Gesture packet: (x, y, z) at half resolution */
- priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
- priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
- priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
- return 1;
- }
hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0;
- if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
+ if (is_forcepad) {
+ /*
+ * ForcePads, like Clickpads, use middle button
+ * bits to report primary button clicks.
+ * Unfortunately they report primary button not
+ * only when user presses on the pad above certain
+ * threshold, but also when there are more than one
+ * finger on the touchpad, which interferes with
+ * out multi-finger gestures.
+ */
+ if (hw->z == 0) {
+ /* No contacts */
+ priv->press = priv->report_press = false;
+ } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
+ /*
+ * Single-finger touch with pressure above
+ * the threshold. If pressure stays long
+ * enough, we'll start reporting primary
+ * button. We rely on the device continuing
+ * sending data even if finger does not
+ * move.
+ */
+ if (!priv->press) {
+ priv->press_start = jiffies;
+ priv->press = true;
+ } else if (time_after(jiffies,
+ priv->press_start +
+ msecs_to_jiffies(50))) {
+ priv->report_press = true;
+ }
+ } else {
+ priv->press = false;
+ }
+
+ hw->left = priv->report_press;
+
+ } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
/*
* Clickpad's button is transmitted as middle button,
* however, since it is primary button, we will report
@@ -449,28 +599,9 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
}
- if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
+ if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 &&
((buf[0] ^ buf[3]) & 0x02)) {
- switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
- default:
- /*
- * if nExtBtn is greater than 8 it should be
- * considered invalid and treated as 0
- */
- break;
- case 8:
- hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
- hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
- case 6:
- hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
- hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
- case 4:
- hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
- hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
- case 2:
- hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
- hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
- }
+ synaptics_parse_ext_buttons(buf, priv, hw);
}
} else {
hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
@@ -483,17 +614,33 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
hw->right = (buf[0] & 0x02) ? 1 : 0;
}
+ /*
+ * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
+ * is used by some firmware to indicate a finger at the edge of
+ * the touchpad whose precise position cannot be determined, so
+ * convert these values to the maximum axis value.
+ */
+ if (hw->x > X_MAX_POSITIVE)
+ hw->x -= 1 << ABS_POS_BITS;
+ else if (hw->x == X_MAX_POSITIVE)
+ hw->x = XMAX;
+
+ if (hw->y > Y_MAX_POSITIVE)
+ hw->y -= 1 << ABS_POS_BITS;
+ else if (hw->y == Y_MAX_POSITIVE)
+ hw->y = YMAX;
+
return 0;
}
-static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
+static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
+ bool active, int x, int y)
{
input_mt_slot(dev, slot);
input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
if (active) {
input_report_abs(dev, ABS_MT_POSITION_X, x);
- input_report_abs(dev, ABS_MT_POSITION_Y,
- YMAX_NOMINAL + YMIN_NOMINAL - y);
+ input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
}
}
@@ -503,17 +650,423 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
int num_fingers)
{
if (num_fingers >= 2) {
- set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
- set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
+ synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
+ min(a->y, b->y));
+ synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
+ max(a->y, b->y));
} else if (num_fingers == 1) {
- set_slot(dev, 0, true, a->x, a->y);
- set_slot(dev, 1, false, 0, 0);
+ synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
+ synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
} else {
- set_slot(dev, 0, false, 0, 0);
- set_slot(dev, 1, false, 0, 0);
+ synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
+ synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
+ }
+}
+
+static void synaptics_report_ext_buttons(struct psmouse *psmouse,
+ const struct synaptics_hw_state *hw)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+ int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
+ int i;
+
+ if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+ return;
+
+ /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */
+ if (SYN_ID_FULL(priv->identity) == 0x801 &&
+ !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02))
+ return;
+
+ for (i = 0; i < ext_bits; i++) {
+ input_report_key(dev, BTN_0 + 2 * i,
+ hw->ext_buttons & (1 << i));
+ input_report_key(dev, BTN_1 + 2 * i,
+ hw->ext_buttons & (1 << (i + ext_bits)));
+ }
+}
+
+static void synaptics_report_buttons(struct psmouse *psmouse,
+ const struct synaptics_hw_state *hw)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+
+ input_report_key(dev, BTN_LEFT, hw->left);
+ input_report_key(dev, BTN_RIGHT, hw->right);
+
+ if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+ input_report_key(dev, BTN_MIDDLE, hw->middle);
+
+ if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+ input_report_key(dev, BTN_FORWARD, hw->up);
+ input_report_key(dev, BTN_BACK, hw->down);
+ }
+
+ synaptics_report_ext_buttons(psmouse, hw);
+}
+
+static void synaptics_report_slot(struct input_dev *dev, int slot,
+ const struct synaptics_hw_state *hw)
+{
+ input_mt_slot(dev, slot);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
+ if (!hw)
+ return;
+
+ input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
+ input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
+}
+
+static void synaptics_report_mt_data(struct psmouse *psmouse,
+ struct synaptics_mt_state *mt_state,
+ const struct synaptics_hw_state *sgm)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_hw_state *agm = &priv->agm;
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ switch (mt_state->count) {
+ case 0:
+ synaptics_report_slot(dev, 0, NULL);
+ synaptics_report_slot(dev, 1, NULL);
+ break;
+ case 1:
+ if (mt_state->sgm == -1) {
+ synaptics_report_slot(dev, 0, NULL);
+ synaptics_report_slot(dev, 1, NULL);
+ } else if (mt_state->sgm == 0) {
+ synaptics_report_slot(dev, 0, sgm);
+ synaptics_report_slot(dev, 1, NULL);
+ } else {
+ synaptics_report_slot(dev, 0, NULL);
+ synaptics_report_slot(dev, 1, sgm);
+ }
+ break;
+ default:
+ /*
+ * If the finger slot contained in SGM is valid, and either
+ * hasn't changed, or is new, then report SGM in MTB slot 0.
+ * Otherwise, empty MTB slot 0.
+ */
+ if (mt_state->sgm != -1 &&
+ (mt_state->sgm == old->sgm || old->sgm == -1))
+ synaptics_report_slot(dev, 0, sgm);
+ else
+ synaptics_report_slot(dev, 0, NULL);
+
+ /*
+ * If the finger slot contained in AGM is valid, and either
+ * hasn't changed, or is new, then report AGM in MTB slot 1.
+ * Otherwise, empty MTB slot 1.
+ */
+ if (mt_state->agm != -1 &&
+ (mt_state->agm == old->agm || old->agm == -1))
+ synaptics_report_slot(dev, 1, agm);
+ else
+ synaptics_report_slot(dev, 1, NULL);
+ break;
+ }
+
+ /* Don't use active slot count to generate BTN_TOOL events. */
+ input_mt_report_pointer_emulation(dev, false);
+
+ /* Send the number of fingers reported by touchpad itself. */
+ input_mt_report_finger_count(dev, mt_state->count);
+
+ synaptics_report_buttons(psmouse, sgm);
+
+ input_sync(dev);
+}
+
+/* Handle case where mt_state->count = 0 */
+static void synaptics_image_sensor_0f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ synaptics_mt_state_set(mt_state, 0, -1, -1);
+ priv->mt_state_lost = false;
+}
+
+/* Handle case where mt_state->count = 1 */
+static void synaptics_image_sensor_1f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ struct synaptics_hw_state *agm = &priv->agm;
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ /*
+ * If the last AGM was (0,0,0), and there is only one finger left,
+ * then we absolutely know that SGM contains slot 0, and all other
+ * fingers have been removed.
+ */
+ if (priv->agm_pending && agm->z == 0) {
+ synaptics_mt_state_set(mt_state, 1, 0, -1);
+ priv->mt_state_lost = false;
+ return;
+ }
+
+ switch (old->count) {
+ case 0:
+ synaptics_mt_state_set(mt_state, 1, 0, -1);
+ break;
+ case 1:
+ /*
+ * If mt_state_lost, then the previous transition was 3->1,
+ * and SGM now contains either slot 0 or 1, but we don't know
+ * which. So, we just assume that the SGM now contains slot 1.
+ *
+ * If pending AGM and either:
+ * (a) the previous SGM slot contains slot 0, or
+ * (b) there was no SGM slot
+ * then, the SGM now contains slot 1
+ *
+ * Case (a) happens with very rapid "drum roll" gestures, where
+ * slot 0 finger is lifted and a new slot 1 finger touches
+ * within one reporting interval.
+ *
+ * Case (b) happens if initially two or more fingers tap
+ * briefly, and all but one lift before the end of the first
+ * reporting interval.
+ *
+ * (In both these cases, slot 0 will becomes empty, so SGM
+ * contains slot 1 with the new finger)
+ *
+ * Else, if there was no previous SGM, it now contains slot 0.
+ *
+ * Otherwise, SGM still contains the same slot.
+ */
+ if (priv->mt_state_lost ||
+ (priv->agm_pending && old->sgm <= 0))
+ synaptics_mt_state_set(mt_state, 1, 1, -1);
+ else if (old->sgm == -1)
+ synaptics_mt_state_set(mt_state, 1, 0, -1);
+ break;
+ case 2:
+ /*
+ * If mt_state_lost, we don't know which finger SGM contains.
+ *
+ * So, report 1 finger, but with both slots empty.
+ * We will use slot 1 on subsequent 1->1
+ */
+ if (priv->mt_state_lost) {
+ synaptics_mt_state_set(mt_state, 1, -1, -1);
+ break;
+ }
+ /*
+ * Since the last AGM was NOT (0,0,0), it was the finger in
+ * slot 0 that has been removed.
+ * So, SGM now contains previous AGM's slot, and AGM is now
+ * empty.
+ */
+ synaptics_mt_state_set(mt_state, 1, old->agm, -1);
+ break;
+ case 3:
+ /*
+ * Since last AGM was not (0,0,0), we don't know which finger
+ * is left.
+ *
+ * So, report 1 finger, but with both slots empty.
+ * We will use slot 1 on subsequent 1->1
+ */
+ synaptics_mt_state_set(mt_state, 1, -1, -1);
+ priv->mt_state_lost = true;
+ break;
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
+ }
+}
+
+/* Handle case where mt_state->count = 2 */
+static void synaptics_image_sensor_2f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ switch (old->count) {
+ case 0:
+ synaptics_mt_state_set(mt_state, 2, 0, 1);
+ break;
+ case 1:
+ /*
+ * If previous SGM contained slot 1 or higher, SGM now contains
+ * slot 0 (the newly touching finger) and AGM contains SGM's
+ * previous slot.
+ *
+ * Otherwise, SGM still contains slot 0 and AGM now contains
+ * slot 1.
+ */
+ if (old->sgm >= 1)
+ synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
+ else
+ synaptics_mt_state_set(mt_state, 2, 0, 1);
+ break;
+ case 2:
+ /*
+ * If mt_state_lost, SGM now contains either finger 1 or 2, but
+ * we don't know which.
+ * So, we just assume that the SGM contains slot 0 and AGM 1.
+ */
+ if (priv->mt_state_lost)
+ synaptics_mt_state_set(mt_state, 2, 0, 1);
+ /*
+ * Otherwise, use the same mt_state, since it either hasn't
+ * changed, or was updated by a recently received AGM-CONTACT
+ * packet.
+ */
+ break;
+ case 3:
+ /*
+ * 3->2 transitions have two unsolvable problems:
+ * 1) no indication is given which finger was removed
+ * 2) no way to tell if agm packet was for finger 3
+ * before 3->2, or finger 2 after 3->2.
+ *
+ * So, report 2 fingers, but empty all slots.
+ * We will guess slots [0,1] on subsequent 2->2.
+ */
+ synaptics_mt_state_set(mt_state, 2, -1, -1);
+ priv->mt_state_lost = true;
+ break;
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
}
}
+/* Handle case where mt_state->count = 3 */
+static void synaptics_image_sensor_3f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ switch (old->count) {
+ case 0:
+ synaptics_mt_state_set(mt_state, 3, 0, 2);
+ break;
+ case 1:
+ /*
+ * If previous SGM contained slot 2 or higher, SGM now contains
+ * slot 0 (one of the newly touching fingers) and AGM contains
+ * SGM's previous slot.
+ *
+ * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
+ */
+ if (old->sgm >= 2)
+ synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
+ else
+ synaptics_mt_state_set(mt_state, 3, 0, 2);
+ break;
+ case 2:
+ /*
+ * If the AGM previously contained slot 3 or higher, then the
+ * newly touching finger is in the lowest available slot.
+ *
+ * If SGM was previously 1 or higher, then the new SGM is
+ * now slot 0 (with a new finger), otherwise, the new finger
+ * is now in a hidden slot between 0 and AGM's slot.
+ *
+ * In all such cases, the SGM now contains slot 0, and the AGM
+ * continues to contain the same slot as before.
+ */
+ if (old->agm >= 3) {
+ synaptics_mt_state_set(mt_state, 3, 0, old->agm);
+ break;
+ }
+
+ /*
+ * After some 3->1 and all 3->2 transitions, we lose track
+ * of which slot is reported by SGM and AGM.
+ *
+ * For 2->3 in this state, report 3 fingers, but empty all
+ * slots, and we will guess (0,2) on a subsequent 0->3.
+ *
+ * To userspace, the resulting transition will look like:
+ * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
+ */
+ if (priv->mt_state_lost) {
+ synaptics_mt_state_set(mt_state, 3, -1, -1);
+ break;
+ }
+
+ /*
+ * If the (SGM,AGM) really previously contained slots (0, 1),
+ * then we cannot know what slot was just reported by the AGM,
+ * because the 2->3 transition can occur either before or after
+ * the AGM packet. Thus, this most recent AGM could contain
+ * either the same old slot 1 or the new slot 2.
+ * Subsequent AGMs will be reporting slot 2.
+ *
+ * To userspace, the resulting transition will look like:
+ * 2:[0,1] -> 3:[0,-1] -> 3:[0,2]
+ */
+ synaptics_mt_state_set(mt_state, 3, 0, -1);
+ break;
+ case 3:
+ /*
+ * If, for whatever reason, the previous agm was invalid,
+ * Assume SGM now contains slot 0, AGM now contains slot 2.
+ */
+ if (old->agm <= 2)
+ synaptics_mt_state_set(mt_state, 3, 0, 2);
+ /*
+ * mt_state either hasn't changed, or was updated by a recently
+ * received AGM-CONTACT packet.
+ */
+ break;
+
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
+ }
+}
+
+/* Handle case where mt_state->count = 4, or = 5 */
+static void synaptics_image_sensor_45f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ /* mt_state was updated correctly by AGM-CONTACT packet */
+ priv->mt_state_lost = false;
+}
+
+static void synaptics_image_sensor_process(struct psmouse *psmouse,
+ struct synaptics_hw_state *sgm)
+{
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_hw_state *agm = &priv->agm;
+ struct synaptics_mt_state mt_state;
+
+ /* Initialize using current mt_state (as updated by last agm) */
+ mt_state = agm->mt_state;
+
+ /*
+ * Update mt_state using the new finger count and current mt_state.
+ */
+ if (sgm->z == 0)
+ synaptics_image_sensor_0f(priv, &mt_state);
+ else if (sgm->w >= 4)
+ synaptics_image_sensor_1f(priv, &mt_state);
+ else if (sgm->w == 0)
+ synaptics_image_sensor_2f(priv, &mt_state);
+ else if (sgm->w == 1 && mt_state.count <= 3)
+ synaptics_image_sensor_3f(priv, &mt_state);
+ else
+ synaptics_image_sensor_45f(priv, &mt_state);
+
+ /* Send resulting input events to user space */
+ synaptics_report_mt_data(psmouse, &mt_state, sgm);
+
+ /* Store updated mt_state */
+ priv->mt_state = agm->mt_state = mt_state;
+ priv->agm_pending = false;
+}
+
/*
* called for each full received packet from the touchpad
*/
@@ -524,11 +1077,15 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct synaptics_hw_state hw;
int num_fingers;
int finger_width;
- int i;
if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
return;
+ if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+ synaptics_image_sensor_process(psmouse, &hw);
+ return;
+ }
+
if (hw.scroll) {
priv->scroll += hw.scroll;
@@ -574,7 +1131,8 @@ static void synaptics_process_packet(struct psmouse *psmouse)
}
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
- synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);
+ synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
+ num_fingers);
/* Post events
* BTN_TOUCH has to be first as mousedev relies on it when doing
@@ -585,7 +1143,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
if (num_fingers > 0) {
input_report_abs(dev, ABS_X, hw.x);
- input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
+ input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
}
input_report_abs(dev, ABS_PRESSURE, hw.z);
@@ -593,35 +1151,25 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
- input_report_key(dev, BTN_LEFT, hw.left);
- input_report_key(dev, BTN_RIGHT, hw.right);
-
if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
}
- if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
- input_report_key(dev, BTN_MIDDLE, hw.middle);
-
- if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
- input_report_key(dev, BTN_FORWARD, hw.up);
- input_report_key(dev, BTN_BACK, hw.down);
- }
-
- for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
- input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
+ synaptics_report_buttons(psmouse, &hw);
input_sync(dev);
}
-static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
+static int synaptics_validate_byte(struct psmouse *psmouse,
+ int idx, unsigned char pkt_type)
{
static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
+ const char *packet = psmouse->packet;
if (idx < 0 || idx > 4)
return 0;
@@ -639,7 +1187,7 @@ static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned cha
return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
default:
- printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
+ psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
return 0;
}
}
@@ -649,8 +1197,8 @@ static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
int i;
for (i = 0; i < 5; i++)
- if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
- printk(KERN_INFO "synaptics: using relaxed packet validation\n");
+ if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
+ psmouse_info(psmouse, "using relaxed packet validation\n");
return SYN_NEWABS_RELAXED;
}
@@ -675,13 +1223,30 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
return PSMOUSE_FULL_PACKET;
}
- return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
+ return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
}
/*****************************************************************************
* Driver initialization/cleanup functions
****************************************************************************/
+static void set_abs_position_params(struct input_dev *dev,
+ struct synaptics_data *priv, int x_code,
+ int y_code)
+{
+ int x_min = priv->x_min ?: XMIN_NOMINAL;
+ int x_max = priv->x_max ?: XMAX_NOMINAL;
+ int y_min = priv->y_min ?: YMIN_NOMINAL;
+ int y_max = priv->y_max ?: YMAX_NOMINAL;
+ int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
+ SYN_REDUCED_FILTER_FUZZ : 0;
+
+ input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
+ input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
+ input_abs_set_res(dev, x_code, priv->x_res);
+ input_abs_set_res(dev, y_code, priv->y_res);
+}
+
static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
{
int i;
@@ -689,19 +1254,25 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
__set_bit(INPUT_PROP_POINTER, dev->propbit);
__set_bit(EV_ABS, dev->evbit);
- input_set_abs_params(dev, ABS_X,
- XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0);
- input_set_abs_params(dev, ABS_Y,
- YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
+ set_abs_position_params(dev, priv, ABS_X, ABS_Y);
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
- if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+ if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+ input_mt_init_slots(dev, 2);
+ set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+ ABS_MT_POSITION_Y);
+ /* Image sensors can report per-contact pressure */
+ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ /* Image sensors can signal 4 and 5 finger clicks */
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+ } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+ /* Non-image sensors with AGM use semi-mt */
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2);
- input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
- priv->x_max ?: XMAX_NOMINAL, 0, 0);
- input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
- priv->y_max ?: YMAX_NOMINAL, 0, 0);
+ set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+ ABS_MT_POSITION_Y);
}
if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -734,9 +1305,6 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
__clear_bit(REL_X, dev->relbit);
__clear_bit(REL_Y, dev->relbit);
- input_abs_set_res(dev, ABS_X, priv->x_res);
- input_abs_set_res(dev, ABS_Y, priv->y_res);
-
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
/* Clickpads report only left button */
@@ -778,21 +1346,21 @@ static int synaptics_reconnect(struct psmouse *psmouse)
return -1;
if (retry > 1)
- printk(KERN_DEBUG "Synaptics reconnected after %d tries\n",
- retry);
+ psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
if (synaptics_query_hardware(psmouse)) {
- printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to query device.\n");
return -1;
}
if (synaptics_set_absolute_mode(psmouse)) {
- printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to initialize device.\n");
return -1;
}
if (synaptics_set_advanced_gesture_mode(psmouse)) {
- printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+ psmouse_err(psmouse,
+ "Advanced gesture mode reconnect failed.\n");
return -1;
}
@@ -800,12 +1368,12 @@ static int synaptics_reconnect(struct psmouse *psmouse)
old_priv.model_id != priv->model_id ||
old_priv.capabilities != priv->capabilities ||
old_priv.ext_cap != priv->ext_cap) {
- printk(KERN_ERR "Synaptics hardware appears to be different: "
- "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
- old_priv.identity, priv->identity,
- old_priv.model_id, priv->model_id,
- old_priv.capabilities, priv->capabilities,
- old_priv.ext_cap, priv->ext_cap);
+ psmouse_err(psmouse,
+ "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
+ old_priv.identity, priv->identity,
+ old_priv.model_id, priv->model_id,
+ old_priv.capabilities, priv->capabilities,
+ old_priv.ext_cap, priv->ext_cap);
return -1;
}
@@ -866,10 +1434,130 @@ static const struct dmi_system_id __initconst olpc_dmi_table[] = {
{ }
};
+static const struct dmi_system_id min_max_dmi_table[] __initconst = {
+#if defined(CONFIG_DMI)
+ {
+ /* Lenovo ThinkPad Helix */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
+ },
+ .driver_data = (int []){1024, 5052, 2258, 4832},
+ },
+ {
+ /* Lenovo ThinkPad X240 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"),
+ },
+ .driver_data = (int []){1232, 5710, 1156, 4696},
+ },
+ {
+ /* Lenovo ThinkPad Edge E431 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E431"),
+ },
+ .driver_data = (int []){1024, 5022, 2508, 4832},
+ },
+ {
+ /* Lenovo ThinkPad T431s */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+ {
+ /* Lenovo ThinkPad T440s */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+ {
+ /* Lenovo ThinkPad L440 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+ {
+ /* Lenovo ThinkPad T540p */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+ {
+ /* Lenovo ThinkPad L540 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+ {
+ /* Lenovo ThinkPad W540 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W540"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+ {
+ /* Lenovo Yoga S1 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+ "ThinkPad S1 Yoga"),
+ },
+ .driver_data = (int []){1232, 5710, 1156, 4696},
+ },
+ {
+ /* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,
+ "ThinkPad X1 Carbon 2nd"),
+ },
+ .driver_data = (int []){1024, 5112, 2024, 4832},
+ },
+#endif
+ { }
+};
+
+static const struct dmi_system_id forcepad_dmi_table[] __initconst = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Folio 1040 G1"),
+ },
+ },
+#endif
+ { }
+};
+
void __init synaptics_module_init(void)
{
+ const struct dmi_system_id *min_max_dmi;
+
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
broken_olpc_ec = dmi_check_system(olpc_dmi_table);
+
+ min_max_dmi = dmi_first_match(min_max_dmi_table);
+ if (min_max_dmi)
+ quirk_min_max = min_max_dmi->driver_data;
+
+ /*
+ * Unfortunately ForcePad capability is not exported over PS/2,
+ * so we have to resort to checking DMI.
+ */
+ is_forcepad = dmi_check_system(forcepad_dmi_table);
}
int synaptics_init(struct psmouse *psmouse)
@@ -886,7 +1574,8 @@ int synaptics_init(struct psmouse *psmouse)
* just fine.
*/
if (broken_olpc_ec) {
- printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n");
+ psmouse_info(psmouse,
+ "OLPC XO detected, not enabling Synaptics protocol.\n");
return -ENODEV;
}
@@ -897,26 +1586,28 @@ int synaptics_init(struct psmouse *psmouse)
psmouse_reset(psmouse);
if (synaptics_query_hardware(psmouse)) {
- printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to query device.\n");
goto init_fail;
}
if (synaptics_set_absolute_mode(psmouse)) {
- printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to initialize device.\n");
goto init_fail;
}
if (synaptics_set_advanced_gesture_mode(psmouse)) {
- printk(KERN_ERR "Advanced gesture mode init failed.\n");
+ psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
goto init_fail;
}
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
- printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
- SYN_ID_MODEL(priv->identity),
- SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
- priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
+ psmouse_info(psmouse,
+ "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
+ SYN_ID_MODEL(priv->identity),
+ SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
+ priv->model_id,
+ priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
set_input_params(psmouse->dev, priv);
@@ -948,8 +1639,9 @@ int synaptics_init(struct psmouse *psmouse)
* the same rate as a standard PS/2 mouse).
*/
if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
- printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
- dmi_get_system_info(DMI_PRODUCT_NAME));
+ psmouse_info(psmouse,
+ "Toshiba %s detected, limiting rate to 40pps.\n",
+ dmi_get_system_info(DMI_PRODUCT_NAME));
psmouse->rate = 40;
}
@@ -982,4 +1674,3 @@ bool synaptics_supported(void)
}
#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
-
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 7453938..6cf156d 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -19,7 +19,8 @@
#define SYN_QUE_RESOLUTION 0x08
#define SYN_QUE_EXT_CAPAB 0x09
#define SYN_QUE_EXT_CAPAB_0C 0x0c
-#define SYN_QUE_EXT_DIMENSIONS 0x0d
+#define SYN_QUE_EXT_MAX_COORDS 0x0d
+#define SYN_QUE_EXT_MIN_COORDS 0x0f
/* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
@@ -66,18 +67,26 @@
* 1 0x60 multifinger mode identifies firmware finger counting
* (not reporting!) algorithm.
* Not particularly meaningful
- * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered
- * 2 0x01 clickpad bit 1 2-button ClickPad
- * 2 0x02 deluxe LED controls touchpad support LED commands
+ * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered
+ * 2 0x01 clickpad bit 1 2-button ClickPad
+ * 2 0x02 deluxe LED controls touchpad support LED commands
* ala multimedia control bar
* 2 0x04 reduced filtering firmware does less filtering on
* position data, driver should watch
* for noise.
+ * 2 0x08 image sensor image sensor tracks 5 fingers, but only
+ * reports 2.
+ * 2 0x01 uniform clickpad whole clickpad moves instead of being
+ * hinged at the top.
+ * 2 0x20 report min query 0x0f gives min coord reported
*/
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */
#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */
#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000)
+#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000)
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)
+#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400)
+#define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
@@ -104,10 +113,22 @@
#define SYN_NEWABS_RELAXED 2
#define SYN_OLDABS 3
+/* amount to fuzz position data when touchpad reports reduced filtering */
+#define SYN_REDUCED_FILTER_FUZZ 8
+
/*
- * A structure to describe the state of the touchpad hardware (buttons and pad)
+ * A structure to describe which internal touchpad finger slots are being
+ * reported in raw packets.
*/
+struct synaptics_mt_state {
+ int count; /* num fingers being tracked */
+ int sgm; /* which slot is reported by sgm pkt */
+ int agm; /* which slot is reported by agm pkt*/
+};
+/*
+ * A structure to describe the state of the touchpad hardware (buttons and pad)
+ */
struct synaptics_hw_state {
int x;
int y;
@@ -120,6 +141,9 @@ struct synaptics_hw_state {
unsigned int down:1;
unsigned char ext_buttons;
signed char scroll;
+
+ /* As reported in last AGM-CONTACT packets */
+ struct synaptics_mt_state mt_state;
};
struct synaptics_data {
@@ -130,7 +154,8 @@ struct synaptics_data {
unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */
unsigned long int identity; /* Identification */
unsigned int x_res, y_res; /* X/Y resolution in units/mm */
- unsigned int x_max, y_max; /* Max dimensions (from FW) */
+ unsigned int x_max, y_max; /* Max coordinates (from FW) */
+ unsigned int x_min, y_min; /* Min coordinates (from FW) */
unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */
@@ -138,7 +163,20 @@ struct synaptics_data {
struct serio *pt_port; /* Pass-through serio port */
- struct synaptics_hw_state mt; /* current gesture packet */
+ struct synaptics_mt_state mt_state; /* Current mt finger state */
+ bool mt_state_lost; /* mt_state may be incorrect */
+
+ /*
+ * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
+ * contains position data for a second contact, at half resolution.
+ */
+ struct synaptics_hw_state agm;
+ bool agm_pending; /* new AGM packet received */
+
+ /* ForcePad handling */
+ unsigned long press_start;
+ bool press;
+ bool report_press;
};
void synaptics_module_init(void);
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index cba3c84..4b755cb 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -570,7 +570,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client,
"Requesting IRQ: %d\n", touch->client->irq);
ret = request_irq(touch->client->irq, synaptics_i2c_irq,
- IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING,
+ IRQ_TYPE_EDGE_FALLING,
DRIVER_NAME, touch);
if (ret) {
dev_warn(&touch->client->dev,
@@ -619,7 +619,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int synaptics_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 4b2a42f..d4d08bd 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -24,6 +24,7 @@
#include <linux/irq.h>
#include <linux/serio.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/mach-types.h>
#include <plat/board-ams-delta.h>
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
index 6ee8f0d..95280f9 100644
--- a/drivers/input/serio/at32psif.c
+++ b/drivers/input/serio/at32psif.c
@@ -372,6 +372,6 @@ static void __exit psif_exit(void)
module_init(psif_init);
module_exit(psif_exit);
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 4220620..979c443 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
/************************* Keepalive timer task *********************/
-void hp_sdc_kicker (unsigned long data)
+static void hp_sdc_kicker(unsigned long data)
{
tasklet_schedule(&hp_sdc.task);
/* Re-insert the periodic task. */
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 20153fe..858b0e3 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -101,6 +101,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"),
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
@@ -146,6 +152,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
},
},
{
+ /* Medion Akoya E7225 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
+ },
+ },
+ {
/* Blue FB5601 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "blue"),
@@ -402,6 +416,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
},
},
{
+ /* Acer Aspire 7738 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),
+ },
+ },
+ {
/* Gericom Bellagio */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
@@ -451,6 +472,20 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
},
},
+ {
+ /* Newer HP Pavilion dv4 models */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+ },
+ },
+ {
+ /* Avatar AVIU-145A6 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
+ },
+ },
{ }
};
@@ -580,6 +615,37 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
},
},
+ {
+ /* Newer HP Pavilion dv4 models */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+ },
+ },
+ {
+ /* Fujitsu A544 laptop */
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),
+ },
+ },
+ {
+ /* Fujitsu AH544 laptop */
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
+ },
+ },
+ {
+ /* Fujitsu U574 laptop */
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
+ },
+ },
{ }
};
@@ -663,6 +729,35 @@ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
{ }
};
+/*
+ * Some laptops need keyboard reset before probing for the trackpad to get
+ * it detected, initialised & finally work.
+ */
+static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
+ {
+ /* Gigabyte P35 v2 - Elantech touchpad */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),
+ },
+ },
+ {
+ /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X3"),
+ },
+ },
+ {
+ /* Gigabyte P34 - Elantech touchpad */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
+ },
+ },
+ { }
+};
+
#endif /* CONFIG_X86 */
#ifdef CONFIG_PNP
@@ -941,6 +1036,9 @@ static int __init i8042_platform_init(void)
if (dmi_check_system(i8042_dmi_dritek_table))
i8042_dritek = true;
+ if (dmi_check_system(i8042_dmi_kbdreset_table))
+ i8042_kbdreset = true;
+
/*
* A20 was already enabled during early kernel init. But some buggy
* BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index d37a48e..178e75d 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -67,6 +67,10 @@ static bool i8042_notimeout;
module_param_named(notimeout, i8042_notimeout, bool, 0);
MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042");
+static bool i8042_kbdreset;
+module_param_named(kbdreset, i8042_kbdreset, bool, 0);
+MODULE_PARM_DESC(kbdreset, "Reset device connected to KBD port");
+
#ifdef CONFIG_X86
static bool i8042_dritek;
module_param_named(dritek, i8042_dritek, bool, 0);
@@ -783,6 +787,16 @@ static int __init i8042_check_aux(void)
return -1;
/*
+ * Reset keyboard (needed on some laptops to successfully detect
+ * touchpad, e.g., some Gigabyte laptop models with Elantech
+ * touchpads).
+ */
+ if (i8042_kbdreset) {
+ pr_warn("Attempting to reset device connected to KBD port\n");
+ i8042_kbd_write(NULL, (unsigned char) 0xff);
+ }
+
+/*
* Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and
* used it for a PCI card or somethig else.
*/
@@ -991,7 +1005,7 @@ static int i8042_controller_init(void)
* Reset the controller and reset CRT to the original value set by BIOS.
*/
-static void i8042_controller_reset(void)
+static void i8042_controller_reset(bool force_reset)
{
i8042_flush();
@@ -1016,7 +1030,7 @@ static void i8042_controller_reset(void)
* Reset the controller if requested.
*/
- if (i8042_reset)
+ if (i8042_reset || force_reset)
i8042_controller_selftest();
/*
@@ -1139,9 +1153,9 @@ static int i8042_controller_resume(bool force_reset)
* upsetting it.
*/
-static int i8042_pm_reset(struct device *dev)
+static int i8042_pm_suspend(struct device *dev)
{
- i8042_controller_reset();
+ i8042_controller_reset(true);
return 0;
}
@@ -1163,13 +1177,20 @@ static int i8042_pm_thaw(struct device *dev)
return 0;
}
+static int i8042_pm_reset(struct device *dev)
+{
+ i8042_controller_reset(false);
+
+ return 0;
+}
+
static int i8042_pm_restore(struct device *dev)
{
return i8042_controller_resume(false);
}
static const struct dev_pm_ops i8042_pm_ops = {
- .suspend = i8042_pm_reset,
+ .suspend = i8042_pm_suspend,
.resume = i8042_pm_resume,
.thaw = i8042_pm_thaw,
.poweroff = i8042_pm_reset,
@@ -1185,7 +1206,7 @@ static const struct dev_pm_ops i8042_pm_ops = {
static void i8042_shutdown(struct platform_device *dev)
{
- i8042_controller_reset();
+ i8042_controller_reset(false);
}
static int __init i8042_create_kbd_port(void)
@@ -1424,7 +1445,7 @@ static int __init i8042_probe(struct platform_device *dev)
out_fail:
i8042_free_aux_ports(); /* in case KBD failed but AUX not */
i8042_free_irqs();
- i8042_controller_reset();
+ i8042_controller_reset(false);
i8042_platform_device = NULL;
return error;
@@ -1434,7 +1455,7 @@ static int __devexit i8042_remove(struct platform_device *dev)
{
i8042_unregister_ports();
i8042_free_irqs();
- i8042_controller_reset();
+ i8042_controller_reset(false);
i8042_platform_device = NULL;
return 0;
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 980af94..07a8363 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -210,7 +210,7 @@ int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
/*
* Some devices (Synaptics) peform the reset before
* ACKing the reset command, and so it can take a long
- * time before the ACK arrrives.
+ * time before the ACK arrives.
*/
if (ps2_sendbyte(ps2dev, command & 0xff,
command == PS2_CMD_RESET_BAT ? 1000 : 200))
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index d55874e..44fc8b4 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -300,8 +300,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
out:
sa1111_disable_device(ps2if->dev);
- release_mem_region(dev->res.start,
- dev->res.end - dev->res.start + 1);
+ release_mem_region(dev->res.start, resource_size(&dev->res));
free:
sa1111_set_drvdata(dev, NULL);
kfree(ps2if);
@@ -317,8 +316,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev)
struct ps2if *ps2if = sa1111_get_drvdata(dev);
serio_unregister_port(ps2if->io);
- release_mem_region(dev->res.start,
- dev->res.end - dev->res.start + 1);
+ release_mem_region(dev->res.start, resource_size(&dev->res));
sa1111_set_drvdata(dev, NULL);
kfree(ps2if);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index b7ba459..4d4cd14 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -9,6 +9,7 @@
* the Free Software Foundation.
*/
+#include <linux/kref.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
@@ -33,15 +34,16 @@ struct serio_raw {
unsigned int tail, head;
char name[16];
- unsigned int refcnt;
+ struct kref kref;
struct serio *serio;
struct miscdevice dev;
wait_queue_head_t wait;
- struct list_head list;
+ struct list_head client_list;
struct list_head node;
+ bool dead;
};
-struct serio_raw_list {
+struct serio_raw_client {
struct fasync_struct *fasync;
struct serio_raw *serio_raw;
struct list_head node;
@@ -49,7 +51,6 @@ struct serio_raw_list {
static DEFINE_MUTEX(serio_raw_mutex);
static LIST_HEAD(serio_raw_list);
-static unsigned int serio_raw_no;
/*********************************************************************
* Interface with userspace (file operations) *
@@ -57,9 +58,9 @@ static unsigned int serio_raw_no;
static int serio_raw_fasync(int fd, struct file *file, int on)
{
- struct serio_raw_list *list = file->private_data;
+ struct serio_raw_client *client = file->private_data;
- return fasync_helper(fd, file, on, &list->fasync);
+ return fasync_helper(fd, file, on, &client->fasync);
}
static struct serio_raw *serio_raw_locate(int minor)
@@ -77,8 +78,8 @@ static struct serio_raw *serio_raw_locate(int minor)
static int serio_raw_open(struct inode *inode, struct file *file)
{
struct serio_raw *serio_raw;
- struct serio_raw_list *list;
- int retval = 0;
+ struct serio_raw_client *client;
+ int retval;
retval = mutex_lock_interruptible(&serio_raw_mutex);
if (retval)
@@ -90,60 +91,61 @@ static int serio_raw_open(struct inode *inode, struct file *file)
goto out;
}
- if (!serio_raw->serio) {
+ if (serio_raw->dead) {
retval = -ENODEV;
goto out;
}
- list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL);
- if (!list) {
+ client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL);
+ if (!client) {
retval = -ENOMEM;
goto out;
}
- list->serio_raw = serio_raw;
- file->private_data = list;
+ client->serio_raw = serio_raw;
+ file->private_data = client;
+
+ kref_get(&serio_raw->kref);
- serio_raw->refcnt++;
- list_add_tail(&list->node, &serio_raw->list);
+ serio_pause_rx(serio_raw->serio);
+ list_add_tail(&client->node, &serio_raw->client_list);
+ serio_continue_rx(serio_raw->serio);
out:
mutex_unlock(&serio_raw_mutex);
return retval;
}
-static int serio_raw_cleanup(struct serio_raw *serio_raw)
+static void serio_raw_free(struct kref *kref)
{
- if (--serio_raw->refcnt == 0) {
- misc_deregister(&serio_raw->dev);
- list_del_init(&serio_raw->node);
- kfree(serio_raw);
+ struct serio_raw *serio_raw =
+ container_of(kref, struct serio_raw, kref);
- return 1;
- }
-
- return 0;
+ put_device(&serio_raw->serio->dev);
+ kfree(serio_raw);
}
static int serio_raw_release(struct inode *inode, struct file *file)
{
- struct serio_raw_list *list = file->private_data;
- struct serio_raw *serio_raw = list->serio_raw;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
- mutex_lock(&serio_raw_mutex);
+ serio_pause_rx(serio_raw->serio);
+ list_del(&client->node);
+ serio_continue_rx(serio_raw->serio);
- serio_raw_cleanup(serio_raw);
+ kfree(client);
+
+ kref_put(&serio_raw->kref, serio_raw_free);
- mutex_unlock(&serio_raw_mutex);
return 0;
}
-static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
+static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
{
- unsigned long flags;
- int empty;
+ bool empty;
- spin_lock_irqsave(&serio_raw->serio->lock, flags);
+ serio_pause_rx(serio_raw->serio);
empty = serio_raw->head == serio_raw->tail;
if (!empty) {
@@ -151,30 +153,31 @@ static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
}
- spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+ serio_continue_rx(serio_raw->serio);
return !empty;
}
-static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
{
- struct serio_raw_list *list = file->private_data;
- struct serio_raw *serio_raw = list->serio_raw;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
char uninitialized_var(c);
ssize_t retval = 0;
- if (!serio_raw->serio)
+ if (serio_raw->dead)
return -ENODEV;
if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(list->serio_raw->wait,
- serio_raw->head != serio_raw->tail || !serio_raw->serio);
+ retval = wait_event_interruptible(serio_raw->wait,
+ serio_raw->head != serio_raw->tail || serio_raw->dead);
if (retval)
return retval;
- if (!serio_raw->serio)
+ if (serio_raw->dead)
return -ENODEV;
while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
@@ -186,9 +189,11 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou
return retval;
}
-static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
- struct serio_raw_list *list = file->private_data;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
ssize_t written = 0;
int retval;
unsigned char c;
@@ -197,7 +202,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
if (retval)
return retval;
- if (!list->serio_raw->serio) {
+ if (serio_raw->dead) {
retval = -ENODEV;
goto out;
}
@@ -210,7 +215,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
retval = -EFAULT;
goto out;
}
- if (serio_write(list->serio_raw->serio, c)) {
+ if (serio_write(serio_raw->serio, c)) {
retval = -EIO;
goto out;
}
@@ -224,46 +229,49 @@ out:
static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
{
- struct serio_raw_list *list = file->private_data;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
+ unsigned int mask;
- poll_wait(file, &list->serio_raw->wait, wait);
+ poll_wait(file, &serio_raw->wait, wait);
- if (list->serio_raw->head != list->serio_raw->tail)
+ mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM;
+ if (serio_raw->head != serio_raw->tail)
return POLLIN | POLLRDNORM;
return 0;
}
static const struct file_operations serio_raw_fops = {
- .owner = THIS_MODULE,
- .open = serio_raw_open,
- .release = serio_raw_release,
- .read = serio_raw_read,
- .write = serio_raw_write,
- .poll = serio_raw_poll,
- .fasync = serio_raw_fasync,
- .llseek = noop_llseek,
+ .owner = THIS_MODULE,
+ .open = serio_raw_open,
+ .release = serio_raw_release,
+ .read = serio_raw_read,
+ .write = serio_raw_write,
+ .poll = serio_raw_poll,
+ .fasync = serio_raw_fasync,
+ .llseek = noop_llseek,
};
/*********************************************************************
- * Interface with serio port *
+ * Interface with serio port *
*********************************************************************/
static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
unsigned int dfl)
{
struct serio_raw *serio_raw = serio_get_drvdata(serio);
- struct serio_raw_list *list;
+ struct serio_raw_client *client;
unsigned int head = serio_raw->head;
- /* we are holding serio->lock here so we are prootected */
+ /* we are holding serio->lock here so we are protected */
serio_raw->queue[head] = data;
head = (head + 1) % SERIO_RAW_QUEUE_LEN;
if (likely(head != serio_raw->tail)) {
serio_raw->head = head;
- list_for_each_entry(list, &serio_raw->list, node)
- kill_fasync(&list->fasync, SIGIO, POLL_IN);
+ list_for_each_entry(client, &serio_raw->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&serio_raw->wait);
}
@@ -272,29 +280,37 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
{
+ static atomic_t serio_raw_no = ATOMIC_INIT(0);
struct serio_raw *serio_raw;
int err;
- if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
- printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
+ serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL);
+ if (!serio_raw) {
+ dev_dbg(&serio->dev, "can't allocate memory for a device\n");
return -ENOMEM;
}
- mutex_lock(&serio_raw_mutex);
+ snprintf(serio_raw->name, sizeof(serio_raw->name),
+ "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
+ kref_init(&serio_raw->kref);
+ INIT_LIST_HEAD(&serio_raw->client_list);
+ init_waitqueue_head(&serio_raw->wait);
- snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
- serio_raw->refcnt = 1;
serio_raw->serio = serio;
- INIT_LIST_HEAD(&serio_raw->list);
- init_waitqueue_head(&serio_raw->wait);
+ get_device(&serio->dev);
serio_set_drvdata(serio, serio_raw);
err = serio_open(serio, drv);
if (err)
- goto out_free;
+ goto err_free;
+
+ err = mutex_lock_killable(&serio_raw_mutex);
+ if (err)
+ goto err_close;
list_add_tail(&serio_raw->node, &serio_raw_list);
+ mutex_unlock(&serio_raw_mutex);
serio_raw->dev.minor = PSMOUSE_MINOR;
serio_raw->dev.name = serio_raw->name;
@@ -308,23 +324,23 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
}
if (err) {
- printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
+ dev_err(&serio->dev,
+ "failed to register raw access device for %s\n",
serio->phys);
- goto out_close;
+ goto err_unlink;
}
- printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
- serio->phys, serio_raw->name, serio_raw->dev.minor);
- goto out;
+ dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
+ serio->phys, serio_raw->name, serio_raw->dev.minor);
+ return 0;
-out_close:
- serio_close(serio);
+err_unlink:
list_del_init(&serio_raw->node);
-out_free:
+err_close:
+ serio_close(serio);
+err_free:
serio_set_drvdata(serio, NULL);
- kfree(serio_raw);
-out:
- mutex_unlock(&serio_raw_mutex);
+ kref_put(&serio_raw->kref, serio_raw_free);
return err;
}
@@ -334,7 +350,8 @@ static int serio_raw_reconnect(struct serio *serio)
struct serio_driver *drv = serio->drv;
if (!drv || !serio_raw) {
- printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
+ dev_dbg(&serio->dev,
+ "reconnect request, but serio is disconnected, ignoring...\n");
return -1;
}
@@ -345,22 +362,40 @@ static int serio_raw_reconnect(struct serio *serio)
return 0;
}
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void serio_raw_hangup(struct serio_raw *serio_raw)
+{
+ struct serio_raw_client *client;
+
+ serio_pause_rx(serio_raw->serio);
+ list_for_each_entry(client, &serio_raw->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ serio_continue_rx(serio_raw->serio);
+
+ wake_up_interruptible(&serio_raw->wait);
+}
+
+
static void serio_raw_disconnect(struct serio *serio)
{
- struct serio_raw *serio_raw;
+ struct serio_raw *serio_raw = serio_get_drvdata(serio);
+
+ misc_deregister(&serio_raw->dev);
mutex_lock(&serio_raw_mutex);
+ serio_raw->dead = true;
+ list_del_init(&serio_raw->node);
+ mutex_unlock(&serio_raw_mutex);
- serio_raw = serio_get_drvdata(serio);
+ serio_raw_hangup(serio_raw);
serio_close(serio);
- serio_set_drvdata(serio, NULL);
-
- serio_raw->serio = NULL;
- if (!serio_raw_cleanup(serio_raw))
- wake_up_interruptible(&serio_raw->wait);
+ kref_put(&serio_raw->kref, serio_raw_free);
- mutex_unlock(&serio_raw_mutex);
+ serio_set_drvdata(serio, NULL);
}
static struct serio_device_id serio_raw_serio_ids[] = {
@@ -391,7 +426,7 @@ static struct serio_driver serio_raw_drv = {
.connect = serio_raw_connect,
.reconnect = serio_raw_reconnect,
.disconnect = serio_raw_disconnect,
- .manual_bind = 1,
+ .manual_bind = true,
};
static int __init serio_raw_init(void)
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 8755f5f..e4ecf3b 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/tty.h>
+#include <linux/compat.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input device TTY line discipline");
@@ -196,28 +197,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
return 0;
}
+static void serport_set_type(struct tty_struct *tty, unsigned long type)
+{
+ struct serport *serport = tty->disc_data;
+
+ serport->id.proto = type & 0x000000ff;
+ serport->id.id = (type & 0x0000ff00) >> 8;
+ serport->id.extra = (type & 0x00ff0000) >> 16;
+}
+
/*
* serport_ldisc_ioctl() allows to set the port protocol, and device ID
*/
-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct serport *serport = (struct serport*) tty->disc_data;
- unsigned long type;
-
if (cmd == SPIOCSTYPE) {
+ unsigned long type;
+
if (get_user(type, (unsigned long __user *) arg))
return -EFAULT;
- serport->id.proto = type & 0x000000ff;
- serport->id.id = (type & 0x0000ff00) >> 8;
- serport->id.extra = (type & 0x00ff0000) >> 16;
+ serport_set_type(tty, type);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+#ifdef CONFIG_COMPAT
+#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
+static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
+ struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ if (cmd == COMPAT_SPIOCSTYPE) {
+ void __user *uarg = compat_ptr(arg);
+ compat_ulong_t compat_type;
+
+ if (get_user(compat_type, (compat_ulong_t __user *)uarg))
+ return -EFAULT;
+ serport_set_type(tty, compat_type);
return 0;
}
return -EINVAL;
}
+#endif
static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{
@@ -241,6 +269,9 @@ static struct tty_ldisc_ops serport_ldisc = {
.close = serport_ldisc_close,
.read = serport_ldisc_read,
.ioctl = serport_ldisc_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = serport_ldisc_compat_ioctl,
+#endif
.receive_buf = serport_ldisc_receive,
.write_wakeup = serport_ldisc_write_wakeup
};
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 80baa53..d64c5a4 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -23,7 +23,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/io.h>
-
+#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 0a619c5..6d89fd1 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -225,7 +225,6 @@
/* toolMode codes
*/
#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
-#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
#define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL
#define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH
#define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 23317bd..0783864 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2011 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -93,7 +93,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.52"
+#define DRIVER_VERSION "v1.53"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -114,6 +114,12 @@ struct wacom {
struct mutex lock;
bool open;
char phys[32];
+ struct wacom_led {
+ u8 select[2]; /* status led selector (0..3) */
+ u8 llv; /* status led brightness no button (1..127) */
+ u8 hlv; /* status led brightness button pressed (1..127) */
+ u8 img_lum; /* OLED matrix display brightness */
+ } led;
};
extern const struct usb_device_id wacom_ids[];
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 449c0a4..1c1b7b4 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -48,26 +48,49 @@ struct hid_descriptor {
/* defines to get/set USB message */
#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_SET_REPORT 0x09
+
#define WAC_HID_FEATURE_REPORT 0x03
+#define WAC_MSG_RETRIES 5
+
+#define WAC_CMD_LED_CONTROL 0x20
+#define WAC_CMD_ICON_START 0x21
+#define WAC_CMD_ICON_XFER 0x23
+#define WAC_CMD_RETRIES 10
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
- unsigned char id, void *buf, int size)
+static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
+ void *buf, size_t size, unsigned int retries)
{
- return usb_control_msg(interface_to_usbdev(intf),
- usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
- USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 100);
+ struct usb_device *dev = interface_to_usbdev(intf);
+ int retval;
+
+ do {
+ retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id,
+ intf->altsetting[0].desc.bInterfaceNumber,
+ buf, size, 100);
+ } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+ return retval;
}
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
- unsigned char id, void *buf, int size)
+static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
+ void *buf, size_t size, unsigned int retries)
{
- return usb_control_msg(interface_to_usbdev(intf),
- usb_sndctrlpipe(interface_to_usbdev(intf), 0),
- USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 1000);
+ struct usb_device *dev = interface_to_usbdev(intf);
+ int retval;
+
+ do {
+ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id,
+ intf->altsetting[0].desc.bInterfaceNumber,
+ buf, size, 1000);
+ } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+ return retval;
}
static void wacom_sys_irq(struct urb *urb)
@@ -165,7 +188,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
report,
hid_desc->wDescriptorLength,
5000); /* 5 secs */
- } while (result < 0 && limit++ < 5);
+ } while (result < 0 && limit++ < WAC_MSG_RETRIES);
/* No need to parse the Descriptor. It isn't an error though */
if (result < 0)
@@ -228,13 +251,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
get_unaligned_le16(&report[i + 3]);
i += 4;
}
- } else if (usage == WCM_DIGITIZER) {
- /* max pressure isn't reported
- features->pressure_max = (unsigned short)
- (report[i+4] << 8 | report[i + 3]);
- */
- features->pressure_max = 255;
- i += 4;
}
break;
@@ -290,13 +306,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
pen = 1;
i++;
break;
-
- case HID_USAGE_UNDEFINED:
- if (usage == WCM_DESKTOP && finger) /* capacity */
- features->pressure_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- break;
}
break;
@@ -319,35 +328,37 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
int limit = 0, report_id = 2;
int error = -ENOMEM;
- rep_data = kmalloc(2, GFP_KERNEL);
+ rep_data = kmalloc(4, GFP_KERNEL);
if (!rep_data)
return error;
- /* ask to report tablet data if it is 2FGT Tablet PC or
+ /* ask to report tablet data if it is MT Tablet PC or
* not a Tablet PC */
if (features->type == TABLETPC2FG) {
do {
rep_data[0] = 3;
rep_data[1] = 4;
+ rep_data[2] = 0;
+ rep_data[3] = 0;
report_id = 3;
- error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
- report_id, rep_data, 2);
+ error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 4, 1);
if (error >= 0)
- error = usb_get_report(intf,
- WAC_HID_FEATURE_REPORT, report_id,
- rep_data, 3);
- } while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
+ error = wacom_get_report(intf,
+ WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 4, 1);
+ } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
} else if (features->type != TABLETPC) {
do {
rep_data[0] = 2;
rep_data[1] = 2;
- error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
- report_id, rep_data, 2);
+ error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 2, 1);
if (error >= 0)
- error = usb_get_report(intf,
- WAC_HID_FEATURE_REPORT, report_id,
- rep_data, 2);
- } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+ error = wacom_get_report(intf,
+ WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 2, 1);
+ } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
}
kfree(rep_data);
@@ -465,6 +476,275 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom)
}
}
+static int wacom_led_control(struct wacom *wacom)
+{
+ unsigned char *buf;
+ int retval, led = 0;
+
+ buf = kzalloc(9, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (wacom->wacom_wac.features.type == WACOM_21UX2)
+ led = (wacom->led.select[1] << 4) | 0x40;
+
+ led |= wacom->led.select[0] | 0x4;
+
+ buf[0] = WAC_CMD_LED_CONTROL;
+ buf[1] = led;
+ buf[2] = wacom->led.llv;
+ buf[3] = wacom->led.hlv;
+ buf[4] = wacom->led.img_lum;
+
+ retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
+ buf, 9, WAC_CMD_RETRIES);
+ kfree(buf);
+
+ return retval;
+}
+
+static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
+{
+ unsigned char *buf;
+ int i, retval;
+
+ buf = kzalloc(259, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Send 'start' command */
+ buf[0] = WAC_CMD_ICON_START;
+ buf[1] = 1;
+ retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+ buf, 2, WAC_CMD_RETRIES);
+ if (retval < 0)
+ goto out;
+
+ buf[0] = WAC_CMD_ICON_XFER;
+ buf[1] = button_id & 0x07;
+ for (i = 0; i < 4; i++) {
+ buf[2] = i;
+ memcpy(buf + 3, img + i * 256, 256);
+
+ retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
+ buf, 259, WAC_CMD_RETRIES);
+ if (retval < 0)
+ break;
+ }
+
+ /* Send 'stop' */
+ buf[0] = WAC_CMD_ICON_START;
+ buf[1] = 0;
+ wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+ buf, 2, WAC_CMD_RETRIES);
+
+out:
+ kfree(buf);
+ return retval;
+}
+
+static ssize_t wacom_led_select_store(struct device *dev, int set_id,
+ const char *buf, size_t count)
+{
+ struct wacom *wacom = dev_get_drvdata(dev);
+ unsigned int id;
+ int err;
+
+ err = kstrtouint(buf, 10, &id);
+ if (err)
+ return err;
+
+ mutex_lock(&wacom->lock);
+
+ wacom->led.select[set_id] = id & 0x3;
+ err = wacom_led_control(wacom);
+
+ mutex_unlock(&wacom->lock);
+
+ return err < 0 ? err : count;
+}
+
+#define DEVICE_LED_SELECT_ATTR(SET_ID) \
+static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return wacom_led_select_store(dev, SET_ID, buf, count); \
+} \
+static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct wacom *wacom = dev_get_drvdata(dev); \
+ return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \
+} \
+static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR, \
+ wacom_led##SET_ID##_select_show, \
+ wacom_led##SET_ID##_select_store)
+
+DEVICE_LED_SELECT_ATTR(0);
+DEVICE_LED_SELECT_ATTR(1);
+
+static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
+ const char *buf, size_t count)
+{
+ unsigned int value;
+ int err;
+
+ err = kstrtouint(buf, 10, &value);
+ if (err)
+ return err;
+
+ mutex_lock(&wacom->lock);
+
+ *dest = value & 0x7f;
+ err = wacom_led_control(wacom);
+
+ mutex_unlock(&wacom->lock);
+
+ return err < 0 ? err : count;
+}
+
+#define DEVICE_LUMINANCE_ATTR(name, field) \
+static ssize_t wacom_##name##_luminance_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct wacom *wacom = dev_get_drvdata(dev); \
+ \
+ return wacom_luminance_store(wacom, &wacom->led.field, \
+ buf, count); \
+} \
+static DEVICE_ATTR(name##_luminance, S_IWUSR, \
+ NULL, wacom_##name##_luminance_store)
+
+DEVICE_LUMINANCE_ATTR(status0, llv);
+DEVICE_LUMINANCE_ATTR(status1, hlv);
+DEVICE_LUMINANCE_ATTR(buttons, img_lum);
+
+static ssize_t wacom_button_image_store(struct device *dev, int button_id,
+ const char *buf, size_t count)
+{
+ struct wacom *wacom = dev_get_drvdata(dev);
+ int err;
+
+ if (count != 1024)
+ return -EINVAL;
+
+ mutex_lock(&wacom->lock);
+
+ err = wacom_led_putimage(wacom, button_id, buf);
+
+ mutex_unlock(&wacom->lock);
+
+ return err < 0 ? err : count;
+}
+
+#define DEVICE_BTNIMG_ATTR(BUTTON_ID) \
+static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return wacom_button_image_store(dev, BUTTON_ID, buf, count); \
+} \
+static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR, \
+ NULL, wacom_btnimg##BUTTON_ID##_store)
+
+DEVICE_BTNIMG_ATTR(0);
+DEVICE_BTNIMG_ATTR(1);
+DEVICE_BTNIMG_ATTR(2);
+DEVICE_BTNIMG_ATTR(3);
+DEVICE_BTNIMG_ATTR(4);
+DEVICE_BTNIMG_ATTR(5);
+DEVICE_BTNIMG_ATTR(6);
+DEVICE_BTNIMG_ATTR(7);
+
+static struct attribute *cintiq_led_attrs[] = {
+ &dev_attr_status_led0_select.attr,
+ &dev_attr_status_led1_select.attr,
+ NULL
+};
+
+static struct attribute_group cintiq_led_attr_group = {
+ .name = "wacom_led",
+ .attrs = cintiq_led_attrs,
+};
+
+static struct attribute *intuos4_led_attrs[] = {
+ &dev_attr_status0_luminance.attr,
+ &dev_attr_status1_luminance.attr,
+ &dev_attr_status_led0_select.attr,
+ &dev_attr_buttons_luminance.attr,
+ &dev_attr_button0_rawimg.attr,
+ &dev_attr_button1_rawimg.attr,
+ &dev_attr_button2_rawimg.attr,
+ &dev_attr_button3_rawimg.attr,
+ &dev_attr_button4_rawimg.attr,
+ &dev_attr_button5_rawimg.attr,
+ &dev_attr_button6_rawimg.attr,
+ &dev_attr_button7_rawimg.attr,
+ NULL
+};
+
+static struct attribute_group intuos4_led_attr_group = {
+ .name = "wacom_led",
+ .attrs = intuos4_led_attrs,
+};
+
+static int wacom_initialize_leds(struct wacom *wacom)
+{
+ int error;
+
+ /* Initialize default values */
+ switch (wacom->wacom_wac.features.type) {
+ case INTUOS4:
+ case INTUOS4L:
+ wacom->led.select[0] = 0;
+ wacom->led.select[1] = 0;
+ wacom->led.llv = 10;
+ wacom->led.hlv = 20;
+ wacom->led.img_lum = 10;
+ error = sysfs_create_group(&wacom->intf->dev.kobj,
+ &intuos4_led_attr_group);
+ break;
+
+ case WACOM_21UX2:
+ wacom->led.select[0] = 0;
+ wacom->led.select[1] = 0;
+ wacom->led.llv = 0;
+ wacom->led.hlv = 0;
+ wacom->led.img_lum = 0;
+
+ error = sysfs_create_group(&wacom->intf->dev.kobj,
+ &cintiq_led_attr_group);
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (error) {
+ dev_err(&wacom->intf->dev,
+ "cannot create sysfs group err: %d\n", error);
+ return error;
+ }
+ wacom_led_control(wacom);
+
+ return 0;
+}
+
+static void wacom_destroy_leds(struct wacom *wacom)
+{
+ switch (wacom->wacom_wac.features.type) {
+ case INTUOS4:
+ case INTUOS4L:
+ sysfs_remove_group(&wacom->intf->dev.kobj,
+ &intuos4_led_attr_group);
+ break;
+
+ case WACOM_21UX2:
+ sysfs_remove_group(&wacom->intf->dev.kobj,
+ &cintiq_led_attr_group);
+ break;
+ }
+}
+
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -553,16 +833,21 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->irq->transfer_dma = wacom->data_dma;
wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- error = input_register_device(input_dev);
+ error = wacom_initialize_leds(wacom);
if (error)
goto fail4;
+ error = input_register_device(input_dev);
+ if (error)
+ goto fail5;
+
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(intf, features);
usb_set_intfdata(intf, wacom);
return 0;
+ fail5: wacom_destroy_leds(wacom);
fail4: wacom_remove_shared_data(wacom_wac);
fail3: usb_free_urb(wacom->irq);
fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
@@ -579,6 +864,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_kill_urb(wacom->irq);
input_unregister_device(wacom->wacom_wac.input);
+ wacom_destroy_leds(wacom);
usb_free_urb(wacom->irq);
usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
wacom->wacom_wac.data, wacom->data_dma);
@@ -601,17 +887,16 @@ static int wacom_resume(struct usb_interface *intf)
{
struct wacom *wacom = usb_get_intfdata(intf);
struct wacom_features *features = &wacom->wacom_wac.features;
- int rv;
+ int rv = 0;
mutex_lock(&wacom->lock);
/* switch to wacom mode first */
wacom_query_tablet_data(intf, features);
+ wacom_led_control(wacom);
- if (wacom->open)
- rv = usb_submit_urb(wacom->irq, GFP_NOIO);
- else
- rv = 0;
+ if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
+ rv = -EIO;
mutex_unlock(&wacom->lock);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index a28ebf0..f00c70e 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -15,6 +15,7 @@
#include "wacom_wac.h"
#include "wacom.h"
#include <linux/input/mt.h>
+#include <linux/hid.h>
/* resolution for penabled devices */
#define WACOM_PL_RES 20
@@ -242,7 +243,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
if (wacom->tool[0] != BTN_TOOL_MOUSE) {
- input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8));
+ input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
input_report_key(input, BTN_TOUCH, data[1] & 0x01);
input_report_key(input, BTN_STYLUS, data[1] & 0x02);
input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
@@ -264,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
wacom->id[0] = 0;
input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
input_report_key(input, wacom->tool[0], prox);
+ input_event(input, EV_MSC, MSC_SERIAL, 1);
input_sync(input); /* sync last event */
}
@@ -273,11 +275,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
prox = data[7] & 0xf8;
if (prox || wacom->id[1]) {
wacom->id[1] = PAD_DEVICE_ID;
- input_report_key(input, BTN_0, (data[7] & 0x40));
- input_report_key(input, BTN_4, (data[7] & 0x80));
+ input_report_key(input, BTN_BACK, (data[7] & 0x40));
+ input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
input_report_rel(input, REL_WHEEL, rw);
- input_report_key(input, BTN_TOOL_FINGER, 0xf0);
if (!prox)
wacom->id[1] = 0;
input_report_abs(input, ABS_MISC, wacom->id[1]);
@@ -290,18 +291,17 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
prox = (data[7] & 0xf8) || data[8];
if (prox || wacom->id[1]) {
wacom->id[1] = PAD_DEVICE_ID;
- input_report_key(input, BTN_0, (data[7] & 0x08));
- input_report_key(input, BTN_1, (data[7] & 0x20));
- input_report_key(input, BTN_4, (data[7] & 0x10));
- input_report_key(input, BTN_5, (data[7] & 0x40));
+ input_report_key(input, BTN_BACK, (data[7] & 0x08));
+ input_report_key(input, BTN_LEFT, (data[7] & 0x20));
+ input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
+ input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
- input_report_key(input, BTN_TOOL_FINGER, 0xf0);
if (!prox)
wacom->id[1] = 0;
input_report_abs(input, ABS_MISC, wacom->id[1]);
input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+ retval = 1;
}
- retval = 1;
break;
}
exit:
@@ -494,10 +494,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
/* pad packets. Works as a second tool and is always in prox */
if (data[0] == WACOM_REPORT_INTUOSPAD) {
- /* initiate the pad as a device */
- if (wacom->tool[1] != BTN_TOOL_FINGER)
- wacom->tool[1] = BTN_TOOL_FINGER;
-
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
input_report_key(input, BTN_0, (data[2] & 0x01));
input_report_key(input, BTN_1, (data[3] & 0x01));
@@ -804,25 +800,26 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
int i;
for (i = 0; i < 2; i++) {
- int p = data[9 * i + 2];
- bool touch = p && !wacom->shared->stylus_in_proximity;
+ int offset = (data[1] & 0x80) ? (8 * i) : (9 * i);
+ bool touch = data[offset + 3] & 0x80;
- input_mt_slot(input, i);
- input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
/*
* Touch events need to be disabled while stylus is
* in proximity because user's hand is resting on touchpad
* and sending unwanted events. User expects tablet buttons
* to continue working though.
*/
+ touch = touch && !wacom->shared->stylus_in_proximity;
+
+ input_mt_slot(input, i);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
if (touch) {
- int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
- int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
+ int x = get_unaligned_be16(&data[offset + 3]) & 0x7ff;
+ int y = get_unaligned_be16(&data[offset + 5]) & 0x7ff;
if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
x <<= 5;
y <<= 5;
}
- input_report_abs(input, ABS_MT_PRESSURE, p);
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
}
@@ -846,12 +843,7 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
unsigned char *data = wacom->data;
int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
- /*
- * Similar to Graphire protocol, data[1] & 0x20 is proximity and
- * data[1] & 0x18 is tool ID. 0x30 is safety check to ignore
- * 2 unused tool ID's.
- */
- prox = (data[1] & 0x30) == 0x30;
+ prox = (data[1] & 0x20) == 0x20;
/*
* All reports shared between PEN and RUBBER tool must be
@@ -877,7 +869,15 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
x = le16_to_cpup((__le16 *)&data[2]);
y = le16_to_cpup((__le16 *)&data[4]);
p = le16_to_cpup((__le16 *)&data[6]);
- d = data[8];
+ /*
+ * Convert distance from out prox to distance from tablet.
+ * distance will be greater than distance_max once
+ * touching and applying pressure; do not report negative
+ * distance.
+ */
+ if (data[8] <= wacom->features.distance_max)
+ d = wacom->features.distance_max - data[8];
+
pen = data[1] & 0x01;
btn1 = data[1] & 0x02;
btn2 = data[1] & 0x04;
@@ -1033,8 +1033,6 @@ void wacom_setup_device_quirks(struct wacom_features *features)
features->y_max <<= 5;
features->x_fuzz <<= 5;
features->y_fuzz <<= 5;
- features->pressure_max = 256;
- features->pressure_fuzz = 16;
features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
}
}
@@ -1060,10 +1058,11 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
features->x_fuzz, 0);
input_set_abs_params(input_dev, ABS_Y, 0, features->y_max,
features->y_fuzz, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max,
- features->pressure_fuzz, 0);
if (features->device_type == BTN_TOOL_PEN) {
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max,
+ features->pressure_fuzz, 0);
+
/* penabled devices have fixed resolution for each model */
input_abs_set_res(input_dev, ABS_X, features->x_resolution);
input_abs_set_res(input_dev, ABS_Y, features->y_resolution);
@@ -1080,18 +1079,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
switch (wacom_wac->features.type) {
case WACOM_MO:
- __set_bit(BTN_1, input_dev->keybit);
- __set_bit(BTN_5, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
/* fall through */
case WACOM_G4:
input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
- __set_bit(BTN_0, input_dev->keybit);
- __set_bit(BTN_4, input_dev->keybit);
+ __set_bit(BTN_BACK, input_dev->keybit);
+ __set_bit(BTN_FORWARD, input_dev->keybit);
/* fall through */
case GRAPHIRE:
@@ -1106,6 +1101,8 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
__set_bit(BTN_STYLUS, input_dev->keybit);
__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
break;
case WACOM_21UX2:
@@ -1127,11 +1124,13 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
case CINTIQ:
for (i = 0; i < 8; i++)
__set_bit(BTN_0 + i, input_dev->keybit);
- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
wacom_setup_cintiq(wacom_wac);
break;
@@ -1151,13 +1150,13 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(BTN_2, input_dev->keybit);
__set_bit(BTN_3, input_dev->keybit);
- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
/* fall through */
case INTUOS:
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
wacom_setup_intuos(wacom_wac);
break;
@@ -1170,10 +1169,11 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS4S:
for (i = 0; i < 7; i++)
__set_bit(BTN_0 + i, input_dev->keybit);
- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
wacom_setup_intuos(wacom_wac);
+
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
break;
case TABLETPC2FG:
@@ -1192,26 +1192,40 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
case TABLETPC:
__clear_bit(ABS_MISC, input_dev->absbit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
if (features->device_type != BTN_TOOL_PEN)
break; /* no need to process stylus stuff */
/* fall through */
case PL:
- case PTU:
case DTU:
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
__set_bit(BTN_STYLUS, input_dev->keybit);
__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ break;
+
+ case PTU:
+ __set_bit(BTN_STYLUS2, input_dev->keybit);
/* fall through */
case PENPARTNER:
+ __set_bit(BTN_TOOL_PEN, input_dev->keybit);
__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
break;
case BAMBOO_PT:
__clear_bit(ABS_MISC, input_dev->absbit);
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
if (features->device_type == BTN_TOOL_DOUBLETAP) {
__set_bit(BTN_LEFT, input_dev->keybit);
__set_bit(BTN_FORWARD, input_dev->keybit);
@@ -1228,14 +1242,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, features->y_max,
features->y_fuzz, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE,
- 0, features->pressure_max,
- features->pressure_fuzz, 0);
} else if (features->device_type == BTN_TOOL_PEN) {
__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
__set_bit(BTN_STYLUS, input_dev->keybit);
__set_bit(BTN_STYLUS2, input_dev->keybit);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+ features->distance_max,
+ 0, 0);
}
break;
}
@@ -1295,6 +1309,12 @@ static const struct wacom_features wacom_features_0x65 =
static const struct wacom_features wacom_features_0x69 =
{ "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511,
63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+static const struct wacom_features wacom_features_0x6A =
+ { "Wacom Bamboo1 4x6", WACOM_PKGLEN_GRAPHIRE, 14760, 9225, 1023,
+ 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x6B =
+ { "Wacom Bamboo1 5x8", WACOM_PKGLEN_GRAPHIRE, 21648, 13530, 1023,
+ 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x20 =
{ "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023,
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1427,6 +1447,9 @@ static const struct wacom_features wacom_features_0x90 =
static const struct wacom_features wacom_features_0x93 =
{ "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x97 =
+ { "Wacom ISDv4 97", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 511,
+ 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x9A =
{ "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1442,39 +1465,45 @@ static const struct wacom_features wacom_features_0xE3 =
static const struct wacom_features wacom_features_0xE6 =
{ "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255,
0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xEC =
+ { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255,
+ 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x47 =
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD0 =
{ "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD1 =
{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD2 =
{ "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD3 =
- { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD4 =
- { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD5 =
+ { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD6 =
{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD7 =
{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD8 =
- { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xDA =
{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static struct wacom_features wacom_features_0xDB =
- { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x6004 =
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1483,6 +1512,11 @@ static const struct wacom_features wacom_features_0x6004 =
USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
.driver_info = (kernel_ulong_t)&wacom_features_##prod
+#define USB_DEVICE_DETAILED(prod, class, sub, proto) \
+ USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \
+ sub, proto), \
+ .driver_info = (kernel_ulong_t)&wacom_features_##prod
+
#define USB_DEVICE_LENOVO(prod) \
USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
.driver_info = (kernel_ulong_t)&wacom_features_##prod
@@ -1506,6 +1540,8 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x64) },
{ USB_DEVICE_WACOM(0x65) },
{ USB_DEVICE_WACOM(0x69) },
+ { USB_DEVICE_WACOM(0x6A) },
+ { USB_DEVICE_WACOM(0x6B) },
{ USB_DEVICE_WACOM(0x20) },
{ USB_DEVICE_WACOM(0x21) },
{ USB_DEVICE_WACOM(0x22) },
@@ -1545,12 +1581,19 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xC5) },
{ USB_DEVICE_WACOM(0xC6) },
{ USB_DEVICE_WACOM(0xC7) },
- { USB_DEVICE_WACOM(0xCE) },
+ /*
+ * DTU-2231 has two interfaces on the same configuration,
+ * only one is used.
+ */
+ { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
+ USB_INTERFACE_SUBCLASS_BOOT,
+ USB_INTERFACE_PROTOCOL_MOUSE) },
{ USB_DEVICE_WACOM(0xD0) },
{ USB_DEVICE_WACOM(0xD1) },
{ USB_DEVICE_WACOM(0xD2) },
{ USB_DEVICE_WACOM(0xD3) },
{ USB_DEVICE_WACOM(0xD4) },
+ { USB_DEVICE_WACOM(0xD5) },
{ USB_DEVICE_WACOM(0xD6) },
{ USB_DEVICE_WACOM(0xD7) },
{ USB_DEVICE_WACOM(0xD8) },
@@ -1560,11 +1603,13 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xCC) },
{ USB_DEVICE_WACOM(0x90) },
{ USB_DEVICE_WACOM(0x93) },
+ { USB_DEVICE_WACOM(0x97) },
{ USB_DEVICE_WACOM(0x9A) },
{ USB_DEVICE_WACOM(0x9F) },
{ USB_DEVICE_WACOM(0xE2) },
{ USB_DEVICE_WACOM(0xE3) },
{ USB_DEVICE_WACOM(0xE6) },
+ { USB_DEVICE_WACOM(0xEC) },
{ USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_LENOVO(0x6004) },
{ }
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 4fb6016..a233ed5 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -5,7 +5,7 @@
menuconfig ISDN
bool "ISDN support"
depends on NET
- depends on !S390
+ depends on !S390 && !UML
---help---
ISDN ("Integrated Services Digital Network", called RNIS in France)
is a fully digital telephone service that can be used for voice and
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index ea2dff6..8d51cd1 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -14,6 +14,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
+#include <linux/export.h>
static char *state2str(unsigned short state)
{
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 33ec9e4..9021182 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -242,6 +242,12 @@ static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg)
case IIOCDOCFINT:
if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
return (-EINVAL); /* invalid driver */
+ if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) ==
+ sizeof(dioctl.cf_ctrl.msn))
+ return -EINVAL;
+ if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) ==
+ sizeof(dioctl.cf_ctrl.fwd_nr))
+ return -EINVAL;
if ((i = cf_command(dioctl.cf_ctrl.drvid,
(cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
dioctl.cf_ctrl.cfproc,
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index c3b1dc3..fddae72 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -16,6 +16,7 @@
#include "gigaset.h"
#include <linux/crc-ccitt.h>
#include <linux/bitrev.h>
+#include <linux/export.h>
/* check if byte must be stuffed/escaped
* I'm not sure which data should be encoded.
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 483ac00..08c2329 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -18,6 +18,7 @@
#include <linux/isdn/capilli.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
+#include <linux/export.h>
/* missing from kernelcapi.h */
#define CapiNcpiNotSupportedByProtocol 0x0001
@@ -1888,6 +1889,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
/* check for active logical connection */
if (bcs->apconnstate >= APCONN_ACTIVE) {
+ /* clear it */
+ bcs->apconnstate = APCONN_SETUP;
+
/*
* emit DISCONNECT_B3_IND with cause 0x3301
* use separate cmsg structure, as the content of iif->acmsg
@@ -1912,6 +1916,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
}
capi_cmsg2message(b3cmsg,
__skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN));
+ dump_cmsg(DEBUG_CMD, __func__, b3cmsg);
kfree(b3cmsg);
capi_ctr_handle_message(&iif->ctr, ap->id, b3skb);
}
diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c
index bd0b1ea..19b1c77 100644
--- a/drivers/isdn/gigaset/dummyll.c
+++ b/drivers/isdn/gigaset/dummyll.c
@@ -11,6 +11,7 @@
* =====================================================================
*/
+#include <linux/export.h>
#include "gigaset.h"
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index ba74646..e95fac0 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -13,6 +13,7 @@
* =====================================================================
*/
+#include <linux/export.h>
#include "gigaset.h"
/* ========================================================== */
@@ -189,6 +190,7 @@ struct reply_t gigaset_tab_nocid[] =
ACT_INIT} },
{RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER,
ACT_INIT} },
+{RSP_NONE, 121, 121, -1, 120, 0, {ACT_GETSTRING} },
/* leave dle mode */
{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
@@ -1313,8 +1315,9 @@ static void do_action(int action, struct cardstate *cs,
s = ev->ptr;
if (!strcmp(s, "OK")) {
+ /* OK without version string: assume old response */
*p_genresp = 1;
- *p_resp_code = RSP_ERROR;
+ *p_resp_code = RSP_NONE;
break;
}
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 6dd3607..212efaf 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -34,7 +34,7 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define GIG_VERSION {0, 5, 0, 0}
#define GIG_COMPAT {0, 4, 0, 0}
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 9bec8b9..04231cb 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -15,6 +15,7 @@
#include "gigaset.h"
#include <linux/isdnif.h>
+#include <linux/export.h>
#define SBUFSIZE 4096 /* sk_buff payload size */
#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index e35058b..ee0a549 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -14,6 +14,7 @@
#include "gigaset.h"
#include <linux/gigaset_dev.h>
#include <linux/tty_flip.h>
+#include <linux/module.h>
/*** our ioctls ***/
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 472a2af..861b651 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index f6f3c87..a440d7f 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -152,6 +152,7 @@
#define HFC_MULTI_VERSION "2.03"
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index b01a7be..3261de1 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -44,6 +44,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
index bc0529a..6218775 100644
--- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -38,6 +38,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 64ecc6f..d2ffb1d 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/irqreturn.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mISDNhw.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index d13fa5b..7034af2 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/mISDNhw.h>
+#include <linux/module.h>
#include "isar.h"
#define ISAR_REV "2.1"
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index db25b6b..5ef9f11 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
index 9e07246..4d0d41e 100644
--- a/drivers/isdn/hardware/mISDN/speedfax.c
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -22,6 +22,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 9e84870..e10e028 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 37e685e..c4897e1 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -65,7 +65,7 @@ hisax_findcard(int driverid)
return (struct IsdnCardState *) 0;
}
-static __attribute__((format(printf, 3, 4))) void
+static __printf(3, 4) void
link_debug(struct Channel *chanp, int direction, char *fmt, ...)
{
va_list args;
@@ -1068,7 +1068,7 @@ init_d_st(struct Channel *chanp)
return 0;
}
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
callc_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index de1c669..aff45a1 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/wait.h>
@@ -1286,9 +1287,9 @@ int jiftime(char *s, long mark);
int HiSax_command(isdn_ctrl * ic);
int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-__attribute__((format(printf, 3, 4)))
+__printf(3, 4)
void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-__attribute__((format(printf, 3, 0)))
+__printf(3, 0)
void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
void HiSax_reportcard(int cardnr, int sel);
int QuickHex(char *txt, u_char * p, int cnt);
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 8b0a7d8..478ebab 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/kmod.h>
diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
index 425d861..66ddcab 100644
--- a/drivers/isdn/hisax/isdnl1.h
+++ b/drivers/isdn/hisax/isdnl1.h
@@ -21,7 +21,7 @@
#define B_XMTBUFREADY 1
#define B_ACKPENDING 2
-__attribute__((format(printf, 2, 3)))
+__printf(2, 3)
void debugl1(struct IsdnCardState *cs, char *fmt, ...);
void DChannel_proc_xmt(struct IsdnCardState *cs);
void DChannel_proc_rcv(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index ad291f2..1c24e44 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -66,7 +66,7 @@ static char *strL3Event[] =
"EV_TIMEOUT",
};
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
l3m_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index b0d9ab1..6a8acf6 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -353,7 +353,7 @@ l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
{ l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
return;
}
-#ifdef HISAX_DE_AOC
+#ifdef CONFIG_DE_AOC
{
#define FOO1(s,a,b) \
@@ -422,9 +422,9 @@ l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
#undef FOO1
}
-#else /* not HISAX_DE_AOC */
+#else /* not CONFIG_DE_AOC */
l3_debug(st, "invoke break");
-#endif /* not HISAX_DE_AOC */
+#endif /* not CONFIG_DE_AOC */
break;
case 2: /* return result */
/* if no process available handle separately */
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 4408263..db247b7 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -167,7 +167,7 @@ static struct FsmNode L1FnList[] __initdata =
{ST_L1_F8, EV_IND_RSY, l1_ignore},
};
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
void l1m_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
@@ -270,7 +270,7 @@ static char *strDoutEvent[] =
"EV_DOUT_UNDERRUN",
};
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
void dout_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index 02d9918..aa0b6a6 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -155,7 +155,7 @@ struct bsd_db {
#define LAST 255
#define MAXCODE(b) ((1 << (b)) - 1)
-#define BADCODEM1 MAXCODE(MAX_BSD_BITS);
+#define BADCODEM1 MAXCODE(MAX_BSD_BITS)
#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
^ (unsigned long)(prefix))
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 6ed82ad..6ddb795e 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -2308,11 +2308,11 @@ static int __init isdn_init(void)
int i;
char tmprev[50];
- if (!(dev = vmalloc(sizeof(isdn_dev)))) {
+ dev = vzalloc(sizeof(isdn_dev));
+ if (!dev) {
printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
return -EIO;
}
- memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
spin_lock_init(&dev->lock);
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index b145b5a..2339d73 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1983,13 +1983,14 @@ isdn_net_rebuild_header(struct sk_buff *skb)
return ret;
}
-static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
+static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
+ __be16 type)
{
const struct net_device *dev = neigh->dev;
isdn_net_local *lp = netdev_priv(dev);
if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
- return eth_header_cache(neigh, hh);
+ return eth_header_cache(neigh, hh, type);
return -1;
}
@@ -2755,6 +2756,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
char *c,
*e;
+ if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
+ sizeof(cfg->drvid))
+ return -EINVAL;
drvidx = -1;
chidx = -1;
strcpy(drvid, cfg->drvid);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index d850427..2c26b64 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -750,6 +750,7 @@ isdn_tty_modem_hup(modem_info * info, int local)
* supplementary service (CAPI 2.0 part III)
*/
#include <linux/isdn/capicmd.h>
+#include <linux/module.h>
int
isdn_tty_capi_facility(capi_msg *cm) {
@@ -1693,7 +1694,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
* line status register.
*/
if (info->flags & ISDN_ASYNC_INITIALIZED) {
- tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+ tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index 509135f..75ca5d2 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -518,9 +518,9 @@ static isdnloop_stat isdnloop_cmd_table[] =
static void
isdnloop_fake_err(isdnloop_card * card)
{
- char buf[60];
+ char buf[64];
- sprintf(buf, "E%s", card->omsg);
+ snprintf(buf, sizeof(buf), "E%s", card->omsg);
isdnloop_fake(card, buf, -1);
isdnloop_fake(card, "NAK", -1);
}
@@ -903,6 +903,8 @@ isdnloop_parse_cmd(isdnloop_card * card)
case 7:
/* 0x;EAZ */
p += 3;
+ if (strlen(p) >= sizeof(card->eazlist[0]))
+ break;
strcpy(card->eazlist[ch - 1], p);
break;
case 8:
@@ -1070,6 +1072,12 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp)
return -EBUSY;
if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
return -EFAULT;
+
+ for (i = 0; i < 3; i++) {
+ if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i])))
+ return -EINVAL;
+ }
+
spin_lock_irqsave(&card->isdnloop_lock, flags);
switch (sdef.ptype) {
case ISDN_PTYPE_EURO:
@@ -1083,8 +1091,10 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp)
spin_unlock_irqrestore(&card->isdnloop_lock, flags);
return -ENOMEM;
}
- for (i = 0; i < 3; i++)
- strcpy(card->s0num[i], sdef.num[i]);
+ for (i = 0; i < 3; i++) {
+ strlcpy(card->s0num[i], sdef.num[i],
+ sizeof(card->s0num[0]));
+ }
break;
case ISDN_PTYPE_1TR6:
if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
@@ -1097,7 +1107,7 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp)
spin_unlock_irqrestore(&card->isdnloop_lock, flags);
return -ENOMEM;
}
- strcpy(card->s0num[0], sdef.num[0]);
+ strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0]));
card->s0num[1][0] = '\0';
card->s0num[2][0] = '\0';
break;
@@ -1125,7 +1135,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
{
ulong a;
int i;
- char cbuf[60];
+ char cbuf[80];
isdn_ctrl cmd;
isdnloop_cdef cdef;
@@ -1190,7 +1200,6 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
break;
if ((c->arg & 255) < ISDNLOOP_BCH) {
char *p;
- char dial[50];
char dcode[4];
a = c->arg;
@@ -1202,10 +1211,10 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
} else
/* Normal Dial */
strcpy(dcode, "CAL");
- strcpy(dial, p);
- sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
- dcode, dial, c->parm.setup.si1,
- c->parm.setup.si2, c->parm.setup.eazmsn);
+ snprintf(cbuf, sizeof(cbuf),
+ "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
+ dcode, p, c->parm.setup.si1,
+ c->parm.setup.si2, c->parm.setup.eazmsn);
i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
diff --git a/drivers/isdn/mISDN/clock.c b/drivers/isdn/mISDN/clock.c
index 1fa629b..7418f2d 100644
--- a/drivers/isdn/mISDN/clock.c
+++ b/drivers/isdn/mISDN/clock.c
@@ -38,6 +38,7 @@
#include <linux/stddef.h>
#include <linux/spinlock.h>
#include <linux/mISDNif.h>
+#include <linux/export.h>
#include "core.h"
static u_int *debug;
diff --git a/drivers/isdn/mISDN/dsp_audio.c b/drivers/isdn/mISDN/dsp_audio.c
index 9c7c645..b8f18bd0 100644
--- a/drivers/isdn/mISDN/dsp_audio.c
+++ b/drivers/isdn/mISDN/dsp_audio.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
+#include <linux/export.h>
#include "core.h"
#include "dsp.h"
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 2877291..0c41553 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -1052,12 +1052,11 @@ dspcreate(struct channel_req *crq)
if (crq->protocol != ISDN_P_B_L2DSP
&& crq->protocol != ISDN_P_B_L2DSPHDLC)
return -EPROTONOSUPPORT;
- ndsp = vmalloc(sizeof(struct dsp));
+ ndsp = vzalloc(sizeof(struct dsp));
if (!ndsp) {
printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__);
return -ENOMEM;
}
- memset(ndsp, 0, sizeof(struct dsp));
if (dsp_debug & DEBUG_DSP_CTRL)
printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__);
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
index 621f310..b6c9a58 100644
--- a/drivers/isdn/mISDN/dsp_pipeline.c
+++ b/drivers/isdn/mISDN/dsp_pipeline.c
@@ -30,6 +30,7 @@
#include <linux/string.h>
#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
+#include <linux/export.h>
#include "dsp.h"
#include "dsp_hwec.h"
diff --git a/drivers/isdn/mISDN/l1oip_codec.c b/drivers/isdn/mISDN/l1oip_codec.c
index bbfd1b8..5a89972 100644
--- a/drivers/isdn/mISDN/l1oip_codec.c
+++ b/drivers/isdn/mISDN/l1oip_codec.c
@@ -330,14 +330,12 @@ l1oip_4bit_alloc(int ulaw)
return 0;
/* alloc conversion tables */
- table_com = vmalloc(65536);
- table_dec = vmalloc(512);
+ table_com = vzalloc(65536);
+ table_dec = vzalloc(512);
if (!table_com || !table_dec) {
l1oip_4bit_free();
return -ENOMEM;
}
- memset(table_com, 0, 65536);
- memset(table_dec, 0, 512);
/* generate compression table */
i1 = 0;
while (i1 < 256) {
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 8e32522..98e8274 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -17,6 +17,7 @@
#include <linux/mISDNif.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "core.h"
static u_int *debug;
@@ -116,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
{
struct sk_buff *skb;
struct sock *sk = sock->sk;
- struct sockaddr_mISDN *maddr;
int copied, err;
@@ -134,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (!skb)
return err;
- if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
- msg->msg_namelen = sizeof(struct sockaddr_mISDN);
- maddr = (struct sockaddr_mISDN *)msg->msg_name;
+ if (msg->msg_name) {
+ struct sockaddr_mISDN *maddr = msg->msg_name;
+
maddr->family = AF_ISDN;
maddr->dev = _pms(sk)->dev->id;
if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
@@ -149,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
maddr->sapi = _pms(sk)->ch.addr & 0xFF;
maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF;
}
- } else {
- if (msg->msg_namelen)
- printk(KERN_WARNING "%s: too small namelen %d\n",
- __func__, msg->msg_namelen);
- msg->msg_namelen = 0;
+ msg->msg_namelen = sizeof(*maddr);
}
copied = skb->len + MISDN_HEADER_LEN;
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index efa2024..34842e5 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -117,7 +117,7 @@ static __init int map_switcher(void)
/*
* Now the Switcher is mapped at the right address, we can't fail!
- * Copy in the compiled-in Switcher code (from <arch>_switcher.S).
+ * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
*/
memcpy(switcher_vma->addr, start_switcher_text,
end_switcher_text - start_switcher_text);
@@ -171,7 +171,7 @@ static void unmap_switcher(void)
bool lguest_address_ok(const struct lguest *lg,
unsigned long addr, unsigned long len)
{
- return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
+ return addr+len <= lg->pfn_limit * PAGE_SIZE && (addr+len >= addr);
}
/*
@@ -232,6 +232,13 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
}
}
+ /*
+ * All long-lived kernel loops need to check with this horrible
+ * thing called the freezer. If the Host is trying to suspend,
+ * it stops us.
+ */
+ try_to_freeze();
+
/* Check for signals */
if (signal_pending(current))
return -ERESTARTSYS;
@@ -246,13 +253,6 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
try_deliver_interrupt(cpu, irq, more);
/*
- * All long-lived kernel loops need to check with this horrible
- * thing called the freezer. If the Host is trying to suspend,
- * it stops us.
- */
- try_to_freeze();
-
- /*
* Just make absolutely sure the Guest is still alive. One of
* those hypercalls could have been fatal, for example.
*/
@@ -313,7 +313,7 @@ static int __init init(void)
int err;
/* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */
- if (paravirt_enabled()) {
+ if (get_kernel_rpl() != 0) {
printk("lguest is afraid of being a guest\n");
return -EPERM;
}
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index daaf866..28433a1 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -375,11 +375,9 @@ static bool direct_trap(unsigned int num)
/*
* The Host needs to see page faults (for shadow paging and to save the
* fault address), general protection faults (in/out emulation) and
- * device not available (TS handling), invalid opcode fault (kvm hcall),
- * and of course, the hypercall trap.
+ * device not available (TS handling) and of course, the hypercall trap.
*/
- return num != 14 && num != 13 && num != 7 &&
- num != 6 && num != LGUEST_TRAP_ENTRY;
+ return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
}
/*:*/
@@ -429,8 +427,8 @@ void pin_stack_pages(struct lg_cpu *cpu)
/*
* Direct traps also mean that we need to know whenever the Guest wants to use
- * a different kernel stack, so we can change the IDT entries to use that
- * stack. The IDT entries expect a virtual address, so unlike most addresses
+ * a different kernel stack, so we can change the guest TSS to use that
+ * stack. The TSS entries expect a virtual address, so unlike most addresses
* the Guest gives us, the "esp" (stack pointer) value here is virtual, not
* physical.
*
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 9136411..295df06 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -59,6 +59,8 @@ struct lg_cpu {
struct lguest_pages *last_pages;
+ /* Initialization mode: linear map everything. */
+ bool linear_pages;
int cpu_pgd; /* Which pgd this cpu is currently using */
/* If a hypercall was asked for, this points to the arguments. */
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 69c84a1..0dc30ff 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/virtio_ring.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/paravirt.h>
@@ -109,6 +110,17 @@ static u32 lg_get_features(struct virtio_device *vdev)
}
/*
+ * To notify on reset or feature finalization, we (ab)use the NOTIFY
+ * hypercall, with the descriptor address of the device.
+ */
+static void status_notify(struct virtio_device *vdev)
+{
+ unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
+
+ hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
+}
+
+/*
* The virtio core takes the features the Host offers, and copies the ones
* supported by the driver into the vdev->features array. Once that's all
* sorted out, this routine is called so we can tell the Host which features we
@@ -135,6 +147,9 @@ static void lg_finalize_features(struct virtio_device *vdev)
if (test_bit(i, vdev->features))
out_features[i / 8] |= (1 << (i % 8));
}
+
+ /* Tell Host we've finished with this device's feature negotiation */
+ status_notify(vdev);
}
/* Once they've found a field, getting a copy of it is easy. */
@@ -168,28 +183,21 @@ static u8 lg_get_status(struct virtio_device *vdev)
return to_lgdev(vdev)->desc->status;
}
-/*
- * To notify on status updates, we (ab)use the NOTIFY hypercall, with the
- * descriptor address of the device. A zero status means "reset".
- */
-static void set_status(struct virtio_device *vdev, u8 status)
-{
- unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
-
- /* We set the status. */
- to_lgdev(vdev)->desc->status = status;
- hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
-}
-
static void lg_set_status(struct virtio_device *vdev, u8 status)
{
BUG_ON(!status);
- set_status(vdev, status);
+ to_lgdev(vdev)->desc->status = status;
+
+ /* Tell Host immediately if we failed. */
+ if (status & VIRTIO_CONFIG_S_FAILED)
+ status_notify(vdev);
}
static void lg_reset(struct virtio_device *vdev)
{
- set_status(vdev, 0);
+ /* 0 status means "reset" */
+ to_lgdev(vdev)->desc->status = 0;
+ status_notify(vdev);
}
/*
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 948c547..ff4a0bc 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,8 +1,10 @@
-/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
- * controls and communicates with the Guest. For example, the first write will
- * tell us the Guest's memory layout and entry point. A read will run the
- * Guest until something happens, such as a signal or the Guest doing a NOTIFY
- * out to the Launcher.
+/*P:200 This contains all the /dev/lguest code, whereby the userspace
+ * launcher controls and communicates with the Guest. For example,
+ * the first write will tell us the Guest's memory layout and entry
+ * point. A read will run the Guest until something happens, such as
+ * a signal or the Guest doing a NOTIFY out to the Launcher. There is
+ * also a way for the Launcher to attach eventfds to particular NOTIFY
+ * values instead of returning from the read() call.
:*/
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
@@ -11,6 +13,7 @@
#include <linux/eventfd.h>
#include <linux/file.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "lg.h"
/*L:056
@@ -357,8 +360,8 @@ static int initialize(struct file *file, const unsigned long __user *input)
goto free_eventfds;
/*
- * Initialize the Guest's shadow page tables, using the toplevel
- * address the Launcher gave us. This allocates memory, so can fail.
+ * Initialize the Guest's shadow page tables. This allocates
+ * memory, so can fail.
*/
err = init_guest_pagetable(lg);
if (err)
@@ -516,6 +519,7 @@ static const struct file_operations lguest_fops = {
.read = read,
.llseek = default_llseek,
};
+/*:*/
/*
* This is a textbook example of a "misc" character device. Populate a "struct
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index d21578e..3b62be1 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -17,7 +17,6 @@
#include <linux/percpu.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
-#include <asm/bootparam.h>
#include "lg.h"
/*M:008
@@ -156,7 +155,7 @@ static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
}
/*
- * These functions are just like the above two, except they access the Guest
+ * These functions are just like the above, except they access the Guest
* page tables. Hence they return a Guest address.
*/
static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
@@ -196,7 +195,7 @@ static unsigned long gpte_addr(struct lg_cpu *cpu,
#endif
/*:*/
-/*M:014
+/*M:007
* get_pfn is slow: we could probably try to grab batches of pages here as
* an optimization (ie. pre-faulting).
:*/
@@ -325,10 +324,15 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
#endif
/* First step: get the top-level Guest page table entry. */
- gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
- /* Toplevel not present? We can't map it in. */
- if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
- return false;
+ if (unlikely(cpu->linear_pages)) {
+ /* Faking up a linear mapping. */
+ gpgd = __pgd(CHECK_GPGD_MASK);
+ } else {
+ gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
+ /* Toplevel not present? We can't map it in. */
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
+ return false;
+ }
/* Now look at the matching shadow entry. */
spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
@@ -353,10 +357,15 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
}
#ifdef CONFIG_X86_PAE
- gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
- /* Middle level not present? We can't map it in. */
- if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
- return false;
+ if (unlikely(cpu->linear_pages)) {
+ /* Faking up a linear mapping. */
+ gpmd = __pmd(_PAGE_TABLE);
+ } else {
+ gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+ /* Middle level not present? We can't map it in. */
+ if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
+ return false;
+ }
/* Now look at the matching shadow entry. */
spmd = spmd_addr(cpu, *spgd, vaddr);
@@ -397,8 +406,13 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
gpte_ptr = gpte_addr(cpu, gpgd, vaddr);
#endif
- /* Read the actual PTE value. */
- gpte = lgread(cpu, gpte_ptr, pte_t);
+ if (unlikely(cpu->linear_pages)) {
+ /* Linear? Make up a PTE which points to same page. */
+ gpte = __pte((vaddr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT);
+ } else {
+ /* Read the actual PTE value. */
+ gpte = lgread(cpu, gpte_ptr, pte_t);
+ }
/* If this page isn't in the Guest page tables, we can't page it in. */
if (!(pte_flags(gpte) & _PAGE_PRESENT))
@@ -454,7 +468,8 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
* Finally, we write the Guest PTE entry back: we've set the
* _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags.
*/
- lgwrite(cpu, gpte_ptr, pte_t, gpte);
+ if (likely(!cpu->linear_pages))
+ lgwrite(cpu, gpte_ptr, pte_t, gpte);
/*
* The fault is fixed, the page table is populated, the mapping
@@ -612,6 +627,11 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr)
#ifdef CONFIG_X86_PAE
pmd_t gpmd;
#endif
+
+ /* Still not set up? Just map 1:1. */
+ if (unlikely(cpu->linear_pages))
+ return vaddr;
+
/* First step: get the top-level Guest page table entry. */
gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
/* Toplevel not present? We can't map it in. */
@@ -708,32 +728,6 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
return next;
}
-/*H:430
- * (iv) Switching page tables
- *
- * Now we've seen all the page table setting and manipulation, let's see
- * what happens when the Guest changes page tables (ie. changes the top-level
- * pgdir). This occurs on almost every context switch.
- */
-void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
-{
- int newpgdir, repin = 0;
-
- /* Look to see if we have this one already. */
- newpgdir = find_pgdir(cpu->lg, pgtable);
- /*
- * If not, we allocate or mug an existing one: if it's a fresh one,
- * repin gets set to 1.
- */
- if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
- newpgdir = new_pgdir(cpu, pgtable, &repin);
- /* Change the current pgd index to the new one. */
- cpu->cpu_pgd = newpgdir;
- /* If it was completely blank, we map in the Guest kernel stack */
- if (repin)
- pin_stack_pages(cpu);
-}
-
/*H:470
* Finally, a routine which throws away everything: all PGD entries in all
* the shadow page tables, including the Guest's kernel mappings. This is used
@@ -780,6 +774,44 @@ void guest_pagetable_clear_all(struct lg_cpu *cpu)
/* We need the Guest kernel stack mapped again. */
pin_stack_pages(cpu);
}
+
+/*H:430
+ * (iv) Switching page tables
+ *
+ * Now we've seen all the page table setting and manipulation, let's see
+ * what happens when the Guest changes page tables (ie. changes the top-level
+ * pgdir). This occurs on almost every context switch.
+ */
+void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
+{
+ int newpgdir, repin = 0;
+
+ /*
+ * The very first time they call this, we're actually running without
+ * any page tables; we've been making it up. Throw them away now.
+ */
+ if (unlikely(cpu->linear_pages)) {
+ release_all_pagetables(cpu->lg);
+ cpu->linear_pages = false;
+ /* Force allocation of a new pgdir. */
+ newpgdir = ARRAY_SIZE(cpu->lg->pgdirs);
+ } else {
+ /* Look to see if we have this one already. */
+ newpgdir = find_pgdir(cpu->lg, pgtable);
+ }
+
+ /*
+ * If not, we allocate or mug an existing one: if it's a fresh one,
+ * repin gets set to 1.
+ */
+ if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
+ newpgdir = new_pgdir(cpu, pgtable, &repin);
+ /* Change the current pgd index to the new one. */
+ cpu->cpu_pgd = newpgdir;
+ /* If it was completely blank, we map in the Guest kernel stack */
+ if (repin)
+ pin_stack_pages(cpu);
+}
/*:*/
/*M:009
@@ -919,168 +951,26 @@ void guest_set_pmd(struct lguest *lg, unsigned long pmdp, u32 idx)
}
#endif
-/*H:505
- * To get through boot, we construct simple identity page mappings (which
- * set virtual == physical) and linear mappings which will get the Guest far
- * enough into the boot to create its own. The linear mapping means we
- * simplify the Guest boot, but it makes assumptions about their PAGE_OFFSET,
- * as you'll see.
- *
- * We lay them out of the way, just below the initrd (which is why we need to
- * know its size here).
- */
-static unsigned long setup_pagetables(struct lguest *lg,
- unsigned long mem,
- unsigned long initrd_size)
-{
- pgd_t __user *pgdir;
- pte_t __user *linear;
- unsigned long mem_base = (unsigned long)lg->mem_base;
- unsigned int mapped_pages, i, linear_pages;
-#ifdef CONFIG_X86_PAE
- pmd_t __user *pmds;
- unsigned int j;
- pgd_t pgd;
- pmd_t pmd;
-#else
- unsigned int phys_linear;
-#endif
-
- /*
- * We have mapped_pages frames to map, so we need linear_pages page
- * tables to map them.
- */
- mapped_pages = mem / PAGE_SIZE;
- linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE;
-
- /* We put the toplevel page directory page at the top of memory. */
- pgdir = (pgd_t *)(mem + mem_base - initrd_size - PAGE_SIZE);
-
- /* Now we use the next linear_pages pages as pte pages */
- linear = (void *)pgdir - linear_pages * PAGE_SIZE;
-
-#ifdef CONFIG_X86_PAE
- /*
- * And the single mid page goes below that. We only use one, but
- * that's enough to map 1G, which definitely gets us through boot.
- */
- pmds = (void *)linear - PAGE_SIZE;
-#endif
- /*
- * Linear mapping is easy: put every page's address into the
- * mapping in order.
- */
- for (i = 0; i < mapped_pages; i++) {
- pte_t pte;
- pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER));
- if (copy_to_user(&linear[i], &pte, sizeof(pte)) != 0)
- return -EFAULT;
- }
-
-#ifdef CONFIG_X86_PAE
- /*
- * Make the Guest PMD entries point to the corresponding place in the
- * linear mapping (up to one page worth of PMD).
- */
- for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD;
- i += PTRS_PER_PTE, j++) {
- pmd = pfn_pmd(((unsigned long)&linear[i] - mem_base)/PAGE_SIZE,
- __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
-
- if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0)
- return -EFAULT;
- }
-
- /* One PGD entry, pointing to that PMD page. */
- pgd = __pgd(((unsigned long)pmds - mem_base) | _PAGE_PRESENT);
- /* Copy it in as the first PGD entry (ie. addresses 0-1G). */
- if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0)
- return -EFAULT;
- /*
- * And the other PGD entry to make the linear mapping at PAGE_OFFSET
- */
- if (copy_to_user(&pgdir[KERNEL_PGD_BOUNDARY], &pgd, sizeof(pgd)))
- return -EFAULT;
-#else
- /*
- * The top level points to the linear page table pages above.
- * We setup the identity and linear mappings here.
- */
- phys_linear = (unsigned long)linear - mem_base;
- for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) {
- pgd_t pgd;
- /*
- * Create a PGD entry which points to the right part of the
- * linear PTE pages.
- */
- pgd = __pgd((phys_linear + i * sizeof(pte_t)) |
- (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
-
- /*
- * Copy it into the PGD page at 0 and PAGE_OFFSET.
- */
- if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd))
- || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET)
- + i / PTRS_PER_PTE],
- &pgd, sizeof(pgd)))
- return -EFAULT;
- }
-#endif
-
- /*
- * We return the top level (guest-physical) address: we remember where
- * this is to write it into lguest_data when the Guest initializes.
- */
- return (unsigned long)pgdir - mem_base;
-}
-
/*H:500
* (vii) Setting up the page tables initially.
*
- * When a Guest is first created, the Launcher tells us where the toplevel of
- * its first page table is. We set some things up here:
+ * When a Guest is first created, set initialize a shadow page table which
+ * we will populate on future faults. The Guest doesn't have any actual
+ * pagetables yet, so we set linear_pages to tell demand_page() to fake it
+ * for the moment.
*/
int init_guest_pagetable(struct lguest *lg)
{
- u64 mem;
- u32 initrd_size;
- struct boot_params __user *boot = (struct boot_params *)lg->mem_base;
-#ifdef CONFIG_X86_PAE
- pgd_t *pgd;
- pmd_t *pmd_table;
-#endif
- /*
- * Get the Guest memory size and the ramdisk size from the boot header
- * located at lg->mem_base (Guest address 0).
- */
- if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem))
- || get_user(initrd_size, &boot->hdr.ramdisk_size))
- return -EFAULT;
+ struct lg_cpu *cpu = &lg->cpus[0];
+ int allocated = 0;
- /*
- * We start on the first shadow page table, and give it a blank PGD
- * page.
- */
- lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size);
- if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir))
- return lg->pgdirs[0].gpgdir;
- lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
- if (!lg->pgdirs[0].pgdir)
+ /* lg (and lg->cpus[]) starts zeroed: this allocates a new pgdir */
+ cpu->cpu_pgd = new_pgdir(cpu, 0, &allocated);
+ if (!allocated)
return -ENOMEM;
-#ifdef CONFIG_X86_PAE
- /* For PAE, we also create the initial mid-level. */
- pgd = lg->pgdirs[0].pgdir;
- pmd_table = (pmd_t *) get_zeroed_page(GFP_KERNEL);
- if (!pmd_table)
- return -ENOMEM;
-
- set_pgd(pgd + SWITCHER_PGD_INDEX,
- __pgd(__pa(pmd_table) | _PAGE_PRESENT));
-#endif
-
- /* This is the current page table. */
- lg->cpus[0].cpu_pgd = 0;
+ /* We start with a linear mapping until the initialize. */
+ cpu->linear_pages = true;
return 0;
}
@@ -1095,10 +985,10 @@ void page_table_guest_data_init(struct lg_cpu *cpu)
* of virtual addresses used by the Switcher.
*/
|| put_user(RESERVE_MEM * 1024 * 1024,
- &cpu->lg->lguest_data->reserve_mem)
- || put_user(cpu->lg->pgdirs[0].gpgdir,
- &cpu->lg->lguest_data->pgdir))
+ &cpu->lg->lguest_data->reserve_mem)) {
kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
+ return;
+ }
/*
* In flush_user_mappings() we loop from 0 to
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 9f1659c..65af42f 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -269,10 +269,10 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
static int emulate_insn(struct lg_cpu *cpu)
{
u8 insn;
- unsigned int insnlen = 0, in = 0, shift = 0;
+ unsigned int insnlen = 0, in = 0, small_operand = 0;
/*
* The eip contains the *virtual* address of the Guest's instruction:
- * guest_pa just subtracts the Guest's page_offset.
+ * walk the Guest's page tables to find the "physical" address.
*/
unsigned long physaddr = guest_pa(cpu, cpu->regs->eip);
@@ -300,11 +300,10 @@ static int emulate_insn(struct lg_cpu *cpu)
}
/*
- * 0x66 is an "operand prefix". It means it's using the upper 16 bits
- * of the eax register.
+ * 0x66 is an "operand prefix". It means a 16, not 32 bit in/out.
*/
if (insn == 0x66) {
- shift = 16;
+ small_operand = 1;
/* The instruction is 1 byte so far, read the next byte. */
insnlen = 1;
insn = lgread(cpu, physaddr + insnlen, u8);
@@ -340,11 +339,14 @@ static int emulate_insn(struct lg_cpu *cpu)
* traditionally means "there's nothing there".
*/
if (in) {
- /* Lower bit tells is whether it's a 16 or 32 bit access */
- if (insn & 0x1)
- cpu->regs->eax = 0xFFFFFFFF;
- else
- cpu->regs->eax |= (0xFFFF << shift);
+ /* Lower bit tells means it's a 32/16 bit access */
+ if (insn & 0x1) {
+ if (small_operand)
+ cpu->regs->eax |= 0xFFFF;
+ else
+ cpu->regs->eax = 0xFFFFFFFF;
+ } else
+ cpu->regs->eax |= 0xFF;
}
/* Finally, we've "done" the instruction, so move past it. */
cpu->regs->eip += insnlen;
@@ -352,69 +354,6 @@ static int emulate_insn(struct lg_cpu *cpu)
return 1;
}
-/*
- * Our hypercalls mechanism used to be based on direct software interrupts.
- * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to
- * change over to using kvm hypercalls.
- *
- * KVM_HYPERCALL is actually a "vmcall" instruction, which generates an invalid
- * opcode fault (fault 6) on non-VT cpus, so the easiest solution seemed to be
- * an *emulation approach*: if the fault was really produced by an hypercall
- * (is_hypercall() does exactly this check), we can just call the corresponding
- * hypercall host implementation function.
- *
- * But these invalid opcode faults are notably slower than software interrupts.
- * So we implemented the *patching (or rewriting) approach*: every time we hit
- * the KVM_HYPERCALL opcode in Guest code, we patch it to the old "int 0x1f"
- * opcode, so next time the Guest calls this hypercall it will use the
- * faster trap mechanism.
- *
- * Matias even benchmarked it to convince you: this shows the average cycle
- * cost of a hypercall. For each alternative solution mentioned above we've
- * made 5 runs of the benchmark:
- *
- * 1) direct software interrupt: 2915, 2789, 2764, 2721, 2898
- * 2) emulation technique: 3410, 3681, 3466, 3392, 3780
- * 3) patching (rewrite) technique: 2977, 2975, 2891, 2637, 2884
- *
- * One two-line function is worth a 20% hypercall speed boost!
- */
-static void rewrite_hypercall(struct lg_cpu *cpu)
-{
- /*
- * This are the opcodes we use to patch the Guest. The opcode for "int
- * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we
- * complete the sequence with a NOP (0x90).
- */
- u8 insn[3] = {0xcd, 0x1f, 0x90};
-
- __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
- /*
- * The above write might have caused a copy of that page to be made
- * (if it was read-only). We need to make sure the Guest has
- * up-to-date pagetables. As this doesn't happen often, we can just
- * drop them all.
- */
- guest_pagetable_clear_all(cpu);
-}
-
-static bool is_hypercall(struct lg_cpu *cpu)
-{
- u8 insn[3];
-
- /*
- * This must be the Guest kernel trying to do something.
- * The bottom two bits of the CS segment register are the privilege
- * level.
- */
- if ((cpu->regs->cs & 3) != GUEST_PL)
- return false;
-
- /* Is it a vmcall? */
- __lgread(cpu, insn, guest_pa(cpu, cpu->regs->eip), sizeof(insn));
- return insn[0] == 0x0f && insn[1] == 0x01 && insn[2] == 0xc1;
-}
-
/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
void lguest_arch_handle_trap(struct lg_cpu *cpu)
{
@@ -429,20 +368,6 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
if (emulate_insn(cpu))
return;
}
- /*
- * If KVM is active, the vmcall instruction triggers a General
- * Protection Fault. Normally it triggers an invalid opcode
- * fault (6):
- */
- case 6:
- /*
- * We need to check if ring == GUEST_PL and faulting
- * instruction == vmcall.
- */
- if (is_hypercall(cpu)) {
- rewrite_hypercall(cpu);
- return;
- }
break;
case 14: /* We've intercepted a Page Fault. */
/*
@@ -486,7 +411,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
* These values mean a real interrupt occurred, in which case
* the Host handler has already been run. We just do a
* friendly check if another process should now be run, then
- * return to run the Guest again
+ * return to run the Guest again.
*/
cond_resched();
return;
@@ -536,7 +461,7 @@ void __init lguest_arch_host_init(void)
int i;
/*
- * Most of the i386/switcher.S doesn't care that it's been moved; on
+ * Most of the x86/switcher_32.S doesn't care that it's been moved; on
* Intel, jumps are relative, and it doesn't access any references to
* external code or data.
*
@@ -664,7 +589,7 @@ void __init lguest_arch_host_init(void)
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
}
put_online_cpus();
-};
+}
/*:*/
void __exit lguest_arch_host_fini(void)
@@ -747,8 +672,6 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
/*:*/
/*L:030
- * lguest_arch_setup_regs()
- *
* Most of the Guest's registers are left alone: we used get_zeroed_page() to
* allocate the structure, so they will be 0.
*/
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
index a271c82..f0e03e7 100644
--- a/drivers/macintosh/nvram.c
+++ b/drivers/macintosh/nvram.c
@@ -21,12 +21,16 @@
static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
{
switch (origin) {
+ case 0:
+ break;
case 1:
offset += file->f_pos;
break;
case 2:
offset += NVRAM_SIZE;
break;
+ default:
+ offset = -1;
}
if (offset < 0)
return -EINVAL;
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 817f37a..c9570fc 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -159,7 +159,7 @@ int macii_init(void)
err = macii_init_via();
if (err) goto out;
- err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+ err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
macii_interrupt);
if (err) goto out;
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 9ab5b0c..34d02a9 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -122,8 +122,8 @@ maciisi_init(void)
return err;
}
- if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST,
- "ADB", maciisi_interrupt)) {
+ if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
+ maciisi_interrupt)) {
printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
return -EAGAIN;
}
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index ce88979..004fa10 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -421,7 +421,7 @@ int wf_unregister_client(struct notifier_block *nb)
{
mutex_lock(&wf_lock);
blocking_notifier_chain_unregister(&wf_client_list, nb);
- wf_client_count++;
+ wf_client_count--;
if (wf_client_count == 0)
wf_stop_thread();
mutex_unlock(&wf_lock);
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 9af2140..d6b1cf6 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -18,7 +18,10 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146.h>
+#include <linux/module.h>
LIST_HEAD(saa7146_devices);
DEFINE_MUTEX(saa7146_devices_lock);
@@ -35,10 +38,9 @@ static void dump_registers(struct saa7146_dev* dev)
{
int i = 0;
- INFO((" @ %li jiffies:\n",jiffies));
- for(i = 0; i <= 0x148; i+=4) {
- printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
- }
+ pr_info(" @ %li jiffies:\n", jiffies);
+ for (i = 0; i <= 0x148; i += 4)
+ pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
}
#endif
@@ -72,9 +74,8 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
if (saa7146_read(dev, MC2) & 2)
break;
if (err) {
- printk(KERN_ERR "%s: %s timed out while waiting for "
- "registers getting programmed\n",
- dev->name, __func__);
+ pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
msleep(1);
@@ -88,8 +89,8 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
break;
saa7146_read(dev, MC2);
if (err) {
- DEB_S(("%s: %s timed out while waiting for transfer "
- "completion\n", dev->name, __func__));
+ DEB_S("%s: %s timed out while waiting for transfer completion\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
msleep(1);
@@ -109,9 +110,8 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
if (saa7146_read(dev, MC2) & 2)
break;
if (!loops--) {
- printk(KERN_ERR "%s: %s timed out while waiting for "
- "registers getting programmed\n",
- dev->name, __func__);
+ pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
udelay(1);
@@ -124,8 +124,8 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
break;
saa7146_read(dev, MC2);
if (!loops--) {
- DEB_S(("%s: %s timed out while waiting for transfer "
- "completion\n", dev->name, __func__));
+ DEB_S("%s: %s timed out while waiting for transfer completion\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
udelay(5);
@@ -264,7 +264,9 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
ptr = pt->cpu;
for (i = 0; i < sglen; i++, list++) {
/*
- printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
+ pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
+ i, sg_dma_address(list), sg_dma_len(list),
+ list->offset);
*/
for (p = 0; p * 4096 < list->length; p++, ptr++) {
*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
@@ -281,9 +283,9 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
/*
ptr = pt->cpu;
- printk("offset: %d\n",pt->offset);
+ pr_debug("offset: %d\n", pt->offset);
for(i=0;i<5;i++) {
- printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
+ pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
}
*/
return 0;
@@ -314,7 +316,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
}
}
if (0 != (isr & (MASK_27))) {
- DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+ DEB_INT("irq: RPS0 (0x%08x)\n", isr);
if (dev->vv_data && dev->vv_callback)
dev->vv_callback(dev,isr);
isr &= ~MASK_27;
@@ -333,14 +335,15 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
} else {
u32 psr = saa7146_read(dev, PSR);
u32 ssr = saa7146_read(dev, SSR);
- printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
- dev->name, isr, psr, ssr);
+ pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+ dev->name, isr, psr, ssr);
}
isr &= ~(MASK_16|MASK_17);
}
if( 0 != isr ) {
- ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
- ERR(("disabling interrupt source(s)!\n"));
+ ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
+ isr);
+ ERR("disabling interrupt source(s)!\n");
SAA7146_IER_DISABLE(dev,isr);
}
saa7146_write(dev, ISR, ack_isr);
@@ -360,15 +363,15 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
/* clear out mem for sure */
dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
if (!dev) {
- ERR(("out of memory.\n"));
+ ERR("out of memory\n");
goto out;
}
- DEB_EE(("pci:%p\n",pci));
+ DEB_EE("pci:%p\n", pci);
err = pci_enable_device(pci);
if (err < 0) {
- ERR(("pci_enable_device() failed.\n"));
+ ERR("pci_enable_device() failed\n");
goto err_free;
}
@@ -389,7 +392,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
dev->mem = ioremap(pci_resource_start(pci, 0),
pci_resource_len(pci, 0));
if (!dev->mem) {
- ERR(("ioremap() failed.\n"));
+ ERR("ioremap() failed\n");
err = -ENODEV;
goto err_release;
}
@@ -414,7 +417,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
dev->name, dev);
if (err < 0) {
- ERR(("request_irq() failed.\n"));
+ ERR("request_irq() failed\n");
goto err_unmap;
}
@@ -444,7 +447,9 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
/* create a nice device name */
sprintf(dev->name, "saa7146 (%d)", saa7146_num);
- INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
+ pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
+ dev->mem, dev->revision, pci->irq,
+ pci->subsystem_vendor, pci->subsystem_device);
dev->ext = ext;
mutex_init(&dev->v4l2_lock);
@@ -464,12 +469,12 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
err = -ENODEV;
if (ext->probe && ext->probe(dev)) {
- DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
+ DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
goto err_free_i2c;
}
if (ext->attach(dev, pci_ext)) {
- DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
+ DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
goto err_free_i2c;
}
/* V4L extensions will set the pci drvdata to the v4l2_device in the
@@ -521,7 +526,7 @@ static void saa7146_remove_one(struct pci_dev *pdev)
{ NULL, 0 }
}, *p;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
dev->ext->detach(dev);
/* Zero the PCI drvdata after use. */
@@ -552,21 +557,21 @@ static void saa7146_remove_one(struct pci_dev *pdev)
int saa7146_register_extension(struct saa7146_extension* ext)
{
- DEB_EE(("ext:%p\n",ext));
+ DEB_EE("ext:%p\n", ext);
ext->driver.name = ext->name;
ext->driver.id_table = ext->pci_tbl;
ext->driver.probe = saa7146_init_one;
ext->driver.remove = saa7146_remove_one;
- printk("saa7146: register extension '%s'.\n",ext->name);
+ pr_info("register extension '%s'\n", ext->name);
return pci_register_driver(&ext->driver);
}
int saa7146_unregister_extension(struct saa7146_extension* ext)
{
- DEB_EE(("ext:%p\n",ext));
- printk("saa7146: unregister extension '%s'.\n",ext->name);
+ DEB_EE("ext:%p\n", ext);
+ pr_info("unregister extension '%s'\n", ext->name);
pci_unregister_driver(&ext->driver);
return 0;
}
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 1bd3dd7..71f8e01 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -1,4 +1,7 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146_vv.h>
+#include <linux/module.h>
/****************************************************************************/
/* resource management functions, shamelessly stolen from saa7134 driver */
@@ -9,21 +12,23 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
struct saa7146_vv *vv = dev->vv_data;
if (fh->resources & bit) {
- DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
+ DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
+ bit, vv->resources);
/* have it already allocated */
return 1;
}
/* is it free? */
if (vv->resources & bit) {
- DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
+ DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
+ vv->resources, bit);
/* no, someone else uses it */
return 0;
}
/* it's free, grab it */
- fh->resources |= bit;
+ fh->resources |= bit;
vv->resources |= bit;
- DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
+ DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
return 1;
}
@@ -34,9 +39,9 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
BUG_ON((fh->resources & bits) != bits);
- fh->resources &= ~bits;
+ fh->resources &= ~bits;
vv->resources &= ~bits;
- DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
+ DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
}
@@ -47,7 +52,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
struct saa7146_buf *buf)
{
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- DEB_EE(("dev:%p, buf:%p\n",dev,buf));
+ DEB_EE("dev:%p, buf:%p\n", dev, buf);
BUG_ON(in_interrupt());
@@ -66,18 +71,19 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
struct saa7146_buf *buf)
{
assert_spin_locked(&dev->slock);
- DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
+ DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
BUG_ON(!q);
if (NULL == q->curr) {
q->curr = buf;
- DEB_D(("immediately activating buffer %p\n", buf));
+ DEB_D("immediately activating buffer %p\n", buf);
buf->activate(dev,buf,NULL);
} else {
list_add_tail(&buf->vb.queue,&q->queue);
buf->vb.state = VIDEOBUF_QUEUED;
- DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
+ DEB_D("adding buffer %p to queue. (active buffer present)\n",
+ buf);
}
return 0;
}
@@ -87,14 +93,14 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
int state)
{
assert_spin_locked(&dev->slock);
- DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
- DEB_EE(("q->curr:%p\n",q->curr));
+ DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
+ DEB_EE("q->curr:%p\n", q->curr);
BUG_ON(!q->curr);
/* finish current buffer */
if (NULL == q->curr) {
- DEB_D(("aiii. no current buffer\n"));
+ DEB_D("aiii. no current buffer\n");
return;
}
@@ -112,7 +118,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
BUG_ON(!q);
- DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+ DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
assert_spin_locked(&dev->slock);
if (!list_empty(&q->queue)) {
@@ -122,10 +128,11 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
if (!list_empty(&q->queue))
next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
q->curr = buf;
- DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+ DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
+ buf, q->queue.prev, q->queue.next);
buf->activate(dev,buf,next);
} else {
- DEB_INT(("no next buffer. stopping.\n"));
+ DEB_INT("no next buffer. stopping.\n");
if( 0 != vbi ) {
/* turn off video-dma3 */
saa7146_write(dev,MC1, MASK_20);
@@ -162,11 +169,11 @@ void saa7146_buffer_timeout(unsigned long data)
struct saa7146_dev *dev = q->dev;
unsigned long flags;
- DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
+ DEB_EE("dev:%p, dmaq:%p\n", dev, q);
spin_lock_irqsave(&dev->slock,flags);
if (q->curr) {
- DEB_D(("timeout on %p\n", q->curr));
+ DEB_D("timeout on %p\n", q->curr);
saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
}
@@ -194,12 +201,12 @@ static int fops_open(struct file *file)
enum v4l2_buf_type type;
- DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
+ DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
- DEB_D(("using: %p\n",dev));
+ DEB_D("using: %p\n", dev);
type = vdev->vfl_type == VFL_TYPE_GRABBER
? V4L2_BUF_TYPE_VIDEO_CAPTURE
@@ -207,7 +214,7 @@ static int fops_open(struct file *file)
/* check if an extension is registered */
if( NULL == dev->ext ) {
- DEB_S(("no extension registered for this device.\n"));
+ DEB_S("no extension registered for this device\n");
result = -ENODEV;
goto out;
}
@@ -215,7 +222,7 @@ static int fops_open(struct file *file)
/* allocate per open data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh) {
- DEB_S(("cannot allocate memory for per open data.\n"));
+ DEB_S("cannot allocate memory for per open data\n");
result = -ENOMEM;
goto out;
}
@@ -225,13 +232,13 @@ static int fops_open(struct file *file)
fh->type = type;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- DEB_S(("initializing vbi...\n"));
+ DEB_S("initializing vbi...\n");
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
result = saa7146_vbi_uops.open(dev,file);
if (dev->ext_vv_data->vbi_fops.open)
dev->ext_vv_data->vbi_fops.open(file);
} else {
- DEB_S(("initializing video...\n"));
+ DEB_S("initializing video...\n");
result = saa7146_video_uops.open(dev,file);
}
@@ -259,7 +266,7 @@ static int fops_release(struct file *file)
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
- DEB_EE(("file:%p\n", file));
+ DEB_EE("file:%p\n", file);
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
@@ -289,12 +296,14 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
+ file, vma);
q = &fh->video_q;
break;
}
case V4L2_BUF_TYPE_VBI_CAPTURE: {
- DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
+ DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
+ file, vma);
q = &fh->vbi_q;
break;
}
@@ -312,14 +321,14 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
struct videobuf_buffer *buf = NULL;
struct videobuf_queue *q;
- DEB_EE(("file:%p, poll:%p\n",file, wait));
+ DEB_EE("file:%p, poll:%p\n", file, wait);
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if( 0 == fh->vbi_q.streaming )
return videobuf_poll_stream(file, &fh->vbi_q, wait);
q = &fh->vbi_q;
} else {
- DEB_D(("using video queue.\n"));
+ DEB_D("using video queue\n");
q = &fh->video_q;
}
@@ -327,17 +336,17 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
if (!buf) {
- DEB_D(("buf == NULL!\n"));
+ DEB_D("buf == NULL!\n");
return POLLERR;
}
poll_wait(file, &buf->done, wait);
if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
- DEB_D(("poll succeeded!\n"));
+ DEB_D("poll succeeded!\n");
return POLLIN|POLLRDNORM;
}
- DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
+ DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
return 0;
}
@@ -346,18 +355,20 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
struct saa7146_fh *fh = file->private_data;
switch (fh->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+/*
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
+ file, data, (unsigned long)count);
+*/
return saa7146_video_uops.read(file,data,count,ppos);
- }
- case V4L2_BUF_TYPE_VBI_CAPTURE: {
-// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+/*
+ DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
+ file, data, (unsigned long)count);
+*/
if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
return saa7146_vbi_uops.read(file,data,count,ppos);
- else
- return -EINVAL;
- }
- break;
+ return -EINVAL;
default:
BUG();
return 0;
@@ -398,22 +409,22 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
{
u32 isr = status;
- DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+ DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
if (0 != (isr & (MASK_27))) {
- DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+ DEB_INT("irq: RPS0 (0x%08x)\n", isr);
saa7146_video_uops.irq_done(dev,isr);
}
if (0 != (isr & (MASK_28))) {
u32 mc2 = saa7146_read(dev, MC2);
if( 0 != (mc2 & MASK_15)) {
- DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
+ DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
wake_up(&dev->vv_data->vbi_wq);
saa7146_write(dev,MC2, MASK_31);
return;
}
- DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
+ DEB_INT("irq: RPS1 (0x%08x)\n", isr);
saa7146_vbi_uops.irq_done(dev,isr);
}
}
@@ -429,13 +440,13 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
if (vv == NULL) {
- ERR(("out of memory. aborting.\n"));
+ ERR("out of memory. aborting.\n");
return -ENOMEM;
}
ext_vv->ops = saa7146_video_ioctl_ops;
ext_vv->core_ops = &saa7146_video_ioctl_ops;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
/* set default values for video parts of the saa7146 */
saa7146_write(dev, BCS_CTRL, 0x80400040);
@@ -450,7 +461,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
if( NULL == vv->d_clipping.cpu_addr ) {
- ERR(("out of memory. aborting.\n"));
+ ERR("out of memory. aborting.\n");
kfree(vv);
return -1;
}
@@ -471,7 +482,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
{
struct saa7146_vv *vv = dev->vv_data;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
v4l2_device_unregister(&dev->v4l2_dev);
pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
@@ -490,7 +501,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
int err;
int i;
- DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
+ DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
// released by vfd->release
vfd = video_device_alloc();
@@ -509,13 +520,13 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
err = video_register_device(vfd, type, -1);
if (err < 0) {
- ERR(("cannot register v4l2 device. skipping.\n"));
+ ERR("cannot register v4l2 device. skipping.\n");
video_device_release(vfd);
return err;
}
- INFO(("%s: registered device %s [v4l2]\n",
- dev->name, video_device_node_name(vfd)));
+ pr_info("%s: registered device %s [v4l2]\n",
+ dev->name, video_device_node_name(vfd));
*vid = vfd;
return 0;
@@ -524,7 +535,7 @@ EXPORT_SYMBOL_GPL(saa7146_register_device);
int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
{
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
video_unregister_device(*vid);
*vid = NULL;
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 1d1d8d2..bc1f545 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -1,4 +1,7 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
+#include <linux/export.h>
#include <media/saa7146_vv.h>
static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
@@ -711,8 +714,8 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
int depth = sfmt->depth;
- DEB_CAP(("[size=%dx%d,fields=%s]\n",
- width,height,v4l2_field_names[field]));
+ DEB_CAP("[size=%dx%d,fields=%s]\n",
+ width, height, v4l2_field_names[field]);
if( bytesperline != 0) {
vdma1.pitch = bytesperline*2;
@@ -837,8 +840,8 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
BUG_ON(0 == buf->pt[1].dma);
BUG_ON(0 == buf->pt[2].dma);
- DEB_CAP(("[size=%dx%d,fields=%s]\n",
- width,height,v4l2_field_names[field]));
+ DEB_CAP("[size=%dx%d,fields=%s]\n",
+ width, height, v4l2_field_names[field]);
/* fixme: look at bytesperline! */
@@ -998,12 +1001,12 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
struct saa7146_vv *vv = dev->vv_data;
u32 vdma1_prot_addr;
- DEB_CAP(("buf:%p, next:%p\n",buf,next));
+ DEB_CAP("buf:%p, next:%p\n", buf, next);
vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
if( 0 == vdma1_prot_addr ) {
/* clear out beginning of streaming bit (rps register 0)*/
- DEB_CAP(("forcing sync to new frame\n"));
+ DEB_CAP("forcing sync to new frame\n");
saa7146_write(dev, MC2, MASK_27 );
}
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index b2ba9dc..2202719 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -1,8 +1,10 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146_vv.h>
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
{
-//fm DEB_I2C(("'%s'.\n", adapter->name));
+ /* DEB_I2C("'%s'\n", adapter->name); */
return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_QUICK
@@ -14,9 +16,7 @@ static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
{
u32 iicsta = saa7146_read(dev, I2C_STATUS);
-/*
- DEB_I2C(("status: 0x%08x\n",iicsta));
-*/
+ /* DEB_I2C("status: 0x%08x\n", iicsta); */
return iicsta;
}
@@ -39,10 +39,11 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
plus one extra byte to address the device */
mem = 1 + ((mem-1) / 3);
- /* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
- size. if we exceed this limit... */
- if ( (4*mem) > SAA7146_I2C_MEM ) {
-//fm DEB_I2C(("cannot prepare i2c-message.\n"));
+ /* we assume that op points to a memory of at least
+ * SAA7146_I2C_MEM bytes size. if we exceed this limit...
+ */
+ if ((4 * mem) > SAA7146_I2C_MEM) {
+ /* DEB_I2C("cannot prepare i2c-message\n"); */
return -ENOMEM;
}
@@ -123,7 +124,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
/* yes, kill ongoing operation */
- DEB_I2C(("busy_state detected.\n"));
+ DEB_I2C("busy_state detected\n");
/* set "ABORT-OPERATION"-bit (bit 7)*/
saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
@@ -141,7 +142,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
if ( dev->i2c_bitrate != status ) {
- DEB_I2C(("error_state detected. status:0x%08x\n",status));
+ DEB_I2C("error_state detected. status:0x%08x\n", status);
/* Repeat the abort operation. This seems to be necessary
after serious protocol errors caused by e.g. the SAA7740 */
@@ -164,7 +165,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
/* if any error is still present, a fatal error has occurred ... */
status = saa7146_i2c_status(dev);
if ( dev->i2c_bitrate != status ) {
- DEB_I2C(("fatal error. status:0x%08x\n",status));
+ DEB_I2C("fatal error. status:0x%08x\n", status);
return -1;
}
@@ -181,7 +182,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
unsigned long timeout;
/* write out i2c-command */
- DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
+ DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
+ *dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
@@ -202,7 +204,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
/* a signal arrived */
return -ERESTARTSYS;
- printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+ pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
dev->name, __func__);
return -EIO;
}
@@ -220,7 +222,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
break;
}
if (time_after(jiffies,timeout)) {
- printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+ pr_warn("%s %s: timed out waiting for MC2\n",
dev->name, __func__);
return -EIO;
}
@@ -237,7 +239,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
/* this is normal when probing the bus
* (no answer from nonexisistant device...)
*/
- printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+ pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
dev->name, __func__);
return -EIO;
}
@@ -257,24 +259,24 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
if ( 0 == (status & SAA7146_I2C_ERR) ||
0 == (status & SAA7146_I2C_BUSY) ) {
/* it may take some time until ERR goes high - ignore */
- DEB_I2C(("unexpected i2c status %04x\n", status));
+ DEB_I2C("unexpected i2c status %04x\n", status);
}
if( 0 != (status & SAA7146_I2C_SPERR) ) {
- DEB_I2C(("error due to invalid start/stop condition.\n"));
+ DEB_I2C("error due to invalid start/stop condition\n");
}
if( 0 != (status & SAA7146_I2C_DTERR) ) {
- DEB_I2C(("error in data transmission.\n"));
+ DEB_I2C("error in data transmission\n");
}
if( 0 != (status & SAA7146_I2C_DRERR) ) {
- DEB_I2C(("error when receiving data.\n"));
+ DEB_I2C("error when receiving data\n");
}
if( 0 != (status & SAA7146_I2C_AL) ) {
- DEB_I2C(("error because arbitration lost.\n"));
+ DEB_I2C("error because arbitration lost\n");
}
/* we handle address-errors here */
if( 0 != (status & SAA7146_I2C_APERR) ) {
- DEB_I2C(("error in address phase.\n"));
+ DEB_I2C("error in address phase\n");
return -EREMOTEIO;
}
@@ -284,7 +286,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
/* read back data, just in case we were reading ... */
*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
- DEB_I2C(("after: 0x%08x\n",*dword));
+ DEB_I2C("after: 0x%08x\n", *dword);
return 0;
}
@@ -299,7 +301,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
return -ERESTARTSYS;
for(i=0;i<num;i++) {
- DEB_I2C(("msg:%d/%d\n",i+1,num));
+ DEB_I2C("msg:%d/%d\n", i+1, num);
}
/* prepare the message(s), get number of u32s to transfer */
@@ -316,7 +318,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
/* reset the i2c-device if necessary */
err = saa7146_i2c_reset(dev);
if ( 0 > err ) {
- DEB_I2C(("could not reset i2c-device.\n"));
+ DEB_I2C("could not reset i2c-device\n");
goto out;
}
@@ -336,7 +338,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
address error and trust the saa7146 address error detection. */
if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
goto out;
- DEB_I2C(("error while sending message(s). starting again.\n"));
+ DEB_I2C("error while sending message(s). starting again\n");
break;
}
}
@@ -356,13 +358,13 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
/* if any things had to be read, get the results */
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
- DEB_I2C(("could not cleanup i2c-message.\n"));
+ DEB_I2C("could not cleanup i2c-message\n");
err = -1;
goto out;
}
/* return the number of delivered messages */
- DEB_I2C(("transmission successful. (msg:%d).\n",err));
+ DEB_I2C("transmission successful. (msg:%d)\n", err);
out:
/* another bug in revision 0: the i2c-registers get uploaded randomly by other
uploads, so we better clear them out before continuing */
@@ -370,7 +372,7 @@ out:
__le32 zero = 0;
saa7146_i2c_reset(dev);
if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
- INFO(("revision 0 error. this should never happen.\n"));
+ pr_info("revision 0 error. this should never happen\n");
}
}
@@ -400,7 +402,7 @@ static struct i2c_algorithm saa7146_algo = {
int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
{
- DEB_EE(("bitrate: 0x%08x\n",bitrate));
+ DEB_EE("bitrate: 0x%08x\n", bitrate);
/* enable i2c-port pins */
saa7146_write(dev, MC1, (MASK_08 | MASK_24));
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index afe8580..b2e7183 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -14,7 +14,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
DECLARE_WAITQUEUE(wait, current);
- DEB_VBI(("dev:%p\n",dev));
+ DEB_VBI("dev:%p\n", dev);
/* once again, a bug in the saa7146: the brs acquisition
is buggy and especially the BXO-counter does not work
@@ -40,14 +40,14 @@ static int vbi_workaround(struct saa7146_dev *dev)
WRITE_RPS1(0xc000008c);
/* wait for vbi_a or vbi_b*/
if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
- DEB_D(("...using port b\n"));
+ DEB_D("...using port b\n");
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
/*
WRITE_RPS1(CMD_PAUSE | MASK_09);
*/
} else {
- DEB_D(("...using port a\n"));
+ DEB_D("...using port a\n");
WRITE_RPS1(CMD_PAUSE | MASK_10);
}
/* upload brs */
@@ -103,7 +103,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
schedule();
- DEB_VBI(("brs bug workaround %d/1.\n",i));
+ DEB_VBI("brs bug workaround %d/1\n", i);
remove_wait_queue(&vv->vbi_wq, &wait);
current->state = TASK_RUNNING;
@@ -116,7 +116,8 @@ static int vbi_workaround(struct saa7146_dev *dev)
if(signal_pending(current)) {
- DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
+ DEB_VBI("aborted (rps:0x%08x)\n",
+ saa7146_read(dev, RPS_ADDR1));
/* stop rps1 for sure */
saa7146_write(dev, MC1, MASK_29);
@@ -207,7 +208,7 @@ static int buffer_activate(struct saa7146_dev *dev,
struct saa7146_vv *vv = dev->vv_data;
buf->vb.state = VIDEOBUF_ACTIVE;
- DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
+ DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
saa7146_set_vbi_capture(dev,buf,next);
mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
@@ -228,10 +229,10 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
llength = vbi_pixel_to_capture;
size = lines * llength;
- DEB_VBI(("vb:%p\n",vb));
+ DEB_VBI("vb:%p\n", vb);
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
- DEB_VBI(("size mismatch.\n"));
+ DEB_VBI("size mismatch\n");
return -EINVAL;
}
@@ -263,7 +264,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
return 0;
oops:
- DEB_VBI(("error out.\n"));
+ DEB_VBI("error out\n");
saa7146_dma_free(dev,q,buf);
return err;
@@ -279,7 +280,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
*size = lines * llength;
*count = 2;
- DEB_VBI(("count:%d, size:%d\n",*count,*size));
+ DEB_VBI("count:%d, size:%d\n", *count, *size);
return 0;
}
@@ -292,7 +293,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_VBI(("vb:%p\n",vb));
+ DEB_VBI("vb:%p\n", vb);
saa7146_buffer_queue(dev,&vv->vbi_q,buf);
}
@@ -303,7 +304,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_dev *dev = fh->dev;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_VBI(("vb:%p\n",vb));
+ DEB_VBI("vb:%p\n", vb);
saa7146_dma_free(dev,q,buf);
}
@@ -321,7 +322,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
unsigned long flags;
- DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
spin_lock_irqsave(&dev->slock,flags);
@@ -354,14 +355,14 @@ static void vbi_read_timeout(unsigned long data)
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
- DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
vbi_stop(fh, file);
}
static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
{
- DEB_VBI(("dev:%p\n",dev));
+ DEB_VBI("dev:%p\n", dev);
INIT_LIST_HEAD(&vv->vbi_q.queue);
@@ -380,11 +381,11 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
int ret = 0;
- DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
if (0 == ret) {
- DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
+ DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
return -EBUSY;
}
@@ -425,7 +426,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
saa7146_write(dev, BRS_CTRL, 0x00000001);
if (0 != (ret = vbi_workaround(dev))) {
- DEB_VBI(("vbi workaround failed!\n"));
+ DEB_VBI("vbi workaround failed!\n");
/* return ret;*/
}
}
@@ -439,7 +440,7 @@ static void vbi_close(struct saa7146_dev *dev, struct file *file)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_vv *vv = dev->vv_data;
- DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
if( fh == vv->vbi_streaming ) {
vbi_stop(fh, file);
@@ -453,13 +454,13 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
spin_lock(&dev->slock);
if (vv->vbi_q.curr) {
- DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
+ DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_q.curr);
/* this must be += 2, one count for each field */
vv->vbi_fieldcount+=2;
vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
} else {
- DEB_VBI(("dev:%p\n",dev));
+ DEB_VBI("dev:%p\n", dev);
}
saa7146_buffer_next(dev,&vv->vbi_q,1);
@@ -473,7 +474,7 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
struct saa7146_vv *vv = dev->vv_data;
ssize_t ret = 0;
- DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
if( NULL == vv->vbi_streaming ) {
// fixme: check if dma3 is available
@@ -482,7 +483,8 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
}
if( fh != vv->vbi_streaming ) {
- DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
+ DEB_VBI("open %p is already using vbi capture\n",
+ vv->vbi_streaming);
return -EBUSY;
}
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 9aafa4e..ce30533 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -1,5 +1,8 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146_vv.h>
#include <media/v4l2-chip-ident.h>
+#include <linux/module.h>
static int max_memory = 32;
@@ -94,7 +97,7 @@ struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fou
}
}
- DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
+ DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
return NULL;
}
@@ -107,32 +110,32 @@ int saa7146_start_preview(struct saa7146_fh *fh)
struct v4l2_format fmt;
int ret = 0, err = 0;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
/* check if we have overlay informations */
if( NULL == fh->ov.fh ) {
- DEB_D(("no overlay data available. try S_FMT first.\n"));
+ DEB_D("no overlay data available. try S_FMT first.\n");
return -EAGAIN;
}
/* check if streaming capture is running */
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("streaming capture is active.\n"));
+ DEB_D("streaming capture is active\n");
return -EBUSY;
}
/* check if overlay is running */
if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh == fh) {
- DEB_D(("overlay is already active.\n"));
+ DEB_D("overlay is already active\n");
return 0;
}
- DEB_D(("overlay is already active in another open.\n"));
+ DEB_D("overlay is already active in another open\n");
return -EBUSY;
}
if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
- DEB_D(("cannot get necessary overlay resources\n"));
+ DEB_D("cannot get necessary overlay resources\n");
return -EBUSY;
}
@@ -145,13 +148,13 @@ int saa7146_start_preview(struct saa7146_fh *fh)
fh->ov.win = fmt.fmt.win;
vv->ov_data = &fh->ov;
- DEB_D(("%dx%d+%d+%d %s field=%s\n",
- fh->ov.win.w.width,fh->ov.win.w.height,
- fh->ov.win.w.left,fh->ov.win.w.top,
- vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
+ DEB_D("%dx%d+%d+%d %s field=%s\n",
+ fh->ov.win.w.width, fh->ov.win.w.height,
+ fh->ov.win.w.left, fh->ov.win.w.top,
+ vv->ov_fmt->name, v4l2_field_names[fh->ov.win.field]);
if (0 != (ret = saa7146_enable_overlay(fh))) {
- DEB_D(("enabling overlay failed: %d\n",ret));
+ DEB_D("enabling overlay failed: %d\n", ret);
saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
return ret;
}
@@ -168,22 +171,22 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
/* check if streaming capture is running */
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("streaming capture is active.\n"));
+ DEB_D("streaming capture is active\n");
return -EBUSY;
}
/* check if overlay is running at all */
if ((vv->video_status & STATUS_OVERLAY) == 0) {
- DEB_D(("no active overlay.\n"));
+ DEB_D("no active overlay\n");
return 0;
}
if (vv->video_fh != fh) {
- DEB_D(("overlay is active, but in another open.\n"));
+ DEB_D("overlay is active, but in another open\n");
return -EBUSY;
}
@@ -268,7 +271,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
int length = dma->sglen;
struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
- DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
+ DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
if( 0 != IS_PLANAR(sfmt->trans)) {
struct saa7146_pgtable *pt1 = &buf->pt[0];
@@ -288,7 +291,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
o1 = size%PAGE_SIZE;
o2 = (size+(size/4))%PAGE_SIZE;
- DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+ DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+ size, m1, m2, m3, o1, o2);
break;
}
case 16: {
@@ -298,7 +302,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
o1 = size%PAGE_SIZE;
o2 = (size+(size/2))%PAGE_SIZE;
- DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+ DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+ size, m1, m2, m3, o1, o2);
break;
}
default: {
@@ -387,23 +392,23 @@ static int video_begin(struct saa7146_fh *fh)
unsigned int resource;
int ret = 0, err = 0;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
if ((vv->video_status & STATUS_CAPTURE) != 0) {
if (vv->video_fh == fh) {
- DEB_S(("already capturing.\n"));
+ DEB_S("already capturing\n");
return 0;
}
- DEB_S(("already capturing in another open.\n"));
+ DEB_S("already capturing in another open\n");
return -EBUSY;
}
if ((vv->video_status & STATUS_OVERLAY) != 0) {
- DEB_S(("warning: suspending overlay video for streaming capture.\n"));
+ DEB_S("warning: suspending overlay video for streaming capture\n");
vv->ov_suspend = vv->video_fh;
err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
if (0 != err) {
- DEB_D(("suspending video failed. aborting\n"));
+ DEB_D("suspending video failed. aborting\n");
return err;
}
}
@@ -420,7 +425,7 @@ static int video_begin(struct saa7146_fh *fh)
ret = saa7146_res_get(fh, resource);
if (0 == ret) {
- DEB_S(("cannot get capture resource %d\n",resource));
+ DEB_S("cannot get capture resource %d\n", resource);
if (vv->ov_suspend != NULL) {
saa7146_start_preview(vv->ov_suspend);
vv->ov_suspend = NULL;
@@ -448,15 +453,15 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
unsigned long flags;
unsigned int resource;
u32 dmas = 0;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
- DEB_S(("not capturing.\n"));
+ DEB_S("not capturing\n");
return 0;
}
if (vv->video_fh != fh) {
- DEB_S(("capturing, but in another open.\n"));
+ DEB_S("capturing, but in another open\n");
return -EBUSY;
}
@@ -530,7 +535,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_format *fmt;
- DEB_EE(("VIDIOC_S_FBUF\n"));
+ DEB_EE("VIDIOC_S_FBUF\n");
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
return -EPERM;
@@ -542,13 +547,13 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
/* planar formats are not allowed for overlay video, clipping and video dma would clash */
if (fmt->flags & FORMAT_IS_PLANAR)
- DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
- (char *)&fmt->pixelformat));
+ DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
+ (char *)&fmt->pixelformat);
/* check if overlay is running */
if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh != fh) {
- DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+ DEB_D("refusing to change framebuffer informations while overlay is active in another open\n");
return -EBUSY;
}
}
@@ -559,7 +564,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
- DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline));
+ DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
}
return 0;
}
@@ -588,7 +593,7 @@ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *
if (ctrl == NULL)
return -EINVAL;
- DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
+ DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id);
*c = *ctrl;
return 0;
}
@@ -607,25 +612,25 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
case V4L2_CID_BRIGHTNESS:
value = saa7146_read(dev, BCS_CTRL);
c->value = 0xff & (value >> 24);
- DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
+ DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value);
break;
case V4L2_CID_CONTRAST:
value = saa7146_read(dev, BCS_CTRL);
c->value = 0x7f & (value >> 16);
- DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
+ DEB_D("V4L2_CID_CONTRAST: %d\n", c->value);
break;
case V4L2_CID_SATURATION:
value = saa7146_read(dev, BCS_CTRL);
c->value = 0x7f & (value >> 0);
- DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
+ DEB_D("V4L2_CID_SATURATION: %d\n", c->value);
break;
case V4L2_CID_VFLIP:
c->value = vv->vflip;
- DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
+ DEB_D("V4L2_CID_VFLIP: %d\n", c->value);
break;
case V4L2_CID_HFLIP:
c->value = vv->hflip;
- DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
+ DEB_D("V4L2_CID_HFLIP: %d\n", c->value);
break;
default:
return -EINVAL;
@@ -641,7 +646,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
ctrl = ctrl_by_id(c->id);
if (NULL == ctrl) {
- DEB_D(("unknown control %d\n", c->id));
+ DEB_D("unknown control %d\n", c->id);
return -EINVAL;
}
@@ -686,14 +691,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
case V4L2_CID_HFLIP:
/* fixme: we can support changing VFLIP and HFLIP here... */
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+ DEB_D("V4L2_CID_HFLIP while active capture\n");
return -EBUSY;
}
vv->hflip = c->value;
break;
case V4L2_CID_VFLIP:
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+ DEB_D("V4L2_CID_VFLIP while active capture\n");
return -EBUSY;
}
vv->vflip = c->value;
@@ -748,7 +753,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
int maxw, maxh;
int calc_bpl;
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
if (NULL == fmt)
@@ -777,7 +782,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
vv->last_field = V4L2_FIELD_INTERLACED;
break;
default:
- DEB_D(("no known field mode '%d'.\n", field));
+ DEB_D("no known field mode '%d'\n", field);
return -EINVAL;
}
@@ -796,8 +801,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
f->fmt.pix.bytesperline = calc_bpl;
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
- DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
- f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
+ DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
+ f->fmt.pix.width, f->fmt.pix.height,
+ f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
return 0;
}
@@ -811,22 +817,23 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_f
enum v4l2_field field;
int maxw, maxh;
- DEB_EE(("dev:%p\n", dev));
+ DEB_EE("dev:%p\n", dev);
if (NULL == vv->ov_fb.base) {
- DEB_D(("no fb base set.\n"));
+ DEB_D("no fb base set\n");
return -EINVAL;
}
if (NULL == vv->ov_fmt) {
- DEB_D(("no fb fmt set.\n"));
+ DEB_D("no fb fmt set\n");
return -EINVAL;
}
if (win->w.width < 48 || win->w.height < 32) {
- DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
+ DEB_D("min width/height. (%d,%d)\n",
+ win->w.width, win->w.height);
return -EINVAL;
}
if (win->clipcount > 16) {
- DEB_D(("clipcount too big.\n"));
+ DEB_D("clipcount too big\n");
return -EINVAL;
}
@@ -848,7 +855,7 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_f
case V4L2_FIELD_INTERLACED:
break;
default:
- DEB_D(("no known field mode '%d'.\n", field));
+ DEB_D("no known field mode '%d'\n", field);
return -EINVAL;
}
@@ -868,16 +875,17 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_forma
struct saa7146_vv *vv = dev->vv_data;
int err;
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_EE(("streaming capture is active\n"));
+ DEB_EE("streaming capture is active\n");
return -EBUSY;
}
err = vidioc_try_fmt_vid_cap(file, fh, f);
if (0 != err)
return err;
fh->video_fmt = f->fmt.pix;
- DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
+ DEB_EE("set to pixelformat '%4.4s'\n",
+ (char *)&fh->video_fmt.pixelformat);
return 0;
}
@@ -888,7 +896,7 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f
struct saa7146_vv *vv = dev->vv_data;
int err;
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
err = vidioc_try_fmt_vid_overlay(file, fh, f);
if (0 != err)
return err;
@@ -931,7 +939,7 @@ static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
if (e->index < 0 )
return -EINVAL;
if( e->index < dev->ext_vv_data->num_stds ) {
- DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
+ DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
return 0;
}
@@ -946,10 +954,10 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
int found = 0;
int err, i;
- DEB_EE(("VIDIOC_S_STD\n"));
+ DEB_EE("VIDIOC_S_STD\n");
if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
- DEB_D(("cannot change video standard while streaming capture is active\n"));
+ DEB_D("cannot change video standard while streaming capture is active\n");
return -EBUSY;
}
@@ -957,7 +965,7 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
vv->ov_suspend = vv->video_fh;
err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
if (0 != err) {
- DEB_D(("suspending video failed. aborting\n"));
+ DEB_D("suspending video failed. aborting\n");
return err;
}
}
@@ -978,11 +986,11 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
}
if (!found) {
- DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
+ DEB_EE("VIDIOC_S_STD: standard not found\n");
return -EINVAL;
}
- DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
+ DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
return 0;
}
@@ -990,7 +998,7 @@ static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
{
int err;
- DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
+ DEB_D("VIDIOC_OVERLAY on:%d\n", on);
if (on)
err = saa7146_start_preview(fh);
else
@@ -1047,7 +1055,7 @@ static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type typ
struct saa7146_fh *fh = __fh;
int err;
- DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
+ DEB_D("VIDIOC_STREAMON, type:%d\n", type);
err = video_begin(fh);
if (err)
@@ -1066,18 +1074,18 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty
struct saa7146_vv *vv = dev->vv_data;
int err;
- DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
+ DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
/* ugly: we need to copy some checks from video_end(),
because videobuf_streamoff() relies on the capture running.
check and fix this */
if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
- DEB_S(("not capturing.\n"));
+ DEB_S("not capturing\n");
return 0;
}
if (vv->video_fh != fh) {
- DEB_S(("capturing, but in another open.\n"));
+ DEB_S("capturing, but in another open\n");
return -EBUSY;
}
@@ -1087,7 +1095,7 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty
else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
err = videobuf_streamoff(&fh->vbi_q);
if (0 != err) {
- DEB_D(("warning: videobuf_streamoff() failed.\n"));
+ DEB_D("warning: videobuf_streamoff() failed\n");
video_end(fh, file);
} else {
err = video_end(fh, file);
@@ -1174,25 +1182,27 @@ static int buffer_prepare(struct videobuf_queue *q,
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
int size,err = 0;
- DEB_CAP(("vbuf:%p\n",vb));
+ DEB_CAP("vbuf:%p\n", vb);
/* sanity checks */
if (fh->video_fmt.width < 48 ||
fh->video_fmt.height < 32 ||
fh->video_fmt.width > vv->standard->h_max_out ||
fh->video_fmt.height > vv->standard->v_max_out) {
- DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
+ DEB_D("w (%d) / h (%d) out of bounds\n",
+ fh->video_fmt.width, fh->video_fmt.height);
return -EINVAL;
}
size = fh->video_fmt.sizeimage;
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
- DEB_D(("size mismatch.\n"));
+ DEB_D("size mismatch\n");
return -EINVAL;
}
- DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
- fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
+ DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
+ fh->video_fmt.width, fh->video_fmt.height,
+ size, v4l2_field_names[fh->video_fmt.field]);
if (buf->vb.width != fh->video_fmt.width ||
buf->vb.bytesperline != fh->video_fmt.bytesperline ||
buf->vb.height != fh->video_fmt.height ||
@@ -1238,7 +1248,7 @@ static int buffer_prepare(struct videobuf_queue *q,
return 0;
oops:
- DEB_D(("error out.\n"));
+ DEB_D("error out\n");
saa7146_dma_free(dev,q,buf);
return err;
@@ -1259,7 +1269,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
*count = (max_memory*1048576) / *size;
}
- DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
+ DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
return 0;
}
@@ -1272,7 +1282,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_CAP(("vbuf:%p\n",vb));
+ DEB_CAP("vbuf:%p\n", vb);
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
}
@@ -1283,7 +1293,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_dev *dev = fh->dev;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_CAP(("vbuf:%p\n",vb));
+ DEB_CAP("vbuf:%p\n", vb);
saa7146_dma_free(dev,q,buf);
@@ -1347,18 +1357,14 @@ static void video_close(struct saa7146_dev *dev, struct file *file)
struct saa7146_fh *fh = file->private_data;
struct saa7146_vv *vv = dev->vv_data;
struct videobuf_queue *q = &fh->video_q;
- int err;
- if (IS_CAPTURE_ACTIVE(fh) != 0) {
- err = video_end(fh, file);
- } else if (IS_OVERLAY_ACTIVE(fh) != 0) {
- err = saa7146_stop_preview(fh);
- }
+ if (IS_CAPTURE_ACTIVE(fh) != 0)
+ video_end(fh, file);
+ else if (IS_OVERLAY_ACTIVE(fh) != 0)
+ saa7146_stop_preview(fh);
videobuf_stop(q);
-
/* hmm, why is this function declared void? */
- /* return err */
}
@@ -1368,7 +1374,7 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
struct saa7146_dmaqueue *q = &vv->video_q;
spin_lock(&dev->slock);
- DEB_CAP(("called.\n"));
+ DEB_CAP("called\n");
/* only finish the buffer if we have one... */
if( NULL != q->curr ) {
@@ -1386,15 +1392,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo
struct saa7146_vv *vv = dev->vv_data;
ssize_t ret = 0;
- DEB_EE(("called.\n"));
+ DEB_EE("called\n");
if ((vv->video_status & STATUS_CAPTURE) != 0) {
/* fixme: should we allow read() captures while streaming capture? */
if (vv->video_fh == fh) {
- DEB_S(("already capturing.\n"));
+ DEB_S("already capturing\n");
return -EBUSY;
}
- DEB_S(("already capturing in another open.\n"));
+ DEB_S("already capturing in another open\n");
return -EBUSY;
}
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index 22d3ca3..996302a 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -23,6 +23,7 @@ config MEDIA_TUNER
depends on VIDEO_MEDIA && I2C
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
@@ -152,6 +153,15 @@ config MEDIA_TUNER_XC5000
This device is only used inside a SiP called together with a
demodulator for now.
+config MEDIA_TUNER_XC4000
+ tristate "Xceive XC4000 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if MEDIA_TUNER_CUSTOMISE
+ help
+ A driver for the silicon tuner XC4000 from Xceive.
+ This device is only used inside a SiP called together with a
+ demodulator for now.
+
config MEDIA_TUNER_MXL5005S
tristate "MaxLinear MSL5005S silicon tuner"
depends on VIDEO_MEDIA && I2C
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
index 2cb4f53..196c12a 100644
--- a/drivers/media/common/tuners/Makefile
+++ b/drivers/media/common/tuners/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
@@ -27,5 +28,5 @@ obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c
index d0e70e1..0e74e97 100644
--- a/drivers/media/common/tuners/mt20xx.c
+++ b/drivers/media/common/tuners/mt20xx.c
@@ -430,11 +430,10 @@ static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
{
struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[2];
- int ret;
buf[0] = 6;
buf[1] = antenna ? 0x11 : 0x10;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
}
@@ -574,21 +573,20 @@ static int mt2050_init(struct dvb_frontend *fe)
{
struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[2];
- int ret;
- buf[0]=6;
- buf[1]=0x10;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
+ buf[0] = 6;
+ buf[1] = 0x10;
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
- buf[0]=0x0f;
- buf[1]=0x0f;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
+ buf[0] = 0x0f;
+ buf[1] = 0x0f;
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
- buf[0]=0x0d;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+ buf[0] = 0x0d;
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
- tuner_dbg("mt2050: sro is %x\n",buf[0]);
+ tuner_dbg("mt2050: sro is %x\n", buf[0]);
memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 56fe75c..54be9e6 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -309,7 +309,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
u8 *RegVal, int *count);
-static u32 MXL_GetXtalInt(u32 Xtal_Freq);
static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
@@ -2307,14 +2306,6 @@ static u16 MXL_IFSynthInit(struct dvb_frontend *fe)
return status ;
}
-static u32 MXL_GetXtalInt(u32 Xtal_Freq)
-{
- if ((Xtal_Freq % 1000000) == 0)
- return (Xtal_Freq / 10000);
- else
- return (((Xtal_Freq / 1000000) + 1)*100);
-}
-
static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
{
struct mxl5005s_state *state = fe->tuner_priv;
@@ -2324,13 +2315,10 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
u32 Kdbl_RF = 2;
u32 tg_divval;
u32 tg_lo;
- u32 Xtal_Int;
u32 Fref_TG;
u32 Fvco;
- Xtal_Int = MXL_GetXtalInt(state->Fxtal);
-
state->RF_IN = RF_Freq;
MXL_SynthRFTGLO_Calc(fe);
@@ -2779,6 +2767,16 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
/* below equation is same as above but much harder to debug.
+ *
+ * static u32 MXL_GetXtalInt(u32 Xtal_Freq)
+ * {
+ * if ((Xtal_Freq % 1000000) == 0)
+ * return (Xtal_Freq / 10000);
+ * else
+ * return (((Xtal_Freq / 1000000) + 1)*100);
+ * }
+ *
+ * u32 Xtal_Int = MXL_GetXtalInt(state->Fxtal);
* tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
* ((state->TG_LO/10000)*divider_val *
* (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
index 7eb1bf7..5d02221 100644
--- a/drivers/media/common/tuners/mxl5007t.c
+++ b/drivers/media/common/tuners/mxl5007t.c
@@ -488,9 +488,10 @@ static int mxl5007t_write_regs(struct mxl5007t_state *state,
static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
{
+ u8 buf[2] = { 0xfb, reg };
struct i2c_msg msg[] = {
{ .addr = state->i2c_props.addr, .flags = 0,
- .buf = &reg, .len = 1 },
+ .buf = buf, .len = 2 },
{ .addr = state->i2c_props.addr, .flags = I2C_M_RD,
.buf = val, .len = 1 },
};
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c
index 1f1db20..e29cc2b 100644
--- a/drivers/media/common/tuners/tda18212.c
+++ b/drivers/media/common/tuners/tda18212.c
@@ -18,7 +18,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "tda18212_priv.h"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "tda18212.h"
+
+struct tda18212_priv {
+ struct tda18212_config *cfg;
+ struct i2c_adapter *i2c;
+};
+
+#define dbg(fmt, arg...) \
+do { \
+ if (debug) \
+ pr_info("%s: " fmt, __func__, ##arg); \
+} while (0)
static int debug;
module_param(debug, int, 0644);
@@ -46,7 +59,8 @@ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
if (ret == 1) {
ret = 0;
} else {
- warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+ pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
+ ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
@@ -77,7 +91,8 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
memcpy(val, buf, len);
ret = 0;
} else {
- warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+ pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
+ ret, reg, len);
ret = -EREMOTEIO;
}
@@ -129,8 +144,8 @@ static int tda18212_set_params(struct dvb_frontend *fe,
{ 0x92, 0x53, 0x03 }, /* DVB-C */
};
- dbg("%s: delsys=%d RF=%d BW=%d", __func__,
- c->delivery_system, c->frequency, c->bandwidth_hz);
+ dbg("delsys=%d RF=%d BW=%d\n",
+ c->delivery_system, c->frequency, c->bandwidth_hz);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
@@ -196,7 +211,7 @@ exit:
return ret;
error:
- dbg("%s: failed:%d", __func__, ret);
+ dbg("failed:%d\n", ret);
goto exit;
}
@@ -245,13 +260,13 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
- dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+ dbg("ret:%d chip ID:%02x\n", ret, val);
if (ret || val != 0xc7) {
kfree(priv);
return NULL;
}
- info("NXP TDA18212HN successfully identified.");
+ pr_info("NXP TDA18212HN successfully identified\n");
memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
sizeof(struct dvb_tuner_ops));
diff --git a/drivers/media/common/tuners/tda18212_priv.h b/drivers/media/common/tuners/tda18212_priv.h
deleted file mode 100644
index 9adff93..0000000
--- a/drivers/media/common/tuners/tda18212_priv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * NXP TDA18212HN silicon tuner driver
- *
- * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TDA18212_PRIV_H
-#define TDA18212_PRIV_H
-
-#include "tda18212.h"
-
-#define LOG_PREFIX "tda18212"
-
-#undef dbg
-#define dbg(f, arg...) \
- if (debug) \
- printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct tda18212_priv {
- struct tda18212_config *cfg;
- struct i2c_adapter *i2c;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c
index aacfe23..4fc2973 100644
--- a/drivers/media/common/tuners/tda18218.c
+++ b/drivers/media/common/tuners/tda18218.c
@@ -141,7 +141,7 @@ static int tda18218_set_params(struct dvb_frontend *fe,
switch (params->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
LP_Fc = 0;
- LO_Frac = params->frequency + 4000000;
+ LO_Frac = params->frequency + 3000000;
break;
case BANDWIDTH_7_MHZ:
LP_Fc = 1;
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
index aae40e5..39c6457 100644
--- a/drivers/media/common/tuners/tda18271-common.c
+++ b/drivers/media/common/tuners/tda18271-common.c
@@ -676,10 +676,28 @@ fail:
return ret;
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+int _tda_printk(struct tda18271_priv *state, const char *level,
+ const char *func, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int rtn;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ if (state)
+ rtn = printk("%s%s: [%d-%04x|%c] %pV",
+ level, func, i2c_adapter_id(state->i2c_props.adap),
+ state->i2c_props.addr,
+ (state->role == TDA18271_MASTER) ? 'M' : 'S',
+ &vaf);
+ else
+ rtn = printk("%s%s: %pV", level, func, &vaf);
+
+ va_end(args);
+
+ return rtn;
+}
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index 57022e8..63cc400 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -1230,7 +1230,7 @@ static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg)
return 0;
}
-static struct dvb_tuner_ops tda18271_tuner_ops = {
+static const struct dvb_tuner_ops tda18271_tuner_ops = {
.info = {
.name = "NXP TDA18271HD",
.frequency_min = 45000000,
diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h
index 9589ab0..94340f4 100644
--- a/drivers/media/common/tuners/tda18271-priv.h
+++ b/drivers/media/common/tuners/tda18271-priv.h
@@ -136,29 +136,26 @@ extern int tda18271_debug;
#define DBG_ADV 8
#define DBG_CAL 16
-#define tda_printk(st, kern, fmt, arg...) do {\
- if (st) { \
- struct tda18271_priv *state = st; \
- printk(kern "%s: [%d-%04x|%s] " fmt, __func__, \
- i2c_adapter_id(state->i2c_props.adap), \
- state->i2c_props.addr, \
- (state->role == TDA18271_MASTER) \
- ? "M" : "S", ##arg); \
- } else \
- printk(kern "%s: " fmt, __func__, ##arg); \
+__attribute__((format(printf, 4, 5)))
+int _tda_printk(struct tda18271_priv *state, const char *level,
+ const char *func, const char *fmt, ...);
+
+#define tda_printk(st, lvl, fmt, arg...) \
+ _tda_printk(st, lvl, __func__, fmt, ##arg)
+
+#define tda_dprintk(st, lvl, fmt, arg...) \
+do { \
+ if (tda18271_debug & lvl) \
+ tda_printk(st, KERN_DEBUG, fmt, ##arg); \
} while (0)
-#define tda_dprintk(st, lvl, fmt, arg...) do {\
- if (tda18271_debug & lvl) \
- tda_printk(st, KERN_DEBUG, fmt, ##arg); } while (0)
-
-#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
-#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
-#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg)
-#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg)
-#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg)
-#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg)
-#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg)
+#define tda_info(fmt, arg...) pr_info(fmt, ##arg)
+#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
+#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg)
+#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg)
+#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg)
+#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg)
+#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg)
#define tda_fail(ret) \
({ \
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index b21b6ea..e0d5b43 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -176,7 +176,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
if_freq = 5000000;
break;
}
- tuner_freq = params->frequency + if_freq;
+ tuner_freq = params->frequency;
i = 0;
while (tda827x_table[i].lomax < tuner_freq) {
@@ -185,6 +185,8 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
i++;
}
+ tuner_freq += if_freq;
+
N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
buf[0] = 0;
buf[1] = (N>>8) | 0x40;
@@ -540,7 +542,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
if_freq = 5000000;
break;
}
- tuner_freq = params->frequency + if_freq;
+ tuner_freq = params->frequency;
if (fe->ops.info.type == FE_QAM) {
dprintk("%s select tda827xa_dvbc\n", __func__);
@@ -554,6 +556,8 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
i++;
}
+ tuner_freq += if_freq;
+
N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
buf[0] = 0; // subaddress
buf[1] = N >> 8;
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c
index afba6dc..e13683b 100644
--- a/drivers/media/common/tuners/tuner-types.c
+++ b/drivers/media/common/tuners/tuner-types.c
@@ -5,6 +5,7 @@
*/
#include <linux/i2c.h>
+#include <linux/module.h>
#include <media/tuner.h>
#include <media/tuner-types.h>
@@ -1805,6 +1806,10 @@ struct tunertype tuners[] = {
.name = "Xceive 5000 tuner",
/* see xc5000.c for details */
},
+ [TUNER_XC4000] = { /* Xceive 4000 */
+ .name = "Xceive 4000 tuner",
+ /* see xc4000.c for details */
+ },
[TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
.name = "TCL tuner MF02GIP-5N-E",
.params = tuner_tcl_mf02gip_5n_params,
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 16fba6b..3acbaa0 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -614,6 +614,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
p += len;
size -= len;
}
+
+ /* silently fail if the frontend doesn't support I2C flush */
+ rc = do_tuner_callback(fe, XC2028_I2C_FLUSH, 0);
+ if ((rc < 0) && (rc != -EINVAL)) {
+ tuner_err("error executing flush: %d\n", rc);
+ return rc;
+ }
}
return 0;
}
@@ -933,11 +940,16 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
* that xc2028 will be in a safe state.
* Maybe this might also be needed for DTV.
*/
- if (new_type == V4L2_TUNER_ANALOG_TV) {
+ switch (new_type) {
+ case V4L2_TUNER_ANALOG_TV:
rc = send_seq(priv, {0x00, 0x00});
- /* Analog modes require offset = 0 */
- } else {
+ /* Analog mode requires offset = 0 */
+ break;
+ case V4L2_TUNER_RADIO:
+ /* Radio mode requires offset = 0 */
+ break;
+ case V4L2_TUNER_DIGITAL_TV:
/*
* Digital modes require an offset to adjust to the
* proper frequency. The offset depends on what
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h
index 9778c96..9ebfb2d 100644
--- a/drivers/media/common/tuners/tuner-xc2028.h
+++ b/drivers/media/common/tuners/tuner-xc2028.h
@@ -54,6 +54,7 @@ struct xc2028_config {
/* xc2028 commands for callback */
#define XC2028_TUNER_RESET 0
#define XC2028_RESET_CLK 1
+#define XC2028_I2C_FLUSH 2
#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index ee214c3..f6e40b3 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -80,6 +80,10 @@ comment "Supported nGene Adapters"
depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/ngene/Kconfig"
+comment "Supported ddbridge ('Octopus') Adapters"
+ depends on DVB_CORE && PCI && I2C
+ source "drivers/media/dvb/ddbridge/Kconfig"
+
comment "Supported DVB Frontends"
depends on DVB_CORE
source "drivers/media/dvb/frontends/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index a1a0875..b2cefe6 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -15,6 +15,7 @@ obj-y := dvb-core/ \
dm1105/ \
pt1/ \
mantis/ \
- ngene/
+ ngene/ \
+ ddbridge/
obj-$(CONFIG_DVB_FIREDTV) += firewire/
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index b97cf72..3d04a8d 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -12,5 +12,5 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
b2c2-flexcop-usb-objs = flexcop-usb.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 9e2148a..437912e 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -6,6 +6,7 @@
#ifndef __FLEXCOP_COMMON_H__
#define __FLEXCOP_COMMON_H__
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/mutex.h>
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
index d98f1d4..0713b3a 100644
--- a/drivers/media/dvb/bt8xx/Makefile
+++ b/drivers/media/dvb/bt8xx/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video/bt8xx
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 1e1106d..521d691 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -892,7 +892,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);
kfree(card);
- return -EFAULT;
+ return -ENODEV;
}
if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
@@ -902,7 +902,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
"installed, try removing it.\n");
kfree(card);
- return -EFAULT;
+ return -ENODEV;
}
mutex_init(&card->bt->gpio_lock);
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
index 8ac28b0..95a008b 100644
--- a/drivers/media/dvb/dm1105/Makefile
+++ b/drivers/media/dvb/dm1105/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_DM1105) += dm1105.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index b2b0c45..55e6533 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -22,6 +22,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index 0b51828..8f22bcd 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -2,8 +2,10 @@
# Makefile for the kernel DVB device drivers.
#
+dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
+
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
dvb_ca_en50221.o dvb_frontend.o \
- dvb_net.o dvb_ringbuffer.o dvb_math.o
+ $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index e4b5c03..4f8c3f7 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -380,10 +380,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
buffer2_len);
}
- if (ret < 0) {
- dvb_ringbuffer_flush(&dmxdevfilter->buffer);
+ if (ret < 0)
dmxdevfilter->buffer.error = ret;
- }
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE;
spin_unlock(&dmxdevfilter->dev->lock);
@@ -419,10 +417,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
if (ret == buffer1_len)
ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
- if (ret < 0) {
- dvb_ringbuffer_flush(buffer);
+ if (ret < 0)
buffer->error = ret;
- }
spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 5b6b451..2c0acdb 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -149,30 +149,25 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
dprintk ("%s\n", __func__);
- if (mutex_lock_interruptible (&events->mtx))
- return;
+ if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
+ fe->ops.get_frontend(fe, &fepriv->parameters_out);
- wp = (events->eventw + 1) % MAX_EVENT;
+ mutex_lock(&events->mtx);
+ wp = (events->eventw + 1) % MAX_EVENT;
if (wp == events->eventr) {
events->overflow = 1;
events->eventr = (events->eventr + 1) % MAX_EVENT;
}
e = &events->events[events->eventw];
-
- if (status & FE_HAS_LOCK)
- if (fe->ops.get_frontend)
- fe->ops.get_frontend(fe, &fepriv->parameters_out);
-
+ e->status = status;
e->parameters = fepriv->parameters_out;
events->eventw = wp;
mutex_unlock(&events->mtx);
- e->status = status;
-
wake_up_interruptible (&events->wait_queue);
}
@@ -207,19 +202,24 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
return ret;
}
- if (mutex_lock_interruptible (&events->mtx))
- return -ERESTARTSYS;
-
- memcpy (event, &events->events[events->eventr],
- sizeof(struct dvb_frontend_event));
-
+ mutex_lock(&events->mtx);
+ *event = events->events[events->eventr];
events->eventr = (events->eventr + 1) % MAX_EVENT;
-
mutex_unlock(&events->mtx);
return 0;
}
+static void dvb_frontend_clear_events(struct dvb_frontend *fe)
+{
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dvb_fe_events *events = &fepriv->events;
+
+ mutex_lock(&events->mtx);
+ events->eventr = events->eventw;
+ mutex_unlock(&events->mtx);
+}
+
static void dvb_frontend_init(struct dvb_frontend *fe)
{
dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
@@ -537,7 +537,6 @@ static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- unsigned long timeout;
fe_status_t s;
enum dvbfe_algo algo;
@@ -558,7 +557,7 @@ static int dvb_frontend_thread(void *data)
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
restart:
- timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
+ wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe) || kthread_should_stop()
|| freezing(current),
fepriv->delay);
@@ -577,12 +576,10 @@ restart:
if (fepriv->reinitialise) {
dvb_frontend_init(fe);
- if (fepriv->tone != -1) {
+ if (fe->ops.set_tone && fepriv->tone != -1)
fe->ops.set_tone(fe, fepriv->tone);
- }
- if (fepriv->voltage != -1) {
+ if (fe->ops.set_voltage && fepriv->voltage != -1)
fe->ops.set_voltage(fe, fepriv->voltage);
- }
fepriv->reinitialise = 0;
}
@@ -904,7 +901,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
.buffer = b \
}
-static struct dtv_cmds_h dtv_cmds[] = {
+static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_TUNE, 1, 0),
_DTV_CMD(DTV_CLEAR, 1, 0),
@@ -966,6 +963,7 @@ static struct dtv_cmds_h dtv_cmds[] = {
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0),
_DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
+ _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
/* Get */
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
@@ -1018,6 +1016,29 @@ static int is_legacy_delivery_system(fe_delivery_system_t s)
return 0;
}
+/* Initialize the cache with some default values derived from the
+ * legacy frontend_info structure.
+ */
+static void dtv_property_cache_init(struct dvb_frontend *fe,
+ struct dtv_frontend_properties *c)
+{
+ switch (fe->ops.info.type) {
+ case FE_QPSK:
+ c->modulation = QPSK; /* implied for DVB-S in legacy API */
+ c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+ c->delivery_system = SYS_DVBS;
+ break;
+ case FE_QAM:
+ c->delivery_system = SYS_DVBC_ANNEX_AC;
+ break;
+ case FE_OFDM:
+ c->delivery_system = SYS_DVBT;
+ break;
+ case FE_ATSC:
+ break;
+ }
+}
+
/* Synchronise the legacy tuning parameters into the cache, so that demodulator
* drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity.
@@ -1031,17 +1052,13 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
switch (fe->ops.info.type) {
case FE_QPSK:
- c->modulation = QPSK; /* implied for DVB-S in legacy API */
- c->rolloff = ROLLOFF_35;/* implied for DVB-S */
c->symbol_rate = p->u.qpsk.symbol_rate;
c->fec_inner = p->u.qpsk.fec_inner;
- c->delivery_system = SYS_DVBS;
break;
case FE_QAM:
c->symbol_rate = p->u.qam.symbol_rate;
c->fec_inner = p->u.qam.fec_inner;
c->modulation = p->u.qam.modulation;
- c->delivery_system = SYS_DVBC_ANNEX_AC;
break;
case FE_OFDM:
if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
@@ -1059,7 +1076,6 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
c->transmission_mode = p->u.ofdm.transmission_mode;
c->guard_interval = p->u.ofdm.guard_interval;
c->hierarchy = p->u.ofdm.hierarchy_information;
- c->delivery_system = SYS_DVBT;
break;
case FE_ATSC:
c->modulation = p->u.vsb.modulation;
@@ -1131,16 +1147,13 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
p->frequency = c->frequency;
p->inversion = c->inversion;
- switch(c->modulation) {
- case PSK_8:
- case APSK_16:
- case APSK_32:
- case QPSK:
+ if (c->delivery_system == SYS_DSS ||
+ c->delivery_system == SYS_DVBS ||
+ c->delivery_system == SYS_DVBS2 ||
+ c->delivery_system == SYS_ISDBS ||
+ c->delivery_system == SYS_TURBO) {
p->u.qpsk.symbol_rate = c->symbol_rate;
p->u.qpsk.fec_inner = c->fec_inner;
- break;
- default:
- break;
}
/* Fake out a generic DVB-T request so we pass validation in the ioctl */
@@ -1823,9 +1836,17 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
memcpy (&fepriv->parameters_in, parg,
sizeof (struct dvb_frontend_parameters));
+ dtv_property_cache_init(fe, c);
dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
}
+ /*
+ * Initialize output parameters to match the values given by
+ * the user. FE_SET_FRONTEND triggers an initial frontend event
+ * with status = 0, which copies output parameters to userspace.
+ */
+ fepriv->parameters_out = fepriv->parameters_in;
+
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
memcpy(&fetunesettings.parameters, parg,
sizeof (struct dvb_frontend_parameters));
@@ -1883,8 +1904,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
/* Request the search algorithm to search */
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
- dvb_frontend_wakeup(fe);
+ dvb_frontend_clear_events(fe);
dvb_frontend_add_event(fe, 0);
+ dvb_frontend_wakeup(fe);
fepriv->status = 0;
err = 0;
break;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 5590eb6..67bbfa7 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -209,6 +209,7 @@ struct dvb_tuner_ops {
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+ int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
#define TUNER_STATUS_LOCKED 1
#define TUNER_STATUS_STEREO 2
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 51752a9..93d9869 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1230,7 +1230,7 @@ static const struct net_device_ops dvb_netdev_ops = {
.ndo_open = dvb_net_open,
.ndo_stop = dvb_net_stop,
.ndo_start_xmit = dvb_net_tx,
- .ndo_set_multicast_list = dvb_net_set_multicast_list,
+ .ndo_set_rx_mode = dvb_net_set_multicast_list,
.ndo_set_mac_address = dvb_net_set_mac,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h
index 3a3126ca..1e53acd 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.h
+++ b/drivers/media/dvb/dvb-core/dvb_net.h
@@ -32,6 +32,8 @@
#define DVB_NET_DEVICES_MAX 10
+#ifdef CONFIG_DVB_NET
+
struct dvb_net {
struct dvb_device *dvbdev;
struct net_device *device[DVB_NET_DEVICES_MAX];
@@ -40,8 +42,25 @@ struct dvb_net {
struct dmx_demux *demux;
};
-
void dvb_net_release(struct dvb_net *);
int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
+#else
+
+struct dvb_net {
+ struct dvb_device *dvbdev;
+};
+
+static inline void dvb_net_release(struct dvb_net *dvbnet)
+{
+}
+
+static inline int dvb_net_init(struct dvb_adapter *adap,
+ struct dvb_net *dvbnet, struct dmx_demux *dmx)
+{
+ return 0;
+}
+
+#endif /* ifdef CONFIG_DVB_NET */
+
#endif
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e85304c..5825716 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -81,6 +81,7 @@ config DVB_USB_DIB0700
select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -257,6 +258,19 @@ config DVB_USB_AF9005_REMOTE
Say Y here to support the default remote control decoding for the
Afatech AF9005 based receiver.
+config DVB_USB_PCTV452E
+ tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
+ depends on DVB_USB
+ select TTPCI_EEPROM
+ select DVB_LNBP22 if !DVB_FE_CUSTOMISE
+ select DVB_STB0899 if !DVB_FE_CUSTOMISE
+ select DVB_STB6100 if !DVB_FE_CUSTOMISE
+ help
+ Support for external USB adapter designed by Pinnacle,
+ shipped under the brand name 'PCTV HDTV Pro USB'.
+ Also supports TT Connect S2-3600/3650 cards.
+ Say Y if you own such a device and want to use it.
+
config DVB_USB_DW2102
tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
depends on DVB_USB
@@ -373,3 +387,18 @@ config DVB_USB_TECHNISAT_USB2
select DVB_STV6110x if !DVB_FE_CUSTOMISE
help
Say Y here to support the Technisat USB2 DVB-S/S2 device
+
+config DVB_USB_IT913X
+ tristate "it913x driver"
+ depends on DVB_USB
+ select DVB_IT913X_FE
+ help
+ Say Y here to support the it913x device
+
+config DVB_USB_MXL111SF
+ tristate "MxL111SF DTV USB2.0 support"
+ depends on DVB_USB
+ select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+ select VIDEO_TVEEPROM
+ help
+ Say Y here to support the MxL111SF USB2.0 DTV receiver.
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 4bac13d..26c8b9e 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -64,6 +64,9 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
dvb-usb-anysee-objs = anysee.o
obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
+dvb-usb-pctv452e-objs = pctv452e.o
+obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
+
dvb-usb-dw2102-objs = dw2102.o
obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
@@ -94,7 +97,16 @@ obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
dvb-usb-technisat-usb2-objs = technisat-usb2.o
obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+dvb-usb-it913x-objs := it913x.o
+obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
+
+dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index b95a95e..2aef3c8 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -127,6 +127,8 @@ static struct dvb_usb_device_properties a800_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.streaming_ctrl = dibusb2_0_streaming_ctrl,
@@ -147,7 +149,7 @@ static struct dvb_usb_device_properties a800_properties = {
}
}
},
-
+ }},
.size_of_priv = sizeof(struct dibusb_state),
},
},
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c
index 6ad9474..3263e97 100644
--- a/drivers/media/dvb/dvb-usb/af9005-fe.c
+++ b/drivers/media/dvb/dvb-usb/af9005-fe.c
@@ -63,11 +63,9 @@ static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi,
u16 reglo, u8 pos, u8 len, u16 value)
{
int ret;
- u8 temp;
if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
return ret;
- temp = (u8) ((value & 0x0300) >> 8);
return af9005_write_register_bits(d, reghi, pos, len,
(u8) ((value & 0x300) >> 8));
}
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c
index c3bc64e..7e3961d 100644
--- a/drivers/media/dvb/dvb-usb/af9005-remote.c
+++ b/drivers/media/dvb/dvb-usb/af9005-remote.c
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*/
#include "af9005.h"
/* debug */
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
index 51f6439..0b3ef9f 100644
--- a/drivers/media/dvb/dvb-usb/af9005.c
+++ b/drivers/media/dvb/dvb-usb/af9005.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*/
#include "af9005.h"
@@ -815,7 +815,7 @@ static int af9005_frontend_attach(struct dvb_usb_adapter *adap)
debug_dump(buf, 8, printk);
}
}
- adap->fe = af9005_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = af9005_fe_attach(adap->dev);
return 0;
}
@@ -999,6 +999,8 @@ static struct dvb_usb_device_properties af9005_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps =
DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1018,6 +1020,7 @@ static struct dvb_usb_device_properties af9005_properties = {
}
}
},
+ }},
}
},
.power_ctrl = af9005_power_ctrl,
@@ -1069,9 +1072,12 @@ static int __init af9005_usb_module_init(void)
err("usb_register failed. (%d)", result);
return result;
}
+#if IS_MODULE(CONFIG_DVB_USB_AF9005) || defined(CONFIG_DVB_USB_AF9005_REMOTE)
+ /* FIXME: convert to todays kernel IR infrastructure */
rc_decode = symbol_request(af9005_rc_decode);
rc_keys = symbol_request(rc_map_af9005_table);
rc_keys_size = symbol_request(rc_map_af9005_table_size);
+#endif
if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
err("af9005_rc_decode function not found, disabling remote");
af9005_properties.rc.legacy.rc_query = NULL;
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 100ebc3..c6c275b 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -91,7 +91,6 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
case GET_CONFIG:
case READ_MEMORY:
case RECONNECT_USB:
- case GET_IR_CODE:
write = 0;
break;
case READ_I2C:
@@ -164,13 +163,6 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
deb_xfer("<<< ");
debug_dump(buf, act_len, deb_xfer);
- /* remote controller query status is 1 if remote code is not received */
- if (req->cmd == GET_IR_CODE && buf[1] == 1) {
- buf[1] = 0; /* clear command "error" status */
- memset(&buf[2], 0, req->data_len);
- buf[3] = 1; /* no remote code received mark */
- }
-
/* check status */
if (buf[1]) {
err("command failed:%d", buf[1]);
@@ -292,6 +284,10 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
}
if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+ if (msg[i].len > 3 || msg[i+1].len > 61) {
+ ret = -EOPNOTSUPP;
+ goto error;
+ }
if (msg[i].addr ==
af9015_af9013_config[0].demod_address)
req.cmd = READ_MEMORY;
@@ -306,12 +302,16 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
ret = af9015_ctrl_msg(d, &req);
i += 2;
} else if (msg[i].flags & I2C_M_RD) {
- ret = -EINVAL;
+ if (msg[i].len > 61) {
+ ret = -EOPNOTSUPP;
+ goto error;
+ }
if (msg[i].addr ==
- af9015_af9013_config[0].demod_address)
+ af9015_af9013_config[0].demod_address) {
+ ret = -EINVAL;
goto error;
- else
- req.cmd = READ_I2C;
+ }
+ req.cmd = READ_I2C;
req.i2c_addr = msg[i].addr;
req.addr = addr;
req.mbox = mbox;
@@ -321,6 +321,10 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
ret = af9015_ctrl_msg(d, &req);
i += 1;
} else {
+ if (msg[i].len > 21) {
+ ret = -EOPNOTSUPP;
+ goto error;
+ }
if (msg[i].addr ==
af9015_af9013_config[0].demod_address)
req.cmd = WRITE_MEMORY;
@@ -735,30 +739,37 @@ static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
{ 0xb8feb708, RC_MAP_MSI_DIGIVOX_II },
{ 0xa3703d00, RC_MAP_ALINK_DTU_M },
{ 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */
+ { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */
{ }
};
static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
- { (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
+ { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC,
RC_MAP_TERRATEC_SLIM_2 },
- { (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
+ { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
RC_MAP_TERRATEC_SLIM },
- { (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700,
+ { (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
RC_MAP_AZUREWAVE_AD_TU700 },
- { (USB_VID_VISIONPLUS << 16) + USB_PID_TINYTWIN,
+ { (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
RC_MAP_AZUREWAVE_AD_TU700 },
- { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III,
+ { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
RC_MAP_MSI_DIGIVOX_III },
- { (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD,
+ { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
+ RC_MAP_MSI_DIGIVOX_III },
+ { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
+ RC_MAP_LEADTEK_Y04G0051 },
+ { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
RC_MAP_LEADTEK_Y04G0051 },
- { (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X,
+ { (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
RC_MAP_AVERMEDIA_M135A },
- { (USB_VID_AFATECH << 16) + USB_PID_TREKSTOR_DVBT,
+ { (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
RC_MAP_TREKSTOR },
- { (USB_VID_KWORLD_2 << 16) + USB_PID_TINYTWIN_2,
+ { (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
RC_MAP_DIGITALNOW_TINYTWIN },
- { (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3,
+ { (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
RC_MAP_DIGITALNOW_TINYTWIN },
+ { (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
+ RC_MAP_MSI_DIGIVOX_III },
{ }
};
@@ -850,13 +861,13 @@ static int af9015_read_config(struct usb_device *udev)
for (i = 0; i < af9015_properties_count; i++) {
/* USB1.1 set smaller buffersize and disable 2nd adapter */
if (udev->speed == USB_SPEED_FULL) {
- af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+ af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
= TS_USB11_FRAME_SIZE;
/* disable 2nd adapter because we don't have
PID-filters */
af9015_config.dual_mode = 0;
} else {
- af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+ af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
= TS_USB20_FRAME_SIZE;
}
}
@@ -1082,44 +1093,11 @@ error:
return ret;
}
-/* init 2nd I2C adapter */
-static int af9015_i2c_init(struct dvb_usb_device *d)
-{
- int ret;
- struct af9015_state *state = d->priv;
- deb_info("%s:\n", __func__);
-
- strncpy(state->i2c_adap.name, d->desc->name,
- sizeof(state->i2c_adap.name));
- state->i2c_adap.algo = d->props.i2c_algo;
- state->i2c_adap.algo_data = NULL;
- state->i2c_adap.dev.parent = &d->udev->dev;
-
- i2c_set_adapdata(&state->i2c_adap, d);
-
- ret = i2c_add_adapter(&state->i2c_adap);
- if (ret < 0)
- err("could not add i2c adapter");
-
- return ret;
-}
-
static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
{
int ret;
- struct af9015_state *state = adap->dev->priv;
- struct i2c_adapter *i2c_adap;
-
- if (adap->id == 0) {
- /* select I2C adapter */
- i2c_adap = &adap->dev->i2c_adap;
-
- deb_info("%s: init I2C\n", __func__);
- ret = af9015_i2c_init(adap->dev);
- } else {
- /* select I2C adapter */
- i2c_adap = &state->i2c_adap;
+ if (adap->id == 1) {
/* copy firmware to 2nd demodulator */
if (af9015_config.dual_mode) {
ret = af9015_copy_firmware(adap->dev);
@@ -1135,10 +1113,10 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
}
/* attach demodulator */
- adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
- i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
+ &adap->dev->i2c_adap);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static struct mt2060_config af9015_mt2060_config = {
@@ -1206,57 +1184,56 @@ static struct mxl5007t_config af9015_mxl5007t_config = {
static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
{
- struct af9015_state *state = adap->dev->priv;
- struct i2c_adapter *i2c_adap;
int ret;
deb_info("%s:\n", __func__);
- /* select I2C adapter */
- if (adap->id == 0)
- i2c_adap = &adap->dev->i2c_adap;
- else
- i2c_adap = &state->i2c_adap;
-
switch (af9015_af9013_config[adap->id].tuner) {
case AF9013_TUNER_MT2060:
case AF9013_TUNER_MT2060_2:
- ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&af9015_mt2060_config,
af9015_config.mt2060_if1[adap->id])
== NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_QT1010:
case AF9013_TUNER_QT1010A:
- ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&af9015_qt1010_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_TDA18271:
- ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap,
+ ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
+ &adap->dev->i2c_adap,
&af9015_tda18271_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_TDA18218:
- ret = dvb_attach(tda18218_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap,
&af9015_tda18218_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MXL5003D:
- ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap,
&af9015_mxl5003_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MXL5005D:
case AF9013_TUNER_MXL5005R:
- ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap,
&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_ENV77H11D5:
- ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap,
+ ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
+ &adap->dev->i2c_adap,
DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MC44S803:
- ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap,
&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MXL5007T:
- ret = dvb_attach(mxl5007t_attach, adap->fe, i2c_adap,
+ ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap,
0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_UNKNOWN:
@@ -1309,6 +1286,7 @@ static struct usb_device_id af9015_usb_table[] = {
USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
/* 35 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
{USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
+ {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
{0},
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1328,6 +1306,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1343,8 +1323,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.count = 6,
.endpoint = 0x84,
},
+ }},
},
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
@@ -1359,6 +1342,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
}
}
},
+ }},
}
},
@@ -1456,6 +1440,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1471,8 +1457,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.count = 6,
.endpoint = 0x84,
},
+ }},
},
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
@@ -1487,6 +1476,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
}
}
},
+ }},
}
},
@@ -1502,7 +1492,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 9, /* check max from dvb-usb.h */
+ .num_device_descs = 10, /* check max from dvb-usb.h */
.devices = {
{
.name = "Xtensions XD-380",
@@ -1554,6 +1544,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.cold_ids = {&af9015_usb_table[20], NULL},
.warm_ids = {NULL},
},
+ {
+ .name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
+ .cold_ids = {&af9015_usb_table[37], NULL},
+ .warm_ids = {NULL},
+ },
}
}, {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -1568,6 +1563,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1583,8 +1580,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.count = 6,
.endpoint = 0x84,
},
+ }},
},
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
@@ -1599,6 +1599,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
}
}
},
+ }},
}
},
@@ -1704,33 +1705,11 @@ static int af9015_usb_probe(struct usb_interface *intf,
return ret;
}
-static void af9015_i2c_exit(struct dvb_usb_device *d)
-{
- struct af9015_state *state = d->priv;
- deb_info("%s:\n", __func__);
-
- /* remove 2nd I2C adapter */
- if (d->state & DVB_USB_STATE_I2C)
- i2c_del_adapter(&state->i2c_adap);
-}
-
-static void af9015_usb_device_exit(struct usb_interface *intf)
-{
- struct dvb_usb_device *d = usb_get_intfdata(intf);
- deb_info("%s:\n", __func__);
-
- /* remove 2nd I2C adapter */
- if (d != NULL && d->desc != NULL)
- af9015_i2c_exit(d);
-
- dvb_usb_device_exit(intf);
-}
-
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver af9015_usb_driver = {
.name = "dvb_usb_af9015",
.probe = af9015_usb_probe,
- .disconnect = af9015_usb_device_exit,
+ .disconnect = dvb_usb_device_exit,
.id_table = af9015_usb_table,
};
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
index beb3004..6252ea6 100644
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -99,7 +99,6 @@ enum af9015_ir_mode {
};
struct af9015_state {
- struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
u8 rc_repeat;
u32 rc_keycode;
u8 rc_last[4];
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 7c327b5..5f2278b 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -347,15 +347,17 @@ static struct isl6423_config anysee_isl6423_config = {
* PCB: ?
* parts: DNOS404ZH102A(MT352, DTT7579(?))
*
- * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
- * PCB: ?
+ * E30 VID=04b4 PID=861f HW=2 FW=2.1 "anysee-T(LP)"
+ * PCB: PCB 507T (rev1.61)
* parts: DNOS404ZH103A(ZL10353, DTT7579(?))
+ * OEA=0a OEB=00 OEC=00 OED=ff OEE=00
+ * IOA=45 IOB=ff IOC=00 IOD=ff IOE=00
*
* E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee"
* PCB: 507CD (rev1.1)
* parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01
- * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
- * IOA=4f IOB=ff IOC=00 IOD=06 IOF=01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe
+ * IOA=4f IOB=ff IOC=00 IOD=06 IOE=01
* IOD[0] ZL10353 1=enabled
* IOA[7] TS 0=enabled
* tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not)
@@ -363,30 +365,30 @@ static struct isl6423_config anysee_isl6423_config = {
* E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)"
* PCB: 507DC (rev0.2)
* parts: TDA10023, DTOS403IH102B TM, CST56I01
- * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
- * IOA=4f IOB=ff IOC=00 IOD=26 IOF=01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe
+ * IOA=4f IOB=ff IOC=00 IOD=26 IOE=01
* IOD[0] TDA10023 1=enabled
*
* E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)"
* PCB: 507SI (rev2.1)
* parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEF=fe
- * IOA=4d IOB=ff IOC=00 IOD=26 IOF=01
+ * OEA=80 OEB=00 OEC=ff OED=ff OEE=fe
+ * IOA=4d IOB=ff IOC=00 IOD=26 IOE=01
* IOD[0] CX24116 1=enabled
*
* E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
* PCB: 507FA (rev0.4)
* parts: TDA10023, DTOS403IH102B TM, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
- * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0
* IOD[5] TDA10023 1=enabled
* IOE[0] tuner 1=enabled
*
* E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
* PCB: 507FA (rev1.1)
* parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
- * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0
* DVB-C:
* IOD[5] TDA10023 1=enabled
* IOE[0] tuner 1=enabled
@@ -398,8 +400,8 @@ static struct isl6423_config anysee_isl6423_config = {
* E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)"
* PCB: 508TC (rev0.6)
* parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
- * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
- * IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
* IOA[7] TS 1=enabled
* IOE[4] TDA18212 1=enabled
* DVB-C:
@@ -414,13 +416,144 @@ static struct isl6423_config anysee_isl6423_config = {
* E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)"
* PCB: 508S2 (rev0.7)
* parts: DNBU10512IST(STV0903, STV6110), ISL6423
- * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
- * IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4
* IOA[7] TS 1=enabled
* IOE[5] STV0903 1=enabled
*
+ * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)"
+ * PCB: 508PTC (rev0.5)
+ * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
+ * IOA[7] TS 1=enabled
+ * IOE[4] TDA18212 1=enabled
+ * DVB-C:
+ * IOD[6] ZL10353 0=disabled
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] IF 1=enabled
+ * DVB-T:
+ * IOD[5] TDA10023 0=disabled
+ * IOD[6] ZL10353 1=enabled
+ * IOE[0] IF 0=enabled
+ *
+ * E7 S2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
+ * PCB: 508PS2 (rev0.4)
+ * parts: DNBU10512IST(STV0903, STV6110), ISL6423
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4
+ * IOA[7] TS 1=enabled
+ * IOE[5] STV0903 1=enabled
*/
+static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct anysee_state *state = adap->dev->priv;
+ int ret;
+
+ deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+ /* no frontend sleep control */
+ if (onoff == 0)
+ return 0;
+
+ switch (state->hw) {
+ case ANYSEE_HW_507FA: /* 15 */
+ /* E30 Combo Plus */
+ /* E30 C Plus */
+
+ if ((fe->id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable DVB-C tuner on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ } else {
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+
+ /* enable DVB-T tuner on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ }
+
+ break;
+ case ANYSEE_HW_508TC: /* 18 */
+ case ANYSEE_HW_508PTC: /* 21 */
+ /* E7 TC */
+ /* E7 PTC */
+
+ if ((fe->id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
+ 0x40);
+ if (ret)
+ goto error;
+
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable IF route on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ } else {
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+ 0x40);
+ if (ret)
+ goto error;
+
+ /* enable IF route on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ }
+
+ break;
+ default:
+ ret = 0;
+ }
+
+error:
+ return ret;
+}
+
static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
{
int ret;
@@ -441,41 +574,54 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
}
};
- /* Check which hardware we have.
- * We must do this call two times to get reliable values (hw bug).
- */
- ret = anysee_get_hw_info(adap->dev, hw_info);
- if (ret)
- goto error;
+ /* detect hardware only once */
+ if (adap->fe_adap[0].fe == NULL) {
+ /* Check which hardware we have.
+ * We must do this call two times to get reliable values (hw bug).
+ */
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ goto error;
- ret = anysee_get_hw_info(adap->dev, hw_info);
- if (ret)
- goto error;
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ goto error;
- /* Meaning of these info bytes are guessed. */
- info("firmware version:%d.%d hardware id:%d",
- hw_info[1], hw_info[2], hw_info[0]);
+ /* Meaning of these info bytes are guessed. */
+ info("firmware version:%d.%d hardware id:%d",
+ hw_info[1], hw_info[2], hw_info[0]);
- state->hw = hw_info[0];
+ state->hw = hw_info[0];
+ }
+
+ /* set current frondend ID for devices having two frondends */
+ if (adap->fe_adap[0].fe)
+ state->fe_id++;
switch (state->hw) {
- case ANYSEE_HW_02: /* 2 */
+ case ANYSEE_HW_507T: /* 2 */
/* E30 */
+ if (state->fe_id)
+ break;
+
/* attach demod */
- adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
&adap->dev->i2c_adap);
- if (adap->fe)
+ if (adap->fe_adap[0].fe)
break;
/* attach demod */
- adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
&adap->dev->i2c_adap);
break;
case ANYSEE_HW_507CD: /* 6 */
/* E30 Plus */
+ if (state->fe_id)
+ break;
+
/* enable DVB-T demod on IOD[0] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
if (ret)
@@ -487,33 +633,39 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &anysee_zl10353_config, &adap->dev->i2c_adap);
break;
case ANYSEE_HW_507DC: /* 10 */
/* E30 C Plus */
+ if (state->fe_id)
+ break;
+
/* enable DVB-C demod on IOD[0] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+ &anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
break;
case ANYSEE_HW_507SI: /* 11 */
/* E30 S2 Plus */
+ if (state->fe_id)
+ break;
+
/* enable DVB-S/S2 demod on IOD[0] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+ adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
&adap->dev->i2c_adap);
break;
@@ -539,118 +691,117 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
if (ret)
goto error;
- if (dvb_usb_anysee_delsys) {
- /* disable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
- 0x20);
+ if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+ 0x01);
if (ret)
goto error;
- /* enable DVB-T demod on IOD[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
- 0x01);
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
if (ret)
goto error;
/* attach demod */
if (tmp == 0xc7) {
/* TDA18212 config */
- adap->fe = dvb_attach(zl10353_attach,
- &anysee_zl10353_tda18212_config2,
- &adap->dev->i2c_adap);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ tda10023_attach,
+ &anysee_tda10023_tda18212_config,
+ &adap->dev->i2c_adap, 0x48);
} else {
/* PLL config */
- adap->fe = dvb_attach(zl10353_attach,
- &anysee_zl10353_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ tda10023_attach,
+ &anysee_tda10023_config,
+ &adap->dev->i2c_adap, 0x48);
}
} else {
- /* disable DVB-T demod on IOD[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
- 0x01);
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+ 0x20);
if (ret)
goto error;
- /* enable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
- 0x20);
+ /* enable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+ 0x01);
if (ret)
goto error;
/* attach demod */
if (tmp == 0xc7) {
/* TDA18212 config */
- adap->fe = dvb_attach(tda10023_attach,
- &anysee_tda10023_tda18212_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ zl10353_attach,
+ &anysee_zl10353_tda18212_config2,
+ &adap->dev->i2c_adap);
} else {
/* PLL config */
- adap->fe = dvb_attach(tda10023_attach,
- &anysee_tda10023_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ zl10353_attach,
+ &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
}
}
break;
case ANYSEE_HW_508TC: /* 18 */
+ case ANYSEE_HW_508PTC: /* 21 */
/* E7 TC */
+ /* E7 PTC */
/* enable transport stream on IOA[7] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
if (ret)
goto error;
- if (dvb_usb_anysee_delsys) {
- /* disable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
- 0x20);
- if (ret)
- goto error;
-
- /* enable DVB-T demod on IOD[6] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+ if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
0x40);
if (ret)
goto error;
- /* enable IF route on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
- 0x01);
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(zl10353_attach,
- &anysee_zl10353_tda18212_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
+ &anysee_tda10023_tda18212_config,
+ &adap->dev->i2c_adap, 0x48);
} else {
- /* disable DVB-T demod on IOD[6] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
- 0x40);
- if (ret)
- goto error;
-
- /* enable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
0x20);
if (ret)
goto error;
- /* enable IF route on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
- 0x01);
+ /* enable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+ 0x40);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(tda10023_attach,
- &anysee_tda10023_tda18212_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
+ &anysee_zl10353_tda18212_config,
+ &adap->dev->i2c_adap);
}
break;
case ANYSEE_HW_508S2: /* 19 */
+ case ANYSEE_HW_508PS2: /* 22 */
/* E7 S2 */
+ /* E7 PS2 */
+
+ if (state->fe_id)
+ break;
/* enable transport stream on IOA[7] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
@@ -663,13 +814,13 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
+ adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
&adap->dev->i2c_adap, 0);
break;
}
- if (!adap->fe) {
+ if (!adap->fe_adap[0].fe) {
/* we have no frontend :-( */
ret = -ENODEV;
err("Unsupported Anysee version. " \
@@ -684,14 +835,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
struct anysee_state *state = adap->dev->priv;
struct dvb_frontend *fe;
int ret;
- deb_info("%s:\n", __func__);
+ deb_info("%s: fe=%d\n", __func__, state->fe_id);
switch (state->hw) {
- case ANYSEE_HW_02: /* 2 */
+ case ANYSEE_HW_507T: /* 2 */
/* E30 */
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
NULL, DVB_PLL_THOMSON_DTT7579);
break;
@@ -699,7 +850,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E30 Plus */
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
break;
@@ -707,7 +858,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E30 C Plus */
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1),
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
break;
@@ -715,28 +866,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E30 S2 Plus */
/* attach LNB controller */
- fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
- &anysee_isl6423_config);
+ fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &anysee_isl6423_config);
break;
case ANYSEE_HW_507FA: /* 15 */
/* E30 Combo Plus */
/* E30 C Plus */
- if (dvb_usb_anysee_delsys) {
- /* enable DVB-T tuner on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
- 0x01);
- if (ret)
- goto error;
- } else {
- /* enable DVB-C tuner on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
- 0x01);
- if (ret)
- goto error;
- }
-
/* Try first attach TDA18212 silicon tuner on IOE[4], if that
* fails attach old simple PLL. */
@@ -746,8 +883,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach tuner */
- fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
- &anysee_tda18212_config);
+ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+ &adap->dev->i2c_adap, &anysee_tda18212_config);
if (fe)
break;
@@ -757,12 +894,15 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
- &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
+ (0xc0 >> 1), &adap->dev->i2c_adap,
+ DVB_PLL_SAMSUNG_DTOS403IH102A);
break;
case ANYSEE_HW_508TC: /* 18 */
+ case ANYSEE_HW_508PTC: /* 21 */
/* E7 TC */
+ /* E7 PTC */
/* enable tuner on IOE[4] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
@@ -770,20 +910,22 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach tuner */
- fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
- &anysee_tda18212_config);
+ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+ &adap->dev->i2c_adap, &anysee_tda18212_config);
break;
case ANYSEE_HW_508S2: /* 19 */
+ case ANYSEE_HW_508PS2: /* 22 */
/* E7 S2 */
+ /* E7 PS2 */
/* attach tuner */
- fe = dvb_attach(stv6110_attach, adap->fe,
+ fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
&anysee_stv6110_config, &adap->dev->i2c_adap);
if (fe) {
/* attach LNB controller */
- fe = dvb_attach(isl6423_attach, adap->fe,
+ fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &anysee_isl6423_config);
}
@@ -885,6 +1027,23 @@ static struct dvb_usb_device_properties anysee_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 2,
+ .frontend_ctrl = anysee_frontend_ctrl,
+ .fe = {{
+ .streaming_ctrl = anysee_streaming_ctrl,
+ .frontend_attach = anysee_frontend_attach,
+ .tuner_attach = anysee_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = (16*512),
+ }
+ }
+ },
+ }, {
.streaming_ctrl = anysee_streaming_ctrl,
.frontend_attach = anysee_frontend_attach,
.tuner_attach = anysee_tuner_attach,
@@ -898,6 +1057,7 @@ static struct dvb_usb_device_properties anysee_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
index a7673aa..57ee500 100644
--- a/drivers/media/dvb/dvb-usb/anysee.h
+++ b/drivers/media/dvb/dvb-usb/anysee.h
@@ -59,15 +59,18 @@ enum cmd {
struct anysee_state {
u8 hw; /* PCB ID */
u8 seq;
+ u8 fe_id:1; /* frondend ID */
};
-#define ANYSEE_HW_02 2 /* E30 */
-#define ANYSEE_HW_507CD 6 /* E30 Plus */
-#define ANYSEE_HW_507DC 10 /* E30 C Plus */
-#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */
-#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
-#define ANYSEE_HW_508TC 18 /* E7 TC */
-#define ANYSEE_HW_508S2 19 /* E7 S2 */
+#define ANYSEE_HW_507T 2 /* E30 */
+#define ANYSEE_HW_507CD 6 /* E30 Plus */
+#define ANYSEE_HW_507DC 10 /* E30 C Plus */
+#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */
+#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
+#define ANYSEE_HW_508TC 18 /* E7 TC */
+#define ANYSEE_HW_508S2 19 /* E7 S2 */
+#define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */
+#define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */
#define REG_IOA 0x80 /* Port A (bit addressable) */
#define REG_IOB 0x90 /* Port B (bit addressable) */
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
index 2351077..b779949 100644
--- a/drivers/media/dvb/dvb-usb/au6610.c
+++ b/drivers/media/dvb/dvb-usb/au6610.c
@@ -140,9 +140,9 @@ static struct zl10353_config au6610_zl10353_config = {
static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
return 0;
@@ -155,7 +155,7 @@ static struct qt1010_config au6610_qt1010_config = {
static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
- adap->fe, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&au6610_qt1010_config) == NULL ? -ENODEV : 0;
}
@@ -204,6 +204,8 @@ static struct dvb_usb_device_properties au6610_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = au6610_zl10353_frontend_attach,
.tuner_attach = au6610_qt1010_tuner_attach,
@@ -219,6 +221,7 @@ static struct dvb_usb_device_properties au6610_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c
index 57e2444..bf67b4d 100644
--- a/drivers/media/dvb/dvb-usb/az6027.c
+++ b/drivers/media/dvb/dvb-usb/az6027.c
@@ -40,7 +40,6 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x99 },
{ STB0899_DISF22RX , 0xa8 },
@@ -782,7 +781,6 @@ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
u8 buf;
- int ret;
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct i2c_msg i2c_msg = {
@@ -800,17 +798,17 @@ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
switch (voltage) {
case SEC_VOLTAGE_13:
buf = 1;
- ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
break;
case SEC_VOLTAGE_18:
buf = 2;
- ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
break;
case SEC_VOLTAGE_OFF:
buf = 0;
- ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
break;
default:
@@ -910,16 +908,16 @@ static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
az6027_frontend_reset(adap);
deb_info("adap = %p, dev = %p\n", adap, adap->dev);
- adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
- if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
+ if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
- adap->fe->ops.set_voltage = az6027_set_voltage;
+ adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
az6027_ci_init(adap);
} else {
- adap->fe = NULL;
+ adap->fe_adap[0].fe = NULL;
}
} else
warn("no front-end attached\n");
@@ -954,7 +952,6 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0, j = 0, len = 0;
- int ret;
u16 index;
u16 value;
int length;
@@ -990,7 +987,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
value = msg[i].addr + (msg[i].len << 8);
length = msg[i + 1].len + 6;
- ret = az6027_usb_in_op(d, req, value, index, data, length);
+ az6027_usb_in_op(d, req, value, index, data, length);
len = msg[i + 1].len;
for (j = 0; j < len; j++)
msg[i + 1].buf[j] = data[j + 5];
@@ -1017,7 +1014,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
index = 0x0;
value = msg[i].addr;
length = msg[i].len + 6;
- ret = az6027_usb_in_op(d, req, value, index, data, length);
+ az6027_usb_in_op(d, req, value, index, data, length);
len = msg[i].len;
for (j = 0; j < len; j++)
msg[i].buf[j] = data[j + 5];
@@ -1106,6 +1103,8 @@ static struct dvb_usb_device_properties az6027_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = az6027_streaming_ctrl,
.frontend_attach = az6027_frontend_attach,
@@ -1120,6 +1119,7 @@ static struct dvb_usb_device_properties az6027_properties = {
}
}
},
+ }},
}
},
/*
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c
index 6d1a304..57afb5a 100644
--- a/drivers/media/dvb/dvb-usb/ce6230.c
+++ b/drivers/media/dvb/dvb-usb/ce6230.c
@@ -186,9 +186,9 @@ static struct zl10353_config ce6230_zl10353_config = {
static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
- adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
return 0;
}
@@ -214,7 +214,7 @@ static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
int ret;
deb_info("%s:\n", __func__);
- ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+ ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
return ret;
}
@@ -273,6 +273,8 @@ static struct dvb_usb_device_properties ce6230_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = ce6230_zl10353_frontend_attach,
.tuner_attach = ce6230_mxl5003s_tuner_attach,
.stream = {
@@ -285,6 +287,7 @@ static struct dvb_usb_device_properties ce6230_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
index 16f2ce2..f9d9050 100644
--- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
@@ -69,7 +69,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
char state[3];
int ret;
- adap->fe = cinergyt2_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
sizeof(state), 0);
@@ -198,6 +198,8 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cinergyt2_streaming_ctrl,
.frontend_attach = cinergyt2_frontend_attach,
@@ -212,6 +214,7 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index acb5fb2..9f2a02c 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -347,7 +347,7 @@ static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
{
- struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
+ struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
const int timeout = 100;
const int junk_len = p->u.bulk.buffersize;
u8 *junk;
@@ -725,7 +725,7 @@ static struct max2165_config mygica_d689_max2165_cfg = {
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(simple_tuner_attach, adap->fe,
+ dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3);
return 0;
@@ -733,27 +733,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
NULL, DVB_PLL_THOMSON_DTT7579);
return 0;
}
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201);
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_LG_Z201);
return 0;
}
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
NULL, DVB_PLL_THOMSON_DTT7579);
return 0;
}
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(simple_tuner_attach, adap->fe,
+ dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
return 0;
}
@@ -795,9 +795,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
};
/* FIXME: generalize & move to common area */
- adap->fe->callback = dvico_bluebird_xc2028_callback;
+ adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
- fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
+ fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
return -EIO;
@@ -808,7 +808,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(mxl5005s_attach, adap->fe,
+ dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &aver_a868r_tuner);
return 0;
}
@@ -816,7 +816,7 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe;
- fe = dvb_attach(mxl5005s_attach, adap->fe,
+ fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &d680_dmb_tuner);
return (fe == NULL) ? -EIO : 0;
}
@@ -824,7 +824,7 @@ static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe;
- fe = dvb_attach(max2165_attach, adap->fe,
+ fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
return (fe == NULL) ? -EIO : 0;
}
@@ -837,8 +837,9 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
- if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -851,8 +852,10 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
+ &cxusb_lgdt3303_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -860,9 +863,9 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
+ adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
&adap->dev->i2c_adap);
- if (adap->fe != NULL)
+ if (adap->fe_adap[0].fe != NULL)
return 0;
return -EIO;
@@ -876,8 +879,9 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -890,11 +894,15 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
- &adap->dev->i2c_adap)) != NULL) ||
- ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_dee1601_config,
- &adap->dev->i2c_adap)) != NULL))
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
+ return 0;
+
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &cxusb_zl10353_dee1601_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -917,9 +925,11 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
- if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config_no_i2c_gate,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe =
+ dvb_attach(zl10353_attach,
+ &cxusb_zl10353_xc3028_config_no_i2c_gate,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
/* try to determine if there is no IR decoder on the I2C bus */
@@ -1031,9 +1041,9 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&cxusb_dualdig4_rev2_config);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -1084,15 +1094,15 @@ static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c =
- dib7000p_get_i2c_master(adap->fe,
+ dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
&dib7070p_dib0070_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
return 0;
}
@@ -1108,14 +1118,16 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
- if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &cxusb_zl10353_xc3028_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
- if ((adap->fe = dvb_attach(mt352_attach,
- &cxusb_mt352_xc3028_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+ &cxusb_mt352_xc3028_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -1150,7 +1162,7 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
usb_clear_halt(d->udev,
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev,
- usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+ usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
/* Drain USB pipes to avoid hang after reboot */
for (n = 0; n < 5; n++) {
@@ -1172,8 +1184,8 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
msleep(100);
/* Attach frontend */
- adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -1207,7 +1219,7 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
usb_clear_halt(d->udev,
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev,
- usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+ usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
/* Reset the tuner */
@@ -1223,9 +1235,9 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
msleep(100);
/* Attach frontend */
- adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
+ adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
&d->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -1383,6 +1395,8 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_cx22702_frontend_attach,
.tuner_attach = cxusb_fmd1216me_tuner_attach,
@@ -1397,7 +1411,7 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
}
}
},
-
+ }},
},
},
.power_ctrl = cxusb_power_ctrl,
@@ -1429,6 +1443,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_lgdt3303_frontend_attach,
.tuner_attach = cxusb_lgh064f_tuner_attach,
@@ -1444,6 +1460,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
}
}
},
+ }},
},
},
@@ -1483,6 +1500,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dee1601_frontend_attach,
.tuner_attach = cxusb_dee1601_tuner_attach,
@@ -1497,6 +1516,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
}
}
},
+ }},
},
},
@@ -1544,6 +1564,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_mt352_frontend_attach,
.tuner_attach = cxusb_lgz201_tuner_attach,
@@ -1559,6 +1581,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
}
}
},
+ }},
},
},
.power_ctrl = cxusb_bluebird_power_ctrl,
@@ -1596,6 +1619,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_mt352_frontend_attach,
.tuner_attach = cxusb_dtt7579_tuner_attach,
@@ -1611,6 +1636,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
}
}
},
+ }},
},
},
.power_ctrl = cxusb_bluebird_power_ctrl,
@@ -1645,6 +1671,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dualdig4_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
@@ -1659,6 +1687,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
}
}
},
+ }},
},
},
@@ -1695,6 +1724,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_nano2_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
@@ -1709,6 +1740,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
}
}
},
+ }},
},
},
@@ -1747,6 +1779,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_nano2_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
@@ -1761,6 +1795,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
}
}
},
+ }},
},
},
@@ -1796,6 +1831,8 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_aver_streaming_ctrl,
.frontend_attach = cxusb_aver_lgdt3303_frontend_attach,
.tuner_attach = cxusb_mxl5003s_tuner_attach,
@@ -1810,7 +1847,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
}
}
},
-
+ }},
},
},
.power_ctrl = cxusb_aver_power_ctrl,
@@ -1839,10 +1876,12 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
.tuner_attach = cxusb_dualdig4_rev2_tuner_attach,
- .size_of_priv = sizeof(struct dib0700_adapter_state),
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
@@ -1854,6 +1893,7 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
}
}
},
+ }},
},
},
@@ -1889,6 +1929,8 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
.frontend_attach = cxusb_d680_dmb_frontend_attach,
.tuner_attach = cxusb_d680_dmb_tuner_attach,
@@ -1904,6 +1946,7 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
}
}
},
+ }},
},
},
@@ -1940,6 +1983,8 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
.frontend_attach = cxusb_mygica_d689_frontend_attach,
.tuner_attach = cxusb_mygica_d689_tuner_attach,
@@ -1955,6 +2000,7 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
}
}
},
+ }},
},
},
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index a224e94..156cbfc 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
if (st->fw_version >= 0x10201) {
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
} else {
/* Write request */
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_NEW_I2C_WRITE;
@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
return -EINVAL;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -528,13 +528,13 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
adap_num++) {
if (fw_version >= 0x10201) {
- dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
+ dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
} else {
/* for fw version older than 1.20.1,
* the buffersize has to be n times 512 */
- dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
- if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
- dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
+ dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
+ if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
+ dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
}
}
}
@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
}
if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
@@ -579,18 +579,18 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
st->channel_state &= ~0x3;
- if ((adap->stream.props.endpoint != 2)
- && (adap->stream.props.endpoint != 3)) {
- deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint);
+ if ((adap->fe_adap[0].stream.props.endpoint != 2)
+ && (adap->fe_adap[0].stream.props.endpoint != 3)) {
+ deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint);
if (onoff)
st->channel_state |= 1 << (adap->id);
else
st->channel_state |= 1 << ~(adap->id);
} else {
if (onoff)
- st->channel_state |= 1 << (adap->stream.props.endpoint-2);
+ st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2);
else
- st->channel_state |= 1 << (3-adap->stream.props.endpoint);
+ st->channel_state |= 1 << (3-adap->fe_adap[0].stream.props.endpoint);
}
st->buf[2] |= st->channel_state;
@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
int new_proto, ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
- deb_info("could not acquire lock");
+ err("could not acquire lock");
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index c519ad5..f313182 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -17,6 +17,7 @@
#include "mt2266.h"
#include "tuner-xc2028.h"
#include "xc5000.h"
+#include "xc4000.h"
#include "s5h1411.h"
#include "dib0070.h"
#include "dib0090.h"
@@ -100,7 +101,7 @@ static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
}
}
st->mt2060_if1[adap->id] = 1220;
- return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
+ return (adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
}
@@ -117,15 +118,16 @@ static int eeprom_read(struct i2c_adapter *adap,u8 adrs,u8 *pval)
static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
- struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+ struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
s8 a;
int if1=1220;
if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
}
- return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
- if1) == NULL ? -ENODEV : 0;
+ return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c,
+ &bristol_mt2060_config[adap->id], if1) == NULL ?
+ -ENODEV : 0;
}
/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
@@ -278,10 +280,12 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
}
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
- &stk7700d_dib7000p_mt2266_config[adap->id]);
+ adap->fe_adap[0].fe =
+ dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ 0x80 + (adap->id << 1),
+ &stk7700d_dib7000p_mt2266_config[adap->id]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
@@ -305,17 +309,19 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
}
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
- &stk7700d_dib7000p_mt2266_config[adap->id]);
+ adap->fe_adap[0].fe =
+ dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ 0x80 + (adap->id << 1),
+ &stk7700d_dib7000p_mt2266_config[adap->id]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
- tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
}
@@ -395,8 +401,8 @@ static int stk7700ph_xc3028_callback(void *ptr, int component,
switch (command) {
case XC2028_TUNER_RESET:
/* Send the tuner in then out of reset */
- dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
break;
case XC2028_RESET_CLK:
break;
@@ -446,25 +452,25 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&stk7700ph_dib7700_xc3028_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
- tun_i2c = dib7000p_get_i2c_master(adap->fe,
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
stk7700ph_xc3028_config.i2c_adap = tun_i2c;
/* FIXME: generalize & move to common area */
- adap->fe->callback = stk7700ph_xc3028_callback;
+ adap->fe_adap[0].fe->callback = stk7700ph_xc3028_callback;
- return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
+ return dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &stk7700ph_xc3028_config)
== NULL ? -ENODEV : 0;
}
@@ -684,12 +690,12 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
st->mt2060_if1[0] = 1220;
if (dib7000pc_detection(&adap->dev->i2c_adap)) {
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
st->is_dib7000pc = 1;
} else
- adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+ adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static struct mt2060_config stk7700p_mt2060_config = {
@@ -708,11 +714,11 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
- tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
else
- tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+ return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk7700p_mt2060_config,
if1) == NULL ? -ENODEV : 0;
}
@@ -842,33 +848,33 @@ static int dib7770_set_param_override(struct dvb_frontend *fe,
static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe,
+ struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
- &dib7770p_dib0070_config) == NULL)
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+ &dib7770p_dib0070_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
return 0;
}
static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
return -ENODEV;
} else {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
return -ENODEV;
}
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
return 0;
}
@@ -877,26 +883,26 @@ static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
{
struct dib0700_state *st = adapter->dev->priv;
if (st->is_dib7000pc)
- return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
- return dib7000m_pid_filter(adapter->fe, index, pid, onoff);
+ return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
struct dib0700_state *st = adapter->dev->priv;
if (st->is_dib7000pc)
- return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
- return dib7000m_pid_filter_ctrl(adapter->fe, onoff);
+ return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
- return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
+ return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
- return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
+ return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -954,9 +960,9 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&dib7070p_dib7000p_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* STK7770P */
@@ -1006,9 +1012,9 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&dib7770p_dib7000p_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* DIB807x generic */
@@ -1224,34 +1230,34 @@ static int dib807x_set_param_override(struct dvb_frontend *fe,
static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe,
+ struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
&dib807x_dib0070_config[0]) == NULL)
return -ENODEV;
} else {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
&dib807x_dib0070_config[1]) == NULL)
return -ENODEV;
}
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib807x_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib807x_set_param_override;
return 0;
}
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
- return dib8000_pid_filter(adapter->fe, index, pid, onoff);
+ return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
int onoff)
{
- return dib8000_pid_filter_ctrl(adapter->fe, onoff);
+ return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
/* STK807x */
@@ -1275,10 +1281,10 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* STK807xPVR */
@@ -1304,10 +1310,10 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
/* initialize IC 0 */
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
@@ -1315,10 +1321,10 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
/* initialize IC 1 */
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
&dib807x_dib8000_config[1]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* STK8096GP */
@@ -1545,13 +1551,13 @@ static int dib8096_set_param_override(struct dvb_frontend *fe,
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
return 0;
}
@@ -1574,30 +1580,30 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c;
- struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe, 1);
+ struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
if (fe_slave) {
tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
- fe_slave->dvb = adap->fe->dvb;
+ fe_slave->dvb = adap->fe_adap[0].fe->dvb;
fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
}
- tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+ tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
return 0;
}
@@ -1625,12 +1631,12 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
- dib8000_set_slave_frontend(adap->fe, fe_slave);
+ dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
@@ -1638,12 +1644,12 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
/* STK9090M */
static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
- return dib9000_fw_pid_filter(adapter->fe, index, pid, onoff);
+ return dib9000_fw_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
- return dib9000_fw_pid_filter_ctrl(adapter->fe, onoff);
+ return dib9000_fw_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
@@ -1855,15 +1861,15 @@ static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap)
stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
- adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
+ adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *state = adap->priv;
- struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe);
+ struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
u16 data_dib190[10] = {
1, 0x1374,
2, 0x01a2,
@@ -1872,13 +1878,13 @@ static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
8, 0x0486,
};
- if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL)
+ if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &dib9090_dib0090_config) == NULL)
return -ENODEV;
- i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+ i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
return -ENODEV;
dib0700_set_i2c_speed(adap->dev, 2000);
- if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+ if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
return -ENODEV;
release_firmware(state->frontend_firmware);
return 0;
@@ -1924,16 +1930,16 @@ static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data;
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
- adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
+ adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
+ i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
- dib9000_set_slave_frontend(adap->fe, fe_slave);
+ dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
@@ -1950,26 +1956,26 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
0, 0x00ef,
8, 0x0406,
};
- i2c = dib9000_get_tuner_interface(adap->fe);
- if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
+ i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
+ if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
return -ENODEV;
- i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+ i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
return -ENODEV;
dib0700_set_i2c_speed(adap->dev, 2000);
- if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+ if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
return -ENODEV;
- fe_slave = dib9000_get_slave_frontend(adap->fe, 1);
+ fe_slave = dib9000_get_slave_frontend(adap->fe_adap[0].fe, 1);
if (fe_slave != NULL) {
- i2c = dib9000_get_component_bus_interface(adap->fe);
+ i2c = dib9000_get_component_bus_interface(adap->fe_adap[0].fe);
dib9000_set_i2c_adapter(fe_slave, i2c);
i2c = dib9000_get_tuner_interface(fe_slave);
if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
return -ENODEV;
- fe_slave->dvb = adap->fe->dvb;
- dib9000_fw_set_component_bus_speed(adap->fe, 2000);
+ fe_slave->dvb = adap->fe_adap[0].fe->dvb;
+ dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000);
if (dib9000_firmware_post_pll_init(fe_slave) < 0)
return -ENODEV;
}
@@ -2392,23 +2398,23 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+ struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
@@ -2438,11 +2444,11 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
}
dib0700_set_i2c_speed(adap->dev, 340);
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- dib7090_slave_reset(adap->fe);
+ dib7090_slave_reset(adap->fe_adap[0].fe);
return 0;
}
@@ -2451,50 +2457,50 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *i2c;
- if (adap->dev->adapter[0].fe == NULL) {
+ if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
err("the master dib7090 has to be initialized first");
return -ENODEV; /* the master device has not been initialized */
}
- i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+ i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
dib0700_set_i2c_speed(adap->dev, 200);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+ struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+ struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
@@ -2554,14 +2560,14 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
- return adap->fe == NULL ? -ENODEV : 0;
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* S5H1411 */
@@ -2616,9 +2622,9 @@ static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
/* GPIOs are initialized, do the attach */
- adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+ adap->fe_adap[0].fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
&adap->dev->i2c_adap);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int dib0700_xc5000_tuner_callback(void *priv, int component,
@@ -2648,13 +2654,163 @@ static struct xc5000_config s5h1411_xc5000_tunerconfig = {
static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
{
/* FIXME: generalize & move to common area */
- adap->fe->callback = dib0700_xc5000_tuner_callback;
+ adap->fe_adap[0].fe->callback = dib0700_xc5000_tuner_callback;
- return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+ return dvb_attach(xc5000_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&s5h1411_xc5000_tunerconfig)
== NULL ? -ENODEV : 0;
}
+static int dib0700_xc4000_tuner_callback(void *priv, int component,
+ int command, int arg)
+{
+ struct dvb_usb_adapter *adap = priv;
+
+ if (command == XC4000_TUNER_RESET) {
+ /* Reset the tuner */
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+ msleep(10);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ } else {
+ err("xc4000: unknown tuner callback command: %d\n", command);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct dibx000_agc_config stk7700p_7000p_xc4000_agc_config = {
+ .band_caps = BAND_UHF | BAND_VHF,
+ .setup = 0x64,
+ .inv_gain = 0x02c8,
+ .time_stabiliz = 0x15,
+ .alpha_level = 0x00,
+ .thlock = 0x76,
+ .wbd_inv = 0x01,
+ .wbd_ref = 0x0b33,
+ .wbd_sel = 0x00,
+ .wbd_alpha = 0x02,
+ .agc1_max = 0x00,
+ .agc1_min = 0x00,
+ .agc2_max = 0x9b26,
+ .agc2_min = 0x26ca,
+ .agc1_pt1 = 0x00,
+ .agc1_pt2 = 0x00,
+ .agc1_pt3 = 0x00,
+ .agc1_slope1 = 0x00,
+ .agc1_slope2 = 0x00,
+ .agc2_pt1 = 0x00,
+ .agc2_pt2 = 0x80,
+ .agc2_slope1 = 0x1d,
+ .agc2_slope2 = 0x1d,
+ .alpha_mant = 0x11,
+ .alpha_exp = 0x1b,
+ .beta_mant = 0x17,
+ .beta_exp = 0x33,
+ .perform_agc_softsplit = 0x00,
+};
+
+static struct dibx000_bandwidth_config stk7700p_xc4000_pll_config = {
+ 60000, 30000, /* internal, sampling */
+ 1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
+ 0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, */
+ /* ADClkSrc, modulo */
+ (3 << 14) | (1 << 12) | 524, /* sad_cfg: refsel, sel, freq_15k */
+ 39370534, /* ifreq */
+ 20452225, /* timf */
+ 30000000 /* xtal */
+};
+
+/* FIXME: none of these inputs are validated yet */
+static struct dib7000p_config pctv_340e_config = {
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &stk7700p_7000p_xc4000_agc_config,
+ .bw = &stk7700p_xc4000_pll_config,
+
+ .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
+};
+
+/* PCTV 340e GPIOs map:
+ dib0700:
+ GPIO2 - CX25843 sleep
+ GPIO3 - CS5340 reset
+ GPIO5 - IRD
+ GPIO6 - Power Supply
+ GPIO8 - LNA (1=off 0=on)
+ GPIO10 - CX25843 reset
+ dib7000:
+ GPIO8 - xc4000 reset
+ */
+static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_state *st = adap->dev->priv;
+
+ /* Power Supply on */
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ msleep(50);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(100); /* Allow power supply to settle before probing */
+
+ /* cx25843 reset */
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+ msleep(1); /* cx25843 datasheet say 350us required */
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+
+ /* LNA off for now */
+ dib0700_set_gpio(adap->dev, GPIO8, GPIO_OUT, 1);
+
+ /* Put the CX25843 to sleep for now since we're in digital mode */
+ dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
+
+ /* FIXME: not verified yet */
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+
+ msleep(500);
+
+ if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
+ /* Demodulator not found for some reason? */
+ return -ENODEV;
+ }
+
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+ &pctv_340e_config);
+ st->is_dib7000pc = 1;
+
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
+}
+
+static struct xc4000_config dib7000p_xc4000_tunerconfig = {
+ .i2c_address = 0x61,
+ .default_pm = 1,
+ .dvb_amplitude = 0,
+ .set_smoothedcvbs = 0,
+ .if_khz = 5400
+};
+
+static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct i2c_adapter *tun_i2c;
+
+ /* The xc4000 is not on the main i2c bus */
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ DIBX000_I2C_INTERFACE_TUNER, 1);
+ if (tun_i2c == NULL) {
+ printk(KERN_ERR "Could not reach tuner i2c bus\n");
+ return 0;
+ }
+
+ /* Setup the reset callback */
+ adap->fe_adap[0].fe->callback = dib0700_xc4000_tuner_callback;
+
+ return dvb_attach(xc4000_attach, adap->fe_adap[0].fe, tun_i2c,
+ &dib7000p_xc4000_tunerconfig)
+ == NULL ? -ENODEV : 0;
+}
+
static struct lgdt3305_config hcw_lgdt3305_config = {
.i2c_addr = 0x0e,
.mpeg_mode = LGDT3305_MPEG_PARALLEL,
@@ -2706,16 +2862,16 @@ static int lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(30);
- adap->fe = dvb_attach(lgdt3305_attach,
+ adap->fe_adap[0].fe = dvb_attach(lgdt3305_attach,
&hcw_lgdt3305_config,
&adap->dev->i2c_adap);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
{
- return dvb_attach(mxl5007t_attach, adap->fe,
+ return dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x60,
&hcw_mxl5007t_config) == NULL ? -ENODEV : 0;
}
@@ -2802,6 +2958,8 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) },
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
/* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E_SE) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -2836,6 +2994,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk7700p_pid_filter,
@@ -2844,6 +3004,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
},
},
@@ -2897,15 +3058,21 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = bristol_frontend_attach,
.tuner_attach = bristol_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
}, {
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = bristol_frontend_attach,
.tuner_attach = bristol_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ }},
}
},
@@ -2931,6 +3098,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -2939,7 +3108,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
}, {
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -2948,6 +3120,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ }},
}
},
@@ -2990,6 +3163,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -2998,6 +3173,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
},
},
@@ -3032,6 +3208,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3040,7 +3218,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
},
},
@@ -3108,6 +3286,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3116,7 +3296,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
},
},
@@ -3152,6 +3332,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3160,9 +3342,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}, {
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3171,7 +3355,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}
},
@@ -3220,6 +3404,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3228,9 +3414,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}, {
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3239,7 +3427,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}
},
@@ -3267,6 +3455,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3275,7 +3465,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700ph_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
@@ -3335,11 +3525,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = s5h1411_frontend_attach,
.tuner_attach = xc5000_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
@@ -3371,11 +3563,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = lgdt3305_frontend_attach,
.tuner_attach = mxl5007t_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
@@ -3397,6 +3591,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3405,7 +3601,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7770p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3447,6 +3643,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
@@ -3455,7 +3653,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib807x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3491,6 +3689,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
@@ -3499,11 +3699,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib807x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
@@ -3512,7 +3714,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib807x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3540,6 +3742,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3549,7 +3753,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib809x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3577,6 +3781,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3586,7 +3792,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib9090_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3614,6 +3820,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3623,7 +3831,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = nim8096md_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3651,6 +3859,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3660,7 +3870,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = nim9090md_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3688,6 +3898,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3697,7 +3909,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = nim7090_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3725,6 +3937,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3734,11 +3948,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = tfe7090pvr_tuner0_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3748,7 +3964,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = tfe7090pvr_tuner1_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3772,6 +3988,43 @@ struct dvb_usb_device_properties dib0700_devices[] = {
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .frontend_attach = pctv340e_frontend_attach,
+ .tuner_attach = xc4000_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
+ .size_of_priv = sizeof(struct
+ dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "Pinnacle PCTV 340e HD Pro USB Stick",
+ { &dib0700_usb_id_table[76], NULL },
+ { NULL },
+ },
+ { "Pinnacle PCTV Hybrid Stick Solo",
+ { &dib0700_usb_id_table[77], NULL },
+ { NULL },
+ },
+ },
+ .rc.core = {
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
+ .module_name = "dib0700",
+ .rc_query = dib0700_rc_query_old_firmware,
+ .allowed_protos = RC_TYPE_RC5 |
+ RC_TYPE_RC6 |
+ RC_TYPE_NEC,
+ .change_protocol = dib0700_change_protocol,
+ },
},
};
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 4c2a689..a76bbb2 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -23,7 +23,7 @@ int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
if (st->ops.fifo_ctrl != NULL)
- if (st->ops.fifo_ctrl(adap->fe,onoff)) {
+ if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
err("error while controlling the fifo of the demod.");
return -ENODEV;
}
@@ -37,7 +37,8 @@ int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onof
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
if (st->ops.pid_ctrl != NULL)
- st->ops.pid_ctrl(adap->fe,index,pid,onoff);
+ st->ops.pid_ctrl(adap->fe_adap[0].fe,
+ index, pid, onoff);
}
return 0;
}
@@ -48,7 +49,7 @@ int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
if (st->ops.pid_parse != NULL)
- if (st->ops.pid_parse(adap->fe,onoff) < 0)
+ if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
err("could not handle pid_parser");
}
return 0;
@@ -254,8 +255,16 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
msleep(1000);
}
- if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL ||
- (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
+ adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+ &adap->dev->i2c_adap,
+ DEFAULT_DIB3000P_I2C_ADDRESS,
+ &mod3000p_dib3000p_config);
+ if ((adap->fe_adap[0].fe) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+ &adap->dev->i2c_adap,
+ DEFAULT_DIB3000MC_I2C_ADDRESS,
+ &mod3000p_dib3000p_config);
+ if ((adap->fe_adap[0].fe) != NULL) {
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
st->ops.pid_parse = dib3000mc_pid_parse;
@@ -309,15 +318,15 @@ int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
}
}
- tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
- if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
+ tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
+ if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
/* not found - use panasonic pll parameters */
- if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
+ if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
return -ENOMEM;
} else {
st->mt2060_present = 1;
/* set the correct parameters for the dib3000p */
- dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config);
+ dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
}
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 04d91bd..7270791 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -31,11 +31,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
demod_cfg.demod_address = 0x8;
- if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg,
- &adap->dev->i2c_adap, &st->ops)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
+ &adap->dev->i2c_adap, &st->ops);
+ if ((adap->fe_adap[0].fe) == NULL)
return -ENODEV;
- adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
return 0;
}
@@ -46,7 +47,7 @@ static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
st->tuner_addr = 0x61;
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
DVB_PLL_TUA6010XS);
return 0;
}
@@ -57,7 +58,7 @@ static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap)
st->tuner_addr = 0x60;
- dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
DVB_PLL_TDA665X);
return 0;
}
@@ -78,16 +79,16 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
- if (adap->fe->ops.i2c_gate_ctrl)
- adap->fe->ops.i2c_gate_ctrl(adap->fe,1);
+ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
err("tuner i2c write failed.");
ret = -EREMOTEIO;
}
- if (adap->fe->ops.i2c_gate_ctrl)
- adap->fe->ops.i2c_gate_ctrl(adap->fe,0);
+ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
if (b2[0] == 0xfe) {
info("This device has the Thomson Cable onboard. Which is default.");
@@ -185,6 +186,8 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
@@ -205,6 +208,7 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
@@ -272,6 +276,8 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
.pid_filter_count = 16,
@@ -292,6 +298,7 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
},
},
@@ -338,6 +345,8 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
@@ -358,6 +367,7 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
@@ -398,6 +408,8 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
@@ -417,6 +429,7 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index c1d9094..9c165e2 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -57,6 +57,8 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.streaming_ctrl = dibusb2_0_streaming_ctrl,
@@ -76,6 +78,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index f6344cd..f718411 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -137,11 +137,16 @@ static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
{
struct digitv_state *st = adap->dev->priv;
- if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL) {
st->is_nxt6000 = 0;
return 0;
}
- if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
+ adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
+ &digitv_nxt6000_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL) {
st->is_nxt6000 = 1;
return 0;
}
@@ -152,11 +157,11 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
{
struct digitv_state *st = adap->dev->priv;
- if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4))
+ if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
return -ENODEV;
if (st->is_nxt6000)
- adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
return 0;
}
@@ -292,6 +297,8 @@ static struct dvb_usb_device_properties digitv_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = digitv_frontend_attach,
.tuner_attach = digitv_tuner_attach,
@@ -306,6 +313,7 @@ static struct dvb_usb_device_properties digitv_properties = {
}
}
},
+ }},
}
},
.identify_state = digitv_identify_state,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index ecd86ec..106dfd5 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -90,7 +90,7 @@ static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dtt200u_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
return 0;
}
@@ -140,6 +140,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -157,6 +159,7 @@ static struct dvb_usb_device_properties dtt200u_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
@@ -187,6 +190,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -204,6 +209,7 @@ static struct dvb_usb_device_properties wt220u_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
@@ -234,6 +240,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -251,6 +259,7 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
@@ -281,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -298,6 +309,7 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c
index 078ce92..7373132 100644
--- a/drivers/media/dvb/dvb-usb/dtv5100.c
+++ b/drivers/media/dvb/dvb-usb/dtv5100.c
@@ -115,13 +115,13 @@ static struct zl10353_config dtv5100_zl10353_config = {
static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
/* disable i2c gate, or it won't work... is this safe? */
- adap->fe->ops.i2c_gate_ctrl = NULL;
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
return 0;
}
@@ -133,7 +133,7 @@ static struct qt1010_config dtv5100_qt1010_config = {
static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
- adap->fe, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
}
@@ -180,6 +180,8 @@ static struct dvb_usb_device_properties dtv5100_properties = {
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dtv5100_frontend_attach,
.tuner_attach = dtv5100_tuner_attach,
@@ -193,6 +195,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {
}
}
},
+ }},
} },
.i2c_algo = &dtv5100_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index b3cb626..ba4a751 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -17,15 +17,20 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
if (adap == NULL)
return -ENODEV;
+ if ((adap->active_fe < 0) ||
+ (adap->active_fe >= adap->num_frontends_initialized)) {
+ return -EINVAL;
+ }
+
newfeedcount = adap->feedcount + (onoff ? 1 : -1);
/* stop feed before setting a new pid if there will be no pid anymore */
if (newfeedcount == 0) {
deb_ts("stop feeding\n");
- usb_urb_kill(&adap->stream);
+ usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
- if (adap->props.streaming_ctrl != NULL) {
- ret = adap->props.streaming_ctrl(adap, 0);
+ if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+ ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
if (ret < 0) {
err("error while stopping stream.");
return ret;
@@ -36,36 +41,37 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
adap->feedcount = newfeedcount;
/* activate the pid on the device specific pid_filter */
- deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ?
- "yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ?
- "on" : "off");
- if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
- adap->pid_filtering &&
- adap->props.pid_filter != NULL)
- adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff);
+ deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
+ adap->fe_adap[adap->active_fe].pid_filtering ?
+ "yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
+ dvbdmxfeed->index, onoff ? "on" : "off");
+ if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+ adap->fe_adap[adap->active_fe].pid_filtering &&
+ adap->props.fe[adap->active_fe].pid_filter != NULL)
+ adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
/* start the feed if this was the first feed and there is still a feed
* for reception.
*/
if (adap->feedcount == onoff && adap->feedcount > 0) {
deb_ts("submitting all URBs\n");
- usb_urb_submit(&adap->stream);
+ usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
deb_ts("controlling pid parser\n");
- if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
- adap->props.caps &
+ if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+ adap->props.fe[adap->active_fe].caps &
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
- adap->props.pid_filter_ctrl != NULL) {
- ret = adap->props.pid_filter_ctrl(adap,
- adap->pid_filtering);
+ adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
+ ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
+ adap->fe_adap[adap->active_fe].pid_filtering);
if (ret < 0) {
err("could not handle pid_parser");
return ret;
}
}
deb_ts("start feeding\n");
- if (adap->props.streaming_ctrl != NULL) {
- ret = adap->props.streaming_ctrl(adap, 1);
+ if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+ ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
if (ret < 0) {
err("error while enabling fifo.");
return ret;
@@ -90,6 +96,7 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
{
+ int i;
int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
adap->dev->owner, &adap->dev->udev->dev,
adapter_nums);
@@ -112,7 +119,12 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
adap->demux.priv = adap;
- adap->demux.feednum = adap->demux.filternum = adap->max_feed_count;
+ adap->demux.filternum = 0;
+ for (i = 0; i < adap->props.num_frontends; i++) {
+ if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
+ adap->demux.filternum = adap->fe_adap[i].max_feed_count;
+ }
+ adap->demux.feednum = adap->demux.filternum;
adap->demux.start_feed = dvb_usb_start_feed;
adap->demux.stop_feed = dvb_usb_stop_feed;
adap->demux.write_to_decoder = NULL;
@@ -156,14 +168,33 @@ int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
return 0;
}
+static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+ int ret = (adap->props.frontend_ctrl) ?
+ adap->props.frontend_ctrl(fe, onoff) : 0;
+
+ if (ret < 0) {
+ err("frontend_ctrl request failed");
+ return ret;
+ }
+ if (onoff)
+ adap->active_fe = fe->id;
+
+ return 0;
+}
+
static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
dvb_usb_device_power_ctrl(adap->dev, 1);
- if (adap->fe_init)
- adap->fe_init(fe);
+ dvb_usb_set_active_fe(fe, 1);
+
+ if (adap->fe_adap[fe->id].fe_init)
+ adap->fe_adap[fe->id].fe_init(fe);
return 0;
}
@@ -172,45 +203,81 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
- if (adap->fe_sleep)
- adap->fe_sleep(fe);
+ if (adap->fe_adap[fe->id].fe_sleep)
+ adap->fe_adap[fe->id].fe_sleep(fe);
+
+ dvb_usb_set_active_fe(fe, 0);
return dvb_usb_device_power_ctrl(adap->dev, 0);
}
int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
{
- if (adap->props.frontend_attach == NULL) {
- err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
- return 0;
- }
+ int ret, i;
- /* re-assign sleep and wakeup functions */
- if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
- adap->fe_init = adap->fe->ops.init; adap->fe->ops.init = dvb_usb_fe_wakeup;
- adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
+ /* register all given adapter frontends */
+ for (i = 0; i < adap->props.num_frontends; i++) {
- if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
- err("Frontend registration failed.");
- dvb_frontend_detach(adap->fe);
- adap->fe = NULL;
- return -ENODEV;
+ if (adap->props.fe[i].frontend_attach == NULL) {
+ err("strange: '%s' #%d,%d "
+ "doesn't want to attach a frontend.",
+ adap->dev->desc->name, adap->id, i);
+
+ return 0;
+ }
+
+ ret = adap->props.fe[i].frontend_attach(adap);
+ if (ret || adap->fe_adap[i].fe == NULL) {
+ /* only print error when there is no FE at all */
+ if (i == 0)
+ err("no frontend was attached by '%s'",
+ adap->dev->desc->name);
+
+ return 0;
+ }
+
+ adap->fe_adap[i].fe->id = i;
+
+ /* re-assign sleep and wakeup functions */
+ adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
+ adap->fe_adap[i].fe->ops.init = dvb_usb_fe_wakeup;
+ adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
+ adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
+
+ if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
+ err("Frontend %d registration failed.", i);
+ dvb_frontend_detach(adap->fe_adap[i].fe);
+ adap->fe_adap[i].fe = NULL;
+ /* In error case, do not try register more FEs,
+ * still leaving already registered FEs alive. */
+ if (i == 0)
+ return -ENODEV;
+ else
+ return 0;
}
/* only attach the tuner if the demod is there */
- if (adap->props.tuner_attach != NULL)
- adap->props.tuner_attach(adap);
- } else
- err("no frontend was attached by '%s'",adap->dev->desc->name);
+ if (adap->props.fe[i].tuner_attach != NULL)
+ adap->props.fe[i].tuner_attach(adap);
+
+ adap->num_frontends_initialized++;
+ }
return 0;
}
int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
{
- if (adap->fe != NULL) {
- dvb_unregister_frontend(adap->fe);
- dvb_frontend_detach(adap->fe);
+ int i = adap->num_frontends_initialized - 1;
+
+ /* unregister all given adapter frontends */
+ for (; i >= 0; i--) {
+ if (adap->fe_adap[i].fe != NULL) {
+ dvb_unregister_frontend(adap->fe_adap[i].fe);
+ dvb_frontend_detach(adap->fe_adap[i].fe);
+ }
}
+ adap->num_frontends_initialized = 0;
+
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 21b1549..2d08c9b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -37,6 +37,7 @@
#define USB_VID_HAUPPAUGE 0x2040
#define USB_VID_HYPER_PALTEK 0x1025
#define USB_VID_INTEL 0x8086
+#define USB_VID_ITETECH 0x048d
#define USB_VID_KWORLD 0xeb2a
#define USB_VID_KWORLD_2 0x1b80
#define USB_VID_KYE 0x0458
@@ -126,6 +127,7 @@
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_INTEL_CE9500 0x9500
+#define USB_PID_ITETECH_IT9135 0x9135
#define USB_PID_KWORLD_399U 0xe399
#define USB_PID_KWORLD_399U_2 0xe400
#define USB_PID_KWORLD_395U 0xe396
@@ -136,6 +138,7 @@
#define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_PC160_T 0xc161
#define USB_PID_KWORLD_UB383_T 0xe383
+#define USB_PID_KWORLD_UB499_2T_T09 0xe409
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
@@ -230,6 +233,8 @@
#define USB_PID_PINNACLE_PCTV310E 0x3211
#define USB_PID_PINNACLE_PCTV801E 0x023a
#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
+#define USB_PID_PINNACLE_PCTV340E 0x023d
+#define USB_PID_PINNACLE_PCTV340E_SE 0x023e
#define USB_PID_PINNACLE_PCTV73A 0x0243
#define USB_PID_PINNACLE_PCTV73ESE 0x0245
#define USB_PID_PINNACLE_PCTV74E 0x0246
@@ -238,6 +243,9 @@
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
+#define USB_PID_PCTV_452E 0x021f
+#define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007
+#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a
#define USB_PID_NEBULA_DIGITV 0x0201
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
@@ -313,6 +321,7 @@
#define USB_PID_FRIIO_WHITE 0x0001
#define USB_PID_TVWAY_PLUS 0x0002
#define USB_PID_SVEON_STV20 0xe39d
+#define USB_PID_SVEON_STV22 0xe401
#define USB_PID_AZUREWAVE_AZ6027 0x3275
#define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4
#define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index 2e3ea0f..169196e 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID
static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
{
struct dvb_usb_adapter *adap;
- int ret, n;
+ int ret, n, o;
for (n = 0; n < d->props.num_adapters; n++) {
adap = &d->adapter[n];
@@ -38,31 +38,42 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
+ for (o = 0; o < adap->props.num_frontends; o++) {
+ struct dvb_usb_adapter_fe_properties *props = &adap->props.fe[o];
/* speed - when running at FULL speed we need a HW PID filter */
- if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
+ if (d->udev->speed == USB_SPEED_FULL && !(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
return -ENODEV;
}
- if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
- (adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
- info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
- adap->pid_filtering = 1;
- adap->max_feed_count = adap->props.pid_filter_count;
+ if ((d->udev->speed == USB_SPEED_FULL && props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
+ (props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
+ info("will use the device's hardware PID filter (table count: %d).", props->pid_filter_count);
+ adap->fe_adap[o].pid_filtering = 1;
+ adap->fe_adap[o].max_feed_count = props->pid_filter_count;
} else {
info("will pass the complete MPEG2 transport stream to the software demuxer.");
- adap->pid_filtering = 0;
- adap->max_feed_count = 255;
+ adap->fe_adap[o].pid_filtering = 0;
+ adap->fe_adap[o].max_feed_count = 255;
}
- if (!adap->pid_filtering &&
+ if (!adap->fe_adap[o].pid_filtering &&
dvb_usb_force_pid_filter_usage &&
- adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) {
+ props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
info("pid filter enabled by module option.");
- adap->pid_filtering = 1;
- adap->max_feed_count = adap->props.pid_filter_count;
+ adap->fe_adap[o].pid_filtering = 1;
+ adap->fe_adap[o].max_feed_count = props->pid_filter_count;
}
+ if (props->size_of_priv > 0) {
+ adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
+ if (adap->fe_adap[o].priv == NULL) {
+ err("no memory for priv for adapter %d fe %d.", n, o);
+ return -ENOMEM;
+ }
+ }
+ }
+
if (adap->props.size_of_priv > 0) {
adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
if (adap->priv == NULL) {
@@ -77,6 +88,10 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
return ret;
}
+ /* use exclusive FE lock if there is multiple shared FEs */
+ if (adap->fe_adap[1].fe)
+ adap->dvb_adap.mfe_shared = 1;
+
d->num_adapters_initialized++;
d->state |= DVB_USB_STATE_DVB;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index bb46ba6..53a5c30 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -82,16 +82,28 @@ static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer
int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
{
- adap->stream.udev = adap->dev->udev;
- if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
- adap->stream.complete = dvb_usb_data_complete_204;
- else
- adap->stream.complete = dvb_usb_data_complete;
- adap->stream.user_priv = adap;
- return usb_urb_init(&adap->stream, &adap->props.stream);
+ int i, ret = 0;
+ for (i = 0; i < adap->props.num_frontends; i++) {
+
+ adap->fe_adap[i].stream.udev = adap->dev->udev;
+ if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
+ adap->fe_adap[i].stream.complete =
+ dvb_usb_data_complete_204;
+ else
+ adap->fe_adap[i].stream.complete = dvb_usb_data_complete;
+ adap->fe_adap[i].stream.user_priv = adap;
+ ret = usb_urb_init(&adap->fe_adap[i].stream,
+ &adap->props.fe[i].stream);
+ if (ret < 0)
+ break;
+ }
+ return ret;
}
int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
{
- return usb_urb_exit(&adap->stream);
+ int i;
+ for (i = 0; i < adap->props.num_frontends; i++)
+ usb_urb_exit(&adap->fe_adap[i].stream);
+ return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 76a8096..6d7d13f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -85,7 +85,7 @@ static inline u8 rc5_data(struct rc_map_table *key)
return key->scancode & 0xff;
}
-static inline u8 rc5_scan(struct rc_map_table *key)
+static inline u16 rc5_scan(struct rc_map_table *key)
{
return key->scancode & 0xffff;
}
@@ -124,6 +124,8 @@ struct usb_data_stream_properties {
* @caps: capabilities of the DVB USB device.
* @pid_filter_count: number of PID filter position in the optional hardware
* PID-filter.
+ * @num_frontends: number of frontends of the DVB USB adapter.
+ * @frontend_ctrl: called to power on/off active frontend.
* @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
* device (not URB submitting/killing).
* @pid_filter_ctrl: called to en/disable the PID filter, if any.
@@ -134,7 +136,7 @@ struct usb_data_stream_properties {
* pll_desc and pll_init_buf of struct dvb_usb_device).
* @stream: configuration of the USB streaming
*/
-struct dvb_usb_adapter_properties {
+struct dvb_usb_adapter_fe_properties {
#define DVB_USB_ADAP_HAS_PID_FILTER 0x01
#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
#define DVB_USB_ADAP_NEED_PID_FILTERING 0x04
@@ -152,9 +154,18 @@ struct dvb_usb_adapter_properties {
struct usb_data_stream_properties stream;
int size_of_priv;
+};
+
+#define MAX_NO_OF_FE_PER_ADAP 2
+struct dvb_usb_adapter_properties {
+ int size_of_priv;
+ int (*frontend_ctrl) (struct dvb_frontend *, int);
int (*fe_ioctl_override) (struct dvb_frontend *,
unsigned int, void *, unsigned int);
+
+ int num_frontends;
+ struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
};
/**
@@ -345,6 +356,20 @@ struct usb_data_stream {
*
* @stream: the usb data stream.
*/
+struct dvb_usb_fe_adapter {
+ struct dvb_frontend *fe;
+
+ int (*fe_init) (struct dvb_frontend *);
+ int (*fe_sleep) (struct dvb_frontend *);
+
+ struct usb_data_stream stream;
+
+ int pid_filtering;
+ int max_feed_count;
+
+ void *priv;
+};
+
struct dvb_usb_adapter {
struct dvb_usb_device *dev;
struct dvb_usb_adapter_properties props;
@@ -356,20 +381,16 @@ struct dvb_usb_adapter {
u8 id;
int feedcount;
- int pid_filtering;
/* dvb */
struct dvb_adapter dvb_adap;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvb_net;
- struct dvb_frontend *fe;
- int max_feed_count;
-
- int (*fe_init) (struct dvb_frontend *);
- int (*fe_sleep) (struct dvb_frontend *);
- struct usb_data_stream stream;
+ struct dvb_usb_fe_adapter fe_adap[MAX_NO_OF_FE_PER_ADAP];
+ int active_fe;
+ int num_frontends_initialized;
void *priv;
};
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 058b231..f103ec1 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -992,18 +992,18 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
struct dvb_tuner_ops *tuner_ops = NULL;
if (demod_probe & 4) {
- d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
+ d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
&d->dev->i2c_adap, 0);
- if (d->fe != NULL) {
- if (dvb_attach(stb6100_attach, d->fe,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
&dw2104a_stb6100_config,
&d->dev->i2c_adap)) {
- tuner_ops = &d->fe->ops.tuner_ops;
+ tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
tuner_ops->set_frequency = stb6100_set_freq;
tuner_ops->get_frequency = stb6100_get_freq;
tuner_ops->set_bandwidth = stb6100_set_bandw;
tuner_ops->get_bandwidth = stb6100_get_bandw;
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached STV0900+STB6100!\n");
return 0;
}
@@ -1011,13 +1011,13 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
}
if (demod_probe & 2) {
- d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
+ d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
&d->dev->i2c_adap, 0);
- if (d->fe != NULL) {
- if (dvb_attach(stv6110_attach, d->fe,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
&dw2104_stv6110_config,
&d->dev->i2c_adap)) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached STV0900+STV6110A!\n");
return 0;
}
@@ -1025,19 +1025,19 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
}
if (demod_probe & 1) {
- d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+ d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached cx24116!\n");
return 0;
}
}
- d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+ d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached DS3000!\n");
return 0;
}
@@ -1053,22 +1053,22 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
{
if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
/*dw2102_properties.adapter->tuner_attach = NULL;*/
- d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
+ d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached si21xx!\n");
return 0;
}
}
if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
- d->fe = dvb_attach(stv0288_attach, &earda_config,
+ d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- if (dvb_attach(stb6000_attach, d->fe, 0x61,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
&d->dev->i2c_adap)) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0288!\n");
return 0;
}
@@ -1077,10 +1077,10 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
- d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+ d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0299!\n");
return 0;
}
@@ -1090,9 +1090,9 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
{
- d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+ d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
&d->dev->i2c_adap, 0x48);
- if (d->fe != NULL) {
+ if (d->fe_adap[0].fe != NULL) {
info("Attached tda10023!\n");
return 0;
}
@@ -1101,12 +1101,12 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
{
- d->fe = dvb_attach(mt312_attach, &zl313_config,
+ d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- if (dvb_attach(zl10039_attach, d->fe, 0x60,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
&d->dev->i2c_adap)) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached zl100313+zl10039!\n");
return 0;
}
@@ -1119,16 +1119,16 @@ static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
{
u8 obuf[] = {7, 1};
- d->fe = dvb_attach(stv0288_attach, &earda_config,
+ d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
&d->dev->i2c_adap);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
- if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
+ if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
return -EIO;
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
@@ -1143,14 +1143,14 @@ static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
u8 obuf[] = {7, 1};
- d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+ d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
&d->dev->i2c_adap);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
- st->old_set_voltage = d->fe->ops.set_voltage;
- d->fe->ops.set_voltage = s660_set_voltage;
+ st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
@@ -1163,12 +1163,12 @@ static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
{
u8 obuf[] = {7, 1};
- d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
+ d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
&d->dev->i2c_adap, 0);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
@@ -1204,9 +1204,9 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
err("command 0x51 transfer failed.");
- d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
+ d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
&d->dev->i2c_adap);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
info("Attached DS3000!\n");
@@ -1216,14 +1216,14 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
&adap->dev->i2c_adap, DVB_PLL_OPERA1);
return 0;
}
static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
&adap->dev->i2c_adap, DVB_PLL_TUA6034);
return 0;
@@ -1535,7 +1535,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
DW210X_READ_MSG);
if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
dw2102_properties.i2c_algo = &dw2102_i2c_algo;
- dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
+ dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
break;
} else {
/* check STV0288 frontend */
@@ -1591,6 +1591,8 @@ static struct dvb_usb_device_properties dw2102_properties = {
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dw2102_frontend_attach,
.stream = {
.type = USB_BULK,
@@ -1602,6 +1604,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 3,
@@ -1642,6 +1645,8 @@ static struct dvb_usb_device_properties dw2104_properties = {
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dw2104_frontend_attach,
.stream = {
.type = USB_BULK,
@@ -1653,6 +1658,7 @@ static struct dvb_usb_device_properties dw2104_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 2,
@@ -1689,6 +1695,8 @@ static struct dvb_usb_device_properties dw3101_properties = {
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dw3101_frontend_attach,
.tuner_attach = dw3101_tuner_attach,
.stream = {
@@ -1701,6 +1709,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 1,
@@ -1733,6 +1742,8 @@ static struct dvb_usb_device_properties s6x0_properties = {
.read_mac_address = s6x0_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = zl100313_frontend_attach,
.stream = {
.type = USB_BULK,
@@ -1744,6 +1755,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 1,
@@ -1810,6 +1822,8 @@ static struct dvb_usb_device_properties su3000_properties = {
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = su3000_streaming_ctrl,
.frontend_attach = su3000_frontend_attach,
.stream = {
@@ -1822,6 +1836,7 @@ static struct dvb_usb_device_properties su3000_properties = {
}
}
}
+ }},
}
},
.num_device_descs = 3,
@@ -1855,7 +1870,7 @@ static int dw2102_probe(struct usb_interface *intf,
p1100->devices[0] = d1100;
p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
- p1100->adapter->frontend_attach = stv0288_frontend_attach;
+ p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!s660) {
@@ -1869,7 +1884,7 @@ static int dw2102_probe(struct usb_interface *intf,
s660->devices[0] = d660;
s660->devices[1] = d480_1;
s660->devices[2] = d480_2;
- s660->adapter->frontend_attach = ds3000_frontend_attach;
+ s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!p7500) {
@@ -1883,7 +1898,7 @@ static int dw2102_probe(struct usb_interface *intf,
p7500->devices[0] = d7500;
p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
- p7500->adapter->frontend_attach = prof_7500_frontend_attach;
+ p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
THIS_MODULE, NULL, adapter_nr) ||
diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/dvb/dvb-usb/ec168.c
index 1ba3e5d..78442fe 100644
--- a/drivers/media/dvb/dvb-usb/ec168.c
+++ b/drivers/media/dvb/dvb-usb/ec168.c
@@ -200,9 +200,9 @@ static struct ec100_config ec168_ec100_config = {
static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
- adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,
+ adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
return 0;
@@ -228,7 +228,7 @@ static struct mxl5005s_config ec168_mxl5003s_config = {
static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
- return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+ return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
}
@@ -382,6 +382,8 @@ static struct dvb_usb_device_properties ec168_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = ec168_streaming_ctrl,
.frontend_attach = ec168_ec100_frontend_attach,
.tuner_attach = ec168_mxl5003s_tuner_attach,
@@ -395,6 +397,7 @@ static struct dvb_usb_device_properties ec168_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/dvb/dvb-usb/friio.c
index 76159ae..b092dc2 100644
--- a/drivers/media/dvb/dvb-usb/friio.c
+++ b/drivers/media/dvb/dvb-usb/friio.c
@@ -403,8 +403,8 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap)
if (friio_initialize(adap->dev) < 0)
return -EIO;
- adap->fe = jdvbt90502_attach(adap->dev);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -473,6 +473,8 @@ static struct dvb_usb_device_properties friio_properties = {
/* caps:0 => no pid filter, 188B TS packet */
/* GL861 has a HW pid filter, but no info available. */
{
+ .num_frontends = 1,
+ .fe = {{
.caps = 0,
.frontend_attach = friio_frontend_attach,
@@ -490,6 +492,7 @@ static struct dvb_usb_device_properties friio_properties = {
}
}
},
+ }},
}
},
.i2c_algo = &gl861_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
index 6f596ed..63681df 100644
--- a/drivers/media/dvb/dvb-usb/gl861.c
+++ b/drivers/media/dvb/dvb-usb/gl861.c
@@ -103,9 +103,9 @@ static struct zl10353_config gl861_zl10353_config = {
static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -118,7 +118,7 @@ static struct qt1010_config gl861_qt1010_config = {
static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
- adap->fe, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&gl861_qt1010_config) == NULL ? -ENODEV : 0;
}
@@ -167,6 +167,8 @@ static struct dvb_usb_device_properties gl861_properties = {
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = gl861_frontend_attach,
.tuner_attach = gl861_tuner_attach,
@@ -181,6 +183,7 @@ static struct dvb_usb_device_properties gl861_properties = {
}
}
},
+ }},
} },
.i2c_algo = &gl861_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
index 60d11e5..5426267 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -144,19 +144,25 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
cmd[6] = (freq >> 16) & 0xff;
cmd[7] = (freq >> 24) & 0xff;
+ /* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
+ if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
+ c->delivery_system = SYS_TURBO;
+
switch (c->delivery_system) {
case SYS_DVBS:
- /* Allow QPSK and 8PSK (even for DVB-S) */
- if (c->modulation != QPSK && c->modulation != PSK_8) {
+ if (c->modulation != QPSK) {
deb_fe("%s: unsupported modulation selected (%d)\n",
__func__, c->modulation);
return -EOPNOTSUPP;
}
c->fec_inner = FEC_AUTO;
break;
- case SYS_DVBS2:
+ case SYS_DVBS2: /* kept for backwards compatibility */
deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
break;
+ case SYS_TURBO:
+ deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
+ break;
default:
deb_fe("%s: unsupported delivery system selected (%d)\n",
@@ -189,7 +195,10 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
default:
cmd[9] = 5; break;
}
- cmd[8] = ADV_MOD_DVB_QPSK;
+ if (c->delivery_system == SYS_TURBO)
+ cmd[8] = ADV_MOD_TURBO_QPSK;
+ else
+ cmd[8] = ADV_MOD_DVB_QPSK;
break;
case PSK_8: /* PSK_8 is for compatibility with DN */
cmd[8] = ADV_MOD_TURBO_8PSK;
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 1cb3d9a..5f71284 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -230,7 +230,7 @@ static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = gp8psk_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
return 0;
}
@@ -268,6 +268,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = gp8psk_streaming_ctrl,
.frontend_attach = gp8psk_frontend_attach,
/* parameter for the MPEG2-data transfer */
@@ -281,6 +283,7 @@ static struct dvb_usb_device_properties gp8psk_properties = {
}
}
},
+ }},
}
},
.power_ctrl = gp8psk_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
index 831749a..ed32b9d 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.h
+++ b/drivers/media/dvb/dvb-usb/gp8psk.h
@@ -78,9 +78,6 @@ extern int dvb_usb_gp8psk_debug;
#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */
#define GET_USB_SPEED 0x07
- #define USB_SPEED_LOW 0
- #define USB_SPEED_FULL 1
- #define USB_SPEED_HIGH 2
#define RESET_FX2 0x13
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
index 37b1469..c7ad854 100644
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -162,7 +162,7 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
int ret = 0;
if (st->usb_buffer == NULL) {
- st->usb_buffer = kmalloc(512, GFP_KERNEL);
+ st->usb_buffer = kmalloc(64, GFP_KERNEL);
if (st->usb_buffer == NULL) {
info("MEM Error no memory");
return -ENOMEM;
@@ -175,8 +175,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
if (ret < 0)
return -EAGAIN;
- /* the read/write capped at 512 */
- memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
+ /* the read/write capped at 64 */
+ memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
@@ -186,8 +186,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
- ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ?
- 512 : rlen , 0x01);
+ ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
+ rlen : 64 , 0x01);
if (rlen > 0)
memcpy(rbuf, buff, rlen);
@@ -326,14 +326,16 @@ static void lme2510_int_response(struct urb *lme_urb)
static int lme2510_int_read(struct dvb_usb_adapter *adap)
{
+ struct dvb_usb_device *d = adap->dev;
struct lme2510_state *lme_int = adap->dev->priv;
+ struct usb_host_endpoint *ep;
lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (lme_int->lme_urb == NULL)
return -ENOMEM;
- lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 5000, GFP_ATOMIC,
+ lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
&lme_int->lme_urb->transfer_dma);
if (lme_int->buffer == NULL)
@@ -343,10 +345,16 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
adap->dev->udev,
usb_rcvintpipe(adap->dev->udev, 0xa),
lme_int->buffer,
- 4096,
+ 128,
lme2510_int_response,
adap,
- 11);
+ 8);
+
+ /* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */
+ ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe);
+
+ if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
+ lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa),
lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -580,7 +588,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
struct lme2510_state *st = d->priv;
- static u8 obuf[64], ibuf[512];
+ static u8 obuf[64], ibuf[64];
int i, read, read_o;
u16 len;
u8 gate = st->i2c_gate;
@@ -621,7 +629,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
len = msg[i].len+3;
}
- if (lme2510_msg(d, obuf, len, ibuf, 512) < 0) {
+ if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
deb_info(1, "i2c transfer failed.");
return -EAGAIN;
}
@@ -941,7 +949,7 @@ static int lme_name(struct dvb_usb_adapter *adap)
const char *desc = adap->dev->desc->name;
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
" SHARP:BS2F7HZ0194"};
- char *name = adap->fe->ops.info.name;
+ char *name = adap->fe_adap[0].fe->ops.info.name;
strlcpy(name, desc, 128);
strlcat(name, fe_name[st->tuner_config], 128);
@@ -958,10 +966,10 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
st->i2c_talk_onoff = 1;
st->i2c_gate = 4;
- adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
+ adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config,
&adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
info("TUN Found Frontend TDA10086");
st->i2c_tuner_gate_w = 4;
st->i2c_tuner_gate_r = 4;
@@ -975,9 +983,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
}
st->i2c_gate = 4;
- adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
+ adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
&adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
info("FE Found Stv0299");
st->i2c_tuner_gate_w = 4;
st->i2c_tuner_gate_r = 5;
@@ -991,9 +999,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
}
st->i2c_gate = 5;
- adap->fe = dvb_attach(stv0288_attach, &lme_config,
+ adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
&adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
info("FE Found Stv0288");
st->i2c_tuner_gate_w = 4;
st->i2c_tuner_gate_r = 5;
@@ -1010,15 +1018,15 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
end: if (ret) {
- if (adap->fe) {
- dvb_frontend_detach(adap->fe);
- adap->fe = NULL;
+ if (adap->fe_adap[0].fe) {
+ dvb_frontend_detach(adap->fe_adap[0].fe);
+ adap->fe_adap[0].fe = NULL;
}
adap->dev->props.rc.core.rc_codes = NULL;
return -ENODEV;
}
- adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
+ adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
ret = lme_name(adap);
return ret;
}
@@ -1031,17 +1039,17 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
switch (st->tuner_config) {
case TUNER_LG:
- if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
+ if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
&adap->dev->i2c_adap, 1))
ret = st->tuner_config;
break;
case TUNER_S7395:
- if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
+ if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
&adap->dev->i2c_adap))
ret = st->tuner_config;
break;
case TUNER_S0194:
- if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
+ if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
&adap->dev->i2c_adap, DVB_PLL_OPERA1))
ret = st->tuner_config;
break;
@@ -1145,6 +1153,8 @@ static struct dvb_usb_device_properties lme2510_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
DVB_USB_ADAP_NEED_PID_FILTERING|
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1166,6 +1176,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
}
}
}
+ }},
}
},
.rc.core = {
@@ -1193,6 +1204,8 @@ static struct dvb_usb_device_properties lme2510c_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
DVB_USB_ADAP_NEED_PID_FILTERING|
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1214,6 +1227,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
}
}
}
+ }},
}
},
.rc.core = {
@@ -1241,7 +1255,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
void *buffer = NULL;
if (adap != NULL) {
- lme2510_kill_urb(&adap->stream);
+ lme2510_kill_urb(&adap->fe_adap[0].stream);
adap->feedcount = 0;
}
@@ -1255,7 +1269,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
if (st->lme_urb != NULL) {
usb_kill_urb(st->lme_urb);
- usb_free_coherent(d->udev, 5000, st->buffer,
+ usb_free_coherent(d->udev, 128, st->buffer,
st->lme_urb->transfer_dma);
info("Interrupt Service Stopped");
}
@@ -1306,5 +1320,5 @@ module_exit(lme2510_module_exit);
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.88");
+MODULE_VERSION("1.90");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index 9456792..a1e1287 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -86,12 +86,12 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
}
for (i = 0; i < d->props.num_adapters; i++)
- flags |= d->adapter[i].props.caps;
+ flags |= d->adapter[i].props.fe[0].caps;
/* Some devices(Dposh) might crash if we attempt touch at all. */
if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
for (i = 0; i < d->props.num_adapters; i++) {
- epi = d->adapter[i].props.stream.endpoint - 0x81;
+ epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
@@ -292,7 +292,7 @@ static int m920x_update_filters(struct dvb_usb_adapter *adap)
struct m920x_state *m = adap->dev->priv;
int enabled = m->filtering_enabled[adap->id];
int i, ret = 0, filter = 0;
- int ep = adap->props.stream.endpoint;
+ int ep = adap->props.fe[0].stream.endpoint;
for (i = 0; i < M9206_MAX_FILTERS; i++)
if (m->filters[adap->id][i] == 8192)
@@ -501,9 +501,10 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if ((adap->fe = dvb_attach(mt352_attach,
- &m920x_mt352_config,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+ &m920x_mt352_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
return 0;
@@ -513,9 +514,10 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if ((adap->fe = dvb_attach(tda10046_attach,
- &m920x_tda10046_08_config,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+ &m920x_tda10046_08_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
return 0;
@@ -525,9 +527,10 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if ((adap->fe = dvb_attach(tda10046_attach,
- &m920x_tda10046_0b_config,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+ &m920x_tda10046_0b_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
return 0;
@@ -537,7 +540,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
+ if (dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
return -ENODEV;
return 0;
@@ -547,7 +550,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+ if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
return -ENODEV;
return 0;
@@ -557,7 +560,7 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+ if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
return -ENODEV;
return 0;
@@ -565,7 +568,7 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(simple_tuner_attach, adap->fe,
+ dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3);
return 0;
@@ -807,6 +810,9 @@ static struct dvb_usb_device_properties megasky_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -827,6 +833,7 @@ static struct dvb_usb_device_properties megasky_properties = {
}
}
},
+ }},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -851,6 +858,9 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -871,6 +881,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
}
}
},
+ }},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -910,6 +921,9 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 2,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -929,7 +943,11 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.buffersize = 512,
}
}
+ }},
}},{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -949,6 +967,7 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.buffersize = 512,
}
}
+ }},
},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -974,6 +993,8 @@ static struct dvb_usb_device_properties dposh_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
/* Hardware pid filters don't work with this device/firmware */
.frontend_attach = m920x_mt352_frontend_attach,
@@ -989,6 +1010,7 @@ static struct dvb_usb_device_properties dposh_properties = {
}
}
},
+ }},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -1019,6 +1041,9 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1041,6 +1066,7 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
}
}
},
+ }},
} },
.i2c_algo = &m920x_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index bc350e9..21384da 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -166,6 +166,8 @@ static struct dvb_usb_device_properties nova_t_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -186,7 +188,7 @@ static struct dvb_usb_device_properties nova_t_properties = {
}
}
},
-
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index 2e4fab7..98fd9a6 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -263,10 +263,10 @@ static struct stv0299_config opera1_stv0299_config = {
static int opera1_frontend_attach(struct dvb_usb_adapter *d)
{
- if ((d->fe =
- dvb_attach(stv0299_attach, &opera1_stv0299_config,
- &d->dev->i2c_adap)) != NULL) {
- d->fe->ops.set_voltage = opera1_set_voltage;
+ d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,
+ &d->dev->i2c_adap);
+ if ((d->fe_adap[0].fe) != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;
return 0;
}
info("not attached stv0299");
@@ -276,7 +276,7 @@ static int opera1_frontend_attach(struct dvb_usb_adapter *d)
static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(
- dvb_pll_attach, adap->fe, 0xc0>>1,
+ dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,
&adap->dev->i2c_adap, DVB_PLL_OPERA1
);
return 0;
@@ -516,6 +516,8 @@ static struct dvb_usb_device_properties opera1_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = opera1_frontend_attach,
.streaming_ctrl = opera1_streaming_ctrl,
.tuner_attach = opera1_tuner_attach,
@@ -535,6 +537,7 @@ static struct dvb_usb_device_properties opera1_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 1,
diff --git a/drivers/media/dvb/dvb-usb/technisat-usb2.c b/drivers/media/dvb/dvb-usb/technisat-usb2.c
index 08f8842..0998fe9 100644
--- a/drivers/media/dvb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/dvb/dvb-usb/technisat-usb2.c
@@ -292,7 +292,7 @@ static void technisat_usb2_green_led_control(struct work_struct *work)
{
struct technisat_usb2_state *state =
container_of(work, struct technisat_usb2_state, green_led_work.work);
- struct dvb_frontend *fe = state->dev->adapter[0].fe;
+ struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
if (state->power_state == 0)
goto schedule;
@@ -505,14 +505,14 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
struct usb_device *udev = a->dev->udev;
int ret;
- a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
+ a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
- if (a->fe) {
+ if (a->fe_adap[0].fe) {
struct stv6110x_devctl *ctl;
ctl = dvb_attach(stv6110x_attach,
- a->fe,
+ a->fe_adap[0].fe,
&technisat_usb2_stv6110x_config,
&a->dev->i2c_adap);
@@ -532,8 +532,8 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
/* call the init function once to initialize
tuner's clock output divider and demod's
master clock */
- if (a->fe->ops.init)
- a->fe->ops.init(a->fe);
+ if (a->fe_adap[0].fe->ops.init)
+ a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
return -EAGAIN;
@@ -548,20 +548,20 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
if (ret != 0)
err("could not set IF_CLK to external");
- a->fe->ops.set_voltage = technisat_usb2_set_voltage;
+ a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
/* if everything was successful assign a nice name to the frontend */
- strlcpy(a->fe->ops.info.name, a->dev->desc->name,
- sizeof(a->fe->ops.info.name));
+ strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
+ sizeof(a->fe_adap[0].fe->ops.info.name));
} else {
- dvb_frontend_detach(a->fe);
- a->fe = NULL;
+ dvb_frontend_detach(a->fe_adap[0].fe);
+ a->fe_adap[0].fe = NULL;
}
}
technisat_usb2_set_led_timer(a->dev, 1, 1);
- return a->fe == NULL ? -ENODEV : 0;
+ return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* Remote control */
@@ -697,6 +697,8 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = technisat_usb2_frontend_attach,
.stream = {
@@ -711,7 +713,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
}
}
},
-
+ }},
.size_of_priv = 0,
},
},
@@ -765,10 +767,8 @@ static void technisat_usb2_disconnect(struct usb_interface *intf)
/* work and stuff was only created when the device is is hot-state */
if (dev != NULL) {
struct technisat_usb2_state *state = dev->priv;
- if (state != NULL) {
+ if (state != NULL)
cancel_delayed_work_sync(&state->green_led_work);
- flush_scheduled_work();
- }
}
dvb_usb_device_exit(intf);
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 0d4709f..ea4eab8 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -30,18 +30,43 @@
#include "tda826x.h"
#include "tda10086.h"
#include "tda1002x.h"
+#include "tda10048.h"
#include "tda827x.h"
#include "lnbp21.h"
+/* CA */
+#include "dvb_ca_en50221.h"
/* debug */
static int dvb_usb_ttusb2_debug;
#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+static int dvb_usb_ttusb2_debug_ci;
+module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
+MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+#define ci_dbg(format, arg...) \
+do { \
+ if (dvb_usb_ttusb2_debug_ci) \
+ printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
+ ": %s " format "\n" , __func__, ## arg); \
+} while (0)
+
+enum {
+ TT3650_CMD_CI_TEST = 0x40,
+ TT3650_CMD_CI_RD_CTRL,
+ TT3650_CMD_CI_WR_CTRL,
+ TT3650_CMD_CI_RD_ATTR,
+ TT3650_CMD_CI_WR_ATTR,
+ TT3650_CMD_CI_RESET,
+ TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
struct ttusb2_state {
+ struct dvb_ca_en50221 ca;
+ struct mutex ca_mutex;
u8 id;
u16 last_rc_key;
};
@@ -78,11 +103,260 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
return 0;
}
+/* ci */
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+ int ret;
+ u8 rx[60];/* (64 -4) */
+ ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
+ if (!ret)
+ memcpy(data, rx, read_len);
+ return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+ struct dvb_usb_device *d = ca->data;
+ struct ttusb2_state *state = d->priv;
+ int ret;
+
+ mutex_lock(&state->ca_mutex);
+ ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+ mutex_unlock(&state->ca_mutex);
+
+ return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+{
+ u8 buf[3];
+ int ret = 0;
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = (address >> 8) & 0x0F;
+ buf[1] = address;
+
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+ ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
+
+ if (ret < 0)
+ return ret;
+
+ return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
+{
+ u8 buf[3];
+
+ ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = (address >> 8) & 0x0F;
+ buf[1] = address;
+ buf[2] = value;
+
+ return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
+{
+ u8 buf[2];
+ int ret;
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = address & 3;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+ ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
+
+ if (ret < 0)
+ return ret;
+
+ return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
+{
+ u8 buf[2];
+
+ ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = address;
+ buf[1] = value;
+
+ return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
+{
+ u8 buf[1];
+ int ret;
+
+ ci_dbg("%d %d", slot, enable);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = enable;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+ if (ret < 0)
+ return ret;
+
+ if (enable != buf[0]) {
+ err("CI not %sabled.", enable ? "en" : "dis");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+ return tt3650_ci_set_video_port(ca, slot, 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+ return tt3650_ci_set_video_port(ca, slot, 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+ struct dvb_usb_device *d = ca->data;
+ struct ttusb2_state *state = d->priv;
+ u8 buf[1];
+ int ret;
+
+ ci_dbg("%d", slot);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = 0;
+
+ mutex_lock(&state->ca_mutex);
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+ if (ret)
+ goto failed;
+
+ msleep(500);
+
+ buf[0] = 1;
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+ if (ret)
+ goto failed;
+
+ msleep(500);
+
+ buf[0] = 0; /* FTA */
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+ msleep(1100);
+
+ failed:
+ mutex_unlock(&state->ca_mutex);
+
+ return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+ u8 buf[1];
+ int ret;
+
+ if (slot)
+ return -EINVAL;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+ if (ret)
+ return ret;
+
+ if (1 == buf[0]) {
+ return DVB_CA_EN50221_POLL_CAM_PRESENT |
+ DVB_CA_EN50221_POLL_CAM_READY;
+ }
+ return 0;
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+ struct ttusb2_state *state;
+
+ ci_dbg("");
+
+ if (NULL == d)
+ return;
+
+ state = d->priv;
+ if (NULL == state)
+ return;
+
+ if (NULL == state->ca.data)
+ return;
+
+ dvb_ca_en50221_release(&state->ca);
+
+ memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+ struct dvb_usb_device *d = a->dev;
+ struct ttusb2_state *state = d->priv;
+ int ret;
+
+ ci_dbg("");
+
+ mutex_init(&state->ca_mutex);
+
+ state->ca.owner = THIS_MODULE;
+ state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+ state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+ state->ca.read_cam_control = tt3650_ci_read_cam_control;
+ state->ca.write_cam_control = tt3650_ci_write_cam_control;
+ state->ca.slot_reset = tt3650_ci_slot_reset;
+ state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+ state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+ state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+ state->ca.data = d;
+
+ ret = dvb_ca_en50221_init(&a->dvb_adap,
+ &state->ca,
+ /* flags */ 0,
+ /* n_slots */ 1);
+ if (ret) {
+ err("Cannot initialize CI: Error %d.", ret);
+ memset(&state->ca, 0, sizeof(state->ca));
+ return ret;
+ }
+
+ info("CI initialized.");
+
+ return 0;
+}
+
static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
static u8 obuf[60], ibuf[60];
- int i,read;
+ int i, write_read, read;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
@@ -91,28 +365,35 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) {
- read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+ write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+ read = msg[i].flags & I2C_M_RD;
- obuf[0] = (msg[i].addr << 1) | read;
- obuf[1] = msg[i].len;
+ obuf[0] = (msg[i].addr << 1) | (write_read | read);
+ if (read)
+ obuf[1] = 0;
+ else
+ obuf[1] = msg[i].len;
/* read request */
- if (read)
+ if (write_read)
obuf[2] = msg[i+1].len;
+ else if (read)
+ obuf[2] = msg[i].len;
else
obuf[2] = 0;
- memcpy(&obuf[3],msg[i].buf,msg[i].len);
+ memcpy(&obuf[3], msg[i].buf, msg[i].len);
if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
err("i2c transfer failed.");
break;
}
- if (read) {
- memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
+ if (write_read) {
+ memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
i++;
- }
+ } else if (read)
+ memcpy(msg[i].buf, &ibuf[3], msg[i].len);
}
mutex_unlock(&d->i2c_mutex);
@@ -190,12 +471,31 @@ static struct tda10023_config tda10023_config = {
.deltaf = 0xa511,
};
+static struct tda10048_config tda10048_config = {
+ .demod_address = 0x10 >> 1,
+ .output_mode = TDA10048_PARALLEL_OUTPUT,
+ .inversion = TDA10048_INVERSION_ON,
+ .dtv6_if_freq_khz = TDA10048_IF_4000,
+ .dtv7_if_freq_khz = TDA10048_IF_4500,
+ .dtv8_if_freq_khz = TDA10048_IF_5000,
+ .clk_freq_khz = TDA10048_CLK_16000,
+ .no_firmware = 1,
+ .set_pll = true ,
+ .pll_m = 5,
+ .pll_n = 3,
+ .pll_p = 0,
+};
+
+static struct tda827x_config tda827x_config = {
+ .config = 0,
+};
+
static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev,0,3) < 0)
err("set interface to alts=3 failed");
- if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
+ if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
deb_info("TDA10086 attach failed\n");
return -ENODEV;
}
@@ -203,20 +503,57 @@ static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+ return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
+}
+
static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
err("set interface to alts=3 failed");
- if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
- deb_info("TDA10023 attach failed\n");
- return -ENODEV;
+
+ if (adap->fe_adap[0].fe == NULL) {
+ /* FE 0 DVB-C */
+ adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+ &tda10023_config, &adap->dev->i2c_adap, 0x48);
+
+ if (adap->fe_adap[0].fe == NULL) {
+ deb_info("TDA10023 attach failed\n");
+ return -ENODEV;
+ }
+ tt3650_ci_init(adap);
+ } else {
+ adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
+ &tda10048_config, &adap->dev->i2c_adap);
+
+ if (adap->fe_adap[1].fe == NULL) {
+ deb_info("TDA10048 attach failed\n");
+ return -ENODEV;
+ }
+
+ /* tuner is behind TDA10023 I2C-gate */
+ adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
+
}
+
return 0;
}
static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
{
- if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+ struct dvb_frontend *fe;
+
+ /* MFE: select correct FE to attach tuner since that's called twice */
+ if (adap->fe_adap[1].fe == NULL)
+ fe = adap->fe_adap[0].fe;
+ else
+ fe = adap->fe_adap[1].fe;
+
+ /* attach tuner */
+ if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
printk(KERN_ERR "%s: No tda827x found!\n", __func__);
return -ENODEV;
}
@@ -225,12 +562,12 @@ static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
{
- if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
+ if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
deb_info("TDA8263 attach failed\n");
return -ENODEV;
}
- if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
+ if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
deb_info("LNBP21 attach failed\n");
return -ENODEV;
}
@@ -242,6 +579,14 @@ static struct dvb_usb_device_properties ttusb2_properties;
static struct dvb_usb_device_properties ttusb2_properties_s2400;
static struct dvb_usb_device_properties ttusb2_properties_ct3650;
+static void ttusb2_usb_disconnect(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+ tt3650_ci_uninit(d);
+ dvb_usb_device_exit(intf);
+}
+
static int ttusb2_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -277,6 +622,8 @@ static struct dvb_usb_device_properties ttusb2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
.frontend_attach = ttusb2_frontend_tda10086_attach,
@@ -295,6 +642,7 @@ static struct dvb_usb_device_properties ttusb2_properties = {
}
}
}
+ }},
}
},
@@ -329,6 +677,8 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = NULL,
.frontend_attach = ttusb2_frontend_tda10086_attach,
@@ -347,6 +697,7 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
}
}
}
+ }},
}
},
@@ -383,6 +734,27 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 2,
+ .fe = {{
+ .streaming_ctrl = NULL,
+
+ .frontend_attach = ttusb2_frontend_tda10023_attach,
+ .tuner_attach = ttusb2_tuner_tda827x_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_ISOC,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .isoc = {
+ .framesperurb = 4,
+ .framesize = 940,
+ .interval = 1,
+ }
+ }
+ }
+ }, {
.streaming_ctrl = NULL,
.frontend_attach = ttusb2_frontend_tda10023_attach,
@@ -401,6 +773,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
}
}
}
+ }},
},
},
@@ -422,7 +795,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
static struct usb_driver ttusb2_driver = {
.name = "dvb_usb_ttusb2",
.probe = ttusb2_probe,
- .disconnect = dvb_usb_device_exit,
+ .disconnect = ttusb2_usb_disconnect,
.id_table = ttusb2_table,
};
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 118aab1..463673a 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -60,14 +60,14 @@ static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap)
umt_config.demod_init = umt_mt352_demod_init;
umt_config.demod_address = 0xf;
- adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
return 0;
}
static int umt_tuner_attach (struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034);
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034);
return 0;
}
@@ -100,6 +100,8 @@ static struct dvb_usb_device_properties umt_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = dibusb2_0_streaming_ctrl,
.frontend_attach = umt_mt352_frontend_attach,
.tuner_attach = umt_tuner_attach,
@@ -115,7 +117,7 @@ static struct dvb_usb_device_properties umt_properties = {
}
}
},
-
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c
index 86d6893..d62ee0f 100644
--- a/drivers/media/dvb/dvb-usb/usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/usb-urb.c
@@ -148,7 +148,7 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!.\n");
for (j = 0; j < i; j++)
- usb_free_urb(stream->urb_list[i]);
+ usb_free_urb(stream->urb_list[j]);
return -ENOMEM;
}
usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
@@ -181,7 +181,7 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!\n");
for (j = 0; j < i; j++)
- usb_free_urb(stream->urb_list[i]);
+ usb_free_urb(stream->urb_list[j]);
return -ENOMEM;
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index 54355f8..45e31f2 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -320,7 +320,7 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
vp702x_init_pid_filter(adap);
- adap->fe = vp702x_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
return 0;
@@ -383,6 +383,8 @@ static struct dvb_usb_device_properties vp702x_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
.streaming_ctrl = vp702x_streaming_ctrl,
@@ -399,6 +401,7 @@ static struct dvb_usb_device_properties vp702x_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct vp702x_adapter_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 536c16c..90873af 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -214,7 +214,7 @@ static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)
/* Dump the EEPROM */
/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
- adap->fe = vp7045_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
return 0;
}
@@ -245,6 +245,8 @@ static struct dvb_usb_device_properties vp7045_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = vp7045_frontend_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
@@ -257,6 +259,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
}
}
},
+ }},
}
},
.power_ctrl = vp7045_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h
index 969688f..cf5ec46 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.h
+++ b/drivers/media/dvb/dvb-usb/vp7045.h
@@ -36,9 +36,6 @@
#define Tuner_Power_OFF 0
#define GET_USB_SPEED 0x07
- #define USB_SPEED_LOW 0
- #define USB_SPEED_FULL 1
- #define USB_SPEED_HIGH 2
#define LOCK_TUNER_COMMAND 0x09
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 21c52e3..489ae82 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -1208,7 +1208,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
if (r->response != AVC_RESPONSE_ACCEPTED) {
dev_err(fdtv->device,
"CA PMT failed with response 0x%x\n", r->response);
- ret = -EFAULT;
+ ret = -EACCES;
}
out:
mutex_unlock(&fdtv->avc_mutex);
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
index 8ffb565..e5ebdbf 100644
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -45,11 +45,6 @@ static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
return flags;
}
-static int fdtv_ca_reset(struct firedtv *fdtv)
-{
- return avc_ca_reset(fdtv) ? -EFAULT : 0;
-}
-
static int fdtv_ca_get_caps(void *arg)
{
struct ca_caps *cap = arg;
@@ -65,12 +60,14 @@ static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
{
struct firedtv_tuner_status stat;
struct ca_slot_info *slot = arg;
+ int err;
- if (avc_tuner_status(fdtv, &stat))
- return -EFAULT;
+ err = avc_tuner_status(fdtv, &stat);
+ if (err)
+ return err;
if (slot->num != 0)
- return -EFAULT;
+ return -EACCES;
slot->type = CA_CI;
slot->flags = fdtv_get_ca_flags(&stat);
@@ -81,21 +78,21 @@ static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
- return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+ return avc_ca_app_info(fdtv, reply->msg, &reply->length);
}
static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
- return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+ return avc_ca_info(fdtv, reply->msg, &reply->length);
}
static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
- return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+ return avc_ca_get_mmi(fdtv, reply->msg, &reply->length);
}
static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
@@ -111,14 +108,15 @@ static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
err = fdtv_ca_info(fdtv, arg);
break;
default:
- if (avc_tuner_status(fdtv, &stat))
- err = -EFAULT;
- else if (stat.ca_mmi == 1)
+ err = avc_tuner_status(fdtv, &stat);
+ if (err)
+ break;
+ if (stat.ca_mmi == 1)
err = fdtv_ca_get_mmi(fdtv, arg);
else {
dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
fdtv->ca_last_command);
- err = -EFAULT;
+ err = -EACCES;
}
}
fdtv->ca_last_command = 0;
@@ -141,7 +139,7 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
data_length = msg->msg[3];
}
- return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
+ return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
}
static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
@@ -170,7 +168,7 @@ static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
default:
dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
fdtv->ca_last_command);
- err = -EFAULT;
+ err = -EACCES;
}
return err;
}
@@ -184,7 +182,7 @@ static int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg)
switch (cmd) {
case CA_RESET:
- err = fdtv_ca_reset(fdtv);
+ err = avc_ca_reset(fdtv);
break;
case CA_GET_CAP:
err = fdtv_ca_get_caps(arg);
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 44b816f..4a2d2e6 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -49,6 +49,27 @@ config DVB_STV6110x
help
A Silicon tuner that supports DVB-S and DVB-S2 modes
+comment "Multistandard (cable + terrestrial) frontends"
+ depends on DVB_CORE
+
+config DVB_DRXK
+ tristate "Micronas DRXK based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ Micronas DRX-K DVB-C/T demodulator.
+
+ Say Y when you want to support this frontend.
+
+config DVB_TDA18271C2DD
+ tristate "NXP TDA18271C2 silicon tuner"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ NXP TDA18271 silicon tuner.
+
+ Say Y when you want to support this tuner.
+
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
@@ -215,6 +236,13 @@ config DVB_MB86A16
A DVB-S/DSS Direct Conversion reveiver.
Say Y when you want to support this frontend.
+config DVB_TDA10071
+ tristate "NXP TDA10071"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ Say Y when you want to support this frontend.
+
comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
@@ -579,6 +607,16 @@ config DVB_LNBP21
help
An SEC control chips.
+config DVB_LNBP22
+ tristate "LNBP22 SEC controllers"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ LNB power supply and control voltage
+ regulator chip with step-up converter
+ and I2C interface.
+ Say Y when you want to support this chip.
+
config DVB_ISL6405
tristate "ISL6405 SEC controller"
depends on DVB_CORE && I2C
@@ -600,6 +638,11 @@ config DVB_ISL6423
help
A SEC controller chip from Intersil
+config DVB_A8293
+ tristate "Allegro A8293"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+
config DVB_LGS8GL5
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
depends on DVB_CORE && I2C
@@ -640,6 +683,14 @@ config DVB_IX2505V
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_IT913X_FE
+ tristate "it913x frontend and it9137 tuner"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-T tuner module.
+ Say Y when you want to support this frontend.
+
comment "Tools to develop new frontends"
config DVB_DUMMY_FE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 2f3a6f7..f639f67 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -2,14 +2,15 @@
# Makefile for the kernel DVB frontend device drivers.
#
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/common/tuners/
stb0899-objs = stb0899_drv.o stb0899_algo.o
stv0900-objs = stv0900_core.o stv0900_sw.o
au8522-objs = au8522_dig.o au8522_decoder.o
drxd-objs = drxd_firm.o drxd_hard.o
cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
+drxk-objs := drxk_hard.o
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -51,6 +52,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
obj-$(CONFIG_DVB_ISL6405) += isl6405.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
@@ -88,4 +90,9 @@ obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
obj-$(CONFIG_DVB_STV0367) += stv0367.o
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
+obj-$(CONFIG_DVB_DRXK) += drxk.o
+obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
+obj-$(CONFIG_DVB_A8293) += a8293.o
+obj-$(CONFIG_DVB_TDA10071) += tda10071.o
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index b537891..2b248c1 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -692,7 +692,7 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
/* Interrogate the decoder to see if we are getting a real signal */
lock_status = au8522_readreg(state, 0x00);
if (lock_status == 0xa2)
- vt->signal = 0x01;
+ vt->signal = 0xffff;
else
vt->signal = 0x00;
diff --git a/drivers/media/dvb/frontends/cx24113.c b/drivers/media/dvb/frontends/cx24113.c
index e9ee555..c341d57 100644
--- a/drivers/media/dvb/frontends/cx24113.c
+++ b/drivers/media/dvb/frontends/cx24113.c
@@ -31,8 +31,8 @@
static int debug;
-#define info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
-#define err(args...) do { printk(KERN_ERR "CX24113: " args); } while (0)
+#define cx_info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
+#define cx_err(args...) do { printk(KERN_ERR "CX24113: " args); } while (0)
#define dprintk(args...) \
do { \
@@ -341,7 +341,7 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
} while (N < 6 && R < 3);
if (N < 6) {
- err("strange frequency: N < 6\n");
+ cx_err("strange frequency: N < 6\n");
return;
}
F = freq_hz;
@@ -563,7 +563,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
int rc;
if (state == NULL) {
- err("Unable to kzalloc\n");
+ cx_err("Unable to kzalloc\n");
goto error;
}
@@ -571,7 +571,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
state->config = config;
state->i2c = i2c;
- info("trying to detect myself\n");
+ cx_info("trying to detect myself\n");
/* making a dummy read, because of some expected troubles
* after power on */
@@ -579,24 +579,24 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
rc = cx24113_readreg(state, 0x00);
if (rc < 0) {
- info("CX24113 not found.\n");
+ cx_info("CX24113 not found.\n");
goto error;
}
state->rev = rc;
switch (rc) {
case 0x43:
- info("detected CX24113 variant\n");
+ cx_info("detected CX24113 variant\n");
break;
case REV_CX24113:
- info("successfully detected\n");
+ cx_info("successfully detected\n");
break;
default:
- err("unsupported device id: %x\n", state->rev);
+ cx_err("unsupported device id: %x\n", state->rev);
goto error;
}
state->ver = cx24113_readreg(state, 0x01);
- info("version: %x\n", state->ver);
+ cx_info("version: %x\n", state->ver);
/* create dvb_frontend */
memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops,
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index 95c6465..4ff6d15 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -963,6 +963,10 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
struct cx24116_state *state = fe->demodulator_priv;
int i, ret;
+ /* Validate length */
+ if (d->msg_len > sizeof(d->msg))
+ return -EINVAL;
+
/* Dump DiSEqC message */
if (debug) {
printk(KERN_INFO "cx24116: %s(", __func__);
@@ -974,10 +978,6 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
printk(") toneburst=%d\n", toneburst);
}
- /* Validate length */
- if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
- return -EINVAL;
-
/* DiSEqC message */
for (i = 0; i < d->msg_len; i++)
state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
@@ -1452,11 +1452,7 @@ tuned: /* Set/Reset B/W */
cmd.args[0x00] = CMD_BANDWIDTH;
cmd.args[0x01] = 0x00;
cmd.len = 0x02;
- ret = cx24116_cmd_execute(fe, &cmd);
- if (ret != 0)
- return ret;
-
- return ret;
+ return cx24116_cmd_execute(fe, &cmd);
}
static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h
index ad17845..03cab7b 100644
--- a/drivers/media/dvb/frontends/cxd2820r.h
+++ b/drivers/media/dvb/frontends/cxd2820r.h
@@ -55,13 +55,13 @@ struct cxd2820r_config {
* Default: 0
* Values: 0, 1
*/
- int if_agc_polarity:1;
+ bool if_agc_polarity;
/* Spectrum inversion.
* Default: 0
* Values: 0, 1
*/
- int spec_inv:1;
+ bool spec_inv;
/* IFs for all used modes.
* Default: none, must set
@@ -93,9 +93,6 @@ extern struct dvb_frontend *cxd2820r_attach(
struct i2c_adapter *i2c,
struct dvb_frontend *fe
);
-extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
- struct dvb_frontend *fe
-);
#else
static inline struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
@@ -106,12 +103,6 @@ static inline struct dvb_frontend *cxd2820r_attach(
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
- struct dvb_frontend *fe
-)
-{
- return NULL;
-}
#endif
diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c
index 3c07d40..b85f501 100644
--- a/drivers/media/dvb/frontends/cxd2820r_c.c
+++ b/drivers/media/dvb/frontends/cxd2820r_c.c
@@ -335,4 +335,3 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
return 0;
}
-
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index 0779f69..036480f 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -314,6 +314,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe,
} else if (c->delivery_system == SYS_DVBT2) {
/* DVB-T => DVB-T2 */
ret = cxd2820r_sleep_t(fe);
+ if (ret)
+ break;
ret = cxd2820r_set_frontend_t2(fe, p);
}
break;
@@ -324,6 +326,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe,
} else if (c->delivery_system == SYS_DVBT) {
/* DVB-T2 => DVB-T */
ret = cxd2820r_sleep_t2(fe);
+ if (ret)
+ break;
ret = cxd2820r_set_frontend_t(fe, p);
}
break;
@@ -723,62 +727,22 @@ static void cxd2820r_release(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
dbg("%s", __func__);
- if (fe->ops.info.type == FE_OFDM) {
- i2c_del_adapter(&priv->tuner_i2c_adapter);
+ if (fe->ops.info.type == FE_OFDM)
kfree(priv);
- }
return;
}
-static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msg[], int num)
-{
- struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
- u8 obuf[msg[0].len + 2];
- struct i2c_msg msg2[2] = {
- {
- .addr = priv->cfg.i2c_address,
- .flags = 0,
- .len = sizeof(obuf),
- .buf = obuf,
- }, {
- .addr = priv->cfg.i2c_address,
- .flags = I2C_M_RD,
- .len = msg[1].len,
- .buf = msg[1].buf,
- }
- };
-
- obuf[0] = 0x09;
- obuf[1] = (msg[0].addr << 1);
- if (num == 2) { /* I2C read */
- obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
- msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */
- }
- memcpy(&obuf[2], msg[0].buf, msg[0].len);
-
- return i2c_transfer(priv->i2c, msg2, num);
-}
-
-static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
- .master_xfer = cxd2820r_tuner_i2c_xfer,
- .functionality = cxd2820r_tuner_i2c_func,
-};
-
-struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
- return &priv->tuner_i2c_adapter;
+ dbg("%s: %d", __func__, enable);
+
+ /* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
+ return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
}
-EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
-static struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops[2];
struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
struct i2c_adapter *i2c, struct dvb_frontend *fe)
@@ -817,18 +781,6 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
priv->fe[0].demodulator_priv = priv;
priv->fe[1].demodulator_priv = priv;
- /* create tuner i2c adapter */
- strlcpy(priv->tuner_i2c_adapter.name,
- "CXD2820R tuner I2C adapter",
- sizeof(priv->tuner_i2c_adapter.name));
- priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
- priv->tuner_i2c_adapter.algo_data = NULL;
- i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
- if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
- err("tuner I2C bus could not be initialized");
- goto error;
- }
-
return &priv->fe[0];
} else {
@@ -844,7 +796,7 @@ error:
}
EXPORT_SYMBOL(cxd2820r_attach);
-static struct dvb_frontend_ops cxd2820r_ops[2] = {
+static const struct dvb_frontend_ops cxd2820r_ops[2] = {
{
/* DVB-T/T2 */
.info = {
@@ -869,6 +821,7 @@ static struct dvb_frontend_ops cxd2820r_ops[2] = {
.sleep = cxd2820r_sleep,
.get_tune_settings = cxd2820r_get_tune_settings,
+ .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
.get_frontend = cxd2820r_get_frontend,
@@ -897,6 +850,7 @@ static struct dvb_frontend_ops cxd2820r_ops[2] = {
.sleep = cxd2820r_sleep,
.get_tune_settings = cxd2820r_get_tune_settings,
+ .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
.set_frontend = cxd2820r_set_frontend,
.get_frontend = cxd2820r_get_frontend,
diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb/frontends/cxd2820r_priv.h
index 25adbee..9553913 100644
--- a/drivers/media/dvb/frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb/frontends/cxd2820r_priv.h
@@ -50,18 +50,17 @@ struct cxd2820r_priv {
struct i2c_adapter *i2c;
struct dvb_frontend fe[2];
struct cxd2820r_config cfg;
- struct i2c_adapter tuner_i2c_adapter;
struct mutex fe_lock; /* FE lock */
int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
- int ber_running:1;
+ bool ber_running;
u8 bank[2];
u8 gpio[3];
fe_delivery_system_t delivery_system;
- int last_tune_failed:1; /* for switch between T and T2 tune */
+ bool last_tune_failed; /* for switch between T and T2 tune */
};
/* cxd2820r_core.c */
diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c
index 6582564..a04f9c8 100644
--- a/drivers/media/dvb/frontends/cxd2820r_t.c
+++ b/drivers/media/dvb/frontends/cxd2820r_t.c
@@ -446,4 +446,3 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
return 0;
}
-
diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c
index c47b35c..6548588 100644
--- a/drivers/media/dvb/frontends/cxd2820r_t2.c
+++ b/drivers/media/dvb/frontends/cxd2820r_t2.c
@@ -420,4 +420,3 @@ int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
return 0;
}
-
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index ba91735..404f63a 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -17,7 +17,7 @@
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*
*/
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index e80c597..437904c 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -17,7 +17,7 @@
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*
*/
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 292bc19..ce8534f 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -1598,8 +1598,8 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
return -ENOMEM;
rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
if (!rx) {
- goto rx_memory_error;
ret = -ENOMEM;
+ goto rx_memory_error;
}
msg[0].buf = tx;
@@ -2360,6 +2360,11 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
more common) */
st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+ /* FIXME: make sure the dev.parent field is initialized, or else
+ request_firmware() will hit an OOPS (this should be moved somewhere
+ more common) */
+ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+
dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
/* init 7090 tuner adapter */
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
index fe284d5..a542db1 100644
--- a/drivers/media/dvb/frontends/dib8000.c
+++ b/drivers/media/dvb/frontends/dib8000.c
@@ -114,15 +114,10 @@ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
return ret;
}
-static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+static u16 __dib8000_read_word(struct dib8000_state *state, u16 reg)
{
u16 ret;
- if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
- dprintk("could not acquire lock");
- return 0;
- }
-
state->i2c_write_buffer[0] = reg >> 8;
state->i2c_write_buffer[1] = reg & 0xff;
@@ -140,6 +135,21 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
dprintk("i2c read error on %d", reg);
ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+
+ return ret;
+}
+
+static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
+ ret = __dib8000_read_word(state, reg);
+
mutex_unlock(&state->i2c_buffer_lock);
return ret;
@@ -149,8 +159,15 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
{
u16 rw[2];
- rw[0] = dib8000_read_word(state, reg + 0);
- rw[1] = dib8000_read_word(state, reg + 1);
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
+ rw[0] = __dib8000_read_word(state, reg + 0);
+ rw[1] = __dib8000_read_word(state, reg + 1);
+
+ mutex_unlock(&state->i2c_buffer_lock);
return ((rw[0] << 16) | (rw[1]));
}
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
index b931074..660f806 100644
--- a/drivers/media/dvb/frontends/dib9000.c
+++ b/drivers/media/dvb/frontends/dib9000.c
@@ -1180,8 +1180,8 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- goto error;
ret = -EIO;
+ goto error;
}
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
@@ -2169,6 +2169,7 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
DibAcquireLock(&state->demod_lock);
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
goto error;
}
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
index 774d507..43be723 100644
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ b/drivers/media/dvb/frontends/dibx000_common.c
@@ -1,5 +1,6 @@
#include <linux/i2c.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include "dibx000_common.h"
diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c
index ea4c1c3..88e46f4 100644
--- a/drivers/media/dvb/frontends/drxd_hard.c
+++ b/drivers/media/dvb/frontends/drxd_hard.c
@@ -28,7 +28,6 @@
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
-#include <linux/version.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
@@ -233,7 +232,7 @@ static int i2c_read(struct i2c_adapter *adap,
return 0;
}
-inline u32 MulDiv32(u32 a, u32 b, u32 c)
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
{
u64 tmp64;
@@ -890,10 +889,15 @@ static int ReadIFAgc(struct drxd_state *state, u32 * pValue)
u32 R2 = state->if_agc_cfg.R2;
u32 R3 = state->if_agc_cfg.R3;
- u32 Vmax = (3300 * R2) / (R1 + R2);
- u32 Rpar = (R2 * R3) / (R3 + R2);
- u32 Vmin = (3300 * Rpar) / (R1 + Rpar);
- u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
+ u32 Vmax, Rpar, Vmin, Vout;
+
+ if (R2 == 0 && (R1 == 0 || R3 == 0))
+ return 0;
+
+ Vmax = (3300 * R2) / (R1 + R2);
+ Rpar = (R2 * R3) / (R3 + R2);
+ Vmin = (3300 * Rpar) / (R1 + Rpar);
+ Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
*pValue = Vout;
}
@@ -910,14 +914,16 @@ static int load_firmware(struct drxd_state *state, const char *fw_name)
return -EIO;
}
- state->microcode = kzalloc(fw->size, GFP_KERNEL);
+ state->microcode = kmalloc(fw->size, GFP_KERNEL);
if (state->microcode == NULL) {
- printk(KERN_ERR "drxd: firmware load failure: nomemory\n");
+ release_firmware(fw);
+ printk(KERN_ERR "drxd: firmware load failure: no memory\n");
return -ENOMEM;
}
memcpy(state->microcode, fw->data, fw->size);
state->microcode_length = fw->size;
+ release_firmware(fw);
return 0;
}
@@ -925,16 +931,15 @@ static int DownloadMicrocode(struct drxd_state *state,
const u8 *pMCImage, u32 Length)
{
u8 *pSrc;
- u16 Flags;
u32 Address;
u16 nBlocks;
u16 BlockSize;
- u16 BlockCRC;
u32 offset = 0;
int i, status = 0;
pSrc = (u8 *) pMCImage;
- Flags = (pSrc[0] << 8) | pSrc[1];
+ /* We're not using Flags */
+ /* Flags = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
nBlocks = (pSrc[0] << 8) | pSrc[1];
@@ -951,11 +956,13 @@ static int DownloadMicrocode(struct drxd_state *state,
pSrc += sizeof(u16);
offset += sizeof(u16);
- Flags = (pSrc[0] << 8) | pSrc[1];
+ /* We're not using Flags */
+ /* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
- BlockCRC = (pSrc[0] << 8) | pSrc[1];
+ /* We're not using BlockCRC */
+ /* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index 90bf573..2151c99 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -925,6 +925,13 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
memcpy(&state->frontend.ops, &ds3000_ops,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
+
+ /*
+ * Some devices like T480 starts with voltage on. Be sure
+ * to turn voltage off during init, as this can otherwise
+ * interfere with Unicable SCR systems.
+ */
+ ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
return &state->frontend;
error3:
diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
index f7a40a1..aa9ccb8 100644
--- a/drivers/media/dvb/frontends/itd1000.c
+++ b/drivers/media/dvb/frontends/itd1000.c
@@ -35,21 +35,18 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-#define deb(args...) do { \
+#define itd_dbg(args...) do { \
if (debug) { \
printk(KERN_DEBUG "ITD1000: " args);\
- printk("\n"); \
} \
} while (0)
-#define warn(args...) do { \
+#define itd_warn(args...) do { \
printk(KERN_WARNING "ITD1000: " args); \
- printk("\n"); \
} while (0)
-#define info(args...) do { \
+#define itd_info(args...) do { \
printk(KERN_INFO "ITD1000: " args); \
- printk("\n"); \
} while (0)
/* don't write more than one byte with flexcop behind */
@@ -62,7 +59,7 @@ static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 le
buf[0] = reg;
memcpy(&buf[1], v, len);
- /* deb("wr %02x: %02x", reg, v[0]); */
+ /* itd_dbg("wr %02x: %02x\n", reg, v[0]); */
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
printk(KERN_WARNING "itd1000 I2C write failed\n");
@@ -83,7 +80,7 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
if (i2c_transfer(state->i2c, msg, 2) != 2) {
- warn("itd1000 I2C read failed");
+ itd_warn("itd1000 I2C read failed\n");
return -EREMOTEIO;
}
return val;
@@ -127,14 +124,14 @@ static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
u8 bw = itd1000_read_reg(state, BW) & 0xf0;
- deb("symbol_rate = %d", symbol_rate);
+ itd_dbg("symbol_rate = %d\n", symbol_rate);
/* not sure what is that ? - starting to download the table */
itd1000_write_reg(state, CON1, con1 | (1 << 1));
for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
- deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
+ itd_dbg("symrate: index: %d pgaext: %x, bbgvmin: %x\n", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
itd1000_write_reg(state, PLLFH, pllfh | (itd1000_lpf_pga[i].pgaext << 4));
itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
itd1000_write_reg(state, BW, bw | (i & 0x0f));
@@ -182,7 +179,7 @@ static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
- deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+ itd_dbg("VCO: %dkHz: %d -> ADCOUT: %d %02x\n", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
if (adcout > 13) {
if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
@@ -232,7 +229,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
pllf = (u32) tmp;
state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
- deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
+ itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
itd1000_write_reg(state, PLLNL, plln & 0xff);
@@ -242,7 +239,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
if (freq_khz <= itd1000_fre_values[i].freq) {
- deb("fre_values: %d", i);
+ itd_dbg("fre_values: %d\n", i);
itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
for (j = 0; j < 9; j++)
itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
@@ -382,7 +379,7 @@ struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter
kfree(state);
return NULL;
}
- info("successfully identified (ID: %d)", i);
+ itd_info("successfully identified (ID: %d)\n", i);
memset(state->shadow, 0xff, sizeof(state->shadow));
for (i = 0x65; i < 0x9c; i++)
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a763ec75..6599b8f 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -50,7 +50,7 @@ static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret);
- return (ret != 1) ? -EFAULT : 0;
+ return (ret != 1) ? -EIO : 0;
}
static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg)
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 17f8cdf..507ccae 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -180,7 +180,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
int result = 0;
dprintk("enter %s\n", __func__);
- if (cmd->msg_len > 8)
+ if (cmd->msg_len > sizeof(cmd->msg))
return -EINVAL;
/* setup for DISEQC */
@@ -634,7 +634,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
struct s5h1420_state* state = fe->demodulator_priv;
int frequency_delta;
struct dvb_frontend_tune_settings fesettings;
- uint8_t clock_settting;
+ uint8_t clock_setting;
dprintk("enter %s\n", __func__);
@@ -684,19 +684,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
switch (state->fclk) {
default:
case 88000000:
- clock_settting = 80;
+ clock_setting = 80;
break;
case 86000000:
- clock_settting = 78;
+ clock_setting = 78;
break;
case 80000000:
- clock_settting = 72;
+ clock_setting = 72;
break;
case 59000000:
- clock_settting = 51;
+ clock_setting = 51;
break;
case 44000000:
- clock_settting = 36;
+ clock_setting = 36;
break;
}
dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c
index d70eee0..117a569 100644
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ b/drivers/media/dvb/frontends/stb0899_algo.c
@@ -358,6 +358,9 @@ static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
else
dataTime = 500;
+ /* clear previous failed END_LOOPVIT */
+ stb0899_read_reg(state, STB0899_VSTATUS);
+
stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */
while (1) {
/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index 37a222d..8408ef8 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -706,7 +706,7 @@ static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma
stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
for (i = 0; i < cmd->msg_len; i++) {
/* wait for FIFO empty */
- if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+ if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0)
return -ETIMEDOUT;
stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
@@ -1426,9 +1426,9 @@ static void stb0899_set_iterations(struct stb0899_state *state)
if (iter_scale > config->ldpc_max_iter)
iter_scale = config->ldpc_max_iter;
- reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+ reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER);
STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
- stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+ stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
}
static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
index 8e0cfad..0aa3962 100644
--- a/drivers/media/dvb/frontends/stv0288.c
+++ b/drivers/media/dvb/frontends/stv0288.c
@@ -127,6 +127,11 @@ static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
if ((srate < 1000000) || (srate > 45000000))
return -EINVAL;
+ stv0288_writeregI(state, 0x22, 0);
+ stv0288_writeregI(state, 0x23, 0);
+ stv0288_writeregI(state, 0x2b, 0xff);
+ stv0288_writeregI(state, 0x2c, 0xf7);
+
temp = (unsigned int)srate / 1000;
temp = temp * 32768;
@@ -461,6 +466,7 @@ static int stv0288_set_frontend(struct dvb_frontend *fe,
char tm;
unsigned char tda[3];
+ u8 reg, time_out = 0;
dprintk("%s : FE_SET_FRONTEND\n", __func__);
@@ -488,22 +494,29 @@ static int stv0288_set_frontend(struct dvb_frontend *fe,
/* Carrier lock control register */
stv0288_writeregI(state, 0x15, 0xc5);
- tda[0] = 0x2b; /* CFRM */
tda[2] = 0x0; /* CFRL */
- for (tm = -6; tm < 7;) {
+ for (tm = -9; tm < 7;) {
/* Viterbi status */
- if (stv0288_readreg(state, 0x24) & 0x8)
- break;
-
- tda[2] += 40;
- if (tda[2] < 40)
+ reg = stv0288_readreg(state, 0x24);
+ if (reg & 0x8)
+ break;
+ if (reg & 0x80) {
+ time_out++;
+ if (time_out > 10)
+ break;
+ tda[2] += 40;
+ if (tda[2] < 40)
+ tm++;
+ } else {
tm++;
+ tda[2] = 0;
+ time_out = 0;
+ }
tda[1] = (unsigned char)tm;
stv0288_writeregI(state, 0x2b, tda[1]);
stv0288_writeregI(state, 0x2c, tda[2]);
udelay(30);
}
-
state->tuner_frequency = c->frequency;
state->fec_inner = FEC_AUTO;
state->symbol_rate = c->symbol_rate;
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index 52d8712..ebda419 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -3463,9 +3463,15 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct stv090x_state *state = fe->demodulator_priv;
- u32 reg;
+ u32 reg, dstatus;
u8 search_state;
+ *status = 0;
+
+ dstatus = STV090x_READ_DEMOD(state, DSTATUS);
+ if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
reg = STV090x_READ_DEMOD(state, DMDSTATE);
search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
@@ -3474,41 +3480,30 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
case 1: /* first PLH detected */
default:
dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
- *status = 0;
break;
case 2: /* DVB-S2 mode */
dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
- reg = STV090x_READ_DEMOD(state, DSTATUS);
- if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+ if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
+ *status |= FE_HAS_VITERBI;
reg = STV090x_READ_DEMOD(state, TSSTATUS);
- if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
- *status = FE_HAS_SIGNAL |
- FE_HAS_CARRIER |
- FE_HAS_VITERBI |
- FE_HAS_SYNC |
- FE_HAS_LOCK;
- }
+ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
}
}
break;
case 3: /* DVB-S1/legacy mode */
dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
- reg = STV090x_READ_DEMOD(state, DSTATUS);
- if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+ if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+ *status |= FE_HAS_VITERBI;
reg = STV090x_READ_DEMOD(state, TSSTATUS);
- if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
- *status = FE_HAS_SIGNAL |
- FE_HAS_CARRIER |
- FE_HAS_VITERBI |
- FE_HAS_SYNC |
- FE_HAS_LOCK;
- }
+ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
}
}
break;
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 93f6a75..7f10594 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -206,15 +206,16 @@ static struct init_tab {
static struct pll_tab {
u32 clk_freq_khz;
u32 if_freq_khz;
- u8 m, n, p;
} pll_tab[] = {
- { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_3300, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
+ { TDA10048_CLK_4000, TDA10048_IF_36130 },
+ { TDA10048_CLK_16000, TDA10048_IF_3300 },
+ { TDA10048_CLK_16000, TDA10048_IF_3500 },
+ { TDA10048_CLK_16000, TDA10048_IF_3800 },
+ { TDA10048_CLK_16000, TDA10048_IF_4000 },
+ { TDA10048_CLK_16000, TDA10048_IF_4300 },
+ { TDA10048_CLK_16000, TDA10048_IF_4500 },
+ { TDA10048_CLK_16000, TDA10048_IF_5000 },
+ { TDA10048_CLK_16000, TDA10048_IF_36130 },
};
static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
@@ -460,9 +461,6 @@ static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
- state->pll_mfactor = pll_tab[i].m;
- state->pll_nfactor = pll_tab[i].n;
- state->pll_pfactor = pll_tab[i].p;
break;
}
}
@@ -781,6 +779,10 @@ static int tda10048_init(struct dvb_frontend *fe)
dprintk(1, "%s()\n", __func__);
+ /* PLL */
+ init_tab[4].data = (u8)(state->pll_mfactor);
+ init_tab[5].data = (u8)(state->pll_nfactor) | 0x40;
+
/* Apply register defaults */
for (i = 0; i < ARRAY_SIZE(init_tab); i++)
tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
@@ -1123,7 +1125,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
/* setup the state and clone the config */
memcpy(&state->config, config, sizeof(*config));
state->i2c = i2c;
- state->fwloaded = 0;
+ state->fwloaded = config->no_firmware;
state->bandwidth = BANDWIDTH_8_MHZ;
/* check if the demod is present */
@@ -1135,6 +1137,17 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
+ /* set pll */
+ if (config->set_pll) {
+ state->pll_mfactor = config->pll_m;
+ state->pll_nfactor = config->pll_n;
+ state->pll_pfactor = config->pll_p;
+ } else {
+ state->pll_mfactor = 10;
+ state->pll_nfactor = 3;
+ state->pll_pfactor = 0;
+ }
+
/* Establish any defaults the the user didn't pass */
tda10048_establish_defaults(&state->frontend);
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
index 8828cea..fb2ef5a 100644
--- a/drivers/media/dvb/frontends/tda10048.h
+++ b/drivers/media/dvb/frontends/tda10048.h
@@ -51,6 +51,7 @@ struct tda10048_config {
#define TDA10048_IF_4300 4300
#define TDA10048_IF_4500 4500
#define TDA10048_IF_4750 4750
+#define TDA10048_IF_5000 5000
#define TDA10048_IF_36130 36130
u16 dtv6_if_freq_khz;
u16 dtv7_if_freq_khz;
@@ -62,6 +63,13 @@ struct tda10048_config {
/* Disable I2C gate access */
u8 disable_gate_access;
+
+ bool no_firmware;
+
+ bool set_pll;
+ u8 pll_m;
+ u8 pll_p;
+ u8 pll_n;
};
#if defined(CONFIG_DVB_TDA10048) || \
diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile
index 98dc5cd..ec8116d 100644
--- a/drivers/media/dvb/mantis/Makefile
+++ b/drivers/media/dvb/mantis/Makefile
@@ -25,4 +25,4 @@ obj-$(CONFIG_MANTIS_CORE) += mantis_core.o
obj-$(CONFIG_DVB_MANTIS) += mantis.o
obj-$(CONFIG_DVB_HOPPER) += hopper.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c
index 1402062..71622f6 100644
--- a/drivers/media/dvb/mantis/hopper_cards.c
+++ b/drivers/media/dvb/mantis/hopper_cards.c
@@ -65,7 +65,7 @@ static int devs;
static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
{
- u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+ u32 stat = 0, mask = 0, lstat = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
@@ -80,7 +80,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
- mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+ lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
@@ -126,7 +126,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
}
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
- mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+ mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
}
if (stat & MANTIS_INT_I2CDONE) {
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c
index 330216f..3d70469 100644
--- a/drivers/media/dvb/mantis/mantis_ca.c
+++ b/drivers/media/dvb/mantis/mantis_ca.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c
index 05cbb9d..c2bb90b 100644
--- a/drivers/media/dvb/mantis/mantis_cards.c
+++ b/drivers/media/dvb/mantis/mantis_cards.c
@@ -73,7 +73,7 @@ static char *label[10] = {
static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
{
- u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+ u32 stat = 0, mask = 0, lstat = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
@@ -88,7 +88,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
- mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+ lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
@@ -134,7 +134,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
}
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
- mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+ mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
}
if (stat & MANTIS_INT_I2CDONE) {
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
index bd400d2..f2410cf 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -21,6 +21,7 @@
#ifndef __MANTIS_COMMON_H
#define __MANTIS_COMMON_H
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
@@ -122,11 +123,8 @@ struct mantis_pci {
unsigned int num;
/* RISC Core */
- u32 finished_block;
+ u32 busy_block;
u32 last_block;
- u32 line_bytes;
- u32 line_count;
- u32 risc_pos;
u8 *buf_cpu;
dma_addr_t buf_dma;
u32 *risc_cpu;
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c
index 46202a4..c61ca7d 100644
--- a/drivers/media/dvb/mantis/mantis_dma.c
+++ b/drivers/media/dvb/mantis/mantis_dma.c
@@ -43,13 +43,17 @@
#define RISC_IRQ (0x01 << 24)
#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
-#define RISC_FLUSH() (mantis->risc_pos = 0)
-#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))
+#define RISC_FLUSH(risc_pos) (risc_pos = 0)
+#define RISC_INSTR(risc_pos, opcode) (mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
#define MANTIS_BUF_SIZE (64 * 1024)
-#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4)
-#define MANTIS_BLOCK_COUNT (1 << 4)
-#define MANTIS_RISC_SIZE PAGE_SIZE
+#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE / 4)
+#define MANTIS_DMA_TR_BYTES (2 * 1024) /* upper limit: 4095 bytes. */
+#define MANTIS_BLOCK_COUNT (MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
+
+#define MANTIS_DMA_TR_UNITS (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
+/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
+#define MANTIS_RISC_SIZE PAGE_SIZE /* RISC program must fit here. */
int mantis_dma_exit(struct mantis_pci *mantis)
{
@@ -124,27 +128,6 @@ err:
return -ENOMEM;
}
-static inline int mantis_calc_lines(struct mantis_pci *mantis)
-{
- mantis->line_bytes = MANTIS_BLOCK_BYTES;
- mantis->line_count = MANTIS_BLOCK_COUNT;
-
- while (mantis->line_bytes > 4095) {
- mantis->line_bytes >>= 1;
- mantis->line_count <<= 1;
- }
-
- dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",
- MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);
-
- if (mantis->line_count > 255) {
- dprintk(MANTIS_ERROR, 1, "Buffer size error");
- return -EINVAL;
- }
-
- return 0;
-}
-
int mantis_dma_init(struct mantis_pci *mantis)
{
int err = 0;
@@ -158,12 +141,6 @@ int mantis_dma_init(struct mantis_pci *mantis)
goto err;
}
- err = mantis_calc_lines(mantis);
- if (err < 0) {
- dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
-
- goto err;
- }
return 0;
err:
@@ -174,31 +151,32 @@ EXPORT_SYMBOL_GPL(mantis_dma_init);
static inline void mantis_risc_program(struct mantis_pci *mantis)
{
u32 buf_pos = 0;
- u32 line;
+ u32 line, step;
+ u32 risc_pos;
dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
- RISC_FLUSH();
-
- dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
- mantis->line_count, mantis->line_bytes);
-
- for (line = 0; line < mantis->line_count; line++) {
- dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
- if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
- RISC_INSTR(RISC_WRITE |
- RISC_IRQ |
- RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +
- (MANTIS_BLOCK_COUNT - 1)) %
- MANTIS_BLOCK_COUNT) |
- mantis->line_bytes);
- } else {
- RISC_INSTR(RISC_WRITE | mantis->line_bytes);
- }
- RISC_INSTR(mantis->buf_dma + buf_pos);
- buf_pos += mantis->line_bytes;
+ RISC_FLUSH(risc_pos);
+
+ dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
+ MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES);
+
+ for (line = 0; line < MANTIS_BLOCK_COUNT; line++) {
+ for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) {
+ dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step);
+ if (step == 0) {
+ RISC_INSTR(risc_pos, RISC_WRITE |
+ RISC_IRQ |
+ RISC_STATUS(line) |
+ MANTIS_DMA_TR_BYTES);
+ } else {
+ RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES);
+ }
+ RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos);
+ buf_pos += MANTIS_DMA_TR_BYTES;
+ }
}
- RISC_INSTR(RISC_JUMP);
- RISC_INSTR(mantis->risc_dma);
+ RISC_INSTR(risc_pos, RISC_JUMP);
+ RISC_INSTR(risc_pos, mantis->risc_dma);
}
void mantis_dma_start(struct mantis_pci *mantis)
@@ -210,7 +188,7 @@ void mantis_dma_start(struct mantis_pci *mantis)
mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
mmwrite(0, MANTIS_DMA_CTL);
- mantis->last_block = mantis->finished_block = 0;
+ mantis->last_block = mantis->busy_block = 0;
mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
@@ -245,9 +223,9 @@ void mantis_dma_xfer(unsigned long data)
struct mantis_pci *mantis = (struct mantis_pci *) data;
struct mantis_hwconfig *config = mantis->hwconfig;
- while (mantis->last_block != mantis->finished_block) {
+ while (mantis->last_block != mantis->busy_block) {
dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
- mantis->last_block, mantis->finished_block);
+ mantis->last_block, mantis->busy_block);
(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
index 9f73c2c..36f2256 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -23,6 +23,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
index 5772ebb..672cf4d 100644
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
index 479086d..24fcdc6 100644
--- a/drivers/media/dvb/mantis/mantis_ioc.c
+++ b/drivers/media/dvb/mantis/mantis_ioc.c
@@ -24,6 +24,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c
index 5cb545b..2f188c0 100644
--- a/drivers/media/dvb/mantis/mantis_pcmcia.c
+++ b/drivers/media/dvb/mantis/mantis_pcmcia.c
@@ -23,6 +23,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
index f807c8b..18340da 100644
--- a/drivers/media/dvb/mantis/mantis_uart.c
+++ b/drivers/media/dvb/mantis/mantis_uart.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <asm/io.h>
#include <linux/signal.h>
#include <linux/sched.h>
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
index 26bc0cb..430ae84 100644
--- a/drivers/media/dvb/mantis/mantis_vp1034.c
+++ b/drivers/media/dvb/mantis/mantis_vp1034.c
@@ -21,6 +21,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c
index 38a436c..07aa887 100644
--- a/drivers/media/dvb/mantis/mantis_vp1041.c
+++ b/drivers/media/dvb/mantis/mantis_vp1041.c
@@ -51,7 +51,6 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x99 },
{ STB0899_DISF22RX , 0xa8 },
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig
index cec242b..64c8470 100644
--- a/drivers/media/dvb/ngene/Kconfig
+++ b/drivers/media/dvb/ngene/Kconfig
@@ -5,6 +5,8 @@ config DVB_NGENE
select DVB_STV6110x if !DVB_FE_CUSTOMISE
select DVB_STV090x if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_DRXK if !DVB_FE_CUSTOMISE
+ select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
---help---
Support for Micronas PCI express cards with nGene bridge.
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile
index 2bc9687..13ebeff 100644
--- a/drivers/media/dvb/ngene/Makefile
+++ b/drivers/media/dvb/ngene/Makefile
@@ -6,9 +6,9 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o
obj-$(CONFIG_DVB_NGENE) += ngene.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
# For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c
index fcf4be9..0564192 100644
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ b/drivers/media/dvb/ngene/ngene-cards.c
@@ -40,6 +40,8 @@
#include "lnbh24.h"
#include "lgdt330x.h"
#include "mt2131.h"
+#include "tda18271c2dd.h"
+#include "drxk.h"
/****************************************************************************/
@@ -83,6 +85,49 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
}
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct ngene_channel *chan = fe->sec_priv;
+ int status;
+
+ if (enable) {
+ down(&chan->dev->pll_mutex);
+ status = chan->gate_ctrl(fe, 1);
+ } else {
+ status = chan->gate_ctrl(fe, 0);
+ up(&chan->dev->pll_mutex);
+ }
+ return status;
+}
+
+static int tuner_attach_tda18271(struct ngene_channel *chan)
+{
+ struct i2c_adapter *i2c;
+ struct dvb_frontend *fe;
+
+ i2c = &chan->dev->channel[0].i2c_adapter;
+ if (chan->fe->ops.i2c_gate_ctrl)
+ chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
+ fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
+ if (chan->fe->ops.i2c_gate_ctrl)
+ chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
+ if (!fe) {
+ printk(KERN_ERR "No TDA18271 found!\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int tuner_attach_probe(struct ngene_channel *chan)
+{
+ if (chan->demod_type == 0)
+ return tuner_attach_stv6110(chan);
+ if (chan->demod_type == 1)
+ return tuner_attach_tda18271(chan);
+ return -EINVAL;
+}
+
static int demod_attach_stv0900(struct ngene_channel *chan)
{
struct i2c_adapter *i2c;
@@ -130,6 +175,60 @@ static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
up(&chan->dev->pll_mutex);
}
+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = 1 } };
+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+ u16 reg, u8 *val)
+{
+ u8 msg[2] = {reg>>8, reg&0xff};
+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+ .buf = msg, .len = 2},
+ {.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = 1} };
+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int port_has_stv0900(struct i2c_adapter *i2c, int port)
+{
+ u8 val;
+ if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
+ return 0;
+ return 1;
+}
+
+static int port_has_drxk(struct i2c_adapter *i2c, int port)
+{
+ u8 val;
+
+ if (i2c_read(i2c, 0x29+port, &val) < 0)
+ return 0;
+ return 1;
+}
+
+static int demod_attach_drxk(struct ngene_channel *chan,
+ struct i2c_adapter *i2c)
+{
+ struct drxk_config config;
+
+ memset(&config, 0, sizeof(config));
+ config.adr = 0x29 + (chan->number ^ 2);
+
+ chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2);
+ if (!chan->fe) {
+ printk(KERN_ERR "No DRXK found!\n");
+ return -ENODEV;
+ }
+ chan->fe->sec_priv = chan;
+ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
+ chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+ return 0;
+}
+
static int cineS2_probe(struct ngene_channel *chan)
{
struct i2c_adapter *i2c;
@@ -144,43 +243,42 @@ static int cineS2_probe(struct ngene_channel *chan)
else
i2c = &chan->dev->channel[1].i2c_adapter;
- fe_conf = chan->dev->card_info->fe_config[chan->number];
- i2c_msg.addr = fe_conf->address;
-
- /* probe demod */
- i2c_msg.len = 2;
- buf[0] = 0xf1;
- buf[1] = 0x00;
- rc = i2c_transfer(i2c, &i2c_msg, 1);
- if (rc != 1)
- return -ENODEV;
-
- /* demod found, attach it */
- rc = demod_attach_stv0900(chan);
- if (rc < 0 || chan->number < 2)
- return rc;
-
- /* demod #2: reprogram outputs DPN1 & DPN2 */
- i2c_msg.len = 3;
- buf[0] = 0xf1;
- switch (chan->number) {
- case 2:
- buf[1] = 0x5c;
- buf[2] = 0xc2;
- break;
- case 3:
- buf[1] = 0x61;
- buf[2] = 0xcc;
- break;
- default:
+ if (port_has_stv0900(i2c, chan->number)) {
+ chan->demod_type = 0;
+ fe_conf = chan->dev->card_info->fe_config[chan->number];
+ /* demod found, attach it */
+ rc = demod_attach_stv0900(chan);
+ if (rc < 0 || chan->number < 2)
+ return rc;
+
+ /* demod #2: reprogram outputs DPN1 & DPN2 */
+ i2c_msg.addr = fe_conf->address;
+ i2c_msg.len = 3;
+ buf[0] = 0xf1;
+ switch (chan->number) {
+ case 2:
+ buf[1] = 0x5c;
+ buf[2] = 0xc2;
+ break;
+ case 3:
+ buf[1] = 0x61;
+ buf[2] = 0xcc;
+ break;
+ default:
+ return -ENODEV;
+ }
+ rc = i2c_transfer(i2c, &i2c_msg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
+ return -EIO;
+ }
+ } else if (port_has_drxk(i2c, chan->number^2)) {
+ chan->demod_type = 1;
+ demod_attach_drxk(chan, i2c);
+ } else {
+ printk(KERN_ERR "No demod found on chan %d\n", chan->number);
return -ENODEV;
}
- rc = i2c_transfer(i2c, &i2c_msg, 1);
- if (rc != 1) {
- printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
- return -EIO;
- }
-
return 0;
}
@@ -306,7 +404,7 @@ static struct ngene_info ngene_info_satixS2v2 = {
.io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
NGENE_IO_TSOUT},
.demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
- .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+ .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
.fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
.tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
.lnb = {0x0a, 0x08, 0x0b, 0x09},
@@ -321,7 +419,7 @@ static struct ngene_info ngene_info_cineS2v5 = {
.io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
NGENE_IO_TSOUT},
.demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
- .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+ .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
.fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
.tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
.lnb = {0x0a, 0x08, 0x0b, 0x09},
@@ -331,13 +429,13 @@ static struct ngene_info ngene_info_cineS2v5 = {
};
-static struct ngene_info ngene_info_duoFlexS2 = {
+static struct ngene_info ngene_info_duoFlex = {
.type = NGENE_SIDEWINDER,
- .name = "Digital Devices DuoFlex S2 miniPCIe",
+ .name = "Digital Devices DuoFlex PCIe or miniPCIe",
.io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
NGENE_IO_TSOUT},
.demod_attach = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
- .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+ .tuner_attach = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
.fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
.tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
.lnb = {0x0a, 0x08, 0x0b, 0x09},
@@ -385,8 +483,8 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
- NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
- NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
+ NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
+ NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
NGENE_ID(0x1461, 0x062e, ngene_info_m780),
{0}
};
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index 6927c72..f129a93 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -41,7 +41,7 @@
#include "ngene.h"
-static int one_adapter = 1;
+static int one_adapter;
module_param(one_adapter, int, 0444);
MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
@@ -461,7 +461,7 @@ static u8 TSFeatureDecoderSetup[8 * 5] = {
0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */
0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */
- 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */
+ 0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */
0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
};
@@ -507,7 +507,7 @@ void FillTSBuffer(void *Buffer, int Length, u32 Flags)
{
u32 *ptr = Buffer;
- memset(Buffer, 0xff, Length);
+ memset(Buffer, TS_FILLER, Length);
while (Length > 0) {
if (Flags & DF_SWAP32)
*ptr = 0x471FFF10;
@@ -1443,6 +1443,9 @@ static void release_channel(struct ngene_channel *chan)
chan->ci_dev = NULL;
}
+ if (chan->fe2)
+ dvb_unregister_frontend(chan->fe2);
+
if (chan->fe) {
dvb_unregister_frontend(chan->fe);
dvb_frontend_detach(chan->fe);
@@ -1534,6 +1537,14 @@ static int init_channel(struct ngene_channel *chan)
goto err;
chan->has_demux = true;
}
+ if (chan->fe2) {
+ if (dvb_register_frontend(adapter, chan->fe2) < 0)
+ goto err;
+ chan->fe2->tuner_priv = chan->fe->tuner_priv;
+ memcpy(&chan->fe2->ops.tuner_ops,
+ &chan->fe->ops.tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+ }
if (chan->has_demux) {
ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
@@ -1571,11 +1582,18 @@ static int init_channels(struct ngene *dev)
return 0;
}
+static struct cxd2099_cfg cxd_cfg = {
+ .bitrate = 62000,
+ .adr = 0x40,
+ .polarity = 0,
+ .clock_mode = 0,
+};
+
static void cxd_attach(struct ngene *dev)
{
struct ngene_ci *ci = &dev->ci;
- ci->en = cxd2099_attach(0x40, dev, &dev->channel[0].i2c_adapter);
+ ci->en = cxd2099_attach(&cxd_cfg, dev, &dev->channel[0].i2c_adapter);
ci->dev = dev;
return;
}
diff --git a/drivers/media/dvb/ngene/ngene-dvb.c b/drivers/media/dvb/ngene/ngene-dvb.c
index 0b49432..fcb16a6 100644
--- a/drivers/media/dvb/ngene/ngene-dvb.c
+++ b/drivers/media/dvb/ngene/ngene-dvb.c
@@ -118,6 +118,16 @@ static void swap_buffer(u32 *p, u32 len)
}
}
+/* start of filler packet */
+static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
+
+/* #define DEBUG_CI_XFER */
+#ifdef DEBUG_CI_XFER
+static u32 ok;
+static u32 overflow;
+static u32 stripped;
+#endif
+
void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
{
struct ngene_channel *chan = priv;
@@ -126,21 +136,41 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
if (flags & DF_SWAP32)
swap_buffer(buf, len);
+
if (dev->ci.en && chan->number == 2) {
- if (dvb_ringbuffer_free(&dev->tsin_rbuf) > len) {
- dvb_ringbuffer_write(&dev->tsin_rbuf, buf, len);
- wake_up_interruptible(&dev->tsin_rbuf.queue);
+ while (len >= 188) {
+ if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
+ if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
+ dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
+ wake_up(&dev->tsin_rbuf.queue);
+#ifdef DEBUG_CI_XFER
+ ok++;
+#endif
+ }
+#ifdef DEBUG_CI_XFER
+ else
+ overflow++;
+#endif
+ }
+#ifdef DEBUG_CI_XFER
+ else
+ stripped++;
+
+ if (ok % 100 == 0 && overflow)
+ printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
+#endif
+ buf += 188;
+ len -= 188;
}
- return 0;
+ return NULL;
}
- if (chan->users > 0) {
+
+ if (chan->users > 0)
dvb_dmx_swfilter(&chan->demux, buf, len);
- }
+
return NULL;
}
-u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 };
-
void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
{
struct ngene_channel *chan = priv;
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
index 40fce9e..5443dc0 100644
--- a/drivers/media/dvb/ngene/ngene.h
+++ b/drivers/media/dvb/ngene/ngene.h
@@ -641,8 +641,11 @@ struct ngene_channel {
int mode;
bool has_adapter;
bool has_demux;
+ int demod_type;
+ int (*gate_ctrl)(struct dvb_frontend *, int);
struct dvb_frontend *fe;
+ struct dvb_frontend *fe2;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvbnet;
@@ -786,6 +789,8 @@ struct ngene {
u8 uart_rbuf[UART_RBUF_LEN];
int uart_rp, uart_wp;
+#define TS_FILLER 0x6f
+
u8 *tsout_buf;
#define TSOUT_BUF_SIZE (512*188*8)
struct dvb_ringbuffer tsout_rbuf;
@@ -852,7 +857,7 @@ struct ngene_info {
};
#ifdef NGENE_V4L
-struct ngene_format{
+struct ngene_format {
char *name;
int fourcc; /* video4linux 2 */
int btformat; /* BT848_COLOR_FMT_* */
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
index 7ac1287..7008223 100644
--- a/drivers/media/dvb/pluto2/Makefile
+++ b/drivers/media/dvb/pluto2/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 7cb79ec..80fb510 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -26,6 +26,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/media/dvb/pt1/Makefile b/drivers/media/dvb/pt1/Makefile
index a66da17..d80d8e8 100644
--- a/drivers/media/dvb/pt1/Makefile
+++ b/drivers/media/dvb/pt1/Makefile
@@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o
obj-$(CONFIG_DVB_PT1) += earth-pt1.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
index c54140b..f233b57 100644
--- a/drivers/media/dvb/siano/Makefile
+++ b/drivers/media/dvb/siano/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index af121db..680c781 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -19,6 +19,7 @@
#include "sms-cards.h"
#include "smsir.h"
+#include <linux/module.h>
static int sms_dbg;
module_param_named(cards_dbg, sms_dbg, int, 0644);
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index 78765ed..7331e84 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -1147,7 +1147,7 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
if (!client) {
sms_err("bad parameter.");
- return -EFAULT;
+ return -EINVAL;
}
registered_client = smscore_find_client(coredev, data_type, id);
if (registered_client == client)
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
index 8ecadec..c592ae0 100644
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -22,7 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __SMS_CORE_API_H__
#define __SMS_CORE_API_H__
-#include <linux/version.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/mm.h>
diff --git a/drivers/media/dvb/siano/smsendian.c b/drivers/media/dvb/siano/smsendian.c
index 457b6d0..e2657c2 100644
--- a/drivers/media/dvb/siano/smsendian.c
+++ b/drivers/media/dvb/siano/smsendian.c
@@ -19,6 +19,7 @@
****************************************************************/
+#include <linux/export.h>
#include <asm/byteorder.h>
#include "smsendian.h"
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
index e57d38b..91f8c82 100644
--- a/drivers/media/dvb/siano/smssdio.c
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -39,6 +39,7 @@
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
#include "smscoreapi.h"
#include "sms-cards.h"
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 3d2867d..027550d 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <linux/usb.h>
#include <linux/firmware.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "smscoreapi.h"
#include "sms-cards.h"
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index 8a4d5bb..f6e8693 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -17,5 +17,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index cdd31ca..ee8ee1d 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -25,6 +25,8 @@
* the project's page is at http://www.linuxtv.org/
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/delay.h>
@@ -253,7 +255,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
switch (av7110->current_input) {
case 1:
- dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+ dprintk(1, "switching SAA7113 to Analog Tuner Input\n");
msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
@@ -263,7 +265,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
- dprintk(1, "setting band in demodulator failed.\n");
+ dprintk(1, "setting band in demodulator failed\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
@@ -272,17 +274,17 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
break;
case 2:
- dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+ dprintk(1, "switching SAA7113 to Video AV CVBS Input\n");
if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
break;
case 3:
- dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+ dprintk(1, "switching SAA7113 to Video AV Y/C Input\n");
if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
break;
default:
- dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
+ dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input\n");
}
} else {
adswitch = 0;
@@ -299,7 +301,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
- dprintk(1, "setting band in demodulator failed.\n");
+ dprintk(1, "setting band in demodulator failed\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -413,7 +415,7 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
- dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
+ dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x\n", f->frequency);
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
@@ -429,7 +431,7 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
- dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
+ dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x\n", f->frequency);
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
@@ -689,12 +691,12 @@ int av7110_init_analog_module(struct av7110 *av7110)
if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
- printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
+ pr_info("DVB-C analog module @ card %d detected, initializing MSP3400\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP34x0;
} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
- printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
+ pr_info("DVB-C analog module @ card %d detected, initializing MSP3415\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP34x5;
} else
@@ -715,7 +717,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
- INFO(("saa7113 not accessible.\n"));
+ pr_info("saa7113 not accessible\n");
} else {
u8 *i = saa7113_init_regs;
@@ -733,7 +735,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
/* setup for DVB by default */
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
- dprintk(1, "setting band in demodulator failed.\n");
+ dprintk(1, "setting band in demodulator failed\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -797,7 +799,7 @@ int av7110_init_v4l(struct av7110 *av7110)
ret = saa7146_vv_init(dev, vv_data);
if (ret) {
- ERR(("cannot init capture device. skipping.\n"));
+ ERR("cannot init capture device. skipping\n");
return -ENODEV;
}
vv_data->ops.vidioc_enum_input = vidioc_enum_input;
@@ -814,12 +816,12 @@ int av7110_init_v4l(struct av7110 *av7110)
vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
- ERR(("cannot register capture device. skipping.\n"));
+ ERR("cannot register capture device. skipping\n");
saa7146_vv_release(dev);
return -ENODEV;
}
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
+ ERR("cannot register vbi v4l2 device. skipping\n");
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index e957d76..78d32f7 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -33,6 +33,8 @@
* the project's page is at http://www.linuxtv.org/
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "budget.h"
#include "stv0299.h"
#include "stb0899_drv.h"
@@ -149,7 +151,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 1\n");
+ pr_info("cam ejected 1\n");
}
return result;
}
@@ -168,7 +170,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 2\n");
+ pr_info("cam ejected 2\n");
}
return result;
}
@@ -187,7 +189,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 3\n");
+ pr_info("cam ejected 3\n");
return -ETIMEDOUT;
}
return result;
@@ -207,7 +209,7 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 5\n");
+ pr_info("cam ejected 5\n");
}
return result;
}
@@ -289,7 +291,7 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
if (saa7146_read(saa, PSR) & MASK_06) {
if (budget_av->slot_status == SLOTSTATUS_NONE) {
budget_av->slot_status = SLOTSTATUS_PRESENT;
- printk(KERN_INFO "budget-av: cam inserted A\n");
+ pr_info("cam inserted A\n");
}
}
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
@@ -306,11 +308,11 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
budget_av->slot_status = SLOTSTATUS_PRESENT;
- printk(KERN_INFO "budget-av: cam inserted B\n");
+ pr_info("cam inserted B\n");
} else if (result < 0) {
if (budget_av->slot_status != SLOTSTATUS_NONE) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 5\n");
+ pr_info("cam ejected 5\n");
return 0;
}
}
@@ -365,11 +367,11 @@ static int ciintf_init(struct budget_av *budget_av)
if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
&budget_av->ca, 0, 1)) != 0) {
- printk(KERN_ERR "budget-av: ci initialisation failed.\n");
+ pr_err("ci initialisation failed\n");
goto error;
}
- printk(KERN_INFO "budget-av: ci interface initialised.\n");
+ pr_info("ci interface initialised\n");
return 0;
error:
@@ -896,7 +898,6 @@ static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x8c },
{ STB0899_DISF22RX , 0x9a },
@@ -1197,6 +1198,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBC_KNC1 0x0020
#define SUBID_DVBC_KNC1_PLUS 0x0021
#define SUBID_DVBC_KNC1_MK3 0x0022
+#define SUBID_DVBC_KNC1_TDA10024 0x0028
#define SUBID_DVBC_KNC1_PLUS_MK3 0x0023
#define SUBID_DVBC_CINERGY1200 0x1156
#define SUBID_DVBC_CINERGY1200_MK3 0x1176
@@ -1316,6 +1318,7 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_EASYWATCH_MK3:
case SUBID_DVBC_CINERGY1200_MK3:
case SUBID_DVBC_KNC1_MK3:
+ case SUBID_DVBC_KNC1_TDA10024:
case SUBID_DVBC_KNC1_PLUS_MK3:
budget_av->reinitialise_demod = 1;
budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
@@ -1343,8 +1346,7 @@ static void frontend_init(struct budget_av *budget_av)
}
if (fe == NULL) {
- printk(KERN_ERR "budget-av: A frontend driver was not found "
- "for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
saa->pci->vendor,
saa->pci->device,
saa->pci->subsystem_vendor,
@@ -1356,7 +1358,7 @@ static void frontend_init(struct budget_av *budget_av)
if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
budget_av->budget.dvb_frontend)) {
- printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+ pr_err("Frontend registration failed!\n");
dvb_frontend_detach(budget_av->budget.dvb_frontend);
budget_av->budget.dvb_frontend = NULL;
}
@@ -1414,7 +1416,7 @@ static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
- dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
+ dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
if (i->index >= KNC1_INPUTS)
return -EINVAL;
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
@@ -1428,7 +1430,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
*i = budget_av->cur_input;
- dprintk(1, "VIDIOC_G_INPUT %d.\n", *i);
+ dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
return 0;
}
@@ -1437,7 +1439,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
- dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
+ dprintk(1, "VIDIOC_S_INPUT %d\n", input);
return saa7113_setinput(budget_av, input);
}
@@ -1476,7 +1478,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
if (0 != saa7146_vv_init(dev, &vv_data)) {
/* fixme: proper cleanup here */
- ERR(("cannot init vv subsystem.\n"));
+ ERR("cannot init vv subsystem\n");
return err;
}
vv_data.ops.vidioc_enum_input = vidioc_enum_input;
@@ -1485,7 +1487,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
/* fixme: proper cleanup here */
- ERR(("cannot register capture v4l2 device.\n"));
+ ERR("cannot register capture v4l2 device\n");
saa7146_vv_release(dev);
return err;
}
@@ -1502,13 +1504,12 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
mac = budget_av->budget.dvb_adapter.proposed_mac;
if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
- printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+ pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
budget_av->budget.dvb_adapter.num);
memset(mac, 0, 6);
} else {
- printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- budget_av->budget.dvb_adapter.num,
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ pr_info("KNC1-%d: MAC addr = %pM\n",
+ budget_av->budget.dvb_adapter.num, mac);
}
budget_av->budget.dvb_adapter.priv = budget_av;
@@ -1558,6 +1559,7 @@ MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
+MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
@@ -1587,6 +1589,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
+ MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 926f299..ca02e97 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1053,7 +1053,6 @@ static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x8c },
{ STB0899_DISF22RX , 0x9a },
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 37666d4..37d02fe 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -110,6 +110,7 @@ static int start_ts_capture(struct budget *budget)
break;
case BUDGET_CIN1200C_MK3:
case BUDGET_KNC1C_MK3:
+ case BUDGET_KNC1C_TDA10024:
case BUDGET_KNC1CP_MK3:
if (budget->video_port == BUDGET_VIDEO_PORTA) {
saa7146_write(dev, DD1_INIT, 0x06000200);
@@ -434,6 +435,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
case BUDGET_KNC1CP:
case BUDGET_CIN1200C:
case BUDGET_KNC1C_MK3:
+ case BUDGET_KNC1C_TDA10024:
case BUDGET_KNC1CP_MK3:
case BUDGET_CIN1200C_MK3:
budget->buffer_width = TS_WIDTH_DVBC;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 3ad0c67..3d8a806 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -104,6 +104,7 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_KNC1C_MK3 16
#define BUDGET_KNC1CP_MK3 17
#define BUDGET_KNC1S2 18
+#define BUDGET_KNC1C_TDA10024 19
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
index 7dd54b3..32d4315 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -85,6 +85,35 @@ static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC)
return 0;
}
+int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
+{
+ u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
+ 0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
+ 0x1d, 0x36, 0x64, 0x78};
+ u8 data[20];
+ int i;
+
+ memcpy(data, encodedMAC, 20);
+
+ for (i = 0; i < 20; i++)
+ data[i] ^= xor[i];
+ for (i = 0; i < 10; i++)
+ data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
+ >> ((data[2 * i + 1] >> 6) & 3);
+
+ if (check_mac_tt(data))
+ return -ENODEV;
+
+ decodedMAC[0] = data[2];
+ decodedMAC[1] = data[1];
+ decodedMAC[2] = data[0];
+ decodedMAC[3] = data[6];
+ decodedMAC[4] = data[5];
+ decodedMAC[5] = data[4];
+ return 0;
+}
+EXPORT_SYMBOL(ttpci_eeprom_decode_mac);
+
static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
{
int ret;
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h
index e2dc6cf..dcc33d5 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.h
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.h
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/i2c.h>
+extern int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC);
extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac);
#endif
diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile
index fbe2b95..8d6c4ac 100644
--- a/drivers/media/dvb/ttusb-budget/Makefile
+++ b/drivers/media/dvb/ttusb-budget/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile
index 2d70a82..ed28b53 100644
--- a/drivers/media/dvb/ttusb-dec/Makefile
+++ b/drivers/media/dvb/ttusb-dec/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 21260aa..852870b 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -154,6 +154,9 @@ static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struc
0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
+ if (cmd->msg_len > sizeof(b) - 4)
+ return -EINVAL;
+
memcpy(&b[4], cmd->msg, cmd->msg_len);
state->config->send_command(fe, 0x72,
diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h
index 1a45a5d..d84ad9d 100644
--- a/drivers/media/radio/wl128x/fmdrv.h
+++ b/drivers/media/radio/wl128x/fmdrv.h
@@ -28,14 +28,11 @@
#include <sound/core.h>
#include <sound/initval.h>
#include <linux/timer.h>
-#include <linux/version.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
-#define FM_DRV_VERSION "0.10"
-/* Should match with FM_DRV_VERSION */
-#define FM_DRV_RADIO_VERSION KERNEL_VERSION(0, 0, 1)
+#define FM_DRV_VERSION "0.1.1"
#define FM_DRV_NAME "ti_fmdrv"
#define FM_DRV_CARD_SHORT_NAME "TI FM Radio"
#define FM_DRV_CARD_LONG_NAME "Texas Instruments FM Radio"
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 8701072..4f5c43d 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -28,6 +28,8 @@
*
*/
+#include <linux/export.h>
+
#include "fmdrv.h"
#include "fmdrv_v4l2.h"
#include "fmdrv_common.h"
@@ -84,12 +86,14 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
ret = copy_from_user(&rds, buf, sizeof(rds));
fmdbg("(%d)type: %d, text %s, af %d\n",
ret, rds.text_type, rds.text, rds.af_freq);
+ if (ret)
+ return -EFAULT;
fmdev = video_drvdata(file);
fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
fm_tx_set_af(fmdev, rds.af_freq);
- return 0;
+ return sizeof(rds);
}
static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
@@ -175,7 +179,6 @@ static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
sizeof(capability->card));
sprintf(capability->bus_info, "UART");
- capability->version = FM_DRV_RADIO_VERSION;
capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
@@ -191,7 +194,7 @@ static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- ctrl->cur.val = fm_tx_get_tune_cap_val(fmdev);
+ ctrl->val = fm_tx_get_tune_cap_val(fmdev);
break;
default:
fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
@@ -403,7 +406,7 @@ static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
struct v4l2_modulator *mod)
{
- struct fmdev *fmdev = video_drvdata(file);;
+ struct fmdev *fmdev = video_drvdata(file);
if (mod->index != 0)
return -EINVAL;
@@ -558,7 +561,7 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
255, 1, 255);
if (ctrl)
- ctrl->is_volatile = 1;
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
return 0;
}
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
index 5c7f2f7..bd22223 100644
--- a/drivers/media/video/au0828/Makefile
+++ b/drivers/media/video/au0828/Makefile
@@ -2,8 +2,8 @@ au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-vid
obj-$(CONFIG_VIDEO_AU0828) += au0828.o
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
index 39fc923..d6adee6 100644
--- a/drivers/media/video/au0828/au0828-cards.c
+++ b/drivers/media/video/au0828/au0828-cards.c
@@ -36,6 +36,11 @@ void hvr950q_cs5340_audio(void *priv, int enable)
au0828_clear(dev, REG_000, 0x10);
}
+/*
+ * WARNING: There's a quirks table at sound/usb/quirks-table.h
+ * that should also be updated every time a new device with V4L2 support
+ * is added here.
+ */
struct au0828_board au0828_boards[] = {
[AU0828_BOARD_UNKNOWN] = {
.name = "Unknown board",
@@ -162,11 +167,14 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
switch (tv.model) {
case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+ case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+ case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+ case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
break;
@@ -324,6 +332,10 @@ struct usb_device_id au0828_usb_id_table[] = {
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
{ USB_DEVICE(0x2040, 0x8200),
.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
+ { USB_DEVICE(0x2040, 0x7260),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+ { USB_DEVICE(0x2040, 0x7213),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ },
};
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index ca342e4..1e4ce50 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -292,3 +292,4 @@ module_exit(au0828_exit);
MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index 9945aaf..eab0641 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -33,7 +33,6 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/suspend.h>
-#include <linux/version.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-chip-ident.h>
@@ -43,8 +42,6 @@
static DEFINE_MUTEX(au0828_sysfs_lock);
-#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
-
/* ------------------------------------------------------------------
Videobuf operations
------------------------------------------------------------------*/
@@ -1254,8 +1251,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->card, dev->board.name, sizeof(cap->card));
strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
- cap->version = AU0828_VERSION_CODE;
-
/*set the device capabilities */
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VBI_CAPTURE |
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
index e415f6f..3f9a2b2 100644
--- a/drivers/media/video/bt8xx/Makefile
+++ b/drivers/media/video/bt8xx/Makefile
@@ -8,6 +8,6 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
obj-$(CONFIG_VIDEO_BT848) += bttv.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 3c9e6c7..5939021 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -25,6 +25,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kmod.h>
@@ -2892,13 +2894,10 @@ void __devinit bttv_idcard(struct bttv *btv)
{
unsigned int gpiobits;
int i,type;
- unsigned short tmp;
/* read PCI subsystem ID */
- pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_ID, &tmp);
- btv->cardid = tmp << 16;
- pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_VENDOR_ID, &tmp);
- btv->cardid |= tmp;
+ btv->cardid = btv->c.pci->subsystem_device << 16;
+ btv->cardid |= btv->c.pci->subsystem_vendor;
if (0 != btv->cardid && 0xffffffff != btv->cardid) {
/* look for the card */
@@ -2908,19 +2907,17 @@ void __devinit bttv_idcard(struct bttv *btv)
if (type != -1) {
/* found it */
- printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
- "PCI subsystem ID is %04x:%04x\n",
- btv->c.nr,cards[type].name,cards[type].cardnr,
- btv->cardid & 0xffff,
- (btv->cardid >> 16) & 0xffff);
+ pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
+ btv->c.nr, cards[type].name, cards[type].cardnr,
+ btv->cardid & 0xffff,
+ (btv->cardid >> 16) & 0xffff);
btv->c.type = cards[type].cardnr;
} else {
/* 404 */
- printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
- btv->c.nr, btv->cardid & 0xffff,
- (btv->cardid >> 16) & 0xffff);
- printk(KERN_DEBUG "please mail id, board name and "
- "the correct card= insmod option to linux-media@vger.kernel.org\n");
+ pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
+ btv->c.nr, btv->cardid & 0xffff,
+ (btv->cardid >> 16) & 0xffff);
+ pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
}
}
@@ -2929,10 +2926,10 @@ void __devinit bttv_idcard(struct bttv *btv)
btv->c.type=card[btv->c.nr];
/* print which card config we are using */
- printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr,
- bttv_tvcards[btv->c.type].name, btv->c.type,
- card[btv->c.nr] < bttv_num_tvcards
- ? "insmod option" : "autodetected");
+ pr_info("%d: using: %s [card=%d,%s]\n",
+ btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
+ card[btv->c.nr] < bttv_num_tvcards
+ ? "insmod option" : "autodetected");
/* overwrite gpio stuff ?? */
if (UNSET == audioall && UNSET == audiomux[0])
@@ -2951,12 +2948,13 @@ void __devinit bttv_idcard(struct bttv *btv)
}
}
bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
- printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
- btv->c.nr,bttv_tvcards[btv->c.type].gpiomask);
+ pr_info("%d: gpio config override: mask=0x%x, mux=",
+ btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
- printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
+ pr_cont("%s0x%x",
+ i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
}
- printk("\n");
+ pr_cont("\n");
}
/*
@@ -2977,8 +2975,8 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
if (-1 != type) {
btv->c.type = type;
- printk("bttv%d: detected by eeprom: %s [card=%d]\n",
- btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
+ pr_info("%d: detected by eeprom: %s [card=%d]\n",
+ btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
}
}
@@ -3022,7 +3020,7 @@ static void flyvideo_gpio(struct bttv *btv)
tuner_type = 3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
break;
default:
- printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+ pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
break;
}
@@ -3039,13 +3037,13 @@ static void flyvideo_gpio(struct bttv *btv)
if (is_capture_only)
tuner_type = TUNER_ABSENT; /* No tuner present */
- printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
- btv->c.nr, has_radio ? "yes" : "no ",
- has_remote ? "yes" : "no ", tuner_type, gpio);
- printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n",
- btv->c.nr, is_lr90 ? "yes" : "no ",
- has_tda9820_tda9821 ? "yes" : "no ",
- is_capture_only ? "yes" : "no ");
+ pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+ btv->c.nr, has_radio ? "yes" : "no",
+ has_remote ? "yes" : "no", tuner_type, gpio);
+ pr_info("%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n",
+ btv->c.nr, is_lr90 ? "yes" : "no",
+ has_tda9820_tda9821 ? "yes" : "no",
+ is_capture_only ? "yes" : "no");
if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
btv->tuner_type = tuner_type;
@@ -3094,12 +3092,11 @@ static void miro_pinnacle_gpio(struct bttv *btv)
if (btv->c.type == BTTV_BOARD_PINNACLE)
btv->c.type = BTTV_BOARD_PINNACLEPRO;
}
- printk(KERN_INFO
- "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
- btv->c.nr, id+1, btv->tuner_type,
- !btv->has_radio ? "no" :
- (btv->has_matchbox ? "matchbox" : "fmtuner"),
- (-1 == msp) ? "no" : "yes");
+ pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+ btv->c.nr, id+1, btv->tuner_type,
+ !btv->has_radio ? "no" :
+ (btv->has_matchbox ? "matchbox" : "fmtuner"),
+ (-1 == msp) ? "no" : "yes");
} else {
/* new cards with microtune tuner */
id = 63 - id;
@@ -3141,9 +3138,8 @@ static void miro_pinnacle_gpio(struct bttv *btv)
}
if (-1 != msp)
btv->c.type = BTTV_BOARD_PINNACLEPRO;
- printk(KERN_INFO
- "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
- btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
+ pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
+ btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
btv->tuner_type = TUNER_MT2032;
}
}
@@ -3205,7 +3201,7 @@ static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
static void init_lmlbt4x(struct bttv *btv)
{
- printk(KERN_DEBUG "LMLBT4x init\n");
+ pr_debug("LMLBT4x init\n");
btwrite(0x000000, BT848_GPIO_REG_INP);
gpio_inout(0xffffff, 0x0006C0);
gpio_write(0x000000);
@@ -3249,7 +3245,7 @@ static void bttv_reset_audio(struct bttv *btv)
return;
if (bttv_debug)
- printk("bttv%d: BT878A ARESET\n",btv->c.nr);
+ pr_debug("%d: BT878A ARESET\n", btv->c.nr);
btwrite((1<<7), 0x058);
udelay(10);
btwrite( 0, 0x058);
@@ -3352,7 +3348,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
case BTTV_BOARD_MAGICTVIEW061:
if (btv->cardid == 0x3002144f) {
btv->has_radio=1;
- printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr);
+ pr_info("%d: radio detected by subsystem id (CPH05x)\n",
+ btv->c.nr);
}
break;
case BTTV_BOARD_STB2:
@@ -3441,17 +3438,16 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->tuner_type = tuner[btv->c.nr];
if (btv->tuner_type == TUNER_ABSENT)
- printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr);
- else if(btv->tuner_type == UNSET)
- printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr);
+ pr_info("%d: tuner absent\n", btv->c.nr);
+ else if (btv->tuner_type == UNSET)
+ pr_warn("%d: tuner type unset\n", btv->c.nr);
else
- printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr,
- btv->tuner_type);
+ pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
if (autoload != UNSET) {
- printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr);
- printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr);
- printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr);
+ pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
+ pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
+ btv->c.nr);
}
if (UNSET == btv->tuner_type)
@@ -3544,8 +3540,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
}
default:
- printk(KERN_WARNING "bttv%d: unknown audiodev value!\n",
- btv->c.nr);
+ pr_warn("%d: unknown audiodev value!\n", btv->c.nr);
return;
}
@@ -3588,8 +3583,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
return;
no_audio:
- printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n",
- btv->c.nr);
+ pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
}
@@ -3642,19 +3636,19 @@ static void modtec_eeprom(struct bttv *btv)
{
if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
- printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
} else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
- printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
} else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
btv->tuner_type=TUNER_PHILIPS_NTSC;
- printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
} else {
- printk("bttv%d: Modtec: Unknown TunerString: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Unknown TunerString: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
}
}
@@ -3666,7 +3660,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
btv->tuner_type = tv.tuner_type;
btv->has_radio = tv.has_radio;
- printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
+ pr_info("%d: Hauppauge eeprom indicates model#%d\n",
btv->c.nr, tv.model);
/*
@@ -3674,7 +3668,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
* type based on model #.
*/
if(tv.model == 64900) {
- printk("bttv%d: Switching board type from %s to %s\n",
+ pr_info("%d: Switching board type from %s to %s\n",
btv->c.nr,
bttv_tvcards[btv->c.type].name,
bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
@@ -3701,8 +3695,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
freq=88000/62.5;
tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
if (0x1ed8 == tea5757_read(btv)) {
- printk("bttv%d: Terratec Active Radio Upgrade found.\n",
- btv->c.nr);
+ pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
btv->has_radio = 1;
btv->has_saa6588 = 1;
btv->has_matchbox = 1;
@@ -3774,13 +3767,12 @@ static int __devinit pvr_boot(struct bttv *btv)
rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
if (rc != 0) {
- printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n",
- btv->c.nr);
+ pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
return rc;
}
rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
- printk(KERN_INFO "bttv%d: altera firmware upload %s\n",
- btv->c.nr, (rc < 0) ? "failed" : "ok");
+ pr_info("%d: altera firmware upload %s\n",
+ btv->c.nr, (rc < 0) ? "failed" : "ok");
release_firmware(fw_entry);
return rc;
}
@@ -3876,29 +3868,27 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
break;
default:
/* unknown...leave generic, but get serial # */
- printk(KERN_INFO "bttv%d: "
- "osprey eeprom: unknown card type 0x%04x\n",
- btv->c.nr, type);
+ pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
+ btv->c.nr, type);
break;
}
serial = get_unaligned_be32((__be32 *)(ee+6));
}
- printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
- btv->c.nr, cardid,
- cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+ pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
+ btv->c.nr, cardid,
+ cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
if (cardid<0 || btv->c.type == cardid)
return;
/* card type isn't set correctly */
if (card[btv->c.nr] < bttv_num_tvcards) {
- printk(KERN_WARNING "bttv%d: osprey eeprom: "
- "Not overriding user specified card type\n", btv->c.nr);
+ pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
+ btv->c.nr);
} else {
- printk(KERN_INFO "bttv%d: osprey eeprom: "
- "Changing card type from %d to %d\n", btv->c.nr,
- btv->c.type, cardid);
+ pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
+ btv->c.nr, btv->c.type, cardid);
btv->c.type = cardid;
}
}
@@ -3941,14 +3931,14 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
if (tuner_format == 0x09)
tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
- printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+ pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
if (tuner_type) {
btv->tuner_type = tuner_type;
- printk(KERN_CONT "%d", tuner_type);
+ pr_cont("%d", tuner_type);
} else
- printk(KERN_CONT "Unknown type");
- printk(KERN_CONT " radio:%s remote control:%s\n",
+ pr_cont("Unknown type");
+ pr_cont(" radio:%s remote control:%s\n",
tuner_tv_fm ? "yes" : "no",
btv->has_remote ? "yes" : "no");
}
@@ -3996,8 +3986,8 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
if (bttv_gpio)
bttv_gpio_tracking(btv,"msp34xx");
if (bttv_verbose)
- printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
- "init [%d]\n", btv->c.nr, pin);
+ pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
+ btv->c.nr, pin);
}
/* ----------------------------------------------------------------------- */
@@ -4037,7 +4027,7 @@ static void __devinit init_PXC200(struct bttv *btv)
btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
/* Initialise MAX517 DAC */
- printk(KERN_INFO "Setting DAC reference voltage level ...\n");
+ pr_info("Setting DAC reference voltage level ...\n");
bttv_I2CWrite(btv,0x5E,0,0x80,1);
/* Initialise 12C508 PIC */
@@ -4046,7 +4036,7 @@ static void __devinit init_PXC200(struct bttv *btv)
* argument so the numbers are different */
- printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
+ pr_info("Initialising 12C508 PIC chip ...\n");
/* First of all, enable the clock line. This is used in the PXC200-F */
val = btread(BT848_GPIO_DMA_CTL);
@@ -4065,13 +4055,12 @@ static void __devinit init_PXC200(struct bttv *btv)
for (i = 0; i < ARRAY_SIZE(vals); i++) {
tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
if (tmp != -1) {
- printk(KERN_INFO
- "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+ pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
}
}
- printk(KERN_INFO "PXC200 Initialised.\n");
+ pr_info("PXC200 Initialised\n");
}
@@ -4110,8 +4099,7 @@ init_RTV24 (struct bttv *btv)
uint32_t dataRead = 0;
long watchdog_value = 0x0E;
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation in progress ...\n",
+ pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
btv->c.nr);
btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
@@ -4125,8 +4113,7 @@ init_RTV24 (struct bttv *btv)
dataRead = btread (BT848_GPIO_DATA);
if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+ pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
btv->c.nr, dataRead);
}
@@ -4139,15 +4126,13 @@ init_RTV24 (struct bttv *btv)
dataRead = btread (BT848_GPIO_DATA);
if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+ pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
btv->c.nr, dataRead);
return;
}
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
+ pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
}
@@ -4264,22 +4249,25 @@ static int tea5757_read(struct bttv *btv)
while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
schedule();
if (bus_in(btv,btv->mbox_data)) {
- printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr);
+ pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
return -1;
}
- dprintk("bttv%d: tea5757:",btv->c.nr);
+ dprintk("%d: tea5757:", btv->c.nr);
for (i = 0; i < 24; i++) {
udelay(5);
bus_high(btv,btv->mbox_clk);
udelay(5);
- dprintk("%c",(bus_in(btv,btv->mbox_most) == 0)?'T':'-');
+ dprintk_cont("%c",
+ bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
bus_low(btv,btv->mbox_clk);
value <<= 1;
value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */
- dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M');
+ dprintk_cont("%c",
+ bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
}
- dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value);
+ dprintk_cont("\n");
+ dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
return value;
}
@@ -4298,7 +4286,7 @@ static int tea5757_write(struct bttv *btv, int value)
if (bttv_gpio)
bttv_gpio_tracking(btv,"tea5757 write");
- dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value);
+ dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
bus_low(btv,btv->mbox_clk);
bus_high(btv,btv->mbox_we);
for (i = 0; i < 25; i++) {
@@ -4550,7 +4538,7 @@ static void picolo_tetra_init(struct bttv *btv)
static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
{
- dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel => input = %d\n",btv->c.nr,input);
+ dprintk("%d : picolo_tetra_muxsel => input = %d\n", btv->c.nr, input);
/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
/*GPIO[20]&GPIO[21] used to choose the right input*/
btwrite (input<<20,BT848_GPIO_DATA);
@@ -4595,7 +4583,7 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input)
int key = input % 4;
int matrix = input / 4;
- dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
+ dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
btv->c.nr, input, matrix, key);
/* Handles the input selection on the TDA8540's */
@@ -4652,15 +4640,17 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input)
buf[1]=0;
rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
if (rc) {
- printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc);
+ pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
+ btv->c.nr, rc);
/* not PXC ? do nothing */
- return;
+ return;
}
rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
if (!(rc & PX_CFG_PXC200F)) {
- printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
- return;
+ pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
+ btv->c.nr, rc);
+ return;
}
@@ -4699,7 +4689,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input)
else /* older device */
btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
- printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
+ pr_debug("%d: setting input channel to:%d\n", btv->c.nr, (int)mux);
}
static void phytec_muxsel(struct bttv *btv, unsigned int input)
@@ -4850,29 +4840,27 @@ void __init bttv_check_chipset(void)
/* print warnings about any quirks found */
if (triton1)
- printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
+ pr_info("Host bridge needs ETBF enabled\n");
if (vsfx)
- printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
+ pr_info("Host bridge needs VSFX enabled\n");
if (pcipci_fail) {
- printk(KERN_INFO "bttv: bttv and your chipset may not work "
- "together.\n");
+ pr_info("bttv and your chipset may not work together\n");
if (!no_overlay) {
- printk(KERN_INFO "bttv: overlay will be disabled.\n");
+ pr_info("overlay will be disabled\n");
no_overlay = 1;
} else {
- printk(KERN_INFO "bttv: overlay forced. Use this "
- "option at your own risk.\n");
+ pr_info("overlay forced. Use this option at your own risk.\n");
}
}
if (UNSET != latency)
- printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
+ pr_info("pci latency fixup [%d]\n", latency);
while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82441, dev))) {
unsigned char b;
pci_read_config_byte(dev, 0x53, &b);
if (bttv_debug)
- printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "
- "bufcon=0x%02x\n",b);
+ pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
+ b);
}
}
@@ -4885,12 +4873,13 @@ int __devinit bttv_handle_chipset(struct bttv *btv)
if (bttv_verbose) {
if (triton1)
- printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr);
+ pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
+ btv->c.nr);
if (vsfx && btv->id >= 878)
- printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr);
+ pr_info("%d: enabling VSFX\n", btv->c.nr);
if (UNSET != latency)
- printk(KERN_INFO "bttv%d: setting pci timer to %d\n",
- btv->c.nr,latency);
+ pr_info("%d: setting pci timer to %d\n",
+ btv->c.nr, latency);
}
if (btv->id < 878) {
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 834a483..3dd0660 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -34,6 +34,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -57,6 +59,7 @@
#include <media/saa6588.h>
+#define BTTV_VERSION "0.9.19"
unsigned int bttv_num; /* number of Bt848s in use */
struct bttv *bttvs[BTTV_MAX];
@@ -163,6 +166,7 @@ MODULE_PARM_DESC(radio_nr, "radio device numbers");
MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
MODULE_LICENSE("GPL");
+MODULE_VERSION(BTTV_VERSION);
/* ----------------------------------------------------------------------- */
/* sysfs */
@@ -940,8 +944,8 @@ static
void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
{
if ((fh->resources & bits) != bits) {
- /* trying to free ressources not allocated by us ... */
- printk("bttv: BUG! (btres)\n");
+ /* trying to free resources not allocated by us ... */
+ pr_err("BUG! (btres)\n");
}
fh->resources &= ~bits;
btv->resources &= ~bits;
@@ -998,7 +1002,7 @@ static void set_pll(struct bttv *btv)
return;
if (btv->pll.pll_ofreq == btv->pll.pll_current) {
- dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
+ dprintk("%d: PLL: no change required\n", btv->c.nr);
return;
}
@@ -1006,21 +1010,23 @@ static void set_pll(struct bttv *btv)
/* no PLL needed */
if (btv->pll.pll_current == 0)
return;
- bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
- btv->c.nr,btv->pll.pll_ifreq);
+ if (bttv_verbose)
+ pr_info("%d: PLL can sleep, using XTAL (%d)\n",
+ btv->c.nr, btv->pll.pll_ifreq);
btwrite(0x00,BT848_TGCTRL);
btwrite(0x00,BT848_PLL_XCI);
btv->pll.pll_current = 0;
return;
}
- bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
- btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+ if (bttv_verbose)
+ pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
+ btv->c.nr,
+ btv->pll.pll_ifreq, btv->pll.pll_ofreq);
set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
for (i=0; i<10; i++) {
/* Let other people run while the PLL stabilizes */
- bttv_printk(".");
msleep(10);
if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
@@ -1028,12 +1034,14 @@ static void set_pll(struct bttv *btv)
} else {
btwrite(0x08,BT848_TGCTRL);
btv->pll.pll_current = btv->pll.pll_ofreq;
- bttv_printk(" ok\n");
+ if (bttv_verbose)
+ pr_info("PLL set ok\n");
return;
}
}
btv->pll.pll_current = -1;
- bttv_printk("failed\n");
+ if (bttv_verbose)
+ pr_info("Setting PLL failed\n");
return;
}
@@ -1045,7 +1053,7 @@ static void bt848A_set_timing(struct bttv *btv)
int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
if (btv->input == btv->dig) {
- dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
+ dprintk("%d: load digital timing table (table_idx=%d)\n",
btv->c.nr,table_idx);
/* timing change...reset timing generator address */
@@ -1074,7 +1082,7 @@ static void bt848_bright(struct bttv *btv, int bright)
{
int value;
- // printk("bttv: set bright: %d\n",bright); // DEBUG
+ // printk("set bright: %d\n", bright); // DEBUG
btv->bright = bright;
/* We want -128 to 127 we get 0-65535 */
@@ -1148,8 +1156,7 @@ video_mux(struct bttv *btv, unsigned int input)
}
mux = bttv_muxsel(btv, input);
btaor(mux<<5, ~(3<<5), BT848_IFORM);
- dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
- btv->c.nr,input,mux);
+ dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
/* card specific hook */
if(bttv_tvcards[btv->c.type].muxsel_hook)
@@ -1438,7 +1445,7 @@ static void bttv_reinit_bt848(struct bttv *btv)
unsigned long flags;
if (bttv_verbose)
- printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
+ pr_info("%d: reset, reinitialize\n", btv->c.nr);
spin_lock_irqsave(&btv->s_lock,flags);
btv->errors=0;
bttv_set_dma(btv,0);
@@ -1620,8 +1627,8 @@ void bttv_gpio_tracking(struct bttv *btv, char *comment)
unsigned int outbits, data;
outbits = btread(BT848_GPIO_OUT_EN);
data = btread(BT848_GPIO_DATA);
- printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
- btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
+ pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
+ btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
}
static void bttv_field_count(struct bttv *btv)
@@ -1666,7 +1673,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
unsigned long flags;
int retval = 0;
- dprintk("switch_overlay: enter [new=%p]\n",new);
+ dprintk("switch_overlay: enter [new=%p]\n", new);
if (new)
new->vb.state = VIDEOBUF_DONE;
spin_lock_irqsave(&btv->s_lock,flags);
@@ -1676,7 +1683,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
bttv_set_dma(btv, 0x03);
spin_unlock_irqrestore(&btv->s_lock,flags);
if (NULL != old) {
- dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
+ dprintk("switch_overlay: old=%p state is %d\n",
+ old, old->vb.state);
bttv_dma_free(&fh->cap,btv, old);
kfree(old);
}
@@ -2027,11 +2035,11 @@ static int bttv_log_status(struct file *file, void *f)
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
- printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n",
- btv->c.nr, btv->c.nr);
+ pr_info("%d: ======== START STATUS CARD #%d ========\n",
+ btv->c.nr, btv->c.nr);
bttv_call_all(btv, core, log_status);
- printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n",
- btv->c.nr, btv->c.nr);
+ pr_info("%d: ======== END STATUS CARD #%d ========\n",
+ btv->c.nr, btv->c.nr);
return 0;
}
@@ -2596,7 +2604,7 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
struct bttv *btv = fh->btv;
if (no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
@@ -2616,7 +2624,6 @@ static int bttv_querycap(struct file *file, void *priv,
strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"PCI:%s", pci_name(btv->c.pci));
- cap->version = BTTV_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VBI_CAPTURE |
@@ -2672,7 +2679,7 @@ static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
int rc;
if (no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
@@ -2713,7 +2720,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
return -EINVAL;
}
if (unlikely(!fh->ov.setup_ok)) {
- dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
+ dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
retval = -EINVAL;
}
if (retval)
@@ -3090,8 +3097,8 @@ static ssize_t bttv_read(struct file *file, char __user *data,
if (fh->btv->errors)
bttv_reinit_bt848(fh->btv);
- dprintk("bttv%d: read count=%d type=%s\n",
- fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
+ dprintk("%d: read count=%d type=%s\n",
+ fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -3173,7 +3180,7 @@ static int bttv_open(struct file *file)
struct bttv_fh *fh;
enum v4l2_buf_type type = 0;
- dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
+ dprintk("open dev=%s\n", video_device_node_name(vdev));
if (vdev->vfl_type == VFL_TYPE_GRABBER) {
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -3184,8 +3191,8 @@ static int bttv_open(struct file *file)
return -ENODEV;
}
- dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
- btv->c.nr,v4l2_type_names[type]);
+ dprintk("%d: open called (type=%s)\n",
+ btv->c.nr, v4l2_type_names[type]);
/* allocate per filehandle data */
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3287,7 +3294,7 @@ bttv_mmap(struct file *file, struct vm_area_struct *vma)
{
struct bttv_fh *fh = file->private_data;
- dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
+ dprintk("%d: mmap type=%s 0x%lx+%ld\n",
fh->btv->c.nr, v4l2_type_names[fh->type],
vma->vm_start, vma->vm_end - vma->vm_start);
return videobuf_mmap_mapper(bttv_queue(fh),vma);
@@ -3369,9 +3376,9 @@ static int radio_open(struct file *file)
struct bttv *btv = video_drvdata(file);
struct bttv_fh *fh;
- dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
+ dprintk("open dev=%s\n", video_device_node_name(vdev));
- dprintk("bttv%d: open called (radio)\n",btv->c.nr);
+ dprintk("%d: open called (radio)\n", btv->c.nr);
/* allocate per filehandle data */
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3416,7 +3423,6 @@ static int radio_querycap(struct file *file, void *priv,
strcpy(cap->driver, "bttv");
strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
- cap->version = BTTV_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
return 0;
@@ -3616,12 +3622,12 @@ static int bttv_risc_decode(u32 risc)
};
int i;
- printk("0x%08x [ %s", risc,
+ pr_cont("0x%08x [ %s", risc,
instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
if (risc & (1 << (i + 12)))
- printk(" %s",bits[i]);
- printk(" count=%d ]\n", risc & 0xfff);
+ pr_cont(" %s", bits[i]);
+ pr_cont(" count=%d ]\n", risc & 0xfff);
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
@@ -3630,16 +3636,18 @@ static void bttv_risc_disasm(struct bttv *btv,
{
unsigned int i,j,n;
- printk("%s: risc disasm: %p [dma=0x%08lx]\n",
- btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
+ pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
+ btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
for (i = 0; i < (risc->size >> 2); i += n) {
- printk("%s: 0x%lx: ", btv->c.v4l2_dev.name,
- (unsigned long)(risc->dma + (i<<2)));
+ pr_info("%s: 0x%lx: ",
+ btv->c.v4l2_dev.name,
+ (unsigned long)(risc->dma + (i<<2)));
n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
for (j = 1; j < n; j++)
- printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
- btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
- risc->cpu[i+j], j);
+ pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
+ btv->c.v4l2_dev.name,
+ (unsigned long)(risc->dma + ((i+j)<<2)),
+ risc->cpu[i+j], j);
if (0 == risc->cpu[i])
break;
}
@@ -3647,17 +3655,18 @@ static void bttv_risc_disasm(struct bttv *btv,
static void bttv_print_riscaddr(struct bttv *btv)
{
- printk(" main: %08Lx\n",
- (unsigned long long)btv->main.dma);
- printk(" vbi : o=%08Lx e=%08Lx\n",
- btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
- btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
- printk(" cap : o=%08Lx e=%08Lx\n",
- btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
- btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
- printk(" scr : o=%08Lx e=%08Lx\n",
- btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
- btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+ pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
+ pr_info(" vbi : o=%08llx e=%08llx\n",
+ btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+ btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+ pr_info(" cap : o=%08llx e=%08llx\n",
+ btv->curr.top
+ ? (unsigned long long)btv->curr.top->top.dma : 0,
+ btv->curr.bottom
+ ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+ pr_info(" scr : o=%08llx e=%08llx\n",
+ btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+ btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
bttv_risc_disasm(btv, &btv->main);
}
@@ -3690,34 +3699,34 @@ static void bttv_print_irqbits(u32 print, u32 mark)
{
unsigned int i;
- printk("bits:");
+ pr_cont("bits:");
for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
if (print & (1 << i))
- printk(" %s",irq_name[i]);
+ pr_cont(" %s", irq_name[i]);
if (mark & (1 << i))
- printk("*");
+ pr_cont("*");
}
}
static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
{
- printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
- btv->c.nr,
- (unsigned long)btv->main.dma,
- (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
- (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
- (unsigned long)rc);
+ pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
+ btv->c.nr,
+ (unsigned long)btv->main.dma,
+ (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
+ (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
+ (unsigned long)rc);
if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
- printk("bttv%d: Oh, there (temporarely?) is no input signal. "
- "Ok, then this is harmless, don't worry ;)\n",
- btv->c.nr);
+ pr_notice("%d: Oh, there (temporarily?) is no input signal. "
+ "Ok, then this is harmless, don't worry ;)\n",
+ btv->c.nr);
return;
}
- printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
- btv->c.nr);
- printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
- btv->c.nr);
+ pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
+ btv->c.nr);
+ pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
+ btv->c.nr);
dump_stack();
}
@@ -3798,9 +3807,9 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
}
}
- dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
- btv->c.nr,set->top, set->bottom,
- btv->screen,set->frame_irq,set->top_irq);
+ dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+ btv->c.nr, set->top, set->bottom,
+ btv->screen, set->frame_irq, set->top_irq);
return 0;
}
@@ -3815,7 +3824,8 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
if (wakeup->top == wakeup->bottom) {
if (NULL != wakeup->top && curr->top != wakeup->top) {
if (irq_debug > 1)
- printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
+ pr_debug("%d: wakeup: both=%p\n",
+ btv->c.nr, wakeup->top);
wakeup->top->vb.ts = ts;
wakeup->top->vb.field_count = btv->field_count;
wakeup->top->vb.state = state;
@@ -3824,7 +3834,8 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
} else {
if (NULL != wakeup->top && curr->top != wakeup->top) {
if (irq_debug > 1)
- printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
+ pr_debug("%d: wakeup: top=%p\n",
+ btv->c.nr, wakeup->top);
wakeup->top->vb.ts = ts;
wakeup->top->vb.field_count = btv->field_count;
wakeup->top->vb.state = state;
@@ -3832,7 +3843,8 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
}
if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
if (irq_debug > 1)
- printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
+ pr_debug("%d: wakeup: bottom=%p\n",
+ btv->c.nr, wakeup->bottom);
wakeup->bottom->vb.ts = ts;
wakeup->bottom->vb.field_count = btv->field_count;
wakeup->bottom->vb.state = state;
@@ -3866,11 +3878,11 @@ static void bttv_irq_timeout(unsigned long data)
unsigned long flags;
if (bttv_verbose) {
- printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
- btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
- btread(BT848_RISC_COUNT));
+ pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
+ btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
+ btread(BT848_RISC_COUNT));
bttv_print_irqbits(btread(BT848_INT_STAT),0);
- printk("\n");
+ pr_cont("\n");
}
spin_lock_irqsave(&btv->s_lock,flags);
@@ -4033,21 +4045,23 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
dstat=btread(BT848_DSTATUS);
if (irq_debug) {
- printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
- "riscs=%x, riscc=%08x, ",
- btv->c.nr, count, btv->field_count,
- stat>>28, btread(BT848_RISC_COUNT));
+ pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
+ btv->c.nr, count, btv->field_count,
+ stat>>28, btread(BT848_RISC_COUNT));
bttv_print_irqbits(stat,astat);
if (stat & BT848_INT_HLOCK)
- printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
- ? "yes" : "no");
+ pr_cont(" HLOC => %s",
+ dstat & BT848_DSTATUS_HLOC
+ ? "yes" : "no");
if (stat & BT848_INT_VPRES)
- printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
- ? "yes" : "no");
+ pr_cont(" PRES => %s",
+ dstat & BT848_DSTATUS_PRES
+ ? "yes" : "no");
if (stat & BT848_INT_FMTCHG)
- printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
- ? "625" : "525");
- printk("\n");
+ pr_cont(" NUML => %s",
+ dstat & BT848_DSTATUS_NUML
+ ? "625" : "525");
+ pr_cont("\n");
}
if (astat&BT848_INT_VSYNC)
@@ -4075,18 +4089,19 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
audio_mute(btv, btv->mute); /* trigger automute */
if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
- printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
- (astat & BT848_INT_SCERR) ? "SCERR" : "",
- (astat & BT848_INT_OCERR) ? "OCERR" : "",
- btread(BT848_RISC_COUNT));
+ pr_info("%d: %s%s @ %08x,",
+ btv->c.nr,
+ (astat & BT848_INT_SCERR) ? "SCERR" : "",
+ (astat & BT848_INT_OCERR) ? "OCERR" : "",
+ btread(BT848_RISC_COUNT));
bttv_print_irqbits(stat,astat);
- printk("\n");
+ pr_cont("\n");
if (bttv_debug)
bttv_print_riscaddr(btv);
}
if (fdsr && astat & BT848_INT_FDSR) {
- printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
- btv->c.nr,btread(BT848_RISC_COUNT));
+ pr_info("%d: FDSR @ %08x\n",
+ btv->c.nr, btread(BT848_RISC_COUNT));
if (bttv_debug)
bttv_print_riscaddr(btv);
}
@@ -4097,11 +4112,11 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
if (count > 8 || !(astat & BT848_INT_GPINT)) {
btwrite(0, BT848_INT_MASK);
- printk(KERN_ERR
- "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
+ pr_err("%d: IRQ lockup, cleared int mask [",
+ btv->c.nr);
} else {
- printk(KERN_ERR
- "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
+ pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
+ btv->c.nr);
btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
BT848_INT_MASK);
@@ -4109,7 +4124,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
bttv_print_irqbits(stat,astat);
- printk("]\n");
+ pr_cont("]\n");
}
}
btv->irq_total++;
@@ -4171,7 +4186,7 @@ static void bttv_unregister_video(struct bttv *btv)
static int __devinit bttv_register_video(struct bttv *btv)
{
if (no_overlay > 0)
- printk("bttv: Overlay support disabled.\n");
+ pr_notice("Overlay support disabled\n");
/* video */
btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
@@ -4181,12 +4196,11 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
video_nr[btv->c.nr]) < 0)
goto err;
- printk(KERN_INFO "bttv%d: registered device %s\n",
- btv->c.nr, video_device_node_name(btv->video_dev));
+ pr_info("%d: registered device %s\n",
+ btv->c.nr, video_device_node_name(btv->video_dev));
if (device_create_file(&btv->video_dev->dev,
&dev_attr_card)<0) {
- printk(KERN_ERR "bttv%d: device_create_file 'card' "
- "failed\n", btv->c.nr);
+ pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
goto err;
}
@@ -4198,8 +4212,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
vbi_nr[btv->c.nr]) < 0)
goto err;
- printk(KERN_INFO "bttv%d: registered device %s\n",
- btv->c.nr, video_device_node_name(btv->vbi_dev));
+ pr_info("%d: registered device %s\n",
+ btv->c.nr, video_device_node_name(btv->vbi_dev));
if (!btv->has_radio)
return 0;
@@ -4210,8 +4224,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
radio_nr[btv->c.nr]) < 0)
goto err;
- printk(KERN_INFO "bttv%d: registered device %s\n",
- btv->c.nr, video_device_node_name(btv->radio_dev));
+ pr_info("%d: registered device %s\n",
+ btv->c.nr, video_device_node_name(btv->radio_dev));
/* all done */
return 0;
@@ -4244,10 +4258,10 @@ static int __devinit bttv_probe(struct pci_dev *dev,
if (bttv_num == BTTV_MAX)
return -ENOMEM;
- printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
+ pr_info("Bt8xx card found (%d)\n", bttv_num);
bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
if (btv == NULL) {
- printk(KERN_ERR "bttv: out of memory.\n");
+ pr_err("out of memory\n");
return -ENOMEM;
}
btv->c.nr = bttv_num;
@@ -4277,21 +4291,19 @@ static int __devinit bttv_probe(struct pci_dev *dev,
btv->c.pci = dev;
btv->id = dev->device;
if (pci_enable_device(dev)) {
- printk(KERN_WARNING "bttv%d: Can't enable device.\n",
- btv->c.nr);
+ pr_warn("%d: Can't enable device\n", btv->c.nr);
return -EIO;
}
if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
- printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
- btv->c.nr);
+ pr_warn("%d: No suitable DMA available\n", btv->c.nr);
return -EIO;
}
if (!request_mem_region(pci_resource_start(dev,0),
pci_resource_len(dev,0),
btv->c.v4l2_dev.name)) {
- printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
- btv->c.nr,
- (unsigned long long)pci_resource_start(dev,0));
+ pr_warn("%d: can't request iomem (0x%llx)\n",
+ btv->c.nr,
+ (unsigned long long)pci_resource_start(dev, 0));
return -EBUSY;
}
pci_set_master(dev);
@@ -4299,22 +4311,21 @@ static int __devinit bttv_probe(struct pci_dev *dev,
result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
if (result < 0) {
- printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
+ pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
goto fail0;
}
btv->revision = dev->revision;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
- bttv_num,btv->id, btv->revision, pci_name(dev));
- printk("irq: %d, latency: %d, mmio: 0x%llx\n",
- btv->c.pci->irq, lat,
- (unsigned long long)pci_resource_start(dev,0));
+ pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
+ bttv_num, btv->id, btv->revision, pci_name(dev),
+ btv->c.pci->irq, lat,
+ (unsigned long long)pci_resource_start(dev, 0));
schedule();
btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
if (NULL == btv->bt848_mmio) {
- printk("bttv%d: ioremap() failed\n", btv->c.nr);
+ pr_err("%d: ioremap() failed\n", btv->c.nr);
result = -EIO;
goto fail1;
}
@@ -4327,8 +4338,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
result = request_irq(btv->c.pci->irq, bttv_irq,
IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
if (result < 0) {
- printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
- bttv_num,btv->c.pci->irq);
+ pr_err("%d: can't get IRQ %d\n",
+ bttv_num, btv->c.pci->irq);
goto fail1;
}
@@ -4433,7 +4444,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
struct bttv *btv = to_bttv(v4l2_dev);
if (bttv_verbose)
- printk("bttv%d: unloading\n",btv->c.nr);
+ pr_info("%d: unloading\n", btv->c.nr);
if (bttv_tvcards[btv->c.type].has_dvb)
flush_request_modules(btv);
@@ -4481,7 +4492,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
struct bttv_buffer_set idle;
unsigned long flags;
- dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
+ dprintk("%d: suspend %d\n", btv->c.nr, state.event);
/* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags);
@@ -4517,14 +4528,13 @@ static int bttv_resume(struct pci_dev *pci_dev)
unsigned long flags;
int err;
- dprintk("bttv%d: resume\n", btv->c.nr);
+ dprintk("%d: resume\n", btv->c.nr);
/* restore pci state */
if (btv->state.disabled) {
err=pci_enable_device(pci_dev);
if (err) {
- printk(KERN_WARNING "bttv%d: Can't enable device.\n",
- btv->c.nr);
+ pr_warn("%d: Can't enable device\n", btv->c.nr);
return err;
}
btv->state.disabled = 0;
@@ -4532,8 +4542,7 @@ static int bttv_resume(struct pci_dev *pci_dev)
err=pci_set_power_state(pci_dev, PCI_D0);
if (err) {
pci_disable_device(pci_dev);
- printk(KERN_WARNING "bttv%d: Can't enable device.\n",
- btv->c.nr);
+ pr_warn("%d: Can't enable device\n", btv->c.nr);
btv->state.disabled = 1;
return err;
}
@@ -4585,28 +4594,21 @@ static int __init bttv_init_module(void)
bttv_num = 0;
- printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
- (BTTV_VERSION_CODE >> 16) & 0xff,
- (BTTV_VERSION_CODE >> 8) & 0xff,
- BTTV_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ pr_info("driver version %s loaded\n", BTTV_VERSION);
if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
gbuffers = 2;
if (gbufsize > BTTV_MAX_FBUF)
gbufsize = BTTV_MAX_FBUF;
gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
if (bttv_verbose)
- printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
- gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
+ pr_info("using %d buffers with %dk (%d pages) each for capture\n",
+ gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
bttv_check_chipset();
ret = bus_register(&bttv_sub_bus_type);
if (ret < 0) {
- printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+ pr_warn("bus_register error: %d\n", ret);
return ret;
}
ret = pci_register_driver(&bttv_pci_driver);
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c
index 13ce72c..922e823 100644
--- a/drivers/media/video/bt8xx/bttv-gpio.c
+++ b/drivers/media/video/bt8xx/bttv-gpio.c
@@ -26,6 +26,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -99,7 +101,7 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
kfree(sub);
return err;
}
- printk("bttv%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
+ pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
list_add_tail(&sub->list,&core->subs);
return 0;
}
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index d49b675..e3952af 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -27,6 +27,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -154,9 +156,7 @@ bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
if (retval == 0)
goto eio;
if (i2c_debug) {
- printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
- if (!(xmit & BT878_I2C_NOSTOP))
- printk(" >\n");
+ pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
}
for (cnt = 1; cnt < msg->len; cnt++ ) {
@@ -170,19 +170,18 @@ bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
goto err;
if (retval == 0)
goto eio;
- if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
- if (!(xmit & BT878_I2C_NOSTOP))
- printk(" >\n");
- }
+ if (i2c_debug)
+ pr_cont(" %02x", msg->buf[cnt]);
}
+ if (!(xmit & BT878_I2C_NOSTOP))
+ pr_cont(">\n");
return msg->len;
eio:
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n",retval);
+ pr_cont(" ERR: %d\n",retval);
return retval;
}
@@ -193,7 +192,7 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
u32 cnt;
int retval;
- for(cnt = 0; cnt < msg->len; cnt++) {
+ for (cnt = 0; cnt < msg->len; cnt++) {
xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
if (cnt < msg->len-1)
xmit |= BT848_I2C_W3B;
@@ -201,6 +200,12 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
xmit |= BT878_I2C_NOSTOP;
if (cnt)
xmit |= BT878_I2C_NOSTART;
+
+ if (i2c_debug) {
+ if (!(xmit & BT878_I2C_NOSTART))
+ pr_cont(" <R %02x", (msg->addr << 1) +1);
+ }
+
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
@@ -209,20 +214,20 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
goto eio;
msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
if (i2c_debug) {
- if (!(xmit & BT878_I2C_NOSTART))
- printk(" <R %02x", (msg->addr << 1) +1);
- printk(" =%02x", msg->buf[cnt]);
- if (!(xmit & BT878_I2C_NOSTOP))
- printk(" >\n");
+ pr_cont(" =%02x", msg->buf[cnt]);
}
+ if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
+ pr_cont(" >\n");
}
+
+
return msg->len;
eio:
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n",retval);
+ pr_cont(" ERR: %d\n",retval);
return retval;
}
@@ -234,7 +239,8 @@ static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int
int i;
if (i2c_debug)
- printk("bt-i2c:");
+ pr_debug("bt-i2c:");
+
btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
for (i = 0 ; i < num; i++) {
if (msgs[i].flags & I2C_M_RD) {
@@ -271,20 +277,20 @@ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
if (0 != btv->i2c_rc)
return -1;
if (bttv_verbose && NULL != probe_for)
- printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ",
- btv->c.nr,probe_for,addr);
+ pr_info("%d: i2c: checking for %s @ 0x%02x... ",
+ btv->c.nr, probe_for, addr);
btv->i2c_client.addr = addr >> 1;
if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
if (NULL != probe_for) {
if (bttv_verbose)
- printk("not found\n");
+ pr_cont("not found\n");
} else
- printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
- btv->c.nr,addr);
+ pr_warn("%d: i2c read 0x%x: error\n",
+ btv->c.nr, addr);
return -1;
}
if (bttv_verbose && NULL != probe_for)
- printk("found\n");
+ pr_cont("found\n");
return buffer;
}
@@ -335,8 +341,8 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
rc = i2c_master_recv(c,&buf,0);
if (rc < 0)
continue;
- printk("%s: i2c scan: found device @ 0x%x [%s]\n",
- name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+ pr_info("%s: i2c scan: found device @ 0x%x [%s]\n",
+ name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
}
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 677d70c..ef4c7cd 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -36,9 +38,10 @@ static int ir_rc5_remote_gap = 885;
module_param(ir_rc5_remote_gap, int, 0644);
#undef dprintk
-#define dprintk(arg...) do { \
- if (ir_debug >= 1) \
- printk(arg); \
+#define dprintk(fmt, ...) \
+do { \
+ if (ir_debug >= 1) \
+ pr_info(fmt, ##__VA_ARGS__); \
} while (0)
#define DEVNAME "bttv-input"
@@ -62,7 +65,7 @@ static void ir_handle_key(struct bttv *btv)
/* extract data */
data = ir_extract_bits(gpio, ir->mask_keycode);
- dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
+ dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
gpio, data,
ir->polling ? "poll" : "irq",
(gpio & ir->mask_keydown) ? " down" : "",
@@ -96,7 +99,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
if ((ir->last_gpio & 0x7f) != data) {
- dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n",
+ dprintk("gpio=0x%x code=%d | %s\n",
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "up/down");
@@ -107,7 +110,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
if ((ir->last_gpio & 1 << 31) == keyup)
return;
- dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n",
+ dprintk("(cnt) gpio=0x%x code=%d | %s\n",
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "down");
@@ -177,13 +180,12 @@ static u32 bttv_rc5_decode(unsigned int code)
rc5 |= 1;
break;
case 3:
- dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n",
+ dprintk("rc5_decode(%x) bad code\n",
org_code);
return 0;
}
}
- dprintk(KERN_INFO DEVNAME ":"
- "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+ dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
"instr=%x\n", rc5, org_code, RC5_START(rc5),
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
return rc5;
@@ -212,20 +214,20 @@ static void bttv_rc5_timer_end(unsigned long data)
/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
if (gap < 28000) {
- dprintk(KERN_INFO DEVNAME ": spurious timer_end\n");
+ dprintk("spurious timer_end\n");
return;
}
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
- dprintk(KERN_INFO DEVNAME ": short code: %x\n", ir->code);
+ dprintk("short code: %x\n", ir->code);
} else {
ir->code = (ir->code << ir->shift_by) | 1;
rc5 = bttv_rc5_decode(ir->code);
/* two start bits? */
if (RC5_START(rc5) != ir->start) {
- printk(KERN_INFO DEVNAME ":"
+ pr_info(DEVNAME ":"
" rc5 start bits invalid: %u\n", RC5_START(rc5));
/* right address? */
@@ -235,8 +237,7 @@ static void bttv_rc5_timer_end(unsigned long data)
/* Good code */
rc_keydown(ir->dev, instr, toggle);
- dprintk(KERN_INFO DEVNAME ":"
- " instruction %x, toggle %x\n",
+ dprintk("instruction %x, toggle %x\n",
instr, toggle);
}
}
@@ -265,7 +266,7 @@ static int bttv_rc5_irq(struct bttv *btv)
tv.tv_usec - ir->base_time.tv_usec;
}
- dprintk(KERN_INFO DEVNAME ": RC5 IRQ: gap %d us for %s\n",
+ dprintk("RC5 IRQ: gap %d us for %s\n",
gap, (gpio & 0x20) ? "mark" : "space");
/* remote IRQ? */
@@ -340,14 +341,14 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
/* poll IR chip */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
- dprintk(KERN_INFO DEVNAME ": read error\n");
+ dprintk("read error\n");
return -EIO;
}
/* ignore 0xaa */
if (b==0xaa)
return 0;
- dprintk(KERN_INFO DEVNAME ": key %02x\n", b);
+ dprintk("key %02x\n", b);
/*
* NOTE:
@@ -517,7 +518,7 @@ int bttv_input_init(struct bttv *btv)
break;
}
if (NULL == ir_codes) {
- dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+ dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
err = -ENODEV;
goto err_out_free;
}
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index 9b57d09..82cc47d 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -24,6 +24,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -473,8 +475,7 @@ bttv_set_dma(struct bttv *btv, int override)
capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
capctl |= override;
- d2printk(KERN_DEBUG
- "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
+ d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
btv->c.nr,capctl,btv->loop_irq,
btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
@@ -517,8 +518,8 @@ bttv_risc_init_main(struct bttv *btv)
if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
return rc;
- dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
- btv->c.nr,(unsigned long long)btv->main.dma);
+ dprintk("%d: risc main @ %08llx\n",
+ btv->c.nr, (unsigned long long)btv->main.dma);
btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
BT848_FIFO_STATUS_VRE);
@@ -557,12 +558,12 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
unsigned long next = btv->main.dma + ((slot+2) << 2);
if (NULL == risc) {
- d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
- btv->c.nr,risc,slot);
+ d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
btv->main.cpu[slot+1] = cpu_to_le32(next);
} else {
- d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
- btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
+ d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
+ btv->c.nr, risc, slot,
+ (unsigned long long)risc->dma, irqflags);
cmd = BT848_RISC_JUMP;
if (irqflags) {
cmd |= BT848_RISC_IRQ;
@@ -708,8 +709,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- dprintk(KERN_DEBUG
- "bttv%d: buffer field: %s format: %s size: %dx%d\n",
+ dprintk("%d: buffer field: %s format: %s size: %dx%d\n",
btv->c.nr, v4l2_field_names[buf->vb.field],
buf->fmt->name, buf->vb.width, buf->vb.height);
@@ -870,10 +870,9 @@ bttv_overlay_risc(struct bttv *btv,
struct bttv_buffer *buf)
{
/* check interleave, bottom+top fields */
- dprintk(KERN_DEBUG
- "bttv%d: overlay fields: %s format: %s size: %dx%d\n",
+ dprintk("%d: overlay fields: %s format: %s size: %dx%d\n",
btv->c.nr, v4l2_field_names[buf->vb.field],
- fmt->name,ov->w.width,ov->w.height);
+ fmt->name, ov->w.width, ov->w.height);
/* calculate geometry */
bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index e79a402..b433267 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -23,6 +23,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
@@ -65,8 +67,11 @@ MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
#ifdef dprintk
# undef dprintk
#endif
-#define dprintk(fmt, arg...) if (vbi_debug) \
- printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
+#define dprintk(fmt, ...) \
+do { \
+ if (vbi_debug) \
+ pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__); \
+} while (0)
#define IMAGE_SIZE(fmt) \
(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 9b776fa..db943a8d 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -25,9 +25,6 @@
#ifndef _BTTVP_H_
#define _BTTVP_H_
-#include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,18)
-
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/i2c.h>
@@ -313,9 +310,21 @@ extern unsigned int bttv_gpio;
extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
extern int init_bttv_i2c(struct bttv *btv);
-#define bttv_printk if (bttv_verbose) printk
-#define dprintk if (bttv_debug >= 1) printk
-#define d2printk if (bttv_debug >= 2) printk
+#define dprintk(fmt, ...) \
+do { \
+ if (bttv_debug >= 1) \
+ pr_debug(fmt, ##__VA_ARGS__); \
+} while (0)
+#define dprintk_cont(fmt, ...) \
+do { \
+ if (bttv_debug >= 1) \
+ pr_cont(fmt, ##__VA_ARGS__); \
+} while (0)
+#define d2printk(fmt, ...) \
+do { \
+ if (bttv_debug >= 2) \
+ printk(fmt, ##__VA_ARGS__); \
+} while (0)
#define BTTV_MAX_FBUF 0x208000
#define BTTV_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
index 6d6d184..ab25218 100644
--- a/drivers/media/video/cpia2/cpia2.h
+++ b/drivers/media/video/cpia2/cpia2.h
@@ -31,7 +31,6 @@
#ifndef __CPIA2_H__
#define __CPIA2_H__
-#include <linux/version.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <linux/usb.h>
@@ -43,10 +42,6 @@
/* define for verbose debug output */
//#define _CPIA2_DEBUG_
-#define CPIA2_MAJ_VER 3
-#define CPIA2_MIN_VER 0
-#define CPIA2_PATCH_VER 0
-
/***
* Image defines
***/
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
index dc5b07a..59c797c 100644
--- a/drivers/media/video/cpia2/cpia2_usb.c
+++ b/drivers/media/video/cpia2/cpia2_usb.c
@@ -31,6 +31,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/usb.h>
+#include <linux/module.h>
#include "cpia2.h"
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 40eb632..077eb1d 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -29,8 +29,7 @@
* Alan Cox <alan@lxorguk.ukuu.org.uk>
****************************************************************************/
-#include <linux/version.h>
-
+#define CPIA_VERSION "3.0.1"
#include <linux/module.h>
#include <linux/time.h>
@@ -80,6 +79,7 @@ MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
MODULE_SUPPORTED_DEVICE("video");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CPIA_VERSION);
#define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
@@ -465,9 +465,6 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v
if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0)
memset(vc->bus_info,0, sizeof(vc->bus_info));
- vc->version = KERNEL_VERSION(CPIA2_MAJ_VER, CPIA2_MIN_VER,
- CPIA2_PATCH_VER);
-
vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
@@ -1558,8 +1555,8 @@ static void __init check_parameters(void)
*****************************************************************************/
static int __init cpia2_init(void)
{
- LOG("%s v%d.%d.%d\n",
- ABOUT, CPIA2_MAJ_VER, CPIA2_MIN_VER, CPIA2_PATCH_VER);
+ LOG("%s v%s\n",
+ ABOUT, CPIA_VERSION);
check_parameters();
cpia2_usb_init();
return 0;
@@ -1579,4 +1576,3 @@ static void __exit cpia2_exit(void)
module_init(cpia2_init);
module_exit(cpia2_exit);
-
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile
index 2fadd9d..a86bab5 100644
--- a/drivers/media/video/cx18/Makefile
+++ b/drivers/media/video/cx18/Makefile
@@ -8,6 +8,6 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
obj-$(CONFIG_VIDEO_CX18) += cx18.o
obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c
index d50d69d..a1e6c2a 100644
--- a/drivers/media/video/cx18/cx18-alsa-main.c
+++ b/drivers/media/video/cx18/cx18-alsa-main.c
@@ -192,6 +192,7 @@ static int snd_cx18_init(struct v4l2_device *v4l2_dev)
err_exit_free:
if (sc != NULL)
snd_card_free(sc);
+ kfree(cxsc);
err_exit:
return ret;
}
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 9e2f870..c6ff32a 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -1085,6 +1085,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
setup.addr = ADDR_UNSET;
setup.type = cx->options.tuner;
setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
+ if (cx->options.radio > 0)
+ setup.mode_mask |= T_RADIO;
setup.tuner_callback = (setup.type == TUNER_XC2028) ?
cx18_reset_tuner_gpio : NULL;
cx18_call_all(cx, tuner, s_type_addr, &setup);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 0864272..b9a94fc 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -25,7 +25,6 @@
#ifndef CX18_DRIVER_H
#define CX18_DRIVER_H
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -410,6 +409,7 @@ struct cx18_stream {
/* Videobuf for YUV video */
u32 pixelformat;
+ u32 vb_bytes_per_frame;
struct list_head vb_capture; /* video capture queue */
spinlock_t vb_lock;
struct timer_list vb_timeout;
@@ -431,10 +431,6 @@ struct cx18_open_id {
u32 open_id;
int type;
struct cx18 *cx;
-
- struct videobuf_queue vbuf_q;
- spinlock_t s_lock; /* Protect vbuf_q */
- enum v4l2_buf_type vb_type;
};
static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 07411f3..14cb961 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -784,8 +784,6 @@ int cx18_v4l2_close(struct file *filp)
cx18_release_stream(s);
} else {
cx18_stop_capture(id, 0);
- if (id->type == CX18_ENC_STREAM_TYPE_YUV)
- videobuf_mmap_free(&id->vbuf_q);
}
kfree(id);
mutex_unlock(&cx->serialize_lock);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index e80134f..66b1c15 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -160,12 +160,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
pixfmt->priv = 0;
if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = s->pixelformat;
- /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
- UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
- if (s->pixelformat == V4L2_PIX_FMT_HM12)
- pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
- else
- pixfmt->sizeimage = pixfmt->height * 720 * 2;
+ pixfmt->sizeimage = s->vb_bytes_per_frame;
pixfmt->bytesperline = 720;
} else {
pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,6 +291,12 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
return -EBUSY;
s->pixelformat = fmt->fmt.pix.pixelformat;
+ /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+ if (s->pixelformat == V4L2_PIX_FMT_HM12)
+ s->vb_bytes_per_frame = h * 720 * 3 / 2;
+ else
+ s->vb_bytes_per_frame = h * 720 * 2;
mbus_fmt.width = cx->cxhdl.width = w;
mbus_fmt.height = cx->cxhdl.height = h;
@@ -463,14 +464,16 @@ static int cx18_s_register(struct file *file, void *fh,
static int cx18_querycap(struct file *file, void *fh,
struct v4l2_capability *vcap)
{
- struct cx18 *cx = fh2id(fh)->cx;
+ struct cx18_open_id *id = fh2id(fh);
+ struct cx18 *cx = id->cx;
strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCI:%s", pci_name(cx->pci_dev));
- vcap->version = CX18_DRIVER_VERSION; /* version */
vcap->capabilities = cx->v4l2_cap; /* capabilities */
+ if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+ vcap->capabilities |= V4L2_CAP_STREAMING;
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index c07191e..0c7796e 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -196,7 +196,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
}
/* If we've filled the buffer as per the callers res then dispatch it */
- if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) {
+ if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
dispatch = 1;
vb_buf->bytes_used = 0;
}
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
index 05fe6bd..b63fdfa 100644
--- a/drivers/media/video/cx18/cx18-mailbox.h
+++ b/drivers/media/video/cx18/cx18-mailbox.h
@@ -69,7 +69,7 @@ struct cx18_mailbox {
/* Each command can have up to 6 arguments */
u32 args[MAX_MB_ARGUMENTS];
/* The return code can be one of the codes in the file cx23418.h. If the
- command is completed successfuly, the error will be ERR_SYS_SUCCESS.
+ command is completed successfully, the error will be ERR_SYS_SUCCESS.
If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
code would indicate the task from which the error originated and will
be one of the errors in cx23418.h. In that case, the following
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 852f420..638cca1 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -138,6 +138,12 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
buf->tvnorm = cx->std;
s->pixelformat = pixelformat;
+ /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+ if (s->pixelformat == V4L2_PIX_FMT_HM12)
+ s->vb_bytes_per_frame = height * 720 * 3 / 2;
+ else
+ s->vb_bytes_per_frame = height * 720 * 2;
cx18_dma_free(q, s, buf);
}
@@ -154,6 +160,12 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
buf->tvnorm = cx->std;
s->pixelformat = pixelformat;
+ /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+ if (s->pixelformat == V4L2_PIX_FMT_HM12)
+ s->vb_bytes_per_frame = height * 720 * 3 / 2;
+ else
+ s->vb_bytes_per_frame = height * 720 * 2;
rc = videobuf_iolock(q, &buf->vb, NULL);
if (rc != 0)
goto fail;
@@ -287,6 +299,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
/* Assume the previous pixel default */
s->pixelformat = V4L2_PIX_FMT_HM12;
+ s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
}
}
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
index cd189b6..fed48b6 100644
--- a/drivers/media/video/cx18/cx18-version.h
+++ b/drivers/media/video/cx18/cx18-version.h
@@ -23,12 +23,6 @@
#define CX18_VERSION_H
#define CX18_DRIVER_NAME "cx18"
-#define CX18_DRIVER_VERSION_MAJOR 1
-#define CX18_DRIVER_VERSION_MINOR 5
-#define CX18_DRIVER_VERSION_PATCHLEVEL 0
-
-#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
-#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
- CX18_DRIVER_VERSION_MINOR, CX18_DRIVER_VERSION_PATCHLEVEL)
+#define CX18_VERSION "1.5.1"
#endif
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
index 2c24843..b334897 100644
--- a/drivers/media/video/cx231xx/Makefile
+++ b/drivers/media/video/cx231xx/Makefile
@@ -8,9 +8,9 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-usb
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c
index 8d78134..53ff26e 100644
--- a/drivers/media/video/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/video/cx231xx/cx231xx-avcore.c
@@ -355,6 +355,8 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev,
case CX231XX_BOARD_HAUPPAUGE_EXETER:
case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
FLD_PWRDN_ENABLE_PLL)) {
@@ -1733,6 +1735,8 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
break;
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
func_mode = 0x01;
break;
default:
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 2270381..53dae2a 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -387,6 +387,7 @@ struct cx231xx_board cx231xx_boards[] = {
.norm = V4L2_STD_NTSC,
.no_alt_vanc = 1,
.external_av = 1,
+ .dont_use_port_3 = 1,
.input = {{
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
@@ -532,6 +533,76 @@ struct cx231xx_board cx231xx_boards[] = {
.gpio = NULL,
} },
},
+ [CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = {
+ .name = "Hauppauge WinTV USB2 FM (PAL)",
+ .tuner_type = TUNER_NXP_TDA18271,
+ .tuner_addr = 0x60,
+ .tuner_gpio = RDE250_XCV_TUNER,
+ .tuner_sif_gpio = 0x05,
+ .tuner_scl_gpio = 0x1a,
+ .tuner_sda_gpio = 0x1b,
+ .decoder = CX231XX_AVDECODER,
+ .output_mode = OUT_MODE_VIP11,
+ .ctl_pin_status_mask = 0xFFFFFFC4,
+ .agc_analog_digital_select_gpio = 0x0c,
+ .gpio_pin_status_mask = 0x4001000,
+ .tuner_i2c_master = 1,
+ .norm = V4L2_STD_PAL,
+
+ .input = {{
+ .type = CX231XX_VMUX_TELEVISION,
+ .vmux = CX231XX_VIN_3_1,
+ .amux = CX231XX_AMUX_VIDEO,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_COMPOSITE1,
+ .vmux = CX231XX_VIN_2_1,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_SVIDEO,
+ .vmux = CX231XX_VIN_1_1 |
+ (CX231XX_VIN_1_2 << 8) |
+ CX25840_SVIDEO_ON,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ } },
+ },
+ [CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = {
+ .name = "Hauppauge WinTV USB2 FM (NTSC)",
+ .tuner_type = TUNER_NXP_TDA18271,
+ .tuner_addr = 0x60,
+ .tuner_gpio = RDE250_XCV_TUNER,
+ .tuner_sif_gpio = 0x05,
+ .tuner_scl_gpio = 0x1a,
+ .tuner_sda_gpio = 0x1b,
+ .decoder = CX231XX_AVDECODER,
+ .output_mode = OUT_MODE_VIP11,
+ .ctl_pin_status_mask = 0xFFFFFFC4,
+ .agc_analog_digital_select_gpio = 0x0c,
+ .gpio_pin_status_mask = 0x4001000,
+ .tuner_i2c_master = 1,
+ .norm = V4L2_STD_NTSC,
+
+ .input = {{
+ .type = CX231XX_VMUX_TELEVISION,
+ .vmux = CX231XX_VIN_3_1,
+ .amux = CX231XX_AMUX_VIDEO,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_COMPOSITE1,
+ .vmux = CX231XX_VIN_2_1,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_SVIDEO,
+ .vmux = CX231XX_VIN_1_1 |
+ (CX231XX_VIN_1_2 << 8) |
+ CX25840_SVIDEO_ON,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ } },
+ },
};
const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
@@ -553,6 +624,10 @@ struct usb_device_id cx231xx_id_table[] = {
.driver_info = CX231XX_BOARD_CNXT_RDE_250},
{USB_DEVICE(0x0572, 0x58A0),
.driver_info = CX231XX_BOARD_CNXT_RDU_250},
+ {USB_DEVICE(0x2040, 0xb110),
+ .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
+ {USB_DEVICE(0x2040, 0xb111),
+ .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
{USB_DEVICE(0x2040, 0xb120),
.driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
{USB_DEVICE(0x2040, 0xb140),
@@ -1051,6 +1126,9 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
if (assoc_desc->bFirstInterface != ifnum) {
cx231xx_err(DRIVER_NAME ": Not found "
"matching IAD interface\n");
+ cx231xx_devused &= ~(1 << nr);
+ kfree(dev);
+ dev = NULL;
return -ENODEV;
}
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
index abe500f..d4457f9 100644
--- a/drivers/media/video/cx231xx/cx231xx-core.c
+++ b/drivers/media/video/cx231xx/cx231xx-core.c
@@ -742,6 +742,8 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_HAUPPAUGE_EXETER:
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
break;
default:
@@ -1381,6 +1383,8 @@ int cx231xx_dev_init(struct cx231xx *dev)
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_HAUPPAUGE_EXETER:
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+ case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
break;
default:
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index a69c24d..6e81f97 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -29,7 +29,6 @@
#include <linux/bitmap.h>
#include <linux/usb.h>
#include <linux/i2c.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -45,7 +44,7 @@
#include "cx231xx.h"
#include "cx231xx-vbi.h"
-#define CX231XX_VERSION_CODE KERNEL_VERSION(0, 0, 1)
+#define CX231XX_VERSION "0.0.2"
#define DRIVER_AUTHOR "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
#define DRIVER_DESC "Conexant cx231xx based USB video device driver"
@@ -70,6 +69,7 @@ do {\
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX231XX_VERSION);
static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
@@ -1179,7 +1179,8 @@ static int vidioc_enum_input(struct file *file, void *priv,
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
- unsigned int n;
+ u32 gen_stat;
+ unsigned int ret, n;
n = i->index;
if (n >= MAX_CX231XX_INPUT)
@@ -1198,6 +1199,18 @@ static int vidioc_enum_input(struct file *file, void *priv,
i->std = dev->vdev->tvnorms;
+ /* If they are asking about the active input, read signal status */
+ if (n == dev->video_input) {
+ ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+ GEN_STAT, 2, &gen_stat, 4);
+ if (ret > 0) {
+ if ((gen_stat & FLD_VPRES) == 0x00)
+ i->status |= V4L2_IN_ST_NO_SIGNAL;
+ if ((gen_stat & FLD_HLOCK) == 0x00)
+ i->status |= V4L2_IN_ST_NO_H_LOCK;
+ }
+ }
+
return 0;
}
@@ -1869,8 +1882,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->version = CX231XX_VERSION_CODE;
-
cap->capabilities = V4L2_CAP_VBI_CAPTURE |
#if 0
V4L2_CAP_SLICED_VBI_CAPTURE |
@@ -2057,7 +2068,6 @@ static int radio_querycap(struct file *file, void *priv,
strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->version = CX231XX_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
return 0;
}
@@ -2570,11 +2580,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
{
int ret;
- cx231xx_info("%s: v4l2 driver version %d.%d.%d\n",
- dev->name,
- (CX231XX_VERSION_CODE >> 16) & 0xff,
- (CX231XX_VERSION_CODE >> 8) & 0xff,
- CX231XX_VERSION_CODE & 0xff);
+ cx231xx_info("%s: v4l2 driver version %s\n",
+ dev->name, CX231XX_VERSION);
/* set default norm */
/*dev->norm = cx231xx_video_template.current_norm; */
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index 46dd840..2000bc6 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -43,7 +43,7 @@
#include "cx231xx-conf-reg.h"
#define DRIVER_NAME "cx231xx"
-#define PWR_SLEEP_INTERVAL 5
+#define PWR_SLEEP_INTERVAL 10
/* I2C addresses for control block in Cx231xx */
#define AFE_DEVICE_ADDRESS 0x60
@@ -67,6 +67,8 @@
#define CX231XX_BOARD_PV_XCAPTURE_USB 11
#define CX231XX_BOARD_KWORLD_UB430_USB_HYBRID 12
#define CX231XX_BOARD_ICONBIT_U100 13
+#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL 14
+#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15
/* Limits minimum and default number of buffers */
#define CX231XX_MIN_BUF 4
@@ -112,7 +114,6 @@
V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \
V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \
V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK)
-#define CX231xx_VERSION_CODE KERNEL_VERSION(0, 0, 2)
#define SLEEP_S5H1432 30
#define CX23417_OSC_EN 8
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index caab1bf..b391e9b 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -38,7 +38,7 @@ config VIDEO_CX23885
config MEDIA_ALTERA_CI
tristate "Altera FPGA based CI module"
depends on VIDEO_CX23885 && DVB_CORE
- select STAPL_ALTERA
+ select ALTERA_STAPL
---help---
An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 23293c7..f81f279 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -2,14 +2,14 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
- cx23885-f300.o
+ cx23885-f300.o cx23885-alsa.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx23885/altera-ci.c b/drivers/media/video/cx23885/altera-ci.c
index 678539b..1fa8927 100644
--- a/drivers/media/video/cx23885/altera-ci.c
+++ b/drivers/media/video/cx23885/altera-ci.c
@@ -52,7 +52,6 @@
* | DATA7| DATA6| DATA5| DATA4| DATA3| DATA2| DATA1| DATA0|
* +-------+-------+-------+-------+-------+-------+-------+-------+
*/
-#include <linux/version.h>
#include <media/videobuf-dma-sg.h>
#include <media/videobuf-dvb.h>
#include "altera-ci.h"
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 9a98dc5..67c4a59 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -1359,7 +1359,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->version = CX23885_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 934185c..c3cf089 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -25,15 +25,21 @@
#include <linux/delay.h>
#include <media/cx25840.h>
#include <linux/firmware.h>
+#include <misc/altera.h>
-#include "../../../staging/altera-stapl/altera.h"
#include "cx23885.h"
#include "tuner-xc2028.h"
+#include "netup-eeprom.h"
#include "netup-init.h"
#include "altera-ci.h"
+#include "xc4000.h"
#include "xc5000.h"
#include "cx23888-ir.h"
+static unsigned int netup_card_rev = 1;
+module_param(netup_card_rev, int, 0644);
+MODULE_PARM_DESC(netup_card_rev,
+ "NetUP Dual DVB-T/C CI card revision");
static unsigned int enable_885_ir;
module_param(enable_885_ir, int, 0644);
MODULE_PARM_DESC(enable_885_ir,
@@ -100,12 +106,14 @@ struct cx23885_board cx23885_boards[] = {
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN5_CH2 |
CX25840_VIN2_CH1,
+ .amux = CX25840_AUDIO8,
.gpio0 = 0,
}, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN6_CH1,
+ .amux = CX25840_AUDIO7,
.gpio0 = 0,
}, {
.type = CX23885_VMUX_SVIDEO,
@@ -113,6 +121,7 @@ struct cx23885_board cx23885_boards[] = {
CX25840_VIN4_CH2 |
CX25840_VIN8_CH1 |
CX25840_SVIDEO_ON,
+ .amux = CX25840_AUDIO7,
.gpio0 = 0,
} },
},
@@ -147,7 +156,30 @@ struct cx23885_board cx23885_boards[] = {
},
[CX23885_BOARD_HAUPPAUGE_HVR1500] = {
.name = "Hauppauge WinTV-HVR1500",
+ .porta = CX23885_ANALOG_VIDEO,
.portc = CX23885_MPEG_DVB,
+ .tuner_type = TUNER_XC2028,
+ .tuner_addr = 0x61, /* 0xc2 >> 1 */
+ .input = {{
+ .type = CX23885_VMUX_TELEVISION,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN5_CH2 |
+ CX25840_VIN2_CH1,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN6_CH1,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN8_CH1 |
+ CX25840_SVIDEO_ON,
+ .gpio0 = 0,
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1200] = {
.name = "Hauppauge WinTV-HVR1200",
@@ -175,6 +207,34 @@ struct cx23885_board cx23885_boards[] = {
.name = "Leadtek Winfast PxDVR3200 H",
.portc = CX23885_MPEG_DVB,
},
+ [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
+ .name = "Leadtek Winfast PxDVR3200 H XC4000",
+ .porta = CX23885_ANALOG_VIDEO,
+ .portc = CX23885_MPEG_DVB,
+ .tuner_type = TUNER_XC4000,
+ .tuner_addr = 0x61,
+ .radio_type = TUNER_XC4000,
+ .radio_addr = 0x61,
+ .input = {{
+ .type = CX23885_VMUX_TELEVISION,
+ .vmux = CX25840_VIN2_CH1 |
+ CX25840_VIN5_CH2 |
+ CX25840_NONE0_CH3,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_COMPOSITE1,
+ }, {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_SVIDEO_LUMA3 |
+ CX25840_SVIDEO_CHROMA4,
+ }, {
+ .type = CX23885_VMUX_COMPONENT,
+ .vmux = CX25840_VIN7_CH1 |
+ CX25840_VIN6_CH2 |
+ CX25840_VIN8_CH3 |
+ CX25840_COMPONENT_ON,
+ } },
+ },
[CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
.name = "Compro VideoMate E650F",
.portc = CX23885_MPEG_DVB,
@@ -353,6 +413,31 @@ struct cx23885_board cx23885_boards[] = {
.vmux = CX25840_COMPOSITE1,
} },
},
+ [CX23885_BOARD_MPX885] = {
+ .name = "MPX-885",
+ .porta = CX23885_ANALOG_VIDEO,
+ .input = {{
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_COMPOSITE1,
+ .amux = CX25840_AUDIO6,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE2,
+ .vmux = CX25840_COMPOSITE2,
+ .amux = CX25840_AUDIO6,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE3,
+ .vmux = CX25840_COMPOSITE3,
+ .amux = CX25840_AUDIO7,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE4,
+ .vmux = CX25840_COMPOSITE4,
+ .amux = CX25840_AUDIO7,
+ .gpio0 = 0,
+ } },
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -433,6 +518,10 @@ struct cx23885_subid cx23885_subids[] = {
.subdevice = 0x6681,
.card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
}, {
+ .subvendor = 0x107d,
+ .subdevice = 0x6f39,
+ .card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000,
+ }, {
.subvendor = 0x185b,
.subdevice = 0xe800,
.card = CX23885_BOARD_COMPRO_VIDEOMATE_E650F,
@@ -749,6 +838,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
@@ -909,6 +999,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
cx_set(GP0_IO, 0x000f000f);
break;
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
@@ -1097,12 +1188,19 @@ int cx23885_ir_init(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1200:
case CX23885_BOARD_HAUPPAUGE_HVR1400:
- case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1275:
case CX23885_BOARD_HAUPPAUGE_HVR1255:
case CX23885_BOARD_HAUPPAUGE_HVR1210:
/* FIXME: Implement me */
break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
+ ret = cx23888_ir_probe(dev);
+ if (ret)
+ break;
+ dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
+ v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+ ir_rx_pin_cfg_count, ir_rx_pin_cfg);
+ break;
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
ret = cx23888_ir_probe(dev);
@@ -1156,6 +1254,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
void cx23885_ir_fini(struct cx23885_dev *dev)
{
switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
cx23885_irq_remove(dev, PCI_MSK_IR);
@@ -1199,6 +1298,7 @@ int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
{
switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
if (dev->sd_ir)
@@ -1325,6 +1425,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_HAUPPAUGE_HVR1400:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1275:
@@ -1353,16 +1454,20 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_MYGICA_X8506:
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ case CX23885_BOARD_MPX885:
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[2].i2c_adap,
"cx25840", 0x88 >> 1, NULL);
@@ -1383,6 +1488,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
const struct firmware *fw;
const char *filename = "dvb-netup-altera-01.fw";
char *action = "configure";
+ static struct netup_card_info cinfo;
struct altera_config netup_config = {
.dev = dev,
.action = action,
@@ -1391,6 +1497,21 @@ void cx23885_card_setup(struct cx23885_dev *dev)
netup_initialize(dev);
+ netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+ if (netup_card_rev)
+ cinfo.rev = netup_card_rev;
+
+ switch (cinfo.rev) {
+ case 0x4:
+ filename = "dvb-netup-altera-04.fw";
+ break;
+ default:
+ filename = "dvb-netup-altera-01.fw";
+ break;
+ }
+ printk(KERN_INFO "NetUP card rev=0x%x fw_filename=%s\n",
+ cinfo.rev, filename);
+
ret = request_firmware(&fw, filename, &dev->pci->dev);
if (ret != 0)
printk(KERN_ERR "did not find the firmware file. (%s) "
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index 419777a..40e68b2 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -42,6 +42,7 @@
MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX23885_VERSION);
static unsigned int debug;
module_param(debug, int, 0644);
@@ -53,7 +54,7 @@ MODULE_PARM_DESC(card, "card type");
#define dprintk(level, fmt, arg...)\
do { if (debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+ printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
} while (0)
static unsigned int cx23885_devcount;
@@ -154,12 +155,12 @@ static struct sram_channel cx23885_sram_channels[] = {
.cnt2_reg = DMA5_CNT2,
},
[SRAM_CH07] = {
- .name = "ch7",
- .cmds_start = 0x0,
- .ctrl_start = 0x0,
- .cdt = 0x0,
- .fifo_start = 0x0,
- .fifo_size = 0x0,
+ .name = "TV Audio",
+ .cmds_start = 0x10190,
+ .ctrl_start = 0x10480,
+ .cdt = 0x10a00,
+ .fifo_start = 0x7000,
+ .fifo_size = 0x1000,
.ptr1_reg = DMA6_PTR1,
.ptr2_reg = DMA6_PTR2,
.cnt1_reg = DMA6_CNT1,
@@ -1081,10 +1082,10 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
- unsigned int lines)
+ unsigned int lines, unsigned int lpi)
{
struct scatterlist *sg;
- unsigned int line, todo;
+ unsigned int line, todo, sol;
/* sync instruction */
if (sync_line != NO_SYNC_LINE)
@@ -1097,16 +1098,22 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
offset -= sg_dma_len(sg);
sg++;
}
+
+ if (lpi && line > 0 && !(line % lpi))
+ sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+ else
+ sol = RISC_SOL;
+
if (bpl <= sg_dma_len(sg)-offset) {
/* fits into current chunk */
- *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+ *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
offset += bpl;
} else {
/* scanline needs to be split */
todo = bpl;
- *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
+ *(rp++) = cpu_to_le32(RISC_WRITE|sol|
(sg_dma_len(sg)-offset));
*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
@@ -1163,10 +1170,10 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
rp = risc->cpu;
if (UNSET != top_offset)
rp = cx23885_risc_field(rp, sglist, top_offset, 0,
- bpl, padding, lines);
+ bpl, padding, lines, 0);
if (UNSET != bottom_offset)
rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
- bpl, padding, lines);
+ bpl, padding, lines, 0);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -1174,11 +1181,11 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
-static int cx23885_risc_databuffer(struct pci_dev *pci,
+int cx23885_risc_databuffer(struct pci_dev *pci,
struct btcx_riscmem *risc,
struct scatterlist *sglist,
unsigned int bpl,
- unsigned int lines)
+ unsigned int lines, unsigned int lpi)
{
u32 instructions;
__le32 *rp;
@@ -1198,7 +1205,55 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
/* write risc instructions */
rp = risc->cpu;
- rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+ rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
+ bpl, 0, lines, lpi);
+
+ /* save pointer to jmp instruction address */
+ risc->jmp = rp;
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+ return 0;
+}
+
+int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int top_offset,
+ unsigned int bottom_offset, unsigned int bpl,
+ unsigned int padding, unsigned int lines)
+{
+ u32 instructions, fields;
+ __le32 *rp;
+ int rc;
+
+ fields = 0;
+ if (UNSET != top_offset)
+ fields++;
+ if (UNSET != bottom_offset)
+ fields++;
+
+ /* estimate risc mem: worst case is one write per page border +
+ one write per scan line + syncs + jump (all 2 dwords). Padding
+ can cause next bpl to start close to a page border. First DMA
+ region may be smaller than PAGE_SIZE */
+ /* write and jump need and extra dword */
+ instructions = fields * (1 + ((bpl + padding) * lines)
+ / PAGE_SIZE + lines);
+ instructions += 2;
+ rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+ if (rc < 0)
+ return rc;
+ /* write risc instructions */
+ rp = risc->cpu;
+
+ /* Sync to line 6, so US CC line 21 will appear in line '12'
+ * in the userland vbi payload */
+ if (UNSET != top_offset)
+ rp = cx23885_risc_field(rp, sglist, top_offset, 6,
+ bpl, padding, lines, 0);
+
+ if (UNSET != bottom_offset)
+ rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
+ bpl, padding, lines, 0);
+
+
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -1206,6 +1261,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
return 0;
}
+
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
@@ -1516,7 +1572,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
goto fail;
cx23885_risc_databuffer(dev->pci, &buf->risc,
videobuf_to_dma(&buf->vb)->sglist,
- buf->vb.width, buf->vb.height);
+ buf->vb.width, buf->vb.height, 0);
}
buf->vb.state = VIDEOBUF_PREPARED;
return 0;
@@ -1740,15 +1796,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
struct cx23885_tsport *ts2 = &dev->ts2;
u32 pci_status, pci_mask;
u32 vida_status, vida_mask;
+ u32 audint_status, audint_mask;
u32 ts1_status, ts1_mask;
u32 ts2_status, ts2_mask;
int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+ int audint_count = 0;
bool subdev_handled;
pci_status = cx_read(PCI_INT_STAT);
pci_mask = cx23885_irq_get_mask(dev);
vida_status = cx_read(VID_A_INT_STAT);
vida_mask = cx_read(VID_A_INT_MSK);
+ audint_status = cx_read(AUDIO_INT_INT_STAT);
+ audint_mask = cx_read(AUDIO_INT_INT_MSK);
ts1_status = cx_read(VID_B_INT_STAT);
ts1_mask = cx_read(VID_B_INT_MSK);
ts2_status = cx_read(VID_C_INT_STAT);
@@ -1758,12 +1818,15 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
goto out;
vida_count = cx_read(VID_A_GPCNT);
+ audint_count = cx_read(AUD_INT_A_GPCNT);
ts1_count = cx_read(ts1->reg_gpcnt);
ts2_count = cx_read(ts2->reg_gpcnt);
dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n",
pci_status, pci_mask);
dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
vida_status, vida_mask, vida_count);
+ dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
+ audint_status, audint_mask, audint_count);
dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n",
ts1_status, ts1_mask, ts1_count);
dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
@@ -1860,6 +1923,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
if (vida_status)
handled += cx23885_video_irq(dev, vida_status);
+ if (audint_status)
+ handled += cx23885_audio_irq(dev, audint_status, audint_mask);
+
if (pci_status & PCI_MSK_IR) {
subdev_handled = false;
v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
@@ -2147,14 +2213,8 @@ static struct pci_driver cx23885_pci_driver = {
static int __init cx23885_init(void)
{
- printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n",
- (CX23885_VERSION_CODE >> 16) & 0xff,
- (CX23885_VERSION_CODE >> 8) & 0xff,
- CX23885_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "cx23885: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "cx23885 driver version %s loaded\n",
+ CX23885_VERSION);
return pci_register_driver(&cx23885_pci_driver);
}
@@ -2165,5 +2225,3 @@ static void __exit cx23885_fini(void)
module_init(cx23885_init);
module_exit(cx23885_fini);
-
-/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 2b5cd21..f0482b2 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -37,6 +37,7 @@
#include "tda8290.h"
#include "tda18271.h"
#include "lgdt330x.h"
+#include "xc4000.h"
#include "xc5000.h"
#include "max2165.h"
#include "tda10048.h"
@@ -921,6 +922,31 @@ static int dvb_register(struct cx23885_tsport *port)
fe->ops.tuner_ops.set_config(fe, &ctl);
}
break;
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+ i2c_bus = &dev->i2c_bus[0];
+
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &dvico_fusionhdtv_xc3028,
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ struct dvb_frontend *fe;
+ struct xc4000_config cfg = {
+ .i2c_address = 0x61,
+ .default_pm = 0,
+ .dvb_amplitude = 134,
+ .set_smoothedcvbs = 1,
+ .if_khz = 4560
+ };
+
+ fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
+ &dev->i2c_bus[1].i2c_adap, &cfg);
+ if (!fe) {
+ printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+ dev->name);
+ goto frontend_detach;
+ }
+ }
+ break;
case CX23885_BOARD_TBS_6920:
i2c_bus = &dev->i2c_bus[1];
@@ -1249,7 +1275,7 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
* implement MFE support.
*/
fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
- if (fe0->dvb.frontend)
+ if (fe0 && fe0->dvb.frontend)
videobuf_dvb_unregister_bus(&port->frontends);
switch (port->dev->board) {
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 307ff54..0ff7a9e 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -287,6 +287,7 @@ static char *i2c_devs[128] = {
[0x32 >> 1] = "cx24227",
[0x88 >> 1] = "cx25837",
[0x84 >> 1] = "tda8295",
+ [0x98 >> 1] = "flatiron",
[0xa0 >> 1] = "eeprom",
[0xc0 >> 1] = "tuner/mt2131/tda8275",
[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index e97cafd..ce765e3 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -82,6 +82,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
return;
switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_TEVII_S470:
@@ -133,6 +134,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_HAUPPAUGE_HVR1250:
@@ -229,6 +231,9 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev)
v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
}
+ flush_work_sync(&dev->cx25840_work);
+ flush_work_sync(&dev->ir_rx_work);
+ flush_work_sync(&dev->ir_tx_work);
}
static void cx23885_input_ir_close(struct rc_dev *rc)
@@ -257,6 +262,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
return -ENODEV;
switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_HAUPPAUGE_HVR1250:
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index c87ac68..a99936e 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -203,6 +203,7 @@ Channel manager Data Structure entry = 20 DWORD
#define SD2_BIAS_CTRL 0x0000000A
#define AMP_BIAS_CTRL 0x0000000C
#define CH_PWR_CTRL1 0x0000000E
+#define FLD_CH_SEL (1 << 3)
#define CH_PWR_CTRL2 0x0000000F
#define DSM_STATUS1 0x00000010
#define DSM_STATUS2 0x00000011
@@ -271,7 +272,9 @@ Channel manager Data Structure entry = 20 DWORD
#define VID_BC_MSK_OPC_ERR (1 << 16)
#define VID_BC_MSK_SYNC (1 << 12)
#define VID_BC_MSK_OF (1 << 8)
+#define VID_BC_MSK_VBI_RISCI2 (1 << 5)
#define VID_BC_MSK_RISCI2 (1 << 4)
+#define VID_BC_MSK_VBI_RISCI1 (1 << 1)
#define VID_BC_MSK_RISCI1 1
#define VID_C_INT_MSK 0x00040040
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c
index c0b6038..a1154f0 100644
--- a/drivers/media/video/cx23885/cx23885-vbi.c
+++ b/drivers/media/video/cx23885/cx23885-vbi.c
@@ -41,6 +41,12 @@ MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
/* ------------------------------------------------------------------ */
+#define VBI_LINE_LENGTH 1440
+#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */
+#define NTSC_VBI_END_LINE 21
+#define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
+
+
int cx23885_vbi_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
@@ -49,43 +55,86 @@ int cx23885_vbi_fmt(struct file *file, void *priv,
if (dev->tvnorm & V4L2_STD_525_60) {
/* ntsc */
- f->fmt.vbi.sampling_rate = 28636363;
+ f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+ f->fmt.vbi.sampling_rate = 27000000;
+ f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+ f->fmt.vbi.offset = 0;
+ f->fmt.vbi.flags = 0;
f->fmt.vbi.start[0] = 10;
- f->fmt.vbi.start[1] = 273;
-
+ f->fmt.vbi.count[0] = 17;
+ f->fmt.vbi.start[1] = 263 + 10 + 1;
+ f->fmt.vbi.count[1] = 17;
} else if (dev->tvnorm & V4L2_STD_625_50) {
/* pal */
f->fmt.vbi.sampling_rate = 35468950;
f->fmt.vbi.start[0] = 7 - 1;
f->fmt.vbi.start[1] = 319 - 1;
}
+
return 0;
}
+/* We're given the Video Interrupt status register.
+ * The cx23885_video_irq() func has already validated
+ * the potential error bits, we just need to
+ * deal with vbi payload and return indication if
+ * we actually processed any payload.
+ */
+int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
+{
+ u32 count;
+ int handled = 0;
+
+ if (status & VID_BC_MSK_VBI_RISCI1) {
+ dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
+ spin_lock(&dev->slock);
+ count = cx_read(VID_A_GPCNT);
+ cx23885_video_wakeup(dev, &dev->vbiq, count);
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+
+ if (status & VID_BC_MSK_VBI_RISCI2) {
+ dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
+ dprintk(2, "stopper vbi\n");
+ spin_lock(&dev->slock);
+ cx23885_restart_vbi_queue(dev, &dev->vbiq);
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+
+ return handled;
+}
+
static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q,
struct cx23885_buffer *buf)
{
+ dprintk(1, "%s()\n", __func__);
+
/* setup fifo + format */
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
buf->vb.width, buf->risc.dma);
/* reset counter */
+ cx_write(VID_A_GPCNT_CTL, 3);
+ cx_write(VID_A_VBI_CTRL, 3);
+ cx_write(VBI_A_GPCNT_CTL, 3);
q->count = 1;
- /* enable irqs */
+ /* enable irq */
cx23885_irq_add_enable(dev, 0x01);
cx_set(VID_A_INT_MSK, 0x000022);
/* start dma */
cx_set(DEV_CNTRL2, (1<<5));
- cx_set(VID_A_DMA_CTL, 0x00000022);
+ cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
return 0;
}
-static int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q)
{
struct cx23885_buffer *buf;
@@ -102,7 +151,7 @@ static int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
buf = list_entry(item, struct cx23885_buffer, vb.queue);
buf->count = q->count++;
}
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
return 0;
}
@@ -113,8 +162,7 @@ void cx23885_vbi_timeout(unsigned long data)
struct cx23885_buffer *buf;
unsigned long flags;
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]);
-
+ /* Stop the VBI engine */
cx_clear(VID_A_DMA_CTL, 0x22);
spin_lock_irqsave(&dev->slock, flags);
@@ -132,7 +180,7 @@ void cx23885_vbi_timeout(unsigned long data)
}
/* ------------------------------------------------------------------ */
-#define VBI_LINE_LENGTH 2048
+#define VBI_LINE_LENGTH 1440
#define VBI_LINE_COUNT 17
static int
@@ -173,7 +221,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
rc = videobuf_iolock(q, &buf->vb, NULL);
if (0 != rc)
goto fail;
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ cx23885_risc_vbibuffer(dev->pci, &buf->risc,
dma->sglist,
0, buf->vb.width * buf->vb.height,
buf->vb.width, 0,
@@ -207,7 +255,7 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
cx23885_start_vbi_dma(dev, q, buf);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
dprintk(2, "[%p/%d] vbi_queue - first active\n",
buf, buf->vb.i);
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index ee57f6b..e730b92 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -37,6 +37,8 @@
#include "cx23885-ioctl.h"
#include "tuner-xc2028.h"
+#include <media/cx25840.h>
+
MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
@@ -69,14 +71,14 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
#define dprintk(level, fmt, arg...)\
do { if (video_debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+ printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
} while (0)
/* ------------------------------------------------------------------- */
/* static data */
#define FORMAT_FLAGS_PACKED 0x01
-
+#if 0
static struct cx23885_fmt formats[] = {
{
.name = "8 bpp, gray",
@@ -130,6 +132,23 @@ static struct cx23885_fmt formats[] = {
.flags = FORMAT_FLAGS_PACKED,
},
};
+#else
+static struct cx23885_fmt formats[] = {
+ {
+#if 0
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+#endif
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ }
+};
+#endif
static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
{
@@ -139,7 +158,12 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
if (formats[i].fourcc == fourcc)
return formats+i;
- printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+ printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
+ (fourcc & 0xff),
+ ((fourcc >> 8) & 0xff),
+ ((fourcc >> 16) & 0xff),
+ ((fourcc >> 24) & 0xff)
+ );
return NULL;
}
@@ -171,7 +195,7 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.id = V4L2_CID_CONTRAST,
.name = "Contrast",
.minimum = 0,
- .maximum = 0xff,
+ .maximum = 0x7f,
.step = 1,
.default_value = 0x3f,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -184,10 +208,10 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.v = {
.id = V4L2_CID_HUE,
.name = "Hue",
- .minimum = 0,
- .maximum = 0xff,
+ .minimum = -127,
+ .maximum = 128,
.step = 1,
- .default_value = 0x7f,
+ .default_value = 0x0,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 128,
@@ -202,9 +226,9 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.id = V4L2_CID_SATURATION,
.name = "Saturation",
.minimum = 0,
- .maximum = 0xff,
+ .maximum = 0x7f,
.step = 1,
- .default_value = 0x7f,
+ .default_value = 0x3f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 0,
@@ -258,8 +282,8 @@ static const u32 *ctrl_classes[] = {
NULL
};
-static void cx23885_video_wakeup(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q, u32 count)
+void cx23885_video_wakeup(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q, u32 count)
{
struct cx23885_buffer *buf;
int bc;
@@ -393,6 +417,71 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
mutex_unlock(&dev->lock);
}
+static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+{
+ /* 8 bit registers, 8 bit values */
+ u8 buf[] = { reg, data };
+
+ struct i2c_msg msg = { .addr = 0x98 >> 1,
+ .flags = 0, .buf = buf, .len = 2 };
+
+ return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+{
+ /* 8 bit registers, 8 bit values */
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+
+ struct i2c_msg msg[] = {
+ { .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
+ if (ret != 2)
+ printk(KERN_ERR "%s() error\n", __func__);
+
+ return b1[0];
+}
+
+static void cx23885_flatiron_dump(struct cx23885_dev *dev)
+{
+ int i;
+ dprintk(1, "Flatiron dump\n");
+ for (i = 0; i < 0x24; i++) {
+ dprintk(1, "FI[%02x] = %02x\n", i,
+ cx23885_flatiron_read(dev, i));
+ }
+}
+
+static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
+{
+ u8 val;
+ dprintk(1, "%s(input = %d)\n", __func__, input);
+
+ if (input == 1)
+ val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
+ else if (input == 2)
+ val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
+ else
+ return -EINVAL;
+
+ val |= 0x20; /* Enable clock to delta-sigma and dec filter */
+
+ cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
+
+ /* Wake up */
+ cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
+
+ if (video_debug)
+ cx23885_flatiron_dump(dev);
+
+ return 0;
+}
+
static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
{
dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
@@ -413,27 +502,59 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
INPUT(input)->vmux, 0, 0);
+ if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
+ (dev->board == CX23885_BOARD_MPX885)) {
+ /* Configure audio routing */
+ v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
+ INPUT(input)->amux, 0, 0);
+
+ if (INPUT(input)->amux == CX25840_AUDIO7)
+ cx23885_flatiron_mux(dev, 1);
+ else if (INPUT(input)->amux == CX25840_AUDIO6)
+ cx23885_flatiron_mux(dev, 2);
+ }
+
return 0;
}
-/* ------------------------------------------------------------------ */
-static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
- unsigned int height, enum v4l2_field field)
+static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
{
- dprintk(1, "%s()\n", __func__);
+ dprintk(1, "%s(input=%d)\n", __func__, input);
+
+ /* The baseband video core of the cx23885 has two audio inputs.
+ * LR1 and LR2. In almost every single case so far only HVR1xxx
+ * cards we've only ever supported LR1. Time to support LR2,
+ * which is available via the optional white breakout header on
+ * the board.
+ * We'll use a could of existing enums in the card struct to allow
+ * devs to specify which baseband input they need, or just default
+ * to what we've always used.
+ */
+ if (INPUT(input)->amux == CX25840_AUDIO7)
+ cx23885_flatiron_mux(dev, 1);
+ else if (INPUT(input)->amux == CX25840_AUDIO6)
+ cx23885_flatiron_mux(dev, 2);
+ else {
+ /* Not specifically defined, assume the default. */
+ cx23885_flatiron_mux(dev, 1);
+ }
+
return 0;
}
+/* ------------------------------------------------------------------ */
static int cx23885_start_video_dma(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q,
struct cx23885_buffer *buf)
{
dprintk(1, "%s()\n", __func__);
+ /* Stop the dma/fifo before we tamper with it's risc programs */
+ cx_clear(VID_A_DMA_CTL, 0x11);
+
/* setup fifo + format */
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
buf->bpl, buf->risc.dma);
- cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
/* reset counter */
cx_write(VID_A_GPCNT_CTL, 3);
@@ -748,7 +869,7 @@ static int video_open(struct file *file)
fh->type = type;
fh->width = 320;
fh->height = 240;
- fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV);
videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
&dev->pci->dev, &dev->slock,
@@ -757,6 +878,14 @@ static int video_open(struct file *file)
sizeof(struct cx23885_buffer),
fh, NULL);
+ videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB,
+ sizeof(struct cx23885_buffer),
+ fh, NULL);
+
+
dprintk(1, "post videobuf_queue_init()\n");
return 0;
@@ -884,8 +1013,9 @@ static int cx23885_get_control(struct cx23885_dev *dev,
static int cx23885_set_control(struct cx23885_dev *dev,
struct v4l2_control *ctl)
{
- dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
- " (disabled - no action)\n", __func__);
+ dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
+ call_all(dev, core, s_ctrl, ctl);
+
return 0;
}
@@ -1000,7 +1130,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->card, cx23885_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
- cap->version = CX23885_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
@@ -1060,13 +1189,22 @@ static int vidioc_streamon(struct file *file, void *priv,
struct cx23885_dev *dev = fh->dev;
dprintk(1, "%s()\n", __func__);
- if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+ if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
return -EINVAL;
if (unlikely(i != fh->type))
return -EINVAL;
if (unlikely(!res_get(dev, fh, get_resource(fh))))
return -EBUSY;
+
+ /* Don't start VBI streaming unless vida streaming
+ * has already started.
+ */
+ if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
+ ((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
+ return -EINVAL;
+
return videobuf_streamon(get_queue(fh));
}
@@ -1077,7 +1215,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
int err, res;
dprintk(1, "%s()\n", __func__);
- if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
return -EINVAL;
if (i != fh->type)
return -EINVAL;
@@ -1120,7 +1259,7 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
dprintk(1, "%s()\n", __func__);
n = i->index;
- if (n >= 4)
+ if (n >= MAX_CX23885_INPUT)
return -EINVAL;
if (0 == INPUT(n)->type)
@@ -1134,6 +1273,11 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
i->type = V4L2_INPUT_TYPE_TUNER;
i->std = CX23885_NORMS;
}
+
+ /* Two selectable audio inputs for non-tv inputs */
+ if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
+ i->audioset = 0x3;
+
return 0;
}
@@ -1160,13 +1304,20 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
dprintk(1, "%s(%d)\n", __func__, i);
- if (i >= 4) {
+ if (i >= MAX_CX23885_INPUT) {
dprintk(1, "%s() -EINVAL\n", __func__);
return -EINVAL;
}
+ if (INPUT(i)->type == 0)
+ return -EINVAL;
+
mutex_lock(&dev->lock);
cx23885_video_mux(dev, i);
+
+ /* By default establish the default audio input for the card also */
+ /* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
+ cx23885_audio_mux(dev, i);
mutex_unlock(&dev->lock);
return 0;
}
@@ -1186,6 +1337,64 @@ static int vidioc_log_status(struct file *file, void *priv)
return 0;
}
+static int cx23885_query_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ static const char *iname[] = {
+ [0] = "Baseband L/R 1",
+ [1] = "Baseband L/R 2",
+ };
+ unsigned int n;
+ dprintk(1, "%s()\n", __func__);
+
+ n = i->index;
+ if (n >= 2)
+ return -EINVAL;
+
+ memset(i, 0, sizeof(*i));
+ i->index = n;
+ strcpy(i->name, iname[n]);
+ i->capability = V4L2_AUDCAP_STEREO;
+ i->mode = V4L2_AUDMODE_AVL;
+ return 0;
+
+}
+
+static int vidioc_enum_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_g_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+ i->index = dev->audinput;
+ dprintk(1, "%s(input=%d)\n", __func__, i->index);
+
+ return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_s_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ if (i->index >= 2)
+ return -EINVAL;
+
+ dprintk(1, "%s(%d)\n", __func__, i->index);
+
+ dev->audinput = i->index;
+
+ /* Skip the audio defaults from the cards struct, caller wants
+ * directly touch the audio mux hardware. */
+ cx23885_flatiron_mux(dev, dev->audinput + 1);
+ return 0;
+}
+
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qctrl)
{
@@ -1222,10 +1431,8 @@ static int vidioc_g_tuner(struct file *file, void *priv,
return -EINVAL;
strcpy(t->name, "Television");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL;
- t->signal = 0xffff ; /* LOCKED */
+
+ call_all(dev, tuner, g_tuner, t);
return 0;
}
@@ -1238,6 +1445,9 @@ static int vidioc_s_tuner(struct file *file, void *priv,
return -EINVAL;
if (0 != t->index)
return -EINVAL;
+ /* Update the A/V core */
+ call_all(dev, tuner, s_tuner, t);
+
return 0;
}
@@ -1303,10 +1513,6 @@ static void cx23885_vid_timeout(unsigned long data)
struct cx23885_buffer *buf;
unsigned long flags;
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
-
- cx_clear(VID_A_DMA_CTL, 0x11);
-
spin_lock_irqsave(&dev->slock, flags);
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next,
@@ -1314,7 +1520,7 @@ static void cx23885_vid_timeout(unsigned long data)
list_del(&buf->vb.queue);
buf->vb.state = VIDEOBUF_ERROR;
wake_up(&buf->vb.done);
- printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n",
+ printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
dev->name, buf, buf->vb.i,
(unsigned long)buf->risc.dma);
}
@@ -1330,27 +1536,43 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
mask = cx_read(VID_A_INT_MSK);
if (0 == (status & mask))
return handled;
+
cx_write(VID_A_INT_STAT, status);
- dprintk(2, "%s() status = 0x%08x\n", __func__, status);
- /* risc op code error */
- if (status & (1 << 16)) {
- printk(KERN_WARNING "%s/0: video risc op code error\n",
- dev->name);
- cx_clear(VID_A_DMA_CTL, 0x11);
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
+ /* risc op code error, fifo overflow or line sync detection error */
+ if ((status & VID_BC_MSK_OPC_ERR) ||
+ (status & VID_BC_MSK_SYNC) ||
+ (status & VID_BC_MSK_OF)) {
+
+ if (status & VID_BC_MSK_OPC_ERR) {
+ dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+ VID_BC_MSK_OPC_ERR);
+ printk(KERN_WARNING "%s: video risc op code error\n",
+ dev->name);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[SRAM_CH01]);
+ }
+
+ if (status & VID_BC_MSK_SYNC)
+ dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
+ "video lines miss-match\n",
+ VID_BC_MSK_SYNC);
+
+ if (status & VID_BC_MSK_OF)
+ dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
+ VID_BC_MSK_OF);
+
}
- /* risc1 y */
- if (status & 0x01) {
+ /* Video */
+ if (status & VID_BC_MSK_RISCI1) {
spin_lock(&dev->slock);
count = cx_read(VID_A_GPCNT);
cx23885_video_wakeup(dev, &dev->vidq, count);
spin_unlock(&dev->slock);
handled++;
}
- /* risc2 y */
- if (status & 0x10) {
+ if (status & VID_BC_MSK_RISCI2) {
dprintk(2, "stopper video\n");
spin_lock(&dev->slock);
cx23885_restart_video_queue(dev, &dev->vidq);
@@ -1358,6 +1580,9 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
handled++;
}
+ /* Allow the VBI framework to process it's payload */
+ handled += cx23885_vbi_irq(dev, status);
+
return handled;
}
@@ -1406,6 +1631,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_g_register = cx23885_g_register,
.vidioc_s_register = cx23885_s_register,
#endif
+ .vidioc_enumaudio = vidioc_enum_audinput,
+ .vidioc_g_audio = vidioc_g_audinput,
+ .vidioc_s_audio = vidioc_s_audinput,
};
static struct video_device cx23885_vbi_template;
@@ -1430,6 +1658,14 @@ void cx23885_video_unregister(struct cx23885_dev *dev)
dprintk(1, "%s()\n", __func__);
cx23885_irq_remove(dev, 0x01);
+ if (dev->vbi_dev) {
+ if (video_is_registered(dev->vbi_dev))
+ video_unregister_device(dev->vbi_dev);
+ else
+ video_device_release(dev->vbi_dev);
+ dev->vbi_dev = NULL;
+ btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
+ }
if (dev->video_dev) {
if (video_is_registered(dev->video_dev))
video_unregister_device(dev->video_dev);
@@ -1439,6 +1675,9 @@ void cx23885_video_unregister(struct cx23885_dev *dev)
btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
}
+
+ if (dev->audio_dev)
+ cx23885_audio_unregister(dev);
}
int cx23885_video_register(struct cx23885_dev *dev)
@@ -1464,7 +1703,14 @@ int cx23885_video_register(struct cx23885_dev *dev)
cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
VID_A_DMA_CTL, 0x11, 0x00);
- /* Don't enable VBI yet */
+ /* init vbi dma queues */
+ INIT_LIST_HEAD(&dev->vbiq.active);
+ INIT_LIST_HEAD(&dev->vbiq.queued);
+ dev->vbiq.timeout.function = cx23885_vbi_timeout;
+ dev->vbiq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->vbiq.timeout);
+ cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
+ VID_A_DMA_CTL, 0x22, 0x00);
cx23885_irq_add_enable(dev, 0x01);
@@ -1505,8 +1751,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
}
}
-
- /* register v4l devices */
+ /* register Video device */
dev->video_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_video_template, "video");
err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
@@ -1516,13 +1761,31 @@ int cx23885_video_register(struct cx23885_dev *dev)
dev->name);
goto fail_unreg;
}
- printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+ printk(KERN_INFO "%s: registered device %s [v4l2]\n",
dev->name, video_device_node_name(dev->video_dev));
+
+ /* register VBI device */
+ dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
+ &cx23885_vbi_template, "vbi");
+ err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+ vbi_nr[dev->nr]);
+ if (err < 0) {
+ printk(KERN_INFO "%s: can't register vbi device\n",
+ dev->name);
+ goto fail_unreg;
+ }
+ printk(KERN_INFO "%s: registered device %s\n",
+ dev->name, video_device_node_name(dev->vbi_dev));
+
+ /* Register ALSA audio device */
+ dev->audio_dev = cx23885_audio_register(dev);
+
/* initial device configuration */
mutex_lock(&dev->lock);
cx23885_set_tvnorm(dev, dev->tvnorm);
init_controls(dev);
cx23885_video_mux(dev, 0);
+ cx23885_audio_mux(dev, 0);
mutex_unlock(&dev->lock);
return 0;
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index c186473..b49036f 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -36,10 +36,9 @@
#include "cx23885-reg.h"
#include "media/cx2341x.h"
-#include <linux/version.h>
#include <linux/mutex.h>
-#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 2)
+#define CX23885_VERSION "0.0.3"
#define UNSET (-1U)
@@ -86,6 +85,8 @@
#define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID 29
#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
+#define CX23885_BOARD_MPX885 32
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
@@ -192,6 +193,7 @@ struct cx23885_buffer {
struct cx23885_input {
enum cx23885_itype type;
unsigned int vmux;
+ unsigned int amux;
u32 gpio0, gpio1, gpio2, gpio3;
};
@@ -318,6 +320,34 @@ struct cx23885_kernel_ir {
struct rc_dev *rc;
};
+struct cx23885_audio_buffer {
+ unsigned int bpl;
+ struct btcx_riscmem risc;
+ struct videobuf_dmabuf dma;
+};
+
+struct cx23885_audio_dev {
+ struct cx23885_dev *dev;
+
+ struct pci_dev *pci;
+
+ struct snd_card *card;
+
+ spinlock_t lock;
+
+ atomic_t count;
+
+ unsigned int dma_size;
+ unsigned int period_size;
+ unsigned int num_periods;
+
+ struct videobuf_dmabuf *dma_risc;
+
+ struct cx23885_audio_buffer *buf;
+
+ struct snd_pcm_substream *substream;
+};
+
struct cx23885_dev {
atomic_t refcount;
struct v4l2_device v4l2_dev;
@@ -362,6 +392,7 @@ struct cx23885_dev {
/* Analog video */
u32 resources;
unsigned int input;
+ unsigned int audinput; /* Selectable audio input */
u32 tvaudio;
v4l2_std_id tvnorm;
unsigned int tuner_type;
@@ -400,6 +431,9 @@ struct cx23885_dev {
atomic_t v4l_reader_count;
struct cx23885_tvnorm encodernorm;
+ /* Analog raw audio */
+ struct cx23885_audio_dev *audio_dev;
+
};
static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
@@ -478,6 +512,11 @@ extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines);
+extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
+ struct btcx_riscmem *risc, struct scatterlist *sglist,
+ unsigned int top_offset, unsigned int bottom_offset,
+ unsigned int bpl, unsigned int padding, unsigned int lines);
+
void cx23885_cancel_buffers(struct cx23885_tsport *port);
extern int cx23885_restart_queue(struct cx23885_tsport *port,
@@ -533,6 +572,8 @@ extern void cx23885_free_buffer(struct videobuf_queue *q,
extern int cx23885_video_register(struct cx23885_dev *dev);
extern void cx23885_video_unregister(struct cx23885_dev *dev);
extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
+extern void cx23885_video_wakeup(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q, u32 count);
/* ----------------------------------------------------------- */
/* cx23885-vbi.c */
@@ -540,6 +581,9 @@ extern int cx23885_vbi_fmt(struct file *file, void *priv,
struct v4l2_format *f);
extern void cx23885_vbi_timeout(unsigned long data);
extern struct videobuf_queue_ops cx23885_vbi_qops;
+extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q);
+extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
/* cx23885-i2c.c */
extern int cx23885_i2c_register(struct cx23885_i2c *bus);
@@ -563,6 +607,18 @@ extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
+/* ----------------------------------------------------------- */
+/* cx23885-alsa.c */
+extern struct cx23885_audio_dev *cx23885_audio_register(
+ struct cx23885_dev *dev);
+extern void cx23885_audio_unregister(struct cx23885_dev *dev);
+extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
+extern int cx23885_risc_databuffer(struct pci_dev *pci,
+ struct btcx_riscmem *risc,
+ struct scatterlist *sglist,
+ unsigned int bpl,
+ unsigned int lines,
+ unsigned int lpi);
/* ----------------------------------------------------------- */
/* tv norms */
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index e37be6f..bb1ce34 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -673,7 +673,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
unsigned int i, n;
union cx23888_ir_fifo_rec *p;
- unsigned u, v;
+ unsigned u, v, w;
n = count / sizeof(union cx23888_ir_fifo_rec)
* sizeof(union cx23888_ir_fifo_rec);
@@ -692,11 +692,12 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
/* Assume RTO was because of no IR light input */
u = 0;
- v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
+ w = 1;
} else {
u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
if (invert)
u = u ? 0 : 1;
+ w = 0;
}
v = (unsigned) pulse_width_count_to_ns(
@@ -707,9 +708,12 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
init_ir_raw_event(&p->ir_core_data);
p->ir_core_data.pulse = u;
p->ir_core_data.duration = v;
+ p->ir_core_data.timeout = w;
- v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n",
- v, u ? "mark" : "space");
+ v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s %s\n",
+ v, u ? "mark" : "space", w ? "(timed out)" : "");
+ if (w)
+ v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
}
return 0;
}
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile
index 2ee96d3..dc40dde 100644
--- a/drivers/media/video/cx25840/Makefile
+++ b/drivers/media/video/cx25840/Makefile
@@ -3,4 +3,4 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 34b96c7..005f110 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -480,6 +480,7 @@ void cx25840_audio_set_path(struct i2c_client *client)
static void set_volume(struct i2c_client *client, int volume)
{
+ struct cx25840_state *state = to_state(i2c_get_clientdata(client));
int vol;
/* Convert the volume to msp3400 values (0-127) */
@@ -495,7 +496,14 @@ static void set_volume(struct i2c_client *client, int volume)
}
/* PATH1_VOLUME */
- cx25840_write(client, 0x8d4, 228 - (vol * 2));
+ if (is_cx2388x(state)) {
+ /* for cx23885 volume doesn't work,
+ * the calculation always results in
+ * e4 regardless.
+ */
+ cx25840_write(client, 0x8d4, volume);
+ } else
+ cx25840_write(client, 0x8d4, 228 - (vol * 2));
}
static void set_balance(struct i2c_client *client, int balance)
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index b7ee2ae..cd99764 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -702,6 +702,13 @@ static void cx231xx_initialize(struct i2c_client *client)
/* start microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0x10);
+
+ /* CC raw enable */
+ cx25840_write(client, 0x404, 0x0b);
+
+ /* CC on */
+ cx25840_write(client, 0x42f, 0x66);
+ cx25840_write4(client, 0x474, 0x1e1e601a);
}
/* ----------------------------------------------------------------------- */
@@ -1067,6 +1074,18 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
cx25840_write(client, 0x919, 0x01);
}
+ if (is_cx2388x(state) && ((aud_input == CX25840_AUDIO7) ||
+ (aud_input == CX25840_AUDIO6))) {
+ /* Configure audio from LR1 or LR2 input */
+ cx25840_write4(client, 0x910, 0);
+ cx25840_write4(client, 0x8d0, 0x63073);
+ } else
+ if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) {
+ /* Configure audio from tuner/sif input */
+ cx25840_write4(client, 0x910, 0x12b000c9);
+ cx25840_write4(client, 0x8d0, 0x1f063870);
+ }
+
return 0;
}
diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c
index 7eb79af..13c380e 100644
--- a/drivers/media/video/cx25840/cx25840-ir.c
+++ b/drivers/media/video/cx25840/cx25840-ir.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/kfifo.h>
+#include <linux/module.h>
#include <media/cx25840.h>
#include <media/rc-core.h>
@@ -668,7 +669,7 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
u16 divider;
unsigned int i, n;
union cx25840_ir_fifo_rec *p;
- unsigned u, v;
+ unsigned u, v, w;
if (ir_state == NULL)
return -ENODEV;
@@ -694,11 +695,12 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
/* Assume RTO was because of no IR light input */
u = 0;
- v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
+ w = 1;
} else {
u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
if (invert)
u = u ? 0 : 1;
+ w = 0;
}
v = (unsigned) pulse_width_count_to_ns(
@@ -709,9 +711,12 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
init_ir_raw_event(&p->ir_core_data);
p->ir_core_data.pulse = u;
p->ir_core_data.duration = v;
+ p->ir_core_data.timeout = w;
- v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s\n",
- v, u ? "mark" : "space");
+ v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s %s\n",
+ v, u ? "mark" : "space", w ? "(timed out)" : "");
+ if (w)
+ v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
}
return 0;
}
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 5b7e267..c1a2785 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 423c1af..68d1240 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -113,6 +113,8 @@ MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
MODULE_AUTHOR("Ricardo Cerqueira");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
"{{Conexant,23882},"
"{{Conexant,23883}");
@@ -973,14 +975,8 @@ static struct pci_driver cx88_audio_pci_driver = {
*/
static int __init cx88_audio_init(void)
{
- printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",
- (CX88_VERSION_CODE >> 16) & 0xff,
- (CX88_VERSION_CODE >> 8) & 0xff,
- CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
+ CX88_VERSION);
return pci_register_driver(&cx88_audio_pci_driver);
}
@@ -994,10 +990,3 @@ static void __exit cx88_audio_fini(void)
module_init(cx88_audio_init);
module_exit(cx88_audio_fini);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 11e49bb..e46446a 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -42,6 +42,7 @@
MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
static unsigned int mpegbufs = 32;
module_param(mpegbufs,int,0644);
@@ -730,7 +731,6 @@ static int vidioc_querycap (struct file *file, void *priv,
strcpy(cap->driver, "cx88_blackbird");
strlcpy(cap->card, core->board.name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
- cap->version = CX88_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
@@ -1368,14 +1368,8 @@ static struct cx8802_driver cx8802_blackbird_driver = {
static int __init blackbird_init(void)
{
- printk(KERN_INFO "cx2388x blackbird driver version %d.%d.%d loaded\n",
- (CX88_VERSION_CODE >> 16) & 0xff,
- (CX88_VERSION_CODE >> 8) & 0xff,
- CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
+ CX88_VERSION);
return cx8802_register_driver(&cx8802_blackbird_driver);
}
@@ -1389,11 +1383,3 @@ module_exit(blackbird_fini);
module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
MODULE_PARM_DESC(debug,"enable debug messages [video]");
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 27222c9..3929d93 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -28,6 +28,7 @@
#include "cx88.h"
#include "tea5767.h"
+#include "xc4000.h"
static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
@@ -1572,8 +1573,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Pinnacle Hybrid PCTV",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC2028,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -1610,8 +1611,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Leadtek TV2000 XP Global",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC2028,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -2042,8 +2043,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Terratec Cinergy HT PCI MKII",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC2028,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -2081,9 +2082,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV1800H] = {
.name = "Leadtek WinFast DTV1800 Hybrid",
.tuner_type = TUNER_XC2028,
- .radio_type = TUNER_XC2028,
+ .radio_type = UNSET,
.tuner_addr = 0x61,
- .radio_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
/*
* GPIO setting
*
@@ -2119,6 +2120,99 @@ static const struct cx88_board cx88_boards[] = {
},
.mpeg = CX88_MPEG_DVB,
},
+ [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
+ .name = "Leadtek WinFast DTV1800 H (XC4000)",
+ .tuner_type = TUNER_XC4000,
+ .radio_type = UNSET,
+ .tuner_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
+ /*
+ * GPIO setting
+ *
+ * 2: mute (0=off,1=on)
+ * 12: tuner reset pin
+ * 13: audio source (0=tuner audio,1=line in)
+ * 14: FM (0=on,1=off ???)
+ */
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */
+ .gpio2 = 0x0000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
+ .gpio2 = 0x0000,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
+ .gpio2 = 0x0000,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */
+ .gpio2 = 0x0000,
+ },
+ .mpeg = CX88_MPEG_DVB,
+ },
+ [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
+ .name = "Leadtek WinFast DTV2000 H PLUS",
+ .tuner_type = TUNER_XC4000,
+ .radio_type = UNSET,
+ .tuner_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
+ /*
+ * GPIO
+ * 2: 1: mute audio
+ * 12: 0: reset XC4000
+ * 13: 1: audio input is line in (0: tuner)
+ * 14: 0: FM radio
+ * 16: 0: RF input is cable
+ */
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0403,
+ .gpio1 = 0xF0D7,
+ .gpio2 = 0x0101,
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_CABLE,
+ .vmux = 0,
+ .gpio0 = 0x0403,
+ .gpio1 = 0xF0D7,
+ .gpio2 = 0x0100,
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0403, /* was 0x0407 */
+ .gpio1 = 0xF0F7,
+ .gpio2 = 0x0101,
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0403, /* was 0x0407 */
+ .gpio1 = 0xF0F7,
+ .gpio2 = 0x0101,
+ .gpio3 = 0x0000,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0403,
+ .gpio1 = 0xF097,
+ .gpio2 = 0x0100,
+ .gpio3 = 0x0000,
+ },
+ .mpeg = CX88_MPEG_DVB,
+ },
[CX88_BOARD_PROF_7301] = {
.name = "Prof 7301 DVB-S/S2",
.tuner_type = UNSET,
@@ -2581,6 +2675,15 @@ static const struct cx88_subid cx88_subids[] = {
.subdevice = 0x6654,
.card = CX88_BOARD_WINFAST_DTV1800H,
}, {
+ /* WinFast DTV1800 H with XC4000 tuner */
+ .subvendor = 0x107d,
+ .subdevice = 0x6f38,
+ .card = CX88_BOARD_WINFAST_DTV1800H_XC4000,
+ }, {
+ .subvendor = 0x107d,
+ .subdevice = 0x6f42,
+ .card = CX88_BOARD_WINFAST_DTV2000H_PLUS,
+ }, {
/* PVR2000 PAL Model [107d:6630] */
.subvendor = 0x107d,
.subdevice = 0x6630,
@@ -2846,6 +2949,23 @@ static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
return -EINVAL;
}
+static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
+ int command, int arg)
+{
+ switch (command) {
+ case XC4000_TUNER_RESET:
+ /* GPIO 12 (xc4000 tuner reset) */
+ cx_set(MO_GP1_IO, 0x1010);
+ mdelay(50);
+ cx_clear(MO_GP1_IO, 0x10);
+ mdelay(75);
+ cx_set(MO_GP1_IO, 0x10);
+ mdelay(75);
+ return 0;
+ }
+ return -EINVAL;
+}
+
/* ------------------------------------------------------------------- */
/* some Divco specific stuff */
static int cx88_pv_8000gt_callback(struct cx88_core *core,
@@ -2948,6 +3068,19 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
return -EINVAL;
}
+static int cx88_xc4000_tuner_callback(struct cx88_core *core,
+ int command, int arg)
+{
+ /* Board-specific callbacks */
+ switch (core->boardnr) {
+ case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+ case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+ return cx88_xc4000_winfast2000h_plus_callback(core,
+ command, arg);
+ }
+ return -EINVAL;
+}
+
/* ----------------------------------------------------------------------- */
/* Tuner callback function. Currently only needed for the Pinnacle *
* PCTV HD 800i with an xc5000 sillicon tuner. This is used for both *
@@ -3022,6 +3155,9 @@ int cx88_tuner_callback(void *priv, int component, int command, int arg)
case TUNER_XC2028:
info_printk(core, "Calling XC2028/3028 callback\n");
return cx88_xc2028_tuner_callback(core, command, arg);
+ case TUNER_XC4000:
+ info_printk(core, "Calling XC4000 callback\n");
+ return cx88_xc4000_tuner_callback(core, command, arg);
case TUNER_XC5000:
info_printk(core, "Calling XC5000 callback\n");
return cx88_xc5000_tuner_callback(core, command, arg);
@@ -3109,13 +3245,13 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
case CX88_BOARD_WINFAST_DTV1800H:
- /* GPIO 12 (xc3028 tuner reset) */
- cx_set(MO_GP1_IO, 0x1010);
- mdelay(50);
- cx_clear(MO_GP1_IO, 0x10);
- mdelay(50);
- cx_set(MO_GP1_IO, 0x10);
- mdelay(50);
+ cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
+ break;
+
+ case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+ case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+ cx88_xc4000_winfast2000h_plus_callback(core,
+ XC4000_TUNER_RESET, 0);
break;
case CX88_BOARD_TWINHAN_VP1027_DVBS:
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 2e145f0..fbfdd80 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -759,8 +759,8 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
if (nocomb)
value |= (3 << 5); // disable comb filter
- cx_write(MO_FILTER_EVEN, value);
- cx_write(MO_FILTER_ODD, value);
+ cx_andor(MO_FILTER_EVEN, 0x7ffc7f, value); /* preserve PEAKEN, PSEL */
+ cx_andor(MO_FILTER_ODD, 0x7ffc7f, value);
dprintk(1,"set_scale: filter 0x%04x\n", value);
return 0;
@@ -994,10 +994,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
// htotal
tmp64 = norm_htotal(norm) * (u64)vdec_clock;
do_div(tmp64, fsc8);
- htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
+ htotal = (u32)tmp64;
dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
htotal, cx_read(MO_HTOTAL), (u32)tmp64);
- cx_write(MO_HTOTAL, htotal);
+ cx_andor(MO_HTOTAL, 0x07ff, htotal);
// vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
// the effective vbi offset ~244 samples, the same as the Bt8x8
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index c69df7e..cf3d33a 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -41,6 +41,7 @@
#include "or51132.h"
#include "lgdt330x.h"
#include "s5h1409.h"
+#include "xc4000.h"
#include "xc5000.h"
#include "nxt200x.h"
#include "cx24123.h"
@@ -63,6 +64,7 @@ MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
static unsigned int debug;
module_param(debug, int, 0644);
@@ -605,6 +607,39 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
return 0;
}
+static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
+{
+ struct dvb_frontend *fe;
+ struct videobuf_dvb_frontend *fe0 = NULL;
+
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
+
+ if (!fe0->dvb.frontend) {
+ printk(KERN_ERR "%s/2: dvb frontend not attached. "
+ "Can't attach xc4000\n",
+ dev->core->name);
+ return -EINVAL;
+ }
+
+ fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
+ cfg);
+ if (!fe) {
+ printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+ dev->core->name);
+ dvb_frontend_detach(fe0->dvb.frontend);
+ dvb_unregister_frontend(fe0->dvb.frontend);
+ fe0->dvb.frontend = NULL;
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
+
+ return 0;
+}
+
static int cx24116_set_ts_param(struct dvb_frontend *fe,
int is_punctured)
{
@@ -1294,7 +1329,25 @@ static int dvb_register(struct cx8802_dev *dev)
goto frontend_detach;
}
break;
- case CX88_BOARD_GENIATECH_X8000_MT:
+ case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+ case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &cx88_pinnacle_hybrid_pctv,
+ &core->i2c_adap);
+ if (fe0->dvb.frontend) {
+ struct xc4000_config cfg = {
+ .i2c_address = 0x61,
+ .default_pm = 0,
+ .dvb_amplitude = 134,
+ .set_smoothedcvbs = 1,
+ .if_khz = 4560
+ };
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+ if (attach_xc4000(dev, &cfg) < 0)
+ goto frontend_detach;
+ }
+ break;
+ case CX88_BOARD_GENIATECH_X8000_MT:
dev->ts_gen_cntrl = 0x00;
fe0->dvb.frontend = dvb_attach(zl10353_attach,
@@ -1577,6 +1630,11 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
udelay(1000);
break;
+ case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+ /* set RF input to AIR for DVB-T (GPIO 16) */
+ cx_write(MO_GP2_IO, 0x0101);
+ break;
+
default:
err = -ENODEV;
}
@@ -1692,14 +1750,8 @@ static struct cx8802_driver cx8802_dvb_driver = {
static int __init dvb_init(void)
{
- printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n",
- (CX88_VERSION_CODE >> 16) & 0xff,
- (CX88_VERSION_CODE >> 8) & 0xff,
- CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
+ CX88_VERSION);
return cx8802_register_driver(&cx8802_dvb_driver);
}
@@ -1710,10 +1762,3 @@ static void __exit dvb_fini(void)
module_init(dvb_init);
module_exit(dvb_fini);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 3f44200..e614201 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -100,6 +100,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
break;
case CX88_BOARD_WINFAST_DTV1000:
case CX88_BOARD_WINFAST_DTV1800H:
+ case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+ case CX88_BOARD_WINFAST_DTV2000H_PLUS:
case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
auxgpio = gpio;
@@ -289,6 +291,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_WINFAST_DTV2000H:
case CX88_BOARD_WINFAST_DTV2000H_J:
case CX88_BOARD_WINFAST_DTV1800H:
+ case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+ case CX88_BOARD_WINFAST_DTV2000H_PLUS:
ir_codes = RC_MAP_WINFAST;
ir->gpio_addr = MO_GP0_IO;
ir->mask_keycode = 0x8f8;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 1a7b983..cd5386e 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -39,6 +39,7 @@ MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
static unsigned int debug;
module_param(debug,int,0644);
@@ -613,13 +614,17 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
core->active_type_id != drv->type_id)
return -EBUSY;
- core->input = 0;
- for (i = 0;
- i < (sizeof(core->board.input) / sizeof(struct cx88_input));
- i++) {
- if (core->board.input[i].type == CX88_VMUX_DVB) {
- core->input = i;
- break;
+ if (drv->type_id == CX88_MPEG_DVB) {
+ /* When switching to DVB, always set the input to the tuner */
+ core->last_analog_input = core->input;
+ core->input = 0;
+ for (i = 0;
+ i < (sizeof(core->board.input) / sizeof(struct cx88_input));
+ i++) {
+ if (core->board.input[i].type == CX88_VMUX_DVB) {
+ core->input = i;
+ break;
+ }
}
}
@@ -644,6 +649,12 @@ static int cx8802_request_release(struct cx8802_driver *drv)
if (drv->advise_release && --core->active_ref == 0)
{
+ if (drv->type_id == CX88_MPEG_DVB) {
+ /* If the DVB driver is releasing, reset the input
+ state to the last configured analog input */
+ core->input = core->last_analog_input;
+ }
+
drv->advise_release(drv);
core->active_type_id = CX88_BOARD_NONE;
mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
@@ -890,14 +901,8 @@ static struct pci_driver cx8802_pci_driver = {
static int __init cx8802_init(void)
{
- printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %d.%d.%d loaded\n",
- (CX88_VERSION_CODE >> 16) & 0xff,
- (CX88_VERSION_CODE >> 8) & 0xff,
- CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
+ CX88_VERSION);
return pci_register_driver(&cx8802_pci_driver);
}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index cef4f28..921c56d 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -45,6 +45,7 @@
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
/* ------------------------------------------------------------------ */
@@ -220,7 +221,23 @@ static const struct cx88_ctrl cx8800_ctls[] = {
.reg = MO_UV_SATURATION,
.mask = 0x00ff,
.shift = 0,
- },{
+ }, {
+ .v = {
+ .id = V4L2_CID_SHARPNESS,
+ .name = "Sharpness",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0x0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },
+ .off = 0,
+ /* NOTE: the value is converted and written to both even
+ and odd registers in the code */
+ .reg = MO_FILTER_ODD,
+ .mask = 7 << 7,
+ .shift = 7,
+ }, {
.v = {
.id = V4L2_CID_CHROMA_AGC,
.name = "Chroma AGC",
@@ -245,6 +262,20 @@ static const struct cx88_ctrl cx8800_ctls[] = {
.mask = 1 << 9,
.shift = 9,
}, {
+ .v = {
+ .id = V4L2_CID_BAND_STOP_FILTER,
+ .name = "Notch filter",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0x0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },
+ .off = 0,
+ .reg = MO_HTOTAL,
+ .mask = 3 << 11,
+ .shift = 11,
+ }, {
/* --- audio --- */
.v = {
.id = V4L2_CID_AUDIO_MUTE,
@@ -300,8 +331,10 @@ const u32 cx88_user_ctrls[] = {
V4L2_CID_AUDIO_VOLUME,
V4L2_CID_AUDIO_BALANCE,
V4L2_CID_AUDIO_MUTE,
+ V4L2_CID_SHARPNESS,
V4L2_CID_CHROMA_AGC,
V4L2_CID_COLOR_KILLER,
+ V4L2_CID_BAND_STOP_FILTER,
0
};
EXPORT_SYMBOL(cx88_user_ctrls);
@@ -962,6 +995,10 @@ int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl)
case V4L2_CID_AUDIO_VOLUME:
ctl->value = 0x3f - (value & 0x3f);
break;
+ case V4L2_CID_SHARPNESS:
+ ctl->value = ((value & 0x0200) ? (((value & 0x0180) >> 7) + 1)
+ : 0);
+ break;
default:
ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
break;
@@ -1039,6 +1076,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
}
mask=0xffff;
break;
+ case V4L2_CID_SHARPNESS:
+ /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
+ value = (ctl->value < 1 ? 0 : ((ctl->value + 3) << 7));
+ /* needs to be set for both fields */
+ cx_andor(MO_FILTER_EVEN, mask, value);
+ break;
case V4L2_CID_CHROMA_AGC:
/* Do not allow chroma AGC to be enabled for SECAM */
value = ((ctl->value - c->off) << c->shift) & c->mask;
@@ -1161,7 +1204,6 @@ static int vidioc_querycap (struct file *file, void *priv,
strcpy(cap->driver, "cx8800");
strlcpy(cap->card, core->board.name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
- cap->version = CX88_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
@@ -1480,7 +1522,6 @@ static int radio_querycap (struct file *file, void *priv,
strcpy(cap->driver, "cx8800");
strlcpy(cap->card, core->board.name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
- cap->version = CX88_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
return 0;
}
@@ -2139,14 +2180,8 @@ static struct pci_driver cx8800_pci_driver = {
static int __init cx8800_init(void)
{
- printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %d.%d.%d loaded\n",
- (CX88_VERSION_CODE >> 16) & 0xff,
- (CX88_VERSION_CODE >> 8) & 0xff,
- CX88_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
+ CX88_VERSION);
return pci_register_driver(&cx8800_pci_driver);
}
@@ -2157,11 +2192,3 @@ static void __exit cx8800_fini(void)
module_init(cx8800_init);
module_exit(cx8800_fini);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index a399a8b..fa8d307 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -39,9 +39,9 @@
#include "cx88-reg.h"
#include "tuner-xc2028.h"
-#include <linux/version.h>
#include <linux/mutex.h>
-#define CX88_VERSION_CODE KERNEL_VERSION(0, 0, 8)
+
+#define CX88_VERSION "0.0.9"
#define UNSET (-1U)
@@ -242,6 +242,8 @@ extern const struct sram_channel const cx88_sram_channels[];
#define CX88_BOARD_SAMSUNG_SMT_7020 84
#define CX88_BOARD_TWINHAN_VP1027_DVBS 85
#define CX88_BOARD_TEVII_S464 86
+#define CX88_BOARD_WINFAST_DTV2000H_PLUS 87
+#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -375,6 +377,7 @@ struct cx88_core {
u32 audiomode_manual;
u32 audiomode_current;
u32 input;
+ u32 last_analog_input;
u32 astat;
u32 use_nicam;
unsigned long last_change;
diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig
index 6b19540..60a456e 100644
--- a/drivers/media/video/davinci/Kconfig
+++ b/drivers/media/video/davinci/Kconfig
@@ -91,3 +91,26 @@ config VIDEO_ISIF
To compile this driver as a module, choose M here: the
module will be called vpfe.
+
+config VIDEO_DM644X_VPBE
+ tristate "DM644X VPBE HW module"
+ depends on ARCH_DAVINCI_DM644x
+ select VIDEO_VPSS_SYSTEM
+ select VIDEOBUF_DMA_CONTIG
+ help
+ Enables VPBE modules used for display on a DM644x
+ SoC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vpbe.
+
+
+config VIDEO_VPBE_DISPLAY
+ tristate "VPBE V4L2 Display driver"
+ depends on ARCH_DAVINCI_DM644x
+ select VIDEO_DM644X_VPBE
+ help
+ Enables VPBE V4L2 Display driver on a DM644x device
+
+ To compile this driver as a module, choose M here: the
+ module will be called vpbe_display.
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile
index a379557..ae7dafb 100644
--- a/drivers/media/video/davinci/Makefile
+++ b/drivers/media/video/davinci/Makefile
@@ -16,3 +16,5 @@ obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o
obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o
obj-$(CONFIG_VIDEO_ISIF) += isif.o
+obj-$(CONFIG_VIDEO_DM644X_VPBE) += vpbe.o vpbe_osd.o vpbe_venc.o
+obj-$(CONFIG_VIDEO_VPBE_DISPLAY) += vpbe_display.o
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c
index c29ac88..bd443ee 100644
--- a/drivers/media/video/davinci/dm355_ccdc.c
+++ b/drivers/media/video/davinci/dm355_ccdc.c
@@ -39,6 +39,7 @@
#include <linux/videodev2.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <media/davinci/dm355_ccdc.h>
#include <media/davinci/vpss.h>
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c
index c8b32c1..8051c29 100644
--- a/drivers/media/video/davinci/dm644x_ccdc.c
+++ b/drivers/media/video/davinci/dm644x_ccdc.c
@@ -40,6 +40,7 @@
#include <linux/gfp.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <media/davinci/dm644x_ccdc.h>
#include <media/davinci/vpss.h>
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c
index 9f3bfc1..af96802 100644
--- a/drivers/media/video/davinci/vpif.c
+++ b/drivers/media/video/davinci/vpif.c
@@ -422,7 +422,7 @@ static int __init vpif_probe(struct platform_device *pdev)
if (!res)
return -ENOENT;
- res_len = res->end - res->start + 1;
+ res_len = resource_size(res);
res = request_mem_region(res->start, res_len, res->name);
if (!res)
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
index d93ad74..49e4deb 100644
--- a/drivers/media/video/davinci/vpif_capture.c
+++ b/drivers/media/video/davinci/vpif_capture.c
@@ -33,7 +33,6 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/version.h>
#include <linux/slab.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
@@ -44,6 +43,7 @@
MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(VPIF_CAPTURE_VERSION);
#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg)
#define vpif_dbg(level, debug, fmt, arg...) \
@@ -1677,7 +1677,6 @@ static int vpif_querycap(struct file *file, void *priv,
{
struct vpif_capture_config *config = vpif_dev->platform_data;
- cap->version = VPIF_CAPTURE_VERSION_CODE;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
strlcpy(cap->bus_info, "DM646x Platform", sizeof(cap->bus_info));
@@ -2211,10 +2210,8 @@ static __init int vpif_probe(struct platform_device *pdev)
vfd->v4l2_dev = &vpif_obj.v4l2_dev;
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name),
- "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
- (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
- (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
- (VPIF_CAPTURE_VERSION_CODE) & 0xff);
+ "DM646x_VPIFCapture_DRIVER_V%s",
+ VPIF_CAPTURE_VERSION);
/* Set video_dev to the video device */
ch->video_dev = vfd;
}
diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h
index 7a4196d..064550f 100644
--- a/drivers/media/video/davinci/vpif_capture.h
+++ b/drivers/media/video/davinci/vpif_capture.h
@@ -23,7 +23,6 @@
/* Header files */
#include <linux/videodev2.h>
-#include <linux/version.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/videobuf-core.h>
@@ -33,11 +32,7 @@
#include "vpif.h"
/* Macros */
-#define VPIF_MAJOR_RELEASE 0
-#define VPIF_MINOR_RELEASE 0
-#define VPIF_BUILD 1
-#define VPIF_CAPTURE_VERSION_CODE ((VPIF_MAJOR_RELEASE << 16) | \
- (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD)
+#define VPIF_CAPTURE_VERSION "0.0.2"
#define VPIF_VALID_FIELD(field) (((V4L2_FIELD_ANY == field) || \
(V4L2_FIELD_NONE == field)) || \
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
index cdf659a..286f029 100644
--- a/drivers/media/video/davinci/vpif_display.c
+++ b/drivers/media/video/davinci/vpif_display.c
@@ -29,7 +29,6 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/version.h>
#include <linux/slab.h>
#include <asm/irq.h>
@@ -47,6 +46,7 @@
MODULE_DESCRIPTION("TI DaVinci VPIF Display driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(VPIF_DISPLAY_VERSION);
#define DM646X_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50)
@@ -701,7 +701,6 @@ static int vpif_querycap(struct file *file, void *priv,
{
struct vpif_display_config *config = vpif_dev->platform_data;
- cap->version = VPIF_DISPLAY_VERSION_CODE;
cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
@@ -1740,10 +1739,8 @@ static __init int vpif_probe(struct platform_device *pdev)
vfd->v4l2_dev = &vpif_obj.v4l2_dev;
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name),
- "DM646x_VPIFDisplay_DRIVER_V%d.%d.%d",
- (VPIF_DISPLAY_VERSION_CODE >> 16) & 0xff,
- (VPIF_DISPLAY_VERSION_CODE >> 8) & 0xff,
- (VPIF_DISPLAY_VERSION_CODE) & 0xff);
+ "DM646x_VPIFDisplay_DRIVER_V%s",
+ VPIF_DISPLAY_VERSION);
/* Set video_dev to the video device */
ch->video_dev = vfd;
diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h
index b53aaa8..5d1936d 100644
--- a/drivers/media/video/davinci/vpif_display.h
+++ b/drivers/media/video/davinci/vpif_display.h
@@ -18,7 +18,6 @@
/* Header files */
#include <linux/videodev2.h>
-#include <linux/version.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/videobuf-core.h>
@@ -27,12 +26,7 @@
#include "vpif.h"
/* Macros */
-#define VPIF_MAJOR_RELEASE (0)
-#define VPIF_MINOR_RELEASE (0)
-#define VPIF_BUILD (1)
-
-#define VPIF_DISPLAY_VERSION_CODE \
- ((VPIF_MAJOR_RELEASE << 16) | (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD)
+#define VPIF_DISPLAY_VERSION "0.0.2"
#define VPIF_VALID_FIELD(field) \
(((V4L2_FIELD_ANY == field) || (V4L2_FIELD_NONE == field)) || \
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 3cb78f2..f6f622e 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -3,7 +3,6 @@ config VIDEO_EM28XX
depends on VIDEO_DEV && I2C
select VIDEO_TUNER
select VIDEO_TVEEPROM
- depends on RC_CORE
select VIDEOBUF_VMALLOC
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
@@ -40,7 +39,20 @@ config VIDEO_EM28XX_DVB
select DVB_S921 if !DVB_FE_CUSTOMISE
select DVB_DRXD if !DVB_FE_CUSTOMISE
select DVB_CXD2820R if !DVB_FE_CUSTOMISE
+ select DVB_DRXK if !DVB_FE_CUSTOMISE
+ select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+ select DVB_TDA10071 if !DVB_FE_CUSTOMISE
+ select DVB_A8293 if !DVB_FE_CUSTOMISE
select VIDEOBUF_DVB
---help---
This adds support for DVB cards based on the
Empiatech em28xx chips.
+
+config VIDEO_EM28XX_RC
+ bool "EM28XX Remote Controller support"
+ depends on RC_CORE
+ depends on VIDEO_EM28XX
+ depends on !(RC_CORE=m && VIDEO_EM28XX=y)
+ default y
+ ---help---
+ Enables Remote Controller support on em28xx driver.
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
index d0f093d..2abdf76 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
@@ -1,5 +1,7 @@
-em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \
- em28xx-input.o em28xx-vbi.o
+em28xx-y := em28xx-video.o em28xx-i2c.o em28xx-cards.o
+em28xx-y += em28xx-core.o em28xx-vbi.o
+
+em28xx-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-input.o
em28xx-alsa-objs := em28xx-audio.o
@@ -7,8 +9,8 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 3c48a72..cff0768 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -3,9 +3,9 @@
*
* Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
*
- * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
* - Port to work with the in-kernel driver
- * - Several cleanups
+ * - Cleanups, fixes, alsa-controls, etc.
*
* This driver is based on my previous au600 usb pstn audio driver
* and inherits all the copyrights
@@ -41,6 +41,7 @@
#include <sound/info.h>
#include <sound/initval.h>
#include <sound/control.h>
+#include <sound/tlv.h>
#include <media/v4l2-common.h>
#include "em28xx.h"
@@ -212,9 +213,12 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
if (errCode) {
+ em28xx_errdev("submit of audio urb failed\n");
em28xx_deinit_isoc_audio(dev);
+ atomic_set(&dev->stream_started, 0);
return errCode;
}
+
}
return 0;
@@ -245,6 +249,7 @@ static struct snd_pcm_hardware snd_em28xx_hw_capture = {
.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BATCH |
SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
@@ -276,24 +281,27 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
return -ENODEV;
}
- /* Sets volume, mute, etc */
+ runtime->hw = snd_em28xx_hw_capture;
+ if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) {
+ if (dev->audio_ifnum)
+ dev->alt = 1;
+ else
+ dev->alt = 7;
- dev->mute = 0;
- mutex_lock(&dev->lock);
- ret = em28xx_audio_analog_set(dev);
- if (ret < 0)
- goto err;
+ dprintk("changing alternate number on interface %d to %d\n",
+ dev->audio_ifnum, dev->alt);
+ usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt);
- runtime->hw = snd_em28xx_hw_capture;
- if (dev->alt == 0 && dev->adev.users == 0) {
- int errCode;
- dev->alt = 7;
- dprintk("changing alternate number to 7\n");
- errCode = usb_set_interface(dev->udev, 0, 7);
- }
+ /* Sets volume, mute, etc */
+ dev->mute = 0;
+ mutex_lock(&dev->lock);
+ ret = em28xx_audio_analog_set(dev);
+ if (ret < 0)
+ goto err;
- dev->adev.users++;
- mutex_unlock(&dev->lock);
+ dev->adev.users++;
+ mutex_unlock(&dev->lock);
+ }
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
dev->adev.capture_pcm_substream = substream;
@@ -342,6 +350,8 @@ static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
ret = snd_pcm_alloc_vmalloc_buffer(substream,
params_buffer_bytes(hw_params));
+ if (ret < 0)
+ return ret;
format = params_format(hw_params);
rate = params_rate(hw_params);
channels = params_channels(hw_params);
@@ -393,20 +403,24 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct em28xx *dev = snd_pcm_substream_chip(substream);
- int retval;
+ int retval = 0;
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+ case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
case SNDRV_PCM_TRIGGER_START:
atomic_set(&dev->stream_started, 1);
break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+ case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
case SNDRV_PCM_TRIGGER_STOP:
- atomic_set(&dev->stream_started, 1);
+ atomic_set(&dev->stream_started, 0);
break;
default:
retval = -EINVAL;
}
schedule_work(&dev->wq_trigger);
- return 0;
+ return retval;
}
static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
@@ -432,6 +446,179 @@ static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
return vmalloc_to_page(pageptr);
}
+/*
+ * AC97 volume control support
+ */
+static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
+{
+ info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ info->count = 2;
+ info->value.integer.min = 0;
+ info->value.integer.max = 0x1f;
+
+ return 0;
+}
+
+static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+ u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) |
+ (0x1f - (value->value.integer.value[1] & 0x1f)) << 8;
+ int rc;
+
+ mutex_lock(&dev->lock);
+ rc = em28xx_read_ac97(dev, kcontrol->private_value);
+ if (rc < 0)
+ goto err;
+
+ val |= rc & 0x8000; /* Preserve the mute flag */
+
+ rc = em28xx_write_ac97(dev, kcontrol->private_value, val);
+ if (rc < 0)
+ goto err;
+
+ dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
+ (val & 0x8000) ? "muted " : "",
+ 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+ val, (int)kcontrol->private_value);
+
+err:
+ mutex_unlock(&dev->lock);
+ return rc;
+}
+
+static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+ int val;
+
+ mutex_lock(&dev->lock);
+ val = em28xx_read_ac97(dev, kcontrol->private_value);
+ mutex_unlock(&dev->lock);
+ if (val < 0)
+ return val;
+
+ dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
+ (val & 0x8000) ? "muted " : "",
+ 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+ val, (int)kcontrol->private_value);
+
+ value->value.integer.value[0] = 0x1f - (val & 0x1f);
+ value->value.integer.value[1] = 0x1f - ((val << 8) & 0x1f);
+
+ return 0;
+}
+
+static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+ u16 val = value->value.integer.value[0];
+ int rc;
+
+ mutex_lock(&dev->lock);
+ rc = em28xx_read_ac97(dev, kcontrol->private_value);
+ if (rc < 0)
+ goto err;
+
+ if (val)
+ rc &= 0x1f1f;
+ else
+ rc |= 0x8000;
+
+ rc = em28xx_write_ac97(dev, kcontrol->private_value, rc);
+ if (rc < 0)
+ goto err;
+
+ dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
+ (val & 0x8000) ? "muted " : "",
+ 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+ val, (int)kcontrol->private_value);
+
+err:
+ mutex_unlock(&dev->lock);
+ return rc;
+}
+
+static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+ int val;
+
+ mutex_lock(&dev->lock);
+ val = em28xx_read_ac97(dev, kcontrol->private_value);
+ mutex_unlock(&dev->lock);
+ if (val < 0)
+ return val;
+
+ if (val & 0x8000)
+ value->value.integer.value[0] = 0;
+ else
+ value->value.integer.value[0] = 1;
+
+ dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
+ (val & 0x8000) ? "muted " : "",
+ 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+ val, (int)kcontrol->private_value);
+
+ return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0);
+
+static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
+ char *name, int id)
+{
+ int err;
+ char ctl_name[44];
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_new tmp;
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ tmp.private_value = id,
+ tmp.name = ctl_name,
+
+ /* Add Mute Control */
+ sprintf(ctl_name, "%s Switch", name);
+ tmp.get = em28xx_vol_get_mute;
+ tmp.put = em28xx_vol_put_mute;
+ tmp.info = snd_ctl_boolean_mono_info;
+ kctl = snd_ctl_new1(&tmp, dev);
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ return err;
+ dprintk("Added control %s for ac97 volume control 0x%04x\n",
+ ctl_name, id);
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ tmp.private_value = id,
+ tmp.name = ctl_name,
+
+ /* Add Volume Control */
+ sprintf(ctl_name, "%s Volume", name);
+ tmp.get = em28xx_vol_get;
+ tmp.put = em28xx_vol_put;
+ tmp.info = em28xx_vol_info;
+ tmp.tlv.p = em28xx_db_scale,
+ kctl = snd_ctl_new1(&tmp, dev);
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ return err;
+ dprintk("Added control %s for ac97 volume control 0x%04x\n",
+ ctl_name, id);
+
+ return 0;
+}
+
+/*
+ * register/unregister code and data
+ */
static struct snd_pcm_ops snd_em28xx_pcm_capture = {
.open = snd_em28xx_capture_open,
.close = snd_em28xx_pcm_close,
@@ -452,17 +639,17 @@ static int em28xx_audio_init(struct em28xx *dev)
static int devnr;
int err;
- if (dev->has_alsa_audio != 1) {
+ if (!dev->has_alsa_audio || dev->audio_ifnum < 0) {
/* This device does not support the extension (in this case
the device is expecting the snd-usb-audio module or
doesn't have analog audio support at all) */
return 0;
}
- printk(KERN_INFO "em28xx-audio.c: probing for em28x1 "
- "non standard usbaudio\n");
+ printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n");
printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
"Rechberger\n");
+ printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n");
err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
&card);
@@ -488,6 +675,22 @@ static int em28xx_audio_init(struct em28xx *dev)
INIT_WORK(&dev->wq_trigger, audio_trigger);
+ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
+ em28xx_cvol_new(card, dev, "Video", AC97_VIDEO_VOL);
+ em28xx_cvol_new(card, dev, "Line In", AC97_LINEIN_VOL);
+ em28xx_cvol_new(card, dev, "Phone", AC97_PHONE_VOL);
+ em28xx_cvol_new(card, dev, "Microphone", AC97_PHONE_VOL);
+ em28xx_cvol_new(card, dev, "CD", AC97_CD_VOL);
+ em28xx_cvol_new(card, dev, "AUX", AC97_AUX_VOL);
+ em28xx_cvol_new(card, dev, "PCM", AC97_PCM_OUT_VOL);
+
+ em28xx_cvol_new(card, dev, "Master", AC97_MASTER_VOL);
+ em28xx_cvol_new(card, dev, "Line", AC97_LINE_LEVEL_VOL);
+ em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO_VOL);
+ em28xx_cvol_new(card, dev, "LFE", AC97_LFE_MASTER_VOL);
+ em28xx_cvol_new(card, dev, "Surround", AC97_SURR_MASTER_VOL);
+ }
+
err = snd_card_register(card);
if (err < 0) {
snd_card_free(card);
@@ -538,7 +741,7 @@ static void __exit em28xx_alsa_unregister(void)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_DESCRIPTION("Em28xx Audio driver");
module_init(em28xx_alsa_register);
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 4e37375..9b747c2 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -60,7 +60,7 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "card type");
-/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
+/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
static unsigned long em28xx_devused;
struct em28xx_hash_table {
@@ -289,7 +289,7 @@ static struct em28xx_reg_seq leadership_reset[] = {
{ -1, -1, -1, -1},
};
-/* 2013:024f PCTV Systems nanoStick T2 290e
+/* 2013:024f PCTV nanoStick T2 290e
* GPIO_6 - demod reset
* GPIO_7 - LED
*/
@@ -300,6 +300,42 @@ static struct em28xx_reg_seq pctv_290e[] = {
{-1, -1, -1, -1},
};
+#if 0
+static struct em28xx_reg_seq terratec_h5_gpio[] = {
+ {EM28XX_R08_GPIO, 0xff, 0xff, 10},
+ {EM2874_R80_GPIO, 0xf6, 0xff, 100},
+ {EM2874_R80_GPIO, 0xf2, 0xff, 50},
+ {EM2874_R80_GPIO, 0xf6, 0xff, 50},
+ { -1, -1, -1, -1},
+};
+
+static struct em28xx_reg_seq terratec_h5_digital[] = {
+ {EM2874_R80_GPIO, 0xf6, 0xff, 10},
+ {EM2874_R80_GPIO, 0xe6, 0xff, 100},
+ {EM2874_R80_GPIO, 0xa6, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+#endif
+
+/* 2013:024f PCTV DVB-S2 Stick 460e
+ * GPIO_0 - POWER_ON
+ * GPIO_1 - BOOST
+ * GPIO_2 - VUV_LNB (red LED)
+ * GPIO_3 - EXT_12V
+ * GPIO_4 - INT_DEM (DEMOD GPIO_0)
+ * GPIO_5 - INT_LNB
+ * GPIO_6 - RESET_DEM
+ * GPIO_7 - LED (green LED)
+ */
+static struct em28xx_reg_seq pctv_460e[] = {
+ {EM2874_R80_GPIO, 0x01, 0xff, 50},
+ {0x0d, 0xff, 0xff, 50},
+ {EM2874_R80_GPIO, 0x41, 0xff, 50}, /* GPIO_6=1 */
+ {0x0d, 0x42, 0xff, 50},
+ {EM2874_R80_GPIO, 0x61, 0xff, 50}, /* GPIO_5=1 */
+ { -1, -1, -1, -1},
+};
+
/*
* Board definitions
*/
@@ -843,6 +879,19 @@ struct em28xx_board em28xx_boards[] = {
.gpio = terratec_cinergy_USB_XS_FR_analog,
} },
},
+ [EM2884_BOARD_TERRATEC_H5] = {
+ .name = "Terratec Cinergy H5",
+ .has_dvb = 1,
+#if 0
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .tuner_addr = 0x41,
+ .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */
+ .tuner_gpio = terratec_h5_gpio,
+#endif
+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
+ EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
+ },
[EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
.name = "Hauppauge WinTV HVR 900",
.tda9887_conf = TDA9887_PRESENT,
@@ -1259,7 +1308,7 @@ struct em28xx_board em28xx_boards[] = {
} },
},
- [EM2874_LEADERSHIP_ISDBT] = {
+ [EM2874_BOARD_LEADERSHIP_ISDBT] = {
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
EM28XX_I2C_CLK_WAIT_ENABLE |
EM28XX_I2C_FREQ_100_KHZ,
@@ -1319,7 +1368,6 @@ struct em28xx_board em28xx_boards[] = {
},
[EM2880_BOARD_KWORLD_DVB_305U] = {
.name = "KWorld DVB-T 305U",
- .valid = EM28XX_BOARD_NOT_VALIDATED,
.tuner_type = TUNER_XC2028,
.tuner_gpio = default_tuner_gpio,
.decoder = EM28XX_TVP5150,
@@ -1770,16 +1818,27 @@ struct em28xx_board em28xx_boards[] = {
.dvb_gpio = kworld_a340_digital,
.tuner_gpio = default_tuner_gpio,
},
- /* 2013:024f PCTV Systems nanoStick T2 290e.
+ /* 2013:024f PCTV nanoStick T2 290e.
* Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */
[EM28174_BOARD_PCTV_290E] = {
+ .name = "PCTV nanoStick T2 290e",
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
- .xclk = EM28XX_XCLK_FREQUENCY_12MHZ,
- .name = "PCTV Systems nanoStick T2 290e",
.tuner_type = TUNER_ABSENT,
.tuner_gpio = pctv_290e,
.has_dvb = 1,
+ .ir_codes = RC_MAP_PINNACLE_PCTV_HD,
+ },
+ /* 2013:024f PCTV DVB-S2 Stick 460e
+ * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
+ [EM28174_BOARD_PCTV_460E] = {
+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
+ EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+ .name = "PCTV DVB-S2 Stick (460e)",
+ .tuner_type = TUNER_ABSENT,
+ .tuner_gpio = pctv_460e,
+ .has_dvb = 1,
+ .ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1855,13 +1914,17 @@ struct usb_device_id em28xx_id_table[] = {
{ USB_DEVICE(0x0ccd, 0x0042),
.driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
{ USB_DEVICE(0x0ccd, 0x0043),
- .driver_info = EM2870_BOARD_TERRATEC_XS },
- { USB_DEVICE(0x0ccd, 0x0047),
+ .driver_info = EM2884_BOARD_TERRATEC_H5 },
+ { USB_DEVICE(0x0ccd, 0x10a2), /* Rev. 1 */
+ .driver_info = EM2884_BOARD_TERRATEC_H5 },
+ { USB_DEVICE(0x0ccd, 0x10ad), /* Rev. 2 */
.driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
{ USB_DEVICE(0x0ccd, 0x0084),
.driver_info = EM2860_BOARD_TERRATEC_AV350 },
{ USB_DEVICE(0x0ccd, 0x0096),
.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+ { USB_DEVICE(0x0ccd, 0x10AF),
+ .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
{ USB_DEVICE(0x0fd9, 0x0033),
.driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
{ USB_DEVICE(0x185b, 0x2870),
@@ -1910,6 +1973,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2870_BOARD_KWORLD_A340 },
{ USB_DEVICE(0x2013, 0x024f),
.driver_info = EM28174_BOARD_PCTV_290E },
+ { USB_DEVICE(0x2013, 0x024c),
+ .driver_info = EM28174_BOARD_PCTV_460E },
{ },
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -1937,7 +2002,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
{0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT},
{0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
{0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
- {0x6b800080, EM2874_LEADERSHIP_ISDBT, TUNER_ABSENT},
+ {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
};
/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
@@ -2660,10 +2725,9 @@ void em28xx_card_setup(struct em28xx *dev)
.addr = 0xba >> 1,
.platform_data = &pdata,
};
- struct v4l2_subdev *sd;
pdata.xtal = dev->sensor_xtal;
- sd = v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
+ v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
&mt9v011_info, NULL);
}
@@ -2738,9 +2802,9 @@ static void flush_request_modules(struct em28xx *dev)
#endif /* CONFIG_MODULES */
/*
- * em28xx_realease_resources()
+ * em28xx_release_resources()
* unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
+ * called when the device gets disconnected or at module unload
*/
void em28xx_release_resources(struct em28xx *dev)
{
@@ -2754,8 +2818,6 @@ void em28xx_release_resources(struct em28xx *dev)
em28xx_release_analog_resources(dev);
- em28xx_remove_from_devlist(dev);
-
em28xx_i2c_unregister(dev);
v4l2_device_unregister(&dev->v4l2_dev);
@@ -2763,7 +2825,7 @@ void em28xx_release_resources(struct em28xx *dev)
usb_put_dev(dev->udev);
/* Mark device as unused */
- em28xx_devused &= ~(1 << dev->devno);
+ clear_bit(dev->devno, &em28xx_devused);
};
/*
@@ -2776,7 +2838,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
{
struct em28xx *dev = *devhandle;
int retval;
- int errCode;
dev->udev = udev;
mutex_init(&dev->ctrl_urb_lock);
@@ -2842,11 +2903,25 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
em28xx_info("chip ID is em2882/em2883\n");
dev->wait_after_write = 0;
break;
+ case CHIP_ID_EM2884:
+ em28xx_info("chip ID is em2884\n");
+ dev->reg_gpio_num = EM2874_R80_GPIO;
+ dev->wait_after_write = 0;
+ break;
default:
em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
}
}
+ if (dev->is_audio_only) {
+ retval = em28xx_audio_setup(dev);
+ if (retval)
+ return -ENODEV;
+ em28xx_init_extension(dev);
+
+ return 0;
+ }
+
/* Prepopulate cached GPO register content */
retval = em28xx_read_reg(dev, dev->reg_gpo_num);
if (retval >= 0)
@@ -2858,7 +2933,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
/* Resets I2C speed */
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
if (retval < 0) {
- em28xx_errdev("%s: em28xx_write_regs_req failed!"
+ em28xx_errdev("%s: em28xx_write_reg failed!"
" retval [%d]\n",
__func__, retval);
return retval;
@@ -2872,12 +2947,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
}
/* register i2c bus */
- errCode = em28xx_i2c_register(dev);
- if (errCode < 0) {
- v4l2_device_unregister(&dev->v4l2_dev);
- em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
- __func__, errCode);
- return errCode;
+ retval = em28xx_i2c_register(dev);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
+ __func__, retval);
+ goto unregister_dev;
}
/*
@@ -2891,11 +2965,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
em28xx_card_setup(dev);
/* Configure audio */
- errCode = em28xx_audio_setup(dev);
- if (errCode < 0) {
- v4l2_device_unregister(&dev->v4l2_dev);
- em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n",
- __func__, errCode);
+ retval = em28xx_audio_setup(dev);
+ if (retval < 0) {
+ em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
+ __func__, retval);
+ goto fail;
}
/* wake i2c devices */
@@ -2909,44 +2983,47 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
if (dev->board.has_msp34xx) {
/* Send a reset to other chips via gpio */
- errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
- if (errCode < 0) {
- em28xx_errdev("%s: em28xx_write_regs_req - "
- "msp34xx(1) failed! errCode [%d]\n",
- __func__, errCode);
- return errCode;
+ retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_write_reg - "
+ "msp34xx(1) failed! error [%d]\n",
+ __func__, retval);
+ goto fail;
}
msleep(3);
- errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
- if (errCode < 0) {
- em28xx_errdev("%s: em28xx_write_regs_req - "
- "msp34xx(2) failed! errCode [%d]\n",
- __func__, errCode);
- return errCode;
+ retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_write_reg - "
+ "msp34xx(2) failed! error [%d]\n",
+ __func__, retval);
+ goto fail;
}
msleep(3);
}
- em28xx_add_into_devlist(dev);
-
retval = em28xx_register_analog_devices(dev);
if (retval < 0) {
- em28xx_release_resources(dev);
- goto fail_reg_devices;
+ goto fail;
}
- em28xx_init_extension(dev);
-
/* Save some power by putting tuner to sleep */
v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
return 0;
-fail_reg_devices:
+fail:
+ em28xx_i2c_unregister(dev);
+
+unregister_dev:
+ v4l2_device_unregister(&dev->v4l2_dev);
+
return retval;
}
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
/*
* em28xx_usb_probe()
* checks for supported devices
@@ -2956,19 +3033,27 @@ static int em28xx_usb_probe(struct usb_interface *interface,
{
const struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev;
- struct usb_interface *uif;
struct em28xx *dev = NULL;
int retval;
- int i, nr, ifnum, isoc_pipe;
+ bool is_audio_only = false, has_audio = false;
+ int i, nr, isoc_pipe;
+ const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
char *speed;
char descr[255] = "";
udev = usb_get_dev(interface_to_usbdev(interface));
- ifnum = interface->altsetting[0].desc.bInterfaceNumber;
/* Check to see next free device and mark as used */
- nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
- em28xx_devused |= 1<<nr;
+ do {
+ nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+ if (nr >= EM28XX_MAXBOARDS) {
+ /* No free device slots */
+ printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+ EM28XX_MAXBOARDS);
+ retval = -ENOMEM;
+ goto err_no_slot;
+ }
+ } while (test_and_set_bit(nr, &em28xx_devused));
/* Don't register audio interfaces */
if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
@@ -2979,11 +3064,23 @@ static int em28xx_usb_probe(struct usb_interface *interface,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
- em28xx_devused &= ~(1<<nr);
retval = -ENODEV;
goto err;
}
+ /* Get endpoints */
+ for (i = 0; i < interface->num_altsetting; i++) {
+ int ep;
+
+ for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
+ struct usb_host_endpoint *e;
+ e = &interface->altsetting[i].endpoint[ep];
+
+ if (e->desc.bEndpointAddress == 0x83)
+ has_audio = true;
+ }
+ }
+
endpoint = &interface->cur_altsetting->endpoint[0].desc;
/* check if the device has the iso in endpoint at the correct place */
@@ -3003,19 +3100,21 @@ static int em28xx_usb_probe(struct usb_interface *interface,
check_interface = 0;
if (!check_interface) {
- em28xx_err(DRIVER_NAME " video device (%04x:%04x): "
- "interface %i, class %i found.\n",
- le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct),
- ifnum,
- interface->altsetting[0].desc.bInterfaceClass);
-
- em28xx_err(DRIVER_NAME " This is an anciliary "
- "interface not used by the driver\n");
-
- em28xx_devused &= ~(1<<nr);
- retval = -ENODEV;
- goto err;
+ if (has_audio) {
+ is_audio_only = true;
+ } else {
+ em28xx_err(DRIVER_NAME " video device (%04x:%04x): "
+ "interface %i, class %i found.\n",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ ifnum,
+ interface->altsetting[0].desc.bInterfaceClass);
+ em28xx_err(DRIVER_NAME " This is an anciliary "
+ "interface not used by the driver\n");
+
+ retval = -ENODEV;
+ goto err;
+ }
}
}
@@ -3045,8 +3144,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (*descr)
strlcat(descr, " ", sizeof(descr));
- printk(DRIVER_NAME ": New device %s@ %s Mbps "
- "(%04x:%04x, interface %d, class %d)\n",
+ printk(KERN_INFO DRIVER_NAME
+ ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n",
descr,
speed,
le16_to_cpu(udev->descriptor.idVendor),
@@ -3054,6 +3153,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
ifnum,
interface->altsetting->desc.bInterfaceNumber);
+ if (has_audio)
+ printk(KERN_INFO DRIVER_NAME
+ ": Audio Vendor Class interface %i found\n",
+ ifnum);
+
/*
* Make sure we have 480 Mbps of bandwidth, otherwise things like
* video stream wouldn't likely work, since 12 Mbps is generally
@@ -3063,36 +3167,29 @@ static int em28xx_usb_probe(struct usb_interface *interface,
printk(DRIVER_NAME ": Device initialization failed.\n");
printk(DRIVER_NAME ": Device must be connected to a high-speed"
" USB 2.0 port.\n");
- em28xx_devused &= ~(1<<nr);
retval = -ENODEV;
goto err;
}
- if (nr >= EM28XX_MAXBOARDS) {
- printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
- EM28XX_MAXBOARDS);
- em28xx_devused &= ~(1<<nr);
- retval = -ENOMEM;
- goto err;
- }
-
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n");
- em28xx_devused &= ~(1<<nr);
retval = -ENOMEM;
goto err;
}
- snprintf(dev->name, 29, "em28xx #%d", nr);
+ snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
dev->devno = nr;
dev->model = id->driver_info;
dev->alt = -1;
+ dev->is_audio_only = is_audio_only;
+ dev->has_alsa_audio = has_audio;
+ dev->audio_ifnum = ifnum;
/* Checks if audio is provided by some interface */
for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
- uif = udev->config->interface[i];
+ struct usb_interface *uif = udev->config->interface[i];
if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
dev->has_audio_class = 1;
break;
@@ -3100,42 +3197,43 @@ static int em28xx_usb_probe(struct usb_interface *interface,
}
/* compute alternate max packet sizes */
- uif = udev->actconfig->interface[0];
-
- dev->num_alt = uif->num_altsetting;
+ dev->num_alt = interface->num_altsetting;
dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
if (dev->alt_max_pkt_size == NULL) {
em28xx_errdev("out of memory!\n");
- em28xx_devused &= ~(1<<nr);
kfree(dev);
retval = -ENOMEM;
goto err;
}
for (i = 0; i < dev->num_alt ; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
- dev->alt_max_pkt_size[i] =
- (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+ u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
+ unsigned int size = tmp & 0x7ff;
+
+ if (udev->speed == USB_SPEED_HIGH)
+ size = size * hb_mult(tmp);
+
+ dev->alt_max_pkt_size[i] = size;
}
if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
dev->model = card[nr];
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
/* allocate device struct */
mutex_init(&dev->lock);
mutex_lock(&dev->lock);
retval = em28xx_init_dev(&dev, udev, interface, nr);
if (retval) {
- em28xx_devused &= ~(1<<dev->devno);
mutex_unlock(&dev->lock);
+ kfree(dev->alt_max_pkt_size);
kfree(dev);
goto err;
}
- /* save our data pointer in this interface device */
- usb_set_intfdata(interface, dev);
-
request_modules(dev);
/* Should be the last thing to do, to avoid newer udev's to
@@ -3143,15 +3241,26 @@ static int em28xx_usb_probe(struct usb_interface *interface,
*/
mutex_unlock(&dev->lock);
+ /*
+ * These extensions can be modules. If the modules are already
+ * loaded then we can initialise the device now, otherwise we
+ * will initialise it when the modules load instead.
+ */
+ em28xx_init_extension(dev);
+
return 0;
err:
+ clear_bit(nr, &em28xx_devused);
+
+err_no_slot:
+ usb_put_dev(udev);
return retval;
}
/*
* em28xx_usb_disconnect()
- * called when the device gets diconencted
+ * called when the device gets disconnected
* video device will be unregistered on v4l2_close in case it is still open
*/
static void em28xx_usb_disconnect(struct usb_interface *interface)
@@ -3164,6 +3273,13 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
if (!dev)
return;
+ if (dev->is_audio_only) {
+ mutex_lock(&dev->lock);
+ em28xx_close_extension(dev);
+ mutex_unlock(&dev->lock);
+ return;
+ }
+
em28xx_info("disconnecting %s\n", dev->vdev->name);
flush_request_modules(dev);
@@ -3192,10 +3308,10 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
em28xx_release_resources(dev);
}
- em28xx_close_extension(dev);
-
mutex_unlock(&dev->lock);
+ em28xx_close_extension(dev);
+
if (!dev->users) {
kfree(dev->alt_max_pkt_size);
kfree(dev);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index e33f145..804a4ab 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -211,6 +211,7 @@ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val)
{
return em28xx_write_regs(dev, reg, &val, 1);
}
+EXPORT_SYMBOL_GPL(em28xx_write_reg);
/*
* em28xx_write_reg_bits()
@@ -286,6 +287,7 @@ int em28xx_read_ac97(struct em28xx *dev, u8 reg)
return ret;
return le16_to_cpu(val);
}
+EXPORT_SYMBOL_GPL(em28xx_read_ac97);
/*
* em28xx_write_ac97()
@@ -313,13 +315,14 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val)
return 0;
}
+EXPORT_SYMBOL_GPL(em28xx_write_ac97);
-struct em28xx_vol_table {
+struct em28xx_vol_itable {
enum em28xx_amux mux;
u8 reg;
};
-static struct em28xx_vol_table inputs[] = {
+static struct em28xx_vol_itable inputs[] = {
{ EM28XX_AMUX_VIDEO, AC97_VIDEO_VOL },
{ EM28XX_AMUX_LINE_IN, AC97_LINEIN_VOL },
{ EM28XX_AMUX_PHONE, AC97_PHONE_VOL },
@@ -403,7 +406,12 @@ static int em28xx_set_audio_source(struct em28xx *dev)
return ret;
}
-static const struct em28xx_vol_table outputs[] = {
+struct em28xx_vol_otable {
+ enum em28xx_aout mux;
+ u8 reg;
+};
+
+static const struct em28xx_vol_otable outputs[] = {
{ EM28XX_AOUT_MASTER, AC97_MASTER_VOL },
{ EM28XX_AOUT_LINE, AC97_LINE_LEVEL_VOL },
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO_VOL },
@@ -492,17 +500,13 @@ int em28xx_audio_setup(struct em28xx *dev)
if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874
|| dev->chip_id == CHIP_ID_EM28174) {
/* Digital only device - don't load any alsa module */
- dev->audio_mode.has_audio = 0;
- dev->has_audio_class = 0;
- dev->has_alsa_audio = 0;
+ dev->audio_mode.has_audio = false;
+ dev->has_audio_class = false;
+ dev->has_alsa_audio = false;
return 0;
}
- /* If device doesn't support Usb Audio Class, use vendor class */
- if (!dev->has_audio_class)
- dev->has_alsa_audio = 1;
-
- dev->audio_mode.has_audio = 1;
+ dev->audio_mode.has_audio = true;
/* See how this device is configured */
cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
@@ -512,8 +516,8 @@ int em28xx_audio_setup(struct em28xx *dev)
cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */
} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) {
/* The device doesn't have vendor audio at all */
- dev->has_alsa_audio = 0;
- dev->audio_mode.has_audio = 0;
+ dev->has_alsa_audio = false;
+ dev->audio_mode.has_audio = false;
return 0;
} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
@@ -542,8 +546,8 @@ int em28xx_audio_setup(struct em28xx *dev)
*/
em28xx_warn("AC97 chip type couldn't be determined\n");
dev->audio_mode.ac97 = EM28XX_NO_AC97;
- dev->has_alsa_audio = 0;
- dev->audio_mode.has_audio = 0;
+ dev->has_alsa_audio = false;
+ dev->audio_mode.has_audio = false;
goto init_audio;
}
@@ -615,7 +619,9 @@ int em28xx_capture_start(struct em28xx *dev, int start)
{
int rc;
- if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) {
+ if (dev->chip_id == CHIP_ID_EM2874 ||
+ dev->chip_id == CHIP_ID_EM2884 ||
+ dev->chip_id == CHIP_ID_EM28174) {
/* The Transport Stream Enable Register moved in em2874 */
if (!start) {
rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
@@ -884,6 +890,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
}
return rc;
}
+EXPORT_SYMBOL_GPL(em28xx_gpio_set);
int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
{
@@ -917,7 +924,7 @@ EXPORT_SYMBOL_GPL(em28xx_set_mode);
static void em28xx_irq_callback(struct urb *urb)
{
struct em28xx *dev = urb->context;
- int rc, i;
+ int i;
switch (urb->status) {
case 0: /* success */
@@ -934,7 +941,7 @@ static void em28xx_irq_callback(struct urb *urb)
/* Copy data from URB */
spin_lock(&dev->slock);
- rc = dev->isoc_ctl.isoc_copy(dev, urb);
+ dev->isoc_ctl.isoc_copy(dev, urb);
spin_unlock(&dev->slock);
/* Reset urb buffers */
@@ -1106,17 +1113,19 @@ EXPORT_SYMBOL_GPL(em28xx_init_isoc);
int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
{
unsigned int chip_cfg2;
- unsigned int packet_size = 564;
-
- if (dev->chip_id == CHIP_ID_EM2874) {
- /* FIXME - for now assume 564 like it was before, but the
- em2874 code should be added to return the proper value... */
- packet_size = 564;
- } else if (dev->chip_id == CHIP_ID_EM28174) {
- /* FIXME same as em2874. 564 was enough for 22 Mbit DVB-T
- but too much for 44 Mbit DVB-C. */
- packet_size = 752;
- } else {
+ unsigned int packet_size;
+
+ switch (dev->chip_id) {
+ case CHIP_ID_EM2710:
+ case CHIP_ID_EM2750:
+ case CHIP_ID_EM2800:
+ case CHIP_ID_EM2820:
+ case CHIP_ID_EM2840:
+ case CHIP_ID_EM2860:
+ /* No DVB support */
+ return -EINVAL;
+ case CHIP_ID_EM2870:
+ case CHIP_ID_EM2883:
/* TS max packet size stored in bits 1-0 of R01 */
chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2);
switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) {
@@ -1133,9 +1142,24 @@ int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
packet_size = 752;
break;
}
+ break;
+ case CHIP_ID_EM2874:
+ /*
+ * FIXME: for now assumes 564 like it was before, but the
+ * em2874 code should be added to return the proper value
+ */
+ packet_size = 564;
+ break;
+ case CHIP_ID_EM2884:
+ case CHIP_ID_EM28174:
+ default:
+ /*
+ * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T
+ * but not enough for 44 Mbit DVB-C.
+ */
+ packet_size = 752;
}
- em28xx_coredbg("dvb max packet size=%d\n", packet_size);
return packet_size;
}
EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize);
@@ -1160,25 +1184,6 @@ static LIST_HEAD(em28xx_devlist);
static DEFINE_MUTEX(em28xx_devlist_mutex);
/*
- * em28xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void em28xx_remove_from_devlist(struct em28xx *dev)
-{
- mutex_lock(&em28xx_devlist_mutex);
- list_del(&dev->devlist);
- mutex_unlock(&em28xx_devlist_mutex);
-};
-
-void em28xx_add_into_devlist(struct em28xx *dev)
-{
- mutex_lock(&em28xx_devlist_mutex);
- list_add_tail(&dev->devlist, &em28xx_devlist);
- mutex_unlock(&em28xx_devlist_mutex);
-};
-
-/*
* Extension interface
*/
@@ -1193,8 +1198,8 @@ int em28xx_register_extension(struct em28xx_ops *ops)
list_for_each_entry(dev, &em28xx_devlist, devlist) {
ops->init(dev);
}
- printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_devlist_mutex);
+ printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
return 0;
}
EXPORT_SYMBOL(em28xx_register_extension);
@@ -1207,36 +1212,34 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
list_for_each_entry(dev, &em28xx_devlist, devlist) {
ops->fini(dev);
}
- printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next);
mutex_unlock(&em28xx_devlist_mutex);
+ printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
}
EXPORT_SYMBOL(em28xx_unregister_extension);
void em28xx_init_extension(struct em28xx *dev)
{
- struct em28xx_ops *ops = NULL;
+ const struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_devlist_mutex);
- if (!list_empty(&em28xx_extension_devlist)) {
- list_for_each_entry(ops, &em28xx_extension_devlist, next) {
- if (ops->init)
- ops->init(dev);
- }
+ list_add_tail(&dev->devlist, &em28xx_devlist);
+ list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+ if (ops->init)
+ ops->init(dev);
}
mutex_unlock(&em28xx_devlist_mutex);
}
void em28xx_close_extension(struct em28xx *dev)
{
- struct em28xx_ops *ops = NULL;
+ const struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_devlist_mutex);
- if (!list_empty(&em28xx_extension_devlist)) {
- list_for_each_entry(ops, &em28xx_extension_devlist, next) {
- if (ops->fini)
- ops->fini(dev);
- }
+ list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+ if (ops->fini)
+ ops->fini(dev);
}
+ list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
}
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 7904ca4..cef7a2d 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -1,7 +1,7 @@
/*
DVB device driver for em28xx
- (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+ (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
(c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
- Fixes for the driver to properly work with HVR-950
@@ -40,6 +40,10 @@
#include "s921.h"
#include "drxd.h"
#include "cxd2820r.h"
+#include "tda18271c2dd.h"
+#include "drxk.h"
+#include "tda10071.h"
+#include "a8293.h"
MODULE_DESCRIPTION("driver for em28xx based DVB cards");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -73,6 +77,11 @@ struct em28xx_dvb {
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
struct dvb_net net;
+
+ /* Due to DRX-K - probably need changes */
+ int (*gate_ctrl)(struct dvb_frontend *, int);
+ struct semaphore pll_mutex;
+ bool dont_attach_fe1;
};
@@ -115,7 +124,7 @@ static inline void print_err_status(struct em28xx *dev,
}
}
-static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
{
int i;
@@ -148,7 +157,7 @@ static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
return 0;
}
-static int start_streaming(struct em28xx_dvb *dvb)
+static int em28xx_start_streaming(struct em28xx_dvb *dvb)
{
int rc;
struct em28xx *dev = dvb->adapter.priv;
@@ -160,13 +169,18 @@ static int start_streaming(struct em28xx_dvb *dvb)
return rc;
max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev);
+ if (max_dvb_packet_size < 0)
+ return max_dvb_packet_size;
+ dprintk(1, "Using %d buffers each with %d bytes\n",
+ EM28XX_DVB_NUM_BUFS,
+ max_dvb_packet_size);
return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
- dvb_isoc_copy);
+ em28xx_dvb_isoc_copy);
}
-static int stop_streaming(struct em28xx_dvb *dvb)
+static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
{
struct em28xx *dev = dvb->adapter.priv;
@@ -177,7 +191,7 @@ static int stop_streaming(struct em28xx_dvb *dvb)
return 0;
}
-static int start_feed(struct dvb_demux_feed *feed)
+static int em28xx_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct em28xx_dvb *dvb = demux->priv;
@@ -191,7 +205,7 @@ static int start_feed(struct dvb_demux_feed *feed)
rc = dvb->nfeeds;
if (dvb->nfeeds == 1) {
- ret = start_streaming(dvb);
+ ret = em28xx_start_streaming(dvb);
if (ret < 0)
rc = ret;
}
@@ -200,7 +214,7 @@ static int start_feed(struct dvb_demux_feed *feed)
return rc;
}
-static int stop_feed(struct dvb_demux_feed *feed)
+static int em28xx_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct em28xx_dvb *dvb = demux->priv;
@@ -210,7 +224,7 @@ static int stop_feed(struct dvb_demux_feed *feed)
dvb->nfeeds--;
if (0 == dvb->nfeeds)
- err = stop_streaming(dvb);
+ err = em28xx_stop_streaming(dvb);
mutex_unlock(&dvb->lock);
return err;
@@ -295,7 +309,80 @@ static struct drxd_config em28xx_drxd = {
.disable_i2c_gate_ctrl = 1,
};
-static int mt352_terratec_xs_init(struct dvb_frontend *fe)
+struct drxk_config terratec_h5_drxk = {
+ .adr = 0x29,
+ .single_master = 1,
+ .no_i2c_bridge = 1,
+ .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
+};
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct em28xx_dvb *dvb = fe->sec_priv;
+ int status;
+
+ if (!dvb)
+ return -EINVAL;
+
+ if (enable) {
+ down(&dvb->pll_mutex);
+ status = dvb->gate_ctrl(fe, 1);
+ } else {
+ status = dvb->gate_ctrl(fe, 0);
+ up(&dvb->pll_mutex);
+ }
+ return status;
+}
+
+static void terratec_h5_init(struct em28xx *dev)
+{
+ int i;
+ struct em28xx_reg_seq terratec_h5_init[] = {
+ {EM28XX_R08_GPIO, 0xff, 0xff, 10},
+ {EM2874_R80_GPIO, 0xf6, 0xff, 100},
+ {EM2874_R80_GPIO, 0xf2, 0xff, 50},
+ {EM2874_R80_GPIO, 0xf6, 0xff, 100},
+ { -1, -1, -1, -1},
+ };
+ struct em28xx_reg_seq terratec_h5_end[] = {
+ {EM2874_R80_GPIO, 0xe6, 0xff, 100},
+ {EM2874_R80_GPIO, 0xa6, 0xff, 50},
+ {EM2874_R80_GPIO, 0xe6, 0xff, 100},
+ { -1, -1, -1, -1},
+ };
+ struct {
+ unsigned char r[4];
+ int len;
+ } regs[] = {
+ {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+ {{ 0x01, 0x02 }, 2},
+ {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+ {{ 0x01, 0x00 }, 2},
+ {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+ {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+ {{ 0x01, 0x00 }, 2},
+ {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+ {{ 0x04, 0x00 }, 2},
+ {{ 0x00, 0x04 }, 2},
+ {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+ {{ 0x04, 0x14 }, 2},
+ {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+ };
+
+ em28xx_gpio_set(dev, terratec_h5_init);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+ msleep(10);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+ msleep(10);
+
+ dev->i2c_client.addr = 0x82 >> 1;
+
+ for (i = 0; i < ARRAY_SIZE(regs); i++)
+ i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+ em28xx_gpio_set(dev, terratec_h5_end);
+};
+
+static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
{
/* Values extracted from a USB trace of the Terratec Windows driver */
static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c };
@@ -327,7 +414,7 @@ static struct mt352_config terratec_xs_mt352_cfg = {
.demod_address = (0x1e >> 1),
.no_tuner = 1,
.if2 = 45600,
- .demod_init = mt352_terratec_xs_init,
+ .demod_init = em28xx_mt352_terratec_xs_init,
};
static struct tda10023_config em28xx_tda10023_config = {
@@ -353,11 +440,25 @@ static struct cxd2820r_config em28xx_cxd2820r_config = {
static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
.output_opt = TDA18271_OUTPUT_LT_OFF,
+ .gate = TDA18271_GATE_DIGITAL,
+};
+
+static const struct tda10071_config em28xx_tda10071_config = {
+ .i2c_address = 0x55, /* (0xaa >> 1) */
+ .i2c_wr_max = 64,
+ .ts_mode = TDA10071_TS_SERIAL,
+ .spec_inv = 0,
+ .xtal = 40444000, /* 40.444 MHz */
+ .pll_multiplier = 20,
+};
+
+static const struct a8293_config em28xx_a8293_config = {
+ .i2c_addr = 0x08, /* (0x10 >> 1) */
};
/* ------------------------------------------------------------------ */
-static int attach_xc3028(u8 addr, struct em28xx *dev)
+static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
{
struct dvb_frontend *fe;
struct xc2028_config cfg;
@@ -387,10 +488,8 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
/* ------------------------------------------------------------------ */
-static int register_dvb(struct em28xx_dvb *dvb,
- struct module *module,
- struct em28xx *dev,
- struct device *device)
+static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
+ struct em28xx *dev, struct device *device)
{
int result;
@@ -437,8 +536,8 @@ static int register_dvb(struct em28xx_dvb *dvb,
dvb->demux.priv = dvb;
dvb->demux.filternum = 256;
dvb->demux.feednum = 256;
- dvb->demux.start_feed = start_feed;
- dvb->demux.stop_feed = stop_feed;
+ dvb->demux.start_feed = em28xx_start_feed;
+ dvb->demux.stop_feed = em28xx_stop_feed;
result = dvb_dmx_init(&dvb->demux);
if (result < 0) {
@@ -506,7 +605,7 @@ fail_adapter:
return result;
}
-static void unregister_dvb(struct em28xx_dvb *dvb)
+static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
{
dvb_net_release(&dvb->net);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
@@ -516,15 +615,15 @@ static void unregister_dvb(struct em28xx_dvb *dvb)
if (dvb->fe[1])
dvb_unregister_frontend(dvb->fe[1]);
dvb_unregister_frontend(dvb->fe[0]);
- if (dvb->fe[1])
+ if (dvb->fe[1] && !dvb->dont_attach_fe1)
dvb_frontend_detach(dvb->fe[1]);
dvb_frontend_detach(dvb->fe[0]);
dvb_unregister_adapter(&dvb->adapter);
}
-static int dvb_init(struct em28xx *dev)
+static int em28xx_dvb_init(struct em28xx *dev)
{
- int result = 0;
+ int result = 0, mfe_shared = 0;
struct em28xx_dvb *dvb;
if (!dev->board.has_dvb) {
@@ -546,7 +645,7 @@ static int dvb_init(struct em28xx *dev)
em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
/* init frontend */
switch (dev->model) {
- case EM2874_LEADERSHIP_ISDBT:
+ case EM2874_BOARD_LEADERSHIP_ISDBT:
dvb->fe[0] = dvb_attach(s921_attach,
&sharp_isdbt, &dev->i2c_adap);
@@ -563,7 +662,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(lgdt330x_attach,
&em2880_lgdt3303_dev,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -572,7 +671,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(zl10353_attach,
&em28xx_zl10353_with_xc3028,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -583,7 +682,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(zl10353_attach,
&em28xx_zl10353_xc3028_no_i2c_gate,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -604,7 +703,7 @@ static int dvb_init(struct em28xx *dev)
&dev->i2c_adap);
}
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -614,7 +713,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(s5h1409_attach,
&em28xx_s5h1409_with_xc3028,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -635,7 +734,7 @@ static int dvb_init(struct em28xx *dev)
case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
&dev->i2c_adap, &dev->udev->dev);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -668,11 +767,9 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(cxd2820r_attach,
&em28xx_cxd2820r_config, &dev->i2c_adap, NULL);
if (dvb->fe[0]) {
- struct i2c_adapter *i2c_tuner;
- i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]);
/* FE 0 attach tuner */
if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
- i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+ &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
dvb_frontend_detach(dvb->fe[0]);
result = -EINVAL;
goto out_free;
@@ -683,12 +780,59 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[1]->id = 1;
/* FE 1 attach tuner */
if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60,
- i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+ &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
dvb_frontend_detach(dvb->fe[1]);
/* leave FE 0 still active */
}
+
+ mfe_shared = 1;
}
break;
+ case EM2884_BOARD_TERRATEC_H5:
+ terratec_h5_init(dev);
+
+ dvb->dont_attach_fe1 = 1;
+
+ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]);
+ if (!dvb->fe[0]) {
+ result = -EINVAL;
+ goto out_free;
+ }
+
+ /* FIXME: do we need a pll semaphore? */
+ dvb->fe[0]->sec_priv = dvb;
+ sema_init(&dvb->pll_mutex, 1);
+ dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+ dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+ dvb->fe[1]->id = 1;
+
+ /* Attach tda18271 to DVB-C frontend */
+ if (dvb->fe[0]->ops.i2c_gate_ctrl)
+ dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+ if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ if (dvb->fe[0]->ops.i2c_gate_ctrl)
+ dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
+ /* Hack - needed by drxk/tda18271c2dd */
+ dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv;
+ memcpy(&dvb->fe[1]->ops.tuner_ops,
+ &dvb->fe[0]->ops.tuner_ops,
+ sizeof(dvb->fe[0]->ops.tuner_ops));
+
+ break;
+ case EM28174_BOARD_PCTV_460E:
+ /* attach demod */
+ dvb->fe[0] = dvb_attach(tda10071_attach,
+ &em28xx_tda10071_config, &dev->i2c_adap);
+
+ /* attach SEC */
+ if (dvb->fe[0])
+ dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
+ &em28xx_a8293_config);
+ break;
default:
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n");
@@ -703,11 +847,14 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0]->callback = em28xx_tuner_callback;
/* register everything */
- result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+ result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
if (result < 0)
goto out_free;
+ /* MFE lock */
+ dvb->adapter.mfe_shared = mfe_shared;
+
em28xx_info("Successfully loaded em28xx-dvb\n");
ret:
em28xx_set_mode(dev, EM28XX_SUSPEND);
@@ -720,7 +867,14 @@ out_free:
goto ret;
}
-static int dvb_fini(struct em28xx *dev)
+static inline void prevent_sleep(struct dvb_frontend_ops *ops)
+{
+ ops->set_voltage = NULL;
+ ops->sleep = NULL;
+ ops->tuner_ops.sleep = NULL;
+}
+
+static int em28xx_dvb_fini(struct em28xx *dev)
{
if (!dev->board.has_dvb) {
/* This device does not support the extension */
@@ -728,8 +882,19 @@ static int dvb_fini(struct em28xx *dev)
}
if (dev->dvb) {
- unregister_dvb(dev->dvb);
- kfree(dev->dvb);
+ struct em28xx_dvb *dvb = dev->dvb;
+
+ if (dev->state & DEV_DISCONNECTED) {
+ /* We cannot tell the device to sleep
+ * once it has been unplugged. */
+ if (dvb->fe[0])
+ prevent_sleep(&dvb->fe[0]->ops);
+ if (dvb->fe[1])
+ prevent_sleep(&dvb->fe[1]->ops);
+ }
+
+ em28xx_unregister_dvb(dvb);
+ kfree(dvb);
dev->dvb = NULL;
}
@@ -739,8 +904,8 @@ static int dvb_fini(struct em28xx *dev)
static struct em28xx_ops dvb_ops = {
.id = EM28XX_DVB,
.name = "Em28xx dvb Extension",
- .init = dvb_init,
- .fini = dvb_fini,
+ .init = em28xx_dvb_init,
+ .fini = em28xx_dvb_fini,
};
static int __init em28xx_dvb_register(void)
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 4739fc7..36f5a9b 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -181,16 +181,25 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
/*
* em28xx_i2c_send_bytes()
- * untested for more than 4 bytes
*/
static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
short len, int stop)
{
int wrcount = 0;
struct em28xx *dev = (struct em28xx *)data;
+ int write_timeout, ret;
wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
+ /* Seems to be required after a write */
+ for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
+ write_timeout -= 5) {
+ ret = dev->em28xx_read_reg(dev, 0x05);
+ if (!ret)
+ break;
+ msleep(5);
+ }
+
return wrcount;
}
@@ -218,9 +227,7 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
*/
static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
{
- char msg;
int ret;
- msg = addr;
ret = dev->em28xx_read_reg_req(dev, 2, addr);
if (ret < 0) {
@@ -332,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
struct em28xx_eeprom *em_eeprom = (void *)eedata;
int i, err, size = len, block;
- if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) {
+ if (dev->chip_id == CHIP_ID_EM2874 ||
+ dev->chip_id == CHIP_ID_EM28174 ||
+ dev->chip_id == CHIP_ID_EM2884) {
/* Empia switched to a 16-bit addressable eeprom in newer
devices. While we could certainly write a routine to read
the eeprom, there is nothing of use in there that cannot be
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index ba1ba86..679da48 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -372,6 +372,7 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
ir->get_key = default_polling_getkey;
break;
case CHIP_ID_EM2874:
+ case CHIP_ID_EM28174:
ir->get_key = em2874_polling_getkey;
em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
break;
@@ -462,11 +463,11 @@ int em28xx_ir_fini(struct em28xx *dev)
if (!ir)
return 0;
- em28xx_ir_stop(ir->rc);
- rc_unregister_device(ir->rc);
- kfree(ir);
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
/* done */
+ kfree(ir);
dev->ir = NULL;
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
index e92a28e..66f7923 100644
--- a/drivers/media/video/em28xx/em28xx-reg.h
+++ b/drivers/media/video/em28xx/em28xx-reg.h
@@ -201,6 +201,7 @@ enum em28xx_chip_id {
CHIP_ID_EM2870 = 35,
CHIP_ID_EM2883 = 36,
CHIP_ID_EM2874 = 65,
+ CHIP_ID_EM2884 = 68,
CHIP_ID_EM28174 = 113,
};
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 7b6461d..9b4557a 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -32,7 +32,6 @@
#include <linux/bitmap.h>
#include <linux/usb.h>
#include <linux/i2c.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -50,7 +49,8 @@
"Sascha Sommer <saschasommer@freenet.de>"
#define DRIVER_DESC "Empia em28xx based USB video device driver"
-#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 2)
+
+#define EM28XX_VERSION "0.1.3"
#define em28xx_videodbg(fmt, arg...) do {\
if (video_debug) \
@@ -72,6 +72,7 @@ do {\
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_VERSION(EM28XX_VERSION);
static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
@@ -1155,6 +1156,21 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
return 0;
}
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
+
+ v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+
+ return 0;
+}
+
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
{
struct em28xx_fh *fh = priv;
@@ -1757,8 +1773,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->version = EM28XX_VERSION_CODE;
-
cap->capabilities =
V4L2_CAP_SLICED_VBI_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE |
@@ -1788,6 +1802,45 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+ struct em28xx_fmt *fmt;
+ unsigned int maxw = norm_maxw(dev);
+ unsigned int maxh = norm_maxh(dev);
+
+ fmt = format_by_fourcc(fsize->pixel_format);
+ if (!fmt) {
+ em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+ fsize->pixel_format);
+ return -EINVAL;
+ }
+
+ if (dev->board.is_em2800) {
+ if (fsize->index > 1)
+ return -EINVAL;
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = maxw / (1 + fsize->index);
+ fsize->discrete.height = maxh / (1 + fsize->index);
+ return 0;
+ }
+
+ if (fsize->index != 0)
+ return -EINVAL;
+
+ /* Report a continuous range */
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = 48;
+ fsize->stepwise.min_height = 32;
+ fsize->stepwise.max_width = maxw;
+ fsize->stepwise.max_height = maxh;
+ fsize->stepwise.step_width = 1;
+ fsize->stepwise.step_height = 1;
+ return 0;
+}
+
/* Sliced VBI ioctls */
static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
@@ -1976,7 +2029,6 @@ static int radio_querycap(struct file *file, void *priv,
strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->version = EM28XX_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
return 0;
}
@@ -2202,6 +2254,7 @@ static int em28xx_v4l2_close(struct file *filp)
free the remaining resources */
if (dev->state & DEV_DISCONNECTED) {
em28xx_release_resources(dev);
+ kfree(dev->alt_max_pkt_size);
kfree(dev);
return 0;
}
@@ -2342,10 +2395,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
+ .vidioc_enum_framesizes = vidioc_enum_framesizes,
.vidioc_g_audio = vidioc_g_audio,
.vidioc_s_audio = vidioc_s_audio,
.vidioc_cropcap = vidioc_cropcap,
-
.vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
.vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
@@ -2355,6 +2408,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_g_std = vidioc_g_std,
+ .vidioc_querystd = vidioc_querystd,
.vidioc_s_std = vidioc_s_std,
.vidioc_g_parm = vidioc_g_parm,
.vidioc_s_parm = vidioc_s_parm,
@@ -2450,10 +2504,8 @@ int em28xx_register_analog_devices(struct em28xx *dev)
u8 val;
int ret;
- printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n",
- dev->name,
- (EM28XX_VERSION_CODE >> 16) & 0xff,
- (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);
+ printk(KERN_INFO "%s: v4l2 driver version %s\n",
+ dev->name, EM28XX_VERSION);
/* set default norm */
dev->norm = em28xx_video_template.current_norm;
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 3cca331..2a2cb7e 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -117,9 +117,10 @@
#define EM2800_BOARD_VC211A 74
#define EM2882_BOARD_DIKOM_DK300 75
#define EM2870_BOARD_KWORLD_A340 76
-#define EM2874_LEADERSHIP_ISDBT 77
+#define EM2874_BOARD_LEADERSHIP_ISDBT 77
#define EM28174_BOARD_PCTV_290E 78
-
+#define EM2884_BOARD_TERRATEC_H5 79
+#define EM28174_BOARD_PCTV_460E 80
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
@@ -487,6 +488,8 @@ struct em28xx {
int devno; /* marks the number of this device */
enum em28xx_chip_id chip_id;
+ int audio_ifnum;
+
struct v4l2_device v4l2_dev;
struct em28xx_board board;
@@ -503,6 +506,7 @@ struct em28xx {
unsigned int has_audio_class:1;
unsigned int has_alsa_audio:1;
+ unsigned int is_audio_only:1;
/* Controls audio streaming */
struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */
@@ -674,8 +678,6 @@ int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
void em28xx_wake_i2c(struct em28xx *dev);
-void em28xx_remove_from_devlist(struct em28xx *dev);
-void em28xx_add_into_devlist(struct em28xx *dev);
int em28xx_register_extension(struct em28xx_ops *dev);
void em28xx_unregister_extension(struct em28xx_ops *dev);
void em28xx_init_extension(struct em28xx *dev);
@@ -697,6 +699,9 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
void em28xx_release_resources(struct em28xx *dev);
/* Provided by em28xx-input.c */
+
+#ifdef CONFIG_VIDEO_EM28XX_RC
+
int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
@@ -709,6 +714,20 @@ void em28xx_deregister_snapshot_button(struct em28xx *dev);
int em28xx_ir_init(struct em28xx *dev);
int em28xx_ir_fini(struct em28xx *dev);
+#else
+
+#define em28xx_get_key_terratec NULL
+#define em28xx_get_key_em_haup NULL
+#define em28xx_get_key_pinnacle_usb_grey NULL
+#define em28xx_get_key_winfast_usbii_deluxe NULL
+
+static inline void em28xx_register_snapshot_button(struct em28xx *dev) {}
+static inline void em28xx_deregister_snapshot_button(struct em28xx *dev) {}
+static inline int em28xx_ir_init(struct em28xx *dev) { return 0; }
+static inline int em28xx_ir_fini(struct em28xx *dev) { return 0; }
+
+#endif
+
/* Provided by em28xx-vbi.c */
extern struct videobuf_queue_ops em28xx_vbi_qops;
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h
index bf66189..337ded4 100644
--- a/drivers/media/video/et61x251/et61x251.h
+++ b/drivers/media/video/et61x251/et61x251.h
@@ -21,7 +21,6 @@
#ifndef _ET61X251_H_
#define _ET61X251_H_
-#include <linux/version.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
@@ -166,45 +165,49 @@ et61x251_attach_sensor(struct et61x251_device* cam,
#undef DBG
#undef KDBG
#ifdef ET61X251_DEBUG
-# define DBG(level, fmt, args...) \
-do { \
- if (debug >= (level)) { \
- if ((level) == 1) \
- dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
- else if ((level) == 2) \
- dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
- else if ((level) >= 3) \
- dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
- __FILE__, __func__, __LINE__ , ## args); \
- } \
+#define DBG(level, fmt, ...) \
+do { \
+ if (debug >= (level)) { \
+ if ((level) == 1) \
+ dev_err(&cam->usbdev->dev, fmt "\n", \
+ ##__VA_ARGS__); \
+ else if ((level) == 2) \
+ dev_info(&cam->usbdev->dev, fmt "\n", \
+ ##__VA_ARGS__); \
+ else if ((level) >= 3) \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+ __FILE__, __func__, __LINE__, \
+ ##__VA_ARGS__); \
+ } \
} while (0)
-# define KDBG(level, fmt, args...) \
-do { \
- if (debug >= (level)) { \
- if ((level) == 1 || (level) == 2) \
- pr_info("et61x251: " fmt "\n", ## args); \
- else if ((level) == 3) \
- pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
- __func__, __LINE__ , ## args); \
- } \
+#define KDBG(level, fmt, ...) \
+do { \
+ if (debug >= (level)) { \
+ if ((level) == 1 || (level) == 2) \
+ pr_info(fmt "\n", ##__VA_ARGS__); \
+ else if ((level) == 3) \
+ pr_debug("[%s:%s:%d] " fmt "\n", \
+ __FILE__, __func__, __LINE__, \
+ ##__VA_ARGS__); \
+ } \
} while (0)
-# define V4LDBG(level, name, cmd) \
-do { \
- if (debug >= (level)) \
- v4l_print_ioctl(name, cmd); \
+#define V4LDBG(level, name, cmd) \
+do { \
+ if (debug >= (level)) \
+ v4l_print_ioctl(name, cmd); \
} while (0)
#else
-# define DBG(level, fmt, args...) do {;} while(0)
-# define KDBG(level, fmt, args...) do {;} while(0)
-# define V4LDBG(level, name, cmd) do {;} while(0)
+#define DBG(level, fmt, ...) do {;} while(0)
+#define KDBG(level, fmt, ...) do {;} while(0)
+#define V4LDBG(level, name, cmd) do {;} while(0)
#endif
#undef PDBG
-#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
- __LINE__ , ## args)
+#define PDBG(fmt, ...) \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+ __FILE__, __func__, __LINE__, ##__VA_ARGS__)
#undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+#define PDBGG(fmt, args...) do {;} while (0) /* placeholder */
#endif /* _ET61X251_H_ */
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index a982750..d3777c8 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -18,6 +18,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -48,8 +51,7 @@
#define ET61X251_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia"
#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ET61X251_MODULE_LICENSE "GPL"
-#define ET61X251_MODULE_VERSION "1:1.09"
-#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 9)
+#define ET61X251_MODULE_VERSION "1.1.10"
/*****************************************************************************/
@@ -1579,7 +1581,7 @@ et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
{
struct v4l2_capability cap = {
.driver = "et61x251",
- .version = ET61X251_MODULE_VERSION_CODE,
+ .version = LINUX_VERSION_CODE,
.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING,
};
@@ -2480,16 +2482,8 @@ static long et61x251_ioctl_v4l2(struct file *filp,
case VIDIOC_S_PARM:
return et61x251_vidioc_s_parm(cam, arg);
- case VIDIOC_G_STD:
- case VIDIOC_S_STD:
- case VIDIOC_QUERYSTD:
- case VIDIOC_ENUMSTD:
- case VIDIOC_QUERYMENU:
- case VIDIOC_ENUM_FRAMEINTERVALS:
- return -EINVAL;
-
default:
- return -EINVAL;
+ return -ENOTTY;
}
}
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
index 04b7fbb..ced2e16 100644
--- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c
+++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "et61x251_sensor.h"
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 34ae2c2..103af3f 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -179,6 +179,16 @@ config USB_GSPCA_PAC7311
To compile this driver as a module, choose M here: the
module will be called gspca_pac7311.
+config USB_GSPCA_SE401
+ tristate "SE401 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the
+ Endpoints (formerly known as AOX) se401 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_se401.
+
config USB_GSPCA_SN9C2028
tristate "SONIX Dual-Mode USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
@@ -346,6 +356,16 @@ config USB_GSPCA_T613
To compile this driver as a module, choose M here: the
module will be called gspca_t613.
+config USB_GSPCA_TOPRO
+ tristate "TOPRO USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the
+ TP6800 and TP6810 Topro chips.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_topro.
+
config USB_GSPCA_TV8532
tristate "TV8532 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index 802fbe1..f345f49 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o
obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o
obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SE401) += gspca_se401.o
obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o
obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o
obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o
obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o
@@ -58,6 +60,7 @@ gspca_ov534_9-objs := ov534_9.o
gspca_pac207-objs := pac207.o
gspca_pac7302-objs := pac7302.o
gspca_pac7311-objs := pac7311.o
+gspca_se401-objs := se401.o
gspca_sn9c2028-objs := sn9c2028.o
gspca_sn9c20x-objs := sn9c20x.o
gspca_sonixb-objs := sonixb.o
@@ -76,6 +79,7 @@ gspca_stk014-objs := stk014.o
gspca_stv0680-objs := stv0680.o
gspca_sunplus-objs := sunplus.o
gspca_t613-objs := t613.o
+gspca_topro-objs := topro.o
gspca_tv8532-objs := tv8532.o
gspca_vc032x-objs := vc032x.o
gspca_vicam-objs := vicam.o
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c
index a09c470..6ae2616 100644
--- a/drivers/media/video/gspca/benq.c
+++ b/drivers/media/video/gspca/benq.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "benq"
#include "gspca.h"
@@ -62,7 +64,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
0,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -84,20 +86,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
- int ret;
-
- ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,
- gspca_dev->nbalt - 1);
- if (ret < 0) {
- err("usb_set_interface failed");
- return ret;
- }
-/* reg_w(gspca_dev, 0x0003, 0x0002); */
- return 0;
-}
-
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
@@ -113,7 +101,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
for (n = 0; n < 4; n++) {
urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
if (!urb) {
- err("usb_alloc_urb failed");
+ pr_err("usb_alloc_urb failed\n");
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
@@ -123,7 +111,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
- err("usb_alloc_coherent failed");
+ pr_err("usb_alloc_coherent failed\n");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;
@@ -181,7 +169,7 @@ static void sd_isoc_irq(struct urb *urb)
if (gspca_dev->frozen)
return;
#endif
- err("urb status: %d", urb->status);
+ pr_err("urb status: %d\n", urb->status);
return;
}
@@ -209,7 +197,7 @@ static void sd_isoc_irq(struct urb *urb)
if (st == 0)
st = urb->iso_frame_desc[i].status;
if (st) {
- err("ISOC data error: [%d] status=%d",
+ pr_err("ISOC data error: [%d] status=%d\n",
i, st);
gspca_dev->last_packet_type = DISCARD_PACKET;
continue;
@@ -256,10 +244,10 @@ static void sd_isoc_irq(struct urb *urb)
/* resubmit the URBs */
st = usb_submit_urb(urb0, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb(0) ret %d", st);
+ pr_err("usb_submit_urb(0) ret %d\n", st);
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb() ret %d", st);
+ pr_err("usb_submit_urb() ret %d\n", st);
}
/* sub-driver description */
@@ -269,7 +257,6 @@ static const struct sd_desc sd_desc = {
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.init = sd_init,
- .isoc_init = sd_isoc_init,
.start = sd_start,
.stopN = sd_stopN,
.pkt_scan = sd_pkt_scan,
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 8b39849..4c56dbe 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "conex"
#include "gspca.h"
@@ -129,7 +131,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -169,7 +171,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
+ pr_err("reg_w: buffer overflow\n");
return;
}
PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c
index f2a9451..f9b86b2 100644
--- a/drivers/media/video/gspca/cpia1.c
+++ b/drivers/media/video/gspca/cpia1.c
@@ -26,6 +26,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "cpia1"
#include <linux/input.h>
@@ -550,8 +552,7 @@ retry:
gspca_dev->usb_buf, databytes, 1000);
if (ret < 0)
- err("usb_control_msg %02x, error %d", command[1],
- ret);
+ pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
if (ret == -EPIPE && retries > 0) {
retries--;
@@ -1279,7 +1280,7 @@ static void monitor_exposure(struct gspca_dev *gspca_dev)
cmd[7] = 0;
ret = cpia_usb_transferCmd(gspca_dev, cmd);
if (ret) {
- err("ReadVPRegs(30,4,9,8) - failed: %d", ret);
+ pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
return;
}
exp_acc = gspca_dev->usb_buf[0];
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index 4b2c483..0357d6d 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "etoms"
#include "gspca.h"
@@ -236,7 +238,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -274,7 +276,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
+ pr_err("reg_w: buffer overflow\n");
return;
}
PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
index 987b4b6..ea48200 100644
--- a/drivers/media/video/gspca/finepix.c
+++ b/drivers/media/video/gspca/finepix.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "finepix"
#include "gspca.h"
@@ -182,7 +184,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* Init the device */
ret = command(gspca_dev, 0);
if (ret < 0) {
- err("init failed %d", ret);
+ pr_err("init failed %d\n", ret);
return ret;
}
@@ -194,14 +196,14 @@ static int sd_start(struct gspca_dev *gspca_dev)
FPIX_MAX_TRANSFER, &len,
FPIX_TIMEOUT);
if (ret < 0) {
- err("usb_bulk_msg failed %d", ret);
+ pr_err("usb_bulk_msg failed %d\n", ret);
return ret;
}
/* Request a frame, but don't read it */
ret = command(gspca_dev, 1);
if (ret < 0) {
- err("frame request failed %d", ret);
+ pr_err("frame request failed %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/gl860/Makefile b/drivers/media/video/gspca/gl860/Makefile
index 13c9403..f511ecc 100644
--- a/drivers/media/video/gspca/gl860/Makefile
+++ b/drivers/media/video/gspca/gl860/Makefile
@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \
gl860-ov9655.o \
gl860-mi2020.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
index e8e071a..2ced3b7 100644
--- a/drivers/media/video/gspca/gl860/gl860.c
+++ b/drivers/media/video/gspca/gl860/gl860.c
@@ -18,6 +18,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "gspca.h"
#include "gl860.h"
@@ -572,9 +575,8 @@ int gl860_RTx(struct gspca_dev *gspca_dev,
}
if (r < 0)
- err("ctrl transfer failed %4d "
- "[p%02x r%d v%04x i%04x len%d]",
- r, pref, req, val, index, len);
+ pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
+ r, pref, req, val, index, len);
else if (len > 1 && r < len)
PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h
index 49ad4ac..0330a02 100644
--- a/drivers/media/video/gspca/gl860/gl860.h
+++ b/drivers/media/video/gspca/gl860/gl860.h
@@ -18,7 +18,6 @@
*/
#ifndef GL860_DEV_H
#define GL860_DEV_H
-#include <linux/version.h>
#include "gspca.h"
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 08ce994..981501f 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -21,10 +21,11 @@
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define MODULE_NAME "gspca"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define GSPCA_VERSION "2.14.0"
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
@@ -54,8 +55,7 @@
MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
-
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 13, 0)
+MODULE_VERSION(GSPCA_VERSION);
#ifdef GSPCA_DEBUG
int gspca_debug = D_ERR | D_PROBE;
@@ -148,7 +148,7 @@ static void int_irq(struct urb *urb)
if (ret == 0) {
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0)
- err("Resubmit URB failed with error %i", ret);
+ pr_err("Resubmit URB failed with error %i\n", ret);
}
}
@@ -177,8 +177,8 @@ static int gspca_input_connect(struct gspca_dev *dev)
err = input_register_device(input_dev);
if (err) {
- err("Input device registration failed with error %i",
- err);
+ pr_err("Input device registration failed with error %i\n",
+ err);
input_dev->dev.parent = NULL;
input_free_device(input_dev);
} else {
@@ -323,8 +323,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
/* check the packet status and length */
st = urb->iso_frame_desc[i].status;
if (st) {
- err("ISOC data error: [%d] len=%d, status=%d",
- i, len, st);
+ pr_err("ISOC data error: [%d] len=%d, status=%d\n",
+ i, len, st);
gspca_dev->last_packet_type = DISCARD_PACKET;
continue;
}
@@ -346,7 +346,7 @@ resubmit:
/* resubmit the URB */
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb() ret %d", st);
+ pr_err("usb_submit_urb() ret %d\n", st);
}
/*
@@ -400,7 +400,7 @@ resubmit:
if (gspca_dev->cam.bulk_nurbs != 0) {
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb() ret %d", st);
+ pr_err("usb_submit_urb() ret %d\n", st);
}
}
@@ -443,8 +443,11 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
} else {
switch (gspca_dev->last_packet_type) {
case DISCARD_PACKET:
- if (packet_type == LAST_PACKET)
+ if (packet_type == LAST_PACKET) {
gspca_dev->last_packet_type = packet_type;
+ gspca_dev->image = NULL;
+ gspca_dev->image_len = 0;
+ }
return;
case LAST_PACKET:
return;
@@ -461,7 +464,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
} else {
/* !! image is NULL only when last pkt is LAST or DISCARD
if (gspca_dev->image == NULL) {
- err("gspca_frame_add() image == NULL");
+ pr_err("gspca_frame_add() image == NULL\n");
return;
}
*/
@@ -494,19 +497,6 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
}
EXPORT_SYMBOL(gspca_frame_add);
-static int gspca_is_compressed(__u32 format)
-{
- switch (format) {
- case V4L2_PIX_FMT_MJPEG:
- case V4L2_PIX_FMT_JPEG:
- case V4L2_PIX_FMT_SPCA561:
- case V4L2_PIX_FMT_PAC207:
- case V4L2_PIX_FMT_MR97310A:
- return 1;
- }
- return 0;
-}
-
static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
enum v4l2_memory memory, unsigned int count)
{
@@ -522,7 +512,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
count = GSPCA_MAX_FRAMES - 1;
gspca_dev->frbuf = vmalloc_32(frsz * count);
if (!gspca_dev->frbuf) {
- err("frame alloc failed");
+ pr_err("frame alloc failed\n");
return -ENOMEM;
}
gspca_dev->capt_file = file;
@@ -594,7 +584,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
return 0;
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
if (ret < 0)
- err("set alt 0 err %d", ret);
+ pr_err("set alt 0 err %d\n", ret);
return ret;
}
@@ -637,53 +627,104 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
return NULL;
}
+/* compute the minimum bandwidth for the current transfer */
+static u32 which_bandwidth(struct gspca_dev *gspca_dev)
+{
+ u32 bandwidth;
+ int i;
+
+ i = gspca_dev->curr_mode;
+ bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
+
+ /* if the image is compressed, estimate the mean image size */
+ if (bandwidth < gspca_dev->cam.cam_mode[i].width *
+ gspca_dev->cam.cam_mode[i].height)
+ bandwidth /= 3;
+
+ /* estimate the frame rate */
+ if (gspca_dev->sd_desc->get_streamparm) {
+ struct v4l2_streamparm parm;
+
+ parm.parm.capture.timeperframe.denominator = 15;
+ gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
+ bandwidth *= parm.parm.capture.timeperframe.denominator;
+ } else {
+ bandwidth *= 15; /* 15 fps */
+ }
+
+ PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
+ return bandwidth;
+}
+
+/* endpoint table */
+#define MAX_ALT 16
+struct ep_tb_s {
+ u32 alt;
+ u32 bandwidth;
+};
+
/*
- * look for an input (isoc or bulk) endpoint
- *
- * The endpoint is defined by the subdriver.
- * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
- * This routine may be called many times when the bandwidth is too small
- * (the bandwidth is checked on urb submit).
+ * build the table of the endpoints
+ * and compute the minimum bandwidth for the image transfer
*/
-static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
+static int build_ep_tb(struct gspca_dev *gspca_dev,
+ struct usb_interface *intf,
+ int xfer,
+ struct ep_tb_s *ep_tb)
{
- struct usb_interface *intf;
struct usb_host_endpoint *ep;
- int xfer, i, ret;
+ int i, j, nbalt, psize, found;
+ u32 bandwidth, last_bw;
- intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
- ep = NULL;
- xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
- : USB_ENDPOINT_XFER_ISOC;
- i = gspca_dev->alt; /* previous alt setting */
- if (gspca_dev->cam.reverse_alts) {
- while (++i < gspca_dev->nbalt) {
- ep = alt_xfer(&intf->altsetting[i], xfer);
- if (ep)
- break;
- }
- } else {
- while (--i >= 0) {
- ep = alt_xfer(&intf->altsetting[i], xfer);
- if (ep)
- break;
- }
- }
- if (ep == NULL) {
- err("no transfer endpoint found");
- return NULL;
- }
- PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
- i, ep->desc.bEndpointAddress);
- gspca_dev->alt = i; /* memorize the current alt setting */
- if (gspca_dev->nbalt > 1) {
- ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
- if (ret < 0) {
- err("set alt %d err %d", i, ret);
- ep = NULL;
+ nbalt = intf->num_altsetting;
+ if (nbalt > MAX_ALT)
+ nbalt = MAX_ALT; /* fixme: should warn */
+
+ /* build the endpoint table */
+ i = 0;
+ last_bw = 0;
+ for (;;) {
+ ep_tb->bandwidth = 2000 * 2000 * 120;
+ found = 0;
+ for (j = 0; j < nbalt; j++) {
+ ep = alt_xfer(&intf->altsetting[j], xfer);
+ if (ep == NULL)
+ continue;
+ psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+ if (!gspca_dev->cam.bulk) /* isoc */
+ psize = (psize & 0x07ff) *
+ (1 + ((psize >> 11) & 3));
+ bandwidth = psize * ep->desc.bInterval * 1000;
+ if (gspca_dev->dev->speed == USB_SPEED_HIGH
+ || gspca_dev->dev->speed == USB_SPEED_SUPER)
+ bandwidth *= 8;
+ if (bandwidth <= last_bw)
+ continue;
+ if (bandwidth < ep_tb->bandwidth) {
+ ep_tb->bandwidth = bandwidth;
+ ep_tb->alt = j;
+ found = 1;
+ }
}
+ if (!found)
+ break;
+ PDEBUG(D_STREAM, "alt %d bandwidth %d",
+ ep_tb->alt, ep_tb->bandwidth);
+ last_bw = ep_tb->bandwidth;
+ i++;
+ ep_tb++;
+ }
+
+ /* get the requested bandwidth and start at the highest atlsetting */
+ bandwidth = which_bandwidth(gspca_dev);
+ ep_tb--;
+ while (i > 1) {
+ ep_tb--;
+ if (ep_tb->bandwidth < bandwidth)
+ break;
+ i--;
}
- return ep;
+ return i;
}
/*
@@ -728,7 +769,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
for (n = 0; n < nurbs; n++) {
urb = usb_alloc_urb(npkt, GFP_KERNEL);
if (!urb) {
- err("usb_alloc_urb failed");
+ pr_err("usb_alloc_urb failed\n");
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
@@ -738,7 +779,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
- err("usb_alloc_coherent failed");
+ pr_err("usb_alloc_coherent failed\n");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;
@@ -749,7 +790,10 @@ static int create_urbs(struct gspca_dev *gspca_dev,
ep->desc.bEndpointAddress);
urb->transfer_flags = URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP;
- urb->interval = ep->desc.bInterval;
+ if (gspca_dev->dev->speed == USB_SPEED_LOW)
+ urb->interval = ep->desc.bInterval;
+ else
+ urb->interval = 1 << (ep->desc.bInterval - 1);
urb->complete = isoc_irq;
urb->number_of_packets = npkt;
for (i = 0; i < npkt; i++) {
@@ -771,9 +815,11 @@ static int create_urbs(struct gspca_dev *gspca_dev,
*/
static int gspca_init_transfer(struct gspca_dev *gspca_dev)
{
+ struct usb_interface *intf;
struct usb_host_endpoint *ep;
struct urb *urb;
- int n, ret;
+ struct ep_tb_s ep_tb[MAX_ALT];
+ int n, ret, xfer, alt, alt_idx;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
@@ -791,30 +837,65 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
gspca_dev->usb_err = 0;
- /* set the higher alternate setting and
- * loop until urb submit succeeds */
- if (gspca_dev->cam.reverse_alts)
- gspca_dev->alt = 0;
- else
- gspca_dev->alt = gspca_dev->nbalt;
-
+ /* do the specific subdriver stuff before endpoint selection */
+ intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+ gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
if (gspca_dev->sd_desc->isoc_init) {
ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
if (ret < 0)
goto unlock;
}
+ xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+ : USB_ENDPOINT_XFER_ISOC;
- gspca_input_destroy_urb(gspca_dev);
- ep = get_ep(gspca_dev);
- if (ep == NULL) {
- ret = -EIO;
- goto out;
+ /* if the subdriver forced an altsetting, get the endpoint */
+ if (gspca_dev->alt != 0) {
+ gspca_dev->alt--; /* (previous version compatibility) */
+ ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+ if (ep == NULL) {
+ pr_err("bad altsetting %d\n", gspca_dev->alt);
+ ret = -EIO;
+ goto out;
+ }
+ ep_tb[0].alt = gspca_dev->alt;
+ alt_idx = 1;
+ } else {
+
+ /* else, compute the minimum bandwidth
+ * and build the endpoint table */
+ alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb);
+ if (alt_idx <= 0) {
+ pr_err("no transfer endpoint found\n");
+ ret = -EIO;
+ goto unlock;
+ }
}
+
+ /* set the highest alternate setting and
+ * loop until urb submit succeeds */
+ gspca_input_destroy_urb(gspca_dev);
+
+ gspca_dev->alt = ep_tb[--alt_idx].alt;
+ alt = -1;
for (;;) {
+ if (alt != gspca_dev->alt) {
+ alt = gspca_dev->alt;
+ if (gspca_dev->nbalt > 1) {
+ ret = usb_set_interface(gspca_dev->dev,
+ gspca_dev->iface,
+ alt);
+ if (ret < 0) {
+ if (ret == -ENOSPC)
+ goto retry; /*fixme: ugly*/
+ pr_err("set alt %d err %d\n", alt, ret);
+ goto out;
+ }
+ }
+ }
if (!gspca_dev->cam.no_urb_create) {
- PDEBUG(D_STREAM, "init transfer alt %d",
- gspca_dev->alt);
- ret = create_urbs(gspca_dev, ep);
+ PDEBUG(D_STREAM, "init transfer alt %d", alt);
+ ret = create_urbs(gspca_dev,
+ alt_xfer(&intf->altsetting[alt], xfer));
if (ret < 0) {
destroy_urbs(gspca_dev);
goto out;
@@ -848,29 +929,35 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
break;
}
if (ret >= 0)
- break;
+ break; /* transfer is started */
+
+ /* something when wrong
+ * stop the webcam and free the transfer resources */
gspca_stream_off(gspca_dev);
if (ret != -ENOSPC) {
- err("usb_submit_urb alt %d err %d",
- gspca_dev->alt, ret);
+ pr_err("usb_submit_urb alt %d err %d\n",
+ gspca_dev->alt, ret);
goto out;
}
/* the bandwidth is not wide enough
* negotiate or try a lower alternate setting */
+retry:
PDEBUG(D_ERR|D_STREAM,
- "bandwidth not wide enough - trying again");
+ "alt %d - bandwidth not wide enough - trying again",
+ alt);
msleep(20); /* wait for kill complete */
if (gspca_dev->sd_desc->isoc_nego) {
ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
if (ret < 0)
goto out;
} else {
- ep = get_ep(gspca_dev);
- if (ep == NULL) {
+ if (alt_idx <= 0) {
+ pr_err("no transfer endpoint found\n");
ret = -EIO;
goto out;
}
+ gspca_dev->alt = ep_tb[--alt_idx].alt;
}
}
out:
@@ -1041,7 +1128,9 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL; /* no more format */
fmtdesc->pixelformat = fmt_tb[index];
- if (gspca_is_compressed(fmt_tb[index]))
+ if (gspca_dev->cam.cam_mode[i].sizeimage <
+ gspca_dev->cam.cam_mode[i].width *
+ gspca_dev->cam.cam_mode[i].height)
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
@@ -1278,10 +1367,10 @@ static int vidioc_querycap(struct file *file, void *priv,
ret = -ENODEV;
goto out;
}
- strncpy((char *) cap->driver, gspca_dev->sd_desc->name,
+ strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
sizeof cap->driver);
if (gspca_dev->dev->product != NULL) {
- strncpy((char *) cap->card, gspca_dev->dev->product,
+ strlcpy((char *) cap->card, gspca_dev->dev->product,
sizeof cap->card);
} else {
snprintf((char *) cap->card, sizeof cap->card,
@@ -1291,7 +1380,6 @@ static int vidioc_querycap(struct file *file, void *priv,
}
usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
sizeof(cap->bus_info));
- cap->version = DRIVER_VERSION_NUMBER;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
| V4L2_CAP_READWRITE;
@@ -1460,7 +1548,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
return -EINVAL;
input->type = V4L2_INPUT_TYPE_CAMERA;
input->status = gspca_dev->cam.input_flags;
- strncpy(input->name, gspca_dev->sd_desc->name,
+ strlcpy(input->name, gspca_dev->sd_desc->name,
sizeof input->name);
return 0;
}
@@ -1609,7 +1697,7 @@ static int vidioc_streamoff(struct file *file, void *priv,
enum v4l2_buf_type buf_type)
{
struct gspca_dev *gspca_dev = priv;
- int ret;
+ int i, ret;
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1640,6 +1728,8 @@ static int vidioc_streamoff(struct file *file, void *priv,
wake_up_interruptible(&gspca_dev->wq);
/* empty the transfer queues */
+ for (i = 0; i < gspca_dev->nframes; i++)
+ gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
atomic_set(&gspca_dev->fr_q, 0);
atomic_set(&gspca_dev->fr_i, 0);
gspca_dev->fr_o = 0;
@@ -2193,19 +2283,20 @@ int gspca_dev_probe2(struct usb_interface *intf,
struct usb_device *dev = interface_to_usbdev(intf);
int ret;
- PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
+ pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
+ sd_desc->name, id->idVendor, id->idProduct);
/* create the device */
if (dev_size < sizeof *gspca_dev)
dev_size = sizeof *gspca_dev;
gspca_dev = kzalloc(dev_size, GFP_KERNEL);
if (!gspca_dev) {
- err("couldn't kzalloc gspca struct");
+ pr_err("couldn't kzalloc gspca struct\n");
return -ENOMEM;
}
gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
if (!gspca_dev->usb_buf) {
- err("out of memory");
+ pr_err("out of memory\n");
ret = -ENOMEM;
goto out;
}
@@ -2262,7 +2353,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
VFL_TYPE_GRABBER,
-1);
if (ret < 0) {
- err("video_register_device err %d", ret);
+ pr_err("video_register_device err %d\n", ret);
goto out;
}
@@ -2294,8 +2385,8 @@ int gspca_dev_probe(struct usb_interface *intf,
/* we don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1) {
- err("%04x:%04x too many config",
- id->idVendor, id->idProduct);
+ pr_err("%04x:%04x too many config\n",
+ id->idVendor, id->idProduct);
return -ENODEV;
}
@@ -2478,10 +2569,7 @@ EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
/* -- module insert / remove -- */
static int __init gspca_init(void)
{
- info("v%d.%d.%d registered",
- (DRIVER_VERSION_NUMBER >> 16) & 0xff,
- (DRIVER_VERSION_NUMBER >> 8) & 0xff,
- DRIVER_VERSION_NUMBER & 0xff);
+ pr_info("v" GSPCA_VERSION " registered\n");
return 0;
}
static void __exit gspca_exit(void)
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 49e2fcb..e444f16 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -14,11 +14,12 @@
#ifdef GSPCA_DEBUG
/* GSPCA our debug messages */
extern int gspca_debug;
-#define PDEBUG(level, fmt, args...) \
- do {\
- if (gspca_debug & (level)) \
- printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
- } while (0)
+#define PDEBUG(level, fmt, ...) \
+do { \
+ if (gspca_debug & (level)) \
+ pr_info(fmt, ##__VA_ARGS__); \
+} while (0)
+
#define D_ERR 0x01
#define D_PROBE 0x02
#define D_CONF 0x04
@@ -29,17 +30,8 @@ extern int gspca_debug;
#define D_USBO 0x00
#define D_V4L2 0x0100
#else
-#define PDEBUG(level, fmt, args...)
+#define PDEBUG(level, fmt, ...)
#endif
-#undef err
-#define err(fmt, args...) \
- printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args)
-#undef info
-#define info(fmt, args...) \
- printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args)
-#undef warn
-#define warn(fmt, args...) \
- printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args)
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
/* image transfers */
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c
index 1bd9c4b..8e3dabe 100644
--- a/drivers/media/video/gspca/jeilinj.c
+++ b/drivers/media/video/gspca/jeilinj.c
@@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "jeilinj"
#include <linux/slab.h>
@@ -113,8 +115,8 @@ static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
usb_sndbulkpipe(gspca_dev->dev, 3),
gspca_dev->usb_buf, 2, NULL, 500);
if (retval < 0) {
- err("command write [%02x] error %d",
- gspca_dev->usb_buf[0], retval);
+ pr_err("command write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], retval);
gspca_dev->usb_err = retval;
}
}
@@ -131,8 +133,8 @@ static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
gspca_dev->usb_buf, 1, NULL, 500);
response = gspca_dev->usb_buf[0];
if (retval < 0) {
- err("read command [%02x] error %d",
- gspca_dev->usb_buf[0], retval);
+ pr_err("read command [%02x] error %d\n",
+ gspca_dev->usb_buf[0], retval);
gspca_dev->usb_err = retval;
}
}
@@ -403,13 +405,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
dev->type = id->driver_info;
gspca_dev->cam.ctrls = dev->ctrls;
dev->quality = QUALITY_DEF;
- dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
- dev->ctrls[RED].def = RED_BALANCE_DEF;
- dev->ctrls[GREEN].def = GREEN_BALANCE_DEF;
- dev->ctrls[BLUE].def = BLUE_BALANCE_DEF;
- PDEBUG(D_PROBE,
- "JEILINJ camera detected"
- " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+
cam->cam_mode = jlj_mode;
cam->nmodes = ARRAY_SIZE(jlj_mode);
cam->bulk = 1;
@@ -422,7 +418,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
{
int i;
u8 *buf;
- u8 stop_commands[][2] = {
+ static u8 stop_commands[][2] = {
{0x71, 0x00},
{0x70, 0x09},
{0x71, 0x80},
diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c
index 26fc206..acaef66 100644
--- a/drivers/media/video/gspca/kinect.c
+++ b/drivers/media/video/gspca/kinect.c
@@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "kinect"
#include "gspca.h"
@@ -34,11 +36,6 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
MODULE_LICENSE("GPL");
-#ifdef GSPCA_DEBUG
-int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
- D_USBI | D_USBO | D_V4L2;
-#endif
-
struct pkt_hdr {
uint8_t magic[2];
uint8_t pad;
@@ -141,7 +138,7 @@ static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
struct cam_hdr *rhdr = (void *)ibuf;
if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
- err("send_cmd: Invalid command length (0x%x)", cmd_len);
+ pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
return -1;
}
@@ -157,7 +154,7 @@ static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
sd->cam_tag, cmd_len, res);
if (res < 0) {
- err("send_cmd: Output control transfer failed (%d)", res);
+ pr_err("send_cmd: Output control transfer failed (%d)\n", res);
return res;
}
@@ -166,33 +163,35 @@ static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
} while (actual_len == 0);
PDEBUG(D_USBO, "Control reply: %d", res);
if (actual_len < sizeof(*rhdr)) {
- err("send_cmd: Input control transfer failed (%d)", res);
+ pr_err("send_cmd: Input control transfer failed (%d)\n", res);
return res;
}
actual_len -= sizeof(*rhdr);
if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
- err("send_cmd: Bad magic %02x %02x", rhdr->magic[0],
- rhdr->magic[1]);
+ pr_err("send_cmd: Bad magic %02x %02x\n",
+ rhdr->magic[0], rhdr->magic[1]);
return -1;
}
if (rhdr->cmd != chdr->cmd) {
- err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd);
+ pr_err("send_cmd: Bad cmd %02x != %02x\n",
+ rhdr->cmd, chdr->cmd);
return -1;
}
if (rhdr->tag != chdr->tag) {
- err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag);
+ pr_err("send_cmd: Bad tag %04x != %04x\n",
+ rhdr->tag, chdr->tag);
return -1;
}
if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
- err("send_cmd: Bad len %04x != %04x",
- cpu_to_le16(rhdr->len), (int)(actual_len/2));
+ pr_err("send_cmd: Bad len %04x != %04x\n",
+ cpu_to_le16(rhdr->len), (int)(actual_len/2));
return -1;
}
if (actual_len > reply_len) {
- warn("send_cmd: Data buffer is %d bytes long, but got %d bytes",
- reply_len, actual_len);
+ pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
+ reply_len, actual_len);
memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
} else {
memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
@@ -218,8 +217,8 @@ static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
if (res < 0)
return res;
if (res != 2) {
- warn("send_cmd returned %d [%04x %04x], 0000 expected",
- res, reply[0], reply[1]);
+ pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
+ res, reply[0], reply[1]);
}
return 0;
}
@@ -353,8 +352,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
return;
if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
- warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag,
- hdr->magic[0], hdr->magic[1]);
+ pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
+ sd->stream_flag, hdr->magic[0], hdr->magic[1]);
return;
}
@@ -368,7 +367,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
else
- warn("Packet type not recognized...");
+ pr_warn("Packet type not recognized...\n");
}
/* sub-driver description */
@@ -391,6 +390,7 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */
static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x045e, 0x02ae)},
+ {USB_DEVICE(0x045e, 0x02bf)},
{}
};
diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c
index 5964691..f3f7fe0 100644
--- a/drivers/media/video/gspca/konica.c
+++ b/drivers/media/video/gspca/konica.c
@@ -28,6 +28,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "konica"
#include <linux/input.h>
@@ -200,7 +202,7 @@ static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
0,
1000);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -221,7 +223,7 @@ static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index)
2,
1000);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -284,7 +286,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
return -EIO;
}
@@ -315,7 +317,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
if (!urb) {
- err("usb_alloc_urb failed");
+ pr_err("usb_alloc_urb failed\n");
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
@@ -324,7 +326,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
GFP_KERNEL,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
- err("usb_buffer_alloc failed");
+ pr_err("usb_buffer_alloc failed\n");
return -ENOMEM;
}
@@ -386,7 +388,7 @@ static void sd_isoc_irq(struct urb *urb)
PDEBUG(D_ERR, "urb status: %d", urb->status);
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("resubmit urb error %d", st);
+ pr_err("resubmit urb error %d\n", st);
return;
}
@@ -477,7 +479,7 @@ resubmit:
}
st = usb_submit_urb(status_urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb(status_urb) ret %d", st);
+ pr_err("usb_submit_urb(status_urb) ret %d\n", st);
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
index bf7a19a..7f52961 100644
--- a/drivers/media/video/gspca/m5602/Makefile
+++ b/drivers/media/video/gspca/m5602/Makefile
@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \
m5602_s5k83a.o \
m5602_s5k4aa.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index a7722b1..67533e5 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_ov9650.h"
#include "m5602_ov7660.h"
#include "m5602_mt9m111.h"
@@ -192,10 +194,9 @@ static void m5602_dump_bridge(struct sd *sd)
for (i = 0; i < 0x80; i++) {
unsigned char val = 0;
m5602_read_bridge(sd, i, &val);
- info("ALi m5602 address 0x%x contains 0x%x", i, val);
+ pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
}
- info("Warning: The ALi m5602 webcam probably won't work "
- "until it's power cycled");
+ pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
}
static int m5602_probe_sensor(struct sd *sd)
@@ -231,7 +232,7 @@ static int m5602_probe_sensor(struct sd *sd)
return 0;
/* More sensor probe function goes here */
- info("Failed to find a sensor");
+ pr_info("Failed to find a sensor\n");
sd->sensor = NULL;
return -ENODEV;
}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
index 0d605a5..6268aa2 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_mt9m111.h"
static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
@@ -163,7 +165,7 @@ int mt9m111_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == MT9M111_SENSOR) {
- info("Forcing a %s sensor", mt9m111.name);
+ pr_info("Forcing a %s sensor\n", mt9m111.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -191,7 +193,7 @@ int mt9m111_probe(struct sd *sd)
return -ENODEV;
if ((data[0] == 0x14) && (data[1] == 0x3a)) {
- info("Detected a mt9m111 sensor");
+ pr_info("Detected a mt9m111 sensor\n");
goto sensor_found;
}
@@ -612,34 +614,34 @@ static void mt9m111_dump_registers(struct sd *sd)
{
u8 address, value[2] = {0x00, 0x00};
- info("Dumping the mt9m111 register state");
+ pr_info("Dumping the mt9m111 register state\n");
- info("Dumping the mt9m111 sensor core registers");
+ pr_info("Dumping the mt9m111 sensor core registers\n");
value[1] = MT9M111_SENSOR_CORE;
m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
m5602_read_sensor(sd, address, value, 2);
- info("register 0x%x contains 0x%x%x",
- address, value[0], value[1]);
+ pr_info("register 0x%x contains 0x%x%x\n",
+ address, value[0], value[1]);
}
- info("Dumping the mt9m111 color pipeline registers");
+ pr_info("Dumping the mt9m111 color pipeline registers\n");
value[1] = MT9M111_COLORPIPE;
m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
m5602_read_sensor(sd, address, value, 2);
- info("register 0x%x contains 0x%x%x",
- address, value[0], value[1]);
+ pr_info("register 0x%x contains 0x%x%x\n",
+ address, value[0], value[1]);
}
- info("Dumping the mt9m111 camera control registers");
+ pr_info("Dumping the mt9m111 camera control registers\n");
value[1] = MT9M111_CAMERA_CONTROL;
m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
m5602_read_sensor(sd, address, value, 2);
- info("register 0x%x contains 0x%x%x",
- address, value[0], value[1]);
+ pr_info("register 0x%x contains 0x%x%x\n",
+ address, value[0], value[1]);
}
- info("mt9m111 register state dump complete");
+ pr_info("mt9m111 register state dump complete\n");
}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c
index b12f604..9a14835 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov7660.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_ov7660.h"
static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -149,7 +151,7 @@ int ov7660_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == OV7660_SENSOR) {
- info("Forcing an %s sensor", ov7660.name);
+ pr_info("Forcing an %s sensor\n", ov7660.name);
goto sensor_found;
}
/* If we want to force another sensor,
@@ -180,10 +182,10 @@ int ov7660_probe(struct sd *sd)
if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
return -ENODEV;
- info("Sensor reported 0x%x%x", prod_id, ver_id);
+ pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
if ((prod_id == 0x76) && (ver_id == 0x60)) {
- info("Detected a ov7660 sensor");
+ pr_info("Detected a ov7660 sensor\n");
goto sensor_found;
}
return -ENODEV;
@@ -457,17 +459,16 @@ static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
static void ov7660_dump_registers(struct sd *sd)
{
int address;
- info("Dumping the ov7660 register state");
+ pr_info("Dumping the ov7660 register state\n");
for (address = 0; address < 0xa9; address++) {
u8 value;
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n", address, value);
}
- info("ov7660 register state dump complete");
+ pr_info("ov7660 register state dump complete\n");
- info("Probing for which registers that are read/write");
+ pr_info("Probing for which registers that are read/write\n");
for (address = 0; address < 0xff; address++) {
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
@@ -477,9 +478,9 @@ static void ov7660_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n", address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n", address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index 703d486..2114a8b 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_ov9650.h"
static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
@@ -299,7 +301,7 @@ int ov9650_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == OV9650_SENSOR) {
- info("Forcing an %s sensor", ov9650.name);
+ pr_info("Forcing an %s sensor\n", ov9650.name);
goto sensor_found;
}
/* If we want to force another sensor,
@@ -330,7 +332,7 @@ int ov9650_probe(struct sd *sd)
return -ENODEV;
if ((prod_id == 0x96) && (ver_id == 0x52)) {
- info("Detected an ov9650 sensor");
+ pr_info("Detected an ov9650 sensor\n");
goto sensor_found;
}
return -ENODEV;
@@ -850,17 +852,16 @@ static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
static void ov9650_dump_registers(struct sd *sd)
{
int address;
- info("Dumping the ov9650 register state");
+ pr_info("Dumping the ov9650 register state\n");
for (address = 0; address < 0xa9; address++) {
u8 value;
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n", address, value);
}
- info("ov9650 register state dump complete");
+ pr_info("ov9650 register state dump complete\n");
- info("Probing for which registers that are read/write");
+ pr_info("Probing for which registers that are read/write\n");
for (address = 0; address < 0xff; address++) {
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
@@ -870,9 +871,9 @@ static void ov9650_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n", address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n", address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
index 1febd34..b877169 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.c
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_po1030.h"
static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -197,7 +199,7 @@ int po1030_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == PO1030_SENSOR) {
- info("Forcing a %s sensor", po1030.name);
+ pr_info("Forcing a %s sensor\n", po1030.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -221,7 +223,7 @@ int po1030_probe(struct sd *sd)
return -ENODEV;
if (dev_id_h == 0x30) {
- info("Detected a po1030 sensor");
+ pr_info("Detected a po1030 sensor\n");
goto sensor_found;
}
return -ENODEV;
@@ -267,7 +269,7 @@ int po1030_init(struct sd *sd)
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -733,16 +735,15 @@ static void po1030_dump_registers(struct sd *sd)
int address;
u8 value = 0;
- info("Dumping the po1030 sensor core registers");
+ pr_info("Dumping the po1030 sensor core registers\n");
for (address = 0; address < 0x7f; address++) {
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n", address, value);
}
- info("po1030 register state dump complete");
+ pr_info("po1030 register state dump complete\n");
- info("Probing for which registers that are read/write");
+ pr_info("Probing for which registers that are read/write\n");
for (address = 0; address < 0xff; address++) {
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
@@ -752,9 +753,9 @@ static void po1030_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n", address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n", address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index d27280b..cc8ec3f 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_s5k4aa.h"
static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -240,7 +242,7 @@ int s5k4aa_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == S5K4AA_SENSOR) {
- info("Forcing a %s sensor", s5k4aa.name);
+ pr_info("Forcing a %s sensor\n", s5k4aa.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -276,7 +278,7 @@ int s5k4aa_probe(struct sd *sd)
data, 2);
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -292,7 +294,7 @@ int s5k4aa_probe(struct sd *sd)
if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
return -ENODEV;
else
- info("Detected a s5k4aa sensor");
+ pr_info("Detected a s5k4aa sensor\n");
sensor_found:
sensor_settings = kmalloc(
@@ -347,7 +349,7 @@ int s5k4aa_start(struct sd *sd)
break;
default:
- err("Invalid stream command, exiting init");
+ pr_err("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -383,7 +385,7 @@ int s5k4aa_start(struct sd *sd)
break;
default:
- err("Invalid stream command, exiting init");
+ pr_err("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -447,7 +449,7 @@ int s5k4aa_init(struct sd *sd)
init_s5k4aa[i][1], data, 2);
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -686,20 +688,21 @@ static void s5k4aa_dump_registers(struct sd *sd)
m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
- info("Dumping the s5k4aa register state for page 0x%x", page);
+ pr_info("Dumping the s5k4aa register state for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 value = 0;
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n",
+ address, value);
}
}
- info("s5k4aa register state dump complete");
+ pr_info("s5k4aa register state dump complete\n");
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
- info("Probing for which registers that are "
- "read/write for page 0x%x", page);
+ pr_info("Probing for which registers that are read/write for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 old_value, ctrl_value, test_value = 0xff;
@@ -708,14 +711,16 @@ static void s5k4aa_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value)
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n",
+ address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n",
+ address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
}
}
- info("Read/write register probing complete");
+ pr_info("Read/write register probing complete\n");
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index fbd9154..1de743a 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kthread.h>
#include "m5602_s5k83a.h"
@@ -135,7 +137,7 @@ int s5k83a_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == S5K83A_SENSOR) {
- info("Forcing a %s sensor", s5k83a.name);
+ pr_info("Forcing a %s sensor\n", s5k83a.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -168,7 +170,7 @@ int s5k83a_probe(struct sd *sd)
if ((prod_id == 0xff) || (ver_id == 0xff))
return -ENODEV;
else
- info("Detected a s5k83a sensor");
+ pr_info("Detected a s5k83a sensor\n");
sensor_found:
sens_priv = kmalloc(
@@ -227,7 +229,7 @@ int s5k83a_init(struct sd *sd)
init_s5k83a[i][1], data, 2);
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -273,7 +275,7 @@ static int rotation_thread_function(void *data)
s5k83a_get_rotation(sd, &reg);
if (previous_rotation != reg) {
previous_rotation = reg;
- info("Camera was flipped");
+ pr_info("Camera was flipped\n");
s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
@@ -566,20 +568,20 @@ static void s5k83a_dump_registers(struct sd *sd)
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
- info("Dumping the s5k83a register state for page 0x%x", page);
+ pr_info("Dumping the s5k83a register state for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 val = 0;
m5602_read_sensor(sd, address, &val, 1);
- info("register 0x%x contains 0x%x",
- address, val);
+ pr_info("register 0x%x contains 0x%x\n", address, val);
}
}
- info("s5k83a register state dump complete");
+ pr_info("s5k83a register state dump complete\n");
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
- info("Probing for which registers that are read/write "
- "for page 0x%x", page);
+ pr_info("Probing for which registers that are read/write for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 old_val, ctrl_val, test_val = 0xff;
@@ -588,14 +590,16 @@ static void s5k83a_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_val, 1);
if (ctrl_val == test_val)
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n",
+ address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n",
+ address);
/* Restore original val */
m5602_write_sensor(sd, address, &old_val, 1);
}
}
- info("Read/write register probing complete");
+ pr_info("Read/write register probing complete\n");
m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
}
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index 0196209..ef45fa5 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "mars"
#include "gspca.h"
@@ -178,8 +180,8 @@ static void reg_w(struct gspca_dev *gspca_dev,
&alen,
500); /* timeout in milliseconds */
if (ret < 0) {
- err("reg write [%02x] error %d",
- gspca_dev->usb_buf[0], ret);
+ pr_err("reg write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], ret);
gspca_dev->usb_err = ret;
}
}
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
index 97e5079..473e813 100644
--- a/drivers/media/video/gspca/mr97310a.c
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -40,6 +40,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "mr97310a"
#include "gspca.h"
@@ -267,7 +269,7 @@ static int mr_write(struct gspca_dev *gspca_dev, int len)
usb_sndbulkpipe(gspca_dev->dev, 4),
gspca_dev->usb_buf, len, NULL, 500);
if (rc < 0)
- err("reg write [%02x] error %d",
+ pr_err("reg write [%02x] error %d\n",
gspca_dev->usb_buf[0], rc);
return rc;
}
@@ -281,7 +283,7 @@ static int mr_read(struct gspca_dev *gspca_dev, int len)
usb_rcvbulkpipe(gspca_dev->dev, 3),
gspca_dev->usb_buf, len, NULL, 500);
if (rc < 0)
- err("reg read [%02x] error %d",
+ pr_err("reg read [%02x] error %d\n",
gspca_dev->usb_buf[0], rc);
return rc;
}
@@ -540,7 +542,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->sensor_type = 1;
break;
default:
- err("Unknown CIF Sensor id : %02x",
+ pr_err("Unknown CIF Sensor id : %02x\n",
gspca_dev->usb_buf[1]);
return -ENODEV;
}
@@ -575,10 +577,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->sensor_type = 2;
} else if ((gspca_dev->usb_buf[0] != 0x03) &&
(gspca_dev->usb_buf[0] != 0x04)) {
- err("Unknown VGA Sensor id Byte 0: %02x",
- gspca_dev->usb_buf[0]);
- err("Defaults assumed, may not work");
- err("Please report this");
+ pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
+ gspca_dev->usb_buf[0]);
+ pr_err("Defaults assumed, may not work\n");
+ pr_err("Please report this\n");
}
/* Sakar Digital color needs to be adjusted. */
if ((gspca_dev->usb_buf[0] == 0x03) &&
@@ -595,10 +597,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* Nothing to do here. */
break;
default:
- err("Unknown VGA Sensor id Byte 1: %02x",
- gspca_dev->usb_buf[1]);
- err("Defaults assumed, may not work");
- err("Please report this");
+ pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
+ gspca_dev->usb_buf[1]);
+ pr_err("Defaults assumed, may not work\n");
+ pr_err("Please report this\n");
}
}
PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c
index 8e754fd..7681814 100644
--- a/drivers/media/video/gspca/nw80x.c
+++ b/drivers/media/video/gspca/nw80x.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "nw80x"
#include "gspca.h"
@@ -1571,7 +1573,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
len,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1592,7 +1594,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
0x00, index,
gspca_dev->usb_buf, len, 500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
return;
}
@@ -1802,7 +1804,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
}
if (webcam_chip[sd->webcam] != sd->bridge) {
- err("Bad webcam type %d for NW80%d", sd->webcam, sd->bridge);
+ pr_err("Bad webcam type %d for NW80%d\n",
+ sd->webcam, sd->bridge);
gspca_dev->usb_err = -ENODEV;
return gspca_dev->usb_err;
}
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 057e287..6a01b35 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -36,6 +36,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "ov519"
#include <linux/input.h>
@@ -134,6 +137,7 @@ enum sensors {
SEN_OV7670,
SEN_OV76BE,
SEN_OV8610,
+ SEN_OV9600,
};
/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
@@ -340,6 +344,10 @@ static const unsigned ctrl_dis[] = {
(1 << EXPOSURE) |
(1 << AUTOGAIN) |
(1 << FREQ),
+[SEN_OV9600] = ((1 << NCTRL) - 1) /* no control */
+ ^ ((1 << EXPOSURE) /* but exposure */
+ | (1 << AUTOGAIN)), /* and autogain */
+
};
static const struct v4l2_pix_format ov519_vga_mode[] = {
@@ -525,6 +533,17 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
};
+static const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
+ {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1},
+ {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 1280,
+ .sizeimage = 1280 * 1024,
+ .colorspace = V4L2_COLORSPACE_SRGB},
+};
/* Registers common to OV511 / OV518 */
#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */
@@ -1807,6 +1826,22 @@ static const struct ov_i2c_regvals norm_7660[] = {
| OV7670_COM8_AEC},
{0xa1, 0xc8}
};
+static const struct ov_i2c_regvals norm_9600[] = {
+ {0x12, 0x80},
+ {0x0c, 0x28},
+ {0x11, 0x80},
+ {0x13, 0xb5},
+ {0x14, 0x3e},
+ {0x1b, 0x04},
+ {0x24, 0xb0},
+ {0x25, 0x90},
+ {0x26, 0x94},
+ {0x35, 0x90},
+ {0x37, 0x07},
+ {0x38, 0x08},
+ {0x01, 0x8e},
+ {0x02, 0x85}
+};
/* 7670. Defaults taken from OmniVision provided data,
* as provided by Jonathan Corbet of OLPC */
@@ -2139,7 +2174,7 @@ static void reg_w(struct sd *sd, u16 index, u16 value)
sd->gspca_dev.usb_buf, 1, 500);
leave:
if (ret < 0) {
- err("reg_w %02x failed %d", index, ret);
+ pr_err("reg_w %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
return;
}
@@ -2178,7 +2213,7 @@ static int reg_r(struct sd *sd, u16 index)
PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
req, index, ret);
} else {
- err("reg_r %02x failed %d", index, ret);
+ pr_err("reg_r %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2203,7 +2238,7 @@ static int reg_r8(struct sd *sd,
if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0];
} else {
- err("reg_r8 %02x failed %d", index, ret);
+ pr_err("reg_r8 %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2256,7 +2291,7 @@ static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
0, index,
sd->gspca_dev.usb_buf, n, 500);
if (ret < 0) {
- err("reg_w32 %02x failed %d", index, ret);
+ pr_err("reg_w32 %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
}
}
@@ -2400,9 +2435,12 @@ static int ov518_i2c_r(struct sd *sd, u8 reg)
/* Initiate 2-byte write cycle */
reg_w(sd, R518_I2C_CTL, 0x03);
+ reg_r8(sd, R518_I2C_CTL);
/* Initiate 2-byte read cycle */
reg_w(sd, R518_I2C_CTL, 0x05);
+ reg_r8(sd, R518_I2C_CTL);
+
value = reg_r(sd, R51x_I2C_DATA);
PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
return value;
@@ -2422,7 +2460,7 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
(u16) value, (u16) reg, NULL, 0, 500);
if (ret < 0) {
- err("ovfx2_i2c_w %02x failed %d", reg, ret);
+ pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2446,7 +2484,7 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg)
ret = sd->gspca_dev.usb_buf[0];
PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
} else {
- err("ovfx2_i2c_r %02x failed %d", reg, ret);
+ pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2686,13 +2724,13 @@ static void write_i2c_regvals(struct sd *sd,
*
***************************************************************************/
-/* This initializes the OV2x10 / OV3610 / OV3620 */
+/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
static void ov_hires_configure(struct sd *sd)
{
int high, low;
if (sd->bridge != BRIDGE_OVFX2) {
- err("error hires sensors only supported with ovfx2");
+ pr_err("error hires sensors only supported with ovfx2\n");
return;
}
@@ -2702,19 +2740,32 @@ static void ov_hires_configure(struct sd *sd)
high = i2c_r(sd, 0x0a);
low = i2c_r(sd, 0x0b);
/* info("%x, %x", high, low); */
- if (high == 0x96 && low == 0x40) {
- PDEBUG(D_PROBE, "Sensor is an OV2610");
- sd->sensor = SEN_OV2610;
- } else if (high == 0x96 && low == 0x41) {
- PDEBUG(D_PROBE, "Sensor is an OV2610AE");
- sd->sensor = SEN_OV2610AE;
- } else if (high == 0x36 && (low & 0x0f) == 0x00) {
- PDEBUG(D_PROBE, "Sensor is an OV3610");
- sd->sensor = SEN_OV3610;
- } else {
- err("Error unknown sensor type: %02x%02x",
- high, low);
+ switch (high) {
+ case 0x96:
+ switch (low) {
+ case 0x40:
+ PDEBUG(D_PROBE, "Sensor is a OV2610");
+ sd->sensor = SEN_OV2610;
+ return;
+ case 0x41:
+ PDEBUG(D_PROBE, "Sensor is a OV2610AE");
+ sd->sensor = SEN_OV2610AE;
+ return;
+ case 0xb1:
+ PDEBUG(D_PROBE, "Sensor is a OV9600");
+ sd->sensor = SEN_OV9600;
+ return;
+ }
+ break;
+ case 0x36:
+ if ((low & 0x0f) == 0x00) {
+ PDEBUG(D_PROBE, "Sensor is a OV3610");
+ sd->sensor = SEN_OV3610;
+ return;
+ }
+ break;
}
+ pr_err("Error unknown sensor type: %02x%02x\n", high, low);
}
/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
@@ -2735,7 +2786,7 @@ static void ov8xx0_configure(struct sd *sd)
if ((rc & 3) == 1)
sd->sensor = SEN_OV8610;
else
- err("Unknown image sensor version: %d", rc & 3);
+ pr_err("Unknown image sensor version: %d\n", rc & 3);
}
/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
@@ -2792,8 +2843,8 @@ static void ov7xx0_configure(struct sd *sd)
if (high == 0x76) {
switch (low) {
case 0x30:
- err("Sensor is an OV7630/OV7635");
- err("7630 is not supported by this driver");
+ pr_err("Sensor is an OV7630/OV7635\n");
+ pr_err("7630 is not supported by this driver\n");
return;
case 0x40:
PDEBUG(D_PROBE, "Sensor is an OV7645");
@@ -2810,7 +2861,6 @@ static void ov7xx0_configure(struct sd *sd)
case 0x60:
PDEBUG(D_PROBE, "Sensor is a OV7660");
sd->sensor = SEN_OV7660;
- sd->invert_led = 0;
break;
default:
PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
@@ -2821,7 +2871,7 @@ static void ov7xx0_configure(struct sd *sd)
sd->sensor = SEN_OV7620;
}
} else {
- err("Unknown image sensor version: %d", rc & 3);
+ pr_err("Unknown image sensor version: %d\n", rc & 3);
}
}
@@ -2844,8 +2894,7 @@ static void ov6xx0_configure(struct sd *sd)
switch (rc) {
case 0x00:
sd->sensor = SEN_OV6630;
- warn("WARNING: Sensor is an OV66308. Your camera may have");
- warn("been misdetected in previous driver versions.");
+ pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
break;
case 0x01:
sd->sensor = SEN_OV6620;
@@ -2861,11 +2910,10 @@ static void ov6xx0_configure(struct sd *sd)
break;
case 0x90:
sd->sensor = SEN_OV6630;
- warn("WARNING: Sensor is an OV66307. Your camera may have");
- warn("been misdetected in previous driver versions.");
+ pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
break;
default:
- err("FATAL: Unknown sensor version: 0x%02x", rc);
+ pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
return;
}
@@ -3289,7 +3337,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
case BRIDGE_OV519:
cam->cam_mode = ov519_vga_mode;
cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
- sd->invert_led = !sd->invert_led;
break;
case BRIDGE_OVFX2:
cam->cam_mode = ov519_vga_mode;
@@ -3359,7 +3406,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
ov_hires_configure(sd);
} else {
- err("Can't determine sensor slave IDs");
+ pr_err("Can't determine sensor slave IDs\n");
goto error;
}
@@ -3400,6 +3447,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
cam->cam_mode = ovfx2_ov3610_mode;
cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
break;
+ case SEN_OV9600:
+ cam->cam_mode = ovfx2_ov9600_mode;
+ cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
+ break;
default:
if (sd->sif) {
cam->cam_mode = ov519_sif_mode;
@@ -3497,6 +3548,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SEN_OV8610:
write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
break;
+ case SEN_OV9600:
+ write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
+
+ /* enable autoexpo */
+/* i2c_w_mask(sd, 0x13, 0x05, 0x05); */
+ break;
}
return gspca_dev->usb_err;
error:
@@ -3534,7 +3591,7 @@ static void ov511_mode_init_regs(struct sd *sd)
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
sd->gspca_dev.usb_err = -EIO;
return;
}
@@ -3657,7 +3714,7 @@ static void ov518_mode_init_regs(struct sd *sd)
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
sd->gspca_dev.usb_err = -EIO;
return;
}
@@ -4085,6 +4142,33 @@ static void mode_init_ov_sensor_regs(struct sd *sd)
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
break;
+ case SEN_OV9600: {
+ const struct ov_i2c_regvals *vals;
+ static const struct ov_i2c_regvals sxga_15[] = {
+ {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
+ };
+ static const struct ov_i2c_regvals sxga_7_5[] = {
+ {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
+ };
+ static const struct ov_i2c_regvals vga_30[] = {
+ {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
+ };
+ static const struct ov_i2c_regvals vga_15[] = {
+ {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
+ };
+
+ /* frame rates:
+ * 15fps / 7.5 fps for 1280x1024
+ * 30fps / 15fps for 640x480
+ */
+ i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
+ if (qvga)
+ vals = sd->frame_rate < 30 ? vga_15 : vga_30;
+ else
+ vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
+ write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
+ return;
+ }
default:
return;
}
@@ -4120,6 +4204,7 @@ static void set_ov_sensor_window(struct sd *sd)
case SEN_OV2610AE:
case SEN_OV3610:
case SEN_OV7670:
+ case SEN_OV9600:
mode_init_ov_sensor_regs(sd);
return;
case SEN_OV7660:
@@ -4919,23 +5004,24 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */
static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
- {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x041e, 0x4052),
+ .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
{USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
- {USB_DEVICE(0x041e, 0x4064),
- .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+ {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
- {USB_DEVICE(0x041e, 0x4068),
+ {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x045e, 0x028c),
.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
- {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
- {USB_DEVICE(0x054c, 0x0155),
- .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+ {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
{USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
- {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
- {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x05a9, 0x0519),
+ .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+ {USB_DEVICE(0x05a9, 0x0530),
+ .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
{USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
{USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
index 0c6369b..76907ec 100644
--- a/drivers/media/video/gspca/ov534.c
+++ b/drivers/media/video/gspca/ov534.c
@@ -28,6 +28,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "ov534"
#include "gspca.h"
@@ -775,7 +777,7 @@ static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
if (ret < 0) {
- err("write failed %d", ret);
+ pr_err("write failed %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -794,7 +796,7 @@ static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("read failed %d", ret);
+ pr_err("read failed %d\n", ret);
gspca_dev->usb_err = ret;
}
return gspca_dev->usb_buf[0];
@@ -858,7 +860,7 @@ static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
if (!sccb_check_status(gspca_dev)) {
- err("sccb_reg_write failed");
+ pr_err("sccb_reg_write failed\n");
gspca_dev->usb_err = -EIO;
}
}
@@ -868,11 +870,11 @@ static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_reg_read failed 1");
+ pr_err("sccb_reg_read failed 1\n");
ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_reg_read failed 2");
+ pr_err("sccb_reg_read failed 2\n");
return ov534_reg_read(gspca_dev, OV534_REG_READ);
}
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
index aaf5428..b3b1ea6 100644
--- a/drivers/media/video/gspca/ov534_9.c
+++ b/drivers/media/video/gspca/ov534_9.c
@@ -1,7 +1,7 @@
/*
- * ov534-ov965x gspca driver
+ * ov534-ov9xxx gspca driver
*
- * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
+ * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
* Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
* Copyright (C) 2008 Jim Paris <jim@jtan.com>
*
@@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "ov534_9"
#include "gspca.h"
@@ -45,39 +47,44 @@ MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
MODULE_LICENSE("GPL");
+/* controls */
+enum e_ctrl {
+ BRIGHTNESS,
+ CONTRAST,
+ AUTOGAIN,
+ EXPOSURE,
+ SHARPNESS,
+ SATUR,
+ LIGHTFREQ,
+ NCTRLS /* number of controls */
+};
+
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
+ struct gspca_ctrl ctrls[NCTRLS];
__u32 last_pts;
u8 last_fid;
- u8 brightness;
- u8 contrast;
- u8 autogain;
- u8 exposure;
- s8 sharpness;
- u8 satur;
- u8 freq;
+ u8 sensor;
+};
+enum sensors {
+ SENSOR_OV965x, /* ov9657 */
+ SENSOR_OV971x, /* ov9712 */
+ NSENSORS
};
/* V4L2 controls supported by the driver */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
-
-static const struct ctrl sd_ctrls[] = {
- { /* 0 */
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setautogain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
+static void setsatur(struct gspca_dev *gspca_dev);
+static void setlightfreq(struct gspca_dev *gspca_dev);
+
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -85,13 +92,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 15,
.step = 1,
-#define BRIGHTNESS_DEF 7
- .default_value = BRIGHTNESS_DEF,
+ .default_value = 7
},
- .set = sd_setbrightness,
- .get = sd_getbrightness,
+ .set_control = setbrightness
},
- { /* 1 */
+[CONTRAST] = {
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -99,13 +104,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 15,
.step = 1,
-#define CONTRAST_DEF 3
- .default_value = CONTRAST_DEF,
+ .default_value = 3
},
- .set = sd_setcontrast,
- .get = sd_getcontrast,
+ .set_control = setcontrast
},
- { /* 2 */
+[AUTOGAIN] = {
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -116,11 +119,9 @@ static const struct ctrl sd_ctrls[] = {
#define AUTOGAIN_DEF 1
.default_value = AUTOGAIN_DEF,
},
- .set = sd_setautogain,
- .get = sd_getautogain,
+ .set_control = setautogain
},
-#define EXPO_IDX 3
- { /* 3 */
+[EXPOSURE] = {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -128,13 +129,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 3,
.step = 1,
-#define EXPO_DEF 0
- .default_value = EXPO_DEF,
+ .default_value = 0
},
- .set = sd_setexposure,
- .get = sd_getexposure,
+ .set_control = setexposure
},
- { /* 4 */
+[SHARPNESS] = {
{
.id = V4L2_CID_SHARPNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -142,13 +141,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = -1, /* -1 = auto */
.maximum = 4,
.step = 1,
-#define SHARPNESS_DEF -1
- .default_value = SHARPNESS_DEF,
+ .default_value = -1
},
- .set = sd_setsharpness,
- .get = sd_getsharpness,
+ .set_control = setsharpness
},
- { /* 5 */
+[SATUR] = {
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -156,13 +153,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 4,
.step = 1,
-#define SATUR_DEF 2
- .default_value = SATUR_DEF,
+ .default_value = 2
},
- .set = sd_setsatur,
- .get = sd_getsatur,
+ .set_control = setsatur
},
- {
+[LIGHTFREQ] = {
{
.id = V4L2_CID_POWER_LINE_FREQUENCY,
.type = V4L2_CTRL_TYPE_MENU,
@@ -170,11 +165,9 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
.step = 1,
-#define FREQ_DEF 0
- .default_value = FREQ_DEF,
+ .default_value = 0
},
- .set = sd_setfreq,
- .get = sd_getfreq,
+ .set_control = setlightfreq
},
};
@@ -206,6 +199,14 @@ static const struct v4l2_pix_format ov965x_mode[] = {
.colorspace = V4L2_COLORSPACE_JPEG},
};
+static const struct v4l2_pix_format ov971x_mode[] = {
+ {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480,
+ .colorspace = V4L2_COLORSPACE_SRGB
+ }
+};
+
static const u8 bridge_init[][2] = {
{0x88, 0xf8},
{0x89, 0xff},
@@ -240,7 +241,7 @@ static const u8 bridge_init[][2] = {
{0x94, 0x11},
};
-static const u8 sensor_init[][2] = {
+static const u8 ov965x_init[][2] = {
{0x12, 0x80}, /* com7 - SSCB reset */
{0x00, 0x00}, /* gain */
{0x01, 0x80}, /* blue */
@@ -450,7 +451,7 @@ static const u8 bridge_init_2[][2] = {
{0x94, 0x11},
};
-static const u8 sensor_init_2[][2] = {
+static const u8 ov965x_init_2[][2] = {
{0x3b, 0xc4},
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -492,7 +493,65 @@ static const u8 sensor_init_2[][2] = {
{0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
};
-static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
+static const u8 ov971x_init[][2] = {
+ {0x12, 0x80},
+ {0x09, 0x10},
+ {0x1e, 0x07},
+ {0x5f, 0x18},
+ {0x69, 0x04},
+ {0x65, 0x2a},
+ {0x68, 0x0a},
+ {0x39, 0x28},
+ {0x4d, 0x90},
+ {0xc1, 0x80},
+ {0x0c, 0x30},
+ {0x6d, 0x02},
+ {0x96, 0xf1},
+ {0xbc, 0x68},
+ {0x12, 0x00},
+ {0x3b, 0x00},
+ {0x97, 0x80},
+ {0x17, 0x25},
+ {0x18, 0xa2},
+ {0x19, 0x01},
+ {0x1a, 0xca},
+ {0x03, 0x0a},
+ {0x32, 0x07},
+ {0x98, 0x40}, /*{0x98, 0x00},*/
+ {0x99, 0xA0}, /*{0x99, 0x00},*/
+ {0x9a, 0x01}, /*{0x9a, 0x00},*/
+ {0x57, 0x00},
+ {0x58, 0x78}, /*{0x58, 0xc8},*/
+ {0x59, 0x50}, /*{0x59, 0xa0},*/
+ {0x4c, 0x13},
+ {0x4b, 0x36},
+ {0x3d, 0x3c},
+ {0x3e, 0x03},
+ {0xbd, 0x50}, /*{0xbd, 0xa0},*/
+ {0xbe, 0x78}, /*{0xbe, 0xc8},*/
+ {0x4e, 0x55},
+ {0x4f, 0x55},
+ {0x50, 0x55},
+ {0x51, 0x55},
+ {0x24, 0x55},
+ {0x25, 0x40},
+ {0x26, 0xa1},
+ {0x5c, 0x59},
+ {0x5d, 0x00},
+ {0x11, 0x00},
+ {0x2a, 0x98},
+ {0x2b, 0x06},
+ {0x2d, 0x00},
+ {0x2e, 0x00},
+ {0x13, 0xa5},
+ {0x14, 0x40},
+ {0x4a, 0x00},
+ {0x49, 0xce},
+ {0x22, 0x03},
+ {0x09, 0x00}
+};
+
+static const u8 ov965x_start_1_vga[][2] = { /* same for qvga */
{0x12, 0x62}, /* com7 - 30fps VGA YUV */
{0x36, 0xfa}, /* aref3 */
{0x69, 0x0a}, /* hv */
@@ -515,7 +574,7 @@ static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
{0xc0, 0xaa},
};
-static const u8 sensor_start_1_svga[][2] = {
+static const u8 ov965x_start_1_svga[][2] = {
{0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
{0x36, 0xf8}, /* aref3 */
{0x69, 0x02}, /* hv */
@@ -537,7 +596,7 @@ static const u8 sensor_start_1_svga[][2] = {
{0xc0, 0xe2},
};
-static const u8 sensor_start_1_xga[][2] = {
+static const u8 ov965x_start_1_xga[][2] = {
{0x12, 0x02}, /* com7 */
{0x36, 0xf8}, /* aref3 */
{0x69, 0x02}, /* hv */
@@ -560,7 +619,7 @@ static const u8 sensor_start_1_xga[][2] = {
{0xc0, 0xe2},
};
-static const u8 sensor_start_1_sxga[][2] = {
+static const u8 ov965x_start_1_sxga[][2] = {
{0x12, 0x02}, /* com7 */
{0x36, 0xf8}, /* aref3 */
{0x69, 0x02}, /* hv */
@@ -709,7 +768,7 @@ static const u8 bridge_start_sxga[][2] = {
{0x94, 0x11},
};
-static const u8 sensor_start_2_qvga[][2] = {
+static const u8 ov965x_start_2_qvga[][2] = {
{0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -727,7 +786,7 @@ static const u8 sensor_start_2_qvga[][2] = {
{0x3a, 0x80}, /* tslb - yuyv */
};
-static const u8 sensor_start_2_vga[][2] = {
+static const u8 ov965x_start_2_vga[][2] = {
{0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -743,7 +802,7 @@ static const u8 sensor_start_2_vga[][2] = {
{0x2d, 0x00}, /* advfl */
};
-static const u8 sensor_start_2_svga[][2] = { /* same for xga */
+static const u8 ov965x_start_2_svga[][2] = { /* same for xga */
{0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -757,7 +816,7 @@ static const u8 sensor_start_2_svga[][2] = { /* same for xga */
{0xa3, 0x41}, /* bd60 */
};
-static const u8 sensor_start_2_sxga[][2] = {
+static const u8 ov965x_start_2_sxga[][2] = {
{0x13, 0xe0}, /* com8 */
{0x00, 0x00},
{0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
@@ -785,7 +844,7 @@ static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
if (ret < 0) {
- err("reg_w failed %d", ret);
+ pr_err("reg_w failed %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -810,7 +869,7 @@ static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
return gspca_dev->usb_buf[0];
@@ -848,7 +907,7 @@ static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
if (!sccb_check_status(gspca_dev))
- err("sccb_write failed");
+ pr_err("sccb_write failed\n");
}
static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
@@ -856,11 +915,11 @@ static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_read failed 1");
+ pr_err("sccb_read failed 1\n");
reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_read failed 2");
+ pr_err("sccb_read failed 2\n");
return reg_r(gspca_dev, OV534_REG_READ);
}
@@ -922,7 +981,9 @@ static void setbrightness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
- val = sd->brightness;
+ if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
+ return;
+ val = sd->ctrls[BRIGHTNESS].val;
if (val < 8)
val = 15 - val; /* f .. 8 */
else
@@ -935,8 +996,10 @@ static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (gspca_dev->ctrl_dis & (1 << CONTRAST))
+ return;
sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
- sd->contrast << 4);
+ sd->ctrls[CONTRAST].val << 4);
}
static void setautogain(struct gspca_dev *gspca_dev)
@@ -944,10 +1007,12 @@ static void setautogain(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
+ if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+ return;
/*fixme: should adjust agc/awb/aec by different controls */
val = sccb_read(gspca_dev, 0x13); /* com8 */
sccb_write(gspca_dev, 0xff, 0x00);
- if (sd->autogain)
+ if (sd->ctrls[AUTOGAIN].val)
val |= 0x05; /* agc & aec */
else
val &= 0xfa;
@@ -960,8 +1025,10 @@ static void setexposure(struct gspca_dev *gspca_dev)
u8 val;
static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
+ if (gspca_dev->ctrl_dis & (1 << EXPOSURE))
+ return;
sccb_write(gspca_dev, 0x10, /* aec[9:2] */
- expo[sd->exposure]);
+ expo[sd->ctrls[EXPOSURE].val]);
val = sccb_read(gspca_dev, 0x13); /* com8 */
sccb_write(gspca_dev, 0xff, 0x00);
@@ -977,7 +1044,9 @@ static void setsharpness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
s8 val;
- val = sd->sharpness;
+ if (gspca_dev->ctrl_dis & (1 << SHARPNESS))
+ return;
+ val = sd->ctrls[SHARPNESS].val;
if (val < 0) { /* auto */
val = sccb_read(gspca_dev, 0x42); /* com17 */
sccb_write(gspca_dev, 0xff, 0x00);
@@ -1006,8 +1075,10 @@ static void setsatur(struct gspca_dev *gspca_dev)
{0x48, 0x90}
};
- val1 = matrix[sd->satur][0];
- val2 = matrix[sd->satur][1];
+ if (gspca_dev->ctrl_dis & (1 << SATUR))
+ return;
+ val1 = matrix[sd->ctrls[SATUR].val][0];
+ val2 = matrix[sd->ctrls[SATUR].val][1];
val3 = val1 + val2;
sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */
sccb_write(gspca_dev, 0x50, val3);
@@ -1022,14 +1093,16 @@ static void setsatur(struct gspca_dev *gspca_dev)
sccb_write(gspca_dev, 0x41, val1);
}
-static void setfreq(struct gspca_dev *gspca_dev)
+static void setlightfreq(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
+ if (gspca_dev->ctrl_dis & (1 << LIGHTFREQ))
+ return;
val = sccb_read(gspca_dev, 0x13); /* com8 */
sccb_write(gspca_dev, 0xff, 0x00);
- if (sd->freq == 0) {
+ if (sd->ctrls[LIGHTFREQ].val == 0) {
sccb_write(gspca_dev, 0x13, val & 0xdf);
return;
}
@@ -1037,7 +1110,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
val = sccb_read(gspca_dev, 0x42); /* com17 */
sccb_write(gspca_dev, 0xff, 0x00);
- if (sd->freq == 1)
+ if (sd->ctrls[LIGHTFREQ].val == 1)
val |= 0x01;
else
val &= 0xfe;
@@ -1049,34 +1122,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct cam *cam;
-
- cam = &gspca_dev->cam;
- cam->cam_mode = ov965x_mode;
- cam->nmodes = ARRAY_SIZE(ov965x_mode);
+ gspca_dev->cam.ctrls = sd->ctrls;
- sd->brightness = BRIGHTNESS_DEF;
- sd->contrast = CONTRAST_DEF;
#if AUTOGAIN_DEF != 0
- sd->autogain = AUTOGAIN_DEF;
- gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
-#endif
-#if EXPO_DEF != 0
- sd->exposure = EXPO_DEF;
-#endif
-#if SHARPNESS_DEF != 0
- sd->sharpness = SHARPNESS_DEF;
+ gspca_dev->ctrl_inac |= (1 << EXPOSURE);
#endif
- sd->satur = SATUR_DEF;
- sd->freq = FREQ_DEF;
-
return 0;
}
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
u16 sensor_id;
/* reset bridge */
@@ -1099,68 +1157,117 @@ static int sd_init(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
/* initialize */
- reg_w_array(gspca_dev, bridge_init,
- ARRAY_SIZE(bridge_init));
- sccb_w_array(gspca_dev, sensor_init,
- ARRAY_SIZE(sensor_init));
- reg_w_array(gspca_dev, bridge_init_2,
- ARRAY_SIZE(bridge_init_2));
- sccb_w_array(gspca_dev, sensor_init_2,
- ARRAY_SIZE(sensor_init_2));
- reg_w(gspca_dev, 0xe0, 0x00);
- reg_w(gspca_dev, 0xe0, 0x01);
- set_led(gspca_dev, 0);
- reg_w(gspca_dev, 0xe0, 0x00);
+ if ((sensor_id & 0xfff0) == 0x9650) {
+ sd->sensor = SENSOR_OV965x;
+
+ gspca_dev->cam.cam_mode = ov965x_mode;
+ gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
+
+ reg_w_array(gspca_dev, bridge_init,
+ ARRAY_SIZE(bridge_init));
+ sccb_w_array(gspca_dev, ov965x_init,
+ ARRAY_SIZE(ov965x_init));
+ reg_w_array(gspca_dev, bridge_init_2,
+ ARRAY_SIZE(bridge_init_2));
+ sccb_w_array(gspca_dev, ov965x_init_2,
+ ARRAY_SIZE(ov965x_init_2));
+ reg_w(gspca_dev, 0xe0, 0x00);
+ reg_w(gspca_dev, 0xe0, 0x01);
+ set_led(gspca_dev, 0);
+ reg_w(gspca_dev, 0xe0, 0x00);
+ } else if ((sensor_id & 0xfff0) == 0x9710) {
+ const char *p;
+ int l;
+
+ sd->sensor = SENSOR_OV971x;
+
+ gspca_dev->cam.cam_mode = ov971x_mode;
+ gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
+
+ /* no control yet */
+ gspca_dev->ctrl_dis = (1 << NCTRLS) - 1;
+
+ gspca_dev->cam.bulk = 1;
+ gspca_dev->cam.bulk_size = 16384;
+ gspca_dev->cam.bulk_nurbs = 2;
+
+ sccb_w_array(gspca_dev, ov971x_init,
+ ARRAY_SIZE(ov971x_init));
+
+ /* set video format on bridge processor */
+ /* access bridge processor's video format registers at: 0x00 */
+ reg_w(gspca_dev, 0x1c, 0x00);
+ /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
+ reg_w(gspca_dev, 0x1d, 0x00);
+
+ /* Will W. specific stuff
+ * set VSYNC to
+ * output (0x1f) if first webcam
+ * input (0x17) if 2nd or 3rd webcam */
+ p = video_device_node_name(&gspca_dev->vdev);
+ l = strlen(p) - 1;
+ if (p[l] == '0')
+ reg_w(gspca_dev, 0x56, 0x1f);
+ else
+ reg_w(gspca_dev, 0x56, 0x17);
+ } else {
+ err("Unknown sensor %04x", sensor_id);
+ return -EINVAL;
+ }
return gspca_dev->usb_err;
}
static int sd_start(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_OV971x)
+ return gspca_dev->usb_err;
switch (gspca_dev->curr_mode) {
case QVGA_MODE: /* 320x240 */
- sccb_w_array(gspca_dev, sensor_start_1_vga,
- ARRAY_SIZE(sensor_start_1_vga));
+ sccb_w_array(gspca_dev, ov965x_start_1_vga,
+ ARRAY_SIZE(ov965x_start_1_vga));
reg_w_array(gspca_dev, bridge_start_qvga,
ARRAY_SIZE(bridge_start_qvga));
- sccb_w_array(gspca_dev, sensor_start_2_qvga,
- ARRAY_SIZE(sensor_start_2_qvga));
+ sccb_w_array(gspca_dev, ov965x_start_2_qvga,
+ ARRAY_SIZE(ov965x_start_2_qvga));
break;
case VGA_MODE: /* 640x480 */
- sccb_w_array(gspca_dev, sensor_start_1_vga,
- ARRAY_SIZE(sensor_start_1_vga));
+ sccb_w_array(gspca_dev, ov965x_start_1_vga,
+ ARRAY_SIZE(ov965x_start_1_vga));
reg_w_array(gspca_dev, bridge_start_vga,
ARRAY_SIZE(bridge_start_vga));
- sccb_w_array(gspca_dev, sensor_start_2_vga,
- ARRAY_SIZE(sensor_start_2_vga));
+ sccb_w_array(gspca_dev, ov965x_start_2_vga,
+ ARRAY_SIZE(ov965x_start_2_vga));
break;
case SVGA_MODE: /* 800x600 */
- sccb_w_array(gspca_dev, sensor_start_1_svga,
- ARRAY_SIZE(sensor_start_1_svga));
+ sccb_w_array(gspca_dev, ov965x_start_1_svga,
+ ARRAY_SIZE(ov965x_start_1_svga));
reg_w_array(gspca_dev, bridge_start_svga,
ARRAY_SIZE(bridge_start_svga));
- sccb_w_array(gspca_dev, sensor_start_2_svga,
- ARRAY_SIZE(sensor_start_2_svga));
+ sccb_w_array(gspca_dev, ov965x_start_2_svga,
+ ARRAY_SIZE(ov965x_start_2_svga));
break;
case XGA_MODE: /* 1024x768 */
- sccb_w_array(gspca_dev, sensor_start_1_xga,
- ARRAY_SIZE(sensor_start_1_xga));
+ sccb_w_array(gspca_dev, ov965x_start_1_xga,
+ ARRAY_SIZE(ov965x_start_1_xga));
reg_w_array(gspca_dev, bridge_start_xga,
ARRAY_SIZE(bridge_start_xga));
- sccb_w_array(gspca_dev, sensor_start_2_svga,
- ARRAY_SIZE(sensor_start_2_svga));
+ sccb_w_array(gspca_dev, ov965x_start_2_svga,
+ ARRAY_SIZE(ov965x_start_2_svga));
break;
default:
/* case SXGA_MODE: * 1280x1024 */
- sccb_w_array(gspca_dev, sensor_start_1_sxga,
- ARRAY_SIZE(sensor_start_1_sxga));
+ sccb_w_array(gspca_dev, ov965x_start_1_sxga,
+ ARRAY_SIZE(ov965x_start_1_sxga));
reg_w_array(gspca_dev, bridge_start_sxga,
ARRAY_SIZE(bridge_start_sxga));
- sccb_w_array(gspca_dev, sensor_start_2_sxga,
- ARRAY_SIZE(sensor_start_2_sxga));
+ sccb_w_array(gspca_dev, ov965x_start_2_sxga,
+ ARRAY_SIZE(ov965x_start_2_sxga));
break;
}
- setfreq(gspca_dev);
+ setlightfreq(gspca_dev);
setautogain(gspca_dev);
setbrightness(gspca_dev);
setcontrast(gspca_dev);
@@ -1198,9 +1305,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
__u32 this_pts;
u8 this_fid;
int remaining_len = len;
+ int payload_len;
+ payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
do {
- len = min(remaining_len, 2040);
+ len = min(remaining_len, payload_len);
/* Payloads are prefixed with a UVC-style header. We
consider a frame to start when the FID toggles, or the PTS
@@ -1262,138 +1371,6 @@ scan_next:
} while (remaining_len > 0);
}
-/* controls */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->brightness = val;
- if (gspca_dev->streaming)
- setbrightness(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->brightness;
- return 0;
-}
-
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->contrast = val;
- if (gspca_dev->streaming)
- setcontrast(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->contrast;
- return 0;
-}
-
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->autogain = val;
-
- if (gspca_dev->streaming) {
- if (val)
- gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
- else
- gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
- setautogain(gspca_dev);
- }
- return gspca_dev->usb_err;
-}
-
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->autogain;
- return 0;
-}
-
-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->exposure = val;
- if (gspca_dev->streaming)
- setexposure(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->exposure;
- return 0;
-}
-
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->sharpness = val;
- if (gspca_dev->streaming)
- setsharpness(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->sharpness;
- return 0;
-}
-
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->satur = val;
- if (gspca_dev->streaming)
- setsatur(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->satur;
- return 0;
-}
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->freq = val;
- if (gspca_dev->streaming)
- setfreq(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->freq;
- return 0;
-}
-
static int sd_querymenu(struct gspca_dev *gspca_dev,
struct v4l2_querymenu *menu)
{
@@ -1419,7 +1396,7 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
- .nctrls = ARRAY_SIZE(sd_ctrls),
+ .nctrls = NCTRLS,
.config = sd_config,
.init = sd_init,
.start = sd_start,
@@ -1430,6 +1407,7 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */
static const struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x05a9, 0x8065)},
{USB_DEVICE(0x06f8, 0x3003)},
{}
};
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index 81739a2..1600df1 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -23,6 +23,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "pac207"
#include <linux/input.h>
@@ -178,8 +180,8 @@ static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
0x00, index,
gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
if (err < 0)
- err("Failed to write registers to index 0x%04X, error %d)",
- index, err);
+ pr_err("Failed to write registers to index 0x%04X, error %d\n",
+ index, err);
return err;
}
@@ -194,8 +196,8 @@ static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
if (err)
- err("Failed to write a register (index 0x%04X,"
- " value 0x%02X, error %d)", index, value, err);
+ pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+ index, value, err);
return err;
}
@@ -210,8 +212,8 @@ static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
0x00, index,
gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
if (res < 0) {
- err("Failed to read a register (index 0x%04X, error %d)",
- index, res);
+ pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+ index, res);
return res;
}
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
index 5615d7b..ae433ef 100644
--- a/drivers/media/video/gspca/pac7302.c
+++ b/drivers/media/video/gspca/pac7302.c
@@ -61,6 +61,8 @@
3 | 0x21 | sethvflip()
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "pac7302"
#include <linux/input.h>
@@ -408,8 +410,8 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_w_buf failed index 0x%02x, error %d",
- index, ret);
+ pr_err("reg_w_buf failed index 0x%02x, error %d\n",
+ index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -431,8 +433,8 @@ static void reg_w(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
- index, value, ret);
+ pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, value, ret);
gspca_dev->usb_err = ret;
}
}
@@ -466,9 +468,8 @@ static void reg_w_page(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w_page() failed index 0x%02x, "
- "value 0x%02x, error %d",
- index, page[index], ret);
+ pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, page[index], ret);
gspca_dev->usb_err = ret;
break;
}
@@ -1189,6 +1190,7 @@ static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2620)},
{USB_DEVICE(0x093a, 0x2621)},
{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
+ {USB_DEVICE(0x093a, 0x2623), .driver_info = FL_VFLIP},
{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
{USB_DEVICE(0x093a, 0x2625)},
{USB_DEVICE(0x093a, 0x2626)},
@@ -1196,6 +1198,8 @@ static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
{USB_DEVICE(0x093a, 0x262a)},
{USB_DEVICE(0x093a, 0x262c)},
+ {USB_DEVICE(0x145f, 0x013c)},
+ {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index f8801b5..7509d05 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -49,6 +49,8 @@
for max gain, 0x14 for minimal gain.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "pac7311"
#include <linux/input.h>
@@ -276,8 +278,8 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_w_buf() failed index 0x%02x, error %d",
- index, ret);
+ pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
+ index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -299,8 +301,8 @@ static void reg_w(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
- index, value, ret);
+ pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, value, ret);
gspca_dev->usb_err = ret;
}
}
@@ -334,9 +336,8 @@ static void reg_w_page(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w_page() failed index 0x%02x, "
- "value 0x%02x, error %d",
- index, page[index], ret);
+ pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, page[index], ret);
gspca_dev->usb_err = ret;
break;
}
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c
index 4271f86..48aae39 100644
--- a/drivers/media/video/gspca/sn9c2028.c
+++ b/drivers/media/video/gspca/sn9c2028.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sn9c2028"
#include "gspca.h"
@@ -75,8 +77,8 @@ static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2, 0, gspca_dev->usb_buf, 6, 500);
if (rc < 0) {
- err("command write [%02x] error %d",
- gspca_dev->usb_buf[0], rc);
+ pr_err("command write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], rc);
return rc;
}
@@ -93,7 +95,7 @@ static int sn9c2028_read1(struct gspca_dev *gspca_dev)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1, 0, gspca_dev->usb_buf, 1, 500);
if (rc != 1) {
- err("read1 error %d", rc);
+ pr_err("read1 error %d\n", rc);
return (rc < 0) ? rc : -EIO;
}
PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
@@ -109,7 +111,7 @@ static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
4, 0, gspca_dev->usb_buf, 4, 500);
if (rc != 4) {
- err("read4 error %d", rc);
+ pr_err("read4 error %d\n", rc);
return (rc < 0) ? rc : -EIO;
}
memcpy(reading, gspca_dev->usb_buf, 4);
@@ -131,7 +133,7 @@ static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
for (i = 0; i < 256 && status < 2; i++)
status = sn9c2028_read1(gspca_dev);
if (status != 2) {
- err("long command status read error %d", status);
+ pr_err("long command status read error %d\n", status);
return (status < 0) ? status : -EIO;
}
@@ -638,7 +640,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
err_code = start_vivitar_cam(gspca_dev);
break;
default:
- err("Starting unknown camera, please report this");
+ pr_err("Starting unknown camera, please report this\n");
return -ENXIO;
}
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index c431900..509e202 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/input.h>
#include "gspca.h"
@@ -1123,7 +1125,7 @@ static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
length,
500);
if (unlikely(result < 0 || result != length)) {
- err("Read register failed 0x%02X", reg);
+ pr_err("Read register failed 0x%02X\n", reg);
return -EIO;
}
return 0;
@@ -1144,7 +1146,7 @@ static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
length,
500);
if (unlikely(result < 0 || result != length)) {
- err("Write register failed index 0x%02X", reg);
+ pr_err("Write register failed index 0x%02X\n", reg);
return -EIO;
}
return 0;
@@ -1275,14 +1277,14 @@ static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
return -EINVAL;
if (id != 0x7fa2) {
- err("sensor id for ov9650 doesn't match (0x%04x)", id);
+ pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
return -ENODEV;
}
for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
if (i2c_w1(gspca_dev, ov9650_init[i].reg,
ov9650_init[i].val) < 0) {
- err("OV9650 sensor initialization failed");
+ pr_err("OV9650 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1299,7 +1301,7 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
if (i2c_w1(gspca_dev, ov9655_init[i].reg,
ov9655_init[i].val) < 0) {
- err("OV9655 sensor initialization failed");
+ pr_err("OV9655 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1318,7 +1320,7 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
if (i2c_w1(gspca_dev, soi968_init[i].reg,
soi968_init[i].val) < 0) {
- err("SOI968 sensor initialization failed");
+ pr_err("SOI968 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1338,7 +1340,7 @@ static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
if (i2c_w1(gspca_dev, ov7660_init[i].reg,
ov7660_init[i].val) < 0) {
- err("OV7660 sensor initialization failed");
+ pr_err("OV7660 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1355,7 +1357,7 @@ static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
if (i2c_w1(gspca_dev, ov7670_init[i].reg,
ov7670_init[i].val) < 0) {
- err("OV7670 sensor initialization failed");
+ pr_err("OV7670 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1379,14 +1381,14 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
mt9v011_init[i].val) < 0) {
- err("MT9V011 sensor initialization failed");
+ pr_err("MT9V011 sensor initialization failed\n");
return -ENODEV;
}
}
sd->hstart = 2;
sd->vstart = 2;
sd->sensor = SENSOR_MT9V011;
- info("MT9V011 sensor detected");
+ pr_info("MT9V011 sensor detected\n");
return 0;
}
@@ -1397,7 +1399,7 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
mt9v111_init[i].val) < 0) {
- err("MT9V111 sensor initialization failed");
+ pr_err("MT9V111 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1407,7 +1409,7 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
sd->hstart = 2;
sd->vstart = 2;
sd->sensor = SENSOR_MT9V111;
- info("MT9V111 sensor detected");
+ pr_info("MT9V111 sensor detected\n");
return 0;
}
@@ -1422,14 +1424,14 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
mt9v112_init[i].val) < 0) {
- err("MT9V112 sensor initialization failed");
+ pr_err("MT9V112 sensor initialization failed\n");
return -ENODEV;
}
}
sd->hstart = 6;
sd->vstart = 2;
sd->sensor = SENSOR_MT9V112;
- info("MT9V112 sensor detected");
+ pr_info("MT9V112 sensor detected\n");
return 0;
}
@@ -1443,7 +1445,7 @@ static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
mt9m112_init[i].val) < 0) {
- err("MT9M112 sensor initialization failed");
+ pr_err("MT9M112 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1461,7 +1463,7 @@ static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
mt9m111_init[i].val) < 0) {
- err("MT9M111 sensor initialization failed");
+ pr_err("MT9M111 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1485,20 +1487,20 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
switch (id) {
case 0x8411:
case 0x8421:
- info("MT9M001 color sensor detected");
+ pr_info("MT9M001 color sensor detected\n");
break;
case 0x8431:
- info("MT9M001 mono sensor detected");
+ pr_info("MT9M001 mono sensor detected\n");
break;
default:
- err("No MT9M001 chip detected, ID = %x\n", id);
+ pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
return -ENODEV;
}
for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
mt9m001_init[i].val) < 0) {
- err("MT9M001 sensor initialization failed");
+ pr_err("MT9M001 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1517,7 +1519,7 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
hv7131r_init[i].val) < 0) {
- err("HV7131R Sensor initialization failed");
+ pr_err("HV7131R Sensor initialization failed\n");
return -ENODEV;
}
}
@@ -2103,7 +2105,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
value = bridge_init[i][1];
if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
- err("Device initialization failed");
+ pr_err("Device initialization failed\n");
return -ENODEV;
}
}
@@ -2114,7 +2116,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x1006, 0x20);
if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
- err("Device initialization failed");
+ pr_err("Device initialization failed\n");
return -ENODEV;
}
@@ -2122,27 +2124,27 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SENSOR_OV9650:
if (ov9650_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV9650 sensor detected");
+ pr_info("OV9650 sensor detected\n");
break;
case SENSOR_OV9655:
if (ov9655_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV9655 sensor detected");
+ pr_info("OV9655 sensor detected\n");
break;
case SENSOR_SOI968:
if (soi968_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("SOI968 sensor detected");
+ pr_info("SOI968 sensor detected\n");
break;
case SENSOR_OV7660:
if (ov7660_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV7660 sensor detected");
+ pr_info("OV7660 sensor detected\n");
break;
case SENSOR_OV7670:
if (ov7670_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV7670 sensor detected");
+ pr_info("OV7670 sensor detected\n");
break;
case SENSOR_MT9VPRB:
if (mt9v_init_sensor(gspca_dev) < 0)
@@ -2151,12 +2153,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SENSOR_MT9M111:
if (mt9m111_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("MT9M111 sensor detected");
+ pr_info("MT9M111 sensor detected\n");
break;
case SENSOR_MT9M112:
if (mt9m112_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("MT9M112 sensor detected");
+ pr_info("MT9M112 sensor detected\n");
break;
case SENSOR_MT9M001:
if (mt9m001_init_sensor(gspca_dev) < 0)
@@ -2165,10 +2167,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SENSOR_HV7131R:
if (hv7131r_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("HV7131R sensor detected");
+ pr_info("HV7131R sensor detected\n");
break;
default:
- info("Unsupported Sensor");
+ pr_info("Unsupported Sensor\n");
return -ENODEV;
}
@@ -2263,19 +2265,19 @@ static int sd_start(struct gspca_dev *gspca_dev)
switch (mode & SCALE_MASK) {
case SCALE_1280x1024:
scale = 0xc0;
- info("Set 1280x1024");
+ pr_info("Set 1280x1024\n");
break;
case SCALE_640x480:
scale = 0x80;
- info("Set 640x480");
+ pr_info("Set 640x480\n");
break;
case SCALE_320x240:
scale = 0x90;
- info("Set 320x240");
+ pr_info("Set 320x240\n");
break;
case SCALE_160x120:
scale = 0xa0;
- info("Set 160x120");
+ pr_info("Set 160x120\n");
break;
}
@@ -2513,12 +2515,13 @@ static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
{USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
{USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
- {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
+ {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
{USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
{USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
{USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
{USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
{USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
+ {USB_DEVICE(0x0458, 0x7045), SN9C20X(MT9M112, 0x5d, LED_REVERSE)},
{USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
{USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
{USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 81b8a60..c746bf1 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -1,7 +1,7 @@
/*
* Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
*
- * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
* Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
*
* This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sonixj"
#include <linux/input.h>
@@ -136,7 +138,7 @@ static void setillum(struct gspca_dev *gspca_dev);
static void setfreq(struct gspca_dev *gspca_dev);
static const struct ctrl sd_ctrls[NCTRLS] = {
-[BRIGHTNESS] = {
+[BRIGHTNESS] = {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -157,7 +159,7 @@ static const struct ctrl sd_ctrls[NCTRLS] = {
#define CONTRAST_MAX 127
.maximum = CONTRAST_MAX,
.step = 1,
- .default_value = 63,
+ .default_value = 20,
},
.set_control = setcontrast
},
@@ -737,7 +739,7 @@ static const u8 mi0360_sensor_init[][8] = {
{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
- {0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
+ {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
@@ -1277,7 +1279,7 @@ static const u8 soi768_sensor_param1[][8] = {
/* global gain ? : 07 - change with 0x15 at the end */
{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
- {0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
/* exposure ? : 0200 - change with 0x1e at the end */
{}
};
@@ -1395,7 +1397,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
return;
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -1408,7 +1410,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
500);
PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1432,7 +1434,7 @@ static void reg_w1(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w1 err %d", ret);
+ pr_err("reg_w1 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1449,7 +1451,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
value, buffer[0], buffer[1]);
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
+ pr_err("reg_w: buffer overflow\n");
return;
}
#endif
@@ -1462,7 +1464,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1502,7 +1504,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
gspca_dev->usb_buf, 8,
500);
if (ret < 0) {
- err("i2c_w1 err %d", ret);
+ pr_err("i2c_w1 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1527,7 +1529,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
500);
msleep(2);
if (ret < 0) {
- err("i2c_w8 err %d", ret);
+ pr_err("i2c_w8 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1591,7 +1593,7 @@ static void hv7131r_probe(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor HV7131R found");
return;
}
- warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
+ pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
gspca_dev->usb_buf[2]);
}
@@ -1710,7 +1712,7 @@ static void ov7648_probe(struct gspca_dev *gspca_dev)
sd->sensor = SENSOR_PO1030;
return;
}
- err("Unknown sensor %04x", val);
+ pr_err("Unknown sensor %04x\n", val);
}
/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
@@ -1748,7 +1750,7 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor po2030n");
/* sd->sensor = SENSOR_PO2030N; */
} else {
- err("Unknown sensor ID %04x", val);
+ pr_err("Unknown sensor ID %04x\n", val);
}
}
@@ -2006,8 +2008,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
case SENSOR_OM6802:
expo = brightness << 2;
sd->exposure = setexposure(gspca_dev, expo);
- k2 = brightness >> 3;
- break;
+ return; /* Y offset already set */
}
reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
@@ -2019,13 +2020,13 @@ static void setcontrast(struct gspca_dev *gspca_dev)
u8 k2;
u8 contrast[6];
- k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)
- + 0x10; /* 10..40 */
+ k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
+ + 37; /* 37..73 */
contrast[0] = (k2 + 1) / 2; /* red */
contrast[1] = 0;
contrast[2] = k2; /* green */
contrast[3] = 0;
- contrast[4] = (k2 + 1) / 5; /* blue */
+ contrast[4] = k2 / 5; /* blue */
contrast[5] = 0;
reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
}
@@ -2386,7 +2387,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x01, 0x22);
msleep(100);
reg01 = SCL_SEL_OD | S_PDN_INV;
- reg17 &= MCK_SIZE_MASK;
+ reg17 &= ~MCK_SIZE_MASK;
reg17 |= 0x04; /* clock / 4 */
break;
}
@@ -2507,9 +2508,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
break;
case SENSOR_HV7131R:
case SENSOR_MI0360:
- if (mode)
- reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */
- else
+ if (!mode)
reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */
reg17 &= ~MCK_SIZE_MASK;
reg17 |= 0x01; /* clock / 1 */
@@ -2532,6 +2531,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
if (!mode) { /* if 640x480 */
reg17 &= ~MCK_SIZE_MASK;
reg17 |= 0x04; /* clock / 4 */
+ } else {
+ reg01 &= ~SYS_SEL_48M; /* clk 24Mz */
+ reg17 &= ~MCK_SIZE_MASK;
+ reg17 |= 0x02; /* clock / 2 */
}
break;
case SENSOR_OV7630:
diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c
index 76c006b..6956731 100644
--- a/drivers/media/video/gspca/spca1528.c
+++ b/drivers/media/video/gspca/spca1528.c
@@ -1,7 +1,7 @@
/*
* spca1528 subdriver
*
- * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca1528"
#include "gspca.h"
@@ -171,7 +173,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -193,7 +195,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
value, index,
NULL, 0, 500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -217,21 +219,23 @@ static void reg_wb(struct gspca_dev *gspca_dev,
value, index,
gspca_dev->usb_buf, 1, 500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
static void wait_status_0(struct gspca_dev *gspca_dev)
{
- int i;
+ int i, w;
- i = 20;
+ i = 16;
+ w = 0;
do {
reg_r(gspca_dev, 0x21, 0x0000, 1);
if (gspca_dev->usb_buf[0] == 0)
return;
- msleep(30);
+ w += 15;
+ msleep(w);
} while (--i > 0);
PDEBUG(D_ERR, "wait_status_0 timeout");
gspca_dev->usb_err = -ETIME;
@@ -307,8 +311,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->color = COLOR_DEF;
sd->sharpness = SHARPNESS_DEF;
- gspca_dev->nbalt = 4; /* use alternate setting 3 */
-
return 0;
}
@@ -347,8 +349,12 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
reg_r(gspca_dev, 0x25, 0x0004, 1);
- reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
+ reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06); /* 420 */
reg_r(gspca_dev, 0x27, 0x0000, 1);
+
+/* not useful..
+ gspca_dev->alt = 4; * use alternate setting 3 */
+
return gspca_dev->usb_err;
}
@@ -361,8 +367,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x22); /* JPEG 411 */
- /* the JPEG quality seems to be 82% */
- jpeg_set_qual(sd->jpeg_hdr, 82);
+ /* the JPEG quality shall be 85% */
+ jpeg_set_qual(sd->jpeg_hdr, 85);
/* set the controls */
setbrightness(gspca_dev);
@@ -377,7 +383,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* start the capture */
wait_status_0(gspca_dev);
- reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
+ reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */
wait_status_1(gspca_dev);
wait_status_0(gspca_dev);
msleep(200);
@@ -390,7 +396,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
{
/* stop the capture */
wait_status_0(gspca_dev);
- reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
+ reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */
wait_status_1(gspca_dev);
wait_status_0(gspca_dev);
}
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
index 3e76951..bb82c94 100644
--- a/drivers/media/video/gspca/spca500.c
+++ b/drivers/media/video/gspca/spca500.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca500"
#include "gspca.h"
@@ -396,7 +398,7 @@ static int reg_w(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, NULL, 0, 500);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
@@ -418,7 +420,7 @@ static int reg_r_12(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, length,
500); /* timeout */
if (ret < 0) {
- err("reg_r_12 err %d", ret);
+ pr_err("reg_r_12 err %d\n", ret);
return ret;
}
return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
index f7ef282..7aaac72 100644
--- a/drivers/media/video/gspca/spca501.c
+++ b/drivers/media/video/gspca/spca501.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca501"
#include "gspca.h"
@@ -1852,7 +1854,7 @@ static int reg_write(struct usb_device *dev,
PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
req, index, value);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index e5bf865..16722dc 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca505"
#include "gspca.h"
@@ -578,7 +580,7 @@ static int reg_write(struct usb_device *dev,
PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
req, index, value, ret);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
@@ -685,8 +687,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
return ret;
}
if (ret != 0x0101) {
- err("After vector read returns 0x%04x should be 0x0101",
- ret);
+ pr_err("After vector read returns 0x%04x should be 0x0101\n",
+ ret);
}
ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index 9d0b460..a44fe3d 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca508"
#include "gspca.h"
@@ -1275,7 +1277,7 @@ static int reg_write(struct usb_device *dev,
PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
index, value);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
@@ -1297,7 +1299,7 @@ static int reg_read(struct gspca_dev *gspca_dev,
PDEBUG(D_USBI, "reg read i:%04x --> %02x",
index, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_read err %d", ret);
+ pr_err("reg_read err %d\n", ret);
return ret;
}
return gspca_dev->usb_buf[0];
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index e836e77..c82fd53 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca561"
#include <linux/input.h>
@@ -315,7 +317,7 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
value, index, NULL, 0, 500);
PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
}
static void write_vector(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
index 5ba96af..df805f7 100644
--- a/drivers/media/video/gspca/sq905.c
+++ b/drivers/media/video/gspca/sq905.c
@@ -33,6 +33,8 @@
* drivers.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sq905"
#include <linux/workqueue.h>
@@ -123,8 +125,7 @@ static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
SQ905_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -135,8 +136,7 @@ static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
SQ905_PING, 0, gspca_dev->usb_buf, 1,
SQ905_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed 2 (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
return ret;
}
@@ -158,7 +158,7 @@ static int sq905_ack_frame(struct gspca_dev *gspca_dev)
SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
SQ905_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)", __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -186,7 +186,7 @@ sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
if (need_lock)
mutex_unlock(&gspca_dev->usb_lock);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)", __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
ret = usb_bulk_msg(gspca_dev->dev,
@@ -195,8 +195,7 @@ sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
/* successful, it returns 0, otherwise negative */
if (ret < 0 || act_len != size) {
- err("bulk read fail (%d) len %d/%d",
- ret, act_len, size);
+ pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
return -EIO;
}
return 0;
@@ -226,7 +225,7 @@ static void sq905_dostream(struct work_struct *work)
buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
if (!buffer) {
- err("Couldn't allocate USB buffer");
+ pr_err("Couldn't allocate USB buffer\n");
goto quit_stream;
}
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
index 457563b..c2c0560 100644
--- a/drivers/media/video/gspca/sq905c.c
+++ b/drivers/media/video/gspca/sq905c.c
@@ -27,6 +27,8 @@
* and may contain code fragments from it.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sq905c"
#include <linux/workqueue.h>
@@ -95,8 +97,7 @@ static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
command, index, NULL, 0,
SQ905C_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -115,8 +116,7 @@ static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
command, index, gspca_dev->usb_buf, size,
SQ905C_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -146,7 +146,7 @@ static void sq905c_dostream(struct work_struct *work)
buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
if (!buffer) {
- err("Couldn't allocate USB buffer");
+ pr_err("Couldn't allocate USB buffer\n");
goto quit_stream;
}
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c
index 8215d5d..e4255b4 100644
--- a/drivers/media/video/gspca/sq930x.c
+++ b/drivers/media/video/gspca/sq930x.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sq930x"
#include "gspca.h"
@@ -468,7 +470,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
value, 0, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_r %04x failed %d", value, ret);
+ pr_err("reg_r %04x failed %d\n", value, ret);
gspca_dev->usb_err = ret;
}
}
@@ -488,7 +490,7 @@ static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
500);
msleep(30);
if (ret < 0) {
- err("reg_w %04x %04x failed %d", value, index, ret);
+ pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -511,7 +513,7 @@ static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,
1000);
msleep(30);
if (ret < 0) {
- err("reg_wb %04x %04x failed %d", value, index, ret);
+ pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -556,7 +558,7 @@ static void i2c_write(struct sd *sd,
gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
500);
if (ret < 0) {
- err("i2c_write failed %d", ret);
+ pr_err("i2c_write failed %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -575,7 +577,7 @@ static void ucbus_write(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if ((batchsize - 1) * 3 > USB_BUF_SZ) {
- err("Bug: usb_buf overflow");
+ pr_err("Bug: usb_buf overflow\n");
gspca_dev->usb_err = -ENOMEM;
return;
}
@@ -612,7 +614,7 @@ static void ucbus_write(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
500);
if (ret < 0) {
- err("ucbus_write failed %d", ret);
+ pr_err("ucbus_write failed %d\n", ret);
gspca_dev->usb_err = ret;
return;
}
@@ -688,7 +690,7 @@ static void cmos_probe(struct gspca_dev *gspca_dev)
break;
}
if (i >= ARRAY_SIZE(probe_order)) {
- err("Unknown sensor");
+ pr_err("Unknown sensor\n");
gspca_dev->usb_err = -EINVAL;
return;
}
@@ -696,7 +698,8 @@ static void cmos_probe(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_OV7660:
case SENSOR_OV9630:
- err("Sensor %s not yet treated", sensor_tb[sd->sensor].name);
+ pr_err("Sensor %s not yet treated\n",
+ sensor_tb[sd->sensor].name);
gspca_dev->usb_err = -EINVAL;
break;
}
@@ -1091,7 +1094,7 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
gspca_dev->cam.bulk_nurbs = 1;
ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
if (ret < 0)
- err("sd_dq_callback() err %d", ret);
+ pr_err("sd_dq_callback() err %d\n", ret);
/* wait a little time, otherwise the webcam crashes */
msleep(100);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
index 7637477..42a7a28 100644
--- a/drivers/media/video/gspca/stk014.c
+++ b/drivers/media/video/gspca/stk014.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "stk014"
#include "gspca.h"
@@ -137,7 +139,7 @@ static u8 reg_r(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
return 0;
}
@@ -162,7 +164,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
0,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -192,7 +194,7 @@ static void rcv_val(struct gspca_dev *gspca_dev,
&alen,
500); /* timeout in milliseconds */
if (ret < 0) {
- err("rcv_val err %d", ret);
+ pr_err("rcv_val err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -235,7 +237,7 @@ static void snd_val(struct gspca_dev *gspca_dev,
&alen,
500); /* timeout in milliseconds */
if (ret < 0) {
- err("snd_val err %d", ret);
+ pr_err("snd_val err %d\n", ret);
gspca_dev->usb_err = ret;
} else {
if (ads == 0x003f08) {
@@ -315,7 +317,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
ret = reg_r(gspca_dev, 0x0740);
if (gspca_dev->usb_err >= 0) {
if (ret != 0xff) {
- err("init reg: 0x%02x", ret);
+ pr_err("init reg: 0x%02x\n", ret);
gspca_dev->usb_err = -EIO;
}
}
@@ -349,8 +351,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
gspca_dev->iface,
gspca_dev->alt);
if (ret < 0) {
- err("set intf %d %d failed",
- gspca_dev->iface, gspca_dev->alt);
+ pr_err("set intf %d %d failed\n",
+ gspca_dev->iface, gspca_dev->alt);
gspca_dev->usb_err = ret;
goto out;
}
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c
index e2ef41c..4dcc7e3 100644
--- a/drivers/media/video/gspca/stv0680.c
+++ b/drivers/media/video/gspca/stv0680.c
@@ -27,6 +27,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "stv0680"
#include "gspca.h"
@@ -79,7 +81,7 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
val, 0, gspca_dev->usb_buf, size, 500);
if ((ret < 0) && (req != 0x0a))
- err("usb_control_msg error %i, request = 0x%x, error = %i",
+ pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
set, req, ret);
return ret;
@@ -236,7 +238,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
- err("Could not get descriptor 0100.");
+ pr_err("Could not get descriptor 0100\n");
return stv0680_handle_error(gspca_dev, -EIO);
}
diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile
index 2f3c3a6..5b318fa 100644
--- a/drivers/media/video/gspca/stv06xx/Makefile
+++ b/drivers/media/video/gspca/stv06xx/Makefile
@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \
stv06xx_pb0100.o \
stv06xx_st6422.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index abf1658..b1fca7d 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -27,6 +27,8 @@
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/input.h>
#include "stv06xx_sensor.h"
@@ -189,7 +191,7 @@ int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
STV06XX_URB_MSG_TIMEOUT);
if (err < 0) {
- err("I2C: Read error writing address: %d", err);
+ pr_err("I2C: Read error writing address: %d\n", err);
return err;
}
@@ -213,14 +215,14 @@ static void stv06xx_dump_bridge(struct sd *sd)
int i;
u8 data, buf;
- info("Dumping all stv06xx bridge registers");
+ pr_info("Dumping all stv06xx bridge registers\n");
for (i = 0x1400; i < 0x160f; i++) {
stv06xx_read_bridge(sd, i, &data);
- info("Read 0x%x from address 0x%x", data, i);
+ pr_info("Read 0x%x from address 0x%x\n", data, i);
}
- info("Testing stv06xx bridge registers for writability");
+ pr_info("Testing stv06xx bridge registers for writability\n");
for (i = 0x1400; i < 0x160f; i++) {
stv06xx_read_bridge(sd, i, &data);
buf = data;
@@ -228,12 +230,12 @@ static void stv06xx_dump_bridge(struct sd *sd)
stv06xx_write_bridge(sd, i, 0xff);
stv06xx_read_bridge(sd, i, &data);
if (data == 0xff)
- info("Register 0x%x is read/write", i);
+ pr_info("Register 0x%x is read/write\n", i);
else if (data != buf)
- info("Register 0x%x is read/write,"
- " but only partially", i);
+ pr_info("Register 0x%x is read/write, but only partially\n",
+ i);
else
- info("Register 0x%x is read-only", i);
+ pr_info("Register 0x%x is read-only\n", i);
stv06xx_write_bridge(sd, i, buf);
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h
index e0f63c5..d270a59 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.h
@@ -37,6 +37,8 @@
#define STV_ISOC_ENDPOINT_ADDR 0x81
+#define STV_R 0x0509
+
#define STV_REG23 0x0423
/* Control registers of the STV0600 ASIC */
@@ -61,7 +63,9 @@
/* Refers to the CIF 352x288 and QCIF 176x144 */
/* 1: 288 lines, 2: 144 lines */
-#define STV_Y_CTRL 0x15c3
+#define STV_Y_CTRL 0x15c3
+
+#define STV_RESET 0x1620
/* 0xa: 352 columns, 0x6: 176 columns */
#define STV_X_CTRL 0x1680
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
index b815685..a8698b7 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -28,6 +28,8 @@
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_hdcs.h"
static const struct ctrl hdcs1x00_ctrl[] = {
@@ -428,7 +430,7 @@ static int hdcs_probe_1x00(struct sd *sd)
if (ret < 0 || sensor != 0x08)
return -ENODEV;
- info("HDCS-1000/1100 sensor detected");
+ pr_info("HDCS-1000/1100 sensor detected\n");
sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
@@ -487,7 +489,7 @@ static int hdcs_probe_1020(struct sd *sd)
if (ret < 0 || sensor != 0x10)
return -ENODEV;
- info("HDCS-1020 sensor detected");
+ pr_info("HDCS-1020 sensor detected\n");
sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
@@ -601,11 +603,11 @@ static int hdcs_dump(struct sd *sd)
{
u16 reg, val;
- info("Dumping sensor registers:");
+ pr_info("Dumping sensor registers:\n");
for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
stv06xx_read_sensor(sd, reg, &val);
- info("reg 0x%02x = 0x%02x", reg, val);
+ pr_info("reg 0x%02x = 0x%02x\n", reg, val);
}
return 0;
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
index 75a5b9c..26f14fc 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -44,6 +44,8 @@
* PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_pb0100.h"
static const struct ctrl pb0100_ctrl[] = {
@@ -190,7 +192,7 @@ static int pb0100_probe(struct sd *sd)
if (!sensor_settings)
return -ENOMEM;
- info("Photobit pb0100 sensor detected");
+ pr_info("Photobit pb0100 sensor detected\n");
sd->gspca_dev.cam.cam_mode = pb0100_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
index 8a456de..9940e03 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -26,6 +26,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_st6422.h"
/* controls */
@@ -136,7 +138,7 @@ static int st6422_probe(struct sd *sd)
if (sd->bridge != BRIDGE_ST6422)
return -ENODEV;
- info("st6422 sensor detected");
+ pr_info("st6422 sensor detected\n");
sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
if (!sensor_settings)
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
index f839843..a5c69d9 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
@@ -27,6 +27,8 @@
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_vv6410.h"
static struct v4l2_pix_format vv6410_mode[] = {
@@ -112,7 +114,7 @@ static int vv6410_probe(struct sd *sd)
return -ENODEV;
if (data == 0x19) {
- info("vv6410 sensor detected");
+ pr_info("vv6410 sensor detected\n");
sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
GFP_KERNEL);
@@ -138,18 +140,7 @@ static int vv6410_init(struct sd *sd)
s32 *sensor_settings = sd->sensor_priv;
for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
- /* if NULL then len contains single value */
- if (stv_bridge_init[i].data == NULL) {
- err = stv06xx_write_bridge(sd,
- stv_bridge_init[i].start,
- stv_bridge_init[i].len);
- } else {
- int j;
- for (j = 0; j < stv_bridge_init[i].len; j++)
- err = stv06xx_write_bridge(sd,
- stv_bridge_init[i].start + j,
- stv_bridge_init[i].data[j]);
- }
+ stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
}
if (err < 0)
@@ -183,15 +174,6 @@ static int vv6410_start(struct sd *sd)
struct cam *cam = &sd->gspca_dev.cam;
u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
- if (priv & VV6410_CROP_TO_QVGA) {
- PDEBUG(D_CONF, "Cropping to QVGA");
- stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
- stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
- } else {
- stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
- stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
- }
-
if (priv & VV6410_SUBSAMPLE) {
PDEBUG(D_CONF, "Enabling subsampling");
stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
@@ -201,8 +183,8 @@ static int vv6410_start(struct sd *sd)
} else {
stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
+ stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
- stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
}
/* Turn on LED */
@@ -242,11 +224,11 @@ static int vv6410_dump(struct sd *sd)
u8 i;
int err = 0;
- info("Dumping all vv6410 sensor registers");
+ pr_info("Dumping all vv6410 sensor registers\n");
for (i = 0; i < 0xff && !err; i++) {
u16 data;
err = stv06xx_read_sensor(sd, i, &data);
- info("Register 0x%x contained 0x%x", i, data);
+ pr_info("Register 0x%x contained 0x%x\n", i, data);
}
return (err < 0) ? err : 0;
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
index 7fe3587..a25b887 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -211,49 +211,49 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
/* If NULL, only single value to write, stored in len */
struct stv_init {
- const u8 *data;
- u16 start;
- u8 len;
-};
-
-static const u8 x1500[] = { /* 0x1500 - 0x150f */
- 0x0b, 0xa7, 0xb7, 0x00, 0x00
-};
-
-static const u8 x1536[] = { /* 0x1536 - 0x153b */
- 0x02, 0x00, 0x60, 0x01, 0x20, 0x01
+ u16 addr;
+ u8 data;
};
static const struct stv_init stv_bridge_init[] = {
/* This reg is written twice. Some kind of reset? */
- {NULL, 0x1620, 0x80},
- {NULL, 0x1620, 0x00},
- {NULL, 0x1443, 0x00},
- {NULL, 0x1423, 0x04},
- {x1500, 0x1500, ARRAY_SIZE(x1500)},
- {x1536, 0x1536, ARRAY_SIZE(x1536)},
+ {STV_RESET, 0x80},
+ {STV_RESET, 0x00},
+ {STV_SCAN_RATE, 0x00},
+ {STV_I2C_FLUSH, 0x04},
+ {STV_REG00, 0x0b},
+ {STV_REG01, 0xa7},
+ {STV_REG02, 0xb7},
+ {STV_REG03, 0x00},
+ {STV_REG04, 0x00},
+ {0x1536, 0x02},
+ {0x1537, 0x00},
+ {0x1538, 0x60},
+ {0x1539, 0x01},
+ {0x153a, 0x20},
+ {0x153b, 0x01},
};
static const u8 vv6410_sensor_init[][2] = {
/* Setup registers */
- {VV6410_SETUP0, VV6410_SOFT_RESET},
- {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
+ {VV6410_SETUP0, VV6410_SOFT_RESET},
+ {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
/* Use shuffled read-out mode */
- {VV6410_SETUP1, BIT(6)},
- /* All modes to 1 */
- {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
- {VV6410_PINMAPPING, 0x00},
+ {VV6410_SETUP1, BIT(6)},
+ /* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
+ {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
+ {VV6410_PINMAPPING, 0x00},
/* Pre-clock generator divide off */
- {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
+ {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
- {VV6410_CLKDIV, VV6410_CLK_DIV_2},
+ {VV6410_CLKDIV, VV6410_CLK_DIV_2},
/* System registers */
/* Enable voltage doubler */
- {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
- {VV6410_AT0, 0x00},
+ {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
+ {VV6410_AT0, 0x00},
/* Power up audio, differential */
- {VV6410_AT1, BIT(4)|BIT(0)},
+ {VV6410_AT1, BIT(4) | BIT(0)},
};
#endif
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index b089c0d..c890977 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sunplus"
#include "gspca.h"
@@ -247,7 +249,6 @@ static const struct cmd spca504A_clicksmart420_init_data[] = {
{0x30, 0x0004, 0x000a},
{0xb0, 0x0001, 0x0000},
-
{0xa1, 0x0080, 0x0001},
{0x30, 0x0049, 0x0000},
{0x30, 0x0060, 0x0005},
@@ -256,8 +257,6 @@ static const struct cmd spca504A_clicksmart420_init_data[] = {
{0x00, 0x0000, 0x2000},
{0x00, 0x0013, 0x2301},
{0x00, 0x0003, 0x2000},
- {0x00, 0x0000, 0x2000},
-
};
/* clicksmart 420 open data ? */
@@ -328,7 +327,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -343,7 +342,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
len ? gspca_dev->usb_buf : NULL, len,
500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -368,7 +367,7 @@ static void reg_w_1(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w_1 err %d", ret);
+ pr_err("reg_w_1 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -388,7 +387,7 @@ static void reg_w_riv(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, NULL, 0, 500);
if (ret < 0) {
- err("reg_w_riv err %d", ret);
+ pr_err("reg_w_riv err %d\n", ret);
gspca_dev->usb_err = ret;
return;
}
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index 7e762d5..90f0877 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -26,6 +26,8 @@
* Costantino Leandro
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "t613"
#include <linux/slab.h>
@@ -572,7 +574,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
if (!tmpbuf) {
- err("Out of memory");
+ pr_err("Out of memory\n");
return;
}
usb_control_msg(gspca_dev->dev,
@@ -598,7 +600,7 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
} else {
p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
if (!tmpbuf) {
- err("Out of memory");
+ pr_err("Out of memory\n");
return;
}
}
@@ -652,7 +654,7 @@ static void om6802_sensor_init(struct gspca_dev *gspca_dev)
}
byte = reg_r(gspca_dev, 0x0063);
if (byte != 0x17) {
- err("Bad sensor reset %02x", byte);
+ pr_err("Bad sensor reset %02x\n", byte);
/* continue? */
}
@@ -890,7 +892,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
sd->sensor = SENSOR_OM6802;
break;
default:
- err("unknown sensor %04x", sensor_id);
+ pr_err("unknown sensor %04x\n", sensor_id);
return -EINVAL;
}
@@ -905,7 +907,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
break; /* OK */
}
if (i < 0) {
- err("Bad sensor reset %02x", test_byte);
+ pr_err("Bad sensor reset %02x\n", test_byte);
return -EIO;
}
reg_w_buf(gspca_dev, n2, sizeof n2);
@@ -1387,7 +1389,7 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
return 0;
case V4L2_CID_EFFECTS:
if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
- strncpy((char *) menu->name,
+ strlcpy((char *) menu->name,
effects_control[menu->index],
sizeof menu->name);
return 0;
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index 6caed73..7ee2c82 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "vc032x"
#include "gspca.h"
@@ -3169,7 +3171,7 @@ static void reg_r_i(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -3210,7 +3212,7 @@ static void reg_w_i(struct gspca_dev *gspca_dev,
value, index, NULL, 0,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -3235,8 +3237,7 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev,
reg_r(gspca_dev, 0xa1, 0xb33f, 1);
if (!(gspca_dev->usb_buf[0] & 0x02)) {
- err("I2c Bus Busy Wait %02x",
- gspca_dev->usb_buf[0]);
+ pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
return 0;
}
reg_w(gspca_dev, 0xa0, address, 0xb33a);
@@ -3349,7 +3350,7 @@ static void i2c_write(struct gspca_dev *gspca_dev,
msleep(20);
} while (--retry > 0);
if (retry <= 0)
- err("i2c_write timeout");
+ pr_err("i2c_write timeout\n");
}
static void put_tab_to_reg(struct gspca_dev *gspca_dev,
@@ -3446,7 +3447,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
switch (sensor) {
case -1:
- err("Unknown sensor...");
+ pr_err("Unknown sensor...\n");
return -EINVAL;
case SENSOR_HV7131R:
PDEBUG(D_PROBE, "Find Sensor HV7131R");
diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c
index 84dfbab..81dd4c9 100644
--- a/drivers/media/video/gspca/vicam.c
+++ b/drivers/media/video/gspca/vicam.c
@@ -26,6 +26,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "vicam"
#define HEADER_SIZE 64
@@ -117,7 +119,7 @@ static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, data, len, 1000);
if (ret < 0)
- err("control msg req %02X error %d", request, ret);
+ pr_err("control msg req %02X error %d\n", request, ret);
return ret;
}
@@ -189,8 +191,8 @@ static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
data, size, &act_len, 10000);
/* successful, it returns 0, otherwise negative */
if (ret < 0 || act_len != size) {
- err("bulk read fail (%d) len %d/%d",
- ret, act_len, size);
+ pr_err("bulk read fail (%d) len %d/%d\n",
+ ret, act_len, size);
return -EIO;
}
return 0;
@@ -216,7 +218,7 @@ static void vicam_dostream(struct work_struct *work)
HEADER_SIZE;
buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
if (!buffer) {
- err("Couldn't allocate USB buffer");
+ pr_err("Couldn't allocate USB buffer\n");
goto exit;
}
@@ -269,7 +271,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
ret = request_ihex_firmware(&fw, "vicam/firmware.fw",
&gspca_dev->dev->dev);
if (ret) {
- err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
+ pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c
index 4a9e622..27d2cef 100644
--- a/drivers/media/video/gspca/w996Xcf.c
+++ b/drivers/media/video/gspca/w996Xcf.c
@@ -31,6 +31,8 @@
the sensor drivers to v4l2 sub drivers, and properly split of this
driver from ov519.c */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */
#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
@@ -81,7 +83,7 @@ static void w9968cf_write_fsb(struct sd *sd, u16* data)
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
if (ret < 0) {
- err("Write FSB registers failed (%d)", ret);
+ pr_err("Write FSB registers failed (%d)\n", ret);
sd->gspca_dev.usb_err = ret;
}
}
@@ -108,7 +110,7 @@ static void w9968cf_write_sb(struct sd *sd, u16 value)
udelay(W9968CF_I2C_BUS_DELAY);
if (ret < 0) {
- err("Write SB reg [01] %04x failed", value);
+ pr_err("Write SB reg [01] %04x failed\n", value);
sd->gspca_dev.usb_err = ret;
}
}
@@ -135,7 +137,7 @@ static int w9968cf_read_sb(struct sd *sd)
ret = sd->gspca_dev.usb_buf[0] |
(sd->gspca_dev.usb_buf[1] << 8);
} else {
- err("Read SB reg [01] failed");
+ pr_err("Read SB reg [01] failed\n");
sd->gspca_dev.usb_err = ret;
}
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index c089a0f..3aed42a 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -27,6 +27,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "xirlink-cit"
#include <linux/input.h>
@@ -800,8 +802,8 @@ static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
value, index, NULL, 0, 1000);
if (err < 0)
- err("Failed to write a register (index 0x%04X,"
- " value 0x%02X, error %d)", index, value, err);
+ pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+ index, value, err);
return 0;
}
@@ -816,8 +818,8 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
0x00, index, buf, 8, 1000);
if (res < 0) {
- err("Failed to read a register (index 0x%04X, error %d)",
- index, res);
+ pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+ index, res);
return res;
}
@@ -1587,7 +1589,7 @@ static int cit_get_packet_size(struct gspca_dev *gspca_dev)
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
return -EIO;
}
@@ -2824,7 +2826,7 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev)
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
if (ret < 0)
- err("set alt 1 err %d", ret);
+ pr_err("set alt 1 err %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 61cdd56..30ea1e4 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "zc3xx"
#include <linux/input.h>
@@ -5666,7 +5668,7 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_r_i err %d", ret);
+ pr_err("reg_r_i err %d\n", ret);
gspca_dev->usb_err = ret;
return 0;
}
@@ -5698,7 +5700,7 @@ static void reg_w_i(struct gspca_dev *gspca_dev,
value, index, NULL, 0,
500);
if (ret < 0) {
- err("reg_w_i err %d", ret);
+ pr_err("reg_w_i err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -5724,7 +5726,7 @@ static u16 i2c_read(struct gspca_dev *gspca_dev,
msleep(20);
retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
if (retbyte != 0x00)
- err("i2c_r status error %02x", retbyte);
+ pr_err("i2c_r status error %02x\n", retbyte);
retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */
retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */
PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
@@ -5748,7 +5750,7 @@ static u8 i2c_write(struct gspca_dev *gspca_dev,
msleep(1);
retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
if (retbyte != 0x00)
- err("i2c_w status error %02x", retbyte);
+ pr_err("i2c_w status error %02x\n", retbyte);
PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)",
reg, valH, valL, retbyte);
return retbyte;
@@ -6497,7 +6499,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor GC0303");
break;
default:
- warn("Unknown sensor - set to TAS5130C");
+ pr_warn("Unknown sensor - set to TAS5130C\n");
sd->sensor = SENSOR_TAS5130C;
}
break;
@@ -6603,7 +6605,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
sd->sensor = SENSOR_OV7620; /* same sensor (?) */
break;
default:
- err("Unknown sensor %04x", sensor);
+ pr_err("Unknown sensor %04x\n", sensor);
return -EINVAL;
}
}
@@ -6970,6 +6972,7 @@ static const struct sd_desc sd_desc = {
};
static const struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x03f0, 0x1b07)},
{USB_DEVICE(0x041e, 0x041e)},
{USB_DEVICE(0x041e, 0x4017)},
{USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile
index 3baa9f6..52f057f 100644
--- a/drivers/media/video/hdpvr/Makefile
+++ b/drivers/media/video/hdpvr/Makefile
@@ -2,6 +2,6 @@ hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index a27d93b..060353e 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -17,7 +17,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/usb.h>
#include <linux/mutex.h>
#include <linux/i2c.h>
@@ -297,6 +297,11 @@ static int hdpvr_probe(struct usb_interface *interface,
dev->workqueue = 0;
+ /* init video transfer queues first of all */
+ /* to prevent oops in hdpvr_delete() on error paths */
+ INIT_LIST_HEAD(&dev->free_buff_list);
+ INIT_LIST_HEAD(&dev->rec_buff_list);
+
/* register v4l2_device early so it can be used for printks */
if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
err("v4l2_device_register failed");
@@ -319,10 +324,6 @@ static int hdpvr_probe(struct usb_interface *interface,
if (!dev->workqueue)
goto error;
- /* init video transfer queues */
- INIT_LIST_HEAD(&dev->free_buff_list);
- INIT_LIST_HEAD(&dev->rec_buff_list);
-
dev->options = hdpvr_default_options;
if (default_video_input < HDPVR_VIDEO_INPUTS)
@@ -373,12 +374,6 @@ static int hdpvr_probe(struct usb_interface *interface,
}
mutex_unlock(&dev->io_mutex);
- if (hdpvr_register_videodev(dev, &interface->dev,
- video_nr[atomic_inc_return(&dev_nr)])) {
- v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
- goto error;
- }
-
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
retval = hdpvr_register_i2c_adapter(dev);
if (retval < 0) {
@@ -399,6 +394,13 @@ static int hdpvr_probe(struct usb_interface *interface,
}
#endif
+ retval = hdpvr_register_videodev(dev, &interface->dev,
+ video_nr[atomic_inc_return(&dev_nr)]);
+ if (retval < 0) {
+ v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
+ goto reg_fail;
+ }
+
/* let the user know what node this device is now attached to */
v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
video_device_node_name(dev->video_dev));
@@ -474,5 +476,6 @@ module_init(hdpvr_init);
module_exit(hdpvr_exit);
MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2.1");
MODULE_AUTHOR("Janne Grunau");
MODULE_DESCRIPTION("Hauppauge HD PVR driver");
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
index 2a1ac28..82e819f 100644
--- a/drivers/media/video/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "hdpvr.h"
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index 4c0394a..41fd57b 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -17,7 +17,6 @@
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/mutex.h>
-#include <linux/version.h>
#include <linux/workqueue.h>
#include <linux/videodev2.h>
@@ -575,7 +574,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strcpy(cap->driver, "hdpvr");
strcpy(cap->card, "Hauppauge HD PVR");
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->version = HDPVR_VERSION;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_AUDIO |
V4L2_CAP_READWRITE;
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h
index 072f23c..d6439db 100644
--- a/drivers/media/video/hdpvr/hdpvr.h
+++ b/drivers/media/video/hdpvr/hdpvr.h
@@ -18,12 +18,6 @@
#include <media/v4l2-device.h>
#include <media/ir-kbd-i2c.h>
-#define HDPVR_MAJOR_VERSION 0
-#define HDPVR_MINOR_VERSION 2
-#define HDPVR_RELEASE 0
-#define HDPVR_VERSION \
- KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE)
-
#define HDPVR_MAX 8
#define HDPVR_I2C_MAX_SIZE 128
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile
index 26ce0d6..71ab76a 100644
--- a/drivers/media/video/ivtv/Makefile
+++ b/drivers/media/video/ivtv/Makefile
@@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \
obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 0fb7552..41108a9 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -1180,6 +1180,8 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
setup.addr = ADDR_UNSET;
setup.type = itv->options.tuner;
setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
+ if (itv->options.radio > 0)
+ setup.mode_mask |= T_RADIO;
setup.tuner_callback = (setup.type == TUNER_XC2028) ?
ivtv_reset_tuner_gpio : NULL;
ivtv_call_all(itv, tuner, s_type_addr, &setup);
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 84bdf0f..8f9cc17 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -36,7 +36,6 @@
* using information provided by Jiun-Kuei Jung @ AVerMedia.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index a7f54b0..38f0522 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -722,8 +722,8 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
/* If there are subscribed events, then only use the new event
API instead of the old video.h based API. */
- if (!list_empty(&id->fh.events->subscribed)) {
- poll_wait(filp, &id->fh.events->wait, wait);
+ if (!list_empty(&id->fh.subscribed)) {
+ poll_wait(filp, &id->fh.wait, wait);
/* Turn off the old-style vsync events */
clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
if (v4l2_event_pending(&id->fh))
@@ -750,6 +750,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
struct ivtv *itv = id->itv;
struct ivtv_stream *s = &itv->streams[id->type];
int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+ unsigned res = 0;
/* Start a capture if there is none */
if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
@@ -769,12 +770,16 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
/* add stream's waitq to the poll list */
IVTV_DEBUG_HI_FILE("Encoder poll\n");
poll_wait(filp, &s->waitq, wait);
+ if (v4l2_event_pending(&id->fh))
+ res |= POLLPRI;
+ else
+ poll_wait(filp, &id->fh.wait, wait);
if (s->q_full.length || s->q_io.length)
- return POLLIN | POLLRDNORM;
+ return res | POLLIN | POLLRDNORM;
if (eof)
- return POLLHUP;
- return 0;
+ return res | POLLHUP;
+ return res;
}
void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
@@ -961,10 +966,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
return -ENOMEM;
}
v4l2_fh_init(&item->fh, s->vdev);
- if (s->type == IVTV_DEC_STREAM_TYPE_YUV ||
- s->type == IVTV_DEC_STREAM_TYPE_MPG) {
- res = v4l2_event_alloc(&item->fh, 60);
- }
if (res < 0) {
v4l2_fh_exit(&item->fh);
kfree(item);
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 120c7d8..ecafa69 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -757,7 +757,6 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
- vcap->version = IVTV_DRIVER_VERSION; /* version */
vcap->capabilities = itv->v4l2_cap; /* capabilities */
return 0;
}
@@ -1204,9 +1203,7 @@ static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced
cap->service_lines[f][l] = set;
}
}
- return 0;
- }
- if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+ } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
return -EINVAL;
if (itv->is_60hz) {
@@ -1216,9 +1213,16 @@ static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced
cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
cap->service_lines[0][16] = V4L2_SLICED_VPS;
}
- return 0;
+ } else {
+ return -EINVAL;
}
- return -EINVAL;
+
+ set = 0;
+ for (f = 0; f < 2; f++)
+ for (l = 0; l < 24; l++)
+ set |= cap->service_lines[f][l];
+ cap->service_set = set;
+ return 0;
}
static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
@@ -1451,11 +1455,11 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti
switch (sub->type) {
case V4L2_EVENT_VSYNC:
case V4L2_EVENT_EOS:
- break;
+ case V4L2_EVENT_CTRL:
+ return v4l2_event_subscribe(fh, sub, 0);
default:
return -EINVAL;
}
- return v4l2_event_subscribe(fh, sub);
}
static int ivtv_log_status(struct file *file, void *fh)
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h
index b67a404..a20f346 100644
--- a/drivers/media/video/ivtv/ivtv-version.h
+++ b/drivers/media/video/ivtv/ivtv-version.h
@@ -21,11 +21,6 @@
#define IVTV_VERSION_H
#define IVTV_DRIVER_NAME "ivtv"
-#define IVTV_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 4
-#define IVTV_DRIVER_VERSION_PATCHLEVEL 2
-
-#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
-#define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
+#define IVTV_VERSION "1.4.3"
#endif
diff --git a/drivers/media/video/m5mols/Kconfig b/drivers/media/video/m5mols/Kconfig
index ddb3314..302dc3d 100644
--- a/drivers/media/video/m5mols/Kconfig
+++ b/drivers/media/video/m5mols/Kconfig
@@ -1,6 +1,5 @@
config VIDEO_M5MOLS
tristate "Fujitsu M-5MOLS 8MP sensor support"
- depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API &&\
- (VIDEO_S5P_MIPI_CSIS || VIDEO_EXYNOS_MIPI_CSIS)
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---help---
This driver supports Fujitsu M-5MOLS camera sensor with ISP
diff --git a/drivers/media/video/m5mols/Makefile b/drivers/media/video/m5mols/Makefile
index b5d19bf..0a44e02 100644
--- a/drivers/media/video/m5mols/Makefile
+++ b/drivers/media/video/m5mols/Makefile
@@ -1,3 +1,3 @@
-m5mols-objs := m5mols_core.o m5mols_controls.o
+m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h
index 94022e2..82c8817 100644
--- a/drivers/media/video/m5mols/m5mols.h
+++ b/drivers/media/video/m5mols/m5mols.h
@@ -1,5 +1,5 @@
/*
- * Header for M5MOLS 8M Pixel camera sensor with ISP
+ * Header for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -19,24 +19,12 @@
#include <media/v4l2-subdev.h>
#include "m5mols_reg.h"
-#define M5MO_JPEG_MAXSIZE 0x3A0000
-#define M5MO_THUMB_MAXSIZE 0xFC00
-#define M5MO_POST_MAXSIZE 0xBB800
-#define M5MO_JPEG_MEMSIZE M5MO_JPEG_MAXSIZE + M5MO_THUMB_MAXSIZE + M5MO_POST_MAXSIZE
-
-#define v4l2msg(fmt, arg...) do { \
- v4l2_dbg(1, m5mols_debug, &info->sd, fmt, ## arg); \
-} while (0)
-
extern int m5mols_debug;
-enum m5mols_mode {
- MODE_SYSINIT,
- MODE_PARMSET,
- MODE_MONITOR,
- MODE_CAPTURE,
- MODE_UNKNOWN,
-};
+#define to_m5mols(__sd) container_of(__sd, struct m5mols_info, sd)
+
+#define to_sd(__ctrl) \
+ (&container_of(__ctrl->handler, struct m5mols_info, handle)->sd)
enum m5mols_restype {
M5MOLS_RESTYPE_MONITOR,
@@ -44,341 +32,264 @@ enum m5mols_restype {
M5MOLS_RESTYPE_MAX,
};
-enum m5mols_status {
- STATUS_SYSINIT,
- STATUS_PARMSET,
- STATUS_MONITOR,
- STATUS_AUTO_FOCUS,
- STATUS_FACE_DETECTION,
- STATUS_DUAL_CAPTURE,
- STATUS_SINGLE_CAPTURE,
- STATUS_PREVIEW,
- STATUS_UNKNOWN,
-};
-
-enum m5mols_intterrupt_bit {
- INT_BIT_MODE,
- INT_BIT_AF,
- INT_BIT_ZOOM,
- INT_BIT_CAPTURE,
- INT_BIT_FRAME_SYNC,
- INT_BIT_FD,
- INT_BIT_LENS_INIT,
- INT_BIT_SOUND,
-};
-
-enum m5mols_i2c_size {
- I2C_8BIT = 1,
- I2C_16BIT = 2,
- I2C_32BIT = 4,
- I2C_MAX = 4,
-};
-
-enum m5mols_fps {
- M5MOLS_FPS_AUTO = 0,
- M5MOLS_FPS_10 = 10,
- M5MOLS_FPS_12 = 12,
- M5MOLS_FPS_15 = 15,
- M5MOLS_FPS_20 = 20,
- M5MOLS_FPS_21 = 21,
- M5MOLS_FPS_22 = 22,
- M5MOLS_FPS_23 = 23,
- M5MOLS_FPS_24 = 24,
- M5MOLS_FPS_30 = 30,
- M5MOLS_FPS_MAX = M5MOLS_FPS_30,
-};
-
-enum m5mols_res_type {
- M5MOLS_RES_MON,
- /* It's not supported below yet. */
- M5MOLS_RES_CAPTURE,
- M5MOLS_RES_MAX,
-};
-
+/**
+ * struct m5mols_resolution - structure for the resolution
+ * @type: resolution type according to the pixel code
+ * @width: width of the resolution
+ * @height: height of the resolution
+ * @reg: resolution preset register value
+ */
struct m5mols_resolution {
- u8 value;
- enum m5mols_res_type type;
- u16 width;
- u16 height;
-};
-
-struct m5mols_format {
- enum v4l2_mbus_pixelcode code;
- enum v4l2_colorspace colorspace;
-};
-
-struct m5mols_control {
- u32 id;
- s32 min;
- s32 max;
- u32 step;
- s32 def;
+ u8 reg;
+ enum m5mols_restype type;
+ u16 width;
+ u16 height;
};
+/**
+ * struct m5mols_exif - structure for the EXIF information of M-5MOLS
+ * @exposure_time: exposure time register value
+ * @shutter_speed: speed of the shutter register value
+ * @aperture: aperture register value
+ * @exposure_bias: it calls also EV bias
+ * @iso_speed: ISO register value
+ * @flash: status register value of the flash
+ * @sdr: status register value of the Subject Distance Range
+ * @qval: not written exact meaning in document
+ */
struct m5mols_exif {
- u32 exposure_time;
- u32 shutter_speed;
- u32 aperture;
- u32 brightness;
- u32 exposure_bias;
- u16 iso_speed;
- u16 flash;
- u16 sdr; /* subject(object) distance range */
- u16 qval; /* This is not written precisely in datasheet. */
+ u32 exposure_time;
+ u32 shutter_speed;
+ u32 aperture;
+ u32 brightness;
+ u32 exposure_bias;
+ u16 iso_speed;
+ u16 flash;
+ u16 sdr;
+ u16 qval;
};
+/**
+ * struct m5mols_capture - Structure for the capture capability
+ * @exif: EXIF information
+ * @main: size in bytes of the main image
+ * @thumb: size in bytes of the thumb image, if it was accompanied
+ * @total: total size in bytes of the produced image
+ */
struct m5mols_capture {
- struct m5mols_exif exif;
- u32 main;
- u32 thumb;
- u32 total;
+ struct m5mols_exif exif;
+ u32 main;
+ u32 thumb;
+ u32 total;
+};
+
+/**
+ * struct m5mols_scenemode - structure for the scenemode capability
+ * @metering: metering light register value
+ * @ev_bias: EV bias register value
+ * @wb_mode: mode which means the WhiteBalance is Auto or Manual
+ * @wb_preset: whitebalance preset register value in the Manual mode
+ * @chroma_en: register value whether the Chroma capability is enabled or not
+ * @chroma_lvl: chroma's level register value
+ * @edge_en: register value Whether the Edge capability is enabled or not
+ * @edge_lvl: edge's level register value
+ * @af_range: Auto Focus's range
+ * @fd_mode: Face Detection mode
+ * @mcc: Multi-axis Color Conversion which means emotion color
+ * @light: status of the Light
+ * @flash: status of the Flash
+ * @tone: Tone color which means Contrast
+ * @iso: ISO register value
+ * @capt_mode: Mode of the Image Stabilization while the camera capturing
+ * @wdr: Wide Dynamic Range register value
+ *
+ * The each value according to each scenemode is recommended in the documents.
+ */
+struct m5mols_scenemode {
+ u8 metering;
+ u8 ev_bias;
+ u8 wb_mode;
+ u8 wb_preset;
+ u8 chroma_en;
+ u8 chroma_lvl;
+ u8 edge_en;
+ u8 edge_lvl;
+ u8 af_range;
+ u8 fd_mode;
+ u8 mcc;
+ u8 light;
+ u8 flash;
+ u8 tone;
+ u8 iso;
+ u8 capt_mode;
+ u8 wdr;
};
+/**
+ * struct m5mols_version - firmware version information
+ * @customer: customer information
+ * @project: version of project information according to customer
+ * @fw: firmware revision
+ * @hw: hardware revision
+ * @param: version of the parameter
+ * @awb: Auto WhiteBalance algorithm version
+ * @str: information about manufacturer and packaging vendor
+ * @af: Auto Focus version
+ *
+ * The register offset starts the customer version at 0x0, and it ends
+ * the awb version at 0x09. The customer, project information occupies 1 bytes
+ * each. And also the fw, hw, param, awb each requires 2 bytes. The str is
+ * unique string associated with firmware's version. It includes information
+ * about manufacturer and the vendor of the sensor's packaging. The least
+ * significant 2 bytes of the string indicate packaging manufacturer.
+ */
+#define VERSION_STRING_SIZE 22
struct m5mols_version {
- u8 ctm_code; /* customer code */
- u8 pj_code; /* project code */
- u16 fw; /* firmware version */
- u16 hw; /* hardware version */
- u16 parm; /* parameter version */
- u16 awb; /* AWB version */
+ u8 customer;
+ u8 project;
+ u16 fw;
+ u16 hw;
+ u16 param;
+ u16 awb;
+ u8 str[VERSION_STRING_SIZE];
+ u8 af;
};
+/**
+ * struct m5mols_info - M-5MOLS driver data structure
+ * @pdata: platform data
+ * @sd: v4l-subdev instance
+ * @pad: media pad
+ * @ffmt: current fmt according to resolution type
+ * @res_type: current resolution type
+ * @irq_waitq: waitqueue for the capture
+ * @work_irq: workqueue for the IRQ
+ * @flags: state variable for the interrupt handler
+ * @handle: control handler
+ * @autoexposure: Auto Exposure control
+ * @exposure: Exposure control
+ * @autowb: Auto White Balance control
+ * @colorfx: Color effect control
+ * @saturation: Saturation control
+ * @zoom: Zoom control
+ * @ver: information of the version
+ * @cap: the capture mode attributes
+ * @power: current sensor's power status
+ * @ctrl_sync: true means all controls of the sensor are initialized
+ * @int_capture: true means the capture interrupt is issued once
+ * @lock_ae: true means the Auto Exposure is locked
+ * @lock_awb: true means the Aut WhiteBalance is locked
+ * @resolution: register value for current resolution
+ * @interrupt: register value for current interrupt status
+ * @mode: register value for current operation mode
+ * @mode_save: register value for current operation mode for saving
+ * @set_power: optional power callback to the board code
+ */
struct m5mols_info {
- struct v4l2_subdev sd;
+ const struct m5mols_platform_data *pdata;
+ struct v4l2_subdev sd;
struct media_pad pad;
+ struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
int res_type;
- u8 resolution;
- struct v4l2_mbus_framefmt fmt[M5MOLS_RES_MAX];
- struct v4l2_fract tpf;
+ wait_queue_head_t irq_waitq;
+ struct work_struct work_irq;
+ unsigned long flags;
- struct v4l2_ctrl_handler handle;
+ struct v4l2_ctrl_handler handle;
+ /* Autoexposure/exposure control cluster */
struct {
- /* support only AE of the Monitor Mode in this version */
- struct v4l2_ctrl *autoexposure;
- struct v4l2_ctrl *exposure;
- bool is_ae_lock;
+ struct v4l2_ctrl *autoexposure;
+ struct v4l2_ctrl *exposure;
};
- struct v4l2_ctrl *autofocus;
- bool is_focus;
- struct v4l2_ctrl *autowb;
- bool is_awb_lock;
- struct v4l2_ctrl *colorfx;
- struct v4l2_ctrl *saturation;
- struct v4l2_ctrl *zoom;
- struct v4l2_ctrl *jpeg_size;
- struct v4l2_ctrl *encoded_size;
-
- enum m5mols_mode mode;
- enum m5mols_mode mode_backup;
- enum m5mols_status status;
- enum v4l2_mbus_pixelcode code;
-
- struct m5mols_capture cap;
- wait_queue_head_t cap_wait;
- bool captured;
-
- const struct m5mols_platform_data *pdata;
- struct m5mols_version ver;
- struct work_struct work;
- bool power;
-
- /* for additional power if needed. */
+ struct v4l2_ctrl *autowb;
+ struct v4l2_ctrl *colorfx;
+ struct v4l2_ctrl *saturation;
+ struct v4l2_ctrl *zoom;
+
+ struct m5mols_version ver;
+ struct m5mols_capture cap;
+ bool power;
+ bool ctrl_sync;
+ bool lock_ae;
+ bool lock_awb;
+ u8 resolution;
+ u8 interrupt;
+ u8 mode;
+ u8 mode_save;
int (*set_power)(struct device *dev, int on);
};
-/* control functions */
-int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
-
-/* I2C functions - referenced by below I2C helper functions */
-int m5mols_read_reg(struct v4l2_subdev *sd, enum m5mols_i2c_size size,
- u8 category, u8 cmd, u32 *val);
-int m5mols_write_reg(struct v4l2_subdev *sd, enum m5mols_i2c_size size,
- u8 category, u8 cmd, u32 val);
-int m5mols_check_busy(struct v4l2_subdev *sd,
- u8 category, u8 cmd, u32 value);
-int m5mols_set_mode(struct v4l2_subdev *sd, enum m5mols_mode mode);
-enum m5mols_status m5mols_get_status(struct v4l2_subdev *sd);
+#define ST_CAPT_IRQ 0
+#define is_powered(__info) (__info->power)
+#define is_ctrl_synced(__info) (__info->ctrl_sync)
+#define is_available_af(__info) (__info->ver.af)
+#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
+#define is_manufacturer(__info, __manufacturer) \
+ (__info->ver.str[0] == __manufacturer[0] && \
+ __info->ver.str[1] == __manufacturer[1])
/*
- * helper functions
+ * I2C operation of the M-5MOLS
+ *
+ * The I2C read operation of the M-5MOLS requires 2 messages. The first
+ * message sends the information about the command, command category, and total
+ * message size. The second message is used to retrieve the data specifed in
+ * the first message
+ *
+ * 1st message 2nd message
+ * +-------+---+----------+-----+-------+ +------+------+------+------+
+ * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] |
+ * +-------+---+----------+-----+-------+ +------+------+------+------+
+ * - size1: message data size(5 in this case)
+ * - size2: desired buffer size of the 2nd message
+ * - d[0..3]: according to size2
+ *
+ * The I2C write operation needs just one message. The message includes
+ * category, command, total size, and desired data.
+ *
+ * 1st message
+ * +-------+---+----------+-----+------+------+------+------+
+ * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] |
+ * +-------+---+----------+-----+------+------+------+------+
+ * - d[0..3]: according to size1
*/
-static inline struct m5mols_info *to_m5mols(struct v4l2_subdev *sd)
-{
- return container_of(sd, struct m5mols_info, sd);
-}
-
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
- return &container_of(ctrl->handler, struct m5mols_info, handle)->sd;
-}
-
-static inline bool is_streaming(struct v4l2_subdev *sd)
-{
- struct m5mols_info *info = to_m5mols(sd);
- return (info->mode == MODE_MONITOR) || (info->mode == MODE_CAPTURE);
-}
-
-static inline bool is_stoped(struct v4l2_subdev *sd)
-{
- struct m5mols_info *info = to_m5mols(sd);
- return (info->mode != MODE_MONITOR) && (info->mode != MODE_CAPTURE);
-}
-
-static inline bool is_powerup(struct v4l2_subdev *sd)
-{
- struct m5mols_info *info = to_m5mols(sd);
- return info->power;
-}
-
-static inline int m5mols_set_mode_backup(struct v4l2_subdev *sd,
- enum m5mols_mode mode)
-{
- struct m5mols_info *info = to_m5mols(sd);
-
- info->mode_backup = info->mode;
- return m5mols_set_mode(sd, mode);
-}
-
-static inline int m5mols_set_mode_restore(struct v4l2_subdev *sd)
-{
- struct m5mols_info *info = to_m5mols(sd);
- int ret;
-
- ret = m5mols_set_mode(sd, info->mode_backup);
- if (!ret)
- info->mode = info->mode_backup;
- return ret;
-}
-
-static inline int __must_check i2c_w8_system(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_SYSTEM, cmd, val);
-}
-
-static inline int __must_check i2c_w8_param(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_PARAM, cmd, val);
-}
-
-static inline int __must_check i2c_w8_mon(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_MON, cmd, val);
-}
-
-static inline int __must_check i2c_w8_ae(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_AE, cmd, val);
-}
-
-static inline int __must_check i2c_w16_ae(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_16BIT, CAT_AE, cmd, val);
-}
-
-static inline int __must_check i2c_w8_wb(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_WB, cmd, val);
-}
-
-static inline int __must_check i2c_w8_lens(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_LENS, cmd, val);
-}
-
-static inline int __must_check i2c_w8_capt_parm(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_CAPTURE_PARAMETER, cmd, val);
-}
-
-static inline int __must_check i2c_w8_capt_ctrl(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_CAPTURE_CONTROL, cmd, val);
-}
+int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
+int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
+int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
+int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
+int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
-static inline int __must_check i2c_w8_flash(struct v4l2_subdev *sd,
- u8 cmd, u32 val)
-{
- return m5mols_write_reg(sd, I2C_8BIT, CAT_FLASH, cmd, val);
-}
-
-static inline int __must_check i2c_r8_system(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_8BIT, CAT_SYSTEM, cmd, val);
-}
-
-static inline int __must_check i2c_r8_param(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_8BIT, CAT_PARAM, cmd, val);
-}
-
-static inline int __must_check i2c_r8_mon(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_8BIT, CAT_MON, cmd, val);
-}
-
-static inline int __must_check i2c_r8_ae(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_8BIT, CAT_AE, cmd, val);
-}
-
-static inline int __must_check i2c_r16_ae(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_16BIT, CAT_AE, cmd, val);
-}
-
-static inline int __must_check i2c_r8_lens(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_8BIT, CAT_LENS, cmd, val);
-}
-
-static inline int __must_check i2c_r32_capt_ctrl(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_32BIT, CAT_CAPTURE_CONTROL, cmd, val);
-}
-
-static inline int __must_check i2c_r16_exif(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_16BIT, CAT_EXIF, cmd, val);
-}
-
-static inline int __must_check i2c_r32_exif(struct v4l2_subdev *sd,
- u8 cmd, u32 *val)
-{
- return m5mols_read_reg(sd, I2C_32BIT, CAT_EXIF, cmd, val);
-}
-
-static int m5mols_set_ae_lock(struct m5mols_info *info, bool lock)
-{
- struct v4l2_subdev *sd = &info->sd;
-
- info->is_ae_lock = lock;
-
- return i2c_w8_ae(sd, CAT3_AE_LOCK, !!lock);
-}
+/*
+ * Mode operation of the M-5MOLS
+ *
+ * Changing the mode of the M-5MOLS is needed right executing order.
+ * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed
+ * by user. There are various categories associated with each mode.
+ *
+ * +============================================================+
+ * | mode | category |
+ * +============================================================+
+ * | FLASH | FLASH(only after Stand-by or Power-on) |
+ * | SYSTEM | SYSTEM(only after sensor arm-booting) |
+ * | PARAMETER | PARAMETER |
+ * | MONITOR | MONITOR(preview), Auto Focus, Face Detection |
+ * | CAPTURE | Single CAPTURE, Preview(recording) |
+ * +============================================================+
+ *
+ * The available executing order between each modes are as follows:
+ * PARAMETER <---> MONITOR <---> CAPTURE
+ */
+int m5mols_mode(struct m5mols_info *info, u8 mode);
-static int m5mols_set_awb_lock(struct m5mols_info *info, bool lock)
-{
- struct v4l2_subdev *sd = &info->sd;
+int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
+int m5mols_sync_controls(struct m5mols_info *info);
+int m5mols_start_capture(struct m5mols_info *info);
+int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
+int m5mols_lock_3a(struct m5mols_info *info, bool lock);
+int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
- info->is_awb_lock = lock;
+/* The firmware function */
+int m5mols_update_fw(struct v4l2_subdev *sd,
+ int (*set_power)(struct m5mols_info *, bool));
- return i2c_w8_wb(sd, CAT6_AWB_LOCK, !!lock);
-}
#endif /* M5MOLS_H */
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c
index d947192..3248ac8 100644
--- a/drivers/media/video/m5mols/m5mols_capture.c
+++ b/drivers/media/video/m5mols/m5mols_capture.c
@@ -18,11 +18,9 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/videodev2.h>
-#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c
index 3e08018..d135d20 100644
--- a/drivers/media/video/m5mols/m5mols_controls.c
+++ b/drivers/media/video/m5mols/m5mols_controls.c
@@ -1,5 +1,5 @@
/*
- * Controls for M5MOLS 8M Pixel camera sensor with ISP
+ * Controls for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -14,186 +14,285 @@
*/
#include <linux/i2c.h>
+#include <linux/delay.h>
#include <linux/videodev2.h>
#include <media/v4l2-ctrls.h>
#include "m5mols.h"
#include "m5mols_reg.h"
-static int m5mols_wb_mode(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
-{
- struct v4l2_subdev *sd = &info->sd;
- int ret;
-
- if (info->is_awb_lock) {
- ret = m5mols_set_awb_lock(info, false);
- if (!ret)
- return ret;
- }
-
- /* 0x01 : Auto Whitebalance, 0x02 : Manual Whitebalance. */
- return i2c_w8_wb(sd, CAT6_AWB_MODE, (ctrl->val) ? 0x1 : 0x2);
+static struct m5mols_scenemode m5mols_default_scenemode[] = {
+ [REG_SCENE_NORMAL] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_PORTRAIT] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 4,
+ REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_LANDSCAPE] = {
+ REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 4, REG_EDGE_ON, 6,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_SPORTS] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_PARTY_INDOOR] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_BEACH_SNOW] = {
+ REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_SUNSET] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
+ REG_AWB_DAYLIGHT,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_DAWN_DUSK] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
+ REG_AWB_FLUORESCENT_1,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_FALL] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 5, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_NIGHT] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_AGAINST_LIGHT] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_FIRE] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
+ },
+ [REG_SCENE_TEXT] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 7,
+ REG_AF_MACRO, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,
+ },
+ [REG_SCENE_CANDLE] = {
+ REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+ REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+ REG_AF_NORMAL, REG_FD_OFF,
+ REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+ 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+ },
+};
-}
-
-static int m5mols_exposure_mode(struct m5mols_info *info,
- struct v4l2_ctrl *ctrl)
+/**
+ * m5mols_do_scenemode() - Change current scenemode
+ * @mode: Desired mode of the scenemode
+ *
+ * WARNING: The execution order is important. Do not change the order.
+ */
+int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
{
struct v4l2_subdev *sd = &info->sd;
+ struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
int ret;
- if (info->is_ae_lock) {
- ret = m5mols_set_ae_lock(info, false);
- if (ret)
- return ret;
- }
-
- /* 0x01 : Auto Exposure, 0x0 : Manual Exposure. */
- return i2c_w8_ae(sd, CAT3_AE_MODE,
- (ctrl->val == V4L2_EXPOSURE_AUTO) ? 0x1 : 0x0);
-}
-
-static int m5mols_exposure(struct m5mols_info *info)
-{
- struct v4l2_subdev *sd = &info->sd;
-
- return i2c_w16_ae(sd, CAT3_MANUAL_GAIN_MON, info->exposure->val);
-}
-
-static int m5mols_zoom(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
-{
- struct v4l2_subdev *sd = &info->sd;
-
- return i2c_w8_mon(sd, CAT2_ZOOM, ctrl->val);
-}
-
-static int m5mols_focus_mode(struct m5mols_info *info,
- struct v4l2_ctrl *ctrl)
-{
- struct v4l2_subdev *sd = &info->sd;
- u32 reg;
- int ret;
+ if (mode > REG_SCENE_CANDLE)
+ return -EINVAL;
- ret = m5mols_set_mode(sd, MODE_MONITOR);
+ ret = m5mols_lock_3a(info, false);
+ if (!ret)
+ ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
+ if (!ret)
+ ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);
+ if (!ret)
+ ret = m5mols_write(sd, AE_MODE, scenemode.metering);
+ if (!ret)
+ ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);
+ if (!ret)
+ ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);
+ if (!ret)
+ ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);
+ if (!ret)
+ ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);
+ if (!ret)
+ ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);
+ if (!ret)
+ ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);
+ if (!ret)
+ ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);
+ if (!ret && is_available_af(info))
+ ret = m5mols_write(sd, AF_MODE, scenemode.af_range);
+ if (!ret && is_available_af(info))
+ ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);
+ if (!ret)
+ ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);
+ if (!ret)
+ ret = m5mols_write(sd, AE_ISO, scenemode.iso);
if (!ret)
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg);
+ ret = m5mols_mode(info, REG_CAPTURE);
if (!ret)
- ret = i2c_w8_system(sd, CAT0_INT_ENABLE, (1 << INT_BIT_AF));
+ ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);
if (!ret)
- /* must be excuted in the monitor mode */
- ret = i2c_w8_lens(sd, CATA_INIT_AF_FUNC, 0x1);
+ ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);
+ if (!ret)
+ ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);
+ if (!ret)
+ ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);
+ if (!ret)
+ ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);
+ if (!ret)
+ ret = m5mols_mode(info, REG_MONITOR);
- /* 0x0 : Normal AF mode
- * 0x1 : Macro AF mode
- * 0x2 : Continuous AF mode (Not working) */
- return i2c_w8_lens(sd, CATA_AF_MODE, 0x0);
+ return ret;
}
-static int m5mols_focus(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
+static int m5mols_lock_ae(struct m5mols_info *info, bool lock)
{
- struct v4l2_subdev *sd = &info->sd;
+ int ret = 0;
- /* 0x0: Stop,
- 0x1: Excute AF,
- 0x02: Excutre MF rel(Not tested),
- 0x03: Excute MF absol(Not tested) */
- return i2c_w8_lens(sd, CATA_AF_EXCUTE, ctrl->val);
+ if (info->lock_ae != lock)
+ ret = m5mols_write(&info->sd, AE_LOCK,
+ lock ? REG_AE_LOCK : REG_AE_UNLOCK);
+ if (!ret)
+ info->lock_ae = lock;
+
+ return ret;
}
-static int m5mols_set_saturation(struct m5mols_info *info,
- struct v4l2_ctrl *ctrl)
+static int m5mols_lock_awb(struct m5mols_info *info, bool lock)
{
- struct v4l2_subdev *sd = &info->sd;
- static u8 m5mols_chroma_lvl[] = {
- 0x1c, 0x3e, 0x5f, 0x80, 0xa1, 0xc2, 0xe4,
- };
- int ret;
+ int ret = 0;
- ret = i2c_w8_mon(sd, CAT2_CHROMA_LVL, m5mols_chroma_lvl[ctrl->val]);
+ if (info->lock_awb != lock)
+ ret = m5mols_write(&info->sd, AWB_LOCK,
+ lock ? REG_AWB_LOCK : REG_AWB_UNLOCK);
if (!ret)
- ret = i2c_w8_mon(sd, CAT2_CHROMA_EN, true);
+ info->lock_awb = lock;
return ret;
}
-static int m5mols_set_colorfx(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
+/* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */
+int m5mols_lock_3a(struct m5mols_info *info, bool lock)
{
- struct v4l2_subdev *sd = &info->sd;
- static u8 m5mols_effects_gamma[] = { /* cat 1: Effects */
- [V4L2_COLORFX_NEGATIVE] = 0x01,
- [V4L2_COLORFX_EMBOSS] = 0x06,
- [V4L2_COLORFX_SKETCH] = 0x07,
- };
- static u8 m5mols_cfixb_chroma[] = { /* cat 2: Cr for effect */
- [V4L2_COLORFX_BW] = 0x0,
- [V4L2_COLORFX_SEPIA] = 0xd8,
- [V4L2_COLORFX_SKY_BLUE] = 0x40,
- [V4L2_COLORFX_GRASS_GREEN] = 0xe0,
- };
- static u8 m5mols_cfixr_chroma[] = { /* cat 2: Cb for effect */
- [V4L2_COLORFX_BW] = 0x0,
- [V4L2_COLORFX_SEPIA] = 0x18,
- [V4L2_COLORFX_SKY_BLUE] = 0x00,
- [V4L2_COLORFX_GRASS_GREEN] = 0xe0,
- };
- int ret = -EINVAL;
-
- switch (ctrl->val) {
- case V4L2_COLORFX_NONE:
- return i2c_w8_mon(sd, CAT2_COLOR_EFFECT, false);
- case V4L2_COLORFX_BW: /* chroma: Gray */
- case V4L2_COLORFX_SEPIA: /* chroma: Sepia */
- case V4L2_COLORFX_SKY_BLUE: /* chroma: Blue */
- case V4L2_COLORFX_GRASS_GREEN: /* chroma: Green */
- ret = i2c_w8_mon(sd, CAT2_CFIXB,
- m5mols_cfixb_chroma[ctrl->val]);
- if (!ret)
- ret = i2c_w8_mon(sd, CAT2_CFIXR,
- m5mols_cfixr_chroma[ctrl->val]);
- if (!ret)
- ret = i2c_w8_mon(sd, CAT2_COLOR_EFFECT, true);
- return ret;
- case V4L2_COLORFX_NEGATIVE: /* gamma: Negative */
- case V4L2_COLORFX_EMBOSS: /* gamma: Emboss */
- case V4L2_COLORFX_SKETCH: /* gamma: Outline */
- ret = i2c_w8_param(sd, CAT1_EFFECT,
- m5mols_effects_gamma[ctrl->val]);
- if (!ret)
- ret = i2c_w8_mon(sd, CAT2_COLOR_EFFECT, true);
- return ret;
- }
+ int ret;
+
+ ret = m5mols_lock_ae(info, lock);
+ if (!ret)
+ ret = m5mols_lock_awb(info, lock);
+ /* Don't need to handle unlocking AF */
+ if (!ret && is_available_af(info) && lock)
+ ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
return ret;
}
+/* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */
int m5mols_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
struct m5mols_info *info = to_m5mols(sd);
- int ret = 0;
+ int ret;
switch (ctrl->id) {
case V4L2_CID_ZOOM_ABSOLUTE:
- return m5mols_zoom(info, ctrl);
- case V4L2_CID_FOCUS_AUTO:
- if (ctrl->val != 0)
- ret = m5mols_focus_mode(info, ctrl);
- if (!ret)
- ret = m5mols_focus(info, ctrl);
- return ret;
+ return m5mols_write(sd, MON_ZOOM, ctrl->val);
+
case V4L2_CID_EXPOSURE_AUTO:
- if (!ctrl->is_new)
- ctrl->val = V4L2_EXPOSURE_MANUAL;
- ret = m5mols_exposure_mode(info, ctrl);
- if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL)
- ret = m5mols_exposure(info);
+ ret = m5mols_lock_ae(info,
+ ctrl->val == V4L2_EXPOSURE_AUTO ? false : true);
+ if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO)
+ ret = m5mols_write(sd, AE_MODE, REG_AE_ALL);
+ if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) {
+ int val = info->exposure->val;
+ ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
+ if (!ret)
+ ret = m5mols_write(sd, AE_MAN_GAIN_MON, val);
+ if (!ret)
+ ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val);
+ }
return ret;
+
case V4L2_CID_AUTO_WHITE_BALANCE:
- return m5mols_wb_mode(info, ctrl);
+ ret = m5mols_lock_awb(info, ctrl->val ? false : true);
+ if (!ret)
+ ret = m5mols_write(sd, AWB_MODE, ctrl->val ?
+ REG_AWB_AUTO : REG_AWB_PRESET);
+ return ret;
+
case V4L2_CID_SATURATION:
- return m5mols_set_saturation(info, ctrl);
+ ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val);
+ if (!ret)
+ ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON);
+ return ret;
+
case V4L2_CID_COLORFX:
- return m5mols_set_colorfx(info, ctrl);
+ /*
+ * This control uses two kinds of registers: normal & color.
+ * The normal effect belongs to category 1, while the color
+ * one belongs to category 2.
+ *
+ * The normal effect uses one register: CAT1_EFFECT.
+ * The color effect uses three registers:
+ * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB.
+ */
+ ret = m5mols_write(sd, PARM_EFFECT,
+ ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA :
+ ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS :
+ REG_EFFECT_OFF);
+ if (!ret)
+ ret = m5mols_write(sd, MON_EFFECT,
+ ctrl->val == V4L2_COLORFX_SEPIA ?
+ REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF);
+ if (!ret)
+ ret = m5mols_write(sd, MON_CFIXR,
+ ctrl->val == V4L2_COLORFX_SEPIA ?
+ REG_CFIXR_SEPIA : 0);
+ if (!ret)
+ ret = m5mols_write(sd, MON_CFIXB,
+ ctrl->val == V4L2_COLORFX_SEPIA ?
+ REG_CFIXB_SEPIA : 0);
+ return ret;
}
return -EINVAL;
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c
index cf4c8ba..e0f09e5 100644
--- a/drivers/media/video/m5mols/m5mols_core.c
+++ b/drivers/media/video/m5mols/m5mols_core.c
@@ -1,5 +1,5 @@
/*
- * Driver for M5MOLS 8M Pixel camera sensor with ISP
+ * Driver for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -18,11 +18,10 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/videodev2.h>
-#include <linux/videodev2_exynos_media.h>
+#include <linux/module.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
@@ -34,66 +33,35 @@
int m5mols_debug;
module_param(m5mols_debug, int, 0644);
-#define MOD_NAME "M5MOLS"
-#define M5MOLS_I2C_CHECK_RETRY 50
-#define DEBUG
-#define DEFAULT_SENSOR_WIDTH 800
-#define DEFAULT_SENSOR_HEIGHT 480
-
-#define m5_err \
- do { printk("%s : %d : ret : %d\n", __func__, __LINE__, ret);\
- } while(0)
-/* M5MOLS mode */
-static u8 m5mols_reg_mode[] = {
- [MODE_SYSINIT] = 0x00,
- [MODE_PARMSET] = 0x01,
- [MODE_MONITOR] = 0x02,
- [MODE_CAPTURE] = 0x03,
- [MODE_UNKNOWN] = 0xff,
-};
-
-/* M5MOLS status */
-static u8 m5mols_reg_status[] = {
- [STATUS_SYSINIT] = 0x00,
- [STATUS_PARMSET] = 0x01,
- [STATUS_MONITOR] = 0x02,
- [STATUS_AUTO_FOCUS] = 0x03,
- [STATUS_FACE_DETECTION] = 0x04,
- [STATUS_DUAL_CAPTURE] = 0x05,
- [STATUS_SINGLE_CAPTURE] = 0x06,
- [STATUS_PREVIEW] = 0x07,
- [STATUS_UNKNOWN] = 0xff,
-};
+#define MODULE_NAME "M5MOLS"
+#define M5MOLS_I2C_CHECK_RETRY 500
-/* M5MOLS regulator consumer names */
-/* The DEFAULT names of power are referenced with M5MO datasheet. */
+/* The regulator consumer names for external voltage regulators */
static struct regulator_bulk_data supplies[] = {
{
- /* core power - 1.2v, generally at the M5MOLS */
- .supply = "core",
+ .supply = "core", /* ARM core power, 1.2V */
}, {
- .supply = "dig_18", /* digital power 1 - 1.8v */
+ .supply = "dig_18", /* digital power 1, 1.8V */
}, {
- .supply = "d_sensor", /* sensor power 1 - 1.8v */
+ .supply = "d_sensor", /* sensor power 1, 1.8V */
}, {
- .supply = "dig_28", /* digital power 2 - 2.8v */
+ .supply = "dig_28", /* digital power 2, 2.8V */
}, {
- .supply = "a_sensor", /* analog power */
+ .supply = "a_sensor", /* analog power */
}, {
- .supply = "dig_12", /* digital power 3 - 1.2v */
+ .supply = "dig_12", /* digital power 3, 1.2V */
},
};
-/* M5MOLS default format (codes, sizes, preset values) */
-static struct v4l2_mbus_framefmt default_fmt[M5MOLS_RES_MAX] = {
- [M5MOLS_RES_MON] = {
- .width = DEFAULT_SENSOR_WIDTH,
- .height = DEFAULT_SENSOR_HEIGHT,
- .code = V4L2_MBUS_FMT_YUYV8_2X8,
+static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = {
+ [M5MOLS_RESTYPE_MONITOR] = {
+ .width = 1920,
+ .height = 1080,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_JPEG,
},
- [M5MOLS_RES_CAPTURE] = {
+ [M5MOLS_RESTYPE_CAPTURE] = {
.width = 1920,
.height = 1080,
.code = V4L2_MBUS_FMT_JPEG_1X8,
@@ -101,201 +69,189 @@ static struct v4l2_mbus_framefmt default_fmt[M5MOLS_RES_MAX] = {
.colorspace = V4L2_COLORSPACE_JPEG,
},
};
-
-#define SIZE_DEFAULT_FFMT ARRAY_SIZE(default_fmt)
-
-static const struct m5mols_format m5mols_formats[] = {
- [M5MOLS_RES_MON] = {
- .code = V4L2_MBUS_FMT_YUYV8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
- },
- [M5MOLS_RES_CAPTURE] = {
- .code = V4L2_MBUS_FMT_JPEG_1X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
- },
-};
-
-static const struct m5mols_resolution m5mols_resolutions[] = {
- /* monitor size */
- { 0x01, M5MOLS_RES_MON, 128, 96 }, /* SUB-QCIF */
- { 0x03, M5MOLS_RES_MON, 160, 120 }, /* QQVGA */
- { 0x05, M5MOLS_RES_MON, 176, 144 }, /* QCIF */
- { 0x06, M5MOLS_RES_MON, 176, 176 }, /* 176*176 */
- { 0x08, M5MOLS_RES_MON, 240, 320 }, /* 1 QVGA */
- { 0x09, M5MOLS_RES_MON, 320, 240 }, /* QVGA */
- { 0x0c, M5MOLS_RES_MON, 240, 400 }, /* l WQVGA */
- { 0x0d, M5MOLS_RES_MON, 400, 240 }, /* WQVGA */
- { 0x0e, M5MOLS_RES_MON, 352, 288 }, /* CIF */
- { 0x13, M5MOLS_RES_MON, 480, 360 }, /* 480*360 */
- { 0x15, M5MOLS_RES_MON, 640, 360 }, /* qHD */
- { 0x17, M5MOLS_RES_MON, 640, 480 }, /* VGA */
- { 0x18, M5MOLS_RES_MON, 720, 480 }, /* 720x480 */
- { 0x1a, M5MOLS_RES_MON, 800, 480 }, /* WVGA */
- { 0x1f, M5MOLS_RES_MON, 800, 600 }, /* SVGA */
- { 0x21, M5MOLS_RES_MON, 1280, 720 }, /* HD */
- { 0x25, M5MOLS_RES_MON, 1920, 1080 }, /* 1080p */
- { 0x29, M5MOLS_RES_MON, 3264, 2448 }, /* 8M (2.63fps@3264*2448) */
- { 0x30, M5MOLS_RES_MON, 320, 240 }, /* 60fps for slow motion */
- { 0x31, M5MOLS_RES_MON, 320, 240 }, /* 120fps for slow motion */
- { 0x39, M5MOLS_RES_MON, 800, 602 }, /* AHS_MON debug */
-
- /* capture(JPEG or Bayer RAW or YUV Raw) size */
- { 0x02, M5MOLS_RES_CAPTURE, 320, 240 }, /* QVGA */
- { 0x04, M5MOLS_RES_CAPTURE, 400, 240 }, /* WQVGA */
- { 0x07, M5MOLS_RES_CAPTURE, 480, 360 }, /* 480 x 360 */
- { 0x08, M5MOLS_RES_CAPTURE, 640, 360 }, /* qHD */
- { 0x09, M5MOLS_RES_CAPTURE, 640, 480 }, /* VGA */
- { 0x0a, M5MOLS_RES_CAPTURE, 800, 480 }, /* WVGA */
- { 0x10, M5MOLS_RES_CAPTURE, 1280, 720 }, /* HD */
- { 0x14, M5MOLS_RES_CAPTURE, 1280, 960 }, /* 1M */
- { 0x17, M5MOLS_RES_CAPTURE, 1600, 1200 }, /* 2M */
- { 0x19, M5MOLS_RES_CAPTURE, 1920, 1080 }, /* Full-HD */
- { 0x1a, M5MOLS_RES_CAPTURE, 2048, 1152 }, /* 3M */
- { 0x1b, M5MOLS_RES_CAPTURE, 2048, 1536 }, /* 3M */
- { 0x1c, M5MOLS_RES_CAPTURE, 2560, 1440 }, /* 4M */
- { 0x1d, M5MOLS_RES_CAPTURE, 2560, 1536 }, /* 4M */
- { 0x1f, M5MOLS_RES_CAPTURE, 2560, 1920 }, /* 5M */
- { 0x21, M5MOLS_RES_CAPTURE, 3264, 1836 }, /* 6M */
- { 0x22, M5MOLS_RES_CAPTURE, 3264, 1960 }, /* 6M */
- { 0x25, M5MOLS_RES_CAPTURE, 3264, 2448 }, /* 8M */
-#ifdef M5MO_THUMB_SUPPORT
- /* capture thumb(JPEG) size */
- { 0x00, M5MOLS_RES_THUMB, 160, 90 }, /* 160 x 90 */
- { 0x02, M5MOLS_RES_THUMB, 160, 120 }, /* QQVGA */
- { 0x04, M5MOLS_RES_THUMB, 320, 240 }, /* QVGA */
- { 0x06, M5MOLS_RES_THUMB, 400, 240 }, /* WQVGA */
- { 0x09, M5MOLS_RES_THUMB, 480, 360 }, /* 480 x 360 */
- { 0x0a, M5MOLS_RES_THUMB, 640, 360 }, /* qHD */
- { 0x0b, M5MOLS_RES_THUMB, 640, 480 }, /* VGA */
- { 0x0c, M5MOLS_RES_THUMB, 800, 480 }, /* WVGA */
-#endif
-};
-
-/* M5MOLS default FPS */
-static const struct v4l2_fract default_fps = {
- .numerator = 1,
- .denominator = M5MOLS_FPS_AUTO,
+#define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt)
+
+static const struct m5mols_resolution m5mols_reg_res[] = {
+ { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 }, /* SUB-QCIF */
+ { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */
+ { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */
+ { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
+ { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */
+ { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */
+ { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */
+ { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */
+ { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */
+ { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
+ { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */
+ { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */
+ { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
+ { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */
+ { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */
+ { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 }, /* HD */
+ { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 }, /* 1080p */
+ { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 }, /* 2.63fps 8M */
+ { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */
+
+ { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */
+ { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */
+ { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
+ { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */
+ { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */
+ { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */
+ { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 }, /* HD */
+ { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 }, /* 1M */
+ { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 }, /* 2M */
+ { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 }, /* Full-HD */
+ { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 }, /* 3Mega */
+ { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
+ { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 }, /* 4Mega */
+ { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
+ { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 }, /* 5Mega */
+ { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 }, /* 6Mega */
+ { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
+ { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 }, /* 8Mega */
};
-static u8 m5mols_reg_fps[] = {
- [M5MOLS_FPS_AUTO] = 0x01,
- [M5MOLS_FPS_10] = 0x05,
- [M5MOLS_FPS_12] = 0x04,
- [M5MOLS_FPS_15] = 0x03,
- [M5MOLS_FPS_20] = 0x08,
- [M5MOLS_FPS_21] = 0x09,
- [M5MOLS_FPS_22] = 0x0a,
- [M5MOLS_FPS_23] = 0x0b,
- [M5MOLS_FPS_24] = 0x07,
- [M5MOLS_FPS_30] = 0x02,
-};
-
-static u32 m5mols_swap_byte(u8 *data, enum m5mols_i2c_size size)
+/**
+ * m5mols_swap_byte - an byte array to integer conversion function
+ * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet
+ *
+ * Convert I2C data byte array with performing any required byte
+ * reordering to assure proper values for each data type, regardless
+ * of the architecture endianness.
+ */
+static u32 m5mols_swap_byte(u8 *data, u8 length)
{
- if (size == I2C_8BIT)
+ if (length == 1)
return *data;
- else if (size == I2C_16BIT)
+ else if (length == 2)
return be16_to_cpu(*((u16 *)data));
else
return be32_to_cpu(*((u32 *)data));
}
-/*
- * m5mols_read_reg/m5mols_write_reg - handle sensor's I2C communications.
- *
- * The I2C command packet of M5MOLS is made up 3 kinds of I2C bytes(category,
- * command, bytes). Reference m5mols.h.
- *
- * The packet is needed 2, when M5MOLS is read through I2C.
- * The packet is needed 1, when M5MOLS is written through I2C.
- *
- * I2C packet common order(including both reading/writing)
- * 1st : size (data size + 4)
- * 2nd : READ/WRITE (R - 0x01, W - 0x02)
- * 3rd : Category
- * 4th : Command
- *
- * I2C packet order for READING operation
- * 5th : data real size for reading
- * And, read another I2C packet again, until data size.
- *
- * I2C packet order for WRITING operation
- * 5th to 8th: an actual data to write
+/**
+ * m5mols_read - I2C read function
+ * @reg: combination of size, category and command for the I2C packet
+ * @size: desired size of I2C packet
+ * @val: read value
*/
-
-#define M5MOLS_BYTE_READ 0x01
-#define M5MOLS_BYTE_WRITE 0x02
-
-int m5mols_read_reg(struct v4l2_subdev *sd,
- enum m5mols_i2c_size size,
- u8 category, u8 cmd, u32 *val)
+static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
+ u8 category = I2C_CATEGORY(reg);
+ u8 cmd = I2C_COMMAND(reg);
struct i2c_msg msg[2];
- u8 wbuf[5], rbuf[I2C_MAX + 1];
+ u8 wbuf[5];
int ret;
if (!client->adapter)
return -ENODEV;
- if (size != I2C_8BIT && size != I2C_16BIT && size != I2C_32BIT)
- return -EINVAL;
-
- /* 1st I2C operation for writing category & command. */
msg[0].addr = client->addr;
msg[0].flags = 0;
- msg[0].len = 5; /* 1(cmd size per bytes) + 4 */
+ msg[0].len = 5;
msg[0].buf = wbuf;
- wbuf[0] = 5; /* same right above this */
+ wbuf[0] = 5;
wbuf[1] = M5MOLS_BYTE_READ;
wbuf[2] = category;
wbuf[3] = cmd;
wbuf[4] = size;
- /* 2nd I2C operation for reading data. */
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = size + 1;
msg[1].buf = rbuf;
+ /* minimum stabilization time */
+ usleep_range(200, 200);
+
ret = i2c_transfer(client->adapter, msg, 2);
if (ret < 0) {
- m5_err;
- dev_err(&client->dev, "failed READ[%d] at "
- "cat[%02x] cmd[%02x]\n",
- size, category, cmd);
+ v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
+ size, category, cmd, ret);
return ret;
}
*val = m5mols_swap_byte(&rbuf[1], size);
- usleep_range(15000, 20000); /* must be for stabilization */
-
return 0;
}
-int m5mols_write_reg(struct v4l2_subdev *sd,
- enum m5mols_i2c_size size,
- u8 category, u8 cmd, u32 val)
+int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
+{
+ u32 val_32;
+ int ret;
+
+ if (I2C_SIZE(reg) != 1) {
+ v4l2_err(sd, "Wrong data size\n");
+ return -EINVAL;
+ }
+
+ ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
+ if (ret)
+ return ret;
+
+ *val = (u8)val_32;
+ return ret;
+}
+
+int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
+{
+ u32 val_32;
+ int ret;
+
+ if (I2C_SIZE(reg) != 2) {
+ v4l2_err(sd, "Wrong data size\n");
+ return -EINVAL;
+ }
+
+ ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
+ if (ret)
+ return ret;
+
+ *val = (u16)val_32;
+ return ret;
+}
+
+int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
+{
+ if (I2C_SIZE(reg) != 4) {
+ v4l2_err(sd, "Wrong data size\n");
+ return -EINVAL;
+ }
+
+ return m5mols_read(sd, I2C_SIZE(reg), reg, val);
+}
+
+/**
+ * m5mols_write - I2C command write function
+ * @reg: combination of size, category and command for the I2C packet
+ * @val: value to write
+ */
+int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct device *cdev = &client->dev;
- struct i2c_msg msg[1];
- u8 wbuf[I2C_MAX + 4];
+ u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
+ u8 category = I2C_CATEGORY(reg);
+ u8 cmd = I2C_COMMAND(reg);
+ u8 size = I2C_SIZE(reg);
u32 *buf = (u32 *)&wbuf[4];
+ struct i2c_msg msg[1];
int ret;
if (!client->adapter)
return -ENODEV;
- if (size != I2C_8BIT && size != I2C_16BIT && size != I2C_32BIT) {
- dev_err(cdev, "Wrong data size\n");
+ if (size != 1 && size != 2 && size != 4) {
+ v4l2_err(sd, "Wrong data size\n");
return -EINVAL;
}
msg->addr = client->addr;
msg->flags = 0;
- msg->len = size + 4;
+ msg->len = (u16)size + 4;
msg->buf = wbuf;
wbuf[0] = size + 4;
wbuf[1] = M5MOLS_BYTE_WRITE;
@@ -304,925 +260,547 @@ int m5mols_write_reg(struct v4l2_subdev *sd,
*buf = m5mols_swap_byte((u8 *)&val, size);
+ usleep_range(200, 200);
+
ret = i2c_transfer(client->adapter, msg, 1);
if (ret < 0) {
- m5_err;
- dev_err(&client->dev, "failed WRITE[%d] at "
- "cat[%02x] cmd[%02x], ret %d\n",
- size, msg->buf[2], msg->buf[3], ret);
+ v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n",
+ size, category, cmd, ret);
return ret;
}
- usleep_range(15000, 20000); /* must be for stabilization */
-
return 0;
}
-int m5mols_check_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value)
+int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask)
{
- u32 busy, i;
+ u8 busy;
+ int i;
int ret;
for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) {
- ret = m5mols_read_reg(sd, I2C_8BIT, category, cmd, &busy);
+ ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy);
if (ret < 0)
return ret;
-
- if (busy == value) /* bingo */
+ if ((busy & mask) == mask)
return 0;
-
- /* must be for stabilization */
- usleep_range(10000, 10000);
}
return -EBUSY;
}
-/*
- * m5mols_set_mode - change and set mode of M5MOLS.
+/**
+ * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
*
- * This driver supports now only 3 modes(System, Monitor, Parameter).
+ * Before writing desired interrupt value the INT_FACTOR register should
+ * be read to clear pending interrupts.
*/
-int m5mols_set_mode(struct v4l2_subdev *sd, enum m5mols_mode mode)
+int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
{
struct m5mols_info *info = to_m5mols(sd);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct device *cdev = &client->dev;
- const char *m5mols_str_mode[] = {
- "System initialization",
- "Parameter setting",
- "Monitor setting",
- "Capture setting",
- "Unknown",
- };
- int ret = 0;
-
- if (mode < MODE_SYSINIT || mode > MODE_UNKNOWN)
- return -EINVAL;
-
- ret = i2c_w8_system(sd, CAT0_SYSMODE, m5mols_reg_mode[mode]);
- if (!ret) {
- /* bug detect, capture status is not 0x3 but 0x6 */
- if (mode == MODE_CAPTURE)
- mode = STATUS_SINGLE_CAPTURE;
- ret = m5mols_check_busy(sd, CAT_SYSTEM, CAT0_STATUS,
- m5mols_reg_status[mode]);
- if (ret)
- m5_err;
- }
- if (ret < 0)
- return ret;
-
- info->mode = m5mols_reg_mode[mode];
- dev_dbg(cdev, " mode: %s\n", m5mols_str_mode[mode]);
+ u8 mask = is_available_af(info) ? REG_INT_AF : 0;
+ u8 dummy;
+ int ret;
+ ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
+ if (!ret)
+ ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
return ret;
}
-/*
- * m5mols_get_status - get status of M5MOLS.
+/**
+ * m5mols_reg_mode - Write the mode and check busy status
+ *
+ * It always accompanies a little delay changing the M-5MOLS mode, so it is
+ * needed checking current busy status to guarantee right mode.
*/
-enum m5mols_status m5mols_get_status(struct v4l2_subdev *sd)
+static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
{
- struct m5mols_info *info = to_m5mols(sd);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct device *cdev = &client->dev;
- const char *m5mols_str_status[] = {
- "System initialization",
- "Parameter setting",
- "Monitor setting",
- "Auto Focus",
- "Face Detection",
- "Multi/Dual Capture",
- "Single Capture",
- "Preview (Data transfer)", /* It means recording, not preview. */
- "Unknown",
- };
- u32 reg;
- int ret = 0;
+ int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
- ret = i2c_r8_system(sd, CAT0_STATUS, &reg);
- if (ret)
- return ret;
-
- if (reg < STATUS_SYSINIT || reg >= STATUS_UNKNOWN)
- return -EINVAL;
-
- info->status = m5mols_reg_status[reg];
- dev_dbg(cdev, " status: %s\n", m5mols_str_status[reg]);
-
- return ret;
+ return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode);
}
-/*
- * get_version - get M5MOLS sensor versions.
+/**
+ * m5mols_mode - manage the M-5MOLS's mode
+ * @mode: the required operation mode
+ *
+ * The commands of M-5MOLS are grouped into specific modes. Each functionality
+ * can be guaranteed only when the sensor is operating in mode which which
+ * a command belongs to.
*/
-static int get_version(struct v4l2_subdev *sd)
+int m5mols_mode(struct m5mols_info *info, u8 mode)
{
- struct m5mols_info *info = to_m5mols(sd);
- union {
- struct m5mols_version ver;
- u8 bytes[10];
- } value;
- int ret, i;
-
- for (i = CAT0_CUSTOMER_CODE; i <= CAT0_VERSION_AWB_L; i++) {
- ret = i2c_r8_system(sd, i, (u32 *)&value.bytes[i]);
- if (ret)
- return ret;
- }
-
- info->ver = value.ver;
+ struct v4l2_subdev *sd = &info->sd;
+ int ret = -EINVAL;
+ u8 reg;
- info->ver.fw = be16_to_cpu(info->ver.fw);
- info->ver.hw = be16_to_cpu(info->ver.hw);
- info->ver.parm = be16_to_cpu(info->ver.parm);
- info->ver.awb = be16_to_cpu(info->ver.awb);
+ if (mode < REG_PARAMETER || mode > REG_CAPTURE)
+ return ret;
- return ret;
-}
+ ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
+ if ((!ret && reg == mode) || ret)
+ return ret;
-static void m5mols_show_version(struct v4l2_subdev *sd)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct device *dev = &client->dev;
- struct m5mols_info *info = to_m5mols(sd);
+ switch (reg) {
+ case REG_PARAMETER:
+ ret = m5mols_reg_mode(sd, REG_MONITOR);
+ if (!ret && mode == REG_MONITOR)
+ break;
+ if (!ret)
+ ret = m5mols_reg_mode(sd, REG_CAPTURE);
+ break;
- dev_info(dev, "customer code\t0x%02x\n", info->ver.ctm_code);
- dev_info(dev, "project code\t0x%02x\n", info->ver.pj_code);
- dev_info(dev, "firmware version\t0x%04x\n", info->ver.fw);
- dev_info(dev, "hardware version\t0x%04x\n", info->ver.hw);
- dev_info(dev, "parameter version\t0x%04x\n", info->ver.parm);
- dev_info(dev, "AWB version\t0x%04x\n", info->ver.awb);
-}
+ case REG_MONITOR:
+ if (mode == REG_PARAMETER) {
+ ret = m5mols_reg_mode(sd, REG_PARAMETER);
+ break;
+ }
-/*
- * get_res_preset - find out M5MOLS register value from requested resolution.
- *
- * @width: requested width
- * @height: requested height
- * @type: requested type of each modes. It supports only monitor mode now.
- */
-static int get_res_preset(struct v4l2_subdev *sd, u16 width, u16 height,
- enum m5mols_res_type type)
-{
- struct m5mols_info *info = to_m5mols(sd);
- int i;
+ ret = m5mols_reg_mode(sd, REG_CAPTURE);
+ break;
- for (i = 0; i < ARRAY_SIZE(m5mols_resolutions); i++) {
- if ((m5mols_resolutions[i].type == type) &&
- (m5mols_resolutions[i].width == width) &&
- (m5mols_resolutions[i].height == height))
+ case REG_CAPTURE:
+ ret = m5mols_reg_mode(sd, REG_MONITOR);
+ if (!ret && mode == REG_MONITOR)
break;
- }
+ if (!ret)
+ ret = m5mols_reg_mode(sd, REG_PARAMETER);
+ break;
- if (i >= ARRAY_SIZE(m5mols_resolutions)) {
- v4l2msg("no matching resolution\n");
- return -EINVAL;
+ default:
+ v4l2_warn(sd, "Wrong mode: %d\n", mode);
}
- return m5mols_resolutions[i].value;
+ if (!ret)
+ info->mode = mode;
+
+ return ret;
}
-/*
- * get_fps - calc & check FPS from v4l2_captureparm, if FPS is adequate, set.
+/**
+ * m5mols_get_version - retrieve full revisions information of M-5MOLS
*
- * In M5MOLS case, the denominator means FPS. The each value of numerator and
- * denominator should not be minus. If numerator is 0, it sets AUTO FPS. If
- * numerator is not 1, it recalculates denominator. After it checks, the
- * denominator is set to timeperframe.denominator, and used by FPS.
+ * The version information includes revisions of hardware and firmware,
+ * AutoFocus alghorithm version and the version string.
*/
-static int get_fps(struct v4l2_subdev *sd,
- struct v4l2_captureparm *parm)
+static int m5mols_get_version(struct v4l2_subdev *sd)
{
- int numerator = parm->timeperframe.numerator;
- int denominator = parm->timeperframe.denominator;
+ struct m5mols_info *info = to_m5mols(sd);
+ struct m5mols_version *ver = &info->ver;
+ u8 *str = ver->str;
+ int i;
+ int ret;
- /* The denominator should be +, except 0. The numerator shoud be +. */
- if (numerator < 0 || denominator <= 0)
- return -EINVAL;
+ ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
+ if (!ret)
+ ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
+ if (!ret)
+ ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
+ if (!ret)
+ ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
+ if (!ret)
+ ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
+ if (!ret)
+ ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
+ if (!ret)
+ ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
+ if (ret)
+ return ret;
- /* The numerator is 0, return auto fps. */
- if (numerator == 0) {
- parm->timeperframe.denominator = M5MOLS_FPS_AUTO;
- return 0;
+ for (i = 0; i < VERSION_STRING_SIZE; i++) {
+ ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
+ if (ret)
+ return ret;
}
- /* calc FPS(not time per frame) per 1 numerator */
- denominator = denominator / numerator;
+ ver->fw = be16_to_cpu(ver->fw);
+ ver->hw = be16_to_cpu(ver->hw);
+ ver->param = be16_to_cpu(ver->param);
+ ver->awb = be16_to_cpu(ver->awb);
- if (denominator < M5MOLS_FPS_AUTO || denominator > M5MOLS_FPS_MAX)
- return -EINVAL;
+ v4l2_info(sd, "Manufacturer\t[%s]\n",
+ is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
+ "Samsung Electro-Machanics" :
+ is_manufacturer(info, REG_SAMSUNG_OPTICS) ?
+ "Samsung Fiber-Optics" :
+ is_manufacturer(info, REG_SAMSUNG_TECHWIN) ?
+ "Samsung Techwin" : "None");
+ v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n",
+ info->ver.customer, info->ver.project);
- if (!m5mols_reg_fps[denominator])
- return -EINVAL;
+ if (!is_available_af(info))
+ v4l2_info(sd, "No support Auto Focus on this firmware\n");
- return 0;
-}
-
-/*
- * to_code - return pixelcode of M5MOLS according to resolution type.
- */
-static enum v4l2_mbus_pixelcode to_code(enum m5mols_res_type res_type)
-{
- return m5mols_formats[res_type].code;
+ return ret;
}
-/*
- * to_res_type - return resolution type of M5MOLS according to pixelcode.
+/**
+ * __find_restype - Lookup M-5MOLS resolution type according to pixel code
+ * @code: pixel code
*/
-static enum m5mols_res_type to_res_type(struct v4l2_subdev *sd,
- enum v4l2_mbus_pixelcode code)
+static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code)
{
- int i = ARRAY_SIZE(m5mols_formats);
+ enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
- while (i--)
- if (code == m5mols_formats[i].code)
- break;
- if (i < 0)
- return M5MOLS_RES_MAX;
+ do {
+ if (code == m5mols_default_ffmt[type].code)
+ return type;
+ } while (type++ != SIZE_DEFAULT_FFMT);
- if (code == m5mols_formats[M5MOLS_RES_MON].code)
- return M5MOLS_RES_MON;
- else
- return M5MOLS_RES_CAPTURE;
+ return 0;
}
-static int m5mols_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *ffmt)
+/**
+ * __find_resolution - Lookup preset and type of M-5MOLS's resolution
+ * @mf: pixel format to find/negotiate the resolution preset for
+ * @type: M-5MOLS resolution type
+ * @resolution: M-5MOLS resolution preset register value
+ *
+ * Find nearest resolution matching resolution preset and adjust mf
+ * to supported values.
+ */
+static int __find_resolution(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf,
+ enum m5mols_restype *type,
+ u32 *resolution)
{
- struct m5mols_info *info = to_m5mols(sd);
- enum m5mols_res_type res_type;
+ const struct m5mols_resolution *fsize = &m5mols_reg_res[0];
+ const struct m5mols_resolution *match = NULL;
+ enum m5mols_restype stype = __find_restype(mf->code);
+ int i = ARRAY_SIZE(m5mols_reg_res);
+ unsigned int min_err = ~0;
- res_type = to_res_type(sd, ffmt->code);
- if (res_type == M5MOLS_RES_MAX)
- return -EINVAL;
+ while (i--) {
+ int err;
+ if (stype == fsize->type) {
+ err = abs(fsize->width - mf->width)
+ + abs(fsize->height - mf->height);
- *ffmt = info->fmt[res_type];
- info->code = ffmt->code;
+ if (err < min_err) {
+ min_err = err;
+ match = fsize;
+ }
+ }
+ fsize++;
+ }
+ if (match) {
+ mf->width = match->width;
+ mf->height = match->height;
+ *resolution = match->reg;
+ *type = stype;
+ return 0;
+ }
- return 0;
+ return -EINVAL;
}
-static int m5mols_into_monitor(struct v4l2_subdev *sd, int res_size)
+static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
+ struct v4l2_subdev_fh *fh,
+ enum v4l2_subdev_format_whence which,
+ enum m5mols_restype type)
{
- int ret;
-
- ret = m5mols_set_mode(sd, MODE_PARMSET);
- if (!ret)
- ret = i2c_w8_param(sd, CAT1_MONITOR_SIZE, (u8)res_size);
- if (!ret)
- ret = m5mols_set_mode(sd, MODE_PARMSET);
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
- return ret;
+ return &info->ffmt[type];
}
-static int m5mols_into_capture(struct v4l2_subdev *sd, int res_size)
+static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
{
struct m5mols_info *info = to_m5mols(sd);
- u32 reg;
- int ret, timeout = 1;
- u32 temp = 0;
-
- info->captured = false;
-
- /*
- * The sequence of preparing Capture mode.
- * 1. Clear Interrupt bit (for dummy)
- * 2. Enable Capture bit at Interrupt
- * 3. Lock AE/AWB
- * 4. Enter Still Capture mode
- */
-
- ret = m5mols_set_mode(sd, MODE_MONITOR);
- if (!ret)
- /* FIXME: setting capture exposure at the middle of a amount. */
- ret = i2c_w16_ae(sd, CAT3_MANUAL_GAIN_CAP, 0x90);
- if (!ret)
- ret = m5mols_set_ae_lock(info, true);
- if (!ret)
- ret = m5mols_set_awb_lock(info, true);
- if (!ret)
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg);
- if (!ret)
- ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 1 << INT_BIT_CAPTURE);
- if (!ret)
- ret = m5mols_set_mode(sd, MODE_CAPTURE);
- if (!ret)
- timeout = wait_event_interruptible_timeout(info->cap_wait,
- info->captured, msecs_to_jiffies(2000));
-
- /* disable all interrupt & clear interrupt */
- ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 0x0);
- if (!ret)
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg);
- if (ret)
- return -EPERM;
+ struct v4l2_mbus_framefmt *format;
- /* If all timeout exhausted, return error. */
- if (!timeout)
- return -ETIMEDOUT;
+ format = __find_format(info, fh, fmt->which, info->res_type);
+ if (!format)
+ return -EINVAL;
- ret = i2c_r32_capt_ctrl(sd, CATC_CAP_IMAGE_SIZE, &temp);
- info->captured = false;
- return ret;
+ fmt->format = *format;
+ return 0;
}
-static int m5mols_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *ffmt)
+static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
{
struct m5mols_info *info = to_m5mols(sd);
- enum m5mols_res_type res_type;
- int size;
- int ret = -EINVAL;
-
- res_type = to_res_type(sd, ffmt->code);
- if (res_type == M5MOLS_RES_MAX)
- return -EINVAL;
-
- /* If user set portrait for preview, it is substitued width width height
- * unless get_res_preset will fail that M5MOLS did not support
- * reverse WVGA */
- if (ffmt->width < ffmt->height) {
- int temp;
- temp = ffmt->width;
- ffmt->width = ffmt->height;
- ffmt->height = temp;
- }
- size = get_res_preset(sd, ffmt->width, ffmt->height, res_type);
- if (size < 0)
- return -EINVAL;
-
- if (ffmt->code == m5mols_formats[M5MOLS_RES_MON].code)
- ret = m5mols_into_monitor(sd, size);
- else
- ret = m5mols_into_capture(sd, 0);
+ struct v4l2_mbus_framefmt *format = &fmt->format;
+ struct v4l2_mbus_framefmt *sfmt;
+ enum m5mols_restype type;
+ u32 resolution = 0;
+ int ret;
- info->fmt[res_type] = default_fmt[res_type];
- info->fmt[res_type].width = ffmt->width;
- info->fmt[res_type].height = ffmt->height;
+ ret = __find_resolution(sd, format, &type, &resolution);
+ if (ret < 0)
+ return ret;
- *ffmt = info->fmt[res_type];
- info->code = ffmt->code;
+ sfmt = __find_format(info, fh, fmt->which, type);
+ if (!sfmt)
+ return 0;
- return ret;
-}
-static int m5mols_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- enum v4l2_mbus_pixelcode *code)
-{
- if (!code || index >= ARRAY_SIZE(m5mols_formats))
- return -EINVAL;
+ format->code = m5mols_default_ffmt[type].code;
+ format->colorspace = V4L2_COLORSPACE_JPEG;
+ format->field = V4L2_FIELD_NONE;
- *code = m5mols_formats[index].code;
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ *sfmt = *format;
+ info->resolution = resolution;
+ info->res_type = type;
+ }
return 0;
}
-static int m5mols_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- struct m5mols_info *info = to_m5mols(sd);
- struct v4l2_captureparm *cp = &parms->parm.capture;
-
- if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ if (!code || code->index >= SIZE_DEFAULT_FFMT)
return -EINVAL;
- cp->capability = V4L2_CAP_TIMEPERFRAME;
- cp->timeperframe = info->tpf;
+ code->code = m5mols_default_ffmt[code->index].code;
return 0;
}
-static int m5mols_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
+ .enum_mbus_code = m5mols_enum_mbus_code,
+ .get_fmt = m5mols_get_fmt,
+ .set_fmt = m5mols_set_fmt,
+};
+
+/**
+ * m5mols_sync_controls - Apply default scene mode and the current controls
+ *
+ * This is used only streaming for syncing between v4l2_ctrl framework and
+ * m5mols's controls. First, do the scenemode to the sensor, then call
+ * v4l2_ctrl_handler_setup. It can be same between some commands and
+ * the scenemode's in the default v4l2_ctrls. But, such commands of control
+ * should be prior to the scenemode's one.
+ */
+int m5mols_sync_controls(struct m5mols_info *info)
{
- struct m5mols_info *info = to_m5mols(sd);
- struct v4l2_captureparm *cp = &parms->parm.capture;
int ret = -EINVAL;
- if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- return -EINVAL;
+ if (!is_ctrl_synced(info)) {
+ ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
+ if (ret)
+ return ret;
- ret = m5mols_set_mode_backup(sd, MODE_PARMSET);
- if (!ret)
- ret = get_fps(sd, cp); /* set right FPS to denominator. */
- if (!ret)
- ret = i2c_w8_param(sd, CAT1_MONITOR_FPS,
- m5mols_reg_fps[cp->timeperframe.denominator]);
- if (!ret)
- ret = m5mols_set_mode_restore(sd);
- if (!ret) {
- cp->capability = V4L2_CAP_TIMEPERFRAME;
- info->tpf = cp->timeperframe;
+ v4l2_ctrl_handler_setup(&info->handle);
+ info->ctrl_sync = true;
}
- v4l2msg("denominator: %d / numerator: %d.\n",
- cp->timeperframe.denominator, cp->timeperframe.numerator);
-
return ret;
}
-static int m5mols_get_info_capture(struct v4l2_subdev *sd)
+/**
+ * m5mols_start_monitor - Start the monitor mode
+ *
+ * Before applying the controls setup the resolution and frame rate
+ * in PARAMETER mode, and then switch over to MONITOR mode.
+ */
+static int m5mols_start_monitor(struct m5mols_info *info)
{
- struct m5mols_info *info = to_m5mols(sd);
- struct m5mols_exif *exif = &info->cap.exif;
- int denominator, numerator;
- int ret = 0;
-
- ret = i2c_r32_exif(sd, CAT7_INFO_EXPTIME_NU, &numerator);
- if (!ret)
- ret = i2c_r32_exif(sd, CAT7_INFO_EXPTIME_DE, &denominator);
- if (!ret)
- exif->exposure_time = (u32)(numerator / denominator);
- if (ret)
- return ret;
-
- ret = i2c_r32_exif(sd, CAT7_INFO_TV_NU, &numerator);
- if (!ret)
- ret = i2c_r32_exif(sd, CAT7_INFO_TV_DE, &denominator);
- if (!ret)
- exif->shutter_speed = (u32)(numerator / denominator);
- if (ret)
- return ret;
-
- ret = i2c_r32_exif(sd, CAT7_INFO_AV_NU, &numerator);
- if (!ret)
- ret = i2c_r32_exif(sd, CAT7_INFO_AV_DE, &denominator);
- if (!ret)
- exif->aperture = (u32)(numerator / denominator);
- if (ret)
- return ret;
-
- ret = i2c_r32_exif(sd, CAT7_INFO_BV_NU, &numerator);
- if (!ret)
- ret = i2c_r32_exif(sd, CAT7_INFO_BV_DE, &denominator);
- if (!ret)
- exif->brightness = (u32)(numerator / denominator);
- if (ret)
- return ret;
-
- ret = i2c_r32_exif(sd, CAT7_INFO_EBV_NU, &numerator);
- if (!ret)
- ret = i2c_r32_exif(sd, CAT7_INFO_EBV_DE, &denominator);
- if (!ret)
- exif->exposure_bias = (u32)(numerator / denominator);
- if (ret)
- return ret;
+ struct v4l2_subdev *sd = &info->sd;
+ int ret;
- ret = i2c_r16_exif(sd, CAT7_INFO_ISO, (u32 *)&exif->iso_speed);
- if (!ret)
- ret = i2c_r16_exif(sd, CAT7_INFO_FLASH, (u32 *)&exif->flash);
+ ret = m5mols_mode(info, REG_PARAMETER);
if (!ret)
- ret = i2c_r16_exif(sd, CAT7_INFO_SDR, (u32 *)&exif->sdr);
+ ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution);
if (!ret)
- ret = i2c_r16_exif(sd, CAT7_INFO_QVAL, (u32 *)&exif->qval);
- if (ret)
- return ret;
+ ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30);
if (!ret)
- ret = i2c_r32_capt_ctrl(sd, CATC_CAP_IMAGE_SIZE,
- &info->cap.main);
+ ret = m5mols_mode(info, REG_MONITOR);
if (!ret)
- ret = i2c_r32_capt_ctrl(sd, CATC_CAP_THUMB_SIZE,
- &info->cap.thumb);
-
- info->cap.total = info->cap.main + info->cap.thumb;
-
- v4l2_info(sd, "%s: capture total size %d\n", __func__, info->cap.total);
- v4l2_info(sd, "%s: capture main size %d\n", __func__, info->cap.main);
- v4l2_info(sd, "%s: capture thumb size %d\n", __func__, info->cap.thumb);
- v4l2_info(sd, "%s: exposure_time %d\n", __func__, exif->exposure_time);
- v4l2_info(sd, "%s: shutter_speed %d\n", __func__, exif->shutter_speed);
- v4l2_info(sd, "%s: aperture %d\n", __func__, exif->aperture);
- v4l2_info(sd, "%s: brightness %d\n", __func__, exif->brightness);
- v4l2_info(sd, "%s: exposure_bias %d\n", __func__, exif->exposure_bias);
- v4l2_info(sd, "%s: iso_speed %d\n", __func__, exif->iso_speed);
- v4l2_info(sd, "%s: flash %d\n", __func__, exif->flash);
- v4l2_info(sd, "%s: sdr %d\n", __func__, exif->sdr);
- v4l2_info(sd, "%s: qval %d\n", __func__, exif->qval);
+ ret = m5mols_sync_controls(info);
return ret;
}
-/* TODO: not verified. */
-static int m5mols_start_capture(struct v4l2_subdev *sd)
+static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
{
struct m5mols_info *info = to_m5mols(sd);
- u32 reg, size;
- int ret, timeout;
-
- u8 reg_capt_fmt[] = {
- 0x10, /* JPEG with header + Thumbnail JPEG(YUV422@QVGA) */
- }; /* YUV422, JPEG(422), JPEG(420) */
- info->captured = false;
-
- size = get_res_preset(sd,
- info->fmt[M5MOLS_RES_CAPTURE].width,
- info->fmt[M5MOLS_RES_CAPTURE].height,
- M5MOLS_RES_CAPTURE);
- if (size < 0)
- return -EINVAL;
- ret = 0;
- /*
- * The sequence of Starting Capture mode.
- * 1. Select capture Single or Multi
- * 2. Select format (YUV422, JPEG(YUV420, YUV422))
- * 3. Set image size preset of Capture
- * 4. Read Interrupt bit (for dummy)
- * 5. Enable Capture bit at Interrupt
- * 6. Start Capture
- * 7. Check interrupt and register value
- * 8. Get Image & Thumb size
- */
- ret = i2c_w8_capt_ctrl(sd, CATC_CAP_SEL_FRAME, true); /* single capture */
- if (!ret)
- ret = i2c_w8_capt_parm(sd, CATB_YUVOUT_MAIN, reg_capt_fmt[0]);
- if (!ret)
- ret = i2c_w8_capt_parm(sd, CATB_MAIN_IMAGE_SIZE, size);
- if (!ret)
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg);
- if (!ret)
- ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 1 << INT_BIT_CAPTURE);
- if (!ret)
- ret = i2c_w8_capt_ctrl(sd, CATC_CAP_START, true);
- if (!ret) {
- timeout = wait_event_interruptible_timeout(info->cap_wait,
- info->captured, msecs_to_jiffies(2000));
-
- if (info->captured) {
- ret = m5mols_get_info_capture(sd);
+ u32 code = info->ffmt[info->res_type].code;
- if (!ret)
- v4l2_subdev_notify(sd, info->cap.total, NULL);
- else
- return ret;
- }
-
- /* disable all interrupt & clear interrupt */
- ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 0x0);
- if (!ret)
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg);
- if (ret)
- return -EPERM;
-
- /* If all timeout exhausted, return error. */
- if (!timeout)
- return -ETIMEDOUT;
+ if (enable) {
+ int ret = -EINVAL;
- info->captured = false;
+ if (is_code(code, M5MOLS_RESTYPE_MONITOR))
+ ret = m5mols_start_monitor(info);
+ if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
+ ret = m5mols_start_capture(info);
- ret = 0;
+ return ret;
}
- /* TODO: complete capture. */
-
- return ret;
-}
-
-static int m5mols_start_monitor(struct v4l2_subdev *sd)
-{
- return m5mols_set_mode(sd, MODE_MONITOR);
-}
-
-static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct m5mols_info *info = to_m5mols(sd);
-
- if (enable) {
- if (info->code == to_code(M5MOLS_RES_MON)) {
- v4l2_info(sd, "%s : monitor mode\n", __func__);
- return m5mols_start_monitor(sd);
- }
- if (info->code == to_code(M5MOLS_RES_CAPTURE)) {
- v4l2_info(sd, "%s : capture mode\n", __func__);
- return m5mols_start_capture(sd);
- }
- return -EINVAL;
- } else {
- if (is_streaming(sd))
- return m5mols_set_mode(sd, MODE_PARMSET);
- return -EINVAL;
- }
+ return m5mols_mode(info, REG_PARAMETER);
}
static const struct v4l2_subdev_video_ops m5mols_video_ops = {
- .g_mbus_fmt = m5mols_g_mbus_fmt,
- .s_mbus_fmt = m5mols_s_mbus_fmt,
- .enum_mbus_fmt = m5mols_enum_mbus_fmt,
- .g_parm = m5mols_g_parm,
- .s_parm = m5mols_s_parm,
- .s_stream = m5mols_s_stream,
+ .s_stream = m5mols_s_stream,
};
static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
+ struct m5mols_info *info = to_m5mols(sd);
int ret;
- ret = m5mols_set_mode_backup(sd, MODE_PARMSET);
+ info->mode_save = info->mode;
+
+ ret = m5mols_mode(info, REG_PARAMETER);
if (!ret)
ret = m5mols_set_ctrl(ctrl);
if (!ret)
- ret = m5mols_set_mode_restore(sd);
-
- return ret;
-}
-
-static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct v4l2_subdev *sd = to_sd(ctrl);
- struct m5mols_info *info = to_m5mols(sd);
- int ret = 0;
+ ret = m5mols_mode(info, info->mode_save);
- switch (ctrl->id) {
- case V4L2_CID_CAM_JPEG_ENCODEDSIZE:
- ctrl->cur.val = info->cap.total;
- break;
- default:
- ret = -EINVAL;
- break;
- }
return ret;
}
static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
- .s_ctrl = m5mols_s_ctrl,
- .g_volatile_ctrl = m5mols_g_volatile_ctrl,
+ .s_ctrl = m5mols_s_ctrl,
};
-static const struct v4l2_ctrl_config ctrl_private[] = {
- {
- .ops = &m5mols_ctrl_ops,
- .id = V4L2_CID_CAM_JPEG_MEMSIZE,
- .name = "Jpeg memory size",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .flags = V4L2_CTRL_FLAG_SLIDER,
- .max = M5MO_JPEG_MEMSIZE,
- .step = 1,
- .min = 0,
- .def = M5MO_JPEG_MEMSIZE,
- .is_private = 1,
- }, {
- .ops = &m5mols_ctrl_ops,
- .id = V4L2_CID_CAM_JPEG_ENCODEDSIZE,
- .name = "Jpeg encoded size",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .flags = V4L2_CTRL_FLAG_SLIDER,
- .max = M5MO_JPEG_MEMSIZE,
- .step = 1,
- .min = 0,
- .def = 0,
- .is_private = 1,
- .is_volatile = 1,
- },
-};
-/*
- * m5mols_sensor_power - handle sensor power up/down.
- *
- * @enable: If it is true, power up. If is not, power down.
- */
static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
{
struct v4l2_subdev *sd = &info->sd;
- struct i2c_client *c = v4l2_get_subdevdata(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ const struct m5mols_platform_data *pdata = info->pdata;
int ret;
if (enable) {
- if (is_powerup(sd))
+ if (is_powered(info))
return 0;
- /* power-on additional power */
if (info->set_power) {
- ret = info->set_power(&c->dev, 1);
+ ret = info->set_power(&client->dev, 1);
if (ret)
return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
- if (ret)
+ if (ret) {
+ info->set_power(&client->dev, 0);
return ret;
+ }
- gpio_set_value(info->pdata->gpio_rst, info->pdata->enable_rst);
+ gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity);
usleep_range(1000, 1000);
-
info->power = true;
- } else {
- if (!is_powerup(sd))
- return 0;
- ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
- if (ret)
- return ret;
+ return ret;
+ }
- /* power-off additional power */
- if (info->set_power) {
- ret = info->set_power(&c->dev, 0);
- if (ret)
- return ret;
- }
+ if (!is_powered(info))
+ return 0;
- info->power = false;
+ ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+ if (ret)
+ return ret;
- gpio_set_value(info->pdata->gpio_rst, !info->pdata->enable_rst);
- usleep_range(1000, 1000);
- }
+ if (info->set_power)
+ info->set_power(&client->dev, 0);
- return ret;
-}
+ gpio_set_value(pdata->gpio_reset, pdata->reset_polarity);
+ usleep_range(1000, 1000);
+ info->power = false;
-static void m5mols_irq_work(struct work_struct *work)
-{
- struct m5mols_info *info = container_of(work, struct m5mols_info, work);
- struct v4l2_subdev *sd = &info->sd;
- u32 reg;
- int ret;
- if (is_powerup(sd)) {
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg);
- if (!ret) {
- switch (reg & 0x0f) {
- case (1 << INT_BIT_AF):
- /* Except returning zero at just that upper
- * statments, not entering in this parenthesis.
- * The return value is below:
- * 0x0 : AF Fail
- * 0x2 : AF Success
- * 0x4 : Idle Status
- * 0x5 : Busy Status */
- ret = i2c_r8_lens(sd, CATA_AF_STATUS, &reg);
- if (!ret && (reg == 0x02))
- info->is_focus = true;
- else
- info->is_focus = false;
- printk("%s = AF %02x, focus %d\n",
- __func__, reg, info->is_focus);
- break;
- case (1 << INT_BIT_CAPTURE):
- printk("%s = CAPTURE\n", __func__);
- if (!info->captured) {
- wake_up_interruptible(&info->cap_wait);
- info->captured = true;
- }
- break;
- case (1 << INT_BIT_ZOOM):
- case (1 << INT_BIT_FRAME_SYNC):
- case (1 << INT_BIT_FD):
- case (1 << INT_BIT_LENS_INIT):
- case (1 << INT_BIT_SOUND):
- printk("%s = Nothing : 0x%08x\n", __func__, reg);
- break;
- case (1 << INT_BIT_MODE):
- default:
- break;
- }
- }
- }
+ return ret;
}
-static irqreturn_t m5mols_irq_handler(int irq, void *data)
+/* m5mols_update_fw - optional firmware update routine */
+int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
+ int (*set_power)(struct m5mols_info *, bool))
{
- struct v4l2_subdev *sd = data;
- struct m5mols_info *info = to_m5mols(sd);
-
- v4l2_info(sd, "%s\n", __func__);
-
- schedule_work(&info->work);
-
- return IRQ_HANDLED;
+ return 0;
}
-/*
- * m5mols_sensor_armboot - booting M5MOLS internal ARM core-controller.
+/**
+ * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core.
*
- * It makes to ready M5MOLS for I2C & MIPI interface. After it's powered up,
- * it activates if it gets armboot command for I2C interface. After getting
- * cmd, it must wait about least 500ms referenced by M5MOLS datasheet.
+ * Booting internal ARM core makes the M-5MOLS is ready for getting commands
+ * with I2C. It's the first thing to be done after it powered up. It must wait
+ * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting.
*/
static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct m5mols_info *info = to_m5mols(sd);
- static u8 m5mols_mipi_value = 0x02;
- u32 reg;
int ret;
- /* 1. ARM booting */
- ret = i2c_w8_flash(sd, CATC_CAM_START, true);
+ ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
if (ret < 0)
return ret;
- msleep(500);
- dev_dbg(&client->dev, "Success ARM Booting\n");
+ msleep(520);
- /* after ARM booting, the M5MOLS state changed Parameter mode. */
- info->mode = MODE_PARMSET;
-
- ret = i2c_r8_system(sd, CAT0_INT_FACTOR, &reg); /* clear intterupt */
- if (!ret)
- ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 0x0); /* all disable */
- if (!ret)
- ret = get_version(sd);
+ ret = m5mols_get_version(sd);
if (!ret)
- ret = i2c_w8_param(sd, CAT1_DATA_INTERFACE, m5mols_mipi_value);
+ ret = m5mols_update_fw(sd, m5mols_sensor_power);
+ if (ret)
+ return ret;
- m5mols_show_version(sd);
+ v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");
+
+ ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
+ if (!ret)
+ ret = m5mols_enable_interrupt(sd, REG_INT_AF);
return ret;
}
-/*
- * m5mols_init_controls - initialization using v4l2_ctrl.
- */
static int m5mols_init_controls(struct m5mols_info *info)
{
struct v4l2_subdev *sd = &info->sd;
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- u16 max_ex_mon;
+ u16 max_exposure;
+ u16 step_zoom;
int ret;
- /* check minimum & maximum of M5MOLS controls */
- ret = i2c_r16_ae(sd, CAT3_MAX_GAIN_MON, (u32 *)&max_ex_mon);
+ /* Determine value's range & step of controls for various FW version */
+ ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &max_exposure);
+ if (!ret)
+ step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1;
if (ret)
return ret;
- /* set the controls using v4l2 control frameworks */
- v4l2_ctrl_handler_init(&info->handle, 9);
-
- info->colorfx = v4l2_ctrl_new_std_menu(&info->handle,
- &m5mols_ctrl_ops, V4L2_CID_COLORFX,
- 9, 1, V4L2_COLORFX_NONE);
- info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle,
- &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
- 1, 0, V4L2_EXPOSURE_AUTO);
- info->exposure = v4l2_ctrl_new_std(&info->handle,
- &m5mols_ctrl_ops, V4L2_CID_EXPOSURE,
- 0, max_ex_mon, 1, (int)max_ex_mon/2);
- info->autofocus = v4l2_ctrl_new_std(&info->handle,
- &m5mols_ctrl_ops, V4L2_CID_FOCUS_AUTO,
- 0, 1, 1, 0);
+ v4l2_ctrl_handler_init(&info->handle, 6);
info->autowb = v4l2_ctrl_new_std(&info->handle,
&m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE,
- 0, 1, 1, 1);
+ 0, 1, 1, 0);
info->saturation = v4l2_ctrl_new_std(&info->handle,
&m5mols_ctrl_ops, V4L2_CID_SATURATION,
- 0, 6, 1, 3);
+ 1, 5, 1, 3);
info->zoom = v4l2_ctrl_new_std(&info->handle,
&m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE,
- 0, 70, 1, 0);
- info->jpeg_size = v4l2_ctrl_new_custom(&info->handle,
- &ctrl_private[0],
- NULL);
- info->encoded_size = v4l2_ctrl_new_custom(&info->handle,
- &ctrl_private[1],
- NULL);
+ 1, 70, step_zoom, 1);
+ info->exposure = v4l2_ctrl_new_std(&info->handle,
+ &m5mols_ctrl_ops, V4L2_CID_EXPOSURE,
+ 0, max_exposure, 1, (int)max_exposure/2);
+ info->colorfx = v4l2_ctrl_new_std_menu(&info->handle,
+ &m5mols_ctrl_ops, V4L2_CID_COLORFX,
+ 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE);
+ info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle,
+ &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
+ 1, 0, V4L2_EXPOSURE_MANUAL);
sd->ctrl_handler = &info->handle;
-
if (info->handle.error) {
- dev_err(&client->dev, "Failed to init controls, %d\n", ret);
+ v4l2_err(sd, "Failed to initialize controls: %d\n", ret);
v4l2_ctrl_handler_free(&info->handle);
return info->handle.error;
}
v4l2_ctrl_cluster(2, &info->autoexposure);
- /* If above ctrl value is not good image, so it is better that not set */
- v4l2_ctrl_handler_setup(&info->handle);
return 0;
}
-/*
- * m5mols_setup_default - set default size & fps in the monitor mode.
+/**
+ * m5mols_s_power - Main sensor power control function
+ *
+ * To prevent breaking the lens when the sensor is powered off the Soft-Landing
+ * algorithm is called where available. The Soft-Landing algorithm availability
+ * dependends on the firmware provider.
*/
-static int m5mols_setup_default(struct v4l2_subdev *sd)
-{
- struct m5mols_info *info = to_m5mols(sd);
- int value;
- int ret = -EINVAL;
-
- value = get_res_preset(sd,
- default_fmt[M5MOLS_RES_MON].width,
- default_fmt[M5MOLS_RES_MON].height,
- M5MOLS_RES_MON);
- if (value >= 0)
- ret = i2c_w8_param(sd, CAT1_MONITOR_SIZE, (u8)value);
- if (!ret)
- ret = i2c_w8_param(sd, CAT1_MONITOR_FPS,
- m5mols_reg_fps[default_fps.denominator]);
- if (!ret)
- ret = m5mols_init_controls(info);
- if (!ret)
- ret = m5mols_set_ae_lock(info, false);
- if (!ret)
- ret = m5mols_set_awb_lock(info, false);
- if (!ret) {
- info->fmt[M5MOLS_RES_MON] = default_fmt[M5MOLS_RES_MON];
- info->tpf = default_fps;
-
- ret = 0;
- }
-
- return ret;
-}
-
static int m5mols_s_power(struct v4l2_subdev *sd, int on)
{
struct m5mols_info *info = to_m5mols(sd);
@@ -1233,9 +811,34 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
if (!ret)
ret = m5mols_sensor_armboot(sd);
if (!ret)
- ret = m5mols_setup_default(sd);
- } else {
- ret = m5mols_sensor_power(info, false);
+ ret = m5mols_init_controls(info);
+ if (ret)
+ return ret;
+
+ info->ffmt[M5MOLS_RESTYPE_MONITOR] =
+ m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR];
+ info->ffmt[M5MOLS_RESTYPE_CAPTURE] =
+ m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE];
+ return ret;
+ }
+
+ if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
+ ret = m5mols_mode(info, REG_MONITOR);
+ if (!ret)
+ ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP);
+ if (!ret)
+ ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
+ if (!ret)
+ ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS,
+ REG_AF_IDLE);
+ if (!ret)
+ v4l2_info(sd, "Success soft-landing lens\n");
+ }
+
+ ret = m5mols_sensor_power(info, false);
+ if (!ret) {
+ v4l2_ctrl_handler_free(&info->handle);
+ info->ctrl_sync = false;
}
return ret;
@@ -1251,334 +854,168 @@ static int m5mols_log_status(struct v4l2_subdev *sd)
}
static const struct v4l2_subdev_core_ops m5mols_core_ops = {
- .s_power = m5mols_s_power,
- .g_ctrl = v4l2_subdev_g_ctrl,
- .s_ctrl = v4l2_subdev_s_ctrl,
- .queryctrl = v4l2_subdev_queryctrl,
- .querymenu = v4l2_subdev_querymenu,
- .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
- .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
- .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
- .log_status = m5mols_log_status,
-};
-
-/**
- * __find_restype - Lookup M-5MOLS resolution type according to pixel code
- * @code: pixel code
- */
-static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code)
-{
- enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
-
- do {
- if (code == default_fmt[type].code)
- return type;
- } while (type++ != SIZE_DEFAULT_FFMT);
-
- return 0;
-}
-
-/**
- * __find_resolution - Lookup preset and type of M-5MOLS's resolution
- * @mf: pixel format to find/negotiate the resolution preset for
- * @type: M-5MOLS resolution type
- * @resolution: M-5MOLS resolution preset register value
- *
- * Find nearest resolution matching resolution preset and adjust mf
- * to supported values.
- */
-static int __find_resolution(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf,
- enum m5mols_restype *type,
- u32 *resolution)
-{
- const struct m5mols_resolution *fsize = &m5mols_resolutions[0];
- const struct m5mols_resolution *match = NULL;
- enum m5mols_restype stype = __find_restype(mf->code);
- int i = ARRAY_SIZE(m5mols_resolutions);
- unsigned int min_err = ~0;
-
- while (i--) {
- int err;
- if (stype == fsize->type) {
- err = abs(fsize->width - mf->width)
- + abs(fsize->height - mf->height);
-
- if (err < min_err) {
- min_err = err;
- match = fsize;
- }
- }
- fsize++;
- }
- if (match) {
- mf->width = match->width;
- mf->height = match->height;
- *resolution = match->value;
- *type = stype;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
- struct v4l2_subdev_fh *fh,
- enum v4l2_subdev_format_whence which,
- enum m5mols_restype type)
-{
- if (which == V4L2_SUBDEV_FORMAT_TRY)
- return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
-
- return &info->fmt[type];
-}
-
-static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *fmt)
-{
- struct m5mols_info *info = to_m5mols(sd);
- struct v4l2_mbus_framefmt *format;
-
- if (fmt->pad != 0)
- return -EINVAL;
-
- format = __find_format(info, fh, fmt->which, info->res_type);
- if (!format)
- return -EINVAL;
-
- fmt->format = *format;
- return 0;
-}
-
-static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *fmt)
-{
- struct m5mols_info *info = to_m5mols(sd);
- struct v4l2_mbus_framefmt *format = &fmt->format;
- struct v4l2_mbus_framefmt *sfmt;
- enum m5mols_restype type;
- u32 resolution = 0;
- int ret;
-
- if (fmt->pad != 0)
- return -EINVAL;
-
- ret = __find_resolution(sd, format, &type, &resolution);
- if (ret < 0)
- return ret;
-
- sfmt = __find_format(info, fh, fmt->which, type);
- if (!sfmt)
- return 0;
-
- sfmt = &default_fmt[type];
- sfmt->width = format->width;
- sfmt->height = format->height;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- info->resolution = resolution;
- info->code = format->code;
- info->res_type = type;
- }
-
- return 0;
-}
-
-static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- if (!code || code->index >= SIZE_DEFAULT_FFMT)
- return -EINVAL;
-
- code->code = default_fmt[code->index].code;
-
- return 0;
-}
-
-static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
- .enum_mbus_code = m5mols_enum_mbus_code,
- .get_fmt = m5mols_get_fmt,
- .set_fmt = m5mols_set_fmt,
+ .s_power = m5mols_s_power,
+ .g_ctrl = v4l2_subdev_g_ctrl,
+ .s_ctrl = v4l2_subdev_s_ctrl,
+ .queryctrl = v4l2_subdev_queryctrl,
+ .querymenu = v4l2_subdev_querymenu,
+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+ .log_status = m5mols_log_status,
};
static const struct v4l2_subdev_ops m5mols_ops = {
- .core = &m5mols_core_ops,
- .pad = &m5mols_pad_ops,
- .video = &m5mols_video_ops,
+ .core = &m5mols_core_ops,
+ .pad = &m5mols_pad_ops,
+ .video = &m5mols_video_ops,
};
-static int m5mols_link_setup(struct media_entity *entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags)
-{
- printk("%s\n", __func__);
- return 0;
-}
-static const struct media_entity_operations m5mols_media_ops = {
- .link_setup = m5mols_link_setup,
-};
-
-static int m5mols_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+static void m5mols_irq_work(struct work_struct *work)
{
- struct v4l2_subdev_format format;
+ struct m5mols_info *info =
+ container_of(work, struct m5mols_info, work_irq);
+ struct v4l2_subdev *sd = &info->sd;
+ u8 reg;
+ int ret;
- memset(&format, 0, sizeof(format));
- format.pad = 0;
- format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- format.format.code = m5mols_formats[M5MOLS_RES_MON].code;
- format.format.width = DEFAULT_SENSOR_WIDTH;
- format.format.height = DEFAULT_SENSOR_HEIGHT;
+ if (!is_powered(info) ||
+ m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt))
+ return;
- m5mols_set_fmt(sd, fh, &format);
+ switch (info->interrupt & REG_INT_MASK) {
+ case REG_INT_AF:
+ if (!is_available_af(info))
+ break;
+ ret = m5mols_read_u8(sd, AF_STATUS, &reg);
+ v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
+ reg == REG_AF_FAIL ? "Failed" :
+ reg == REG_AF_SUCCESS ? "Success" :
+ reg == REG_AF_IDLE ? "Idle" : "Busy");
+ break;
+ case REG_INT_CAPTURE:
+ if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags))
+ wake_up_interruptible(&info->irq_waitq);
- return 0;
+ v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n");
+ break;
+ default:
+ v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg);
+ break;
+ };
}
-static int m5mols_subdev_close(struct v4l2_subdev *sd,
- struct v4l2_subdev_fh *fh)
+static irqreturn_t m5mols_irq_handler(int irq, void *data)
{
- v4l2_dbg(1, m5mols_debug, sd, "%s", __func__);
- return 0;
-}
+ struct v4l2_subdev *sd = data;
+ struct m5mols_info *info = to_m5mols(sd);
-static int m5mols_subdev_registered(struct v4l2_subdev *sd)
-{
- v4l2_dbg(1, m5mols_debug, sd, "%s", __func__);
- return 0;
-}
+ schedule_work(&info->work_irq);
-static void m5mols_subdev_unregistered(struct v4l2_subdev *sd)
-{
- v4l2_dbg(1, m5mols_debug, sd, "%s", __func__);
+ return IRQ_HANDLED;
}
-static const struct v4l2_subdev_internal_ops m5mols_v4l2_internal_ops = {
- .open = m5mols_init_formats,
- .close = m5mols_subdev_close,
- .registered = m5mols_subdev_registered,
- .unregistered = m5mols_subdev_unregistered,
-};
-
-static int m5mols_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int __devinit m5mols_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- const struct m5mols_platform_data *pdata =
- client->dev.platform_data;
+ const struct m5mols_platform_data *pdata = client->dev.platform_data;
struct m5mols_info *info;
struct v4l2_subdev *sd;
- int ret = 0;
+ int ret;
if (pdata == NULL) {
dev_err(&client->dev, "No platform data\n");
return -EINVAL;
}
- if (!gpio_is_valid(pdata->gpio_rst)) {
- dev_err(&client->dev, "No valid nRST gpio pin.\n");
+ if (!gpio_is_valid(pdata->gpio_reset)) {
+ dev_err(&client->dev, "No valid RESET GPIO specified\n");
return -EINVAL;
}
- if (!pdata->irq) {
- dev_err(&client->dev, "Interrupt not assigned.\n");
+ if (!client->irq) {
+ dev_err(&client->dev, "Interrupt not assigned\n");
return -EINVAL;
}
info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL);
- if (info == NULL) {
- dev_err(&client->dev, "Failed to allocate info\n");
+ if (!info)
return -ENOMEM;
- }
- info->pdata = pdata;
- if (info->pdata->set_power) /* for additional power if needed. */
- info->set_power = pdata->set_power;
+ info->pdata = pdata;
+ info->set_power = pdata->set_power;
- if (info->pdata->irq) {
- INIT_WORK(&info->work, m5mols_irq_work);
- ret = request_irq(info->pdata->irq, m5mols_irq_handler,
- IRQF_TRIGGER_RISING, MOD_NAME, &info->sd);
- if (ret) {
- dev_err(&client->dev, "Failed to request irq: %d\n", ret);
- return ret;
- }
- }
-
- ret = gpio_request(info->pdata->gpio_rst, "M5MOLS nRST");
+ ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST");
if (ret) {
- dev_err(&client->dev, "Failed to set gpio, %d\n", ret);
- goto out_gpio;
+ dev_err(&client->dev, "Failed to request gpio: %d\n", ret);
+ goto out_free;
}
-
- gpio_direction_output(info->pdata->gpio_rst, !info->pdata->enable_rst);
+ gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity);
ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies);
if (ret) {
- dev_err(&client->dev, "Failed to get regulators, %d\n", ret);
- goto out_reg;
+ dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
+ goto out_gpio;
}
sd = &info->sd;
- strlcpy(sd->name, MOD_NAME, sizeof(sd->name));
-
- init_waitqueue_head(&info->cap_wait);
-
+ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
+
info->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
if (ret < 0)
goto out_reg;
-
- m5mols_init_formats(sd, NULL);
-
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
- sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
- sd->internal_ops = &m5mols_v4l2_internal_ops;
- sd->entity.ops = &m5mols_media_ops;
+ init_waitqueue_head(&info->irq_waitq);
+ INIT_WORK(&info->work_irq, m5mols_irq_work);
+ ret = request_irq(client->irq, m5mols_irq_handler,
+ IRQF_TRIGGER_RISING, MODULE_NAME, sd);
+ if (ret) {
+ dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
+ goto out_me;
+ }
info->res_type = M5MOLS_RESTYPE_MONITOR;
-
- v4l2_info(sd, "%s : m5mols driver probed success\n", __func__);
-
return 0;
-
+out_me:
+ media_entity_cleanup(&sd->entity);
out_reg:
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
out_gpio:
- gpio_free(info->pdata->gpio_rst);
+ gpio_free(pdata->gpio_reset);
+out_free:
kfree(info);
-
return ret;
}
-static int m5mols_remove(struct i2c_client *client)
+static int __devexit m5mols_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct m5mols_info *info = to_m5mols(sd);
v4l2_device_unregister_subdev(sd);
- v4l2_ctrl_handler_free(&info->handle);
- free_irq(info->pdata->irq, sd);
+ free_irq(client->irq, sd);
+
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
- gpio_free(info->pdata->gpio_rst);
+ gpio_free(info->pdata->gpio_reset);
media_entity_cleanup(&sd->entity);
kfree(info);
-
return 0;
}
static const struct i2c_device_id m5mols_id[] = {
- { MOD_NAME, 0 },
+ { MODULE_NAME, 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, m5mols_id);
static struct i2c_driver m5mols_i2c_driver = {
.driver = {
- .name = MOD_NAME,
+ .name = MODULE_NAME,
},
.probe = m5mols_probe,
- .remove = m5mols_remove,
+ .remove = __devexit_p(m5mols_remove),
.id_table = m5mols_id,
};
@@ -1597,5 +1034,5 @@ module_exit(m5mols_mod_exit);
MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>");
-MODULE_DESCRIPTION("Fujitsu M5MOLS 8M Pixel camera sensor with ISP driver");
+MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h
index da9cab5..c755bd6 100644
--- a/drivers/media/video/m5mols/m5mols_reg.h
+++ b/drivers/media/video/m5mols/m5mols_reg.h
@@ -1,5 +1,5 @@
/*
- * Register map for M5MOLS 8M Pixel camera sensor with ISP
+ * Register map for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -16,104 +16,258 @@
#ifndef M5MOLS_REG_H
#define M5MOLS_REG_H
+#define M5MOLS_I2C_MAX_SIZE 4
+#define M5MOLS_BYTE_READ 0x01
+#define M5MOLS_BYTE_WRITE 0x02
+
+#define I2C_CATEGORY(__cat) ((__cat >> 16) & 0xff)
+#define I2C_COMMAND(__comm) ((__comm >> 8) & 0xff)
+#define I2C_SIZE(__reg_s) ((__reg_s) & 0xff)
+#define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s)
+
/*
* Category section register
*
- * The category means a kind of command set. Including category section,
- * all defined categories in this version supports only, as you see below:
+ * The category means set including relevant command of M-5MOLS.
*/
#define CAT_SYSTEM 0x00
#define CAT_PARAM 0x01
-#define CAT_MON 0x02
+#define CAT_MONITOR 0x02
#define CAT_AE 0x03
#define CAT_WB 0x06
#define CAT_EXIF 0x07
+#define CAT_FD 0x09
#define CAT_LENS 0x0a
-#define CAT_CAPTURE_PARAMETER 0x0b
-#define CAT_CAPTURE_CONTROL 0x0c
-#define CAT_FLASH 0x0f /* related with FW, Verions, booting */
+#define CAT_CAPT_PARM 0x0b
+#define CAT_CAPT_CTRL 0x0c
+#define CAT_FLASH 0x0f /* related to FW, revisions, booting */
/*
- * Category 0 - System
+ * Category 0 - SYSTEM mode
+ *
+ * The SYSTEM mode in the M-5MOLS means area available to handle with the whole
+ * & all-round system of sensor. It deals with version/interrupt/setting mode &
+ * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by
+ * packaging & manufacturer, even the customer and project code. And the
+ * function details may vary among them. The version information helps to
+ * determine what methods shall be used in the driver.
*
- * This category supports FW version, managing mode, even interrupt.
+ * There is many registers between customer version address and awb one. For
+ * more specific contents, see definition if file m5mols.h.
*/
-#define CAT0_CUSTOMER_CODE 0x00
-#define CAT0_PJ_CODE 0x01
-#define CAT0_VERSION_FW_H 0x02
-#define CAT0_VERSION_FW_L 0x03
-#define CAT0_VERSION_HW_H 0x04
-#define CAT0_VERSION_HW_L 0x05
-#define CAT0_VERSION_PARM_H 0x06
-#define CAT0_VERSION_PARM_L 0x07
-#define CAT0_VERSION_AWB_H 0x08
-#define CAT0_VERSION_AWB_L 0x09
-#define CAT0_SYSMODE 0x0b
-#define CAT0_STATUS 0x0c
-#define CAT0_INT_QUEUE 0x0e
-#define CAT0_INT_FACTOR 0x10 /* ver 10bit: 0x10, other 0x1c */
-#define CAT0_INT_ENABLE 0x11 /* ver 10bit: 0x11, other 0x10 */
-#define CAT0_INT_ROOTEN 0x12
-#define CAT0_INT_INFO 0x18
+#define CAT0_VER_CUSTOMER 0x00 /* customer version */
+#define CAT0_VER_PROJECT 0x01 /* project version */
+#define CAT0_VER_FIRMWARE 0x02 /* Firmware version */
+#define CAT0_VER_HARDWARE 0x04 /* Hardware version */
+#define CAT0_VER_PARAMETER 0x06 /* Parameter version */
+#define CAT0_VER_AWB 0x08 /* Auto WB version */
+#define CAT0_VER_STRING 0x0a /* string including M-5MOLS */
+#define CAT0_SYSMODE 0x0b /* SYSTEM mode register */
+#define CAT0_STATUS 0x0c /* SYSTEM mode status register */
+#define CAT0_INT_FACTOR 0x10 /* interrupt pending register */
+#define CAT0_INT_ENABLE 0x11 /* interrupt enable register */
+
+#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1)
+#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1)
+#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2)
+#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2)
+#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2)
+#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2)
+
+#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1)
+#define REG_SYSINIT 0x00 /* SYSTEM mode */
+#define REG_PARAMETER 0x01 /* PARAMETER mode */
+#define REG_MONITOR 0x02 /* MONITOR mode */
+#define REG_CAPTURE 0x03 /* CAPTURE mode */
+
+#define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1)
+#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1)
+#define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */
+#define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */
+#define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */
+
+#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1)
+#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1)
+#define REG_INT_MODE (1 << 0)
+#define REG_INT_AF (1 << 1)
+#define REG_INT_ZOOM (1 << 2)
+#define REG_INT_CAPTURE (1 << 3)
+#define REG_INT_FRAMESYNC (1 << 4)
+#define REG_INT_FD (1 << 5)
+#define REG_INT_LENS_INIT (1 << 6)
+#define REG_INT_SOUND (1 << 7)
+#define REG_INT_MASK 0x0f
/*
- * category 1 - Parameter mode
+ * category 1 - PARAMETER mode
*
- * This category is dealing with almost camera vendor. In spite of that,
- * It's a register to be able to detailed value for whole camera syste.
- * The key parameter like a resolution, FPS, data interface connecting
- * with Mobile AP, even effects.
+ * This category supports function of camera features of M-5MOLS. It means we
+ * can handle with preview(MONITOR) resolution size/frame per second/interface
+ * between the sensor and the Application Processor/even the image effect.
*/
-#define CAT1_DATA_INTERFACE 0x00
-#define CAT1_MONITOR_SIZE 0x01
-#define CAT1_MONITOR_FPS 0x02
-#define CAT1_EFFECT 0x0b
+#define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */
+#define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */
+#define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */
+#define CAT1_EFFECT 0x0b /* image effects */
+
+#define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1)
+
+#define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1)
+#define REG_FPS_30 0x02
+
+#define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1)
+#define REG_INTERFACE_MIPI 0x02
+
+#define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1)
+#define REG_EFFECT_OFF 0x00
+#define REG_EFFECT_NEGA 0x01
+#define REG_EFFECT_EMBOSS 0x06
+#define REG_EFFECT_OUTLINE 0x07
+#define REG_EFFECT_WATERCOLOR 0x08
/*
- * Category 2 - Monitor mode
+ * Category 2 - MONITOR mode
*
- * This category supports only monitoring mode. The monitoring mode means,
- * similar to preview. It supports like a YUYV format. At the capture mode,
- * it is handled like a JPEG & RAW formats.
+ * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another
+ * mode named "Preview", but this preview mode is used at the case specific
+ * vider-recording mode. This mmode supports only YUYV format. On the other
+ * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are
+ * another options like zoom/color effect(different with effect in PARAMETER
+ * mode)/anti hand shaking algorithm.
*/
-#define CAT2_ZOOM 0x01
-#define CAT2_ZOOM_POSITION 0x02
-#define CAT2_ZOOM_STEP 0x03
-#define CAT2_CFIXB 0x09
-#define CAT2_CFIXR 0x0a
-#define CAT2_COLOR_EFFECT 0x0b
-#define CAT2_CHROMA_LVL 0x0f
-#define CAT2_CHROMA_EN 0x10
+#define CAT2_ZOOM 0x01 /* set the zoom position & execute */
+#define CAT2_ZOOM_STEP 0x03 /* set the zoom step */
+#define CAT2_CFIXB 0x09 /* CB value for color effect */
+#define CAT2_CFIXR 0x0a /* CR value for color effect */
+#define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */
+#define CAT2_CHROMA_LVL 0x0f /* set chroma level */
+#define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */
+#define CAT2_EDGE_LVL 0x11 /* set sharpness level */
+#define CAT2_EDGE_EN 0x12 /* set on/off sharpness */
+#define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */
+
+#define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1)
+
+#define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1)
+#define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1)
+#define REG_CFIXB_SEPIA 0xd8
+#define REG_CFIXR_SEPIA 0x18
+
+#define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1)
+#define REG_COLOR_EFFECT_OFF 0x00
+#define REG_COLOR_EFFECT_ON 0x01
+
+#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1)
+#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1)
+#define REG_CHROMA_OFF 0x00
+#define REG_CHROMA_ON 0x01
+
+#define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1)
+#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1)
+#define REG_EDGE_OFF 0x00
+#define REG_EDGE_ON 0x01
+
+#define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1)
/*
* Category 3 - Auto Exposure
*
- * Currently, it supports only gain value with monitor mode. This device
- * is able to support Shutter, Gain(similar with Aperture), Flicker, at
- * monitor mode & capture mode both.
+ * The M-5MOLS exposure capbility is detailed as which is similar to digital
+ * camera. This category supports AE locking/various AE mode(range of exposure)
+ * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the
+ * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be
+ * different. So, this category also provide getting the max/min values. And,
+ * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values.
*/
-#define CAT3_AE_LOCK 0x00
-#define CAT3_AE_MODE 0x01
-#define CAT3_MANUAL_GAIN_MON 0x12 /* 2 bytes operations belows */
-#define CAT3_MANUAL_SHUT_MON 0x14
-#define CAT3_MAX_EXPOSURE_MON 0x16
-#define CAT3_MAX_EXPOSURE_CAP 0x18
-#define CAT3_MAX_GAIN_MON 0x1a
-#define CAT3_MAX_GAIN_CAP 0x1c
-#define CAT3_MANUAL_GAIN_CAP 0x26
-#define CAT3_MANUAL_SHUT_CAP 0x28
+#define CAT3_AE_LOCK 0x00 /* locking Auto exposure */
+#define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */
+#define CAT3_ISO 0x05 /* set ISO */
+#define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */
+#define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */
+#define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */
+#define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */
+#define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */
+#define CAT3_AE_INDEX 0x38 /* AE index */
+
+#define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1)
+#define REG_AE_UNLOCK 0x00
+#define REG_AE_LOCK 0x01
+
+#define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1)
+#define REG_AE_OFF 0x00 /* AE off */
+#define REG_AE_ALL 0x01 /* calc AE in all block integral */
+#define REG_AE_CENTER 0x03 /* calc AE in center weighted */
+#define REG_AE_SPOT 0x06 /* calc AE in specific spot */
+
+#define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1)
+#define REG_ISO_AUTO 0x00
+#define REG_ISO_50 0x01
+#define REG_ISO_100 0x02
+#define REG_ISO_200 0x03
+#define REG_ISO_400 0x04
+#define REG_ISO_800 0x05
+
+#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1)
+#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1)
+#define REG_SCENE_NORMAL 0x00
+#define REG_SCENE_PORTRAIT 0x01
+#define REG_SCENE_LANDSCAPE 0x02
+#define REG_SCENE_SPORTS 0x03
+#define REG_SCENE_PARTY_INDOOR 0x04
+#define REG_SCENE_BEACH_SNOW 0x05
+#define REG_SCENE_SUNSET 0x06
+#define REG_SCENE_DAWN_DUSK 0x07
+#define REG_SCENE_FALL 0x08
+#define REG_SCENE_NIGHT 0x09
+#define REG_SCENE_AGAINST_LIGHT 0x0a
+#define REG_SCENE_FIRE 0x0b
+#define REG_SCENE_TEXT 0x0c
+#define REG_SCENE_CANDLE 0x0d
+
+#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2)
+#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2)
+#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2)
+
+#define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1)
+#define REG_AE_INDEX_20_NEG 0x00
+#define REG_AE_INDEX_15_NEG 0x01
+#define REG_AE_INDEX_10_NEG 0x02
+#define REG_AE_INDEX_05_NEG 0x03
+#define REG_AE_INDEX_00 0x04
+#define REG_AE_INDEX_05_POS 0x05
+#define REG_AE_INDEX_10_POS 0x06
+#define REG_AE_INDEX_15_POS 0x07
+#define REG_AE_INDEX_20_POS 0x08
/*
* Category 6 - White Balance
*
- * Currently, it supports only auto white balance.
+ * This category provide AWB locking/mode/preset/speed/gain bias, etc.
*/
-#define CAT6_AWB_LOCK 0x00
-#define CAT6_AWB_MODE 0x02
-#define CAT6_AWB_MANUAL 0x03
+#define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */
+#define CAT6_AWB_MODE 0x02 /* set Auto or Manual */
+#define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */
+
+#define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1)
+#define REG_AWB_UNLOCK 0x00
+#define REG_AWB_LOCK 0x01
+
+#define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1)
+#define REG_AWB_AUTO 0x01 /* AWB off */
+#define REG_AWB_PRESET 0x02 /* AWB preset */
+
+#define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1)
+#define REG_AWB_INCANDESCENT 0x01
+#define REG_AWB_FLUORESCENT_1 0x02
+#define REG_AWB_FLUORESCENT_2 0x03
+#define REG_AWB_DAYLIGHT 0x04
+#define REG_AWB_CLOUDY 0x05
+#define REG_AWB_SHADE 0x06
+#define REG_AWB_HORIZON 0x07
+#define REG_AWB_LEDLIGHT 0x09
/*
- * Category 7 - EXIF Information
+ * Category 7 - EXIF information
*/
#define CAT7_INFO_EXPTIME_NU 0x00
#define CAT7_INFO_EXPTIME_DE 0x04
@@ -130,35 +284,127 @@
#define CAT7_INFO_SDR 0x2c
#define CAT7_INFO_QVAL 0x2e
+#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4)
+#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4)
+#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4)
+#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4)
+#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4)
+#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4)
+#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4)
+#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4)
+#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4)
+#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4)
+#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2)
+#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2)
+#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2)
+#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2)
+
+/*
+ * Category 9 - Face Detection
+ */
+#define CAT9_FD_CTL 0x00
+
+#define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1)
+#define BIT_FD_EN 0
+#define BIT_FD_DRAW_FACE_FRAME 4
+#define BIT_FD_DRAW_SMILE_LVL 6
+#define REG_FD(shift) (1 << shift)
+#define REG_FD_OFF 0x0
+
/*
* Category A - Lens Parameter
*/
-#define CATA_INIT_AF_FUNC 0x00
#define CATA_AF_MODE 0x01
-#define CATA_AF_EXCUTE 0x02
+#define CATA_AF_EXECUTE 0x02
#define CATA_AF_STATUS 0x03
#define CATA_AF_VERSION 0x0a
+#define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1)
+#define REG_AF_NORMAL 0x00 /* Normal AF, one time */
+#define REG_AF_MACRO 0x01 /* Macro AF, one time */
+#define REG_AF_POWEROFF 0x07
+
+#define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1)
+#define REG_AF_STOP 0x00
+#define REG_AF_EXE_AUTO 0x01
+#define REG_AF_EXE_CAF 0x02
+
+#define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1)
+#define REG_AF_FAIL 0x00
+#define REG_AF_SUCCESS 0x02
+#define REG_AF_IDLE 0x04
+#define REG_AF_BUSY 0x05
+
+#define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1)
+
/*
- * Category B - Capture Parameter
+ * Category B - CAPTURE Parameter
*/
#define CATB_YUVOUT_MAIN 0x00
#define CATB_MAIN_IMAGE_SIZE 0x01
+#define CATB_MCC_MODE 0x1d
+#define CATB_WDR_EN 0x2c
+#define CATB_LIGHT_CTRL 0x40
+#define CATB_FLASH_CTRL 0x41
+
+#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1)
+#define REG_YUV422 0x00
+#define REG_BAYER10 0x05
+#define REG_BAYER8 0x06
+#define REG_JPEG 0x10
+
+#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1)
+
+#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1)
+#define REG_MCC_OFF 0x00
+#define REG_MCC_NORMAL 0x01
+
+#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1)
+#define REG_WDR_OFF 0x00
+#define REG_WDR_ON 0x01
+#define REG_WDR_AUTO 0x02
+
+#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1)
+#define REG_LIGHT_OFF 0x00
+#define REG_LIGHT_ON 0x01
+#define REG_LIGHT_AUTO 0x02
+
+#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1)
+#define REG_FLASH_OFF 0x00
+#define REG_FLASH_ON 0x01
+#define REG_FLASH_AUTO 0x02
/*
- * Category C - Capture Control
+ * Category C - CAPTURE Control
*/
-#define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi. */
+#define CATC_CAP_MODE 0x00
+#define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */
#define CATC_CAP_START 0x09
#define CATC_CAP_IMAGE_SIZE 0x0d
#define CATC_CAP_THUMB_SIZE 0x11
+#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1)
+#define REG_CAP_NONE 0x00
+#define REG_CAP_ANTI_SHAKE 0x02
+
+#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1)
+
+#define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1)
+#define REG_CAP_START_MAIN 0x01
+#define REG_CAP_START_THUMB 0x03
+
+#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4)
+#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4)
+
/*
* Category F - Flash
*
- * This mode provides functions about internal Flash works and System startup.
+ * This mode provides functions about internal flash stuff and system startup.
*/
-#define CATC_CAM_START 0x12 /* It start internal ARM core booting
+#define CATF_CAM_START 0x12 /* It starts internal ARM core booting
* after power-up */
+#define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1)
+#define REG_START_ARM_BOOT 0x01
+
#endif /* M5MOLS_REG_H */
diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig
index e63233fd..390ab09 100644
--- a/drivers/media/video/omap/Kconfig
+++ b/drivers/media/video/omap/Kconfig
@@ -1,11 +1,14 @@
+config VIDEO_OMAP2_VOUT_VRFB
+ bool
+
config VIDEO_OMAP2_VOUT
tristate "OMAP2/OMAP3 V4L2-Display driver"
depends on ARCH_OMAP2 || ARCH_OMAP3
select VIDEOBUF_GEN
select VIDEOBUF_DMA_CONTIG
select OMAP2_DSS
- select OMAP2_VRAM
- select OMAP2_VRFB
+ select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
+ select VIDEO_OMAP2_VOUT_VRFB if VIDEO_OMAP2_VOUT && OMAP2_VRFB
default n
---help---
V4L2 Display driver support for OMAP2/3 based boards.
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
index b287880..fc410b4 100644
--- a/drivers/media/video/omap/Makefile
+++ b/drivers/media/video/omap/Makefile
@@ -4,4 +4,5 @@
# OMAP2/3 Display driver
omap-vout-y := omap_vout.o omap_voutlib.o
+omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o
obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 4d07c58..d345215 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -35,9 +35,9 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
#include <linux/irq.h>
#include <linux/videodev2.h>
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <media/videobuf-dma-contig.h>
@@ -45,18 +45,17 @@
#include <media/v4l2-ioctl.h>
#include <plat/dma.h>
-#include <plat/vram.h>
#include <plat/vrfb.h>
#include <video/omapdss.h>
#include "omap_voutlib.h"
#include "omap_voutdef.h"
+#include "omap_vout_vrfb.h"
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
MODULE_LICENSE("GPL");
-
/* Driver Configuration macros */
#define VOUT_NAME "omap_vout"
@@ -65,31 +64,6 @@ enum omap_vout_channels {
OMAP_VIDEO2,
};
-enum dma_channel_state {
- DMA_CHAN_NOT_ALLOTED,
- DMA_CHAN_ALLOTED,
-};
-
-#define QQVGA_WIDTH 160
-#define QQVGA_HEIGHT 120
-
-/* Max Resolution supported by the driver */
-#define VID_MAX_WIDTH 1280 /* Largest width */
-#define VID_MAX_HEIGHT 720 /* Largest height */
-
-/* Mimimum requirement is 2x2 for DSS */
-#define VID_MIN_WIDTH 2
-#define VID_MIN_HEIGHT 2
-
-/* 2048 x 2048 is max res supported by OMAP display controller */
-#define MAX_PIXELS_PER_LINE 2048
-
-#define VRFB_TX_TIMEOUT 1000
-#define VRFB_NUM_BUFS 4
-
-/* Max buffer size tobe allocated during init */
-#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
-
static struct videobuf_queue_ops video_vbq_ops;
/* Variables configurable through module params*/
static u32 video1_numbuffers = 3;
@@ -129,7 +103,7 @@ module_param(debug, bool, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* list of image formats supported by OMAP2 video pipelines */
-const static struct v4l2_fmtdesc omap_formats[] = {
+static const struct v4l2_fmtdesc omap_formats[] = {
{
/* Note: V4L2 defines RGB565 as:
*
@@ -172,84 +146,6 @@ const static struct v4l2_fmtdesc omap_formats[] = {
#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
/*
- * Allocate buffers
- */
-static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
-{
- u32 order, size;
- unsigned long virt_addr, addr;
-
- size = PAGE_ALIGN(buf_size);
- order = get_order(size);
- virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order);
- addr = virt_addr;
-
- if (virt_addr) {
- while (size > 0) {
- SetPageReserved(virt_to_page(addr));
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- }
- *phys_addr = (u32) virt_to_phys((void *) virt_addr);
- return virt_addr;
-}
-
-/*
- * Free buffers
- */
-static void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
-{
- u32 order, size;
- unsigned long addr = virtaddr;
-
- size = PAGE_ALIGN(buf_size);
- order = get_order(size);
-
- while (size > 0) {
- ClearPageReserved(virt_to_page(addr));
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- free_pages((unsigned long) virtaddr, order);
-}
-
-/*
- * Function for allocating video buffers
- */
-static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
- unsigned int *count, int startindex)
-{
- int i, j;
-
- for (i = 0; i < *count; i++) {
- if (!vout->smsshado_virt_addr[i]) {
- vout->smsshado_virt_addr[i] =
- omap_vout_alloc_buffer(vout->smsshado_size,
- &vout->smsshado_phy_addr[i]);
- }
- if (!vout->smsshado_virt_addr[i] && startindex != -1) {
- if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex)
- break;
- }
- if (!vout->smsshado_virt_addr[i]) {
- for (j = 0; j < i; j++) {
- omap_vout_free_buffer(
- vout->smsshado_virt_addr[j],
- vout->smsshado_size);
- vout->smsshado_virt_addr[j] = 0;
- vout->smsshado_phy_addr[j] = 0;
- }
- *count = 0;
- return -ENOMEM;
- }
- memset((void *) vout->smsshado_virt_addr[i], 0,
- vout->smsshado_size);
- }
- return 0;
-}
-
-/*
* Try format
*/
static int omap_vout_try_format(struct v4l2_pix_format *pix)
@@ -310,19 +206,21 @@ static u32 omap_vout_uservirt_to_phys(u32 virtp)
struct vm_area_struct *vma;
struct mm_struct *mm = current->mm;
- vma = find_vma(mm, virtp);
/* For kernel direct-mapped memory, take the easy way */
- if (virtp >= PAGE_OFFSET) {
- physp = virt_to_phys((void *) virtp);
- } else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
+ if (virtp >= PAGE_OFFSET)
+ return virt_to_phys((void *) virtp);
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(mm, virtp);
+ if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
/* this will catch, kernel-allocated, mmaped-to-usermode
addresses */
physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
+ up_read(&current->mm->mmap_sem);
} else {
/* otherwise, use get_user_pages() for general userland pages */
int res, nr_pages = 1;
struct page *pages;
- down_read(&current->mm->mmap_sem);
res = get_user_pages(current, current->mm, virtp, nr_pages, 1,
0, &pages, NULL);
@@ -342,73 +240,9 @@ static u32 omap_vout_uservirt_to_phys(u32 virtp)
}
/*
- * Wakes up the application once the DMA transfer to VRFB space is completed.
- */
-static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
-{
- struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
-
- t->tx_status = 1;
- wake_up_interruptible(&t->wait);
-}
-
-/*
- * Release the VRFB context once the module exits
- */
-static void omap_vout_release_vrfb(struct omap_vout_device *vout)
-{
- int i;
-
- for (i = 0; i < VRFB_NUM_BUFS; i++)
- omap_vrfb_release_ctx(&vout->vrfb_context[i]);
-
- if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
- vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
- omap_free_dma(vout->vrfb_dma_tx.dma_ch);
- }
-}
-
-/*
- * Return true if rotation is 90 or 270
- */
-static inline int rotate_90_or_270(const struct omap_vout_device *vout)
-{
- return (vout->rotation == dss_rotation_90_degree ||
- vout->rotation == dss_rotation_270_degree);
-}
-
-/*
- * Return true if rotation is enabled
- */
-static inline int rotation_enabled(const struct omap_vout_device *vout)
-{
- return vout->rotation || vout->mirror;
-}
-
-/*
- * Reverse the rotation degree if mirroring is enabled
- */
-static inline int calc_rotation(const struct omap_vout_device *vout)
-{
- if (!vout->mirror)
- return vout->rotation;
-
- switch (vout->rotation) {
- case dss_rotation_90_degree:
- return dss_rotation_270_degree;
- case dss_rotation_270_degree:
- return dss_rotation_90_degree;
- case dss_rotation_180_degree:
- return dss_rotation_0_degree;
- default:
- return dss_rotation_180_degree;
- }
-}
-
-/*
* Free the V4L2 buffers
*/
-static void omap_vout_free_buffers(struct omap_vout_device *vout)
+void omap_vout_free_buffers(struct omap_vout_device *vout)
{
int i, numbuffers;
@@ -425,52 +259,6 @@ static void omap_vout_free_buffers(struct omap_vout_device *vout)
}
/*
- * Free VRFB buffers
- */
-static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
-{
- int j;
-
- for (j = 0; j < VRFB_NUM_BUFS; j++) {
- omap_vout_free_buffer(vout->smsshado_virt_addr[j],
- vout->smsshado_size);
- vout->smsshado_virt_addr[j] = 0;
- vout->smsshado_phy_addr[j] = 0;
- }
-}
-
-/*
- * Allocate the buffers for the VRFB space. Data is copied from V4L2
- * buffers to the VRFB buffers using the DMA engine.
- */
-static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
- unsigned int *count, unsigned int startindex)
-{
- int i;
- bool yuv_mode;
-
- /* Allocate the VRFB buffers only if the buffers are not
- * allocated during init time.
- */
- if ((rotation_enabled(vout)) && !vout->vrfb_static_allocation)
- if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
- return -ENOMEM;
-
- if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
- vout->dss_mode == OMAP_DSS_COLOR_UYVY)
- yuv_mode = true;
- else
- yuv_mode = false;
-
- for (i = 0; i < *count; i++)
- omap_vrfb_setup(&vout->vrfb_context[i],
- vout->smsshado_phy_addr[i], vout->pix.width,
- vout->pix.height, vout->bpp, yuv_mode);
-
- return 0;
-}
-
-/*
* Convert V4L2 rotation to DSS rotation
* V4L2 understand 0, 90, 180, 270.
* Convert to 0, 1, 2 and 3 respectively for DSS
@@ -499,124 +287,38 @@ static int v4l2_rot_to_dss_rot(int v4l2_rotation,
return ret;
}
-/*
- * Calculate the buffer offsets from which the streaming should
- * start. This offset calculation is mainly required because of
- * the VRFB 32 pixels alignment with rotation.
- */
static int omap_vout_calculate_offset(struct omap_vout_device *vout)
{
- struct omap_overlay *ovl;
- enum dss_rotation rotation;
struct omapvideo_info *ovid;
- bool mirroring = vout->mirror;
- struct omap_dss_device *cur_display;
struct v4l2_rect *crop = &vout->crop;
struct v4l2_pix_format *pix = &vout->pix;
int *cropped_offset = &vout->cropped_offset;
- int vr_ps = 1, ps = 2, temp_ps = 2;
- int offset = 0, ctop = 0, cleft = 0, line_length = 0;
+ int ps = 2, line_length = 0;
ovid = &vout->vid_info;
- ovl = ovid->overlays[0];
- /* get the display device attached to the overlay */
- if (!ovl->manager || !ovl->manager->device)
- return -1;
- cur_display = ovl->manager->device;
- rotation = calc_rotation(vout);
+ if (ovid->rotation_type == VOUT_ROT_VRFB) {
+ omap_vout_calculate_vrfb_offset(vout);
+ } else {
+ vout->line_length = line_length = pix->width;
- if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
- V4L2_PIX_FMT_UYVY == pix->pixelformat) {
- if (rotation_enabled(vout)) {
- /*
- * ps - Actual pixel size for YUYV/UYVY for
- * VRFB/Mirroring is 4 bytes
- * vr_ps - Virtually pixel size for YUYV/UYVY is
- * 2 bytes
- */
+ if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+ V4L2_PIX_FMT_UYVY == pix->pixelformat)
+ ps = 2;
+ else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
ps = 4;
- vr_ps = 2;
- } else {
- ps = 2; /* otherwise the pixel size is 2 byte */
- }
- } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
- ps = 4;
- } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
- ps = 3;
- }
- vout->ps = ps;
- vout->vr_ps = vr_ps;
-
- if (rotation_enabled(vout)) {
- line_length = MAX_PIXELS_PER_LINE;
- ctop = (pix->height - crop->height) - crop->top;
- cleft = (pix->width - crop->width) - crop->left;
- } else {
- line_length = pix->width;
- }
- vout->line_length = line_length;
- switch (rotation) {
- case dss_rotation_90_degree:
- offset = vout->vrfb_context[0].yoffset *
- vout->vrfb_context[0].bytespp;
- temp_ps = ps / vr_ps;
- if (mirroring == 0) {
- *cropped_offset = offset + line_length *
- temp_ps * cleft + crop->top * temp_ps;
- } else {
- *cropped_offset = offset + line_length * temp_ps *
- cleft + crop->top * temp_ps + (line_length *
- ((crop->width / (vr_ps)) - 1) * ps);
- }
- break;
- case dss_rotation_180_degree:
- offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
- vout->vrfb_context[0].bytespp) +
- (vout->vrfb_context[0].xoffset *
- vout->vrfb_context[0].bytespp));
- if (mirroring == 0) {
- *cropped_offset = offset + (line_length * ps * ctop) +
- (cleft / vr_ps) * ps;
+ else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
+ ps = 3;
- } else {
- *cropped_offset = offset + (line_length * ps * ctop) +
- (cleft / vr_ps) * ps + (line_length *
- (crop->height - 1) * ps);
- }
- break;
- case dss_rotation_270_degree:
- offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
- vout->vrfb_context[0].bytespp;
- temp_ps = ps / vr_ps;
- if (mirroring == 0) {
- *cropped_offset = offset + line_length *
- temp_ps * crop->left + ctop * ps;
- } else {
- *cropped_offset = offset + line_length *
- temp_ps * crop->left + ctop * ps +
- (line_length * ((crop->width / vr_ps) - 1) *
- ps);
- }
- break;
- case dss_rotation_0_degree:
- if (mirroring == 0) {
- *cropped_offset = (line_length * ps) *
- crop->top + (crop->left / vr_ps) * ps;
- } else {
- *cropped_offset = (line_length * ps) *
- crop->top + (crop->left / vr_ps) * ps +
- (line_length * (crop->height - 1) * ps);
- }
- break;
- default:
- *cropped_offset = (line_length * ps * crop->top) /
- vr_ps + (crop->left * ps) / vr_ps +
- ((crop->width / vr_ps) - 1) * ps;
- break;
+ vout->ps = ps;
+
+ *cropped_offset = (line_length * ps) *
+ crop->top + crop->left * ps;
}
+
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
- __func__, *cropped_offset);
+ __func__, vout->cropped_offset);
+
return 0;
}
@@ -664,7 +366,7 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout)
/*
* Setup the overlay
*/
-int omapvid_setup_overlay(struct omap_vout_device *vout,
+static int omapvid_setup_overlay(struct omap_vout_device *vout,
struct omap_overlay *ovl, int posx, int posy, int outw,
int outh, u32 addr)
{
@@ -687,7 +389,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
/* Setup the input plane parameters according to
* rotation value selected.
*/
- if (rotate_90_or_270(vout)) {
+ if (is_rotation_90_or_270(vout)) {
cropheight = vout->crop.width;
cropwidth = vout->crop.height;
pixheight = vout->pix.width;
@@ -701,7 +403,6 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
ovl->get_overlay_info(ovl, &info);
info.paddr = addr;
- info.vaddr = NULL;
info.width = cropwidth;
info.height = cropheight;
info.color_mode = vout->dss_mode;
@@ -711,7 +412,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
info.out_width = outw;
info.out_height = outh;
info.global_alpha = vout->win.global_alpha;
- if (!rotation_enabled(vout)) {
+ if (!is_rotation_enabled(vout)) {
info.rotation = 0;
info.rotation_type = OMAP_DSS_ROT_DMA;
info.screen_width = pixwidth;
@@ -744,7 +445,7 @@ setup_ovl_err:
/*
* Initialize the overlay structure
*/
-int omapvid_init(struct omap_vout_device *vout, u32 addr)
+static int omapvid_init(struct omap_vout_device *vout, u32 addr)
{
int ret = 0, i;
struct v4l2_window *win;
@@ -809,7 +510,7 @@ omapvid_init_err:
/*
* Apply the changes set the go bit of DSS
*/
-int omapvid_apply_changes(struct omap_vout_device *vout)
+static int omapvid_apply_changes(struct omap_vout_device *vout)
{
int i;
struct omap_overlay *ovl;
@@ -825,7 +526,7 @@ int omapvid_apply_changes(struct omap_vout_device *vout)
return 0;
}
-void omap_vout_isr(void *arg, unsigned int irqstatus)
+static void omap_vout_isr(void *arg, unsigned int irqstatus)
{
int ret;
u32 addr, fid;
@@ -848,10 +549,20 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
spin_lock(&vout->vbq_lock);
do_gettimeofday(&timevalue);
- if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) {
- if (!(irqstatus & DISPC_IRQ_VSYNC))
- goto vout_isr_err;
+ if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) {
+ switch (cur_display->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+ if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2)))
+ goto vout_isr_err;
+ break;
+ case OMAP_DISPLAY_TYPE_HDMI:
+ if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
+ goto vout_isr_err;
+ break;
+ default:
+ goto vout_isr_err;
+ }
if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
vout->cur_frm->ts = timevalue;
vout->cur_frm->state = VIDEOBUF_DONE;
@@ -875,7 +586,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
ret = omapvid_init(vout, addr);
if (ret)
printk(KERN_ERR VOUT_NAME
- "failed to set overlay info\n");
+ "failed to set overlay info\n");
/* Enable the pipeline and set the Go bit */
ret = omapvid_apply_changes(vout);
if (ret)
@@ -954,6 +665,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
int startindex = 0, i, j;
u32 phy_addr = 0, virt_addr = 0;
struct omap_vout_device *vout = q->priv_data;
+ struct omapvideo_info *ovid = &vout->vid_info;
if (!vout)
return -EINVAL;
@@ -966,13 +678,10 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
*count = startindex;
- if ((rotation_enabled(vout)) && *count > VRFB_NUM_BUFS)
- *count = VRFB_NUM_BUFS;
-
- /* If rotation is enabled, allocate memory for VRFB space also */
- if (rotation_enabled(vout))
+ if (ovid->rotation_type == VOUT_ROT_VRFB) {
if (omap_vout_vrfb_buffer_setup(vout, count, startindex))
return -ENOMEM;
+ }
if (V4L2_MEMORY_MMAP != vout->memory)
return 0;
@@ -996,8 +705,11 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
virt_addr = omap_vout_alloc_buffer(vout->buffer_size,
&phy_addr);
if (!virt_addr) {
- if (!rotation_enabled(vout))
+ if (ovid->rotation_type == VOUT_ROT_NONE) {
break;
+ } else {
+ if (!is_rotation_enabled(vout))
+ break;
/* Free the VRFB buffers if no space for V4L2 buffers */
for (j = i; j < *count; j++) {
omap_vout_free_buffer(
@@ -1005,6 +717,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
vout->smsshado_size);
vout->smsshado_virt_addr[j] = 0;
vout->smsshado_phy_addr[j] = 0;
+ }
}
}
vout->buf_virt_addr[i] = virt_addr;
@@ -1017,9 +730,9 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
/*
* Free the V4L2 buffers additionally allocated than default
- * number of buffers and free all the VRFB buffers
+ * number of buffers
*/
-static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
+static void omap_vout_free_extra_buffers(struct omap_vout_device *vout)
{
int num_buffers = 0, i;
@@ -1034,20 +747,6 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
vout->buf_virt_addr[i] = 0;
vout->buf_phy_addr[i] = 0;
}
- /* Free the VRFB buffers only if they are allocated
- * during reqbufs. Don't free if init time allocated
- */
- if (!vout->vrfb_static_allocation) {
- for (i = 0; i < VRFB_NUM_BUFS; i++) {
- if (vout->smsshado_virt_addr[i]) {
- omap_vout_free_buffer(
- vout->smsshado_virt_addr[i],
- vout->smsshado_size);
- vout->smsshado_virt_addr[i] = 0;
- vout->smsshado_phy_addr[i] = 0;
- }
- }
- }
vout->buffer_allocated = num_buffers;
}
@@ -1059,16 +758,11 @@ static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
* buffer into VRFB memory space before giving it to the DSS.
*/
static int omap_vout_buffer_prepare(struct videobuf_queue *q,
- struct videobuf_buffer *vb,
- enum v4l2_field field)
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
{
- dma_addr_t dmabuf;
- struct vid_vrfb_dma *tx;
- enum dss_rotation rotation;
struct omap_vout_device *vout = q->priv_data;
- u32 dest_frame_index = 0, src_element_index = 0;
- u32 dest_element_index = 0, src_frame_index = 0;
- u32 elem_count = 0, frame_count = 0, pixsize = 2;
+ struct omapvideo_info *ovid = &vout->vid_info;
if (VIDEOBUF_NEEDS_INIT == vb->state) {
vb->width = vout->pix.width;
@@ -1087,66 +781,24 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
vout->queued_buf_addr[vb->i] = (u8 *)
omap_vout_uservirt_to_phys(vb->baddr);
} else {
- vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
- }
+ u32 addr, dma_addr;
+ unsigned long size;
- if (!rotation_enabled(vout))
- return 0;
+ addr = (unsigned long) vout->buf_virt_addr[vb->i];
+ size = (unsigned long) vb->size;
- dmabuf = vout->buf_phy_addr[vb->i];
- /* If rotation is enabled, copy input buffer into VRFB
- * memory space using DMA. We are copying input buffer
- * into VRFB memory space of desired angle and DSS will
- * read image VRFB memory for 0 degree angle
- */
- pixsize = vout->bpp * vout->vrfb_bpp;
- /*
- * DMA transfer in double index mode
- */
+ dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void *) addr,
+ size, DMA_TO_DEVICE);
+ if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr))
+ v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single failed\n");
- /* Frame index */
- dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
- (vout->pix.width * vout->bpp)) + 1;
-
- /* Source and destination parameters */
- src_element_index = 0;
- src_frame_index = 0;
- dest_element_index = 1;
- /* Number of elements per frame */
- elem_count = vout->pix.width * vout->bpp;
- frame_count = vout->pix.height;
- tx = &vout->vrfb_dma_tx;
- tx->tx_status = 0;
- omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
- (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
- tx->dev_id, 0x0);
- /* src_port required only for OMAP1 */
- omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
- dmabuf, src_element_index, src_frame_index);
- /*set dma source burst mode for VRFB */
- omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
- rotation = calc_rotation(vout);
-
- /* dest_port required only for OMAP1 */
- omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
- vout->vrfb_context[vb->i].paddr[0], dest_element_index,
- dest_frame_index);
- /*set dma dest burst mode for VRFB */
- omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
- omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
-
- omap_start_dma(tx->dma_ch);
- interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
-
- if (tx->tx_status == 0) {
- omap_stop_dma(tx->dma_ch);
- return -EINVAL;
+ vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
}
- /* Store buffers physical address into an array. Addresses
- * from this array will be used to configure DSS */
- vout->queued_buf_addr[vb->i] = (u8 *)
- vout->vrfb_context[vb->i].paddr[rotation];
- return 0;
+
+ if (ovid->rotation_type == VOUT_ROT_VRFB)
+ return omap_vout_prepare_vrfb(vout, vb);
+ else
+ return 0;
}
/*
@@ -1184,6 +836,15 @@ static void omap_vout_buffer_release(struct videobuf_queue *q,
/*
* File operations
*/
+static unsigned int omap_vout_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct omap_vout_device *vout = file->private_data;
+ struct videobuf_queue *q = &vout->vbq;
+
+ return videobuf_poll_stream(file, q, wait);
+}
+
static void omap_vout_vm_open(struct vm_area_struct *vma)
{
struct omap_vout_device *vout = vma->vm_private_data;
@@ -1298,7 +959,15 @@ static int omap_vout_release(struct file *file)
"Unable to apply changes\n");
/* Free all buffers */
- omap_vout_free_allbuffers(vout);
+ omap_vout_free_extra_buffers(vout);
+
+ /* Free the VRFB buffers only if they are allocated
+ * during reqbufs. Don't free if init time allocated
+ */
+ if (ovid->rotation_type == VOUT_ROT_VRFB) {
+ if (!vout->vrfb_static_allocation)
+ omap_vout_free_vrfb_buffers(vout);
+ }
videobuf_mmap_free(q);
/* Even if apply changes fails we should continue
@@ -1307,7 +976,7 @@ static int omap_vout_release(struct file *file)
u32 mask = 0;
mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
- DISPC_IRQ_EVSYNC_ODD;
+ DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_VSYNC2;
omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
vout->streaming = 0;
@@ -1383,10 +1052,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
struct v4l2_fmtdesc *fmt)
{
int index = fmt->index;
- enum v4l2_buf_type type = fmt->type;
- fmt->index = index;
- fmt->type = type;
if (index >= NUM_OUTPUT_FORMATS)
return -EINVAL;
@@ -1457,7 +1123,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
/* We dont support RGB24-packed mode if vrfb rotation
* is enabled*/
- if ((rotation_enabled(vout)) &&
+ if ((is_rotation_enabled(vout)) &&
f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
ret = -EINVAL;
goto s_fmt_vid_out_exit;
@@ -1465,7 +1131,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
/* get the framebuffer parameters */
- if (rotate_90_or_270(vout)) {
+ if (is_rotation_90_or_270(vout)) {
vout->fbuf.fmt.height = timing->x_res;
vout->fbuf.fmt.width = timing->y_res;
} else {
@@ -1510,12 +1176,17 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
{
int ret = 0;
struct omap_vout_device *vout = fh;
+ struct omap_overlay *ovl;
+ struct omapvideo_info *ovid;
struct v4l2_window *win = &f->fmt.win;
+ ovid = &vout->vid_info;
+ ovl = ovid->overlays[0];
+
ret = omap_vout_try_window(&vout->fbuf, win);
if (!ret) {
- if (vout->vid == OMAP_VIDEO1)
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
win->global_alpha = 255;
else
win->global_alpha = f->fmt.win.global_alpha;
@@ -1539,8 +1210,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
if (!ret) {
- /* Video1 plane does not support global alpha */
- if (ovl->id == OMAP_DSS_VIDEO1)
+ /* Video1 plane does not support global alpha on OMAP3 */
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
vout->win.global_alpha = 255;
else
vout->win.global_alpha = f->fmt.win.global_alpha;
@@ -1555,10 +1226,7 @@ static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh,
struct v4l2_fmtdesc *fmt)
{
int index = fmt->index;
- enum v4l2_buf_type type = fmt->type;
- fmt->index = index;
- fmt->type = type;
if (index >= NUM_OUTPUT_FORMATS)
return -EINVAL;
@@ -1645,7 +1313,7 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
/* get the display device attached to the overlay */
timing = &ovl->manager->device->panel.timings;
- if (rotate_90_or_270(vout)) {
+ if (is_rotation_90_or_270(vout)) {
vout->fbuf.fmt.height = timing->x_res;
vout->fbuf.fmt.width = timing->y_res;
} else {
@@ -1725,9 +1393,17 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
switch (a->id) {
case V4L2_CID_ROTATE:
{
+ struct omapvideo_info *ovid;
int rotation = a->value;
+ ovid = &vout->vid_info;
+
mutex_lock(&vout->lock);
+ if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
+ mutex_unlock(&vout->lock);
+ ret = -ERANGE;
+ break;
+ }
if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
mutex_unlock(&vout->lock);
@@ -1783,6 +1459,11 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
ovl = ovid->overlays[0];
mutex_lock(&vout->lock);
+ if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
+ mutex_unlock(&vout->lock);
+ ret = -ERANGE;
+ break;
+ }
if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
mutex_unlock(&vout->lock);
@@ -1893,7 +1574,7 @@ static int vidioc_qbuf(struct file *file, void *fh,
}
}
- if ((rotation_enabled(vout)) &&
+ if ((is_rotation_enabled(vout)) &&
vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) {
v4l2_warn(&vout->vid_dev->v4l2_dev,
"DMA Channel not allocated for Rotation\n");
@@ -1908,15 +1589,28 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
struct omap_vout_device *vout = fh;
struct videobuf_queue *q = &vout->vbq;
+ int ret;
+ u32 addr;
+ unsigned long size;
+ struct videobuf_buffer *vb;
+
+ vb = q->bufs[b->index];
+
if (!vout->streaming)
return -EINVAL;
if (file->f_flags & O_NONBLOCK)
/* Call videobuf_dqbuf for non blocking mode */
- return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
+ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
else
/* Call videobuf_dqbuf for blocking mode */
- return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+
+ addr = (unsigned long) vout->buf_phy_addr[vb->i];
+ size = (unsigned long) vb->size;
+ dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr,
+ size, DMA_TO_DEVICE);
+ return ret;
}
static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
@@ -1965,7 +1659,8 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
+ vout->cropped_offset;
- mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+ | DISPC_IRQ_VSYNC2;
omap_dispc_register_isr(omap_vout_isr, vout, mask);
@@ -2015,7 +1710,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
return -EINVAL;
vout->streaming = 0;
- mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+ | DISPC_IRQ_VSYNC2;
omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
@@ -2108,7 +1804,9 @@ static int vidioc_s_fbuf(struct file *file, void *fh,
if (ovl->manager && ovl->manager->get_manager_info &&
ovl->manager->set_manager_info) {
ovl->manager->get_manager_info(ovl->manager, &info);
- info.alpha_enabled = enable;
+ /* enable this only if there is no zorder cap */
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+ info.partial_alpha_enabled = enable;
if (ovl->manager->set_manager_info(ovl->manager, &info))
return -EINVAL;
}
@@ -2140,7 +1838,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
}
if (ovl->manager && ovl->manager->get_manager_info) {
ovl->manager->get_manager_info(ovl->manager, &info);
- if (info.alpha_enabled)
+ if (info.partial_alpha_enabled)
a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
}
@@ -2175,6 +1873,7 @@ static const struct v4l2_ioctl_ops vout_ioctl_ops = {
static const struct v4l2_file_operations omap_vout_fops = {
.owner = THIS_MODULE,
+ .poll = omap_vout_poll,
.unlocked_ioctl = video_ioctl2,
.mmap = omap_vout_mmap,
.open = omap_vout_open,
@@ -2228,7 +1927,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
vout->mirror = 0;
vout->control[2].id = V4L2_CID_HFLIP;
vout->control[2].value = 0;
- vout->vrfb_bpp = 2;
+ if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
+ vout->vrfb_bpp = 2;
control[1].id = V4L2_CID_BG_COLOR;
control[1].value = 0;
@@ -2260,17 +1960,15 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
int vid_num)
{
u32 numbuffers;
- int ret = 0, i, j;
- int image_width, image_height;
- struct video_device *vfd;
+ int ret = 0, i;
+ struct omapvideo_info *ovid;
struct omap_vout_device *vout;
- int static_vrfb_allocation = 0, vrfb_num_bufs = VRFB_NUM_BUFS;
struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
struct omap2video_device *vid_dev =
container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
vout = vid_dev->vouts[vid_num];
- vfd = vout->vfd;
+ ovid = &vout->vid_info;
numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers;
vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize;
@@ -2287,66 +1985,16 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
}
}
- for (i = 0; i < VRFB_NUM_BUFS; i++) {
- if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
- dev_info(&pdev->dev, ": VRFB allocation failed\n");
- for (j = 0; j < i; j++)
- omap_vrfb_release_ctx(&vout->vrfb_context[j]);
- ret = -ENOMEM;
- goto free_buffers;
- }
- }
vout->cropped_offset = 0;
- /* Calculate VRFB memory size */
- /* allocate for worst case size */
- image_width = VID_MAX_WIDTH / TILE_SIZE;
- if (VID_MAX_WIDTH % TILE_SIZE)
- image_width++;
-
- image_width = image_width * TILE_SIZE;
- image_height = VID_MAX_HEIGHT / TILE_SIZE;
-
- if (VID_MAX_HEIGHT % TILE_SIZE)
- image_height++;
-
- image_height = image_height * TILE_SIZE;
- vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
-
- /*
- * Request and Initialize DMA, for DMA based VRFB transfer
- */
- vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
- vout->vrfb_dma_tx.dma_ch = -1;
- vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
- ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
- omap_vout_vrfb_dma_tx_callback,
- (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
- if (ret < 0) {
- vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
- dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
- " video%d\n", vfd->minor);
- }
- init_waitqueue_head(&vout->vrfb_dma_tx.wait);
-
- /* Allocate VRFB buffers if selected through bootargs */
- static_vrfb_allocation = (vid_num == 0) ?
- vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
-
- /* statically allocated the VRFB buffer is done through
- commands line aruments */
- if (static_vrfb_allocation) {
- if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
- ret = -ENOMEM;
- goto release_vrfb_ctx;
- }
- vout->vrfb_static_allocation = 1;
+ if (ovid->rotation_type == VOUT_ROT_VRFB) {
+ int static_vrfb_allocation = (vid_num == 0) ?
+ vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
+ ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
+ static_vrfb_allocation);
}
- return 0;
-release_vrfb_ctx:
- for (j = 0; j < VRFB_NUM_BUFS; j++)
- omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+ return ret;
free_buffers:
for (i = 0; i < numbuffers; i++) {
@@ -2389,6 +2037,10 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
vout->vid_info.num_overlays = 1;
vout->vid_info.id = k + 1;
+ /* Set VRFB as rotation_type for omap2 and omap3 */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ vout->vid_info.rotation_type = VOUT_ROT_VRFB;
+
/* Setup the default configuration for the video devices
*/
if (omap_vout_setup_video_data(vout) != 0) {
@@ -2422,7 +2074,8 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
goto success;
error2:
- omap_vout_release_vrfb(vout);
+ if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
+ omap_vout_release_vrfb(vout);
omap_vout_free_buffers(vout);
error1:
video_device_release(vfd);
@@ -2443,11 +2096,13 @@ success:
static void omap_vout_cleanup_device(struct omap_vout_device *vout)
{
struct video_device *vfd;
+ struct omapvideo_info *ovid;
if (!vout)
return;
vfd = vout->vfd;
+ ovid = &vout->vid_info;
if (vfd) {
if (!video_is_registered(vfd)) {
/*
@@ -2463,14 +2118,15 @@ static void omap_vout_cleanup_device(struct omap_vout_device *vout)
video_unregister_device(vfd);
}
}
-
- omap_vout_release_vrfb(vout);
+ if (ovid->rotation_type == VOUT_ROT_VRFB) {
+ omap_vout_release_vrfb(vout);
+ /* Free the VRFB buffer if allocated
+ * init time
+ */
+ if (vout->vrfb_static_allocation)
+ omap_vout_free_vrfb_buffers(vout);
+ }
omap_vout_free_buffers(vout);
- /* Free the VRFB buffer if allocated
- * init time
- */
- if (vout->vrfb_static_allocation)
- omap_vout_free_vrfb_buffers(vout);
kfree(vout);
}
@@ -2516,6 +2172,14 @@ static int __init omap_vout_probe(struct platform_device *pdev)
vid_dev->num_displays = 0;
for_each_dss_dev(dssdev) {
omap_dss_get_device(dssdev);
+
+ if (!dssdev->driver) {
+ dev_warn(&pdev->dev, "no driver for display: %s\n",
+ dssdev->name);
+ omap_dss_put_device(dssdev);
+ continue;
+ }
+
vid_dev->displays[vid_dev->num_displays++] = dssdev;
}
@@ -2557,19 +2221,6 @@ static int __init omap_vout_probe(struct platform_device *pdev)
"'%s' Display already enabled\n",
def_display->name);
}
- /* set the update mode */
- if (def_display->caps &
- OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
- if (dssdrv->enable_te)
- dssdrv->enable_te(def_display, 0);
- if (dssdrv->set_update_mode)
- dssdrv->set_update_mode(def_display,
- OMAP_DSS_UPDATE_MANUAL);
- } else {
- if (dssdrv->set_update_mode)
- dssdrv->set_update_mode(def_display,
- OMAP_DSS_UPDATE_AUTO);
- }
}
}
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
index 659497b..d793501 100644
--- a/drivers/media/video/omap/omap_voutdef.h
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -12,6 +12,7 @@
#define OMAP_VOUTDEF_H
#include <video/omapdss.h>
+#include <plat/vrfb.h>
#define YUYV_BPP 2
#define RGB565_BPP 2
@@ -27,6 +28,31 @@
#define MAX_DISPLAYS 3
#define MAX_MANAGERS 3
+#define QQVGA_WIDTH 160
+#define QQVGA_HEIGHT 120
+
+/* Max Resolution supported by the driver */
+#define VID_MAX_WIDTH 1280 /* Largest width */
+#define VID_MAX_HEIGHT 720 /* Largest height */
+
+/* Mimimum requirement is 2x2 for DSS */
+#define VID_MIN_WIDTH 2
+#define VID_MIN_HEIGHT 2
+
+/* 2048 x 2048 is max res supported by OMAP display controller */
+#define MAX_PIXELS_PER_LINE 2048
+
+#define VRFB_TX_TIMEOUT 1000
+#define VRFB_NUM_BUFS 4
+
+/* Max buffer size tobe allocated during init */
+#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
+
+enum dma_channel_state {
+ DMA_CHAN_NOT_ALLOTED,
+ DMA_CHAN_ALLOTED,
+};
+
/* Enum for Rotation
* DSS understands rotation in 0, 1, 2, 3 context
* while V4L2 driver understands it as 0, 90, 180, 270
@@ -37,6 +63,18 @@ enum dss_rotation {
dss_rotation_180_degree = 2,
dss_rotation_270_degree = 3,
};
+
+/* Enum for choosing rotation type for vout
+ * DSS2 doesn't understand no rotation as an
+ * option while V4L2 driver doesn't support
+ * rotation in the case where VRFB is not built in
+ * the kernel
+ */
+enum vout_rotaion_type {
+ VOUT_ROT_NONE = 0,
+ VOUT_ROT_VRFB = 1,
+};
+
/*
* This structure is used to store the DMA transfer parameters
* for VRFB hidden buffer
@@ -53,6 +91,7 @@ struct omapvideo_info {
int id;
int num_overlays;
struct omap_overlay *overlays[MAX_OVLS];
+ enum vout_rotaion_type rotation_type;
};
struct omap2video_device {
@@ -144,4 +183,43 @@ struct omap_vout_device {
int io_allowed;
};
+
+/*
+ * Return true if rotation is 90 or 270
+ */
+static inline int is_rotation_90_or_270(const struct omap_vout_device *vout)
+{
+ return (vout->rotation == dss_rotation_90_degree ||
+ vout->rotation == dss_rotation_270_degree);
+}
+
+/*
+ * Return true if rotation is enabled
+ */
+static inline int is_rotation_enabled(const struct omap_vout_device *vout)
+{
+ return vout->rotation || vout->mirror;
+}
+
+/*
+ * Reverse the rotation degree if mirroring is enabled
+ */
+static inline int calc_rotation(const struct omap_vout_device *vout)
+{
+ if (!vout->mirror)
+ return vout->rotation;
+
+ switch (vout->rotation) {
+ case dss_rotation_90_degree:
+ return dss_rotation_270_degree;
+ case dss_rotation_270_degree:
+ return dss_rotation_90_degree;
+ case dss_rotation_180_degree:
+ return dss_rotation_0_degree;
+ default:
+ return dss_rotation_180_degree;
+ }
+}
+
+void omap_vout_free_buffers(struct omap_vout_device *vout);
#endif /* ifndef OMAP_VOUTDEF_H */
diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c
index 8ae7481..115408b 100644
--- a/drivers/media/video/omap/omap_voutlib.c
+++ b/drivers/media/video/omap/omap_voutlib.c
@@ -24,8 +24,12 @@
#include <linux/types.h>
#include <linux/videodev2.h>
+#include <linux/dma-mapping.h>
+
#include <plat/cpu.h>
+#include "omap_voutlib.h"
+
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("OMAP Video library");
MODULE_LICENSE("GPL");
@@ -291,3 +295,45 @@ void omap_vout_new_format(struct v4l2_pix_format *pix,
}
EXPORT_SYMBOL_GPL(omap_vout_new_format);
+/*
+ * Allocate buffers
+ */
+unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
+{
+ u32 order, size;
+ unsigned long virt_addr, addr;
+
+ size = PAGE_ALIGN(buf_size);
+ order = get_order(size);
+ virt_addr = __get_free_pages(GFP_KERNEL, order);
+ addr = virt_addr;
+
+ if (virt_addr) {
+ while (size > 0) {
+ SetPageReserved(virt_to_page(addr));
+ addr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ }
+ *phys_addr = (u32) virt_to_phys((void *) virt_addr);
+ return virt_addr;
+}
+
+/*
+ * Free buffers
+ */
+void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
+{
+ u32 order, size;
+ unsigned long addr = virtaddr;
+
+ size = PAGE_ALIGN(buf_size);
+ order = get_order(size);
+
+ while (size > 0) {
+ ClearPageReserved(virt_to_page(addr));
+ addr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ free_pages((unsigned long) virtaddr, order);
+}
diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h
index a60b16e..e51750a 100644
--- a/drivers/media/video/omap/omap_voutlib.h
+++ b/drivers/media/video/omap/omap_voutlib.h
@@ -12,23 +12,25 @@
#ifndef OMAP_VOUTLIB_H
#define OMAP_VOUTLIB_H
-extern void omap_vout_default_crop(struct v4l2_pix_format *pix,
+void omap_vout_default_crop(struct v4l2_pix_format *pix,
struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
-extern int omap_vout_new_crop(struct v4l2_pix_format *pix,
+int omap_vout_new_crop(struct v4l2_pix_format *pix,
struct v4l2_rect *crop, struct v4l2_window *win,
struct v4l2_framebuffer *fbuf,
const struct v4l2_rect *new_crop);
-extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
struct v4l2_window *new_win);
-extern int omap_vout_new_window(struct v4l2_rect *crop,
+int omap_vout_new_window(struct v4l2_rect *crop,
struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
struct v4l2_window *new_win);
-extern void omap_vout_new_format(struct v4l2_pix_format *pix,
+void omap_vout_new_format(struct v4l2_pix_format *pix,
struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
struct v4l2_window *win);
+unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
+void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
#endif /* #ifndef OMAP_VOUTLIB_H */
diff --git a/drivers/media/video/omap3isp/Makefile b/drivers/media/video/omap3isp/Makefile
index b1b34477..e8847e7 100644
--- a/drivers/media/video/omap3isp/Makefile
+++ b/drivers/media/video/omap3isp/Makefile
@@ -1,8 +1,6 @@
# Makefile for OMAP3 ISP driver
-ifdef CONFIG_VIDEO_OMAP3_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG
omap3-isp-objs += \
isp.o ispqueue.o ispvideo.o \
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index 94b6ed8..b818cac 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -80,6 +80,13 @@
#include "isph3a.h"
#include "isphist.h"
+/*
+ * this is provided as an interim solution until omap3isp doesn't need
+ * any omap-specific iommu API
+ */
+#define to_iommu(dev) \
+ (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
+
static unsigned int autoidle;
module_param(autoidle, int, 0444);
MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
@@ -732,7 +739,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
struct media_pad *pad;
struct v4l2_subdev *subdev;
unsigned long flags;
- int ret = 0;
+ int ret;
spin_lock_irqsave(&pipe->lock, flags);
pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
@@ -756,7 +763,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
ret = v4l2_subdev_call(subdev, video, s_stream, mode);
if (ret < 0 && ret != -ENOIOCTLCMD)
- break;
+ return ret;
if (subdev == &isp->isp_ccdc.subdev) {
v4l2_subdev_call(&isp->isp_aewb.subdev, video,
@@ -777,7 +784,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
if (pipe->do_propagation && mode == ISP_PIPELINE_STREAM_SINGLESHOT)
atomic_inc(&pipe->frame_number);
- return ret;
+ return 0;
}
static int isp_pipeline_wait_resizer(struct isp_device *isp)
@@ -1108,7 +1115,7 @@ static void isp_save_ctx(struct isp_device *isp)
{
isp_save_context(isp, isp_reg_list);
if (isp->iommu)
- iommu_save_ctx(isp->iommu);
+ omap_iommu_save_ctx(isp->iommu);
}
/*
@@ -1122,7 +1129,7 @@ static void isp_restore_ctx(struct isp_device *isp)
{
isp_restore_context(isp, isp_reg_list);
if (isp->iommu)
- iommu_restore_ctx(isp->iommu);
+ omap_iommu_restore_ctx(isp->iommu);
omap3isp_ccdc_restore_context(isp);
omap3isp_preview_restore_context(isp);
}
@@ -1697,6 +1704,7 @@ static int isp_register_entities(struct isp_device *isp)
isp->media_dev.dev = isp->dev;
strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
sizeof(isp->media_dev.model));
+ isp->media_dev.hw_revision = isp->revision;
isp->media_dev.link_notify = isp_pipeline_link_notify;
ret = media_device_register(&isp->media_dev);
if (ret < 0) {
@@ -1975,7 +1983,8 @@ static int isp_remove(struct platform_device *pdev)
isp_cleanup_modules(isp);
omap3isp_get(isp);
- iommu_put(isp->iommu);
+ iommu_detach_device(isp->domain, isp->iommu_dev);
+ iommu_domain_free(isp->domain);
omap3isp_put(isp);
free_irq(isp->irq_num, isp);
@@ -2123,25 +2132,41 @@ static int isp_probe(struct platform_device *pdev)
}
/* IOMMU */
- isp->iommu = iommu_get("isp");
- if (IS_ERR_OR_NULL(isp->iommu)) {
- isp->iommu = NULL;
+ isp->iommu_dev = omap_find_iommu_device("isp");
+ if (!isp->iommu_dev) {
+ dev_err(isp->dev, "omap_find_iommu_device failed\n");
ret = -ENODEV;
goto error_isp;
}
+ /* to be removed once iommu migration is complete */
+ isp->iommu = to_iommu(isp->iommu_dev);
+
+ isp->domain = iommu_domain_alloc(pdev->dev.bus);
+ if (!isp->domain) {
+ dev_err(isp->dev, "can't alloc iommu domain\n");
+ ret = -ENOMEM;
+ goto error_isp;
+ }
+
+ ret = iommu_attach_device(isp->domain, isp->iommu_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
+ goto free_domain;
+ }
+
/* Interrupt */
isp->irq_num = platform_get_irq(pdev, 0);
if (isp->irq_num <= 0) {
dev_err(isp->dev, "No IRQ resource\n");
ret = -ENODEV;
- goto error_isp;
+ goto detach_dev;
}
if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
dev_err(isp->dev, "Unable to request IRQ\n");
ret = -EINVAL;
- goto error_isp;
+ goto detach_dev;
}
/* Entities */
@@ -2162,8 +2187,11 @@ error_modules:
isp_cleanup_modules(isp);
error_irq:
free_irq(isp->irq_num, isp);
+detach_dev:
+ iommu_detach_device(isp->domain, isp->iommu_dev);
+free_domain:
+ iommu_domain_free(isp->domain);
error_isp:
- iommu_put(isp->iommu);
omap3isp_put(isp);
error:
isp_put_clocks(isp);
@@ -2183,6 +2211,8 @@ error:
regulator_put(isp->isp_csiphy2.vdd);
regulator_put(isp->isp_csiphy1.vdd);
platform_set_drvdata(pdev, NULL);
+
+ mutex_destroy(&isp->isp_mutex);
kfree(isp);
return ret;
@@ -2234,3 +2264,4 @@ module_exit(isp_cleanup);
MODULE_AUTHOR("Nokia Corporation");
MODULE_DESCRIPTION("TI OMAP3 ISP driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(ISP_VIDEO_DRIVER_VERSION);
diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/video/omap3isp/isp.h
index 2620c40..705946e 100644
--- a/drivers/media/video/omap3isp/isp.h
+++ b/drivers/media/video/omap3isp/isp.h
@@ -27,11 +27,13 @@
#ifndef OMAP3_ISP_CORE_H
#define OMAP3_ISP_CORE_H
+#include <media/omap3isp.h>
#include <media/v4l2-device.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/wait.h>
+#include <linux/iommu.h>
#include <plat/iommu.h>
#include <plat/iovmm.h>
@@ -94,14 +96,6 @@ enum isp_subclk_resource {
OMAP3_ISP_SUBCLK_RESIZER = (1 << 4),
};
-enum isp_interface_type {
- ISP_INTERFACE_PARALLEL,
- ISP_INTERFACE_CSI2A_PHY2,
- ISP_INTERFACE_CCP2B_PHY1,
- ISP_INTERFACE_CCP2B_PHY2,
- ISP_INTERFACE_CSI2C_PHY1,
-};
-
/* ISP: OMAP 34xx ES 1.0 */
#define ISP_REVISION_1_0 0x10
/* ISP2: OMAP 34xx ES 2.0, 2.1 and 3.0 */
@@ -130,76 +124,6 @@ struct isp_reg {
u32 val;
};
-/**
- * struct isp_parallel_platform_data - Parallel interface platform data
- * @data_lane_shift: Data lane shifter
- * 0 - CAMEXT[13:0] -> CAM[13:0]
- * 1 - CAMEXT[13:2] -> CAM[11:0]
- * 2 - CAMEXT[13:4] -> CAM[9:0]
- * 3 - CAMEXT[13:6] -> CAM[7:0]
- * @clk_pol: Pixel clock polarity
- * 0 - Non Inverted, 1 - Inverted
- * @bridge: CCDC Bridge input control
- * ISPCTRL_PAR_BRIDGE_DISABLE - Disable
- * ISPCTRL_PAR_BRIDGE_LENDIAN - Little endian
- * ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
- */
-struct isp_parallel_platform_data {
- unsigned int data_lane_shift:2;
- unsigned int clk_pol:1;
- unsigned int bridge:4;
-};
-
-/**
- * struct isp_ccp2_platform_data - CCP2 interface platform data
- * @strobe_clk_pol: Strobe/clock polarity
- * 0 - Non Inverted, 1 - Inverted
- * @crc: Enable the cyclic redundancy check
- * @ccp2_mode: Enable CCP2 compatibility mode
- * 0 - MIPI-CSI1 mode, 1 - CCP2 mode
- * @phy_layer: Physical layer selection
- * ISPCCP2_CTRL_PHY_SEL_CLOCK - Data/clock physical layer
- * ISPCCP2_CTRL_PHY_SEL_STROBE - Data/strobe physical layer
- * @vpclk_div: Video port output clock control
- */
-struct isp_ccp2_platform_data {
- unsigned int strobe_clk_pol:1;
- unsigned int crc:1;
- unsigned int ccp2_mode:1;
- unsigned int phy_layer:1;
- unsigned int vpclk_div:2;
-};
-
-/**
- * struct isp_csi2_platform_data - CSI2 interface platform data
- * @crc: Enable the cyclic redundancy check
- * @vpclk_div: Video port output clock control
- */
-struct isp_csi2_platform_data {
- unsigned crc:1;
- unsigned vpclk_div:2;
-};
-
-struct isp_subdev_i2c_board_info {
- struct i2c_board_info *board_info;
- int i2c_adapter_id;
-};
-
-struct isp_v4l2_subdevs_group {
- struct isp_subdev_i2c_board_info *subdevs;
- enum isp_interface_type interface;
- union {
- struct isp_parallel_platform_data parallel;
- struct isp_ccp2_platform_data ccp2;
- struct isp_csi2_platform_data csi2;
- } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
-};
-
-struct isp_platform_data {
- struct isp_v4l2_subdevs_group *subdevs;
- void (*set_constraints)(struct isp_device *isp, bool enable);
-};
-
struct isp_platform_callback {
u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
int (*csiphy_config)(struct isp_csiphy *phy,
@@ -288,7 +212,9 @@ struct isp_device {
unsigned int sbl_resources;
unsigned int subclk_resources;
- struct iommu *iommu;
+ struct omap_iommu *iommu;
+ struct iommu_domain *domain;
+ struct device *iommu_dev;
struct isp_platform_callback platform_cb;
};
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 39d501b..a319281 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -31,6 +31,7 @@
#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#include <media/v4l2-event.h>
#include "isp.h"
@@ -365,7 +366,7 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
req->iovm->sgt->nents, DMA_TO_DEVICE);
if (req->table)
- iommu_vfree(isp->iommu, req->table);
+ omap_iommu_vfree(isp->domain, isp->iommu, req->table);
kfree(req);
}
@@ -437,15 +438,15 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
req->enable = 1;
- req->table = iommu_vmalloc(isp->iommu, 0, req->config.size,
- IOMMU_FLAG);
+ req->table = omap_iommu_vmalloc(isp->domain, isp->iommu, 0,
+ req->config.size, IOMMU_FLAG);
if (IS_ERR_VALUE(req->table)) {
req->table = 0;
ret = -ENOMEM;
goto done;
}
- req->iovm = find_iovm_area(isp->iommu, req->table);
+ req->iovm = omap_find_iovm_area(isp->iommu, req->table);
if (req->iovm == NULL) {
ret = -ENOMEM;
goto done;
@@ -461,7 +462,7 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
req->iovm->sgt->nents, DMA_TO_DEVICE);
- table = da_to_va(isp->iommu, req->table);
+ table = omap_da_to_va(isp->iommu, req->table);
if (copy_from_user(table, config->lsc, req->config.size)) {
ret = -EFAULT;
goto done;
@@ -730,18 +731,19 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
/*
* table_new must be 64-bytes aligned, but it's
- * already done by iommu_vmalloc().
+ * already done by omap_iommu_vmalloc().
*/
size = ccdc->fpc.fpnum * 4;
- table_new = iommu_vmalloc(isp->iommu, 0, size,
- IOMMU_FLAG);
+ table_new = omap_iommu_vmalloc(isp->domain, isp->iommu,
+ 0, size, IOMMU_FLAG);
if (IS_ERR_VALUE(table_new))
return -ENOMEM;
- if (copy_from_user(da_to_va(isp->iommu, table_new),
+ if (copy_from_user(omap_da_to_va(isp->iommu, table_new),
(__force void __user *)
ccdc->fpc.fpcaddr, size)) {
- iommu_vfree(isp->iommu, table_new);
+ omap_iommu_vfree(isp->domain, isp->iommu,
+ table_new);
return -EFAULT;
}
@@ -751,7 +753,7 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
ccdc_configure_fpc(ccdc);
if (table_old != 0)
- iommu_vfree(isp->iommu, table_old);
+ omap_iommu_vfree(isp->domain, isp->iommu, table_old);
}
return ccdc_lsc_config(ccdc, ccdc_struct);
@@ -1148,6 +1150,8 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
ccdc->syncif.datsz = depth_out;
+ ccdc->syncif.hdpol = pdata ? pdata->hs_pol : 0;
+ ccdc->syncif.vdpol = pdata ? pdata->vs_pol : 0;
ccdc_config_sync_if(ccdc, &ccdc->syncif);
/* CCDC_PAD_SINK */
@@ -1402,11 +1406,13 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
{
- struct video_device *vdev = &ccdc->subdev.devnode;
+ struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+ struct video_device *vdev = ccdc->subdev.devnode;
struct v4l2_event event;
memset(&event, 0, sizeof(event));
- event.type = V4L2_EVENT_OMAP3ISP_HS_VS;
+ event.type = V4L2_EVENT_FRAME_SYNC;
+ event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number);
v4l2_event_queue(vdev, &event);
}
@@ -1688,10 +1694,14 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
- if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
+ if (sub->type != V4L2_EVENT_FRAME_SYNC)
+ return -EINVAL;
+
+ /* line number is zero at frame start */
+ if (sub->id != 0)
return -EINVAL;
- return v4l2_event_subscribe(fh, sub);
+ return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
}
static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
@@ -1825,7 +1835,7 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
* callers to request an output size bigger than the input size
* up to the nearest multiple of 16.
*/
- fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
+ fmt->width = clamp_t(u32, width, 32, fmt->width + 15);
fmt->width &= ~15;
fmt->height = clamp_t(u32, height, 32, fmt->height);
break;
@@ -2141,6 +2151,37 @@ static const struct media_entity_operations ccdc_media_ops = {
.link_setup = ccdc_link_setup,
};
+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
+{
+ v4l2_device_unregister_subdev(&ccdc->subdev);
+ omap3isp_video_unregister(&ccdc->video_out);
+}
+
+int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
+ struct v4l2_device *vdev)
+{
+ int ret;
+
+ /* Register the subdev and video node. */
+ ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&ccdc->video_out, vdev);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ omap3isp_ccdc_unregister_entities(ccdc);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP CCDC initialisation and cleanup
+ */
+
/*
* ccdc_init_entities - Initialize V4L2 subdev and media entity
* @ccdc: ISP CCDC module
@@ -2162,7 +2203,6 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
sd->grp_id = 1 << 16; /* group ID for isp subdevs */
v4l2_set_subdevdata(sd, ccdc);
sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
- sd->nevents = OMAP3ISP_CCDC_NEVENTS;
pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
@@ -2183,50 +2223,23 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
if (ret < 0)
- return ret;
+ goto error_video;
/* Connect the CCDC subdev to the video node. */
ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
&ccdc->video_out.video.entity, 0, 0);
if (ret < 0)
- return ret;
+ goto error_link;
return 0;
-}
-void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
-{
- media_entity_cleanup(&ccdc->subdev.entity);
-
- v4l2_device_unregister_subdev(&ccdc->subdev);
- omap3isp_video_unregister(&ccdc->video_out);
-}
-
-int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video node. */
- ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&ccdc->video_out, vdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- omap3isp_ccdc_unregister_entities(ccdc);
+error_link:
+ omap3isp_video_cleanup(&ccdc->video_out);
+error_video:
+ media_entity_cleanup(me);
return ret;
}
-/* -----------------------------------------------------------------------------
- * ISP CCDC initialisation and cleanup
- */
-
/*
* omap3isp_ccdc_init - CCDC module initialization.
* @dev: Device pointer specific to the OMAP3 ISP.
@@ -2238,6 +2251,7 @@ error:
int omap3isp_ccdc_init(struct isp_device *isp)
{
struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+ int ret;
spin_lock_init(&ccdc->lock);
init_waitqueue_head(&ccdc->wait);
@@ -2257,8 +2271,6 @@ int omap3isp_ccdc_init(struct isp_device *isp)
ccdc->syncif.fldout = 0;
ccdc->syncif.fldpol = 0;
ccdc->syncif.fldstat = 0;
- ccdc->syncif.hdpol = 0;
- ccdc->syncif.vdpol = 0;
ccdc->clamp.oblen = 0;
ccdc->clamp.dcsubval = 0;
@@ -2268,7 +2280,13 @@ int omap3isp_ccdc_init(struct isp_device *isp)
ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
ccdc_apply_controls(ccdc);
- return ccdc_init_entities(ccdc);
+ ret = ccdc_init_entities(ccdc);
+ if (ret < 0) {
+ mutex_destroy(&ccdc->ioctl_lock);
+ return ret;
+ }
+
+ return 0;
}
/*
@@ -2279,6 +2297,9 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
{
struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+ omap3isp_video_cleanup(&ccdc->video_out);
+ media_entity_cleanup(&ccdc->subdev.entity);
+
/* Free LSC requests. As the CCDC is stopped there's no active request,
* so only the pending request and the free queue need to be handled.
*/
@@ -2287,5 +2308,7 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
if (ccdc->fpc.fpcaddr != 0)
- iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr);
+ omap_iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
+
+ mutex_destroy(&ccdc->ioctl_lock);
}
diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c
index 0e16cab..904ca8c 100644
--- a/drivers/media/video/omap3isp/ispccp2.c
+++ b/drivers/media/video/omap3isp/ispccp2.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
#include "isp.h"
#include "ispreg.h"
@@ -163,6 +164,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
int i;
+ if (enable && ccp2->vdds_csib)
+ regulator_enable(ccp2->vdds_csib);
+
/* Enable/Disable all the LCx channels */
for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
@@ -186,6 +190,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
ISPCCP2_LC01_IRQENABLE,
ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
}
+
+ if (!enable && ccp2->vdds_csib)
+ regulator_disable(ccp2->vdds_csib);
}
/*
@@ -236,9 +243,9 @@ static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
if (!(val & ISPCCP2_CTRL_MODE)) {
- if (pdata->ccp2_mode)
+ if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2)
dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
- if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE)
+ if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
/* Strobe mode requires CCP2 */
return -EIO;
}
@@ -1025,6 +1032,48 @@ static const struct media_entity_operations ccp2_media_ops = {
};
/*
+ * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
+ * @ccp2: Pointer to ISP CCP2 device
+ */
+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
+{
+ v4l2_device_unregister_subdev(&ccp2->subdev);
+ omap3isp_video_unregister(&ccp2->video_in);
+}
+
+/*
+ * omap3isp_ccp2_register_entities - Register the subdev media entity
+ * @ccp2: Pointer to ISP CCP2 device
+ * @vdev: Pointer to v4l device
+ * return negative error code or zero on success
+ */
+
+int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
+ struct v4l2_device *vdev)
+{
+ int ret;
+
+ /* Register the subdev and video nodes. */
+ ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&ccp2->video_in, vdev);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ omap3isp_ccp2_unregister_entities(ccp2);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP ccp2 initialisation and cleanup
+ */
+
+/*
* ccp2_init_entities - Initialize ccp2 subdev and media entity.
* @ccp2: Pointer to ISP CCP2 device
* return negative error code or zero on success
@@ -1076,69 +1125,23 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
if (ret < 0)
- return ret;
+ goto error_video;
/* Connect the video node to the ccp2 subdev. */
ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
&ccp2->subdev.entity, CCP2_PAD_SINK, 0);
if (ret < 0)
- return ret;
+ goto error_link;
return 0;
-}
-/*
- * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
- * @ccp2: Pointer to ISP CCP2 device
- */
-void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
-{
+error_link:
+ omap3isp_video_cleanup(&ccp2->video_in);
+error_video:
media_entity_cleanup(&ccp2->subdev.entity);
-
- v4l2_device_unregister_subdev(&ccp2->subdev);
- omap3isp_video_unregister(&ccp2->video_in);
-}
-
-/*
- * omap3isp_ccp2_register_entities - Register the subdev media entity
- * @ccp2: Pointer to ISP CCP2 device
- * @vdev: Pointer to v4l device
- * return negative error code or zero on success
- */
-
-int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video nodes. */
- ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&ccp2->video_in, vdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- omap3isp_ccp2_unregister_entities(ccp2);
return ret;
}
-/* -----------------------------------------------------------------------------
- * ISP ccp2 initialisation and cleanup
- */
-
-/*
- * omap3isp_ccp2_cleanup - CCP2 un-initialization
- * @isp : Pointer to ISP device
- */
-void omap3isp_ccp2_cleanup(struct isp_device *isp)
-{
-}
-
/*
* omap3isp_ccp2_init - CCP2 initialization.
* @isp : Pointer to ISP device
@@ -1151,23 +1154,48 @@ int omap3isp_ccp2_init(struct isp_device *isp)
init_waitqueue_head(&ccp2->wait);
- /* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
+ /*
+ * On the OMAP34xx the CSI1 receiver is operated in the CSIb IO
+ * complex, which is powered by vdds_csib power rail. Hence the
+ * request for the regulator.
+ *
+ * On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
* the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
* configured.
*
* TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
*/
- if (isp->revision == ISP_REVISION_15_0)
+ if (isp->revision == ISP_REVISION_2_0) {
+ ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib");
+ if (IS_ERR(ccp2->vdds_csib)) {
+ dev_dbg(isp->dev,
+ "Could not get regulator vdds_csib\n");
+ ccp2->vdds_csib = NULL;
+ }
+ } else if (isp->revision == ISP_REVISION_15_0) {
ccp2->phy = &isp->isp_csiphy1;
+ }
ret = ccp2_init_entities(ccp2);
- if (ret < 0)
- goto out;
+ if (ret < 0) {
+ regulator_put(ccp2->vdds_csib);
+ return ret;
+ }
ccp2_reset(ccp2);
-out:
- if (ret)
- omap3isp_ccp2_cleanup(isp);
+ return 0;
+}
- return ret;
+/*
+ * omap3isp_ccp2_cleanup - CCP2 un-initialization
+ * @isp : Pointer to ISP device
+ */
+void omap3isp_ccp2_cleanup(struct isp_device *isp)
+{
+ struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
+
+ omap3isp_video_cleanup(&ccp2->video_in);
+ media_entity_cleanup(&ccp2->subdev.entity);
+
+ regulator_put(ccp2->vdds_csib);
}
diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h
index 5505a86..6674e9d 100644
--- a/drivers/media/video/omap3isp/ispccp2.h
+++ b/drivers/media/video/omap3isp/ispccp2.h
@@ -81,6 +81,7 @@ struct isp_ccp2_device {
struct isp_interface_mem_config mem_cfg;
struct isp_video video_in;
struct isp_csiphy *phy;
+ struct regulator *vdds_csib;
unsigned int error;
enum isp_pipeline_stream_state state;
wait_queue_head_t wait;
diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c
index 69161a6..0c5f1cb 100644
--- a/drivers/media/video/omap3isp/ispcsi2.c
+++ b/drivers/media/video/omap3isp/ispcsi2.c
@@ -1187,6 +1187,37 @@ static const struct media_entity_operations csi2_media_ops = {
.link_setup = csi2_link_setup,
};
+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
+{
+ v4l2_device_unregister_subdev(&csi2->subdev);
+ omap3isp_video_unregister(&csi2->video_out);
+}
+
+int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
+ struct v4l2_device *vdev)
+{
+ int ret;
+
+ /* Register the subdev and video nodes. */
+ ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&csi2->video_out, vdev);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ omap3isp_csi2_unregister_entities(csi2);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP CSI2 initialisation and cleanup
+ */
+
/*
* csi2_init_entities - Initialize subdev and media entity.
* @csi2: Pointer to csi2 structure.
@@ -1228,57 +1259,23 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)
ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
if (ret < 0)
- return ret;
+ goto error_video;
/* Connect the CSI2 subdev to the video node. */
ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
&csi2->video_out.video.entity, 0, 0);
if (ret < 0)
- return ret;
+ goto error_link;
return 0;
-}
-void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
-{
+error_link:
+ omap3isp_video_cleanup(&csi2->video_out);
+error_video:
media_entity_cleanup(&csi2->subdev.entity);
-
- v4l2_device_unregister_subdev(&csi2->subdev);
- omap3isp_video_unregister(&csi2->video_out);
-}
-
-int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video nodes. */
- ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&csi2->video_out, vdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- omap3isp_csi2_unregister_entities(csi2);
return ret;
}
-/* -----------------------------------------------------------------------------
- * ISP CSI2 initialisation and cleanup
- */
-
-/*
- * omap3isp_csi2_cleanup - Routine for module driver cleanup
- */
-void omap3isp_csi2_cleanup(struct isp_device *isp)
-{
-}
-
/*
* omap3isp_csi2_init - Routine for module driver init
*/
@@ -1298,7 +1295,7 @@ int omap3isp_csi2_init(struct isp_device *isp)
ret = csi2_init_entities(csi2a);
if (ret < 0)
- goto fail;
+ return ret;
if (isp->revision == ISP_REVISION_15_0) {
csi2c->isp = isp;
@@ -1311,7 +1308,15 @@ int omap3isp_csi2_init(struct isp_device *isp)
}
return 0;
-fail:
- omap3isp_csi2_cleanup(isp);
- return ret;
+}
+
+/*
+ * omap3isp_csi2_cleanup - Routine for module driver cleanup
+ */
+void omap3isp_csi2_cleanup(struct isp_device *isp)
+{
+ struct isp_csi2_device *csi2a = &isp->isp_csi2a;
+
+ omap3isp_video_cleanup(&csi2a->video_out);
+ media_entity_cleanup(&csi2a->subdev.entity);
}
diff --git a/drivers/media/video/omap3isp/isph3a_aewb.c b/drivers/media/video/omap3isp/isph3a_aewb.c
index 8068cef..a3c76bf 100644
--- a/drivers/media/video/omap3isp/isph3a_aewb.c
+++ b/drivers/media/video/omap3isp/isph3a_aewb.c
@@ -370,5 +370,5 @@ void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
{
kfree(isp->isp_aewb.priv);
kfree(isp->isp_aewb.recover_priv);
- omap3isp_stat_free(&isp->isp_aewb);
+ omap3isp_stat_cleanup(&isp->isp_aewb);
}
diff --git a/drivers/media/video/omap3isp/isph3a_af.c b/drivers/media/video/omap3isp/isph3a_af.c
index ba54d0a..58e0bc4 100644
--- a/drivers/media/video/omap3isp/isph3a_af.c
+++ b/drivers/media/video/omap3isp/isph3a_af.c
@@ -425,5 +425,5 @@ void omap3isp_h3a_af_cleanup(struct isp_device *isp)
{
kfree(isp->isp_af.priv);
kfree(isp->isp_af.recover_priv);
- omap3isp_stat_free(&isp->isp_af);
+ omap3isp_stat_cleanup(&isp->isp_af);
}
diff --git a/drivers/media/video/omap3isp/isphist.c b/drivers/media/video/omap3isp/isphist.c
index 1743856..1163907 100644
--- a/drivers/media/video/omap3isp/isphist.c
+++ b/drivers/media/video/omap3isp/isphist.c
@@ -516,5 +516,5 @@ void omap3isp_hist_cleanup(struct isp_device *isp)
if (HIST_USING_DMA(&isp->isp_hist))
omap_free_dma(isp->isp_hist.dma_ch);
kfree(isp->isp_hist.priv);
- omap3isp_stat_free(&isp->isp_hist);
+ omap3isp_stat_cleanup(&isp->isp_hist);
}
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index aba537a..ccb876f 100644
--- a/drivers/media/video/omap3isp/isppreview.c
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -76,9 +76,51 @@ static struct omap3isp_prev_csc flr_prev_csc = {
#define DEF_DETECT_CORRECT_VAL 0xe
-#define PREV_MIN_WIDTH 64
-#define PREV_MIN_HEIGHT 8
-#define PREV_MAX_HEIGHT 16384
+/*
+ * Margins and image size limits.
+ *
+ * The preview engine crops several rows and columns internally depending on
+ * which filters are enabled. To avoid format changes when the filters are
+ * enabled or disabled (which would prevent them from being turned on or off
+ * during streaming), the driver assumes all the filters are enabled when
+ * computing sink crop and source format limits.
+ *
+ * If a filter is disabled, additional cropping is automatically added at the
+ * preview engine input by the driver to avoid overflow at line and frame end.
+ * This is completely transparent for applications.
+ *
+ * Median filter 4 pixels
+ * Noise filter,
+ * Faulty pixels correction 4 pixels, 4 lines
+ * CFA filter 4 pixels, 4 lines in Bayer mode
+ * 2 lines in other modes
+ * Color suppression 2 pixels
+ * or luma enhancement
+ * -------------------------------------------------------------
+ * Maximum total 14 pixels, 8 lines
+ *
+ * The color suppression and luma enhancement filters are applied after bayer to
+ * YUV conversion. They thus can crop one pixel on the left and one pixel on the
+ * right side of the image without changing the color pattern. When both those
+ * filters are disabled, the driver must crop the two pixels on the same side of
+ * the image to avoid changing the bayer pattern. The left margin is thus set to
+ * 8 pixels and the right margin to 6 pixels.
+ */
+
+#define PREV_MARGIN_LEFT 8
+#define PREV_MARGIN_RIGHT 6
+#define PREV_MARGIN_TOP 4
+#define PREV_MARGIN_BOTTOM 4
+
+#define PREV_MIN_IN_WIDTH 64
+#define PREV_MIN_IN_HEIGHT 8
+#define PREV_MAX_IN_HEIGHT 16384
+
+#define PREV_MIN_OUT_WIDTH 0
+#define PREV_MIN_OUT_HEIGHT 0
+#define PREV_MAX_OUT_WIDTH 1280
+#define PREV_MAX_OUT_WIDTH_ES2 3300
+#define PREV_MAX_OUT_WIDTH_3630 4096
/*
* Coeficient Tables for the submodules in Preview.
@@ -979,52 +1021,36 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
* enabled when reporting source pad formats to userspace. If this assumption is
* not true, rows and columns must be manually cropped at the preview engine
* input to avoid overflows at the end of lines and frames.
+ *
+ * See the explanation at the PREV_MARGIN_* definitions for more details.
*/
static void preview_config_input_size(struct isp_prev_device *prev)
{
struct isp_device *isp = to_isp_device(prev);
struct prev_params *params = &prev->params;
- struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
- unsigned int sph = 0;
- unsigned int eph = format->width - 1;
- unsigned int slv = 0;
- unsigned int elv = format->height - 1;
-
- if (prev->input == PREVIEW_INPUT_CCDC) {
- sph += 2;
- eph -= 2;
+ unsigned int sph = prev->crop.left;
+ unsigned int eph = prev->crop.left + prev->crop.width - 1;
+ unsigned int slv = prev->crop.top;
+ unsigned int elv = prev->crop.top + prev->crop.height - 1;
+
+ if (params->features & PREV_CFA) {
+ sph -= 2;
+ eph += 2;
+ slv -= 2;
+ elv += 2;
}
-
- /*
- * Median filter 4 pixels
- * Noise filter 4 pixels, 4 lines
- * or faulty pixels correction
- * CFA filter 4 pixels, 4 lines in Bayer mode
- * 2 lines in other modes
- * Color suppression 2 pixels
- * or luma enhancement
- * -------------------------------------------------------------
- * Maximum total 14 pixels, 8 lines
- */
-
- if (!(params->features & PREV_CFA)) {
- sph += 2;
- eph -= 2;
- slv += 2;
- elv -= 2;
+ if (params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER)) {
+ sph -= 2;
+ eph += 2;
+ slv -= 2;
+ elv += 2;
}
- if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) {
- sph += 2;
- eph -= 2;
- slv += 2;
- elv -= 2;
+ if (params->features & PREV_HORZ_MEDIAN_FILTER) {
+ sph -= 2;
+ eph += 2;
}
- if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) {
- sph += 2;
- eph -= 2;
- }
- if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
- sph += 2;
+ if (params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE))
+ sph -= 2;
isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
@@ -1228,7 +1254,6 @@ static void preview_init_params(struct isp_prev_device *prev)
/* Init values */
params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
- params->average = NO_AVE;
params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
memcpy(params->cfa.table, cfa_coef_table,
sizeof(params->cfa.table));
@@ -1281,14 +1306,14 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
switch (isp->revision) {
case ISP_REVISION_1_0:
- return ISPPRV_MAXOUTPUT_WIDTH;
+ return PREV_MAX_OUT_WIDTH;
case ISP_REVISION_2_0:
default:
- return ISPPRV_MAXOUTPUT_WIDTH_ES2;
+ return PREV_MAX_OUT_WIDTH_ES2;
case ISP_REVISION_15_0:
- return ISPPRV_MAXOUTPUT_WIDTH_3630;
+ return PREV_MAX_OUT_WIDTH_3630;
}
}
@@ -1296,8 +1321,6 @@ static void preview_configure(struct isp_prev_device *prev)
{
struct isp_device *isp = to_isp_device(prev);
struct v4l2_mbus_framefmt *format;
- unsigned int max_out_width;
- unsigned int format_avg;
preview_setup_hw(prev);
@@ -1335,10 +1358,7 @@ static void preview_configure(struct isp_prev_device *prev)
preview_config_outlineoffset(prev,
ALIGN(format->width, 0x10) * 2);
- max_out_width = preview_max_out_width(prev);
-
- format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
- preview_config_averager(prev, format_avg);
+ preview_config_averager(prev, 0);
preview_config_ycpos(prev, format->code);
}
@@ -1597,6 +1617,16 @@ __preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
return &prev->formats[pad];
}
+static struct v4l2_rect *
+__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
+ enum v4l2_subdev_format_whence which)
+{
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return v4l2_subdev_get_try_crop(fh, PREV_PAD_SINK);
+ else
+ return &prev->crop;
+}
+
/* previewer format descriptions */
static const unsigned int preview_input_fmts[] = {
V4L2_MBUS_FMT_SGRBG10_1X10,
@@ -1611,24 +1641,25 @@ static const unsigned int preview_output_fmts[] = {
};
/*
- * preview_try_format - Handle try format by pad subdev method
- * @prev: ISP preview device
- * @fh : V4L2 subdev file handle
- * @pad: pad num
- * @fmt: pointer to v4l2 format structure
+ * preview_try_format - Validate a format
+ * @prev: ISP preview engine
+ * @fh: V4L2 subdev file handle
+ * @pad: pad number
+ * @fmt: format to be validated
+ * @which: try/active format selector
+ *
+ * Validate and adjust the given format for the given pad based on the preview
+ * engine limits and the format and crop rectangles on other pads.
*/
static void preview_try_format(struct isp_prev_device *prev,
struct v4l2_subdev_fh *fh, unsigned int pad,
struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
{
- struct v4l2_mbus_framefmt *format;
- unsigned int max_out_width;
enum v4l2_mbus_pixelcode pixelcode;
+ struct v4l2_rect *crop;
unsigned int i;
- max_out_width = preview_max_out_width(prev);
-
switch (pad) {
case PREV_PAD_SINK:
/* When reading data from the CCDC, the input size has already
@@ -1641,10 +1672,11 @@ static void preview_try_format(struct isp_prev_device *prev,
* filter array interpolation.
*/
if (prev->input == PREVIEW_INPUT_MEMORY) {
- fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH,
- max_out_width * 8);
- fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT,
- PREV_MAX_HEIGHT);
+ fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
+ preview_max_out_width(prev));
+ fmt->height = clamp_t(u32, fmt->height,
+ PREV_MIN_IN_HEIGHT,
+ PREV_MAX_IN_HEIGHT);
}
fmt->colorspace = V4L2_COLORSPACE_SRGB;
@@ -1661,15 +1693,8 @@ static void preview_try_format(struct isp_prev_device *prev,
case PREV_PAD_SOURCE:
pixelcode = fmt->code;
- format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
- memcpy(fmt, format, sizeof(*fmt));
+ *fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
- /* The preview module output size is configurable through the
- * input interface (horizontal and vertical cropping) and the
- * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
- * spite of this, hardcode the output size to the biggest
- * possible value for simplicity reasons.
- */
switch (pixelcode) {
case V4L2_MBUS_FMT_YUYV8_1X16:
case V4L2_MBUS_FMT_UYVY8_1X16:
@@ -1681,31 +1706,14 @@ static void preview_try_format(struct isp_prev_device *prev,
break;
}
- /* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped
- * from the left and right sides when the input source is the
- * CCDC. This seems not to be needed in practice, investigation
- * is required.
- */
- if (prev->input == PREVIEW_INPUT_CCDC)
- fmt->width -= 4;
-
- /* The preview module can output a maximum of 3312 pixels
- * horizontally due to fixed memory-line sizes. Compute the
- * horizontal averaging factor accordingly. Note that the limit
- * applies to the noise filter and CFA interpolation blocks, so
- * it doesn't take cropping by further blocks into account.
- *
- * ES 1.0 hardware revision is limited to 1280 pixels
- * horizontally.
- */
- fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
-
- /* Assume that all blocks are enabled and crop pixels and lines
- * accordingly. See preview_config_input_size() for more
- * information.
+ /* The preview module output size is configurable through the
+ * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
+ * is not supported yet, hardcode the output size to the crop
+ * rectangle size.
*/
- fmt->width -= 14;
- fmt->height -= 8;
+ crop = __preview_get_crop(prev, fh, which);
+ fmt->width = crop->width;
+ fmt->height = crop->height;
fmt->colorspace = V4L2_COLORSPACE_JPEG;
break;
@@ -1715,6 +1723,49 @@ static void preview_try_format(struct isp_prev_device *prev,
}
/*
+ * preview_try_crop - Validate a crop rectangle
+ * @prev: ISP preview engine
+ * @sink: format on the sink pad
+ * @crop: crop rectangle to be validated
+ *
+ * The preview engine crops lines and columns for its internal operation,
+ * depending on which filters are enabled. Enforce minimum crop margins to
+ * handle that transparently for userspace.
+ *
+ * See the explanation at the PREV_MARGIN_* definitions for more details.
+ */
+static void preview_try_crop(struct isp_prev_device *prev,
+ const struct v4l2_mbus_framefmt *sink,
+ struct v4l2_rect *crop)
+{
+ unsigned int left = PREV_MARGIN_LEFT;
+ unsigned int right = sink->width - PREV_MARGIN_RIGHT;
+ unsigned int top = PREV_MARGIN_TOP;
+ unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
+
+ /* When processing data on-the-fly from the CCDC, at least 2 pixels must
+ * be cropped from the left and right sides of the image. As we don't
+ * know which filters will be enabled, increase the left and right
+ * margins by two.
+ */
+ if (prev->input == PREVIEW_INPUT_CCDC) {
+ left += 2;
+ right -= 2;
+ }
+
+ /* Restrict left/top to even values to keep the Bayer pattern. */
+ crop->left &= ~1;
+ crop->top &= ~1;
+
+ crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
+ crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
+ crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
+ right - crop->left);
+ crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
+ bottom - crop->top);
+}
+
+/*
* preview_enum_mbus_code - Handle pixel format enumeration
* @sd : pointer to v4l2 subdev structure
* @fh : V4L2 subdev file handle
@@ -1776,6 +1827,60 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
}
/*
+ * preview_get_crop - Retrieve the crop rectangle on a pad
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @crop: crop rectangle
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int preview_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+
+ /* Cropping is only supported on the sink pad. */
+ if (crop->pad != PREV_PAD_SINK)
+ return -EINVAL;
+
+ crop->rect = *__preview_get_crop(prev, fh, crop->which);
+ return 0;
+}
+
+/*
+ * preview_set_crop - Retrieve the crop rectangle on a pad
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @crop: crop rectangle
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int preview_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+ struct v4l2_mbus_framefmt *format;
+
+ /* Cropping is only supported on the sink pad. */
+ if (crop->pad != PREV_PAD_SINK)
+ return -EINVAL;
+
+ /* The crop rectangle can't be changed while streaming. */
+ if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
+ return -EBUSY;
+
+ format = __preview_get_format(prev, fh, PREV_PAD_SINK, crop->which);
+ preview_try_crop(prev, format, &crop->rect);
+ *__preview_get_crop(prev, fh, crop->which) = crop->rect;
+
+ /* Update the source format. */
+ format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, crop->which);
+ preview_try_format(prev, fh, PREV_PAD_SOURCE, format, crop->which);
+
+ return 0;
+}
+
+/*
* preview_get_format - Handle get format by pads subdev method
* @sd : pointer to v4l2 subdev structure
* @fh : V4L2 subdev file handle
@@ -1808,6 +1913,7 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
{
struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
if (format == NULL)
@@ -1818,9 +1924,18 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
/* Propagate the format from sink to source */
if (fmt->pad == PREV_PAD_SINK) {
+ /* Reset the crop rectangle. */
+ crop = __preview_get_crop(prev, fh, fmt->which);
+ crop->left = 0;
+ crop->top = 0;
+ crop->width = fmt->format.width;
+ crop->height = fmt->format.height;
+
+ preview_try_crop(prev, &fmt->format, crop);
+
+ /* Update the source format. */
format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
fmt->which);
- *format = fmt->format;
preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
fmt->which);
}
@@ -1869,6 +1984,8 @@ static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
.enum_frame_size = preview_enum_frame_size,
.get_fmt = preview_get_format,
.set_fmt = preview_set_format,
+ .get_crop = preview_get_crop,
+ .set_crop = preview_set_crop,
};
/* subdev operations */
@@ -1966,8 +2083,44 @@ static const struct media_entity_operations preview_media_ops = {
.link_setup = preview_link_setup,
};
+void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
+{
+ v4l2_device_unregister_subdev(&prev->subdev);
+ omap3isp_video_unregister(&prev->video_in);
+ omap3isp_video_unregister(&prev->video_out);
+}
+
+int omap3isp_preview_register_entities(struct isp_prev_device *prev,
+ struct v4l2_device *vdev)
+{
+ int ret;
+
+ /* Register the subdev and video nodes. */
+ ret = v4l2_device_register_subdev(vdev, &prev->subdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&prev->video_in, vdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&prev->video_out, vdev);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ omap3isp_preview_unregister_entities(prev);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP previewer initialisation and cleanup
+ */
+
/*
- * review_init_entities - Initialize subdev and media entity.
+ * preview_init_entities - Initialize subdev and media entity.
* @prev : Pointer to preview structure
* return -ENOMEM or zero on success
*/
@@ -2024,69 +2177,34 @@ static int preview_init_entities(struct isp_prev_device *prev)
ret = omap3isp_video_init(&prev->video_in, "preview");
if (ret < 0)
- return ret;
+ goto error_video_in;
ret = omap3isp_video_init(&prev->video_out, "preview");
if (ret < 0)
- return ret;
+ goto error_video_out;
/* Connect the video nodes to the previewer subdev. */
ret = media_entity_create_link(&prev->video_in.video.entity, 0,
&prev->subdev.entity, PREV_PAD_SINK, 0);
if (ret < 0)
- return ret;
+ goto error_link;
ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
&prev->video_out.video.entity, 0, 0);
if (ret < 0)
- return ret;
+ goto error_link;
return 0;
-}
-void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
-{
+error_link:
+ omap3isp_video_cleanup(&prev->video_out);
+error_video_out:
+ omap3isp_video_cleanup(&prev->video_in);
+error_video_in:
media_entity_cleanup(&prev->subdev.entity);
-
- v4l2_device_unregister_subdev(&prev->subdev);
- v4l2_ctrl_handler_free(&prev->ctrls);
- omap3isp_video_unregister(&prev->video_in);
- omap3isp_video_unregister(&prev->video_out);
-}
-
-int omap3isp_preview_register_entities(struct isp_prev_device *prev,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video nodes. */
- ret = v4l2_device_register_subdev(vdev, &prev->subdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&prev->video_in, vdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&prev->video_out, vdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- omap3isp_preview_unregister_entities(prev);
return ret;
}
-/* -----------------------------------------------------------------------------
- * ISP previewer initialisation and cleanup
- */
-
-void omap3isp_preview_cleanup(struct isp_device *isp)
-{
-}
-
/*
* isp_preview_init - Previewer initialization.
* @dev : Pointer to ISP device
@@ -2095,19 +2213,20 @@ void omap3isp_preview_cleanup(struct isp_device *isp)
int omap3isp_preview_init(struct isp_device *isp)
{
struct isp_prev_device *prev = &isp->isp_prev;
- int ret;
spin_lock_init(&prev->lock);
init_waitqueue_head(&prev->wait);
preview_init_params(prev);
- ret = preview_init_entities(prev);
- if (ret < 0)
- goto out;
+ return preview_init_entities(prev);
+}
-out:
- if (ret)
- omap3isp_preview_cleanup(isp);
+void omap3isp_preview_cleanup(struct isp_device *isp)
+{
+ struct isp_prev_device *prev = &isp->isp_prev;
- return ret;
+ v4l2_ctrl_handler_free(&prev->ctrls);
+ omap3isp_video_cleanup(&prev->video_in);
+ omap3isp_video_cleanup(&prev->video_out);
+ media_entity_cleanup(&prev->subdev.entity);
}
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h
index fa943bd..f54e775 100644
--- a/drivers/media/video/omap3isp/isppreview.h
+++ b/drivers/media/video/omap3isp/isppreview.h
@@ -45,11 +45,6 @@
#define ISPPRV_CONTRAST_HIGH 0xFF
#define ISPPRV_CONTRAST_UNITS 0x1
-#define NO_AVE 0x0
-#define AVE_2_PIX 0x1
-#define AVE_4_PIX 0x2
-#define AVE_8_PIX 0x3
-
/* Features list */
#define PREV_LUMA_ENHANCE OMAP3ISP_PREV_LUMAENH
#define PREV_INVERSE_ALAW OMAP3ISP_PREV_INVALAW
@@ -106,7 +101,6 @@ enum preview_ycpos_mode {
* @rgb2ycbcr: RGB to ycbcr parameters.
* @hmed: Horizontal median filter.
* @yclimit: YC limits parameters.
- * @average: Downsampling rate for averager.
* @contrast: Contrast.
* @brightness: Brightness.
*/
@@ -124,7 +118,6 @@ struct prev_params {
struct omap3isp_prev_csc rgb2ycbcr;
struct omap3isp_prev_hmed hmed;
struct omap3isp_prev_yclimit yclimit;
- u8 average;
u8 contrast;
u8 brightness;
};
@@ -159,6 +152,7 @@ struct isptables_update {
* @subdev: V4L2 subdevice
* @pads: Media entity pads
* @formats: Active formats at the subdev pad
+ * @crop: Active crop rectangle
* @input: Module currently connected to the input pad
* @output: Bitmask of the active output
* @video_in: Input video entity
@@ -177,6 +171,7 @@ struct isp_prev_device {
struct v4l2_subdev subdev;
struct media_pad pads[PREV_PADS_NUM];
struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
+ struct v4l2_rect crop;
struct v4l2_ctrl_handler ctrls;
diff --git a/drivers/media/video/omap3isp/ispqueue.c b/drivers/media/video/omap3isp/ispqueue.c
index 9c31714..9bebb1e 100644
--- a/drivers/media/video/omap3isp/ispqueue.c
+++ b/drivers/media/video/omap3isp/ispqueue.c
@@ -868,6 +868,10 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
goto done;
if (vbuf->memory == V4L2_MEMORY_USERPTR &&
+ vbuf->length < buf->vbuf.length)
+ goto done;
+
+ if (vbuf->memory == V4L2_MEMORY_USERPTR &&
vbuf->m.userptr != buf->vbuf.m.userptr) {
isp_video_buffer_cleanup(buf);
buf->vbuf.m.userptr = vbuf->m.userptr;
diff --git a/drivers/media/video/omap3isp/ispreg.h b/drivers/media/video/omap3isp/ispreg.h
index 69f6af6..084ea77 100644
--- a/drivers/media/video/omap3isp/ispreg.h
+++ b/drivers/media/video/omap3isp/ispreg.h
@@ -402,9 +402,6 @@
#define ISPPRV_YENH_TABLE_ADDR 0x1000
#define ISPPRV_CFA_TABLE_ADDR 0x1400
-#define ISPPRV_MAXOUTPUT_WIDTH 1280
-#define ISPPRV_MAXOUTPUT_WIDTH_ES2 3300
-#define ISPPRV_MAXOUTPUT_WIDTH_3630 4096
#define ISPRSZ_MIN_OUTPUT 64
#define ISPRSZ_MAX_OUTPUT 3312
diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c
index 0bb0f8c..50e593b 100644
--- a/drivers/media/video/omap3isp/ispresizer.c
+++ b/drivers/media/video/omap3isp/ispresizer.c
@@ -1608,6 +1608,42 @@ static const struct media_entity_operations resizer_media_ops = {
.link_setup = resizer_link_setup,
};
+void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
+{
+ v4l2_device_unregister_subdev(&res->subdev);
+ omap3isp_video_unregister(&res->video_in);
+ omap3isp_video_unregister(&res->video_out);
+}
+
+int omap3isp_resizer_register_entities(struct isp_res_device *res,
+ struct v4l2_device *vdev)
+{
+ int ret;
+
+ /* Register the subdev and video nodes. */
+ ret = v4l2_device_register_subdev(vdev, &res->subdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&res->video_in, vdev);
+ if (ret < 0)
+ goto error;
+
+ ret = omap3isp_video_register(&res->video_out, vdev);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ omap3isp_resizer_unregister_entities(res);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP resizer initialization and cleanup
+ */
+
/*
* resizer_init_entities - Initialize resizer subdev and media entity.
* @res : Pointer to resizer device structure
@@ -1652,68 +1688,34 @@ static int resizer_init_entities(struct isp_res_device *res)
ret = omap3isp_video_init(&res->video_in, "resizer");
if (ret < 0)
- return ret;
+ goto error_video_in;
ret = omap3isp_video_init(&res->video_out, "resizer");
if (ret < 0)
- return ret;
+ goto error_video_out;
/* Connect the video nodes to the resizer subdev. */
ret = media_entity_create_link(&res->video_in.video.entity, 0,
&res->subdev.entity, RESZ_PAD_SINK, 0);
if (ret < 0)
- return ret;
+ goto error_link;
ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
&res->video_out.video.entity, 0, 0);
if (ret < 0)
- return ret;
+ goto error_link;
return 0;
-}
-void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
-{
+error_link:
+ omap3isp_video_cleanup(&res->video_out);
+error_video_out:
+ omap3isp_video_cleanup(&res->video_in);
+error_video_in:
media_entity_cleanup(&res->subdev.entity);
-
- v4l2_device_unregister_subdev(&res->subdev);
- omap3isp_video_unregister(&res->video_in);
- omap3isp_video_unregister(&res->video_out);
-}
-
-int omap3isp_resizer_register_entities(struct isp_res_device *res,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video nodes. */
- ret = v4l2_device_register_subdev(vdev, &res->subdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&res->video_in, vdev);
- if (ret < 0)
- goto error;
-
- ret = omap3isp_video_register(&res->video_out, vdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- omap3isp_resizer_unregister_entities(res);
return ret;
}
-/* -----------------------------------------------------------------------------
- * ISP resizer initialization and cleanup
- */
-
-void omap3isp_resizer_cleanup(struct isp_device *isp)
-{
-}
-
/*
* isp_resizer_init - Resizer initialization.
* @isp : Pointer to ISP device
@@ -1722,17 +1724,17 @@ void omap3isp_resizer_cleanup(struct isp_device *isp)
int omap3isp_resizer_init(struct isp_device *isp)
{
struct isp_res_device *res = &isp->isp_res;
- int ret;
init_waitqueue_head(&res->wait);
atomic_set(&res->stopping, 0);
- ret = resizer_init_entities(res);
- if (ret < 0)
- goto out;
+ return resizer_init_entities(res);
+}
-out:
- if (ret)
- omap3isp_resizer_cleanup(isp);
+void omap3isp_resizer_cleanup(struct isp_device *isp)
+{
+ struct isp_res_device *res = &isp->isp_res;
- return ret;
+ omap3isp_video_cleanup(&res->video_in);
+ omap3isp_video_cleanup(&res->video_out);
+ media_entity_cleanup(&res->subdev.entity);
}
diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c
index b44cb68..bc0b2c7 100644
--- a/drivers/media/video/omap3isp/ispstat.c
+++ b/drivers/media/video/omap3isp/ispstat.c
@@ -366,7 +366,8 @@ static void isp_stat_bufs_free(struct ispstat *stat)
dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
buf->iovm->sgt->nents,
DMA_FROM_DEVICE);
- iommu_vfree(isp->iommu, buf->iommu_addr);
+ omap_iommu_vfree(isp->domain, isp->iommu,
+ buf->iommu_addr);
} else {
if (!buf->virt_addr)
continue;
@@ -399,8 +400,8 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
struct iovm_struct *iovm;
WARN_ON(buf->dma_addr);
- buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size,
- IOMMU_FLAG);
+ buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->iommu, 0,
+ size, IOMMU_FLAG);
if (IS_ERR((void *)buf->iommu_addr)) {
dev_err(stat->isp->dev,
"%s: Can't acquire memory for "
@@ -409,7 +410,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
return -ENOMEM;
}
- iovm = find_iovm_area(isp->iommu, buf->iommu_addr);
+ iovm = omap_find_iovm_area(isp->iommu, buf->iommu_addr);
if (!iovm ||
!dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
DMA_FROM_DEVICE)) {
@@ -418,7 +419,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
}
buf->iovm = iovm;
- buf->virt_addr = da_to_va(stat->isp->iommu,
+ buf->virt_addr = omap_da_to_va(stat->isp->iommu,
(u32)buf->iommu_addr);
buf->empty = 1;
dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
@@ -495,7 +496,7 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
static void isp_stat_queue_event(struct ispstat *stat, int err)
{
- struct video_device *vdev = &stat->subdev.devnode;
+ struct video_device *vdev = stat->subdev.devnode;
struct v4l2_event event;
struct omap3isp_stat_event_status *status = (void *)event.u.data;
@@ -1022,25 +1023,6 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
__stat_isr(stat, 1);
}
-static int isp_stat_init_entities(struct ispstat *stat, const char *name,
- const struct v4l2_subdev_ops *sd_ops)
-{
- struct v4l2_subdev *subdev = &stat->subdev;
- struct media_entity *me = &subdev->entity;
-
- v4l2_subdev_init(subdev, sd_ops);
- snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
- subdev->grp_id = 1 << 16; /* group ID for isp subdevs */
- subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
- subdev->nevents = STAT_NEVENTS;
- v4l2_set_subdevdata(subdev, stat);
-
- stat->pad.flags = MEDIA_PAD_FL_SINK;
- me->ops = NULL;
-
- return media_entity_init(me, 1, &stat->pad, 0);
-}
-
int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
@@ -1050,7 +1032,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
if (sub->type != stat->event_type)
return -EINVAL;
- return v4l2_event_subscribe(fh, sub);
+ return v4l2_event_subscribe(fh, sub, STAT_NEVENTS);
}
int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
@@ -1062,7 +1044,6 @@ int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
void omap3isp_stat_unregister_entities(struct ispstat *stat)
{
- media_entity_cleanup(&stat->subdev.entity);
v4l2_device_unregister_subdev(&stat->subdev);
}
@@ -1072,21 +1053,50 @@ int omap3isp_stat_register_entities(struct ispstat *stat,
return v4l2_device_register_subdev(vdev, &stat->subdev);
}
+static int isp_stat_init_entities(struct ispstat *stat, const char *name,
+ const struct v4l2_subdev_ops *sd_ops)
+{
+ struct v4l2_subdev *subdev = &stat->subdev;
+ struct media_entity *me = &subdev->entity;
+
+ v4l2_subdev_init(subdev, sd_ops);
+ snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
+ subdev->grp_id = 1 << 16; /* group ID for isp subdevs */
+ subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+ v4l2_set_subdevdata(subdev, stat);
+
+ stat->pad.flags = MEDIA_PAD_FL_SINK;
+ me->ops = NULL;
+
+ return media_entity_init(me, 1, &stat->pad, 0);
+}
+
int omap3isp_stat_init(struct ispstat *stat, const char *name,
const struct v4l2_subdev_ops *sd_ops)
{
+ int ret;
+
stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
if (!stat->buf)
return -ENOMEM;
+
isp_stat_buf_clear(stat);
mutex_init(&stat->ioctl_lock);
atomic_set(&stat->buf_err, 0);
- return isp_stat_init_entities(stat, name, sd_ops);
+ ret = isp_stat_init_entities(stat, name, sd_ops);
+ if (ret < 0) {
+ mutex_destroy(&stat->ioctl_lock);
+ kfree(stat->buf);
+ }
+
+ return ret;
}
-void omap3isp_stat_free(struct ispstat *stat)
+void omap3isp_stat_cleanup(struct ispstat *stat)
{
+ media_entity_cleanup(&stat->subdev.entity);
+ mutex_destroy(&stat->ioctl_lock);
isp_stat_bufs_free(stat);
kfree(stat->buf);
}
diff --git a/drivers/media/video/omap3isp/ispstat.h b/drivers/media/video/omap3isp/ispstat.h
index d86da94..9b7c865 100644
--- a/drivers/media/video/omap3isp/ispstat.h
+++ b/drivers/media/video/omap3isp/ispstat.h
@@ -144,7 +144,7 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,
struct omap3isp_stat_data *data);
int omap3isp_stat_init(struct ispstat *stat, const char *name,
const struct v4l2_subdev_ops *sd_ops);
-void omap3isp_stat_free(struct ispstat *stat);
+void omap3isp_stat_cleanup(struct ispstat *stat);
int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index 9cd8f1a..f229057 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -26,6 +26,7 @@
#include <asm/cacheflush.h>
#include <linux/clk.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
@@ -278,7 +279,8 @@ isp_video_far_end(struct isp_video *video)
* limits reported by every block in the pipeline.
*
* Return 0 if all formats match, or -EPIPE if at least one link is found with
- * different formats on its two ends.
+ * different formats on its two ends or if the pipeline doesn't start with a
+ * video source (either a subdev with no input pad, or a non-subdev entity).
*/
static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
{
@@ -329,10 +331,15 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
* in the middle of it. */
shifter_link = subdev == &isp->isp_ccdc.subdev;
- /* Retrieve the source format */
+ /* Retrieve the source format. Return an error if no source
+ * entity can be found, and stop checking the pipeline if the
+ * source entity isn't a subdev.
+ */
pad = media_entity_remote_source(pad);
- if (pad == NULL ||
- media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ if (pad == NULL)
+ return -EPIPE;
+
+ if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
break;
subdev = media_entity_to_v4l2_subdev(pad->entity);
@@ -446,7 +453,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
sgt->nents = sglen;
sgt->orig_nents = sglen;
- da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG);
+ da = omap_iommu_vmap(isp->domain, isp->iommu, 0, sgt, IOMMU_FLAG);
if (IS_ERR_VALUE(da))
kfree(sgt);
@@ -462,7 +469,7 @@ static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
{
struct sg_table *sgt;
- sgt = iommu_vunmap(isp->iommu, (u32)da);
+ sgt = omap_iommu_vunmap(isp->domain, isp->iommu, (u32)da);
kfree(sgt);
}
@@ -695,7 +702,6 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
strlcpy(cap->card, video->video.name, sizeof(cap->card));
strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
- cap->version = ISP_VIDEO_DRIVER_VERSION;
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
@@ -1051,6 +1057,14 @@ error:
if (video->isp->pdata->set_constraints)
video->isp->pdata->set_constraints(video->isp, false);
media_entity_pipeline_stop(&video->video.entity);
+ /* The DMA queue must be emptied here, otherwise CCDC interrupts
+ * that will get triggered the next time the CCDC is powered up
+ * will try to access buffers that might have been freed but
+ * still present in the DMA queue. This can easily get triggered
+ * if the above omap3isp_pipeline_set_stream() call fails on a
+ * system with a free-running sensor.
+ */
+ INIT_LIST_HEAD(&video->dmaqueue);
video->queue = NULL;
}
@@ -1312,6 +1326,13 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
return 0;
}
+void omap3isp_video_cleanup(struct isp_video *video)
+{
+ media_entity_cleanup(&video->video.entity);
+ mutex_destroy(&video->stream_lock);
+ mutex_destroy(&video->mutex);
+}
+
int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
{
int ret;
@@ -1328,8 +1349,6 @@ int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
void omap3isp_video_unregister(struct isp_video *video)
{
- if (video_is_registered(&video->video)) {
- media_entity_cleanup(&video->video.entity);
+ if (video_is_registered(&video->video))
video_unregister_device(&video->video);
- }
}
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h
index 911bea6..08cbfa1 100644
--- a/drivers/media/video/omap3isp/ispvideo.h
+++ b/drivers/media/video/omap3isp/ispvideo.h
@@ -27,7 +27,6 @@
#define OMAP3_ISP_VIDEO_H
#include <linux/v4l2-mediabus.h>
-#include <linux/version.h>
#include <media/media-entity.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
@@ -35,7 +34,7 @@
#include "ispqueue.h"
#define ISP_VIDEO_DRIVER_NAME "ispvideo"
-#define ISP_VIDEO_DRIVER_VERSION KERNEL_VERSION(0, 0, 1)
+#define ISP_VIDEO_DRIVER_VERSION "0.0.2"
struct isp_device;
struct isp_video;
@@ -191,6 +190,7 @@ struct isp_video_fh {
container_of(q, struct isp_video_fh, queue)
int omap3isp_video_init(struct isp_video *video, const char *name);
+void omap3isp_video_cleanup(struct isp_video *video);
int omap3isp_video_register(struct isp_video *video,
struct v4l2_device *vdev);
void omap3isp_video_unregister(struct isp_video *video);
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
index de2fc14..c17f37d 100644
--- a/drivers/media/video/pvrusb2/Makefile
+++ b/drivers/media/video/pvrusb2/Makefile
@@ -16,7 +16,7 @@ pvrusb2-objs := pvrusb2-i2c-core.o \
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index c4eca15..d8c8982 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -28,6 +28,7 @@ pvr2_device_desc structures.
#include "pvrusb2-devattr.h"
#include <linux/usb.h>
+#include <linux/module.h>
/* This is needed in order to pull in tuner type ids... */
#include <linux/i2c.h>
#include <media/tuner.h>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index e98d382..122b457 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -21,6 +21,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
@@ -2993,6 +2994,13 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id,
pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
}
+int pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw, v4l2_std_id *std)
+{
+ v4l2_device_call_all(&hdw->v4l2_dev, 0,
+ video, querystd, std);
+ return 0;
+}
+
/* Execute whatever commands are required to update the state of all the
sub-devices so that they match our current control values. */
static void pvr2_subdev_update(struct pvr2_hdw *hdw)
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index d7753ae..6654658 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -214,6 +214,9 @@ struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std,
unsigned int idx);
+/* Get the detected video standard */
+int pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw, v4l2_std_id *std);
+
/* Enable / disable retrieval of CPU firmware or prom contents. This must
be enabled before pvr2_hdw_cpufw_get() will function. Note that doing
this may prevent the device from running (and leaving this mode may
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index e72d510..885ce11 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -19,6 +19,7 @@
*/
#include <linux/i2c.h>
+#include <linux/module.h>
#include <media/ir-kbd-i2c.h>
#include "pvrusb2-i2c-core.h"
#include "pvrusb2-hdw-internal.h"
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index 2254194..c1d9bb6 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -168,6 +168,7 @@ module_exit(pvr_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_VERSION("0.9.1");
/*
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 3876114..6d66617 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -29,6 +29,7 @@
#include "pvrusb2-v4l2.h"
#include "pvrusb2-ioread.h"
#include <linux/videodev2.h>
+#include <linux/module.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
@@ -91,7 +92,7 @@ static struct v4l2_capability pvr_capability ={
.driver = "pvrusb2",
.card = "Hauppauge WinTV pvr-usb2",
.bus_info = "usb",
- .version = KERNEL_VERSION(0, 9, 0),
+ .version = LINUX_VERSION_CODE,
.capabilities = (V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
V4L2_CAP_READWRITE),
@@ -227,6 +228,14 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break;
}
+ case VIDIOC_QUERYSTD:
+ {
+ v4l2_std_id *std = arg;
+ *std = V4L2_STD_ALL;
+ ret = pvr2_hdw_get_detected_std(hdw, std);
+ break;
+ }
+
case VIDIOC_G_STD:
{
int val = 0;
@@ -369,11 +378,6 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break;
}
- case VIDIOC_S_AUDIO:
- {
- ret = -EINVAL;
- break;
- }
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
@@ -850,7 +854,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
#endif
default :
- ret = -EINVAL;
+ ret = -ENOTTY;
break;
}
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 8a5ff4d..a646ccf 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 10460fd..dbcdfbf 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -172,7 +172,9 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
dev->dmasound.bufsize, dev->dmasound.blocks);
spin_unlock(&dev->slock);
+ snd_pcm_stream_lock(dev->dmasound.substream);
snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock(dev->dmasound.substream);
return;
}
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index e2062b2..0f9fb99 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -4951,8 +4951,9 @@ struct saa7134_board saa7134_boards[] = {
.audio_clock = 0x00187de7,
.tuner_type = TUNER_XC2028,
.radio_type = UNSET,
- .tuner_addr = ADDR_UNSET,
+ .tuner_addr = 0x61,
.radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -6992,6 +6993,11 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev,
msleep(10);
saa7134_set_gpio(dev, 18, 1);
break;
+ case SAA7134_BOARD_VIDEOMATE_T750:
+ saa7134_set_gpio(dev, 20, 0);
+ msleep(10);
+ saa7134_set_gpio(dev, 20, 1);
+ break;
}
return 0;
}
@@ -7451,6 +7457,11 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0e050000, 0x0c050000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0e050000, 0x0c050000);
break;
+ case SAA7134_BOARD_VIDEOMATE_T750:
+ /* enable the analog tuner */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00008000, 0x00008000);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+ break;
}
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index f9be737..ca65cda 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -39,6 +39,8 @@
MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
+MODULE_VERSION(SAA7134_VERSION);
+
/* ------------------------------------------------------------------ */
@@ -1332,14 +1334,8 @@ static struct pci_driver saa7134_pci_driver = {
static int __init saa7134_init(void)
{
INIT_LIST_HEAD(&saa7134_devlist);
- printk(KERN_INFO "saa7130/34: v4l2 driver version %d.%d.%d loaded\n",
- (SAA7134_VERSION_CODE >> 16) & 0xff,
- (SAA7134_VERSION_CODE >> 8) & 0xff,
- SAA7134_VERSION_CODE & 0xff);
-#ifdef SNAPSHOT
- printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n",
- SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
-#endif
+ printk(KERN_INFO "saa7130/34: v4l2 driver version %s loaded\n",
+ SAA7134_VERSION);
return pci_register_driver(&saa7134_pci_driver);
}
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 996a206..1e4ef16 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -56,6 +56,7 @@
#include "lgs8gxx.h"
#include "zl10353.h"
+#include "qt1010.h"
#include "zl10036.h"
#include "zl10039.h"
@@ -939,6 +940,18 @@ static struct zl10353_config behold_x7_config = {
.disable_i2c_gate_ctrl = 1,
};
+static struct zl10353_config videomate_t750_zl10353_config = {
+ .demod_address = 0x0f,
+ .no_tuner = 1,
+ .parallel_ts = 1,
+ .disable_i2c_gate_ctrl = 1,
+};
+
+static struct qt1010_config videomate_t750_qt1010_config = {
+ .i2c_address = 0x62
+};
+
+
/* ==================================================================
* tda10086 based DVB-S cards, helper functions
*/
@@ -1650,6 +1663,18 @@ static int dvb_init(struct saa7134_dev *dev)
__func__);
break;
+ case SAA7134_BOARD_VIDEOMATE_T750:
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &videomate_t750_zl10353_config,
+ &dev->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ if (dvb_attach(qt1010_attach,
+ fe0->dvb.frontend,
+ &dev->i2c_adap,
+ &videomate_t750_qt1010_config) == NULL)
+ wprintk("error attaching QT1010\n");
+ }
+ break;
case SAA7134_BOARD_ZOLID_HYBRID_PCI:
fe0->dvb.frontend = dvb_attach(tda10048_attach,
&zolid_tda10048_config,
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 18294db..dde361a 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -172,7 +172,6 @@ static int empress_querycap(struct file *file, void *priv,
strlcpy(cap->card, saa7134_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->version = SAA7134_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 776ba2d..9cf7914f 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1810,7 +1810,6 @@ static int saa7134_querycap(struct file *file, void *priv,
strlcpy(cap->card, saa7134_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->version = SAA7134_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VBI_CAPTURE |
@@ -2307,7 +2306,6 @@ static int radio_querycap(struct file *file, void *priv,
strcpy(cap->driver, "saa7134");
strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->version = SAA7134_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 28eb103..9b55068 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -19,8 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0, 2, 16)
+#define SAA7134_VERSION "0, 2, 17"
#include <linux/pci.h>
#include <linux/i2c.h>
@@ -844,10 +843,10 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
int saa7134_ir_start(struct saa7134_dev *dev);
void saa7134_ir_stop(struct saa7134_dev *dev);
#else
-#define saa7134_input_init1(dev) (0)
-#define saa7134_input_fini(dev) (0)
-#define saa7134_input_irq(dev) (0)
-#define saa7134_probe_i2c_ir(dev) (0)
-#define saa7134_ir_start(dev) (0)
-#define saa7134_ir_stop(dev) (0)
+#define saa7134_input_init1(dev) ((void)0)
+#define saa7134_input_fini(dev) ((void)0)
+#define saa7134_input_irq(dev) ((void)0)
+#define saa7134_probe_i2c_ir(dev) ((void)0)
+#define saa7134_ir_start(dev) ((void)0)
+#define saa7134_ir_stop(dev) ((void)0)
#endif
diff --git a/drivers/media/video/saa7164/Makefile b/drivers/media/video/saa7164/Makefile
index 6303a8e..ecd5811 100644
--- a/drivers/media/video/saa7164/Makefile
+++ b/drivers/media/video/saa7164/Makefile
@@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \
obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
index c713691..971591d 100644
--- a/drivers/media/video/saa7164/saa7164-cards.c
+++ b/drivers/media/video/saa7164/saa7164-cards.c
@@ -447,6 +447,62 @@ struct saa7164_board saa7164_boards[] = {
.i2c_reg_len = REGLEN_8bit,
} },
},
+ [SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
+ .name = "Hauppauge WinTV-HVR2200",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x23,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "TDA18271-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x05,
+ .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
+ .name = "TDA8290-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0x84 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x21,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "TDA18271-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x22,
+ .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
+ .name = "TDA8290-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x84 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x24,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "TDA10048-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0x10 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x25,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "TDA10048-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x12 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
};
const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
@@ -490,6 +546,10 @@ struct saa7164_subid saa7164_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x8940,
.card = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x8953,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
},
};
const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
@@ -534,6 +594,7 @@ void saa7164_gpio_setup(struct saa7164_dev *dev)
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
@@ -615,6 +676,7 @@ void saa7164_card_setup(struct saa7164_dev *dev)
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
index 3b7d7b4..8f3c47e 100644
--- a/drivers/media/video/saa7164/saa7164-core.c
+++ b/drivers/media/video/saa7164/saa7164-core.c
@@ -1386,9 +1386,11 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
if (fw_debug) {
dev->kthread = kthread_run(saa7164_thread_function, dev,
"saa7164 debug");
- if (!dev->kthread)
+ if (IS_ERR(dev->kthread)) {
+ dev->kthread = NULL;
printk(KERN_ERR "%s() Failed to create "
"debug kernel thread\n", __func__);
+ }
}
} /* != BOARD_UNKNOWN */
diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/video/saa7164/saa7164-dvb.c
index d377937..5c5cc3e 100644
--- a/drivers/media/video/saa7164/saa7164-dvb.c
+++ b/drivers/media/video/saa7164/saa7164-dvb.c
@@ -476,6 +476,7 @@ int saa7164_dvb_register(struct saa7164_port *port)
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
i2c_bus = &dev->i2c_bus[port->nr + 1];
switch (port->nr) {
case 0:
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c
index 4003645..2fd38a0 100644
--- a/drivers/media/video/saa7164/saa7164-encoder.c
+++ b/drivers/media/video/saa7164/saa7164-encoder.c
@@ -1246,7 +1246,6 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
struct saa7164_encoder_fh *fh =
(struct saa7164_encoder_fh *)file->private_data;
struct saa7164_port *port = fh->port;
- struct saa7164_user_buffer *ubuf;
unsigned int mask = 0;
port->last_poll_msecs_diff = port->last_poll_msecs;
@@ -1278,10 +1277,7 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
}
/* Pull the first buffer from the used list */
- ubuf = list_first_entry(&port->list_buf_used.list,
- struct saa7164_user_buffer, list);
-
- if (ubuf)
+ if (!list_empty(&port->list_buf_used.list))
mask |= POLLIN | POLLRDNORM;
return mask;
diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c
index bc1fced..e2e0341 100644
--- a/drivers/media/video/saa7164/saa7164-vbi.c
+++ b/drivers/media/video/saa7164/saa7164-vbi.c
@@ -1192,7 +1192,6 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
{
struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
struct saa7164_port *port = fh->port;
- struct saa7164_user_buffer *ubuf;
unsigned int mask = 0;
port->last_poll_msecs_diff = port->last_poll_msecs;
@@ -1224,10 +1223,7 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
}
/* Pull the first buffer from the used list */
- ubuf = list_first_entry(&port->list_buf_used.list,
- struct saa7164_user_buffer, list);
-
- if (ubuf)
+ if (!list_empty(&port->list_buf_used.list))
mask |= POLLIN | POLLRDNORM;
return mask;
diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h
index 13bd27e..742b341 100644
--- a/drivers/media/video/saa7164/saa7164.h
+++ b/drivers/media/video/saa7164/saa7164.h
@@ -48,7 +48,6 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/kdev_t.h>
-#include <linux/version.h>
#include <linux/mutex.h>
#include <linux/crc32.h>
#include <linux/kthread.h>
@@ -84,6 +83,7 @@
#define SAA7164_BOARD_HAUPPAUGE_HVR2250_2 7
#define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8
#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10
#define SAA7164_MAX_UNITS 8
#define SAA7164_TS_NUMBER_OF_LINES 312
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index cbfc444..22ea211 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -21,7 +21,6 @@
#ifndef _SN9C102_H_
#define _SN9C102_H_
-#include <linux/version.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 0e07c49..16cb07c5 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -33,6 +33,7 @@
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
+#include <linux/version.h>
#include <linux/page-flags.h>
#include <asm/byteorder.h>
#include <asm/page.h>
@@ -47,8 +48,7 @@
#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.47pre49"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47)
+#define SN9C102_MODULE_VERSION "1:1.48"
/*****************************************************************************/
@@ -2158,7 +2158,7 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
{
struct v4l2_capability cap = {
.driver = "sn9c102",
- .version = SN9C102_MODULE_VERSION_CODE,
+ .version = LINUX_VERSION_CODE,
.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING,
};
@@ -3187,16 +3187,8 @@ static long sn9c102_ioctl_v4l2(struct file *filp,
case VIDIOC_S_AUDIO:
return sn9c102_vidioc_s_audio(cam, arg);
- case VIDIOC_G_STD:
- case VIDIOC_S_STD:
- case VIDIOC_QUERYSTD:
- case VIDIOC_ENUMSTD:
- case VIDIOC_QUERYMENU:
- case VIDIOC_ENUM_FRAMEINTERVALS:
- return -EINVAL;
-
default:
- return -EINVAL;
+ return -ENOTTY;
}
}
diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile
index 81bb7fd..ea09b9a 100644
--- a/drivers/media/video/tlg2300/Makefile
+++ b/drivers/media/video/tlg2300/Makefile
@@ -2,8 +2,8 @@ poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h
index 46066bd..56564e6 100644
--- a/drivers/media/video/tlg2300/pd-common.h
+++ b/drivers/media/video/tlg2300/pd-common.h
@@ -1,7 +1,6 @@
#ifndef PD_COMMON_H
#define PD_COMMON_H
-#include <linux/version.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/list.h>
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c
index edd78f8..d0da11a 100644
--- a/drivers/media/video/tlg2300/pd-dvb.c
+++ b/drivers/media/video/tlg2300/pd-dvb.c
@@ -7,7 +7,7 @@
#include "vendorcmds.h"
#include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
index 99c81a9..129f135 100644
--- a/drivers/media/video/tlg2300/pd-main.c
+++ b/drivers/media/video/tlg2300/pd-main.c
@@ -531,3 +531,4 @@ module_exit(poseidon_exit);
MODULE_AUTHOR("Telegent Systems");
MODULE_DESCRIPTION("For tlg2300-based USB device ");
MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c
index fae84c2..4fad1df 100644
--- a/drivers/media/video/tlg2300/pd-radio.c
+++ b/drivers/media/video/tlg2300/pd-radio.c
@@ -6,7 +6,6 @@
#include <linux/usb.h>
#include <linux/i2c.h>
#include <media/v4l2-dev.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <media/v4l2-ioctl.h>
@@ -149,7 +148,6 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(v->driver, "tele-radio", sizeof(v->driver));
strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
- v->version = KERNEL_VERSION(0, 0, 1);
v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0;
}
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile
index 3387187..aea1e3b 100644
--- a/drivers/media/video/usbvision/Makefile
+++ b/drivers/media/video/usbvision/Makefile
@@ -2,5 +2,5 @@ usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
index 8f52661..3103d0d 100644
--- a/drivers/media/video/usbvision/usbvision-cards.c
+++ b/drivers/media/video/usbvision/usbvision-cards.c
@@ -24,6 +24,7 @@
#include <linux/list.h>
+#include <linux/module.h>
#include <media/v4l2-dev.h>
#include <media/tuner.h>
#include "usbvision.h"
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index ea8ea8a..5a74f5e 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -45,7 +45,6 @@
*
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/timer.h>
@@ -77,15 +76,7 @@
#define DRIVER_ALIAS "USBVision"
#define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
#define DRIVER_LICENSE "GPL"
-#define USBVISION_DRIVER_VERSION_MAJOR 0
-#define USBVISION_DRIVER_VERSION_MINOR 9
-#define USBVISION_DRIVER_VERSION_PATCHLEVEL 10
-#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\
-USBVISION_DRIVER_VERSION_MINOR,\
-USBVISION_DRIVER_VERSION_PATCHLEVEL)
-#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) \
-"." __stringify(USBVISION_DRIVER_VERSION_MINOR) \
-"." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_VERSION_STRING "0.9.11"
#define ENABLE_HEXDUMP 0 /* Enable if you need it */
@@ -516,7 +507,6 @@ static int vidioc_querycap(struct file *file, void *priv,
usbvision_device_data[usbvision->dev_model].model_string,
sizeof(vc->card));
usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
- vc->version = USBVISION_DRIVER_VERSION;
vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_AUDIO |
V4L2_CAP_READWRITE |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index a4db26f..254d326 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -20,7 +20,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "uvcvideo.h"
@@ -1016,7 +1016,8 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
menu_info = &mapping->menu_info[query_menu->index];
- if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+ if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+ (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
s32 bitmap;
if (!ctrl->cached) {
@@ -1225,7 +1226,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
/* Valid menu indices are reported by the GET_RES request for
* UVC controls that support it.
*/
- if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+ if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+ (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
if (!ctrl->cached) {
ret = uvc_ctrl_populate_cache(chain, ctrl);
if (ret < 0)
@@ -1664,8 +1666,8 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
return -EINVAL;
}
- /* Search for the matching (GUID/CS) control in the given device */
- list_for_each_entry(entity, &dev->entities, list) {
+ /* Search for the matching (GUID/CS) control on the current chain */
+ list_for_each_entry(entity, &chain->entities, chain) {
unsigned int i;
if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 1f962dc..135e3ca 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -31,6 +31,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
+#include <linux/version.h>
#include <asm/atomic.h>
#include <asm/unaligned.h>
@@ -113,6 +114,11 @@ static struct uvc_format_desc uvc_fmts[] = {
.guid = UVC_GUID_FORMAT_RGBP,
.fcc = V4L2_PIX_FMT_RGB565,
},
+ {
+ .name = "H.264",
+ .guid = UVC_GUID_FORMAT_H264,
+ .fcc = V4L2_PIX_FMT_H264,
+ },
};
/* ------------------------------------------------------------------------
@@ -1591,12 +1597,12 @@ static void uvc_delete(struct uvc_device *dev)
{
struct list_head *p, *n;
- usb_put_intf(dev->intf);
- usb_put_dev(dev->udev);
-
uvc_status_cleanup(dev);
uvc_ctrl_cleanup_device(dev);
+ usb_put_intf(dev->intf);
+ usb_put_dev(dev->udev);
+
if (dev->vdev.dev)
v4l2_device_unregister(&dev->vdev);
#ifdef CONFIG_MEDIA_CONTROLLER
@@ -1857,7 +1863,7 @@ static int uvc_probe(struct usb_interface *intf,
sizeof(dev->mdev.serial));
strcpy(dev->mdev.bus_info, udev->devpath);
dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
- dev->mdev.driver_version = DRIVER_VERSION_NUMBER;
+ dev->mdev.driver_version = LINUX_VERSION_CODE;
if (media_device_register(&dev->mdev) < 0)
goto error;
@@ -2120,6 +2126,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Dell XPS M1330 (OmniVision OV7670 webcam) */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x05a9,
+ .idProduct = 0x7670,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_DEF },
/* Apple Built-In iSight */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2130,6 +2145,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_BUILTIN_ISIGHT },
+ /* Foxlink ("HP Webcam" on HP Mini 5103) */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x05c8,
+ .idProduct = 0x0403,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_FIX_BANDWIDTH },
/* Genesys Logic USB 2.0 PC Camera */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2321,6 +2345,14 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_DEF },
+ /* The Imaging Source USB CCD cameras */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x199e,
+ .idProduct = 0x8102,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0 },
/* Bodelin ProScopeHR */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_DEV_HI
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index f90ce9f..677691c 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -19,7 +19,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "uvcvideo.h"
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 5afdbb7..1030479 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -21,7 +21,7 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
@@ -32,7 +32,7 @@
* UVC ioctls
*/
static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
- struct uvc_xu_control_mapping *xmap, int old)
+ struct uvc_xu_control_mapping *xmap)
{
struct uvc_control_mapping *map;
unsigned int size;
@@ -58,13 +58,6 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
break;
case V4L2_CTRL_TYPE_MENU:
- if (old) {
- uvc_trace(UVC_TRACE_CONTROL, "V4L2_CTRL_TYPE_MENU not "
- "supported for UVCIOC_CTRL_MAP_OLD.\n");
- ret = -EINVAL;
- goto done;
- }
-
/* Prevent excessive memory consumption, as well as integer
* overflows.
*/
@@ -92,7 +85,7 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
default:
uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
"%u.\n", xmap->v4l2_type);
- ret = -EINVAL;
+ ret = -ENOTTY;
goto done;
}
@@ -547,20 +540,6 @@ static int uvc_v4l2_release(struct file *file)
return 0;
}
-static void uvc_v4l2_ioctl_warn(void)
-{
- static int warned;
-
- if (warned)
- return;
-
- uvc_printk(KERN_INFO, "Deprecated UVCIOC_CTRL_{ADD,MAP_OLD,GET,SET} "
- "ioctls will be removed in 2.6.42.\n");
- uvc_printk(KERN_INFO, "See http://www.ideasonboard.org/uvc/upgrade/ "
- "for upgrade instructions.\n");
- warned = 1;
-}
-
static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
@@ -580,7 +559,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
strlcpy(cap->card, vdev->name, sizeof cap->card);
usb_make_path(stream->dev->udev,
cap->bus_info, sizeof(cap->bus_info));
- cap->version = DRIVER_VERSION_NUMBER;
+ cap->version = LINUX_VERSION_CODE;
if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING;
@@ -1041,37 +1020,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
return -EINVAL;
- /* Dynamic controls. UVCIOC_CTRL_ADD, UVCIOC_CTRL_MAP_OLD,
- * UVCIOC_CTRL_GET and UVCIOC_CTRL_SET are deprecated and scheduled for
- * removal in 2.6.42.
- */
- case __UVCIOC_CTRL_ADD:
- uvc_v4l2_ioctl_warn();
- return -EEXIST;
-
- case __UVCIOC_CTRL_MAP_OLD:
- uvc_v4l2_ioctl_warn();
- case __UVCIOC_CTRL_MAP:
case UVCIOC_CTRL_MAP:
- return uvc_ioctl_ctrl_map(chain, arg,
- cmd == __UVCIOC_CTRL_MAP_OLD);
-
- case __UVCIOC_CTRL_GET:
- case __UVCIOC_CTRL_SET:
- {
- struct uvc_xu_control *xctrl = arg;
- struct uvc_xu_control_query xqry = {
- .unit = xctrl->unit,
- .selector = xctrl->selector,
- .query = cmd == __UVCIOC_CTRL_GET
- ? UVC_GET_CUR : UVC_SET_CUR,
- .size = xctrl->size,
- .data = xctrl->data,
- };
-
- uvc_v4l2_ioctl_warn();
- return uvc_xu_ctrl_query(chain, &xqry);
- }
+ return uvc_ioctl_ctrl_map(chain, arg);
case UVCIOC_CTRL_QUERY:
return uvc_xu_ctrl_query(chain, arg);
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 6f147de..af5c040 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -19,7 +19,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/unaligned.h>
#include <media/v4l2-common.h>
@@ -790,8 +790,12 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
for (i = 0; i < UVC_URBS; ++i) {
if (stream->urb_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
usb_free_coherent(stream->dev->udev, stream->urb_size,
stream->urb_buffer[i], stream->urb_dma[i]);
+#else
+ kfree(stream->urb_buffer[i]);
+#endif
stream->urb_buffer[i] = NULL;
}
}
@@ -831,9 +835,14 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
for (; npackets > 1; npackets /= 2) {
for (i = 0; i < UVC_URBS; ++i) {
stream->urb_size = psize * npackets;
+#ifndef CONFIG_DMA_NONCOHERENT
stream->urb_buffer[i] = usb_alloc_coherent(
stream->dev->udev, stream->urb_size,
gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
+#else
+ stream->urb_buffer[i] =
+ kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
+#endif
if (!stream->urb_buffer[i]) {
uvc_free_urb_buffers(stream);
break;
@@ -908,10 +917,14 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
urb->context = stream;
urb->pipe = usb_rcvisocpipe(stream->dev->udev,
ep->desc.bEndpointAddress);
+#ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+ urb->transfer_dma = stream->urb_dma[i];
+#else
+ urb->transfer_flags = URB_ISO_ASAP;
+#endif
urb->interval = ep->desc.bInterval;
urb->transfer_buffer = stream->urb_buffer[i];
- urb->transfer_dma = stream->urb_dma[i];
urb->complete = uvc_video_complete;
urb->number_of_packets = npackets;
urb->transfer_buffer_length = size;
@@ -969,8 +982,10 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
stream->urb_buffer[i], size, uvc_video_complete,
stream);
+#ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = stream->urb_dma[i];
+#endif
stream->urb[i] = urb;
}
@@ -1252,7 +1267,25 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
if (!enable) {
uvc_uninit_video(stream, 1);
- usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+ if (stream->intf->num_altsetting > 1) {
+ usb_set_interface(stream->dev->udev,
+ stream->intfnum, 0);
+ } else {
+ /* UVC doesn't specify how to inform a bulk-based device
+ * when the video stream is stopped. Windows sends a
+ * CLEAR_FEATURE(HALT) request to the video streaming
+ * bulk endpoint, mimic the same behaviour.
+ */
+ unsigned int epnum = stream->header.bEndpointAddress
+ & USB_ENDPOINT_NUMBER_MASK;
+ unsigned int dir = stream->header.bEndpointAddress
+ & USB_ENDPOINT_DIR_MASK;
+ unsigned int pipe;
+
+ pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
+ usb_clear_halt(stream->dev->udev, pipe);
+ }
+
uvc_queue_enable(&stream->queue, 0);
return 0;
}
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index cf2401a..bc446ba 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -1,106 +1,16 @@
#ifndef _USB_VIDEO_H_
#define _USB_VIDEO_H_
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-
-#ifndef __KERNEL__
-/*
- * This header provides binary compatibility with applications using the private
- * uvcvideo API. This API is deprecated and will be removed in 2.6.42.
- * Applications should be recompiled against the public linux/uvcvideo.h header.
- */
-#warn "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
-
-/*
- * Dynamic controls
- */
-
-/* Data types for UVC control data */
-#define UVC_CTRL_DATA_TYPE_RAW 0
-#define UVC_CTRL_DATA_TYPE_SIGNED 1
-#define UVC_CTRL_DATA_TYPE_UNSIGNED 2
-#define UVC_CTRL_DATA_TYPE_BOOLEAN 3
-#define UVC_CTRL_DATA_TYPE_ENUM 4
-#define UVC_CTRL_DATA_TYPE_BITMASK 5
-
-/* Control flags */
-#define UVC_CONTROL_SET_CUR (1 << 0)
-#define UVC_CONTROL_GET_CUR (1 << 1)
-#define UVC_CONTROL_GET_MIN (1 << 2)
-#define UVC_CONTROL_GET_MAX (1 << 3)
-#define UVC_CONTROL_GET_RES (1 << 4)
-#define UVC_CONTROL_GET_DEF (1 << 5)
-#define UVC_CONTROL_RESTORE (1 << 6)
-#define UVC_CONTROL_AUTO_UPDATE (1 << 7)
-
-#define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
- UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
- UVC_CONTROL_GET_DEF)
-
-struct uvc_menu_info {
- __u32 value;
- __u8 name[32];
-};
-
-struct uvc_xu_control_mapping {
- __u32 id;
- __u8 name[32];
- __u8 entity[16];
- __u8 selector;
-
- __u8 size;
- __u8 offset;
- __u32 v4l2_type;
- __u32 data_type;
-
- struct uvc_menu_info __user *menu_info;
- __u32 menu_count;
-
- __u32 reserved[4];
-};
-
-#endif
-
-struct uvc_xu_control_info {
- __u8 entity[16];
- __u8 index;
- __u8 selector;
- __u16 size;
- __u32 flags;
-};
-
-struct uvc_xu_control_mapping_old {
- __u8 reserved[64];
-};
-
-struct uvc_xu_control {
- __u8 unit;
- __u8 selector;
- __u16 size;
- __u8 __user *data;
-};
-
#ifndef __KERNEL__
-#define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info)
-#define UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old)
-#define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping)
-#define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control)
-#define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control)
-#else
-#define __UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info)
-#define __UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old)
-#define __UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping)
-#define __UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control)
-#define __UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control)
-#endif
-
-#ifdef __KERNEL__
+#error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
+#endif /* __KERNEL__ */
+#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/usb.h>
#include <linux/usb/video.h>
#include <linux/uvcvideo.h>
+#include <linux/videodev2.h>
#include <media/media-device.h>
#include <media/v4l2-device.h>
@@ -179,12 +89,15 @@ struct uvc_xu_control {
{ 'M', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_H264 \
+ { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
/* ------------------------------------------------------------------------
* Driver specific constants.
*/
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(1, 1, 0)
-#define DRIVER_VERSION "v1.1.0"
+#define DRIVER_VERSION "1.1.1"
/* Number of isochronous URBs. */
#define UVC_URBS 5
@@ -700,6 +613,4 @@ extern struct usb_host_endpoint *uvc_find_endpoint(
void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
struct uvc_buffer *buf);
-#endif /* __KERNEL__ */
-
#endif
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
index f3f6400..d7166af 100644
--- a/drivers/media/video/zoran/zoran.h
+++ b/drivers/media/video/zoran/zoran.h
@@ -41,10 +41,6 @@ struct zoran_sync {
};
-#define MAJOR_VERSION 0 /* driver major version */
-#define MINOR_VERSION 10 /* driver minor version */
-#define RELEASE_VERSION 0 /* release version */
-
#define ZORAN_NAME "ZORAN" /* name of the device */
#define ZR_DEVNAME(zr) ((zr)->name)
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
index 79b04ac..c3602d6 100644
--- a/drivers/media/video/zoran/zoran_card.c
+++ b/drivers/media/video/zoran/zoran_card.c
@@ -123,9 +123,12 @@ int zr36067_debug = 1;
module_param_named(debug, zr36067_debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-5)");
+#define ZORAN_VERSION "0.10.1"
+
MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
MODULE_AUTHOR("Serguei Miridonov");
MODULE_LICENSE("GPL");
+MODULE_VERSION(ZORAN_VERSION);
#define ZR_DEVICE(subven, subdev, data) { \
.vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
@@ -1459,8 +1462,8 @@ static int __init zoran_init(void)
{
int res;
- printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n",
- MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION);
+ printk(KERN_INFO "Zoran MJPEG board driver version %s\n",
+ ZORAN_VERSION);
/* check the parameters we have been given, adjust if necessary */
if (v4l_nbufs < 2)
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index 2771d81..d4d05d2 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -44,7 +44,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -1538,8 +1537,6 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
pci_name(zr->pci_dev));
- cap->version = KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
- RELEASE_VERSION);
cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
return 0;
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index 8c1d85e..56ff19c 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -17,6 +17,7 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#define DRIVER_NAME "memstick"
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 4a1909a..f8449d5 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/memstick.h>
+#include <linux/module.h>
#define DRIVER_NAME "mspro_block"
@@ -759,7 +760,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
if (msb->data_dir == READ) {
- for (cnt = 0; cnt < msb->current_seg; cnt++)
+ for (cnt = 0; cnt < msb->current_seg; cnt++) {
t_len += msb->req_sg[cnt].length
/ msb->page_size;
@@ -767,6 +768,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
t_len += msb->current_page - 1;
t_len *= msb->page_size;
+ }
}
} else
t_len = blk_rq_bytes(msb->block_req);
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index d89d925..6ce70e9 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -17,6 +17,7 @@
#include <linux/highmem.h>
#include <linux/memstick.h>
#include <linux/slab.h>
+#include <linux/module.h>
#define DRIVER_NAME "jmb38x_ms"
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index 03f71a4..b7aacf4 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -17,6 +17,7 @@
#include <linux/highmem.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
+#include <linux/module.h>
#include <asm/io.h>
#define DRIVER_NAME "tifm_ms"
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 7956a10..e9c6a60 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -63,6 +63,8 @@
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
+#include <linux/kthread.h>
+#include <scsi/scsi_host.h>
#include "mptbase.h"
#include "lsi/mpi_log_fc.h"
@@ -323,6 +325,32 @@ mpt_is_discovery_complete(MPT_ADAPTER *ioc)
return rc;
}
+
+/**
+ * mpt_remove_dead_ioc_func - kthread context to remove dead ioc
+ * @arg: input argument, used to derive ioc
+ *
+ * Return 0 if controller is removed from pci subsystem.
+ * Return -1 for other case.
+ */
+static int mpt_remove_dead_ioc_func(void *arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+ struct pci_dev *pdev;
+
+ if ((ioc == NULL))
+ return -1;
+
+ pdev = ioc->pcidev;
+ if ((pdev == NULL))
+ return -1;
+
+ pci_remove_bus_device(pdev);
+ return 0;
+}
+
+
+
/**
* mpt_fault_reset_work - work performed on workq after ioc fault
* @work: input argument, used to derive ioc
@@ -336,12 +364,45 @@ mpt_fault_reset_work(struct work_struct *work)
u32 ioc_raw_state;
int rc;
unsigned long flags;
+ MPT_SCSI_HOST *hd;
+ struct task_struct *p;
if (ioc->ioc_reset_in_progress || !ioc->active)
goto out;
+
ioc_raw_state = mpt_GetIocState(ioc, 0);
- if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
+ if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) {
+ printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n",
+ ioc->name, __func__);
+
+ /*
+ * Call mptscsih_flush_pending_cmds callback so that we
+ * flush all pending commands back to OS.
+ * This call is required to aovid deadlock at block layer.
+ * Dead IOC will fail to do diag reset,and this call is safe
+ * since dead ioc will never return any command back from HW.
+ */
+ hd = shost_priv(ioc->sh);
+ ioc->schedule_dead_ioc_flush_running_cmds(hd);
+
+ /*Remove the Dead Host */
+ p = kthread_run(mpt_remove_dead_ioc_func, ioc,
+ "mpt_dead_ioc_%d", ioc->id);
+ if (IS_ERR(p)) {
+ printk(MYIOC_s_ERR_FMT
+ "%s: Running mpt_dead_ioc thread failed !\n",
+ ioc->name, __func__);
+ } else {
+ printk(MYIOC_s_WARN_FMT
+ "%s: Running mpt_dead_ioc thread success !\n",
+ ioc->name, __func__);
+ }
+ return; /* don't rearm timer */
+ }
+
+ if ((ioc_raw_state & MPI_IOC_STATE_MASK)
+ == MPI_IOC_STATE_FAULT) {
printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
@@ -6413,8 +6474,19 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
pReq->Action, ioc->mptbase_cmds.status, timeleft));
if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
goto out;
- if (!timeleft)
+ if (!timeleft) {
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock,
+ flags);
+ printk(MYIOC_s_INFO_FMT "%s: host reset in"
+ " progress mpt_config timed out.!!\n",
+ __func__, ioc->name);
+ return -EFAULT;
+ }
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
issue_hard_reset = 1;
+ }
goto out;
}
@@ -7128,7 +7200,18 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
if (ioc->ioc_reset_in_progress) {
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
- return 0;
+ ioc->wait_on_reset_completion = 1;
+ do {
+ ssleep(1);
+ } while (ioc->ioc_reset_in_progress == 1);
+ ioc->wait_on_reset_completion = 0;
+ return ioc->reset_status;
+ }
+ if (ioc->wait_on_reset_completion) {
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+ rc = 0;
+ time_count = jiffies;
+ goto exit;
}
ioc->ioc_reset_in_progress = 1;
if (ioc->alt_ioc)
@@ -7165,6 +7248,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
ioc->ioc_reset_in_progress = 0;
ioc->taskmgmt_quiesce_io = 0;
ioc->taskmgmt_in_progress = 0;
+ ioc->reset_status = rc;
if (ioc->alt_ioc) {
ioc->alt_ioc->ioc_reset_in_progress = 0;
ioc->alt_ioc->taskmgmt_quiesce_io = 0;
@@ -7180,7 +7264,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
ioc->alt_ioc, MPT_IOC_POST_RESET);
}
}
-
+exit:
dtmprintk(ioc,
printk(MYIOC_s_DEBUG_FMT
"HardResetHandler: completed (%d seconds): %s\n", ioc->name,
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index fe90233..b4d24dc 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.04.19"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.19"
+#define MPT_LINUX_VERSION_COMMON "3.04.20"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.20"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -554,10 +554,47 @@ struct mptfc_rport_info
u8 flags;
};
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
+ * Private to the driver.
+ */
+
+#define MPT_HOST_BUS_UNKNOWN (0xFF)
+#define MPT_HOST_TOO_MANY_TM (0x05)
+#define MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
+#define MPT_HOST_NO_CHAIN (0xFFFFFFFF)
+#define MPT_NVRAM_MASK_TIMEOUT (0x000000FF)
+#define MPT_NVRAM_SYNC_MASK (0x0000FF00)
+#define MPT_NVRAM_SYNC_SHIFT (8)
+#define MPT_NVRAM_DISCONNECT_ENABLE (0x00010000)
+#define MPT_NVRAM_ID_SCAN_ENABLE (0x00020000)
+#define MPT_NVRAM_LUN_SCAN_ENABLE (0x00040000)
+#define MPT_NVRAM_TAG_QUEUE_ENABLE (0x00080000)
+#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
+#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
+
+typedef enum {
+ FC,
+ SPI,
+ SAS
+} BUS_TYPE;
+
+typedef struct _MPT_SCSI_HOST {
+ struct _MPT_ADAPTER *ioc;
+ ushort sel_timeout[MPT_MAX_FC_DEVICES];
+ char *info_kbuf;
+ long last_queue_full;
+ u16 spi_pending;
+ struct list_head target_reset_list;
+} MPT_SCSI_HOST;
+
typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
dma_addr_t dma_addr);
typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc);
+typedef void (*MPT_FLUSH_RUNNING_CMDS)(MPT_SCSI_HOST *hd);
/*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
@@ -716,7 +753,10 @@ typedef struct _MPT_ADAPTER
int taskmgmt_in_progress;
u8 taskmgmt_quiesce_io;
u8 ioc_reset_in_progress;
+ u8 reset_status;
+ u8 wait_on_reset_completion;
MPT_SCHEDULE_TARGET_RESET schedule_target_reset;
+ MPT_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
struct work_struct sas_persist_task;
struct work_struct fc_setup_reset_work;
@@ -830,19 +870,6 @@ typedef struct _MPT_LOCAL_REPLY {
u32 pad;
} MPT_LOCAL_REPLY;
-#define MPT_HOST_BUS_UNKNOWN (0xFF)
-#define MPT_HOST_TOO_MANY_TM (0x05)
-#define MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
-#define MPT_HOST_NO_CHAIN (0xFFFFFFFF)
-#define MPT_NVRAM_MASK_TIMEOUT (0x000000FF)
-#define MPT_NVRAM_SYNC_MASK (0x0000FF00)
-#define MPT_NVRAM_SYNC_SHIFT (8)
-#define MPT_NVRAM_DISCONNECT_ENABLE (0x00010000)
-#define MPT_NVRAM_ID_SCAN_ENABLE (0x00020000)
-#define MPT_NVRAM_LUN_SCAN_ENABLE (0x00040000)
-#define MPT_NVRAM_TAG_QUEUE_ENABLE (0x00080000)
-#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
-#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
/* The TM_STATE variable is used to provide strict single threading of TM
* requests as well as communicate TM error conditions.
@@ -851,21 +878,6 @@ typedef struct _MPT_LOCAL_REPLY {
#define TM_STATE_IN_PROGRESS (1)
#define TM_STATE_ERROR (2)
-typedef enum {
- FC,
- SPI,
- SAS
-} BUS_TYPE;
-
-typedef struct _MPT_SCSI_HOST {
- MPT_ADAPTER *ioc;
- ushort sel_timeout[MPT_MAX_FC_DEVICES];
- char *info_kbuf;
- long last_queue_full;
- u16 spi_pending;
- struct list_head target_reset_list;
-} MPT_SCSI_HOST;
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* More Dynamic Multi-Pathing stuff...
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 7596aec..9d95042 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -92,6 +92,11 @@ static int max_lun = MPTSAS_MAX_LUN;
module_param(max_lun, int, 0);
MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+static int mpt_loadtime_max_sectors = 8192;
+module_param(mpt_loadtime_max_sectors, int, 0);
+MODULE_PARM_DESC(mpt_loadtime_max_sectors,
+ " Maximum sector define for Host Bus Adaptor.Range 64 to 8192 default=8192");
+
static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
@@ -285,10 +290,11 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
spin_lock_irqsave(&ioc->fw_event_lock, flags);
list_add_tail(&fw_event->list, &ioc->fw_event_list);
INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
- devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
- ioc->name, __func__, fw_event));
- queue_delayed_work(ioc->fw_event_q, &fw_event->work,
- delay);
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)"
+ "on cpuid %d\n", ioc->name, __func__,
+ fw_event, smp_processor_id()));
+ queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
+ &fw_event->work, delay);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -300,10 +306,11 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
unsigned long flags;
spin_lock_irqsave(&ioc->fw_event_lock, flags);
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
- "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
+ "(fw_event=0x%p)on cpuid %d\n", ioc->name, __func__,
+ fw_event, smp_processor_id()));
fw_event->retries++;
- queue_delayed_work(ioc->fw_event_q, &fw_event->work,
- msecs_to_jiffies(delay));
+ queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
+ &fw_event->work, msecs_to_jiffies(delay));
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -1943,6 +1950,15 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
goto done;
}
+ /* In case if IOC is in reset from internal context.
+ * Do not execute EEH for the same IOC. SML should to reset timer.
+ */
+ if (ioc->ioc_reset_in_progress) {
+ dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset,"
+ "SML need to reset the timer (sc=%p)\n",
+ ioc->name, __func__, sc));
+ rc = BLK_EH_RESET_TIMER;
+ }
vdevice = sc->device->hostdata;
if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
|| vdevice->vtarget->deleted)) {
@@ -5142,6 +5158,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->TaskCtx = mptsasTaskCtx;
ioc->InternalCtx = mptsasInternalCtx;
ioc->schedule_target_reset = &mptsas_schedule_target_reset;
+ ioc->schedule_dead_ioc_flush_running_cmds =
+ &mptscsih_flush_running_cmds;
/* Added sanity check on readiness of the MPT adapter.
*/
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
@@ -5239,6 +5257,21 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->sg_tablesize = numSGE;
}
+ if (mpt_loadtime_max_sectors) {
+ if (mpt_loadtime_max_sectors < 64 ||
+ mpt_loadtime_max_sectors > 8192) {
+ printk(MYIOC_s_INFO_FMT "Invalid value passed for"
+ "mpt_loadtime_max_sectors %d."
+ "Range from 64 to 8192\n", ioc->name,
+ mpt_loadtime_max_sectors);
+ }
+ mpt_loadtime_max_sectors &= 0xFFFFFFFE;
+ dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+ "Resetting max sector to %d from %d\n",
+ ioc->name, mpt_loadtime_max_sectors, sh->max_sectors));
+ sh->max_sectors = mpt_loadtime_max_sectors;
+ }
+
hd = shost_priv(sh);
hd->ioc = ioc;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index a1d4ee6..0c3ced7 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -827,10 +827,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
* DID_SOFT_ERROR is set.
*/
if (ioc->bus_type == SPI) {
- if (pScsiReq->CDB[0] == READ_6 ||
+ if ((pScsiReq->CDB[0] == READ_6 && ((pScsiReq->CDB[1] & 0x02) == 0)) ||
pScsiReq->CDB[0] == READ_10 ||
pScsiReq->CDB[0] == READ_12 ||
- pScsiReq->CDB[0] == READ_16 ||
+ (pScsiReq->CDB[0] == READ_16 &&
+ ((pScsiReq->CDB[1] & 0x02) == 0)) ||
pScsiReq->CDB[0] == VERIFY ||
pScsiReq->CDB[0] == VERIFY_16) {
if (scsi_bufflen(sc) !=
@@ -1024,7 +1025,7 @@ out:
*
* Must be called while new I/Os are being queued.
*/
-static void
+void
mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
{
MPT_ADAPTER *ioc = hd->ioc;
@@ -1055,6 +1056,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
sc->scsi_done(sc);
}
}
+EXPORT_SYMBOL(mptscsih_flush_running_cmds);
/*
* mptscsih_search_running_cmds - Delete any commands associated
@@ -1629,7 +1631,13 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
return 0;
}
- if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
+ /* DOORBELL ACTIVE check is not required if
+ * MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported.
+ */
+
+ if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q)
+ && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) &&
+ (ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
printk(MYIOC_s_WARN_FMT
"TaskMgmt type=%x: ioc_state: "
"DOORBELL_ACTIVE (0x%x)!\n",
@@ -1728,7 +1736,9 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
printk(MYIOC_s_WARN_FMT
"Issuing Reset from %s!! doorbell=0x%08x\n",
ioc->name, __func__, mpt_GetIocState(ioc, 0));
- retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
+ retval = (ioc->bus_type == SAS) ?
+ mpt_HardResetHandler(ioc, CAN_SLEEP) :
+ mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
mpt_free_msg_frame(ioc, mf);
}
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 45a5ff3..43e75ff 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -135,3 +135,4 @@ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern struct device_attribute *mptscsih_host_attrs[];
extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
+extern void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd);
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 74fbe56..c8ed7b6 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -59,7 +59,7 @@
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 090d2a3..a8c08f3 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -681,11 +681,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->mem_alloc = 1;
- sb->current_mem_size = 1 + res->end - res->start;
+ sb->current_mem_size = resource_size(res);
sb->current_mem_base = res->start;
osm_info("%s: allocated %llu bytes of PCI memory at "
"0x%016llX.\n", c->name,
- (unsigned long long)(1 + res->end - res->start),
+ (unsigned long long)resource_size(res),
(unsigned long long)res->start);
}
}
@@ -703,11 +703,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->io_alloc = 1;
- sb->current_io_size = 1 + res->end - res->start;
+ sb->current_io_size = resource_size(res);
sb->current_mem_base = res->start;
osm_info("%s: allocated %llu bytes of PCI I/O at "
"0x%016llX.\n", c->name,
- (unsigned long long)(1 + res->end - res->start),
+ (unsigned long long)resource_size(res),
(unsigned long long)res->start);
}
}
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 73e4658..7190d52 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -31,6 +31,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/i2o.h>
+#include <linux/module.h>
#include "core.h"
#define OSM_DESCRIPTION "I2O-subsystem"
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
index 8b51cd6..29d12a7 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -163,7 +163,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
int i;
if (lis3->blkread) {
- if (lis3_dev.whoami == WAI_12B) {
+ if (lis3->whoami == WAI_12B) {
u16 data[3];
lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
for (i = 0; i < 3; i++)
@@ -195,18 +195,30 @@ static int lis3_8_rates[2] = {100, 400};
static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
/* ODR is Output Data Rate */
-static int lis3lv02d_get_odr(void)
+static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
{
u8 ctrl;
int shift;
- lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
- ctrl &= lis3_dev.odr_mask;
- shift = ffs(lis3_dev.odr_mask) - 1;
- return lis3_dev.odrs[(ctrl >> shift)];
+ lis3->read(lis3, CTRL_REG1, &ctrl);
+ ctrl &= lis3->odr_mask;
+ shift = ffs(lis3->odr_mask) - 1;
+ return lis3->odrs[(ctrl >> shift)];
}
-static int lis3lv02d_set_odr(int rate)
+static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3)
+{
+ int div = lis3lv02d_get_odr(lis3);
+
+ if (WARN_ONCE(div == 0, "device returned spurious data"))
+ return -ENXIO;
+
+ /* LIS3 power on delay is quite long */
+ msleep(lis3->pwron_delay / div);
+ return 0;
+}
+
+static int lis3lv02d_set_odr(struct lis3lv02d *lis3, int rate)
{
u8 ctrl;
int i, len, shift;
@@ -214,14 +226,14 @@ static int lis3lv02d_set_odr(int rate)
if (!rate)
return -EINVAL;
- lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
- ctrl &= ~lis3_dev.odr_mask;
- len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
- shift = ffs(lis3_dev.odr_mask) - 1;
+ lis3->read(lis3, CTRL_REG1, &ctrl);
+ ctrl &= ~lis3->odr_mask;
+ len = 1 << hweight_long(lis3->odr_mask); /* # of possible values */
+ shift = ffs(lis3->odr_mask) - 1;
for (i = 0; i < len; i++)
- if (lis3_dev.odrs[i] == rate) {
- lis3_dev.write(&lis3_dev, CTRL_REG1,
+ if (lis3->odrs[i] == rate) {
+ lis3->write(lis3, CTRL_REG1,
ctrl | (i << shift));
return 0;
}
@@ -240,12 +252,12 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
mutex_lock(&lis3->mutex);
irq_cfg = lis3->irq_cfg;
- if (lis3_dev.whoami == WAI_8B) {
+ if (lis3->whoami == WAI_8B) {
lis3->data_ready_count[IRQ_LINE0] = 0;
lis3->data_ready_count[IRQ_LINE1] = 0;
/* Change interrupt cfg to data ready for selftest */
- atomic_inc(&lis3_dev.wake_thread);
+ atomic_inc(&lis3->wake_thread);
lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
@@ -253,12 +265,12 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
}
- if (lis3_dev.whoami == WAI_3DC) {
+ if (lis3->whoami == WAI_3DC) {
ctlreg = CTRL_REG4;
selftest = CTRL4_ST0;
} else {
ctlreg = CTRL_REG1;
- if (lis3_dev.whoami == WAI_12B)
+ if (lis3->whoami == WAI_12B)
selftest = CTRL1_ST;
else
selftest = CTRL1_STP;
@@ -266,7 +278,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
lis3->read(lis3, ctlreg, &reg);
lis3->write(lis3, ctlreg, (reg | selftest));
- msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+ ret = lis3lv02d_get_pwron_wait(lis3);
+ if (ret)
+ goto fail;
/* Read directly to avoid axis remap */
x = lis3->read_data(lis3, OUTX);
@@ -275,7 +289,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
/* back to normal settings */
lis3->write(lis3, ctlreg, reg);
- msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+ ret = lis3lv02d_get_pwron_wait(lis3);
+ if (ret)
+ goto fail;
results[0] = x - lis3->read_data(lis3, OUTX);
results[1] = y - lis3->read_data(lis3, OUTY);
@@ -283,9 +299,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
ret = 0;
- if (lis3_dev.whoami == WAI_8B) {
+ if (lis3->whoami == WAI_8B) {
/* Restore original interrupt configuration */
- atomic_dec(&lis3_dev.wake_thread);
+ atomic_dec(&lis3->wake_thread);
lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
lis3->irq_cfg = irq_cfg;
@@ -363,8 +379,9 @@ void lis3lv02d_poweroff(struct lis3lv02d *lis3)
}
EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
-void lis3lv02d_poweron(struct lis3lv02d *lis3)
+int lis3lv02d_poweron(struct lis3lv02d *lis3)
{
+ int err;
u8 reg;
lis3->init(lis3);
@@ -384,35 +401,41 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
lis3->write(lis3, CTRL_REG2, reg);
}
- /* LIS3 power on delay is quite long */
- msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+ err = lis3lv02d_get_pwron_wait(lis3);
+ if (err)
+ return err;
if (lis3->reg_ctrl)
lis3_context_restore(lis3);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
{
+ struct lis3lv02d *lis3 = pidev->private;
int x, y, z;
- mutex_lock(&lis3_dev.mutex);
- lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+ mutex_lock(&lis3->mutex);
+ lis3lv02d_get_xyz(lis3, &x, &y, &z);
input_report_abs(pidev->input, ABS_X, x);
input_report_abs(pidev->input, ABS_Y, y);
input_report_abs(pidev->input, ABS_Z, z);
input_sync(pidev->input);
- mutex_unlock(&lis3_dev.mutex);
+ mutex_unlock(&lis3->mutex);
}
static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
{
- if (lis3_dev.pm_dev)
- pm_runtime_get_sync(lis3_dev.pm_dev);
+ struct lis3lv02d *lis3 = pidev->private;
- if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
- atomic_set(&lis3_dev.wake_thread, 1);
+ if (lis3->pm_dev)
+ pm_runtime_get_sync(lis3->pm_dev);
+
+ if (lis3->pdata && lis3->whoami == WAI_8B && lis3->idev)
+ atomic_set(&lis3->wake_thread, 1);
/*
* Update coordinates for the case where poll interval is 0 and
* the chip in running purely under interrupt control
@@ -422,14 +445,18 @@ static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
{
- atomic_set(&lis3_dev.wake_thread, 0);
- if (lis3_dev.pm_dev)
- pm_runtime_put(lis3_dev.pm_dev);
+ struct lis3lv02d *lis3 = pidev->private;
+
+ atomic_set(&lis3->wake_thread, 0);
+ if (lis3->pm_dev)
+ pm_runtime_put(lis3->pm_dev);
}
-static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+static irqreturn_t lis302dl_interrupt(int irq, void *data)
{
- if (!test_bit(0, &lis3_dev.misc_opened))
+ struct lis3lv02d *lis3 = data;
+
+ if (!test_bit(0, &lis3->misc_opened))
goto out;
/*
@@ -437,12 +464,12 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
* the lid is closed. This leads to interrupts as soon as a little move
* is done.
*/
- atomic_inc(&lis3_dev.count);
+ atomic_inc(&lis3->count);
- wake_up_interruptible(&lis3_dev.misc_wait);
- kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+ wake_up_interruptible(&lis3->misc_wait);
+ kill_fasync(&lis3->async_queue, SIGIO, POLL_IN);
out:
- if (atomic_read(&lis3_dev.wake_thread))
+ if (atomic_read(&lis3->wake_thread))
return IRQ_WAKE_THREAD;
return IRQ_HANDLED;
}
@@ -514,28 +541,37 @@ static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
{
- if (test_and_set_bit(0, &lis3_dev.misc_opened))
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ if (test_and_set_bit(0, &lis3->misc_opened))
return -EBUSY; /* already open */
- if (lis3_dev.pm_dev)
- pm_runtime_get_sync(lis3_dev.pm_dev);
+ if (lis3->pm_dev)
+ pm_runtime_get_sync(lis3->pm_dev);
- atomic_set(&lis3_dev.count, 0);
+ atomic_set(&lis3->count, 0);
return 0;
}
static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
{
- fasync_helper(-1, file, 0, &lis3_dev.async_queue);
- clear_bit(0, &lis3_dev.misc_opened); /* release the device */
- if (lis3_dev.pm_dev)
- pm_runtime_put(lis3_dev.pm_dev);
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ fasync_helper(-1, file, 0, &lis3->async_queue);
+ clear_bit(0, &lis3->misc_opened); /* release the device */
+ if (lis3->pm_dev)
+ pm_runtime_put(lis3->pm_dev);
return 0;
}
static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
DECLARE_WAITQUEUE(wait, current);
u32 data;
unsigned char byte_data;
@@ -544,10 +580,10 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
if (count < 1)
return -EINVAL;
- add_wait_queue(&lis3_dev.misc_wait, &wait);
+ add_wait_queue(&lis3->misc_wait, &wait);
while (true) {
set_current_state(TASK_INTERRUPTIBLE);
- data = atomic_xchg(&lis3_dev.count, 0);
+ data = atomic_xchg(&lis3->count, 0);
if (data)
break;
@@ -577,22 +613,28 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
out:
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&lis3_dev.misc_wait, &wait);
+ remove_wait_queue(&lis3->misc_wait, &wait);
return retval;
}
static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, &lis3_dev.misc_wait, wait);
- if (atomic_read(&lis3_dev.count))
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ poll_wait(file, &lis3->misc_wait, wait);
+ if (atomic_read(&lis3->count))
return POLLIN | POLLRDNORM;
return 0;
}
static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
{
- return fasync_helper(fd, file, on, &lis3_dev.async_queue);
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ return fasync_helper(fd, file, on, &lis3->async_queue);
}
static const struct file_operations lis3lv02d_misc_fops = {
@@ -605,85 +647,80 @@ static const struct file_operations lis3lv02d_misc_fops = {
.fasync = lis3lv02d_misc_fasync,
};
-static struct miscdevice lis3lv02d_misc_device = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "freefall",
- .fops = &lis3lv02d_misc_fops,
-};
-
-int lis3lv02d_joystick_enable(void)
+int lis3lv02d_joystick_enable(struct lis3lv02d *lis3)
{
struct input_dev *input_dev;
int err;
int max_val, fuzz, flat;
int btns[] = {BTN_X, BTN_Y, BTN_Z};
- if (lis3_dev.idev)
+ if (lis3->idev)
return -EINVAL;
- lis3_dev.idev = input_allocate_polled_device();
- if (!lis3_dev.idev)
+ lis3->idev = input_allocate_polled_device();
+ if (!lis3->idev)
return -ENOMEM;
- lis3_dev.idev->poll = lis3lv02d_joystick_poll;
- lis3_dev.idev->open = lis3lv02d_joystick_open;
- lis3_dev.idev->close = lis3lv02d_joystick_close;
- lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
- lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
- lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
- input_dev = lis3_dev.idev->input;
+ lis3->idev->poll = lis3lv02d_joystick_poll;
+ lis3->idev->open = lis3lv02d_joystick_open;
+ lis3->idev->close = lis3lv02d_joystick_close;
+ lis3->idev->poll_interval = MDPS_POLL_INTERVAL;
+ lis3->idev->poll_interval_min = MDPS_POLL_MIN;
+ lis3->idev->poll_interval_max = MDPS_POLL_MAX;
+ lis3->idev->private = lis3;
+ input_dev = lis3->idev->input;
input_dev->name = "ST LIS3LV02DL Accelerometer";
input_dev->phys = DRIVER_NAME "/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0;
- input_dev->dev.parent = &lis3_dev.pdev->dev;
+ input_dev->dev.parent = &lis3->pdev->dev;
set_bit(EV_ABS, input_dev->evbit);
- max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
- if (lis3_dev.whoami == WAI_12B) {
+ max_val = (lis3->mdps_max_val * lis3->scale) / LIS3_ACCURACY;
+ if (lis3->whoami == WAI_12B) {
fuzz = LIS3_DEFAULT_FUZZ_12B;
flat = LIS3_DEFAULT_FLAT_12B;
} else {
fuzz = LIS3_DEFAULT_FUZZ_8B;
flat = LIS3_DEFAULT_FLAT_8B;
}
- fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
- flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+ fuzz = (fuzz * lis3->scale) / LIS3_ACCURACY;
+ flat = (flat * lis3->scale) / LIS3_ACCURACY;
input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
- lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
- lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
- lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
+ lis3->mapped_btns[0] = lis3lv02d_get_axis(abs(lis3->ac.x), btns);
+ lis3->mapped_btns[1] = lis3lv02d_get_axis(abs(lis3->ac.y), btns);
+ lis3->mapped_btns[2] = lis3lv02d_get_axis(abs(lis3->ac.z), btns);
- err = input_register_polled_device(lis3_dev.idev);
+ err = input_register_polled_device(lis3->idev);
if (err) {
- input_free_polled_device(lis3_dev.idev);
- lis3_dev.idev = NULL;
+ input_free_polled_device(lis3->idev);
+ lis3->idev = NULL;
}
return err;
}
EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
-void lis3lv02d_joystick_disable(void)
+void lis3lv02d_joystick_disable(struct lis3lv02d *lis3)
{
- if (lis3_dev.irq)
- free_irq(lis3_dev.irq, &lis3_dev);
- if (lis3_dev.pdata && lis3_dev.pdata->irq2)
- free_irq(lis3_dev.pdata->irq2, &lis3_dev);
+ if (lis3->irq)
+ free_irq(lis3->irq, lis3);
+ if (lis3->pdata && lis3->pdata->irq2)
+ free_irq(lis3->pdata->irq2, lis3);
- if (!lis3_dev.idev)
+ if (!lis3->idev)
return;
- if (lis3_dev.irq)
- misc_deregister(&lis3lv02d_misc_device);
- input_unregister_polled_device(lis3_dev.idev);
- input_free_polled_device(lis3_dev.idev);
- lis3_dev.idev = NULL;
+ if (lis3->irq)
+ misc_deregister(&lis3->miscdev);
+ input_unregister_polled_device(lis3->idev);
+ input_free_polled_device(lis3->idev);
+ lis3->idev = NULL;
}
EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
@@ -708,6 +745,7 @@ static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
static ssize_t lis3lv02d_selftest_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
s16 values[3];
static const char ok[] = "OK";
@@ -715,8 +753,8 @@ static ssize_t lis3lv02d_selftest_show(struct device *dev,
static const char irq[] = "FAIL_IRQ";
const char *res;
- lis3lv02d_sysfs_poweron(&lis3_dev);
- switch (lis3lv02d_selftest(&lis3_dev, values)) {
+ lis3lv02d_sysfs_poweron(lis3);
+ switch (lis3lv02d_selftest(lis3, values)) {
case SELFTEST_FAIL:
res = fail;
break;
@@ -735,33 +773,37 @@ static ssize_t lis3lv02d_selftest_show(struct device *dev,
static ssize_t lis3lv02d_position_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
int x, y, z;
- lis3lv02d_sysfs_poweron(&lis3_dev);
- mutex_lock(&lis3_dev.mutex);
- lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
- mutex_unlock(&lis3_dev.mutex);
+ lis3lv02d_sysfs_poweron(lis3);
+ mutex_lock(&lis3->mutex);
+ lis3lv02d_get_xyz(lis3, &x, &y, &z);
+ mutex_unlock(&lis3->mutex);
return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
}
static ssize_t lis3lv02d_rate_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- lis3lv02d_sysfs_poweron(&lis3_dev);
- return sprintf(buf, "%d\n", lis3lv02d_get_odr());
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
+
+ lis3lv02d_sysfs_poweron(lis3);
+ return sprintf(buf, "%d\n", lis3lv02d_get_odr(lis3));
}
static ssize_t lis3lv02d_rate_set(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
unsigned long rate;
if (strict_strtoul(buf, 0, &rate))
return -EINVAL;
- lis3lv02d_sysfs_poweron(&lis3_dev);
- if (lis3lv02d_set_odr(rate))
+ lis3lv02d_sysfs_poweron(lis3);
+ if (lis3lv02d_set_odr(lis3, rate))
return -EINVAL;
return count;
@@ -790,6 +832,7 @@ static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
if (IS_ERR(lis3->pdev))
return PTR_ERR(lis3->pdev);
+ platform_set_drvdata(lis3->pdev, lis3);
return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
}
@@ -803,7 +846,7 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
/* SYSFS may have left chip running. Turn off if necessary */
if (!pm_runtime_suspended(lis3->pm_dev))
- lis3lv02d_poweroff(&lis3_dev);
+ lis3lv02d_poweroff(lis3);
pm_runtime_disable(lis3->pm_dev);
pm_runtime_set_suspended(lis3->pm_dev);
@@ -813,24 +856,24 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
}
EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
-static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+static void lis3lv02d_8b_configure(struct lis3lv02d *lis3,
struct lis3lv02d_platform_data *p)
{
int err;
int ctrl2 = p->hipass_ctrl;
if (p->click_flags) {
- dev->write(dev, CLICK_CFG, p->click_flags);
- dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
- dev->write(dev, CLICK_LATENCY, p->click_latency);
- dev->write(dev, CLICK_WINDOW, p->click_window);
- dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
- dev->write(dev, CLICK_THSY_X,
+ lis3->write(lis3, CLICK_CFG, p->click_flags);
+ lis3->write(lis3, CLICK_TIMELIMIT, p->click_time_limit);
+ lis3->write(lis3, CLICK_LATENCY, p->click_latency);
+ lis3->write(lis3, CLICK_WINDOW, p->click_window);
+ lis3->write(lis3, CLICK_THSZ, p->click_thresh_z & 0xf);
+ lis3->write(lis3, CLICK_THSY_X,
(p->click_thresh_x & 0xf) |
(p->click_thresh_y << 4));
- if (dev->idev) {
- struct input_dev *input_dev = lis3_dev.idev->input;
+ if (lis3->idev) {
+ struct input_dev *input_dev = lis3->idev->input;
input_set_capability(input_dev, EV_KEY, BTN_X);
input_set_capability(input_dev, EV_KEY, BTN_Y);
input_set_capability(input_dev, EV_KEY, BTN_Z);
@@ -838,22 +881,22 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
}
if (p->wakeup_flags) {
- dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
- dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
+ lis3->write(lis3, FF_WU_CFG_1, p->wakeup_flags);
+ lis3->write(lis3, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
/* pdata value + 1 to keep this backward compatible*/
- dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
+ lis3->write(lis3, FF_WU_DURATION_1, p->duration1 + 1);
ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
}
if (p->wakeup_flags2) {
- dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
- dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
+ lis3->write(lis3, FF_WU_CFG_2, p->wakeup_flags2);
+ lis3->write(lis3, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
/* pdata value + 1 to keep this backward compatible*/
- dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
+ lis3->write(lis3, FF_WU_DURATION_2, p->duration2 + 1);
ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
}
/* Configure hipass filters */
- dev->write(dev, CTRL_REG2, ctrl2);
+ lis3->write(lis3, CTRL_REG2, ctrl2);
if (p->irq2) {
err = request_threaded_irq(p->irq2,
@@ -861,7 +904,7 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
lis302dl_interrupt_thread2_8b,
IRQF_TRIGGER_RISING | IRQF_ONESHOT |
(p->irq_flags2 & IRQF_TRIGGER_MASK),
- DRIVER_NAME, &lis3_dev);
+ DRIVER_NAME, lis3);
if (err < 0)
pr_err("No second IRQ. Limited functionality\n");
}
@@ -871,93 +914,97 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
* Initialise the accelerometer and the various subsystems.
* Should be rather independent of the bus system.
*/
-int lis3lv02d_init_device(struct lis3lv02d *dev)
+int lis3lv02d_init_device(struct lis3lv02d *lis3)
{
int err;
irq_handler_t thread_fn;
int irq_flags = 0;
- dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
+ lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I);
- switch (dev->whoami) {
+ switch (lis3->whoami) {
case WAI_12B:
pr_info("12 bits sensor found\n");
- dev->read_data = lis3lv02d_read_12;
- dev->mdps_max_val = 2048;
- dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
- dev->odrs = lis3_12_rates;
- dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
- dev->scale = LIS3_SENSITIVITY_12B;
- dev->regs = lis3_wai12_regs;
- dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
+ lis3->read_data = lis3lv02d_read_12;
+ lis3->mdps_max_val = 2048;
+ lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
+ lis3->odrs = lis3_12_rates;
+ lis3->odr_mask = CTRL1_DF0 | CTRL1_DF1;
+ lis3->scale = LIS3_SENSITIVITY_12B;
+ lis3->regs = lis3_wai12_regs;
+ lis3->regs_size = ARRAY_SIZE(lis3_wai12_regs);
break;
case WAI_8B:
pr_info("8 bits sensor found\n");
- dev->read_data = lis3lv02d_read_8;
- dev->mdps_max_val = 128;
- dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
- dev->odrs = lis3_8_rates;
- dev->odr_mask = CTRL1_DR;
- dev->scale = LIS3_SENSITIVITY_8B;
- dev->regs = lis3_wai8_regs;
- dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+ lis3->read_data = lis3lv02d_read_8;
+ lis3->mdps_max_val = 128;
+ lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+ lis3->odrs = lis3_8_rates;
+ lis3->odr_mask = CTRL1_DR;
+ lis3->scale = LIS3_SENSITIVITY_8B;
+ lis3->regs = lis3_wai8_regs;
+ lis3->regs_size = ARRAY_SIZE(lis3_wai8_regs);
break;
case WAI_3DC:
pr_info("8 bits 3DC sensor found\n");
- dev->read_data = lis3lv02d_read_8;
- dev->mdps_max_val = 128;
- dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
- dev->odrs = lis3_3dc_rates;
- dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
- dev->scale = LIS3_SENSITIVITY_8B;
+ lis3->read_data = lis3lv02d_read_8;
+ lis3->mdps_max_val = 128;
+ lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+ lis3->odrs = lis3_3dc_rates;
+ lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+ lis3->scale = LIS3_SENSITIVITY_8B;
break;
default:
- pr_err("unknown sensor type 0x%X\n", dev->whoami);
+ pr_err("unknown sensor type 0x%X\n", lis3->whoami);
return -EINVAL;
}
- dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+ lis3->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
sizeof(lis3_wai12_regs)), GFP_KERNEL);
- if (dev->reg_cache == NULL) {
+ if (lis3->reg_cache == NULL) {
printk(KERN_ERR DRIVER_NAME "out of memory\n");
return -ENOMEM;
}
- mutex_init(&dev->mutex);
- atomic_set(&dev->wake_thread, 0);
+ mutex_init(&lis3->mutex);
+ atomic_set(&lis3->wake_thread, 0);
- lis3lv02d_add_fs(dev);
- lis3lv02d_poweron(dev);
+ lis3lv02d_add_fs(lis3);
+ err = lis3lv02d_poweron(lis3);
+ if (err) {
+ lis3lv02d_remove_fs(lis3);
+ return err;
+ }
- if (dev->pm_dev) {
- pm_runtime_set_active(dev->pm_dev);
- pm_runtime_enable(dev->pm_dev);
+ if (lis3->pm_dev) {
+ pm_runtime_set_active(lis3->pm_dev);
+ pm_runtime_enable(lis3->pm_dev);
}
- if (lis3lv02d_joystick_enable())
+ if (lis3lv02d_joystick_enable(lis3))
pr_err("joystick initialization failed\n");
/* passing in platform specific data is purely optional and only
* used by the SPI transport layer at the moment */
- if (dev->pdata) {
- struct lis3lv02d_platform_data *p = dev->pdata;
+ if (lis3->pdata) {
+ struct lis3lv02d_platform_data *p = lis3->pdata;
- if (dev->whoami == WAI_8B)
- lis3lv02d_8b_configure(dev, p);
+ if (lis3->whoami == WAI_8B)
+ lis3lv02d_8b_configure(lis3, p);
irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
- dev->irq_cfg = p->irq_cfg;
+ lis3->irq_cfg = p->irq_cfg;
if (p->irq_cfg)
- dev->write(dev, CTRL_REG3, p->irq_cfg);
+ lis3->write(lis3, CTRL_REG3, p->irq_cfg);
if (p->default_rate)
- lis3lv02d_set_odr(p->default_rate);
+ lis3lv02d_set_odr(lis3, p->default_rate);
}
/* bail if we did not get an IRQ from the bus layer */
- if (!dev->irq) {
+ if (!lis3->irq) {
pr_debug("No IRQ. Disabling /dev/freefall\n");
goto out;
}
@@ -973,23 +1020,27 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
* io-apic is not configurable (and generates a warning) but I keep it
* in case of support for other hardware.
*/
- if (dev->pdata && dev->whoami == WAI_8B)
+ if (lis3->pdata && lis3->whoami == WAI_8B)
thread_fn = lis302dl_interrupt_thread1_8b;
else
thread_fn = NULL;
- err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+ err = request_threaded_irq(lis3->irq, lis302dl_interrupt,
thread_fn,
IRQF_TRIGGER_RISING | IRQF_ONESHOT |
irq_flags,
- DRIVER_NAME, &lis3_dev);
+ DRIVER_NAME, lis3);
if (err < 0) {
pr_err("Cannot get IRQ\n");
goto out;
}
- if (misc_register(&lis3lv02d_misc_device))
+ lis3->miscdev.minor = MISC_DYNAMIC_MINOR;
+ lis3->miscdev.name = "freefall";
+ lis3->miscdev.fops = &lis3lv02d_misc_fops;
+
+ if (misc_register(&lis3->miscdev))
pr_err("misc_register failed\n");
out:
return 0;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h
index a193958..2b1482a 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.h
+++ b/drivers/misc/lis3lv02d/lis3lv02d.h
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
#include <linux/regulator/consumer.h>
+#include <linux/miscdevice.h>
/*
* This driver tries to support the "digital" accelerometer chips from
@@ -273,6 +274,8 @@ struct lis3lv02d {
struct fasync_struct *async_queue; /* queue for the misc device */
wait_queue_head_t misc_wait; /* Wait queue for the misc device */
unsigned long misc_opened; /* bit0: whether the device is open */
+ struct miscdevice miscdev;
+
int data_ready_count[2];
atomic_t wake_thread;
unsigned char irq_cfg;
@@ -282,10 +285,10 @@ struct lis3lv02d {
};
int lis3lv02d_init_device(struct lis3lv02d *lis3);
-int lis3lv02d_joystick_enable(void);
-void lis3lv02d_joystick_disable(void);
+int lis3lv02d_joystick_enable(struct lis3lv02d *lis3);
+void lis3lv02d_joystick_disable(struct lis3lv02d *lis3);
void lis3lv02d_poweroff(struct lis3lv02d *lis3);
-void lis3lv02d_poweron(struct lis3lv02d *lis3);
+int lis3lv02d_poweron(struct lis3lv02d *lis3);
int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
extern struct lis3lv02d lis3_dev;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index b20dfb4..c02fea0 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -79,8 +79,7 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
u8 reg;
int ret;
- if (lis3->reg_ctrl)
- lis3_reg_ctrl(lis3, LIS3_REG_ON);
+ lis3_reg_ctrl(lis3, LIS3_REG_ON);
lis3->read(lis3, WHO_AM_I, &reg);
if (reg != lis3->whoami)
@@ -106,10 +105,6 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
if (pdata) {
- /* Regulator control is optional */
- if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
- lis3_dev.reg_ctrl = lis3_reg_ctrl;
-
if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
(i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK)))
@@ -131,15 +126,13 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
goto fail;
}
- if (lis3_dev.reg_ctrl) {
- lis3_dev.regulators[0].supply = reg_vdd;
- lis3_dev.regulators[1].supply = reg_vdd_io;
- ret = regulator_bulk_get(&client->dev,
- ARRAY_SIZE(lis3_dev.regulators),
- lis3_dev.regulators);
- if (ret < 0)
- goto fail;
- }
+ lis3_dev.regulators[0].supply = reg_vdd;
+ lis3_dev.regulators[1].supply = reg_vdd_io;
+ ret = regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(lis3_dev.regulators),
+ lis3_dev.regulators);
+ if (ret < 0)
+ goto fail;
lis3_dev.pdata = pdata;
lis3_dev.bus_priv = client;
@@ -153,16 +146,19 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, &lis3_dev);
/* Provide power over the init call */
- if (lis3_dev.reg_ctrl)
- lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+ lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
ret = lis3lv02d_init_device(&lis3_dev);
- if (lis3_dev.reg_ctrl)
- lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+ lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
- if (ret == 0)
- return 0;
+ if (ret)
+ goto fail2;
+ return 0;
+
+fail2:
+ regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators),
+ lis3_dev.regulators);
fail:
if (pdata && pdata->release_resources)
pdata->release_resources();
@@ -177,12 +173,11 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
if (pdata && pdata->release_resources)
pdata->release_resources();
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(lis3);
lis3lv02d_remove_fs(&lis3_dev);
- if (lis3_dev.reg_ctrl)
- regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
- lis3_dev.regulators);
+ regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+ lis3_dev.regulators);
return 0;
}
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
index c1f8a8f..b2c1be1 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -83,7 +83,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
static int __devexit lis302dl_spi_remove(struct spi_device *spi)
{
struct lis3lv02d *lis3 = spi_get_drvdata(spi);
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(lis3);
lis3lv02d_poweroff(lis3);
return lis3lv02d_remove_fs(&lis3_dev);
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 9e9bdda..913de07 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -31,6 +31,7 @@
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include <asm/io_apic.h>
#include "gru.h"
#include "grulib.h"
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 54c91ff..ba168a7 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -338,6 +338,12 @@ void st_int_recv(void *disc_data,
/* Unknow packet? */
default:
type = *ptr;
+ if (st_gdata->list[type] == NULL) {
+ pr_err("chip/interface misbehavior dropping"
+ " frame starting with 0x%02x", type);
+ goto done;
+
+ }
st_gdata->rx_skb = alloc_skb(
st_gdata->list[type]->max_frame_size,
GFP_ATOMIC);
@@ -354,6 +360,7 @@ void st_int_recv(void *disc_data,
ptr++;
count--;
}
+done:
spin_unlock_irqrestore(&st_gdata->lock, flags);
pr_debug("done %s", __func__);
return;
@@ -717,9 +724,10 @@ static void st_tty_close(struct tty_struct *tty)
*/
spin_lock_irqsave(&st_gdata->lock, flags);
for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
- if (st_gdata->list[i] != NULL)
+ if (st_gdata->is_registered[i] == true)
pr_err("%d not un-registered", i);
st_gdata->list[i] = NULL;
+ st_gdata->is_registered[i] = false;
}
st_gdata->protos_registered = 0;
spin_unlock_irqrestore(&st_gdata->lock, flags);
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 38fd2f0..43ef8d1 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -35,6 +35,7 @@
#include <linux/skbuff.h>
#include <linux/ti_wilink_st.h>
+#include <linux/module.h>
#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */
@@ -68,6 +69,7 @@ void validate_firmware_response(struct kim_data_s *kim_gdata)
if (unlikely(skb->data[5] != 0)) {
pr_err("no proper response during fw download");
pr_err("data6 %x", skb->data[5]);
+ kfree_skb(skb);
return; /* keep waiting for the proper response */
}
/* becos of all the script being downloaded */
@@ -210,6 +212,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
pr_err(" waiting for ver info- timed out ");
return -ETIMEDOUT;
}
+ INIT_COMPLETION(kim_gdata->kim_rcvd);
version =
MAKEWORD(kim_gdata->resp_buffer[13],
@@ -298,6 +301,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
switch (((struct bts_action *)ptr)->type) {
case ACTION_SEND_COMMAND: /* action send */
+ pr_debug("S");
action_ptr = &(((struct bts_action *)ptr)->data[0]);
if (unlikely
(((struct hci_command *)action_ptr)->opcode ==
@@ -335,6 +339,10 @@ static long download_firmware(struct kim_data_s *kim_gdata)
release_firmware(kim_gdata->fw_entry);
return -ETIMEDOUT;
}
+ /* reinit completion before sending for the
+ * relevant wait
+ */
+ INIT_COMPLETION(kim_gdata->kim_rcvd);
/*
* Free space found in uart buffer, call st_int_write
@@ -361,6 +369,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
}
break;
case ACTION_WAIT_EVENT: /* wait */
+ pr_debug("W");
if (!wait_for_completion_timeout
(&kim_gdata->kim_rcvd,
msecs_to_jiffies(CMD_RESP_TIME))) {
@@ -434,11 +443,17 @@ long st_kim_start(void *kim_data)
{
long err = 0;
long retry = POR_RETRY_COUNT;
+ struct ti_st_plat_data *pdata;
struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
pr_info(" %s", __func__);
+ pdata = kim_gdata->kim_pdev->dev.platform_data;
do {
+ /* platform specific enabling code here */
+ if (pdata->chip_enable)
+ pdata->chip_enable(kim_gdata);
+
/* Configure BT nShutdown to HIGH state */
gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
mdelay(5); /* FIXME: a proper toggle */
@@ -460,6 +475,12 @@ long st_kim_start(void *kim_data)
pr_info("ldisc_install = 0");
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
NULL, "install");
+ /* the following wait is never going to be completed,
+ * since the ldisc was never installed, hence serving
+ * as a mdelay of LDISC_TIME msecs */
+ err = wait_for_completion_timeout
+ (&kim_gdata->ldisc_installed,
+ msecs_to_jiffies(LDISC_TIME));
err = -ETIMEDOUT;
continue;
} else {
@@ -472,6 +493,13 @@ long st_kim_start(void *kim_data)
pr_info("ldisc_install = 0");
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
NULL, "install");
+ /* this wait might be completed, though in the
+ * tty_close() since the ldisc is already
+ * installed */
+ err = wait_for_completion_timeout
+ (&kim_gdata->ldisc_installed,
+ msecs_to_jiffies(LDISC_TIME));
+ err = -EINVAL;
continue;
} else { /* on success don't retry */
break;
@@ -489,6 +517,8 @@ long st_kim_stop(void *kim_data)
{
long err = 0;
struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
+ struct ti_st_plat_data *pdata =
+ kim_gdata->kim_pdev->dev.platform_data;
INIT_COMPLETION(kim_gdata->ldisc_installed);
@@ -515,6 +545,10 @@ long st_kim_stop(void *kim_data)
gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
mdelay(1);
gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+
+ /* platform specific disable */
+ if (pdata->chip_disable)
+ pdata->chip_disable(kim_gdata);
return err;
}
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
index 3f24951..1ff460a 100644
--- a/drivers/misc/ti-st/st_ll.c
+++ b/drivers/misc/ti-st/st_ll.c
@@ -22,6 +22,7 @@
#define pr_fmt(fmt) "(stll) :" fmt
#include <linux/skbuff.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/ti_wilink_st.h>
/**********************************************************************/
@@ -37,6 +38,9 @@ static void send_ll_cmd(struct st_data_s *st_data,
static void ll_device_want_to_sleep(struct st_data_s *st_data)
{
+ struct kim_data_s *kim_data;
+ struct ti_st_plat_data *pdata;
+
pr_debug("%s", __func__);
/* sanity check */
if (st_data->ll_state != ST_LL_AWAKE)
@@ -46,10 +50,19 @@ static void ll_device_want_to_sleep(struct st_data_s *st_data)
send_ll_cmd(st_data, LL_SLEEP_ACK);
/* update state */
st_data->ll_state = ST_LL_ASLEEP;
+
+ /* communicate to platform about chip asleep */
+ kim_data = st_data->kim_data;
+ pdata = kim_data->kim_pdev->dev.platform_data;
+ if (pdata->chip_asleep)
+ pdata->chip_asleep(NULL);
}
static void ll_device_want_to_wakeup(struct st_data_s *st_data)
{
+ struct kim_data_s *kim_data;
+ struct ti_st_plat_data *pdata;
+
/* diff actions in diff states */
switch (st_data->ll_state) {
case ST_LL_ASLEEP:
@@ -70,6 +83,12 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data)
}
/* update state */
st_data->ll_state = ST_LL_AWAKE;
+
+ /* communicate to platform about chip wakeup */
+ kim_data = st_data->kim_data;
+ pdata = kim_data->kim_pdev->dev.platform_data;
+ if (pdata->chip_asleep)
+ pdata->chip_awake(NULL);
}
/**********************************************************************/
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 23175ed..8d70895 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -145,8 +145,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
if (((major << 8) | minor) < 0x3131) {
/* CFI version 1.0 => don't trust bootloc */
- DEBUG(MTD_DEBUG_LEVEL1,
- "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
+ pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
map->name, cfi->mfr, cfi->id);
/* AFAICS all 29LV400 with a bottom boot block have a device ID
@@ -166,8 +165,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
* the 8-bit device ID.
*/
(cfi->mfr == CFI_MFR_MACRONIX)) {
- DEBUG(MTD_DEBUG_LEVEL1,
- "%s: Macronix MX29LV400C with bottom boot block"
+ pr_debug("%s: Macronix MX29LV400C with bottom boot block"
" detected\n", map->name);
extp->TopBottom = 2; /* bottom boot */
} else
@@ -178,8 +176,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
extp->TopBottom = 2; /* bottom boot */
}
- DEBUG(MTD_DEBUG_LEVEL1,
- "%s: AMD CFI PRI V%c.%c has no boot block field;"
+ pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;"
" deduced %s from Device ID\n", map->name, major, minor,
extp->TopBottom == 2 ? "bottom" : "top");
}
@@ -191,7 +188,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd)
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
if (cfi->cfiq->BufWriteTimeoutTyp) {
- DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
+ pr_debug("Using buffer write method\n" );
mtd->write = cfi_amdstd_write_buffers;
}
}
@@ -443,8 +440,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
mtd->writesize = 1;
mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
- DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
- __func__, mtd->writebufsize);
+ pr_debug("MTD %s(): write buffer size %d\n", __func__,
+ mtd->writebufsize);
mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
@@ -1163,7 +1160,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
return ret;
}
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
+ pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
__func__, adr, datum.x[0] );
/*
@@ -1174,7 +1171,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
*/
oldd = map_read(map, adr);
if (map_word_equal(map, oldd, datum)) {
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
+ pr_debug("MTD %s(): NOP\n",
__func__);
goto op_done;
}
@@ -1400,7 +1397,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
datum = map_word_load(map, buf);
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
+ pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
__func__, adr, datum.x[0] );
XIP_INVAL_CACHED_RANGE(map, adr, len);
@@ -1587,7 +1584,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
return ret;
}
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+ pr_debug("MTD %s(): ERASE 0x%.8lx\n",
__func__, chip->start );
XIP_INVAL_CACHED_RANGE(map, adr, map->size);
@@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
return ret;
}
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+ pr_debug("MTD %s(): ERASE 0x%.8lx\n",
__func__, adr );
XIP_INVAL_CACHED_RANGE(map, adr, len);
@@ -1801,8 +1798,7 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip,
goto out_unlock;
chip->state = FL_LOCKING;
- DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
- __func__, adr, len);
+ pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
@@ -1837,8 +1833,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
goto out_unlock;
chip->state = FL_UNLOCKING;
- DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
- __func__, adr, len);
+ pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h
index 5e3cc80..89c6595 100644
--- a/drivers/mtd/chips/fwh_lock.h
+++ b/drivers/mtd/chips/fwh_lock.h
@@ -34,8 +34,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
/* Refuse the operation if the we cannot look behind the chip */
if (chip->start < 0x400000) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
+ pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
__func__, chip->start );
return -EIO;
}
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index ea832ea..c443f52 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -1914,11 +1914,10 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi)
* (oh and incidentaly the jedec spec - 3.5.3.3) the reset
* sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
* 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
- * as they will ignore the writes and dont care what address
+ * as they will ignore the writes and don't care what address
* the F0 is written to */
if (cfi->addr_unlock1) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "reset unlock called %x %x \n",
+ pr_debug( "reset unlock called %x %x \n",
cfi->addr_unlock1,cfi->addr_unlock2);
cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
@@ -1941,7 +1940,7 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in
uint8_t uaddr;
if (!(jedec_table[index].devtypes & cfi->device_type)) {
- DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n",
+ pr_debug("Rejecting potential %s with incompatible %d-bit device type\n",
jedec_table[index].name, 4 * (1<<cfi->device_type));
return 0;
}
@@ -2021,7 +2020,7 @@ static inline int jedec_match( uint32_t base,
* there aren't.
*/
if (finfo->dev_id > 0xff) {
- DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",
+ pr_debug("%s(): ID is not 8bit\n",
__func__);
goto match_done;
}
@@ -2045,12 +2044,10 @@ static inline int jedec_match( uint32_t base,
}
/* the part size must fit in the memory window */
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
+ pr_debug("MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
__func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) );
if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
+ pr_debug("MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
__func__, finfo->mfr_id, finfo->dev_id,
1 << finfo->dev_size );
goto match_done;
@@ -2061,13 +2058,12 @@ static inline int jedec_match( uint32_t base,
uaddr = finfo->uaddr;
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
+ pr_debug("MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
__func__, cfi->addr_unlock1, cfi->addr_unlock2 );
if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
&& ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 ||
unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): 0x%.4x 0x%.4x did not match\n",
+ pr_debug("MTD %s(): 0x%.4x 0x%.4x did not match\n",
__func__,
unlock_addrs[uaddr].addr1,
unlock_addrs[uaddr].addr2);
@@ -2083,15 +2079,13 @@ static inline int jedec_match( uint32_t base,
* FIXME - write a driver that takes all of the chip info as
* module parameters, doesn't probe but forces a load.
*/
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): check ID's disappear when not in ID mode\n",
+ pr_debug("MTD %s(): check ID's disappear when not in ID mode\n",
__func__ );
jedec_reset( base, map, cfi );
mfr = jedec_read_mfr( map, base, cfi );
id = jedec_read_id( map, base, cfi );
if ( mfr == cfi->mfr && id == cfi->id ) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
+ pr_debug("MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
"You might need to manually specify JEDEC parameters.\n",
__func__, cfi->mfr, cfi->id );
goto match_done;
@@ -2104,7 +2098,7 @@ static inline int jedec_match( uint32_t base,
* Put the device back in ID mode - only need to do this if we
* were truly frobbing a real device.
*/
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
+ pr_debug("MTD %s(): return to ID mode\n", __func__ );
if (cfi->addr_unlock1) {
cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
@@ -2167,13 +2161,11 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
cfi->mfr = jedec_read_mfr(map, base, cfi);
cfi->id = jedec_read_id(map, base, cfi);
- DEBUG(MTD_DEBUG_LEVEL3,
- "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
+ pr_debug("Search for id:(%02x %02x) interleave(%d) type(%d)\n",
cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
+ pr_debug("MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
__func__, cfi->mfr, cfi->id,
cfi->addr_unlock1, cfi->addr_unlock2 );
if (!cfi_jedec_setup(map, cfi, i))
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 35081ce..283d887 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -249,6 +249,16 @@ config MTD_DOC2001PLUS
under "NAND Flash Device Drivers" (currently that driver does not
support all Millennium Plus devices).
+config MTD_DOCG3
+ tristate "M-Systems Disk-On-Chip G3"
+ ---help---
+ This provides an MTD device driver for the M-Systems DiskOnChip
+ G3 devices.
+
+ The driver provides access to G3 DiskOnChip, distributed by
+ M-Systems and now Sandisk. The support is very experimental,
+ and doesn't give access to any write operations.
+
config MTD_DOCPROBE
tristate
select MTD_DOCECC
@@ -268,8 +278,7 @@ config MTD_DOCPROBE_ADVANCED
config MTD_DOCPROBE_ADDRESS
hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
depends on MTD_DOCPROBE
- default "0x0000" if MTD_DOCPROBE_ADVANCED
- default "0" if !MTD_DOCPROBE_ADVANCED
+ default "0x0"
---help---
By default, the probe for DiskOnChip devices will look for a
DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index f3226b1..56c7cd4 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_MTD_DOC2000) += doc2000.o
obj-$(CONFIG_MTD_DOC2001) += doc2001.o
obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o
+obj-$(CONFIG_MTD_DOCG3) += docg3.o
obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o
obj-$(CONFIG_MTD_DOCECC) += docecc.o
obj-$(CONFIG_MTD_SLRAM) += slram.o
@@ -17,3 +18,5 @@ obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
obj-$(CONFIG_MTD_SST25L) += sst25l.o
+
+CFLAGS_docg3.o += -I$(src) \ No newline at end of file
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index f7fbf60..e9fad91 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -82,8 +82,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
void __iomem *docptr = doc->virtadr;
unsigned long timeo = jiffies + (HZ * 10);
- DEBUG(MTD_DEBUG_LEVEL3,
- "_DoC_WaitReady called for out-of-line wait\n");
+ pr_debug("_DoC_WaitReady called for out-of-line wait\n");
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
@@ -92,7 +91,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
DoC_Delay(doc, 2);
if (time_after(jiffies, timeo)) {
- DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+ pr_debug("_DoC_WaitReady timed out.\n");
return -EIO;
}
udelay(1);
@@ -323,8 +322,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
/* Reset the chip */
if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
- DEBUG(MTD_DEBUG_LEVEL2,
- "DoC_Command (reset) for %d,%d returned true\n",
+ pr_debug("DoC_Command (reset) for %d,%d returned true\n",
floor, chip);
return 0;
}
@@ -332,8 +330,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
/* Read the NAND chip ID: 1. Send ReadID command */
if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
- DEBUG(MTD_DEBUG_LEVEL2,
- "DoC_Command (ReadID) for %d,%d returned true\n",
+ pr_debug("DoC_Command (ReadID) for %d,%d returned true\n",
floor, chip);
return 0;
}
@@ -699,7 +696,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
#ifdef ECC_DEBUG
printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif
- /* Read the ECC syndrom through the DiskOnChip ECC
+ /* Read the ECC syndrome through the DiskOnChip ECC
logic. These syndrome will be all ZERO when there
is no error */
for (i = 0; i < 6; i++) {
@@ -930,7 +927,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
uint8_t *buf = ops->oobbuf;
size_t len = ops->len;
- BUG_ON(ops->mode != MTD_OOB_PLACE);
+ BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
ofs += ops->ooboffs;
@@ -1094,7 +1091,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
struct DiskOnChip *this = mtd->priv;
int ret;
- BUG_ON(ops->mode != MTD_OOB_PLACE);
+ BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
mutex_lock(&this->lock);
ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index 241192f..a3f7a27 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -55,15 +55,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
{
unsigned short c = 0xffff;
- DEBUG(MTD_DEBUG_LEVEL3,
- "_DoC_WaitReady called for out-of-line wait\n");
+ pr_debug("_DoC_WaitReady called for out-of-line wait\n");
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
;
if (c == 0)
- DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+ pr_debug("_DoC_WaitReady timed out.\n");
return (c == 0);
}
@@ -464,7 +463,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
#ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif
- /* Read the ECC syndrom through the DiskOnChip ECC logic.
+ /* Read the ECC syndrome through the DiskOnChip ECC logic.
These syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; i++) {
syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
@@ -632,7 +631,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
uint8_t *buf = ops->oobbuf;
size_t len = ops->len;
- BUG_ON(ops->mode != MTD_OOB_PLACE);
+ BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
ofs += ops->ooboffs;
@@ -690,7 +689,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
uint8_t *buf = ops->oobbuf;
size_t len = ops->len;
- BUG_ON(ops->mode != MTD_OOB_PLACE);
+ BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
ofs += ops->ooboffs;
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 09ae0ad..99351bc 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -61,15 +61,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
{
unsigned int c = 0xffff;
- DEBUG(MTD_DEBUG_LEVEL3,
- "_DoC_WaitReady called for out-of-line wait\n");
+ pr_debug("_DoC_WaitReady called for out-of-line wait\n");
/* Out-of-line routine to wait for chip response */
while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
;
if (c == 0)
- DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+ pr_debug("_DoC_WaitReady timed out.\n");
return (c == 0);
}
@@ -655,7 +654,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
#ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif
- /* Read the ECC syndrom through the DiskOnChip ECC logic.
+ /* Read the ECC syndrome through the DiskOnChip ECC logic.
These syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; i++)
syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
@@ -835,7 +834,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
uint8_t *buf = ops->oobbuf;
size_t len = ops->len;
- BUG_ON(ops->mode != MTD_OOB_PLACE);
+ BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
ofs += ops->ooboffs;
@@ -920,7 +919,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
uint8_t *buf = ops->oobbuf;
size_t len = ops->len;
- BUG_ON(ops->mode != MTD_OOB_PLACE);
+ BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
ofs += ops->ooboffs;
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
index 37ef29a..4a1c39b 100644
--- a/drivers/mtd/devices/docecc.c
+++ b/drivers/mtd/devices/docecc.c
@@ -2,7 +2,7 @@
* ECC algorithm for M-systems disk on chip. We use the excellent Reed
* Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
* GNU GPL License. The rest is simply to convert the disk on chip
- * syndrom into a standard syndom.
+ * syndrome into a standard syndome.
*
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
* Copyright (C) 2000 Netgem S.A.
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index d374603..45116bb 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -50,11 +50,6 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/doc2000.h>
-/* Where to look for the devices? */
-#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
-#define CONFIG_MTD_DOCPROBE_ADDRESS 0
-#endif
-
static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
module_param(doc_config_location, ulong, 0);
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 09d5b5a..5f12668 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -34,9 +34,6 @@
/* debugging */
//#define LART_DEBUG
-/* partition support */
-#define HAVE_PARTITIONS
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -44,9 +41,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
-#ifdef HAVE_PARTITIONS
#include <linux/mtd/partitions.h>
-#endif
#ifndef CONFIG_SA1100_LART
#error This is for LART architecture only
@@ -598,7 +593,6 @@ static struct mtd_erase_region_info erase_regions[] = {
}
};
-#ifdef HAVE_PARTITIONS
static struct mtd_partition lart_partitions[] = {
/* blob */
{
@@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = {
.size = INITRD_LEN, /* MTDPART_SIZ_FULL */
}
};
-#endif
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
static int __init lart_flash_init (void)
{
@@ -669,7 +663,6 @@ static int __init lart_flash_init (void)
result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
result,mtd.eraseregions[result].numblocks);
-#ifdef HAVE_PARTITIONS
printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
@@ -682,25 +675,16 @@ static int __init lart_flash_init (void)
result,lart_partitions[result].offset,
result,lart_partitions[result].size,lart_partitions[result].size / 1024);
#endif
-#endif
-#ifndef HAVE_PARTITIONS
- result = mtd_device_register(&mtd, NULL, 0);
-#else
result = mtd_device_register(&mtd, lart_partitions,
ARRAY_SIZE(lart_partitions));
-#endif
return (result);
}
static void __exit lart_flash_exit (void)
{
-#ifndef HAVE_PARTITIONS
- mtd_device_unregister(&mtd);
-#else
mtd_device_unregister(&mtd);
-#endif
}
module_init (lart_flash_init);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 9fad104d..3d6beb7 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -30,6 +30,7 @@
#include <linux/mtd/cfi.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/of_platform.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
@@ -70,7 +71,7 @@
/* Define max times to check status register before we give up. */
#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
-#define MAX_CMD_SIZE 5
+#define MAX_CMD_SIZE 6
#ifdef CONFIG_M25PXX_USE_FAST_READ
#define OPCODE_READ OPCODE_FAST_READ
@@ -88,7 +89,6 @@ struct m25p {
struct spi_device *spi;
struct mutex lock;
struct mtd_info mtd;
- unsigned partitioned:1;
u16 page_size;
u16 addr_width;
u8 erase_opcode;
@@ -209,9 +209,8 @@ static int wait_till_ready(struct m25p *flash)
*/
static int erase_chip(struct m25p *flash)
{
- DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
- dev_name(&flash->spi->dev), __func__,
- (long long)(flash->mtd.size >> 10));
+ pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__,
+ (long long)(flash->mtd.size >> 10));
/* Wait until finished previous write command. */
if (wait_till_ready(flash))
@@ -250,9 +249,8 @@ static int m25p_cmdsz(struct m25p *flash)
*/
static int erase_sector(struct m25p *flash, u32 offset)
{
- DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
- dev_name(&flash->spi->dev), __func__,
- flash->mtd.erasesize / 1024, offset);
+ pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev),
+ __func__, flash->mtd.erasesize / 1024, offset);
/* Wait until finished previous write command. */
if (wait_till_ready(flash))
@@ -286,9 +284,9 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
u32 addr,len;
uint32_t rem;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
- dev_name(&flash->spi->dev), __func__, "at",
- (long long)instr->addr, (long long)instr->len);
+ pr_debug("%s: %s at 0x%llx, len %lld\n", dev_name(&flash->spi->dev),
+ __func__, (long long)instr->addr,
+ (long long)instr->len);
/* sanity checks */
if (instr->addr + instr->len > flash->mtd.size)
@@ -348,9 +346,8 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
struct spi_transfer t[2];
struct spi_message m;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
- dev_name(&flash->spi->dev), __func__, "from",
- (u32)from, len);
+ pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+ __func__, (u32)from, len);
/* sanity checks */
if (!len)
@@ -417,9 +414,8 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
struct spi_transfer t[2];
struct spi_message m;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
- dev_name(&flash->spi->dev), __func__, "to",
- (u32)to, len);
+ pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+ __func__, (u32)to, len);
*retlen = 0;
@@ -510,9 +506,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t actual;
int cmd_sz, ret;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
- dev_name(&flash->spi->dev), __func__, "to",
- (u32)to, len);
+ pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+ __func__, (u32)to, len);
*retlen = 0;
@@ -661,6 +656,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
+ { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
{ "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
{ "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
@@ -671,6 +667,7 @@ static const struct spi_device_id m25p_ids[] = {
/* EON -- en25xxx */
{ "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
/* Intel/Numonyx -- xxxs33b */
@@ -788,8 +785,8 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
*/
tmp = spi_write_then_read(spi, &code, 1, id, 5);
if (tmp < 0) {
- DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
- dev_name(&spi->dev), tmp);
+ pr_debug("%s: error %d reading JEDEC ID\n",
+ dev_name(&spi->dev), tmp);
return ERR_PTR(tmp);
}
jedec = id[0];
@@ -825,8 +822,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
struct m25p *flash;
struct flash_info *info;
unsigned i;
- struct mtd_partition *parts = NULL;
- int nr_parts = 0;
+ struct mtd_part_parser_data ppdata;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (!of_device_is_available(spi->dev.of_node))
+ return -ENODEV;
+#endif
/* Platform data helps sort out which chip type we have, as
* well as how this board partitions it. If we don't have
@@ -873,14 +874,13 @@ static int __devinit m25p_probe(struct spi_device *spi)
}
}
- flash = kzalloc(sizeof *flash, GFP_KERNEL);
+ flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
if (!flash)
return -ENOMEM;
- flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
- if (!flash->command) {
- kfree(flash);
+
+ flash->command = devm_kzalloc(&spi->dev, MAX_CMD_SIZE, GFP_KERNEL);
+ if (!flash->command)
return -ENOMEM;
- }
flash->spi = spi;
mutex_init(&flash->lock);
@@ -928,6 +928,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
if (info->flags & M25P_NO_ERASE)
flash->mtd.flags |= MTD_NO_ERASE;
+ ppdata.of_node = spi->dev.of_node;
flash->mtd.dev.parent = &spi->dev;
flash->page_size = info->page_size;
flash->mtd.writebufsize = flash->page_size;
@@ -946,8 +947,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
(long long)flash->mtd.size >> 10);
- DEBUG(MTD_DEBUG_LEVEL2,
- "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+ pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
flash->mtd.name,
(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
@@ -956,8 +956,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
if (flash->mtd.numeraseregions)
for (i = 0; i < flash->mtd.numeraseregions; i++)
- DEBUG(MTD_DEBUG_LEVEL2,
- "mtd.eraseregions[%d] = { .offset = 0x%llx, "
+ pr_debug("mtd.eraseregions[%d] = { .offset = 0x%llx, "
".erasesize = 0x%.8x (%uKiB), "
".numblocks = %d }\n",
i, (long long)flash->mtd.eraseregions[i].offset,
@@ -969,55 +968,19 @@ static int __devinit m25p_probe(struct spi_device *spi)
/* partitions should match sector boundaries; and it may be good to
* use readonly partitions for writeprotected sectors (BP2..BP0).
*/
- if (mtd_has_cmdlinepart()) {
- static const char *part_probes[]
- = { "cmdlinepart", NULL, };
-
- nr_parts = parse_mtd_partitions(&flash->mtd,
- part_probes, &parts, 0);
- }
-
- if (nr_parts <= 0 && data && data->parts) {
- parts = data->parts;
- nr_parts = data->nr_parts;
- }
-
-#ifdef CONFIG_MTD_OF_PARTS
- if (nr_parts <= 0 && spi->dev.of_node) {
- nr_parts = of_mtd_parse_partitions(&spi->dev,
- spi->dev.of_node, &parts);
- }
-#endif
-
- if (nr_parts > 0) {
- for (i = 0; i < nr_parts; i++) {
- DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
- "{.name = %s, .offset = 0x%llx, "
- ".size = 0x%llx (%lldKiB) }\n",
- i, parts[i].name,
- (long long)parts[i].offset,
- (long long)parts[i].size,
- (long long)(parts[i].size >> 10));
- }
- flash->partitioned = 1;
- }
-
- return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
- -ENODEV : 0;
+ return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+ data ? data->parts : NULL,
+ data ? data->nr_parts : 0);
}
static int __devexit m25p_remove(struct spi_device *spi)
{
struct m25p *flash = dev_get_drvdata(&spi->dev);
- int status;
/* Clean up MTD stuff. */
- status = mtd_device_unregister(&flash->mtd);
- if (status == 0) {
- kfree(flash->command);
- kfree(flash);
- }
+ mtd_device_unregister(&flash->mtd);
+
return 0;
}
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 13749d4..d75c7af 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -17,6 +17,8 @@
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
@@ -24,7 +26,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
-
/*
* DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in
* each chip, which may be used for double buffered I/O; but this driver
@@ -98,6 +99,16 @@ struct dataflash {
struct mtd_info mtd;
};
+#ifdef CONFIG_OF
+static const struct of_device_id dataflash_dt_ids[] = {
+ { .compatible = "atmel,at45", },
+ { .compatible = "atmel,dataflash", },
+ { /* sentinel */ }
+};
+#else
+#define dataflash_dt_ids NULL
+#endif
+
/* ......................................................................... */
/*
@@ -122,7 +133,7 @@ static int dataflash_waitready(struct spi_device *spi)
for (;;) {
status = dataflash_status(spi);
if (status < 0) {
- DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
+ pr_debug("%s: status %d?\n",
dev_name(&spi->dev), status);
status = 0;
}
@@ -149,7 +160,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
uint8_t *command;
uint32_t rem;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
+ pr_debug("%s: erase addr=0x%llx len 0x%llx\n",
dev_name(&spi->dev), (long long)instr->addr,
(long long)instr->len);
@@ -187,7 +198,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
command[2] = (uint8_t)(pageaddr >> 8);
command[3] = 0;
- DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
+ pr_debug("ERASE %s: (%x) %x %x %x [%i]\n",
do_block ? "block" : "page",
command[0], command[1], command[2], command[3],
pageaddr);
@@ -238,8 +249,8 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
uint8_t *command;
int status;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
- dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len));
+ pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev),
+ (unsigned)from, (unsigned)(from + len));
*retlen = 0;
@@ -255,7 +266,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
command = priv->command;
- DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
+ pr_debug("READ: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);
spi_message_init(&msg);
@@ -287,7 +298,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
*retlen = msg.actual_length - 8;
status = 0;
} else
- DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
+ pr_debug("%s: read %x..%x --> %d\n",
dev_name(&priv->spi->dev),
(unsigned)from, (unsigned)(from + len),
status);
@@ -314,7 +325,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
int status = -EINVAL;
uint8_t *command;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
+ pr_debug("%s: write 0x%x..0x%x\n",
dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
*retlen = 0;
@@ -340,7 +351,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
mutex_lock(&priv->lock);
while (remaining > 0) {
- DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
+ pr_debug("write @ %i:%i len=%i\n",
pageaddr, offset, writelen);
/* REVISIT:
@@ -368,12 +379,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
command[2] = (addr & 0x0000FF00) >> 8;
command[3] = 0;
- DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
+ pr_debug("TRANSFER: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);
status = spi_sync(spi, &msg);
if (status < 0)
- DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
+ pr_debug("%s: xfer %u -> %d\n",
dev_name(&spi->dev), addr, status);
(void) dataflash_waitready(priv->spi);
@@ -386,7 +397,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
command[2] = (addr & 0x0000FF00) >> 8;
command[3] = (addr & 0x000000FF);
- DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
+ pr_debug("PROGRAM: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);
x[1].tx_buf = writebuf;
@@ -395,7 +406,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
status = spi_sync(spi, &msg);
spi_transfer_del(x + 1);
if (status < 0)
- DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
+ pr_debug("%s: pgm %u/%u -> %d\n",
dev_name(&spi->dev), addr, writelen, status);
(void) dataflash_waitready(priv->spi);
@@ -410,12 +421,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
command[2] = (addr & 0x0000FF00) >> 8;
command[3] = 0;
- DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
+ pr_debug("COMPARE: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);
status = spi_sync(spi, &msg);
if (status < 0)
- DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
+ pr_debug("%s: compare %u -> %d\n",
dev_name(&spi->dev), addr, status);
status = dataflash_waitready(priv->spi);
@@ -634,11 +645,10 @@ add_dataflash_otp(struct spi_device *spi, char *name,
{
struct dataflash *priv;
struct mtd_info *device;
+ struct mtd_part_parser_data ppdata;
struct flash_platform_data *pdata = spi->dev.platform_data;
char *otp_tag = "";
int err = 0;
- struct mtd_partition *parts;
- int nr_parts = 0;
priv = kzalloc(sizeof *priv, GFP_KERNEL);
if (!priv)
@@ -677,28 +687,11 @@ add_dataflash_otp(struct spi_device *spi, char *name,
pagesize, otp_tag);
dev_set_drvdata(&spi->dev, priv);
- if (mtd_has_cmdlinepart()) {
- static const char *part_probes[] = { "cmdlinepart", NULL, };
-
- nr_parts = parse_mtd_partitions(device, part_probes, &parts,
- 0);
- }
+ ppdata.of_node = spi->dev.of_node;
+ err = mtd_device_parse_register(device, NULL, &ppdata,
+ pdata ? pdata->parts : NULL,
+ pdata ? pdata->nr_parts : 0);
- if (nr_parts <= 0 && pdata && pdata->parts) {
- parts = pdata->parts;
- nr_parts = pdata->nr_parts;
- }
-
- if (nr_parts > 0) {
- priv->partitioned = 1;
- err = mtd_device_register(device, parts, nr_parts);
- goto out;
- }
-
- if (mtd_device_register(device, NULL, 0) == 1)
- err = -ENODEV;
-
-out:
if (!err)
return 0;
@@ -787,7 +780,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
*/
tmp = spi_write_then_read(spi, &code, 1, id, 3);
if (tmp < 0) {
- DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
+ pr_debug("%s: error %d reading JEDEC ID\n",
dev_name(&spi->dev), tmp);
return ERR_PTR(tmp);
}
@@ -804,7 +797,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
tmp < ARRAY_SIZE(dataflash_data);
tmp++, info++) {
if (info->jedec_id == jedec) {
- DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n",
+ pr_debug("%s: OTP, sector protect%s\n",
dev_name(&spi->dev),
(info->flags & SUP_POW2PS)
? ", binary pagesize" : ""
@@ -812,8 +805,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
if (info->flags & SUP_POW2PS) {
status = dataflash_status(spi);
if (status < 0) {
- DEBUG(MTD_DEBUG_LEVEL1,
- "%s: status error %d\n",
+ pr_debug("%s: status error %d\n",
dev_name(&spi->dev), status);
return ERR_PTR(status);
}
@@ -878,7 +870,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
*/
status = dataflash_status(spi);
if (status <= 0 || status == 0xff) {
- DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
+ pr_debug("%s: status error %d\n",
dev_name(&spi->dev), status);
if (status == 0 || status == 0xff)
status = -ENODEV;
@@ -914,14 +906,14 @@ static int __devinit dataflash_probe(struct spi_device *spi)
break;
/* obsolete AT45DB1282 not (yet?) supported */
default:
- DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
- dev_name(&spi->dev), status & 0x3c);
+ pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev),
+ status & 0x3c);
status = -ENODEV;
}
if (status < 0)
- DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
- dev_name(&spi->dev), status);
+ pr_debug("%s: add_dataflash --> %d\n", dev_name(&spi->dev),
+ status);
return status;
}
@@ -931,7 +923,7 @@ static int __devexit dataflash_remove(struct spi_device *spi)
struct dataflash *flash = dev_get_drvdata(&spi->dev);
int status;
- DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));
+ pr_debug("%s: remove\n", dev_name(&spi->dev));
status = mtd_device_unregister(&flash->mtd);
if (status == 0) {
@@ -946,6 +938,7 @@ static struct spi_driver dataflash_driver = {
.name = "mtd_dataflash",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .of_match_table = dataflash_dt_ids,
},
.probe = dataflash_probe,
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 867710a..9c35250 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -5,7 +5,7 @@
*
* Copyright © 2009 Bluewater Systems Ltd
* Author: Andre Renaud <andre@bluewatersys.com>
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
*
* Based on m25p80.c
*
@@ -52,8 +52,6 @@ struct sst25l_flash {
struct spi_device *spi;
struct mutex lock;
struct mtd_info mtd;
-
- int partitioned;
};
struct flash_info {
@@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi)
struct sst25l_flash *flash;
struct flash_platform_data *data;
int ret, i;
- struct mtd_partition *parts = NULL;
- int nr_parts = 0;
flash_info = sst25l_match_device(spi);
if (!flash_info)
@@ -415,8 +411,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
(long long)flash->mtd.size >> 10);
- DEBUG(MTD_DEBUG_LEVEL2,
- "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+ pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
flash->mtd.name,
(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
@@ -424,37 +419,10 @@ static int __devinit sst25l_probe(struct spi_device *spi)
flash->mtd.numeraseregions);
- if (mtd_has_cmdlinepart()) {
- static const char *part_probes[] = {"cmdlinepart", NULL};
-
- nr_parts = parse_mtd_partitions(&flash->mtd,
- part_probes,
- &parts, 0);
- }
-
- if (nr_parts <= 0 && data && data->parts) {
- parts = data->parts;
- nr_parts = data->nr_parts;
- }
-
- if (nr_parts > 0) {
- for (i = 0; i < nr_parts; i++) {
- DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
- "{.name = %s, .offset = 0x%llx, "
- ".size = 0x%llx (%lldKiB) }\n",
- i, parts[i].name,
- (long long)parts[i].offset,
- (long long)parts[i].size,
- (long long)(parts[i].size >> 10));
- }
-
- flash->partitioned = 1;
- return mtd_device_register(&flash->mtd, parts,
- nr_parts);
- }
-
- ret = mtd_device_register(&flash->mtd, NULL, 0);
- if (ret == 1) {
+ ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
+ data ? data->parts : NULL,
+ data ? data->nr_parts : 0);
+ if (ret) {
kfree(flash);
dev_set_drvdata(&spi->dev, NULL);
return -ENODEV;
@@ -499,5 +467,5 @@ module_exit(sst25l_exit);
MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips");
MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, "
- "Ryan Mallon <ryan@bluewatersys.com>");
+ "Ryan Mallon");
MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index 65655dd..1dca31d 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -27,6 +27,7 @@
#include <linux/mtd/pfow.h>
#include <linux/mtd/qinfo.h>
#include <linux/slab.h>
+#include <linux/module.h>
static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
size_t *retlen, u_char *buf);
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 2d70d35..7813095 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -30,11 +30,8 @@
*/
#define DRIVER_NAME "onenand-flash"
-static const char *part_probes[] = { "cmdlinepart", NULL, };
-
struct onenand_info {
struct mtd_info mtd;
- struct mtd_partition *parts;
struct onenand_chip onenand;
};
@@ -73,13 +70,9 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev)
goto out_iounmap;
}
- err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
- if (err > 0)
- mtd_device_register(&info->mtd, info->parts, err);
- else if (err <= 0 && pdata && pdata->parts)
- mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
- else
- err = mtd_device_register(&info->mtd, NULL, 0);
+ err = mtd_device_parse_register(&info->mtd, NULL, 0,
+ pdata ? pdata->parts : NULL,
+ pdata ? pdata->nr_parts : 0);
platform_set_drvdata(pdev, info);
@@ -104,7 +97,6 @@ static int __devexit generic_onenand_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
if (info) {
- mtd_device_unregister(&info->mtd);
onenand_release(&info->mtd);
release_mem_region(res->start, size);
iounmap(info->onenand.base);
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index a916dec..7e9ea68 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -40,7 +40,7 @@
#include <asm/mach/flash.h>
#include <plat/gpmc.h>
#include <plat/onenand.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <plat/dma.h>
@@ -57,7 +57,6 @@ struct omap2_onenand {
unsigned long phys_base;
int gpio_irq;
struct mtd_info mtd;
- struct mtd_partition *parts;
struct onenand_chip onenand;
struct completion irq_done;
struct completion dma_done;
@@ -67,8 +66,6 @@ struct omap2_onenand {
struct regulator *regulator;
};
-static const char *part_probes[] = { "cmdlinepart", NULL, };
-
static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
{
struct omap2_onenand *c = data;
@@ -741,6 +738,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
c->regulator = regulator_get(&pdev->dev, "vonenand");
if (IS_ERR(c->regulator)) {
dev_err(&pdev->dev, "Failed to get regulator\n");
+ r = PTR_ERR(c->regulator);
goto err_release_dma;
}
c->onenand.enable = omap2_onenand_enable;
@@ -753,13 +751,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
if ((r = onenand_scan(&c->mtd, 1)) < 0)
goto err_release_regulator;
- r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
- if (r > 0)
- r = mtd_device_register(&c->mtd, c->parts, r);
- else if (pdata->parts != NULL)
- r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts);
- else
- r = mtd_device_register(&c->mtd, NULL, 0);
+ r = mtd_device_parse_register(&c->mtd, NULL, 0,
+ pdata ? pdata->parts : NULL,
+ pdata ? pdata->nr_parts : 0);
if (r)
goto err_release_onenand;
@@ -786,7 +780,6 @@ err_release_mem_region:
err_free_cs:
gpmc_cs_free(c->gpmc_cs);
err_kfree:
- kfree(c->parts);
kfree(c);
return r;
@@ -809,7 +802,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
iounmap(c->onenand.base);
release_mem_region(c->phys_base, ONENAND_IO_SIZE);
gpmc_cs_free(c->gpmc_cs);
- kfree(c->parts);
kfree(c);
return 0;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ac9e959..a839473 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1015,7 +1015,7 @@ static void onenand_release_device(struct mtd_info *mtd)
}
/**
- * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer
* @param mtd MTD device structure
* @param buf destination address
* @param column oob offset to read from
@@ -1079,7 +1079,7 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
return status;
/* check if we failed due to uncorrectable error */
- if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
+ if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR)
return status;
/* check if address lies in MLC region */
@@ -1122,10 +1122,10 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
int ret = 0;
int writesize = this->writesize;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
- __func__, (unsigned int) from, (int) len);
+ pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+ (int)len);
- if (ops->mode == MTD_OOB_AUTO)
+ if (ops->mode == MTD_OPS_AUTO_OOB)
oobsize = this->ecclayout->oobavail;
else
oobsize = mtd->oobsize;
@@ -1159,7 +1159,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
if (unlikely(ret))
ret = onenand_recover_lsb(mtd, from, ret);
onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
+ if (mtd_is_eccerr(ret))
ret = 0;
if (ret)
break;
@@ -1170,7 +1170,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
thisooblen = oobsize - oobcolumn;
thisooblen = min_t(int, thisooblen, ooblen - oobread);
- if (ops->mode == MTD_OOB_AUTO)
+ if (ops->mode == MTD_OPS_AUTO_OOB)
onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
else
this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -1226,10 +1226,10 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
int ret = 0, boundary = 0;
int writesize = this->writesize;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
- __func__, (unsigned int) from, (int) len);
+ pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+ (int)len);
- if (ops->mode == MTD_OOB_AUTO)
+ if (ops->mode == MTD_OPS_AUTO_OOB)
oobsize = this->ecclayout->oobavail;
else
oobsize = mtd->oobsize;
@@ -1255,7 +1255,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
this->command(mtd, ONENAND_CMD_READ, from, writesize);
ret = this->wait(mtd, FL_READING);
onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
+ if (mtd_is_eccerr(ret))
ret = 0;
}
}
@@ -1291,7 +1291,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
thisooblen = oobsize - oobcolumn;
thisooblen = min_t(int, thisooblen, ooblen - oobread);
- if (ops->mode == MTD_OOB_AUTO)
+ if (ops->mode == MTD_OPS_AUTO_OOB)
onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
else
this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -1315,7 +1315,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
/* Now wait for load */
ret = this->wait(mtd, FL_READING);
onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
+ if (mtd_is_eccerr(ret))
ret = 0;
}
@@ -1351,19 +1351,19 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
struct mtd_ecc_stats stats;
int read = 0, thislen, column, oobsize;
size_t len = ops->ooblen;
- mtd_oob_mode_t mode = ops->mode;
+ unsigned int mode = ops->mode;
u_char *buf = ops->oobbuf;
int ret = 0, readcmd;
from += ops->ooboffs;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
- __func__, (unsigned int) from, (int) len);
+ pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+ (int)len);
/* Initialize return length value */
ops->oobretlen = 0;
- if (mode == MTD_OOB_AUTO)
+ if (mode == MTD_OPS_AUTO_OOB)
oobsize = this->ecclayout->oobavail;
else
oobsize = mtd->oobsize;
@@ -1403,13 +1403,13 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
if (unlikely(ret))
ret = onenand_recover_lsb(mtd, from, ret);
- if (ret && ret != -EBADMSG) {
+ if (ret && !mtd_is_eccerr(ret)) {
printk(KERN_ERR "%s: read failed = 0x%x\n",
__func__, ret);
break;
}
- if (mode == MTD_OOB_AUTO)
+ if (mode == MTD_OPS_AUTO_OOB)
onenand_transfer_auto_oob(mtd, buf, column, thislen);
else
this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
@@ -1487,10 +1487,10 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
int ret;
switch (ops->mode) {
- case MTD_OOB_PLACE:
- case MTD_OOB_AUTO:
+ case MTD_OPS_PLACE_OOB:
+ case MTD_OPS_AUTO_OOB:
break;
- case MTD_OOB_RAW:
+ case MTD_OPS_RAW:
/* Not implemented yet */
default:
return -EINVAL;
@@ -1576,8 +1576,8 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
size_t len = ops->ooblen;
u_char *buf = ops->oobbuf;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n",
- __func__, (unsigned int) from, len);
+ pr_debug("%s: from = 0x%08x, len = %zi\n", __func__, (unsigned int)from,
+ len);
/* Initialize return value */
ops->oobretlen = 0;
@@ -1750,8 +1750,8 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
/* Wait for any existing operation to clear */
onenand_panic_wait(mtd);
- DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
- __func__, (unsigned int) to, (int) len);
+ pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+ (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
@@ -1821,7 +1821,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
}
/**
- * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer
* @param mtd MTD device structure
* @param oob_buf oob buffer
* @param buf source address
@@ -1883,8 +1883,8 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
u_char *oobbuf;
int ret = 0, cmd;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
- __func__, (unsigned int) to, (int) len);
+ pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+ (int)len);
/* Initialize retlen, in case of early exit */
ops->retlen = 0;
@@ -1908,7 +1908,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
if (!len)
return 0;
- if (ops->mode == MTD_OOB_AUTO)
+ if (ops->mode == MTD_OPS_AUTO_OOB)
oobsize = this->ecclayout->oobavail;
else
oobsize = mtd->oobsize;
@@ -1945,7 +1945,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
/* We send data to spare ram with oobsize
* to prevent byte access */
memset(oobbuf, 0xff, mtd->oobsize);
- if (ops->mode == MTD_OOB_AUTO)
+ if (ops->mode == MTD_OPS_AUTO_OOB)
onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
else
memcpy(oobbuf + oobcolumn, oob, thisooblen);
@@ -2055,7 +2055,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
/**
- * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
+ * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band
* @param mtd MTD device structure
* @param to offset to write to
* @param len number of bytes to write
@@ -2074,17 +2074,17 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
u_char *oobbuf;
size_t len = ops->ooblen;
const u_char *buf = ops->oobbuf;
- mtd_oob_mode_t mode = ops->mode;
+ unsigned int mode = ops->mode;
to += ops->ooboffs;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
- __func__, (unsigned int) to, (int) len);
+ pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+ (int)len);
/* Initialize retlen, in case of early exit */
ops->oobretlen = 0;
- if (mode == MTD_OOB_AUTO)
+ if (mode == MTD_OPS_AUTO_OOB)
oobsize = this->ecclayout->oobavail;
else
oobsize = mtd->oobsize;
@@ -2128,7 +2128,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
/* We send data to spare ram with oobsize
* to prevent byte access */
memset(oobbuf, 0xff, mtd->oobsize);
- if (mode == MTD_OOB_AUTO)
+ if (mode == MTD_OPS_AUTO_OOB)
onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
else
memcpy(oobbuf + column, buf, thislen);
@@ -2217,10 +2217,10 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
int ret;
switch (ops->mode) {
- case MTD_OOB_PLACE:
- case MTD_OOB_AUTO:
+ case MTD_OPS_PLACE_OOB:
+ case MTD_OPS_AUTO_OOB:
break;
- case MTD_OOB_RAW:
+ case MTD_OPS_RAW:
/* Not implemented yet */
default:
return -EINVAL;
@@ -2281,7 +2281,7 @@ static int onenand_multiblock_erase_verify(struct mtd_info *mtd,
}
/**
- * onenand_multiblock_erase - [Internal] erase block(s) using multiblock erase
+ * onenand_multiblock_erase - [INTERN] erase block(s) using multiblock erase
* @param mtd MTD device structure
* @param instr erase instruction
* @param region erase region
@@ -2397,7 +2397,7 @@ static int onenand_multiblock_erase(struct mtd_info *mtd,
/**
- * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
+ * onenand_block_by_block_erase - [INTERN] erase block(s) using regular erase
* @param mtd MTD device structure
* @param instr erase instruction
* @param region erase region
@@ -2489,8 +2489,9 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
struct mtd_erase_region_info *region = NULL;
loff_t region_offset = 0;
- DEBUG(MTD_DEBUG_LEVEL3, "%s: start=0x%012llx, len=%llu\n", __func__,
- (unsigned long long) instr->addr, (unsigned long long) instr->len);
+ pr_debug("%s: start=0x%012llx, len=%llu\n", __func__,
+ (unsigned long long)instr->addr,
+ (unsigned long long)instr->len);
/* Do not allow erase past end of device */
if (unlikely((len + addr) > mtd->size)) {
@@ -2558,7 +2559,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
*/
static void onenand_sync(struct mtd_info *mtd)
{
- DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+ pr_debug("%s: called\n", __func__);
/* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_SYNCING);
@@ -2602,7 +2603,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
struct bbm_info *bbm = this->bbm;
u_char buf[2] = {0, 0};
struct mtd_oob_ops ops = {
- .mode = MTD_OOB_PLACE,
+ .mode = MTD_OPS_PLACE_OOB,
.ooblen = 2,
.oobbuf = buf,
.ooboffs = 0,
@@ -2922,7 +2923,7 @@ static int onenand_otp_command(struct mtd_info *mtd, int cmd, loff_t addr,
}
/**
- * onenand_otp_write_oob_nolock - [Internal] OneNAND write out-of-band, specific to OTP
+ * onenand_otp_write_oob_nolock - [INTERN] OneNAND write out-of-band, specific to OTP
* @param mtd MTD device structure
* @param to offset to write to
* @param len number of bytes to write
@@ -3170,7 +3171,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
this->command(mtd, ONENAND_CMD_RESET, 0, 0);
this->wait(mtd, FL_RESETING);
} else {
- ops.mode = MTD_OOB_PLACE;
+ ops.mode = MTD_OPS_PLACE_OOB;
ops.ooblen = len;
ops.oobbuf = buf;
ops.ooboffs = 0;
@@ -3429,6 +3430,19 @@ static void onenand_check_features(struct mtd_info *mtd)
else if (numbufs == 1) {
this->options |= ONENAND_HAS_4KB_PAGE;
this->options |= ONENAND_HAS_CACHE_PROGRAM;
+ /*
+ * There are two different 4KiB pagesize chips
+ * and no way to detect it by H/W config values.
+ *
+ * To detect the correct NOP for each chips,
+ * It should check the version ID as workaround.
+ *
+ * Now it has as following
+ * KFM4G16Q4M has NOP 4 with version ID 0x0131
+ * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
+ */
+ if ((this->version_id & 0xf) == 0xe)
+ this->options |= ONENAND_HAS_NOP_1;
}
case ONENAND_DEVICE_DENSITY_2Gb:
@@ -3663,7 +3677,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
int i, ret;
int block;
struct mtd_oob_ops ops = {
- .mode = MTD_OOB_PLACE,
+ .mode = MTD_OPS_PLACE_OOB,
.ooboffs = 0,
.ooblen = mtd->oobsize,
.datbuf = NULL,
@@ -4054,6 +4068,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
this->ecclayout = &onenand_oob_128;
mtd->subpage_sft = 2;
}
+ if (ONENAND_IS_NOP_1(this))
+ mtd->subpage_sft = 0;
break;
case 64:
this->ecclayout = &onenand_oob_64;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index fc2c16a..66fe3b7 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
+#include <linux/export.h>
/**
* check_short_pattern - [GENERIC] check if a pattern is in the buffer
@@ -80,7 +81,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
startblock = 0;
from = 0;
- ops.mode = MTD_OOB_PLACE;
+ ops.mode = MTD_OPS_PLACE_OOB;
ops.ooblen = readlen;
ops.oobbuf = buf;
ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
@@ -153,7 +154,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
block = (int) (onenand_block(this, offs) << 1);
res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
- DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+ pr_debug("onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
(unsigned int) offs, block >> 1, res);
switch ((int) res) {
@@ -188,10 +189,8 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
len = this->chipsize >> (this->erase_shift + 2);
/* Allocate memory (2bit per block) and clear the memory bad block table */
bbm->bbt = kzalloc(len, GFP_KERNEL);
- if (!bbm->bbt) {
- printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+ if (!bbm->bbt)
return -ENOMEM;
- }
/* Set the bad block position */
bbm->badblockpos = ONENAND_BADBLOCK_POS;
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 3306b5b..5474547 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -147,7 +147,6 @@ struct s3c_onenand {
struct resource *dma_res;
unsigned long phys_base;
struct completion complete;
- struct mtd_partition *parts;
};
#define CMD_MAP_00(dev, addr) (dev->cmd_map(MAP_00, ((addr) << 1)))
@@ -157,8 +156,6 @@ struct s3c_onenand {
static struct s3c_onenand *onenand;
-static const char *part_probes[] = { "cmdlinepart", NULL, };
-
static inline int s3c_read_reg(int offset)
{
return readl(onenand->base + offset);
@@ -1017,13 +1014,9 @@ static int s3c_onenand_probe(struct platform_device *pdev)
if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
- err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
- if (err > 0)
- mtd_device_register(mtd, onenand->parts, err);
- else if (err <= 0 && pdata && pdata->parts)
- mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
- else
- err = mtd_device_register(mtd, NULL, 0);
+ err = mtd_device_parse_register(mtd, NULL, 0,
+ pdata ? pdata->parts : NULL,
+ pdata ? pdata->nr_parts : 0);
platform_set_drvdata(pdev, mtd);
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
index dec92ae..933f7e5 100644
--- a/drivers/mtd/tests/mtd_oobtest.c
+++ b/drivers/mtd/tests/mtd_oobtest.c
@@ -30,7 +30,7 @@
#define PRINT_PREF KERN_INFO "mtd_oobtest: "
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -131,7 +131,7 @@ static int write_eraseblock(int ebnum)
for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
set_random_data(writebuf, use_len);
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = use_len;
@@ -184,7 +184,7 @@ static int verify_eraseblock(int ebnum)
for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
set_random_data(writebuf, use_len);
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = use_len;
@@ -211,7 +211,7 @@ static int verify_eraseblock(int ebnum)
if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
int k;
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->ecclayout->oobavail;
@@ -276,7 +276,7 @@ static int verify_eraseblock_in_one_go(int ebnum)
size_t len = mtd->ecclayout->oobavail * pgcnt;
set_random_data(writebuf, len);
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = len;
@@ -366,6 +366,13 @@ static int __init mtd_oobtest_init(void)
printk(KERN_INFO "\n");
printk(KERN_INFO "=================================================\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+ return -EINVAL;
+ }
+
printk(PRINT_PREF "MTD device: %d\n", dev);
mtd = get_mtd_device(NULL, dev);
@@ -507,7 +514,7 @@ static int __init mtd_oobtest_init(void)
addr0 += mtd->erasesize;
/* Attempt to write off end of OOB */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = 1;
@@ -527,7 +534,7 @@ static int __init mtd_oobtest_init(void)
}
/* Attempt to read off end of OOB */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = 1;
@@ -551,7 +558,7 @@ static int __init mtd_oobtest_init(void)
"block is bad\n");
else {
/* Attempt to write off end of device */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->ecclayout->oobavail + 1;
@@ -571,7 +578,7 @@ static int __init mtd_oobtest_init(void)
}
/* Attempt to read off end of device */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->ecclayout->oobavail + 1;
@@ -595,7 +602,7 @@ static int __init mtd_oobtest_init(void)
goto out;
/* Attempt to write off end of device */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->ecclayout->oobavail;
@@ -615,7 +622,7 @@ static int __init mtd_oobtest_init(void)
}
/* Attempt to read off end of device */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->ecclayout->oobavail;
@@ -655,7 +662,7 @@ static int __init mtd_oobtest_init(void)
addr = (i + 1) * mtd->erasesize - mtd->writesize;
for (pg = 0; pg < cnt; ++pg) {
set_random_data(writebuf, sz);
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = sz;
@@ -683,7 +690,7 @@ static int __init mtd_oobtest_init(void)
continue;
set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
addr = (i + 1) * mtd->erasesize - mtd->writesize;
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->ecclayout->oobavail * 2;
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
index 00b937e..afafb69 100644
--- a/drivers/mtd/tests/mtd_pagetest.c
+++ b/drivers/mtd/tests/mtd_pagetest.c
@@ -30,7 +30,7 @@
#define PRINT_PREF KERN_INFO "mtd_pagetest: "
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -128,7 +128,7 @@ static int verify_eraseblock(int ebnum)
for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
/* Do a read to set the internal dataRAMs to different data */
err = mtd->read(mtd, addr0, bufsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != bufsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -136,7 +136,7 @@ static int verify_eraseblock(int ebnum)
return err;
}
err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != bufsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -146,7 +146,7 @@ static int verify_eraseblock(int ebnum)
memset(twopages, 0, bufsize);
read = 0;
err = mtd->read(mtd, addr, bufsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != bufsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -164,7 +164,7 @@ static int verify_eraseblock(int ebnum)
unsigned long oldnext = next;
/* Do a read to set the internal dataRAMs to different data */
err = mtd->read(mtd, addr0, bufsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != bufsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -172,7 +172,7 @@ static int verify_eraseblock(int ebnum)
return err;
}
err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != bufsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -182,7 +182,7 @@ static int verify_eraseblock(int ebnum)
memset(twopages, 0, bufsize);
read = 0;
err = mtd->read(mtd, addr, bufsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != bufsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -231,7 +231,7 @@ static int crosstest(void)
read = 0;
addr = addrn - pgsize - pgsize;
err = mtd->read(mtd, addr, pgsize, &read, pp1);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -244,7 +244,7 @@ static int crosstest(void)
read = 0;
addr = addrn - pgsize - pgsize - pgsize;
err = mtd->read(mtd, addr, pgsize, &read, pp1);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -258,7 +258,7 @@ static int crosstest(void)
addr = addr0;
printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
err = mtd->read(mtd, addr, pgsize, &read, pp2);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -272,7 +272,7 @@ static int crosstest(void)
addr = addrn - pgsize;
printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
err = mtd->read(mtd, addr, pgsize, &read, pp3);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -286,7 +286,7 @@ static int crosstest(void)
addr = addr0;
printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
err = mtd->read(mtd, addr, pgsize, &read, pp4);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -345,7 +345,7 @@ static int erasecrosstest(void)
printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
memset(readbuf, 0, pgsize);
err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -383,7 +383,7 @@ static int erasecrosstest(void)
printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
memset(readbuf, 0, pgsize);
err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -439,7 +439,7 @@ static int erasetest(void)
printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
err = mtd->read(mtd, addr0, pgsize, &read, twopages);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -504,6 +504,13 @@ static int __init mtd_pagetest_init(void)
printk(KERN_INFO "\n");
printk(KERN_INFO "=================================================\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+ return -EINVAL;
+ }
+
printk(PRINT_PREF "MTD device: %d\n", dev);
mtd = get_mtd_device(NULL, dev);
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
index afe71aa..550fe51 100644
--- a/drivers/mtd/tests/mtd_readtest.c
+++ b/drivers/mtd/tests/mtd_readtest.c
@@ -29,7 +29,7 @@
#define PRINT_PREF KERN_INFO "mtd_readtest: "
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -66,7 +66,7 @@ static int read_eraseblock_by_page(int ebnum)
if (mtd->oobsize) {
struct mtd_oob_ops ops;
- ops.mode = MTD_OOB_PLACE;
+ ops.mode = MTD_OPS_PLACE_OOB;
ops.len = 0;
ops.retlen = 0;
ops.ooblen = mtd->oobsize;
@@ -75,7 +75,8 @@ static int read_eraseblock_by_page(int ebnum)
ops.datbuf = NULL;
ops.oobbuf = oobbuf;
ret = mtd->read_oob(mtd, addr, &ops);
- if (ret || ops.oobretlen != mtd->oobsize) {
+ if ((ret && !mtd_is_bitflip(ret)) ||
+ ops.oobretlen != mtd->oobsize) {
printk(PRINT_PREF "error: read oob failed at "
"%#llx\n", (long long)addr);
if (!err)
@@ -169,6 +170,12 @@ static int __init mtd_readtest_init(void)
printk(KERN_INFO "\n");
printk(KERN_INFO "=================================================\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ return -EINVAL;
+ }
+
printk(PRINT_PREF "MTD device: %d\n", dev);
mtd = get_mtd_device(NULL, dev);
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c
index 627d4e2..493b367 100644
--- a/drivers/mtd/tests/mtd_speedtest.c
+++ b/drivers/mtd/tests/mtd_speedtest.c
@@ -29,7 +29,7 @@
#define PRINT_PREF KERN_INFO "mtd_speedtest: "
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -216,7 +216,7 @@ static int read_eraseblock(int ebnum)
err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf);
/* Ignore corrected ECC errors */
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != mtd->erasesize) {
printk(PRINT_PREF "error: read failed at %#llx\n", addr);
@@ -237,7 +237,7 @@ static int read_eraseblock_by_page(int ebnum)
for (i = 0; i < pgcnt; i++) {
err = mtd->read(mtd, addr, pgsize, &read, buf);
/* Ignore corrected ECC errors */
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -263,7 +263,7 @@ static int read_eraseblock_by_2pages(int ebnum)
for (i = 0; i < n; i++) {
err = mtd->read(mtd, addr, sz, &read, buf);
/* Ignore corrected ECC errors */
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != sz) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -278,7 +278,7 @@ static int read_eraseblock_by_2pages(int ebnum)
if (pgcnt % 2) {
err = mtd->read(mtd, addr, pgsize, &read, buf);
/* Ignore corrected ECC errors */
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (err || read != pgsize) {
printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -361,6 +361,13 @@ static int __init mtd_speedtest_init(void)
printk(KERN_INFO "\n");
printk(KERN_INFO "=================================================\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+ return -EINVAL;
+ }
+
if (count)
printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count);
else
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
index 129bad2..811642f 100644
--- a/drivers/mtd/tests/mtd_stresstest.c
+++ b/drivers/mtd/tests/mtd_stresstest.c
@@ -30,7 +30,7 @@
#define PRINT_PREF KERN_INFO "mtd_stresstest: "
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -154,7 +154,7 @@ static int do_read(void)
}
addr = eb * mtd->erasesize + offs;
err = mtd->read(mtd, addr, len, &read, readbuf);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
err = 0;
if (unlikely(err || read != len)) {
printk(PRINT_PREF "error: read failed at 0x%llx\n",
@@ -250,6 +250,13 @@ static int __init mtd_stresstest_init(void)
printk(KERN_INFO "\n");
printk(KERN_INFO "=================================================\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+ return -EINVAL;
+ }
+
printk(PRINT_PREF "MTD device: %d\n", dev);
mtd = get_mtd_device(NULL, dev);
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c
index 334eae5..1a05bfa 100644
--- a/drivers/mtd/tests/mtd_subpagetest.c
+++ b/drivers/mtd/tests/mtd_subpagetest.c
@@ -29,7 +29,7 @@
#define PRINT_PREF KERN_INFO "mtd_subpagetest: "
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -198,7 +198,7 @@ static int verify_eraseblock(int ebnum)
read = 0;
err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
if (unlikely(err || read != subpgsize)) {
- if (err == -EUCLEAN && read == subpgsize) {
+ if (mtd_is_bitflip(err) && read == subpgsize) {
printk(PRINT_PREF "ECC correction at %#llx\n",
(long long)addr);
err = 0;
@@ -226,7 +226,7 @@ static int verify_eraseblock(int ebnum)
read = 0;
err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
if (unlikely(err || read != subpgsize)) {
- if (err == -EUCLEAN && read == subpgsize) {
+ if (mtd_is_bitflip(err) && read == subpgsize) {
printk(PRINT_PREF "ECC correction at %#llx\n",
(long long)addr);
err = 0;
@@ -264,7 +264,7 @@ static int verify_eraseblock2(int ebnum)
read = 0;
err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf);
if (unlikely(err || read != subpgsize * k)) {
- if (err == -EUCLEAN && read == subpgsize * k) {
+ if (mtd_is_bitflip(err) && read == subpgsize * k) {
printk(PRINT_PREF "ECC correction at %#llx\n",
(long long)addr);
err = 0;
@@ -298,7 +298,7 @@ static int verify_eraseblock_ff(int ebnum)
read = 0;
err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
if (unlikely(err || read != subpgsize)) {
- if (err == -EUCLEAN && read == subpgsize) {
+ if (mtd_is_bitflip(err) && read == subpgsize) {
printk(PRINT_PREF "ECC correction at %#llx\n",
(long long)addr);
err = 0;
@@ -379,6 +379,13 @@ static int __init mtd_subpagetest_init(void)
printk(KERN_INFO "\n");
printk(KERN_INFO "=================================================\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+ return -EINVAL;
+ }
+
printk(PRINT_PREF "MTD device: %d\n", dev);
mtd = get_mtd_device(NULL, dev);
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c
index 5c6c3d2..03ab649 100644
--- a/drivers/mtd/tests/mtd_torturetest.c
+++ b/drivers/mtd/tests/mtd_torturetest.c
@@ -46,7 +46,7 @@ static int pgcnt;
module_param(pgcnt, int, S_IRUGO);
MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)");
-static int dev;
+static int dev = -EINVAL;
module_param(dev, int, S_IRUGO);
MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -138,7 +138,7 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf)
retry:
err = mtd->read(mtd, addr, len, &read, check_buf);
- if (err == -EUCLEAN)
+ if (mtd_is_bitflip(err))
printk(PRINT_PREF "single bit flip occurred at EB %d "
"MTD reported that it was fixed.\n", ebnum);
else if (err) {
@@ -213,6 +213,13 @@ static int __init tort_init(void)
printk(KERN_INFO "=================================================\n");
printk(PRINT_PREF "Warning: this program is trying to wear out your "
"flash, stop it if this is not wanted.\n");
+
+ if (dev < 0) {
+ printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+ printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+ return -EINVAL;
+ }
+
printk(PRINT_PREF "MTD device: %d\n", dev);
printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n",
ebcnt, eb, eb + ebcnt - 1, dev);
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 2b351d0..1f9c363 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -958,10 +958,14 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (!ubi->peb_buf2)
goto out_free;
+ err = ubi_debugging_init_dev(ubi);
+ if (err)
+ goto out_free;
+
err = attach_by_scanning(ubi);
if (err) {
dbg_err("failed to attach by scanning, error %d", err);
- goto out_free;
+ goto out_debugging;
}
if (ubi->autoresize_vol_id != -1) {
@@ -974,12 +978,16 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (err)
goto out_detach;
+ err = ubi_debugfs_init_dev(ubi);
+ if (err)
+ goto out_uif;
+
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
if (IS_ERR(ubi->bgt_thread)) {
err = PTR_ERR(ubi->bgt_thread);
ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
err);
- goto out_uif;
+ goto out_debugfs;
}
ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
@@ -1013,12 +1021,18 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
return ubi_num;
+out_debugfs:
+ ubi_debugfs_exit_dev(ubi);
out_uif:
+ get_device(&ubi->dev);
+ ubi_assert(ref);
uif_close(ubi);
out_detach:
ubi_wl_close(ubi);
free_internal_volumes(ubi);
vfree(ubi->vtbl);
+out_debugging:
+ ubi_debugging_exit_dev(ubi);
out_free:
vfree(ubi->peb_buf1);
vfree(ubi->peb_buf2);
@@ -1085,11 +1099,13 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
*/
get_device(&ubi->dev);
+ ubi_debugfs_exit_dev(ubi);
uif_close(ubi);
ubi_wl_close(ubi);
free_internal_volumes(ubi);
vfree(ubi->vtbl);
put_mtd_device(ubi->mtd);
+ ubi_debugging_exit_dev(ubi);
vfree(ubi->peb_buf1);
vfree(ubi->peb_buf2);
ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
@@ -1204,6 +1220,11 @@ static int __init ubi_init(void)
if (!ubi_wl_entry_slab)
goto out_dev_unreg;
+ err = ubi_debugfs_init();
+ if (err)
+ goto out_slab;
+
+
/* Attach MTD devices */
for (i = 0; i < mtd_devs; i++) {
struct mtd_dev_param *p = &mtd_dev_param[i];
@@ -1252,6 +1273,8 @@ out_detach:
ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
mutex_unlock(&ubi_devices_mutex);
}
+ ubi_debugfs_exit();
+out_slab:
kmem_cache_destroy(ubi_wl_entry_slab);
out_dev_unreg:
misc_deregister(&ubi_ctrl_cdev);
@@ -1275,6 +1298,7 @@ static void __exit ubi_exit(void)
ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
mutex_unlock(&ubi_devices_mutex);
}
+ ubi_debugfs_exit();
kmem_cache_destroy(ubi_wl_entry_slab);
misc_deregister(&ubi_ctrl_cdev);
class_remove_file(ubi_class, &ubi_version);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index cdea669..7ac2c05 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -189,12 +189,16 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
return new_offset;
}
-static int vol_cdev_fsync(struct file *file, int datasync)
+static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
struct ubi_volume_desc *desc = file->private_data;
struct ubi_device *ubi = desc->vol->ubi;
-
- return ubi_sync(ubi->ubi_num);
+ struct inode *inode = file->f_path.dentry->d_inode;
+ int err;
+ mutex_lock(&inode->i_mutex);
+ err = ubi_sync(ubi->ubi_num);
+ mutex_unlock(&inode->i_mutex);
+ return err;
}
@@ -471,7 +475,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
/* Validate the request */
err = -EINVAL;
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
- req.bytes < 0 || req.lnum >= vol->usable_leb_size)
+ req.bytes < 0 || req.bytes > vol->usable_leb_size)
break;
if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
req.dtype != UBI_UNKNOWN)
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 2224cbe..ab80c0d 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -27,17 +27,9 @@
#ifdef CONFIG_MTD_UBI_DEBUG
#include "ubi.h"
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-unsigned int ubi_chk_flags;
-unsigned int ubi_tst_flags;
-
-module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
/**
* ubi_dbg_dump_ec_hdr - dump an erase counter header.
@@ -239,4 +231,261 @@ out:
return;
}
+/**
+ * ubi_debugging_init_dev - initialize debugging for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function initializes debugging-related data for UBI device @ubi.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_debugging_init_dev(struct ubi_device *ubi)
+{
+ ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL);
+ if (!ubi->dbg)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * ubi_debugging_exit_dev - free debugging data for an UBI device.
+ * @ubi: UBI device description object
+ */
+void ubi_debugging_exit_dev(struct ubi_device *ubi)
+{
+ kfree(ubi->dbg);
+}
+
+/*
+ * Root directory for UBI stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular UBI devices.
+ */
+static struct dentry *dfs_rootdir;
+
+/**
+ * ubi_debugfs_init - create UBI debugfs directory.
+ *
+ * Create UBI debugfs directory. Returns zero in case of success and a negative
+ * error code in case of failure.
+ */
+int ubi_debugfs_init(void)
+{
+ dfs_rootdir = debugfs_create_dir("ubi", NULL);
+ if (IS_ERR_OR_NULL(dfs_rootdir)) {
+ int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
+
+ ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
+ err);
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ubi_debugfs_exit - remove UBI debugfs directory.
+ */
+void ubi_debugfs_exit(void)
+{
+ debugfs_remove(dfs_rootdir);
+}
+
+/* Read an UBI debugfs file */
+static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long ubi_num = (unsigned long)file->private_data;
+ struct dentry *dent = file->f_path.dentry;
+ struct ubi_device *ubi;
+ struct ubi_debug_info *d;
+ char buf[3];
+ int val;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+ d = ubi->dbg;
+
+ if (dent == d->dfs_chk_gen)
+ val = d->chk_gen;
+ else if (dent == d->dfs_chk_io)
+ val = d->chk_io;
+ else if (dent == d->dfs_disable_bgt)
+ val = d->disable_bgt;
+ else if (dent == d->dfs_emulate_bitflips)
+ val = d->emulate_bitflips;
+ else if (dent == d->dfs_emulate_io_failures)
+ val = d->emulate_io_failures;
+ else {
+ count = -EINVAL;
+ goto out;
+ }
+
+ if (val)
+ buf[0] = '1';
+ else
+ buf[0] = '0';
+ buf[1] = '\n';
+ buf[2] = 0x00;
+
+ count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+
+out:
+ ubi_put_device(ubi);
+ return count;
+}
+
+/* Write an UBI debugfs file */
+static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long ubi_num = (unsigned long)file->private_data;
+ struct dentry *dent = file->f_path.dentry;
+ struct ubi_device *ubi;
+ struct ubi_debug_info *d;
+ size_t buf_size;
+ char buf[8];
+ int val;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+ d = ubi->dbg;
+
+ buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size)) {
+ count = -EFAULT;
+ goto out;
+ }
+
+ if (buf[0] == '1')
+ val = 1;
+ else if (buf[0] == '0')
+ val = 0;
+ else {
+ count = -EINVAL;
+ goto out;
+ }
+
+ if (dent == d->dfs_chk_gen)
+ d->chk_gen = val;
+ else if (dent == d->dfs_chk_io)
+ d->chk_io = val;
+ else if (dent == d->dfs_disable_bgt)
+ d->disable_bgt = val;
+ else if (dent == d->dfs_emulate_bitflips)
+ d->emulate_bitflips = val;
+ else if (dent == d->dfs_emulate_io_failures)
+ d->emulate_io_failures = val;
+ else
+ count = -EINVAL;
+
+out:
+ ubi_put_device(ubi);
+ return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+ if (inode->i_private)
+ file->private_data = inode->i_private;
+
+ return 0;
+}
+
+/* File operations for all UBI debugfs files */
+static const struct file_operations dfs_fops = {
+ .read = dfs_file_read,
+ .write = dfs_file_write,
+ .open = default_open,
+ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function creates all debugfs files for UBI device @ubi. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+int ubi_debugfs_init_dev(struct ubi_device *ubi)
+{
+ int err, n;
+ unsigned long ubi_num = ubi->ubi_num;
+ const char *fname;
+ struct dentry *dent;
+ struct ubi_debug_info *d = ubi->dbg;
+
+ n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
+ ubi->ubi_num);
+ if (n == UBI_DFS_DIR_LEN) {
+ /* The array size is too small */
+ fname = UBI_DFS_DIR_NAME;
+ dent = ERR_PTR(-EINVAL);
+ goto out;
+ }
+
+ fname = d->dfs_dir_name;
+ dent = debugfs_create_dir(fname, dfs_rootdir);
+ if (IS_ERR_OR_NULL(dent))
+ goto out;
+ d->dfs_dir = dent;
+
+ fname = "chk_gen";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_gen = dent;
+
+ fname = "chk_io";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_io = dent;
+
+ fname = "tst_disable_bgt";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_disable_bgt = dent;
+
+ fname = "tst_emulate_bitflips";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_emulate_bitflips = dent;
+
+ fname = "tst_emulate_io_failures";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_emulate_io_failures = dent;
+
+ return 0;
+
+out_remove:
+ debugfs_remove_recursive(d->dfs_dir);
+out:
+ err = dent ? PTR_ERR(dent) : -ENODEV;
+ ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+ fname, err);
+ return err;
+}
+
+/**
+ * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
+ * @ubi: UBI device description object
+ */
+void ubi_debugfs_exit_dev(struct ubi_device *ubi)
+{
+ debugfs_remove_recursive(ubi->dbg->dfs_dir);
+}
+
#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 5f0e4c2..ead2cd1 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -21,14 +21,6 @@
#ifndef __UBI_DEBUG_H__
#define __UBI_DEBUG_H__
-struct ubi_ec_hdr;
-struct ubi_vid_hdr;
-struct ubi_volume;
-struct ubi_vtbl_record;
-struct ubi_scan_volume;
-struct ubi_scan_leb;
-struct ubi_mkvol_req;
-
#ifdef CONFIG_MTD_UBI_DEBUG
#include <linux/random.h>
@@ -74,86 +66,103 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
-
-extern unsigned int ubi_chk_flags;
-
-/*
- * Debugging check flags.
- *
- * UBI_CHK_GEN: general checks
- * UBI_CHK_IO: check writes and erases
- */
-enum {
- UBI_CHK_GEN = 0x1,
- UBI_CHK_IO = 0x2,
-};
-
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
int offset, int len);
-
-extern unsigned int ubi_tst_flags;
+int ubi_debugging_init_dev(struct ubi_device *ubi);
+void ubi_debugging_exit_dev(struct ubi_device *ubi);
+int ubi_debugfs_init(void);
+void ubi_debugfs_exit(void);
+int ubi_debugfs_init_dev(struct ubi_device *ubi);
+void ubi_debugfs_exit_dev(struct ubi_device *ubi);
/*
- * Special testing flags.
+ * The UBI debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 2 for the number plus 1 for the trailing zero byte.
+ */
+#define UBI_DFS_DIR_NAME "ubi%d"
+#define UBI_DFS_DIR_LEN (3 + 2 + 1)
+
+/**
+ * struct ubi_debug_info - debugging information for an UBI device.
*
- * UBIFS_TST_DISABLE_BGT: disable the background thread
- * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips
- * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures
- * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures
+ * @chk_gen: if UBI general extra checks are enabled
+ * @chk_io: if UBI I/O extra checks are enabled
+ * @disable_bgt: disable the background task for testing purposes
+ * @emulate_bitflips: emulate bit-flips for testing purposes
+ * @emulate_io_failures: emulate write/erase failures for testing purposes
+ * @dfs_dir_name: name of debugfs directory containing files of this UBI device
+ * @dfs_dir: direntry object of the UBI device debugfs directory
+ * @dfs_chk_gen: debugfs knob to enable UBI general extra checks
+ * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks
+ * @dfs_disable_bgt: debugfs knob to disable the background task
+ * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips
+ * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures
*/
-enum {
- UBI_TST_DISABLE_BGT = 0x1,
- UBI_TST_EMULATE_BITFLIPS = 0x2,
- UBI_TST_EMULATE_WRITE_FAILURES = 0x4,
- UBI_TST_EMULATE_ERASE_FAILURES = 0x8,
+struct ubi_debug_info {
+ unsigned int chk_gen:1;
+ unsigned int chk_io:1;
+ unsigned int disable_bgt:1;
+ unsigned int emulate_bitflips:1;
+ unsigned int emulate_io_failures:1;
+ char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
+ struct dentry *dfs_dir;
+ struct dentry *dfs_chk_gen;
+ struct dentry *dfs_chk_io;
+ struct dentry *dfs_disable_bgt;
+ struct dentry *dfs_emulate_bitflips;
+ struct dentry *dfs_emulate_io_failures;
};
/**
* ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ * @ubi: UBI device description object
*
* Returns non-zero if the UBI background thread is disabled for testing
* purposes.
*/
-static inline int ubi_dbg_is_bgt_disabled(void)
+static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
{
- return ubi_tst_flags & UBI_TST_DISABLE_BGT;
+ return ubi->dbg->disable_bgt;
}
/**
* ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
+ * @ubi: UBI device description object
*
* Returns non-zero if a bit-flip should be emulated, otherwise returns zero.
*/
-static inline int ubi_dbg_is_bitflip(void)
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS)
+ if (ubi->dbg->emulate_bitflips)
return !(random32() % 200);
return 0;
}
/**
* ubi_dbg_is_write_failure - if it is time to emulate a write failure.
+ * @ubi: UBI device description object
*
* Returns non-zero if a write failure should be emulated, otherwise returns
* zero.
*/
-static inline int ubi_dbg_is_write_failure(void)
+static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES)
+ if (ubi->dbg->emulate_io_failures)
return !(random32() % 500);
return 0;
}
/**
* ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
+ * @ubi: UBI device description object
*
* Returns non-zero if an erase failure should be emulated, otherwise returns
* zero.
*/
-static inline int ubi_dbg_is_erase_failure(void)
+static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES)
+ if (ubi->dbg->emulate_io_failures)
return !(random32() % 400);
return 0;
}
@@ -175,7 +184,7 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_msg(fmt, ...) do { \
if (0) \
- pr_debug(fmt "\n", ##__VA_ARGS__); \
+ printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \
} while (0)
#define dbg_msg(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
@@ -204,11 +213,6 @@ static inline void ubi_dbg_dump_flash(struct ubi_device *ubi,
static inline void
ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r,
int g, const void *b, size_t len, bool a) { return; }
-
-static inline int ubi_dbg_is_bgt_disabled(void) { return 0; }
-static inline int ubi_dbg_is_bitflip(void) { return 0; }
-static inline int ubi_dbg_is_write_failure(void) { return 0; }
-static inline int ubi_dbg_is_erase_failure(void) { return 0; }
static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi,
int pnum, int offset,
int len) { return 0; }
@@ -216,5 +220,20 @@ static inline int ubi_dbg_check_write(struct ubi_device *ubi,
const void *buf, int pnum,
int offset, int len) { return 0; }
+static inline int ubi_debugging_init_dev(struct ubi_device *ubi) { return 0; }
+static inline void ubi_debugging_exit_dev(struct ubi_device *ubi) { return; }
+static inline int ubi_debugfs_init(void) { return 0; }
+static inline void ubi_debugfs_exit(void) { return; }
+static inline int ubi_debugfs_init_dev(struct ubi_device *ubi) { return 0; }
+static inline void ubi_debugfs_exit_dev(struct ubi_device *ubi) { return; }
+
+static inline int
+ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) { return 0; }
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { return 0; }
+static inline int
+ubi_dbg_is_write_failure(const struct ubi_device *ubi) { return 0; }
+static inline int
+ubi_dbg_is_erase_failure(const struct ubi_device *ubi) { return 0; }
+
#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index c696c94..22b3636 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -443,7 +443,7 @@ retry:
if (err == UBI_IO_BITFLIPS) {
scrub = 1;
err = 0;
- } else if (err == -EBADMSG) {
+ } else if (mtd_is_eccerr(err)) {
if (vol->vol_type == UBI_DYNAMIC_VOLUME)
goto out_unlock;
scrub = 1;
@@ -1261,7 +1261,8 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
* during re-size.
*/
ubi_scan_move_to_list(sv, seb, &si->erase);
- vol->eba_tbl[seb->lnum] = seb->pnum;
+ else
+ vol->eba_tbl[seb->lnum] = seb->pnum;
}
}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8c1b1c7..f20b6f2 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -172,9 +172,9 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
retry:
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
if (err) {
- const char *errstr = (err == -EBADMSG) ? " (ECC error)" : "";
+ const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : "";
- if (err == -EUCLEAN) {
+ if (mtd_is_bitflip(err)) {
/*
* -EUCLEAN is reported if there was a bit-flip which
* was corrected, so this is harmless.
@@ -205,14 +205,14 @@ retry:
* all the requested data. But some buggy drivers might do
* this, so we change it to -EIO.
*/
- if (read != len && err == -EBADMSG) {
+ if (read != len && mtd_is_eccerr(err)) {
ubi_assert(0);
err = -EIO;
}
} else {
ubi_assert(len == read);
- if (ubi_dbg_is_bitflip()) {
+ if (ubi_dbg_is_bitflip(ubi)) {
dbg_gen("bit-flip (emulated)");
err = UBI_IO_BITFLIPS;
}
@@ -281,7 +281,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
return err;
}
- if (ubi_dbg_is_write_failure()) {
+ if (ubi_dbg_is_write_failure(ubi)) {
dbg_err("cannot write %d bytes to PEB %d:%d "
"(emulated)", len, pnum, offset);
ubi_dbg_dump_stack();
@@ -396,7 +396,7 @@ retry:
if (err)
return err;
- if (ubi_dbg_is_erase_failure()) {
+ if (ubi_dbg_is_erase_failure(ubi)) {
dbg_err("cannot erase PEB %d (emulated)", pnum);
return -EIO;
}
@@ -469,7 +469,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
out:
mutex_unlock(&ubi->buf_mutex);
- if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+ if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
/*
* If a bit-flip or data integrity error was detected, the test
* has not passed because it happened on a freshly erased
@@ -760,7 +760,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
if (read_err) {
- if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+ if (read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
return read_err;
/*
@@ -776,7 +776,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) {
- if (read_err == -EBADMSG)
+ if (mtd_is_eccerr(read_err))
return UBI_IO_BAD_HDR_EBADMSG;
/*
@@ -1032,12 +1032,12 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
p = (char *)vid_hdr - ubi->vid_hdr_shift;
read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize);
- if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+ if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
return read_err;
magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) {
- if (read_err == -EBADMSG)
+ if (mtd_is_eccerr(read_err))
return UBI_IO_BAD_HDR_EBADMSG;
if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
@@ -1146,7 +1146,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
{
int err;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
err = ubi_io_is_bad(ubi, pnum);
@@ -1173,7 +1173,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
int err;
uint32_t magic;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
magic = be32_to_cpu(ec_hdr->magic);
@@ -1211,7 +1211,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
uint32_t crc, hdr_crc;
struct ubi_ec_hdr *ec_hdr;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1219,7 +1219,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
return -ENOMEM;
err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
- if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+ if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
goto exit;
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -1255,7 +1255,7 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
int err;
uint32_t magic;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
magic = be32_to_cpu(vid_hdr->magic);
@@ -1296,7 +1296,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
struct ubi_vid_hdr *vid_hdr;
void *p;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -1306,7 +1306,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
p = (char *)vid_hdr - ubi->vid_hdr_shift;
err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize);
- if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+ if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
goto exit;
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -1348,7 +1348,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
void *buf1;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
@@ -1358,7 +1358,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
}
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1);
- if (err && err != -EUCLEAN)
+ if (err && !mtd_is_bitflip(err))
goto out_free;
for (i = 0; i < len; i++) {
@@ -1412,7 +1412,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
void *buf;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
@@ -1422,7 +1422,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
}
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
- if (err && err != -EUCLEAN) {
+ if (err && !mtd_is_bitflip(err)) {
ubi_err("error %d while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, len, pnum, offset, read);
goto error;
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index d39716e..1a35fc5 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -410,7 +410,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
return 0;
err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
- if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) {
+ if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
ubi_warn("mark volume %d as corrupted", vol_id);
vol->corrupted = 1;
}
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index ff2a65c..b14ab43 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -74,6 +74,8 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
for (i = 0; i < vol->used_ebs; i++) {
int size;
+ cond_resched();
+
if (i == vol->used_ebs - 1)
size = vol->last_eb_bytes;
else
@@ -81,7 +83,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
if (err) {
- if (err == -EBADMSG)
+ if (mtd_is_eccerr(err))
err = 1;
break;
}
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 0b49ead..c5b2357 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -395,7 +395,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
}
err = ubi_io_read_data(ubi, buf, pnum, 0, len);
- if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+ if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
goto out_free_buf;
data_crc = be32_to_cpu(vid_hdr->data_crc);
@@ -408,7 +408,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
second_is_newer = !second_is_newer;
} else {
dbg_bld("PEB %d CRC is OK", pnum);
- bitflips = !!err;
+ bitflips |= !!err;
}
vfree(buf);
@@ -793,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
ubi->leb_size);
- if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+ if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
/*
* Bit-flips or integrity errors while reading the data area.
* It is difficult to say for sure what type of corruption is
@@ -997,7 +997,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
return err;
goto adjust_mean_ec;
case UBI_IO_FF:
- if (ec_err)
+ if (ec_err || bitflips)
err = add_to_list(si, pnum, ec, 1, &si->erase);
else
err = add_to_list(si, pnum, ec, 0, &si->free);
@@ -1347,7 +1347,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
struct ubi_scan_leb *seb, *last_seb;
uint8_t *buf;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
/*
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index bbfa88d..d51d75d 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -44,7 +44,6 @@
#include "ubi-media.h"
#include "scan.h"
-#include "debug.h"
/* Maximum number of supported UBI devices */
#define UBI_MAX_DEVICES 32
@@ -392,6 +391,8 @@ struct ubi_wl_entry;
* @peb_buf2: another buffer of PEB size used for different purposes
* @buf_mutex: protects @peb_buf1 and @peb_buf2
* @ckvol_mutex: serializes static volume checking when opening
+ *
+ * @dbg: debugging information for this UBI device
*/
struct ubi_device {
struct cdev cdev;
@@ -474,8 +475,12 @@ struct ubi_device {
void *peb_buf2;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+
+ struct ubi_debug_info *dbg;
};
+#include "debug.h"
+
extern struct kmem_cache *ubi_wl_entry_slab;
extern const struct file_operations ubi_ctrl_cdev_operations;
extern const struct file_operations ubi_cdev_operations;
@@ -664,6 +669,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
if (!ubi->ro_mode) {
ubi->ro_mode = 1;
ubi_warn("switch to read-only mode");
+ ubi_dbg_dump_stack();
}
}
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 425bf5a..068a246 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -135,6 +135,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
ubi_assert(!vol->updating && !vol->changing_leb);
vol->updating = 1;
+ vol->upd_buf = vmalloc(ubi->leb_size);
+ if (!vol->upd_buf)
+ return -ENOMEM;
+
err = set_update_marker(ubi, vol);
if (err)
return err;
@@ -154,14 +158,12 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
err = clear_update_marker(ubi, vol, 0);
if (err)
return err;
+
+ vfree(vol->upd_buf);
vol->updating = 0;
return 0;
}
- vol->upd_buf = vmalloc(ubi->leb_size);
- if (!vol->upd_buf)
- return -ENOMEM;
-
vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
vol->usable_leb_size);
vol->upd_bytes = bytes;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 366eb70..863835f 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -26,6 +26,7 @@
#include <linux/err.h>
#include <linux/math64.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG
@@ -871,7 +872,7 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
{
int i, err = 0;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
for (i = 0; i < ubi->vtbl_slots; i++) {
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 326bd93..95b29f5 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -306,9 +306,8 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
int copy, void *vtbl)
{
int err, tries = 0;
- static struct ubi_vid_hdr *vid_hdr;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *new_seb, *old_seb = NULL;
+ struct ubi_vid_hdr *vid_hdr;
+ struct ubi_scan_leb *new_seb;
ubi_msg("create volume table (copy #%d)", copy + 1);
@@ -316,15 +315,6 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
if (!vid_hdr)
return -ENOMEM;
- /*
- * Check if there is a logical eraseblock which would have to contain
- * this volume table copy was found during scanning. It has to be wiped
- * out.
- */
- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
- if (sv)
- old_seb = ubi_scan_find_seb(sv, copy);
-
retry:
new_seb = ubi_scan_get_free_peb(ubi, si);
if (IS_ERR(new_seb)) {
@@ -351,8 +341,8 @@ retry:
goto write_error;
/*
- * And add it to the scanning information. Don't delete the old
- * @old_seb as it will be deleted and freed in 'ubi_scan_add_used()'.
+ * And add it to the scanning information. Don't delete the old version
+ * of this LEB as it will be deleted and freed in 'ubi_scan_add_used()'.
*/
err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
vid_hdr, 0);
@@ -433,7 +423,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
ubi->vtbl_size);
- if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
+ if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
/*
* Scrub the PEB later. Note, -EBADMSG indicates an
* uncorrectable ECC error, but we have our own CRC and
@@ -876,7 +866,7 @@ out_free:
*/
static void paranoid_vtbl_check(const struct ubi_device *ubi)
{
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return;
if (vtbl_check(ubi, ubi->vtbl)) {
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 25f18e9..422e5be 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1,4 +1,5 @@
/*
+ * @ubi: UBI device description object
* Copyright (c) International Business Machines Corp., 2006
*
* This program is free software; you can redistribute it and/or modify
@@ -163,12 +164,14 @@ struct ubi_work {
#ifdef CONFIG_MTD_UBI_DEBUG
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
+static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e,
struct rb_root *root);
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e);
+static int paranoid_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e);
#else
#define paranoid_check_ec(ubi, pnum, ec) 0
-#define paranoid_check_in_wl_tree(e, root)
+#define paranoid_check_in_wl_tree(ubi, e, root)
#define paranoid_check_in_pq(ubi, e) 0
#endif
@@ -447,7 +450,7 @@ retry:
BUG();
}
- paranoid_check_in_wl_tree(e, &ubi->free);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->free);
/*
* Move the physical eraseblock to the protection queue where it will
@@ -611,7 +614,7 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
list_add_tail(&wrk->list, &ubi->works);
ubi_assert(ubi->works_count >= 0);
ubi->works_count += 1;
- if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled())
+ if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
wake_up_process(ubi->bgt_thread);
spin_unlock(&ubi->wl_lock);
}
@@ -662,7 +665,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
int cancel)
{
int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
- int vol_id = -1, uninitialized_var(lnum);
+ int vol_id = -1, lnum = -1;
struct ubi_wl_entry *e1, *e2;
struct ubi_vid_hdr *vid_hdr;
@@ -710,7 +713,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
e1->ec, e2->ec);
goto out_cancel;
}
- paranoid_check_in_wl_tree(e1, &ubi->used);
+ paranoid_check_in_wl_tree(ubi, e1, &ubi->used);
rb_erase(&e1->u.rb, &ubi->used);
dbg_wl("move PEB %d EC %d to PEB %d EC %d",
e1->pnum, e1->ec, e2->pnum, e2->ec);
@@ -719,12 +722,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
scrubbing = 1;
e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- paranoid_check_in_wl_tree(e1, &ubi->scrub);
+ paranoid_check_in_wl_tree(ubi, e1, &ubi->scrub);
rb_erase(&e1->u.rb, &ubi->scrub);
dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
}
- paranoid_check_in_wl_tree(e2, &ubi->free);
+ paranoid_check_in_wl_tree(ubi, e2, &ubi->free);
rb_erase(&e2->u.rb, &ubi->free);
ubi->move_from = e1;
ubi->move_to = e2;
@@ -1171,13 +1174,13 @@ retry:
return 0;
} else {
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(e, &ubi->used);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else if (in_wl_tree(e, &ubi->scrub)) {
- paranoid_check_in_wl_tree(e, &ubi->scrub);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->scrub);
rb_erase(&e->u.rb, &ubi->scrub);
} else if (in_wl_tree(e, &ubi->erroneous)) {
- paranoid_check_in_wl_tree(e, &ubi->erroneous);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->erroneous);
rb_erase(&e->u.rb, &ubi->erroneous);
ubi->erroneous_peb_count -= 1;
ubi_assert(ubi->erroneous_peb_count >= 0);
@@ -1244,7 +1247,7 @@ retry:
}
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(e, &ubi->used);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else {
int err;
@@ -1366,7 +1369,7 @@ int ubi_thread(void *u)
spin_lock(&ubi->wl_lock);
if (list_empty(&ubi->works) || ubi->ro_mode ||
- !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) {
+ !ubi->thread_enabled || ubi_dbg_is_bgt_disabled(ubi)) {
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock(&ubi->wl_lock);
schedule();
@@ -1581,7 +1584,7 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
long long read_ec;
struct ubi_ec_hdr *ec_hdr;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1611,16 +1614,18 @@ out_free:
/**
* paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
+ * @ubi: UBI device description object
* @e: the wear-leveling entry to check
* @root: the root of the tree
*
* This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
* is not.
*/
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
+static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e,
struct rb_root *root)
{
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
if (in_wl_tree(e, root))
@@ -1640,12 +1645,13 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
*
* This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
*/
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
+static int paranoid_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e)
{
struct ubi_wl_entry *p;
int i;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 748c9f5..9abd4eb 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -264,7 +264,7 @@ static const struct net_device_ops cops_netdev_ops = {
.ndo_start_xmit = cops_send_packet,
.ndo_tx_timeout = cops_timeout,
.ndo_do_ioctl = cops_ioctl,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
};
/*
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index e69eead..6057b30 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -652,9 +652,9 @@ static int do_write(struct net_device *dev, void *cbuf, int cbuflen,
int ret;
if(i) {
- qels[i].cbuf = (unsigned char *) cbuf;
+ qels[i].cbuf = cbuf;
qels[i].cbuflen = cbuflen;
- qels[i].dbuf = (unsigned char *) dbuf;
+ qels[i].dbuf = dbuf;
qels[i].dbuflen = dbuflen;
qels[i].QWrite = 1;
qels[i].mailbox = i; /* this should be initted rather */
@@ -676,9 +676,9 @@ static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
int ret;
if(i) {
- qels[i].cbuf = (unsigned char *) cbuf;
+ qels[i].cbuf = cbuf;
qels[i].cbuflen = cbuflen;
- qels[i].dbuf = (unsigned char *) dbuf;
+ qels[i].dbuf = dbuf;
qels[i].dbuflen = dbuflen;
qels[i].QWrite = 0;
qels[i].mailbox = i; /* this should be initted rather */
@@ -1014,7 +1014,7 @@ static int __init ltpc_probe_dma(int base, int dma)
static const struct net_device_ops ltpc_netdev = {
.ndo_start_xmit = ltpc_xmit,
.ndo_do_ioctl = ltpc_ioctl,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
};
struct net_device * __init ltpc_probe(void)
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 3b2f7f1..84fb634 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig ARCNET
- depends on NETDEVICES && (ISA || PCI)
+ depends on NETDEVICES && (ISA || PCI || PCMCIA)
tristate "ARCnet support"
---help---
If you have a network card of this type, say Y and check out the
@@ -123,4 +123,14 @@ config ARCNET_COM20020_PCI
tristate "Support for COM20020 on PCI"
depends on ARCNET_COM20020 && PCI
+config ARCNET_COM20020_CS
+ tristate "COM20020 ARCnet PCMCIA support"
+ depends on ARCNET_COM20020 && PCMCIA
+ help
+ Say Y here if you intend to attach this type of ARCnet PCMCIA card
+ to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called com20020_cs. If unsure, say N.
+
endif # ARCNET
diff --git a/drivers/net/arcnet/Makefile b/drivers/net/arcnet/Makefile
index 5861af5..5ce8ee6 100644
--- a/drivers/net/arcnet/Makefile
+++ b/drivers/net/arcnet/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
obj-$(CONFIG_ARCNET_COM20020) += com20020.o
obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
+obj-$(CONFIG_ARCNET_COM20020_CS) += com20020_cs.o
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 9efbbba..25197b6 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -32,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/arcdevice.h>
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 3727282..45c61a2 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bootmem.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 48a1dbf..d427493 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -34,6 +34,7 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index c9e4594..7b96c5f 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
@@ -153,7 +154,7 @@ const struct net_device_ops com20020_netdev_ops = {
.ndo_stop = arcnet_close,
.ndo_start_xmit = arcnet_send_packet,
.ndo_tx_timeout = arcnet_timeout,
- .ndo_set_multicast_list = com20020_set_mc_list,
+ .ndo_set_rx_mode = com20020_set_mc_list,
};
/* Set up the struct net_device associated with this card. Called after
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index eb27976..487d780 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -33,6 +33,7 @@
#include <linux/netdevice.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/arcdevice.h>
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index f3b46f7..b80fbe4 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c7537abc..aaa7999 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -262,7 +262,7 @@ static inline u32 __get_agg_selection_mode(struct port *port)
if (bond == NULL)
return BOND_AD_STABLE;
- return BOND_AD_INFO(bond).agg_select_mode;
+ return bond->params.ad_select;
}
/**
@@ -1135,13 +1135,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
__record_pdu(lacpdu, port);
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
- // verify that if the aggregator is enabled, the port is enabled too.
- //(because if the link goes down for a short time, the 802.3ad will not
- // catch it, and the port will continue to be disabled)
- if (port->aggregator
- && port->aggregator->is_active
- && !__port_is_enabled(port))
- __enable_port(port);
break;
default: //to silence the compiler
break;
@@ -1859,28 +1852,23 @@ static void ad_marker_response_received(struct bond_marker *marker,
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
{
BOND_AD_INFO(bond).agg_select_timer = timeout;
- BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
}
-static u16 aggregator_identifier;
-
/**
* bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
* @bond: bonding struct to work on
* @tick_resolution: tick duration (millisecond resolution)
- * @lacp_fast: boolean. whether fast periodic should be used
*
* Can be called only after the mac address of the bond is set.
*/
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
{
// check that the bond is not initialized yet
if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
bond->dev->dev_addr)) {
- aggregator_identifier = 0;
+ BOND_AD_INFO(bond).aggregator_identifier = 0;
- BOND_AD_INFO(bond).lacp_fast = lacp_fast;
BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@ -1918,7 +1906,7 @@ int bond_3ad_bind_slave(struct slave *slave)
// port initialization
port = &(SLAVE_AD_INFO(slave).port);
- ad_initialize_port(port, BOND_AD_INFO(bond).lacp_fast);
+ ad_initialize_port(port, bond->params.lacp_fast);
port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave).id;
@@ -1951,7 +1939,7 @@ int bond_3ad_bind_slave(struct slave *slave)
ad_initialize_agg(aggregator);
aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
- aggregator->aggregator_identifier = (++aggregator_identifier);
+ aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier;
aggregator->slave = slave;
aggregator->is_active = 0;
aggregator->num_of_ports = 0;
@@ -2120,9 +2108,6 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
-
//check if there are any slaves
if (bond->slave_cnt == 0)
goto re_arm;
@@ -2172,7 +2157,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
re_arm:
queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
-out:
+
read_unlock(&bond->lock);
}
@@ -2345,8 +2330,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
*/
int bond_3ad_set_carrier(struct bonding *bond)
{
- if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) {
- if (!netif_carrier_ok(bond->dev)) {
+ struct aggregator *active;
+
+ active = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+ if (active) {
+ /* are enough slaves available to consider link up? */
+ if (active->num_of_ports < bond->params.min_links) {
+ if (netif_carrier_ok(bond->dev)) {
+ netif_carrier_off(bond->dev);
+ return 1;
+ }
+ } else if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
return 1;
}
@@ -2473,3 +2467,34 @@ void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
read_unlock(&bond->lock);
}
+
+/*
+ * When modify lacp_rate parameter via sysfs,
+ * update actor_oper_port_state of each port.
+ *
+ * Hold slave->state_machine_lock,
+ * so we can modify port->actor_oper_port_state,
+ * no matter bond is up or down.
+ */
+void bond_3ad_update_lacp_rate(struct bonding *bond)
+{
+ int i;
+ struct slave *slave;
+ struct port *port = NULL;
+ int lacp_fast;
+
+ read_lock(&bond->lock);
+ lacp_fast = bond->params.lacp_fast;
+
+ bond_for_each_slave(bond, slave, i) {
+ port = &(SLAVE_AD_INFO(slave).port);
+ __get_state_machine_lock(port);
+ if (lacp_fast)
+ port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
+ else
+ port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT;
+ __release_state_machine_lock(port);
+ }
+
+ read_unlock(&bond->lock);
+}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 0ee3f16..20d9c78 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -253,11 +253,7 @@ struct ad_system {
struct ad_bond_info {
struct ad_system system; /* 802.3ad system structure */
u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes
- u32 agg_select_mode; // Mode of selection of active aggregator(bandwidth/count)
- int lacp_fast; /* whether fast periodic tx should be
- * requested
- */
- struct timer_list ad_timer;
+ u16 aggregator_identifier;
};
struct ad_slave_info {
@@ -269,7 +265,7 @@ struct ad_slave_info {
};
// ================= AD Exported functions to the main bonding code ==================
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
@@ -282,5 +278,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
+void bond_3ad_update_lacp_rate(struct bonding *bond);
#endif //__BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 5e725e0..30431d8 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -635,7 +635,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
client_info->ntt = 0;
}
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
if (!vlan_get_tag(skb, &client_info->vlan_id))
client_info->tag = 1;
}
@@ -847,7 +847,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
skb->priority = TC_PRIO_CONTROL;
skb->dev = slave->dev;
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
struct vlan_entry *vlan;
vlan = bond_next_vlan(bond,
@@ -1337,10 +1337,6 @@ void bond_alb_monitor(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers) {
- goto out;
- }
-
if (bond->slave_cnt == 0) {
bond_info->tx_rebalance_counter = 0;
bond_info->lp_counter = 0;
@@ -1395,10 +1391,13 @@ void bond_alb_monitor(struct work_struct *work)
/*
* dev_set_promiscuity requires rtnl and
- * nothing else.
+ * nothing else. Avoid race with bond_close.
*/
read_unlock(&bond->lock);
- rtnl_lock();
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ goto re_arm;
+ }
bond_info->rlb_promisc_timeout_counter = 0;
@@ -1435,7 +1434,7 @@ void bond_alb_monitor(struct work_struct *work)
re_arm:
queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
-out:
+
read_unlock(&bond->lock);
}
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index 3680aa2..2cf084e 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -6,7 +6,7 @@
#include "bonding.h"
#include "bond_alb.h"
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS)
#include <linux/debugfs.h>
#include <linux/seq_file.h>
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
index 84fbd4e..027a0ee 100644
--- a/drivers/net/bonding/bond_ipv6.c
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -183,10 +183,10 @@ static int bond_inet6addr_event(struct notifier_block *this,
}
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- if (!bond->vlgrp)
- continue;
- vlan_dev = vlan_group_get_device(bond->vlgrp,
- vlan->vlan_id);
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
+ rcu_read_unlock();
if (vlan_dev == event_dev) {
switch (event) {
case NETDEV_UP:
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f1b566f..9145834c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -99,6 +99,7 @@ static char *mode;
static char *primary;
static char *primary_reselect;
static char *lacp_rate;
+static int min_links;
static char *ad_select;
static char *xmit_hash_policy;
static int arp_interval = BOND_LINK_ARP_INTERV;
@@ -151,6 +152,9 @@ module_param(ad_select, charp, 0);
MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; "
"0 for stable (default), 1 for bandwidth, "
"2 for count");
+module_param(min_links, int, 0);
+MODULE_PARM_DESC(min_links, "Minimum number of available links before turning on carrier");
+
module_param(xmit_hash_policy, charp, 0);
MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; "
"0 for layer 2 (default), 1 for layer 3+4, "
@@ -330,16 +334,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
kfree(vlan);
- if (list_empty(&bond->vlan_list) &&
- (bond->slave_cnt == 0)) {
- /* Last VLAN removed and no slaves, so
- * restore block on adding VLANs. This will
- * be removed once new slaves that are not
- * VLAN challenged will be added.
- */
- bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
- }
-
res = 0;
goto out;
}
@@ -400,7 +394,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
struct net_device *slave_dev)
{
skb->dev = slave_dev;
- skb->priority = 1;
BUILD_BUG_ON(sizeof(skb->queue_mapping) !=
sizeof(qdisc_skb_cb(skb)->bond_queue_mapping));
@@ -415,9 +408,8 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
}
/*
- * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
- * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
- * lock because:
+ * In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
+ * We don't protect the slave list iteration with a lock because:
* a. This operation is performed in IOCTL context,
* b. The operation is protected by the RTNL semaphore in the 8021q code,
* c. Holding a lock with BH disabled while directly calling a base driver
@@ -433,33 +425,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
*/
/**
- * bond_vlan_rx_register - Propagates registration to slaves
- * @bond_dev: bonding net device that got called
- * @grp: vlan group being registered
- */
-static void bond_vlan_rx_register(struct net_device *bond_dev,
- struct vlan_group *grp)
-{
- struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave;
- int i;
-
- write_lock_bh(&bond->lock);
- bond->vlgrp = grp;
- write_unlock_bh(&bond->lock);
-
- bond_for_each_slave(bond, slave, i) {
- struct net_device *slave_dev = slave->dev;
- const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-
- if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_ops->ndo_vlan_rx_register) {
- slave_ops->ndo_vlan_rx_register(slave_dev, grp);
- }
- }
-}
-
-/**
* bond_vlan_rx_add_vid - Propagates adding an id to slaves
* @bond_dev: bonding net device that got called
* @vid: vlan id being added
@@ -496,7 +461,6 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
- struct net_device *vlan_dev;
int i, res;
bond_for_each_slave(bond, slave, i) {
@@ -505,12 +469,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
slave_ops->ndo_vlan_rx_kill_vid) {
- /* Save and then restore vlan_dev in the grp array,
- * since the slave's driver might clear it.
- */
- vlan_dev = vlan_group_get_device(bond->vlgrp, vid);
slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid);
- vlan_group_set_device(bond->vlgrp, vid, vlan_dev);
}
}
@@ -526,13 +485,6 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla
struct vlan_entry *vlan;
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
- if (!bond->vlgrp)
- return;
-
- if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_ops->ndo_vlan_rx_register)
- slave_ops->ndo_vlan_rx_register(slave_dev, bond->vlgrp);
-
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
!(slave_ops->ndo_vlan_rx_add_vid))
return;
@@ -546,30 +498,16 @@ static void bond_del_vlans_from_slave(struct bonding *bond,
{
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
struct vlan_entry *vlan;
- struct net_device *vlan_dev;
-
- if (!bond->vlgrp)
- return;
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
!(slave_ops->ndo_vlan_rx_kill_vid))
- goto unreg;
+ return;
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
if (!vlan->vlan_id)
continue;
- /* Save and then restore vlan_dev in the grp array,
- * since the slave's driver might clear it.
- */
- vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
- vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev);
}
-
-unreg:
- if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_ops->ndo_vlan_rx_register)
- slave_ops->ndo_vlan_rx_register(slave_dev, NULL);
}
/*------------------------------- Link status -------------------------------*/
@@ -613,39 +551,28 @@ down:
/*
* Get link speed and duplex from the slave's base driver
* using ethtool. If for some reason the call fails or the
- * values are invalid, fake speed and duplex to 100/Full
+ * values are invalid, set speed and duplex to -1,
* and return error.
*/
static int bond_update_speed_duplex(struct slave *slave)
{
struct net_device *slave_dev = slave->dev;
- struct ethtool_cmd etool = { .cmd = ETHTOOL_GSET };
+ struct ethtool_cmd ecmd;
u32 slave_speed;
int res;
- /* Fake speed and duplex */
- slave->speed = SPEED_100;
- slave->duplex = DUPLEX_FULL;
-
- if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings)
- return -1;
+ slave->speed = SPEED_UNKNOWN;
+ slave->duplex = DUPLEX_UNKNOWN;
- res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+ res = __ethtool_get_settings(slave_dev, &ecmd);
if (res < 0)
return -1;
- slave_speed = ethtool_cmd_speed(&etool);
- switch (slave_speed) {
- case SPEED_10:
- case SPEED_100:
- case SPEED_1000:
- case SPEED_10000:
- break;
- default:
+ slave_speed = ethtool_cmd_speed(&ecmd);
+ if (slave_speed == 0 || slave_speed == ((__u32) -1))
return -1;
- }
- switch (etool.duplex) {
+ switch (ecmd.duplex) {
case DUPLEX_FULL:
case DUPLEX_HALF:
break;
@@ -654,7 +581,7 @@ static int bond_update_speed_duplex(struct slave *slave)
}
slave->speed = slave_speed;
- slave->duplex = etool.duplex;
+ slave->duplex = ecmd.duplex;
return 0;
}
@@ -850,13 +777,13 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
__bond_resend_igmp_join_requests(bond->dev);
/* rejoin all groups on vlan devices */
- if (bond->vlgrp) {
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- vlan_dev = vlan_group_get_device(bond->vlgrp,
- vlan->vlan_id);
- if (vlan_dev)
- __bond_resend_igmp_join_requests(vlan_dev);
- }
+ list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
+ rcu_read_unlock();
+ if (vlan_dev)
+ __bond_resend_igmp_join_requests(vlan_dev);
}
if (--bond->igmp_retrans > 0)
@@ -934,6 +861,23 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
}
}
+static struct slave *bond_get_old_active(struct bonding *bond,
+ struct slave *new_active)
+{
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i) {
+ if (slave == new_active)
+ continue;
+
+ if (!compare_ether_addr(bond->dev->dev_addr, slave->dev->dev_addr))
+ return slave;
+ }
+
+ return NULL;
+}
+
/*
* bond_do_fail_over_mac
*
@@ -971,6 +915,9 @@ static void bond_do_fail_over_mac(struct bonding *bond,
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
+ if (!old_active)
+ old_active = bond_get_old_active(bond, new_active);
+
if (old_active) {
memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN);
memcpy(saddr.sa_data, old_active->dev->dev_addr,
@@ -1581,7 +1528,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* no need to lock since we're protected by rtnl_lock */
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
bond_dev->name, slave_dev->name, bond_dev->name);
return -EPERM;
@@ -1788,6 +1735,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_compute_features(bond);
+ bond_update_speed_duplex(new_slave);
+
read_lock(&bond->lock);
new_slave->last_arp_rx = jiffies;
@@ -1831,17 +1780,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
new_slave->link = BOND_LINK_DOWN;
}
- if (bond_update_speed_duplex(new_slave) &&
- (new_slave->link != BOND_LINK_DOWN)) {
- pr_warning("%s: Warning: failed to get speed and duplex from %s, assumed to be 100Mb/sec and Full.\n",
- bond_dev->name, new_slave->dev->name);
-
- if (bond->params.mode == BOND_MODE_8023AD) {
- pr_warning("%s: Warning: Operation of 802.3ad mode requires ETHTOOL support in base driver for proper aggregator selection.\n",
- bond_dev->name);
- }
- }
-
if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
/* if there is a primary slave, remember it */
if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
@@ -1869,8 +1807,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* Initialize AD with the number of times that the AD timer is called in 1 second
* can be called only after the mac address of the bond is set
*/
- bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
- bond->params.lacp_fast);
+ bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
} else {
SLAVE_AD_INFO(new_slave).id =
SLAVE_AD_INFO(new_slave->prev).id + 1;
@@ -2098,7 +2035,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
*/
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
bond_dev->name, bond_dev->name);
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
@@ -2286,7 +2223,7 @@ static int bond_release_all(struct net_device *bond_dev)
*/
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
bond_dev->name, bond_dev->name);
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
@@ -2527,8 +2464,6 @@ static void bond_miimon_commit(struct bonding *bond)
bond_set_backup_slave(slave);
}
- bond_update_speed_duplex(slave);
-
pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
bond->dev->name, slave->dev->name,
slave->speed, slave->duplex ? "full" : "half");
@@ -2607,10 +2542,11 @@ void bond_mii_monitor(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
mii_work.work);
bool should_notify_peers = false;
+ unsigned long delay;
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
+
+ delay = msecs_to_jiffies(bond->params.miimon);
if (bond->slave_cnt == 0)
goto re_arm;
@@ -2619,7 +2555,15 @@ void bond_mii_monitor(struct work_struct *work)
if (bond_miimon_inspect(bond)) {
read_unlock(&bond->lock);
- rtnl_lock();
+
+ /* Race avoidance with bond_close cancel of workqueue */
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ delay = 1;
+ should_notify_peers = false;
+ goto re_arm;
+ }
+
read_lock(&bond->lock);
bond_miimon_commit(bond);
@@ -2631,42 +2575,22 @@ void bond_mii_monitor(struct work_struct *work)
re_arm:
if (bond->params.miimon)
- queue_delayed_work(bond->wq, &bond->mii_work,
- msecs_to_jiffies(bond->params.miimon));
-out:
+ queue_delayed_work(bond->wq, &bond->mii_work, delay);
+
read_unlock(&bond->lock);
if (should_notify_peers) {
- rtnl_lock();
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ bond->send_peer_notif++;
+ read_unlock(&bond->lock);
+ return;
+ }
netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
rtnl_unlock();
}
}
-static __be32 bond_glean_dev_ip(struct net_device *dev)
-{
- struct in_device *idev;
- struct in_ifaddr *ifa;
- __be32 addr = 0;
-
- if (!dev)
- return 0;
-
- rcu_read_lock();
- idev = __in_dev_get_rcu(dev);
- if (!idev)
- goto out;
-
- ifa = idev->ifa_list;
- if (!ifa)
- goto out;
-
- addr = ifa->ifa_local;
-out:
- rcu_read_unlock();
- return addr;
-}
-
static int bond_has_this_ip(struct bonding *bond, __be32 ip)
{
struct vlan_entry *vlan;
@@ -2724,7 +2648,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (!targets[i])
break;
pr_debug("basa: target %x\n", targets[i]);
- if (!bond->vlgrp) {
+ if (!bond_vlan_used(bond)) {
pr_debug("basa: empty vlan: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
@@ -2759,7 +2683,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
vlan_id = 0;
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
+ rcu_read_unlock();
if (vlan_dev == rt->dst.dev) {
vlan_id = vlan->vlan_id;
pr_debug("basa: vlan match on %s %d\n",
@@ -2876,9 +2803,6 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
- if (bond->kill_timers)
- goto out;
-
if (bond->slave_cnt == 0)
goto re_arm;
@@ -2977,7 +2901,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
re_arm:
if (bond->params.arp_interval)
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-out:
+
read_unlock(&bond->lock);
}
@@ -3222,9 +3146,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
-
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
if (bond->slave_cnt == 0)
@@ -3234,7 +3155,15 @@ void bond_activebackup_arp_mon(struct work_struct *work)
if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
read_unlock(&bond->lock);
- rtnl_lock();
+
+ /* Race avoidance with bond_close flush of workqueue */
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ delta_in_ticks = 1;
+ should_notify_peers = false;
+ goto re_arm;
+ }
+
read_lock(&bond->lock);
bond_ab_arp_commit(bond, delta_in_ticks);
@@ -3249,11 +3178,16 @@ void bond_activebackup_arp_mon(struct work_struct *work)
re_arm:
if (bond->params.arp_interval)
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-out:
+
read_unlock(&bond->lock);
if (should_notify_peers) {
- rtnl_lock();
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ bond->send_peer_notif++;
+ read_unlock(&bond->lock);
+ return;
+ }
netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
rtnl_unlock();
}
@@ -3282,6 +3216,12 @@ static int bond_master_netdev_event(unsigned long event,
switch (event) {
case NETDEV_CHANGENAME:
return bond_event_changename(event_bond);
+ case NETDEV_UNREGISTER:
+ bond_remove_proc_entry(event_bond);
+ break;
+ case NETDEV_REGISTER:
+ bond_create_proc_entry(event_bond);
+ break;
default:
break;
}
@@ -3294,6 +3234,7 @@ static int bond_slave_netdev_event(unsigned long event,
{
struct net_device *bond_dev = slave_dev->master;
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave = NULL;
switch (event) {
case NETDEV_UNREGISTER:
@@ -3304,20 +3245,16 @@ static int bond_slave_netdev_event(unsigned long event,
bond_release(bond_dev, slave_dev);
}
break;
+ case NETDEV_UP:
case NETDEV_CHANGE:
- if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) {
- struct slave *slave;
-
- slave = bond_get_slave_by_dev(bond, slave_dev);
- if (slave) {
- u32 old_speed = slave->speed;
- u8 old_duplex = slave->duplex;
-
- bond_update_speed_duplex(slave);
+ slave = bond_get_slave_by_dev(bond, slave_dev);
+ if (slave) {
+ u32 old_speed = slave->speed;
+ u8 old_duplex = slave->duplex;
- if (bond_is_lb(bond))
- break;
+ bond_update_speed_duplex(slave);
+ if (bond->params.mode == BOND_MODE_8023AD) {
if (old_speed != slave->speed)
bond_3ad_adapter_speed_changed(slave);
if (old_duplex != slave->duplex)
@@ -3409,6 +3346,10 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
struct bonding *bond;
struct vlan_entry *vlan;
+ /* we only care about primary address */
+ if(ifa->ifa_flags & IFA_F_SECONDARY)
+ return NOTIFY_DONE;
+
list_for_each_entry(bond, &bn->dev_list, bond_list) {
if (bond->dev == event_dev) {
switch (event) {
@@ -3416,7 +3357,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
bond->master_ip = ifa->ifa_local;
return NOTIFY_OK;
case NETDEV_DOWN:
- bond->master_ip = bond_glean_dev_ip(bond->dev);
+ bond->master_ip = 0;
return NOTIFY_OK;
default:
return NOTIFY_DONE;
@@ -3424,17 +3365,15 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
}
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- if (!bond->vlgrp)
- continue;
- vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
if (vlan_dev == event_dev) {
switch (event) {
case NETDEV_UP:
vlan->vlan_ip = ifa->ifa_local;
return NOTIFY_OK;
case NETDEV_DOWN:
- vlan->vlan_ip =
- bond_glean_dev_ip(vlan_dev);
+ vlan->vlan_ip = 0;
return NOTIFY_OK;
default:
return NOTIFY_DONE;
@@ -3485,7 +3424,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
int layer4_xor = 0;
if (skb->protocol == htons(ETH_P_IP)) {
- if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
+ if (!ip_is_fragment(iph) &&
(iph->protocol == IPPROTO_TCP ||
iph->protocol == IPPROTO_UDP)) {
layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
@@ -3510,47 +3449,71 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
/*-------------------------- Device entry points ----------------------------*/
+static void bond_work_init_all(struct bonding *bond)
+{
+ INIT_DELAYED_WORK(&bond->mcast_work,
+ bond_resend_igmp_join_requests_delayed);
+ INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
+ INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon);
+ INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
+}
+
+static void bond_work_cancel_all(struct bonding *bond)
+{
+ cancel_delayed_work_sync(&bond->mii_work);
+ cancel_delayed_work_sync(&bond->arp_work);
+ cancel_delayed_work_sync(&bond->alb_work);
+ cancel_delayed_work_sync(&bond->ad_work);
+ cancel_delayed_work_sync(&bond->mcast_work);
+}
+
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ int i;
- bond->kill_timers = 0;
+ /* reset slave->backup and slave->inactive */
+ read_lock(&bond->lock);
+ if (bond->slave_cnt > 0) {
+ read_lock(&bond->curr_slave_lock);
+ bond_for_each_slave(bond, slave, i) {
+ if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ && (slave != bond->curr_active_slave)) {
+ bond_set_slave_inactive_flags(slave);
+ } else {
+ bond_set_slave_active_flags(slave);
+ }
+ }
+ read_unlock(&bond->curr_slave_lock);
+ }
+ read_unlock(&bond->lock);
- INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
+ bond_work_init_all(bond);
if (bond_is_lb(bond)) {
/* bond_alb_initialize must be called before the timer
* is started.
*/
- if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
- /* something went wrong - fail the open operation */
+ if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB)))
return -ENOMEM;
- }
-
- INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
queue_delayed_work(bond->wq, &bond->alb_work, 0);
}
- if (bond->params.miimon) { /* link check interval, in milliseconds. */
- INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ if (bond->params.miimon) /* link check interval, in milliseconds. */
queue_delayed_work(bond->wq, &bond->mii_work, 0);
- }
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_activebackup_arp_mon);
- else
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_loadbalance_arp_mon);
-
queue_delayed_work(bond->wq, &bond->arp_work, 0);
if (bond->params.arp_validate)
bond->recv_probe = bond_arp_rcv;
}
if (bond->params.mode == BOND_MODE_8023AD) {
- INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
bond->recv_probe = bond_3ad_lacpdu_recv;
@@ -3565,37 +3528,10 @@ static int bond_close(struct net_device *bond_dev)
struct bonding *bond = netdev_priv(bond_dev);
write_lock_bh(&bond->lock);
-
bond->send_peer_notif = 0;
-
- /* signal timers not to re-arm */
- bond->kill_timers = 1;
-
write_unlock_bh(&bond->lock);
- if (bond->params.miimon) { /* link check interval, in milliseconds. */
- cancel_delayed_work(&bond->mii_work);
- }
-
- if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- cancel_delayed_work(&bond->arp_work);
- }
-
- switch (bond->params.mode) {
- case BOND_MODE_8023AD:
- cancel_delayed_work(&bond->ad_work);
- break;
- case BOND_MODE_TLB:
- case BOND_MODE_ALB:
- cancel_delayed_work(&bond->alb_work);
- break;
- default:
- break;
- }
-
- if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work(&bond->mcast_work);
-
+ bond_work_cancel_all(bond);
if (bond_is_lb(bond)) {
/* Must be called only after all
* slaves have been released
@@ -3780,44 +3716,27 @@ static bool bond_addr_in_mc_list(unsigned char *addr,
return false;
}
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_change_rx_flags(struct net_device *bond_dev, int change)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct netdev_hw_addr *ha;
- bool found;
-
- /*
- * Do promisc before checking multicast_mode
- */
- if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
- /*
- * FIXME: Need to handle the error when one of the multi-slaves
- * encounters error.
- */
- bond_set_promiscuity(bond, 1);
+ if (change & IFF_PROMISC)
+ bond_set_promiscuity(bond,
+ bond_dev->flags & IFF_PROMISC ? 1 : -1);
- if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
- bond_set_promiscuity(bond, -1);
-
-
- /* set allmulti flag to slaves */
- if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
- /*
- * FIXME: Need to handle the error when one of the multi-slaves
- * encounters error.
- */
- bond_set_allmulti(bond, 1);
-
-
- if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
- bond_set_allmulti(bond, -1);
+ if (change & IFF_ALLMULTI)
+ bond_set_allmulti(bond,
+ bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
+static void bond_set_multicast_list(struct net_device *bond_dev)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct netdev_hw_addr *ha;
+ bool found;
read_lock(&bond->lock);
- bond->flags = bond_dev->flags;
-
/* looking for addresses to add to slaves' mc list */
netdev_for_each_mc_addr(ha, bond_dev) {
found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
@@ -4376,12 +4295,12 @@ static const struct net_device_ops bond_netdev_ops = {
.ndo_select_queue = bond_select_queue,
.ndo_get_stats64 = bond_get_stats,
.ndo_do_ioctl = bond_do_ioctl,
- .ndo_set_multicast_list = bond_set_multicast_list,
+ .ndo_change_rx_flags = bond_change_rx_flags,
+ .ndo_set_rx_mode = bond_set_multicast_list,
.ndo_change_mtu = bond_change_mtu,
- .ndo_set_mac_address = bond_set_mac_address,
+ .ndo_set_mac_address = bond_set_mac_address,
.ndo_neigh_setup = bond_neigh_setup,
- .ndo_vlan_rx_register = bond_vlan_rx_register,
- .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
+ .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_netpoll_setup = bond_netpoll_setup,
@@ -4456,30 +4375,6 @@ static void bond_setup(struct net_device *bond_dev)
bond_dev->features |= bond_dev->hw_features;
}
-static void bond_work_cancel_all(struct bonding *bond)
-{
- write_lock_bh(&bond->lock);
- bond->kill_timers = 1;
- write_unlock_bh(&bond->lock);
-
- if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
- cancel_delayed_work(&bond->mii_work);
-
- if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
- cancel_delayed_work(&bond->arp_work);
-
- if (bond->params.mode == BOND_MODE_ALB &&
- delayed_work_pending(&bond->alb_work))
- cancel_delayed_work(&bond->alb_work);
-
- if (bond->params.mode == BOND_MODE_8023AD &&
- delayed_work_pending(&bond->ad_work))
- cancel_delayed_work(&bond->ad_work);
-
- if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work(&bond->mcast_work);
-}
-
/*
* Destroy a bonding device.
* Must be under rtnl_lock when this function is called.
@@ -4498,8 +4393,6 @@ static void bond_uninit(struct net_device *bond_dev)
bond_work_cancel_all(bond);
- bond_remove_proc_entry(bond);
-
bond_debug_unregister(bond);
__hw_addr_flush(&bond->mc_list);
@@ -4788,7 +4681,7 @@ static int bond_check_params(struct bond_params *params)
/* miimon and arp_interval not set, we need one so things
* work as expected, see bonding.txt for details
*/
- pr_warning("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
+ pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
}
if (primary && !USES_PRIMARY(bond_mode)) {
@@ -4845,6 +4738,7 @@ static int bond_check_params(struct bond_params *params)
params->tx_queues = tx_queues;
params->all_slaves_active = all_slaves_active;
params->resend_igmp = resend_igmp;
+ params->min_links = min_links;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
@@ -4900,7 +4794,6 @@ static int bond_init(struct net_device *bond_dev)
bond_set_lockdep_class(bond_dev);
- bond_create_proc_entry(bond);
list_add_tail(&bond->bond_list, &bn->dev_list);
bond_prepare_sysfs_group(bond);
@@ -4922,11 +4815,20 @@ static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
return 0;
}
+static int bond_get_tx_queues(struct net *net, struct nlattr *tb[],
+ unsigned int *num_queues,
+ unsigned int *real_num_queues)
+{
+ *num_queues = tx_queues;
+ return 0;
+}
+
static struct rtnl_link_ops bond_link_ops __read_mostly = {
.kind = "bond",
.priv_size = sizeof(struct bonding),
.setup = bond_setup,
.validate = bond_validate,
+ .get_tx_queues = bond_get_tx_queues,
};
/* Create a new bond based on the specified name and bonding parameters.
@@ -4971,6 +4873,7 @@ static int __net_init bond_net_init(struct net *net)
INIT_LIST_HEAD(&bn->dev_list);
bond_create_proc_dir(bn);
+ bond_create_sysfs(bn);
return 0;
}
@@ -4978,8 +4881,18 @@ static int __net_init bond_net_init(struct net *net)
static void __net_exit bond_net_exit(struct net *net)
{
struct bond_net *bn = net_generic(net, bond_net_id);
+ struct bonding *bond, *tmp_bond;
+ LIST_HEAD(list);
+ bond_destroy_sysfs(bn);
bond_destroy_proc_dir(bn);
+
+ /* Kill off any bonds created after unregistering bond rtnl ops */
+ rtnl_lock();
+ list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list)
+ unregister_netdevice_queue(bond->dev, &list);
+ unregister_netdevice_many(&list);
+ rtnl_unlock();
}
static struct pernet_operations bond_net_ops = {
@@ -5016,15 +4929,12 @@ static int __init bonding_init(void)
goto err;
}
- res = bond_create_sysfs();
- if (res)
- goto err;
-
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
out:
return res;
err:
+ bond_destroy_debugfs();
rtnl_link_unregister(&bond_link_ops);
err_link:
unregister_pernet_subsys(&bond_net_ops);
@@ -5037,7 +4947,6 @@ static void __exit bonding_exit(void)
unregister_netdevice_notifier(&bond_netdev_notifier);
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
- bond_destroy_sysfs();
bond_destroy_debugfs();
rtnl_link_unregister(&bond_link_ops);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index c97307d..ad284ba 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -1,4 +1,5 @@
#include <linux/proc_fs.h>
+#include <linux/export.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include "bonding.h"
@@ -125,6 +126,7 @@ static void bond_info_show_master(struct seq_file *seq)
seq_puts(seq, "\n802.3ad info\n");
seq_printf(seq, "LACP rate: %s\n",
(bond->params.lacp_fast) ? "fast" : "slow");
+ seq_printf(seq, "Min links: %d\n", bond->params.min_links);
seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
ad_select_tbl[bond->params.ad_select].modename);
@@ -156,8 +158,16 @@ static void bond_info_show_slave(struct seq_file *seq,
seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
seq_printf(seq, "MII Status: %s\n",
(slave->link == BOND_LINK_UP) ? "up" : "down");
- seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
- seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+ if (slave->speed == SPEED_UNKNOWN)
+ seq_printf(seq, "Speed: %s\n", "Unknown");
+ else
+ seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+
+ if (slave->duplex == DUPLEX_UNKNOWN)
+ seq_printf(seq, "Duplex: %s\n", "Unknown");
+ else
+ seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+
seq_printf(seq, "Link Failure Count: %u\n",
slave->link_failure_count);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 8a96735..cf95bd8 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -55,8 +55,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
struct class_attribute *attr,
char *buf)
{
- struct net *net = current->nsproxy->net_ns;
- struct bond_net *bn = net_generic(net, bond_net_id);
+ struct bond_net *bn =
+ container_of(attr, struct bond_net, class_attr_bonding_masters);
int res = 0;
struct bonding *bond;
@@ -79,9 +79,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
return res;
}
-static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
+static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname)
{
- struct bond_net *bn = net_generic(net, bond_net_id);
struct bonding *bond;
list_for_each_entry(bond, &bn->dev_list, bond_list) {
@@ -103,7 +102,8 @@ static ssize_t bonding_store_bonds(struct class *cls,
struct class_attribute *attr,
const char *buffer, size_t count)
{
- struct net *net = current->nsproxy->net_ns;
+ struct bond_net *bn =
+ container_of(attr, struct bond_net, class_attr_bonding_masters);
char command[IFNAMSIZ + 1] = {0, };
char *ifname;
int rv, res = count;
@@ -116,7 +116,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
if (command[0] == '+') {
pr_info("%s is being created...\n", ifname);
- rv = bond_create(net, ifname);
+ rv = bond_create(bn->net, ifname);
if (rv) {
if (rv == -EEXIST)
pr_info("%s already exists.\n", ifname);
@@ -128,7 +128,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
struct net_device *bond_dev;
rtnl_lock();
- bond_dev = bond_get_by_name(net, ifname);
+ bond_dev = bond_get_by_name(bn, ifname);
if (bond_dev) {
pr_info("%s is being deleted...\n", ifname);
unregister_netdevice(bond_dev);
@@ -150,9 +150,24 @@ err_no_cmd:
return -EPERM;
}
+static const void *bonding_namespace(struct class *cls,
+ const struct class_attribute *attr)
+{
+ const struct bond_net *bn =
+ container_of(attr, struct bond_net, class_attr_bonding_masters);
+ return bn->net;
+}
+
/* class attribute for bond_masters file. This ends up in /sys/class/net */
-static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
- bonding_show_bonds, bonding_store_bonds);
+static const struct class_attribute class_attr_bonding_masters = {
+ .attr = {
+ .name = "bonding_masters",
+ .mode = S_IWUSR | S_IRUGO,
+ },
+ .show = bonding_show_bonds,
+ .store = bonding_store_bonds,
+ .namespace = bonding_namespace,
+};
int bond_create_slave_symlinks(struct net_device *master,
struct net_device *slave)
@@ -169,6 +184,11 @@ int bond_create_slave_symlinks(struct net_device *master,
sprintf(linkname, "slave_%s", slave->name);
ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
linkname);
+
+ /* free the master link created earlier in case of error */
+ if (ret)
+ sysfs_remove_link(&(slave->dev.kobj), "master");
+
return ret;
}
@@ -304,6 +324,13 @@ static ssize_t bonding_store_mode(struct device *d,
goto out;
}
+ if (bond->slave_cnt > 0) {
+ pr_err("unable to update mode of %s because it has slaves.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
new_value = bond_parse_parm(buf, bond_mode_tbl);
if (new_value < 0) {
pr_err("%s: Ignoring invalid mode value %.*s.\n",
@@ -492,6 +519,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (sscanf(buf, "%d", &new_value) != 1) {
pr_err("%s: no arp_interval value specified.\n",
bond->dev->name);
@@ -499,14 +528,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
goto out;
}
if (new_value < 0) {
- pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+ pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n",
bond->dev->name, new_value, INT_MAX);
ret = -EINVAL;
goto out;
}
if (bond->params.mode == BOND_MODE_ALB ||
- bond->params.mode == BOND_MODE_TLB) {
- pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n",
+ bond->params.mode == BOND_MODE_TLB ||
+ bond->params.mode == BOND_MODE_8023AD) {
+ pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
bond->dev->name, bond->dev->name);
ret = -EINVAL;
goto out;
@@ -514,18 +544,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
pr_info("%s: Setting ARP monitoring interval to %d.\n",
bond->dev->name, new_value);
bond->params.arp_interval = new_value;
- if (bond->params.miimon) {
- pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
- bond->dev->name, bond->dev->name);
- bond->params.miimon = 0;
- if (delayed_work_pending(&bond->mii_work)) {
- cancel_delayed_work(&bond->mii_work);
- flush_workqueue(bond->wq);
+ if (new_value) {
+ if (bond->params.miimon) {
+ pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+ bond->dev->name, bond->dev->name);
+ bond->params.miimon = 0;
}
- }
- if (!bond->params.arp_targets[0]) {
- pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
- bond->dev->name);
+ if (!bond->params.arp_targets[0])
+ pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+ bond->dev->name);
}
if (bond->dev->flags & IFF_UP) {
/* If the interface is up, we may need to fire off
@@ -533,19 +560,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (!delayed_work_pending(&bond->arp_work)) {
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_activebackup_arp_mon);
- else
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_loadbalance_arp_mon);
-
+ if (!new_value) {
+ cancel_delayed_work_sync(&bond->arp_work);
+ } else {
+ cancel_delayed_work_sync(&bond->mii_work);
queue_delayed_work(bond->wq, &bond->arp_work, 0);
}
}
-
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
@@ -671,6 +694,8 @@ static ssize_t bonding_store_downdelay(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (!(bond->params.miimon)) {
pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
bond->dev->name);
@@ -685,7 +710,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
}
if (new_value < 0) {
pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
- bond->dev->name, new_value, 1, INT_MAX);
+ bond->dev->name, new_value, 0, INT_MAX);
ret = -EINVAL;
goto out;
} else {
@@ -704,6 +729,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
@@ -726,6 +752,8 @@ static ssize_t bonding_store_updelay(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (!(bond->params.miimon)) {
pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
bond->dev->name);
@@ -740,8 +768,8 @@ static ssize_t bonding_store_updelay(struct device *d,
goto out;
}
if (new_value < 0) {
- pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
- bond->dev->name, new_value, 1, INT_MAX);
+ pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 0, INT_MAX);
ret = -EINVAL;
goto out;
} else {
@@ -759,6 +787,7 @@ static ssize_t bonding_store_updelay(struct device *d,
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
@@ -804,6 +833,7 @@ static ssize_t bonding_store_lacp(struct device *d,
if ((new_value == 1) || (new_value == 0)) {
bond->params.lacp_fast = new_value;
+ bond_3ad_update_lacp_rate(bond);
pr_info("%s: Setting LACP rate to %s (%d).\n",
bond->dev->name, bond_lacp_tbl[new_value].modename,
new_value);
@@ -818,6 +848,38 @@ out:
static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
bonding_show_lacp, bonding_store_lacp);
+static ssize_t bonding_show_min_links(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.min_links);
+}
+
+static ssize_t bonding_store_min_links(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bonding *bond = to_bond(d);
+ int ret;
+ unsigned int new_value;
+
+ ret = kstrtouint(buf, 0, &new_value);
+ if (ret < 0) {
+ pr_err("%s: Ignoring invalid min links value %s.\n",
+ bond->dev->name, buf);
+ return ret;
+ }
+
+ pr_info("%s: Setting min links value to %u\n",
+ bond->dev->name, new_value);
+ bond->params.min_links = new_value;
+ return count;
+}
+static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR,
+ bonding_show_min_links, bonding_store_min_links);
+
static ssize_t bonding_show_ad_select(struct device *d,
struct device_attribute *attr,
char *buf)
@@ -908,6 +970,8 @@ static ssize_t bonding_store_miimon(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (sscanf(buf, "%d", &new_value) != 1) {
pr_err("%s: no miimon value specified.\n",
bond->dev->name);
@@ -916,50 +980,43 @@ static ssize_t bonding_store_miimon(struct device *d,
}
if (new_value < 0) {
pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
- bond->dev->name, new_value, 1, INT_MAX);
+ bond->dev->name, new_value, 0, INT_MAX);
ret = -EINVAL;
goto out;
- } else {
- pr_info("%s: Setting MII monitoring interval to %d.\n",
- bond->dev->name, new_value);
- bond->params.miimon = new_value;
- if (bond->params.updelay)
- pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
- bond->dev->name,
- bond->params.updelay * bond->params.miimon);
- if (bond->params.downdelay)
- pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
- bond->dev->name,
- bond->params.downdelay * bond->params.miimon);
- if (bond->params.arp_interval) {
- pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
- bond->dev->name);
- bond->params.arp_interval = 0;
- if (bond->params.arp_validate) {
- bond->params.arp_validate =
- BOND_ARP_VALIDATE_NONE;
- }
- if (delayed_work_pending(&bond->arp_work)) {
- cancel_delayed_work(&bond->arp_work);
- flush_workqueue(bond->wq);
- }
- }
-
- if (bond->dev->flags & IFF_UP) {
- /* If the interface is up, we may need to fire off
- * the MII timer. If the interface is down, the
- * timer will get fired off when the open function
- * is called.
- */
- if (!delayed_work_pending(&bond->mii_work)) {
- INIT_DELAYED_WORK(&bond->mii_work,
- bond_mii_monitor);
- queue_delayed_work(bond->wq,
- &bond->mii_work, 0);
- }
+ }
+ pr_info("%s: Setting MII monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.miimon = new_value;
+ if (bond->params.updelay)
+ pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.updelay * bond->params.miimon);
+ if (bond->params.downdelay)
+ pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.downdelay * bond->params.miimon);
+ if (new_value && bond->params.arp_interval) {
+ pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+ bond->dev->name);
+ bond->params.arp_interval = 0;
+ if (bond->params.arp_validate)
+ bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+ }
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the MII timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (!new_value) {
+ cancel_delayed_work_sync(&bond->mii_work);
+ } else {
+ cancel_delayed_work_sync(&bond->arp_work);
+ queue_delayed_work(bond->wq, &bond->mii_work, 0);
}
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
@@ -1611,6 +1668,7 @@ static struct attribute *per_bond_attrs[] = {
&dev_attr_queue_id.attr,
&dev_attr_all_slaves_active.attr,
&dev_attr_resend_igmp.attr,
+ &dev_attr_min_links.attr,
NULL,
};
@@ -1623,11 +1681,14 @@ static struct attribute_group bonding_group = {
* Initialize sysfs. This sets up the bonding_masters file in
* /sys/class/net.
*/
-int bond_create_sysfs(void)
+int bond_create_sysfs(struct bond_net *bn)
{
int ret;
- ret = netdev_class_create_file(&class_attr_bonding_masters);
+ bn->class_attr_bonding_masters = class_attr_bonding_masters;
+ sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
+
+ ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
/*
* Permit multiple loads of the module by ignoring failures to
* create the bonding_masters sysfs file. Bonding devices
@@ -1641,7 +1702,7 @@ int bond_create_sysfs(void)
*/
if (ret == -EEXIST) {
/* Is someone being kinky and naming a device bonding_master? */
- if (__dev_get_by_name(&init_net,
+ if (__dev_get_by_name(bn->net,
class_attr_bonding_masters.attr.name))
pr_err("network device named %s already exists in sysfs",
class_attr_bonding_masters.attr.name);
@@ -1655,9 +1716,9 @@ int bond_create_sysfs(void)
/*
* Remove /sys/class/net/bonding_masters.
*/
-void bond_destroy_sysfs(void)
+void bond_destroy_sysfs(struct bond_net *bn)
{
- netdev_class_remove_file(&class_attr_bonding_masters);
+ netdev_class_remove_file(&bn->class_attr_bonding_masters);
}
/*
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ea1d005..1aecc37 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -147,6 +147,7 @@ struct bond_params {
int updelay;
int downdelay;
int lacp_fast;
+ unsigned int min_links;
int ad_select;
char primary[IFNAMSIZ];
int primary_reselect;
@@ -221,7 +222,6 @@ struct bonding {
struct slave *);
rwlock_t lock;
rwlock_t curr_slave_lock;
- s8 kill_timers;
u8 send_peer_notif;
s8 setup_by_slave;
s8 igmp_retrans;
@@ -233,14 +233,11 @@ struct bonding {
struct netdev_hw_addr_list mc_list;
int (*xmit_hash_policy)(struct sk_buff *, int);
__be32 master_ip;
- u16 flags;
u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
struct bond_params params;
struct list_head vlan_list;
- struct vlan_group *vlgrp;
- struct packet_type arp_mon_pt;
struct workqueue_struct *wq;
struct delayed_work mii_work;
struct delayed_work arp_work;
@@ -253,6 +250,11 @@ struct bonding {
#endif /* CONFIG_DEBUG_FS */
};
+static inline bool bond_vlan_used(struct bonding *bond)
+{
+ return !list_empty(&bond->vlan_list);
+}
+
#define bond_slave_get_rcu(dev) \
((struct slave *) rcu_dereference(dev->rx_handler_data))
@@ -376,11 +378,13 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
return slave->inactive;
}
+struct bond_net;
+
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(struct net *net, const char *name);
-int bond_create_sysfs(void);
-void bond_destroy_sysfs(void);
+int bond_create_sysfs(struct bond_net *net);
+void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond);
int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
@@ -406,6 +410,7 @@ struct bond_net {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry * proc_dir;
#endif
+ struct class_attribute class_attr_bonding_masters;
};
#ifdef CONFIG_PROC_FS
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 09ed3f4..abf4d7a 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -38,3 +38,12 @@ config CAIF_SHM
default n
---help---
The CAIF shared memory protocol driver for the STE UX5500 platform.
+
+config CAIF_HSI
+ tristate "CAIF HSI transport driver"
+ depends on CAIF
+ default n
+ ---help---
+ The caif low level driver for CAIF over HSI.
+ Be aware that if you enable this then you also need to
+ enable a low-level HSI driver.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 9560b9d..91dff86 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -10,3 +10,6 @@ obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
# Shared memory
caif_shm-objs := caif_shmcore.o caif_shm_u5500.o
obj-$(CONFIG_CAIF_SHM) += caif_shm.o
+
+# HSI interface
+obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 82b1802..ae286a9 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -4,8 +4,8 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/hardirq.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/types.h>
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c
index 5f771ab..89d76b7 100644
--- a/drivers/net/caif/caif_shm_u5500.c
+++ b/drivers/net/caif/caif_shm_u5500.c
@@ -7,7 +7,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c
index 731aa11..d4b26fb 100644
--- a/drivers/net/caif/caif_shmcore.c
+++ b/drivers/net/caif/caif_shmcore.c
@@ -134,7 +134,7 @@ int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv)
u32 avail_emptybuff = 0;
unsigned long flags = 0;
- pshm_drv = (struct shmdrv_layer *)priv;
+ pshm_drv = priv;
/* Check for received buffers. */
if (mbx_msg & SHM_FULL_MASK) {
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 57e6393..05e791f 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -5,7 +5,6 @@
* License terms: GNU General Public License (GPL) version 2.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
@@ -665,8 +664,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
/* Allocate DMA buffers. */
cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
if (!cfspi->xfer.va_tx) {
- printk(KERN_WARNING
- "CFSPI: failed to allocate dma TX buffer.\n");
res = -ENODEV;
goto err_dma_alloc_tx;
}
@@ -674,8 +671,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
if (!cfspi->xfer.va_rx) {
- printk(KERN_WARNING
- "CFSPI: failed to allocate dma TX buffer.\n");
res = -ENODEV;
goto err_dma_alloc_rx;
}
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c
index b009e03..e139e13 100644
--- a/drivers/net/caif/caif_spi_slave.c
+++ b/drivers/net/caif/caif_spi_slave.c
@@ -4,7 +4,6 @@
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
* License terms: GNU General Public License (GPL) version 2.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 754df5e..f6c98fb 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -4,7 +4,6 @@ menu "CAN Device Drivers"
config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)"
depends on CAN
- default N
---help---
Similar to the network loopback devices, vcan offers a
virtual local CAN interface.
@@ -15,7 +14,6 @@ config CAN_VCAN
config CAN_SLCAN
tristate "Serial / USB serial CAN Adaptors (slcan)"
depends on CAN
- default N
---help---
CAN driver for several 'low cost' CAN interfaces that are attached
via serial lines or via USB-to-serial adapters using the LAWICEL
@@ -58,9 +56,10 @@ config CAN_CALC_BITTIMING
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
- depends on CAN_DEV && ARCH_AT91SAM9263
+ depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
---help---
- This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+ This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
+ and AT91SAM9X5 processors.
config CAN_TI_HECC
depends on CAN_DEV && ARCH_OMAP3
@@ -124,7 +123,6 @@ source "drivers/net/can/softing/Kconfig"
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
depends on CAN
- default N
---help---
Say Y here if you want the CAN device drivers to produce a bunch of
debug messages to the system log. Select this if you are having
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 74efb5a..ab411c3 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -8,8 +8,6 @@
* Public License ("GPL") version 2 as distributed in the 'COPYING'
* file from the main directory of the linux kernel source.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*
* Your platform definition file should specify something like:
*
@@ -41,32 +39,7 @@
#include <mach/board.h>
-#define AT91_NAPI_WEIGHT 11
-
-/*
- * RX/TX Mailbox split
- * don't dare to touch
- */
-#define AT91_MB_RX_NUM 11
-#define AT91_MB_TX_SHIFT 2
-
-#define AT91_MB_RX_FIRST 1
-#define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
-
-#define AT91_MB_RX_MASK(i) ((1 << (i)) - 1)
-#define AT91_MB_RX_SPLIT 8
-#define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1)
-#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
- ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
-
-#define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT)
-#define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1)
-#define AT91_MB_TX_LAST (AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
-
-#define AT91_NEXT_PRIO_SHIFT (AT91_MB_TX_SHIFT)
-#define AT91_NEXT_PRIO_MASK (0xf << AT91_MB_TX_SHIFT)
-#define AT91_NEXT_MB_MASK (AT91_MB_TX_NUM - 1)
-#define AT91_NEXT_MASK ((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
+#define AT91_MB_MASK(i) ((1 << (i)) - 1)
/* Common registers */
enum at91_reg {
@@ -128,12 +101,6 @@ enum at91_mb_mode {
};
/* Interrupt mask bits */
-#define AT91_IRQ_MB_RX ((1 << (AT91_MB_RX_LAST + 1)) \
- - (1 << AT91_MB_RX_FIRST))
-#define AT91_IRQ_MB_TX ((1 << (AT91_MB_TX_LAST + 1)) \
- - (1 << AT91_MB_TX_FIRST))
-#define AT91_IRQ_MB_ALL (AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
-
#define AT91_IRQ_ERRA (1 << 16)
#define AT91_IRQ_WARN (1 << 17)
#define AT91_IRQ_ERRP (1 << 18)
@@ -156,22 +123,51 @@ enum at91_mb_mode {
#define AT91_IRQ_ALL (0x1fffffff)
+enum at91_devtype {
+ AT91_DEVTYPE_SAM9263,
+ AT91_DEVTYPE_SAM9X5,
+};
+
+struct at91_devtype_data {
+ unsigned int rx_first;
+ unsigned int rx_split;
+ unsigned int rx_last;
+ unsigned int tx_shift;
+ enum at91_devtype type;
+};
+
struct at91_priv {
- struct can_priv can; /* must be the first member! */
- struct net_device *dev;
- struct napi_struct napi;
+ struct can_priv can; /* must be the first member! */
+ struct net_device *dev;
+ struct napi_struct napi;
- void __iomem *reg_base;
+ void __iomem *reg_base;
- u32 reg_sr;
- unsigned int tx_next;
- unsigned int tx_echo;
- unsigned int rx_next;
+ u32 reg_sr;
+ unsigned int tx_next;
+ unsigned int tx_echo;
+ unsigned int rx_next;
+ struct at91_devtype_data devtype_data;
- struct clk *clk;
- struct at91_can_data *pdata;
+ struct clk *clk;
+ struct at91_can_data *pdata;
- canid_t mb0_id;
+ canid_t mb0_id;
+};
+
+static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
+ [AT91_DEVTYPE_SAM9263] = {
+ .rx_first = 1,
+ .rx_split = 8,
+ .rx_last = 11,
+ .tx_shift = 2,
+ },
+ [AT91_DEVTYPE_SAM9X5] = {
+ .rx_first = 0,
+ .rx_split = 4,
+ .rx_last = 5,
+ .tx_shift = 1,
+ },
};
static struct can_bittiming_const at91_bittiming_const = {
@@ -186,19 +182,111 @@ static struct can_bittiming_const at91_bittiming_const = {
.brp_inc = 1,
};
-static inline int get_tx_next_mb(const struct at91_priv *priv)
+#define AT91_IS(_model) \
+static inline int at91_is_sam##_model(const struct at91_priv *priv) \
+{ \
+ return priv->devtype_data.type == AT91_DEVTYPE_SAM##_model; \
+}
+
+AT91_IS(9263);
+AT91_IS(9X5);
+
+static inline unsigned int get_mb_rx_first(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_first;
+}
+
+static inline unsigned int get_mb_rx_last(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_last;
+}
+
+static inline unsigned int get_mb_rx_split(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_split;
+}
+
+static inline unsigned int get_mb_rx_num(const struct at91_priv *priv)
+{
+ return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1;
+}
+
+static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv)
+{
+ return get_mb_rx_split(priv) - 1;
+}
+
+static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_rx_split(priv)) &
+ ~AT91_MB_MASK(get_mb_rx_first(priv));
+}
+
+static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv)
+{
+ return priv->devtype_data.tx_shift;
+}
+
+static inline unsigned int get_mb_tx_num(const struct at91_priv *priv)
+{
+ return 1 << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_mb_tx_first(const struct at91_priv *priv)
+{
+ return get_mb_rx_last(priv) + 1;
+}
+
+static inline unsigned int get_mb_tx_last(const struct at91_priv *priv)
+{
+ return get_mb_tx_first(priv) + get_mb_tx_num(priv) - 1;
+}
+
+static inline unsigned int get_next_prio_shift(const struct at91_priv *priv)
+{
+ return get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_prio_mask(const struct at91_priv *priv)
+{
+ return 0xf << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_mb_mask(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_tx_shift(priv));
+}
+
+static inline unsigned int get_next_mask(const struct at91_priv *priv)
+{
+ return get_next_mb_mask(priv) | get_next_prio_mask(priv);
+}
+
+static inline unsigned int get_irq_mb_rx(const struct at91_priv *priv)
{
- return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+ return AT91_MB_MASK(get_mb_rx_last(priv) + 1) &
+ ~AT91_MB_MASK(get_mb_rx_first(priv));
}
-static inline int get_tx_next_prio(const struct at91_priv *priv)
+static inline unsigned int get_irq_mb_tx(const struct at91_priv *priv)
{
- return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf;
+ return AT91_MB_MASK(get_mb_tx_last(priv) + 1) &
+ ~AT91_MB_MASK(get_mb_tx_first(priv));
}
-static inline int get_tx_echo_mb(const struct at91_priv *priv)
+static inline unsigned int get_tx_next_mb(const struct at91_priv *priv)
{
- return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+ return (priv->tx_next & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
+}
+
+static inline unsigned int get_tx_next_prio(const struct at91_priv *priv)
+{
+ return (priv->tx_next >> get_next_prio_shift(priv)) & 0xf;
+}
+
+static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv)
+{
+ return (priv->tx_echo & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
}
static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
@@ -259,29 +347,29 @@ static void at91_setup_mailboxes(struct net_device *dev)
* overflow.
*/
reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
- for (i = 0; i < AT91_MB_RX_FIRST; i++) {
+ for (i = 0; i < get_mb_rx_first(priv); i++) {
set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
at91_write(priv, AT91_MID(i), reg_mid);
at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */
}
- for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
+ for (i = get_mb_rx_first(priv); i < get_mb_rx_last(priv); i++)
set_mb_mode(priv, i, AT91_MB_MODE_RX);
- set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
+ set_mb_mode(priv, get_mb_rx_last(priv), AT91_MB_MODE_RX_OVRWR);
/* reset acceptance mask and id register */
- for (i = AT91_MB_RX_FIRST; i <= AT91_MB_RX_LAST; i++) {
- at91_write(priv, AT91_MAM(i), 0x0 );
+ for (i = get_mb_rx_first(priv); i <= get_mb_rx_last(priv); i++) {
+ at91_write(priv, AT91_MAM(i), 0x0);
at91_write(priv, AT91_MID(i), AT91_MID_MIDE);
}
/* The last 4 mailboxes are used for transmitting. */
- for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++)
+ for (i = get_mb_tx_first(priv); i <= get_mb_tx_last(priv); i++)
set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
/* Reset tx and rx helper pointers */
priv->tx_next = priv->tx_echo = 0;
- priv->rx_next = AT91_MB_RX_FIRST;
+ priv->rx_next = get_mb_rx_first(priv);
}
static int at91_set_bittiming(struct net_device *dev)
@@ -336,7 +424,7 @@ static void at91_chip_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* Enable interrupts */
- reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
+ reg_ier = get_irq_mb_rx(priv) | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
at91_write(priv, AT91_IER, reg_ier);
}
@@ -375,8 +463,8 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
* mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
* encode the mailbox number, the upper 4 bits the mailbox priority:
*
- * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) ||
- * (mb - AT91_MB_TX_FIRST);
+ * priv->tx_next = (prio << get_next_prio_shift(priv)) |
+ * (mb - get_mb_tx_first(priv));
*
*/
static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -417,7 +505,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_bytes += cf->can_dlc;
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
- can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
+ can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));
/*
* we have to stop the queue and deliver all messages in case
@@ -430,7 +518,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
priv->tx_next++;
if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &
AT91_MSR_MRDY) ||
- (priv->tx_next & AT91_NEXT_MASK) == 0)
+ (priv->tx_next & get_next_mask(priv)) == 0)
netif_stop_queue(dev);
/* Enable interrupt for this mailbox */
@@ -447,7 +535,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static inline void at91_activate_rx_low(const struct at91_priv *priv)
{
- u32 mask = AT91_MB_RX_LOW_MASK;
+ u32 mask = get_mb_rx_low_mask(priv);
at91_write(priv, AT91_TCR, mask);
}
@@ -513,17 +601,19 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
reg_msr = at91_read(priv, AT91_MSR(mb));
- if (reg_msr & AT91_MSR_MRTR)
- cf->can_id |= CAN_RTR_FLAG;
cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf);
- *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
- *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+ if (reg_msr & AT91_MSR_MRTR)
+ cf->can_id |= CAN_RTR_FLAG;
+ else {
+ *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
+ *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+ }
/* allow RX of extended frames */
at91_write(priv, AT91_MID(mb), AT91_MID_MIDE);
- if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI))
+ if (unlikely(mb == get_mb_rx_last(priv) && reg_msr & AT91_MSR_MMI))
at91_rx_overflow_err(dev);
}
@@ -561,8 +651,9 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
*
* Theory of Operation:
*
- * 11 of the 16 mailboxes on the chip are reserved for RX. we split
- * them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
+ * About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last())
+ * on the chip are reserved for RX. We split them into 2 groups. The
+ * lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().
*
* Like it or not, but the chip always saves a received CAN message
* into the first free mailbox it finds (starting with the
@@ -610,23 +701,23 @@ static int at91_poll_rx(struct net_device *dev, int quota)
unsigned int mb;
int received = 0;
- if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
- reg_sr & AT91_MB_RX_LOW_MASK)
+ if (priv->rx_next > get_mb_rx_low_last(priv) &&
+ reg_sr & get_mb_rx_low_mask(priv))
netdev_info(dev,
"order of incoming frames cannot be guaranteed\n");
again:
- for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
- mb < AT91_MB_RX_LAST + 1 && quota > 0;
+ for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
+ mb < get_mb_tx_first(priv) && quota > 0;
reg_sr = at91_read(priv, AT91_SR),
- mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
+ mb = find_next_bit(addr, get_mb_tx_first(priv), ++priv->rx_next)) {
at91_read_msg(dev, mb);
/* reactivate mailboxes */
- if (mb == AT91_MB_RX_LOW_LAST)
+ if (mb == get_mb_rx_low_last(priv))
/* all lower mailboxed, if just finished it */
at91_activate_rx_low(priv);
- else if (mb > AT91_MB_RX_LOW_LAST)
+ else if (mb > get_mb_rx_low_last(priv))
/* only the mailbox we read */
at91_activate_rx_mb(priv, mb);
@@ -635,9 +726,9 @@ static int at91_poll_rx(struct net_device *dev, int quota)
}
/* upper group completed, look again in lower */
- if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
- quota > 0 && mb > AT91_MB_RX_LAST) {
- priv->rx_next = AT91_MB_RX_FIRST;
+ if (priv->rx_next > get_mb_rx_low_last(priv) &&
+ quota > 0 && mb > get_mb_rx_last(priv)) {
+ priv->rx_next = get_mb_rx_first(priv);
goto again;
}
@@ -720,7 +811,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
u32 reg_sr = at91_read(priv, AT91_SR);
int work_done = 0;
- if (reg_sr & AT91_IRQ_MB_RX)
+ if (reg_sr & get_irq_mb_rx(priv))
work_done += at91_poll_rx(dev, quota - work_done);
/*
@@ -734,7 +825,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if (work_done < quota) {
/* enable IRQs for frame errors and all mailboxes >= rx_next */
u32 reg_ier = AT91_IRQ_ERR_FRAME;
- reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next);
+ reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
napi_complete(napi);
at91_write(priv, AT91_IER, reg_ier);
@@ -783,7 +874,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
if (likely(reg_msr & AT91_MSR_MRDY &&
~reg_msr & AT91_MSR_MABT)) {
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
- can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
+ can_get_echo_skb(dev, mb - get_mb_tx_first(priv));
dev->stats.tx_packets++;
}
}
@@ -793,8 +884,8 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
* we get a TX int for the last can frame directly before a
* wrap around.
*/
- if ((priv->tx_next & AT91_NEXT_MASK) != 0 ||
- (priv->tx_echo & AT91_NEXT_MASK) == 0)
+ if ((priv->tx_next & get_next_mask(priv)) != 0 ||
+ (priv->tx_echo & get_next_mask(priv)) == 0)
netif_wake_queue(dev);
}
@@ -906,6 +997,29 @@ static void at91_irq_err_state(struct net_device *dev,
at91_write(priv, AT91_IER, reg_ier);
}
+static int at91_get_state_by_bec(const struct net_device *dev,
+ enum can_state *state)
+{
+ struct can_berr_counter bec;
+ int err;
+
+ err = at91_get_berr_counter(dev, &bec);
+ if (err)
+ return err;
+
+ if (bec.txerr < 96 && bec.rxerr < 96)
+ *state = CAN_STATE_ERROR_ACTIVE;
+ else if (bec.txerr < 128 && bec.rxerr < 128)
+ *state = CAN_STATE_ERROR_WARNING;
+ else if (bec.txerr < 256 && bec.rxerr < 256)
+ *state = CAN_STATE_ERROR_PASSIVE;
+ else
+ *state = CAN_STATE_BUS_OFF;
+
+ return 0;
+}
+
+
static void at91_irq_err(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
@@ -913,21 +1027,28 @@ static void at91_irq_err(struct net_device *dev)
struct can_frame *cf;
enum can_state new_state;
u32 reg_sr;
+ int err;
- reg_sr = at91_read(priv, AT91_SR);
-
- /* we need to look at the unmasked reg_sr */
- if (unlikely(reg_sr & AT91_IRQ_BOFF))
- new_state = CAN_STATE_BUS_OFF;
- else if (unlikely(reg_sr & AT91_IRQ_ERRP))
- new_state = CAN_STATE_ERROR_PASSIVE;
- else if (unlikely(reg_sr & AT91_IRQ_WARN))
- new_state = CAN_STATE_ERROR_WARNING;
- else if (likely(reg_sr & AT91_IRQ_ERRA))
- new_state = CAN_STATE_ERROR_ACTIVE;
- else {
- netdev_err(dev, "BUG! hardware in undefined state\n");
- return;
+ if (at91_is_sam9263(priv)) {
+ reg_sr = at91_read(priv, AT91_SR);
+
+ /* we need to look at the unmasked reg_sr */
+ if (unlikely(reg_sr & AT91_IRQ_BOFF))
+ new_state = CAN_STATE_BUS_OFF;
+ else if (unlikely(reg_sr & AT91_IRQ_ERRP))
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ else if (unlikely(reg_sr & AT91_IRQ_WARN))
+ new_state = CAN_STATE_ERROR_WARNING;
+ else if (likely(reg_sr & AT91_IRQ_ERRA))
+ new_state = CAN_STATE_ERROR_ACTIVE;
+ else {
+ netdev_err(dev, "BUG! hardware in undefined state\n");
+ return;
+ }
+ } else {
+ err = at91_get_state_by_bec(dev, &new_state);
+ if (err)
+ return;
}
/* state hasn't changed */
@@ -968,19 +1089,19 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
handled = IRQ_HANDLED;
/* Receive or error interrupt? -> napi */
- if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) {
+ if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
/*
* The error bits are clear on read,
* save for later use.
*/
priv->reg_sr = reg_sr;
at91_write(priv, AT91_IDR,
- AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME);
+ get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME);
napi_schedule(&priv->napi);
}
/* Transmission complete interrupt */
- if (reg_sr & AT91_IRQ_MB_TX)
+ if (reg_sr & get_irq_mb_tx(priv))
at91_irq_tx(dev, reg_sr);
at91_irq_err(dev);
@@ -994,7 +1115,9 @@ static int at91_open(struct net_device *dev)
struct at91_priv *priv = netdev_priv(dev);
int err;
- clk_enable(priv->clk);
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ return err;
/* check or determine and set bittime */
err = open_candev(dev);
@@ -1018,7 +1141,7 @@ static int at91_open(struct net_device *dev)
out_close:
close_candev(dev);
out:
- clk_disable(priv->clk);
+ clk_disable_unprepare(priv->clk);
return err;
}
@@ -1035,7 +1158,7 @@ static int at91_close(struct net_device *dev)
at91_chip_stop(dev, CAN_STATE_STOPPED);
free_irq(dev->irq, dev);
- clk_disable(priv->clk);
+ clk_disable_unprepare(priv->clk);
close_candev(dev);
@@ -1123,6 +1246,8 @@ static struct attribute_group at91_sysfs_attr_group = {
static int __devinit at91_can_probe(struct platform_device *pdev)
{
+ const struct at91_devtype_data *devtype_data;
+ enum at91_devtype devtype;
struct net_device *dev;
struct at91_priv *priv;
struct resource *res;
@@ -1130,6 +1255,9 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
void __iomem *addr;
int err, irq;
+ devtype = pdev->id_entry->driver_data;
+ devtype_data = &at91_devtype_data[devtype];
+
clk = clk_get(&pdev->dev, "can_clk");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "no clock defined\n");
@@ -1157,7 +1285,8 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
goto exit_release;
}
- dev = alloc_candev(sizeof(struct at91_priv), AT91_MB_TX_NUM);
+ dev = alloc_candev(sizeof(struct at91_priv),
+ 1 << devtype_data->tx_shift);
if (!dev) {
err = -ENOMEM;
goto exit_iounmap;
@@ -1166,7 +1295,6 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
dev->netdev_ops = &at91_netdev_ops;
dev->irq = irq;
dev->flags |= IFF_ECHO;
- dev->sysfs_groups[0] = &at91_sysfs_attr_group;
priv = netdev_priv(dev);
priv->can.clock.freq = clk_get_rate(clk);
@@ -1174,13 +1302,18 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
priv->can.do_set_mode = at91_set_mode;
priv->can.do_get_berr_counter = at91_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
- priv->reg_base = addr;
priv->dev = dev;
+ priv->reg_base = addr;
+ priv->devtype_data = *devtype_data;
+ priv->devtype_data.type = devtype;
priv->clk = clk;
priv->pdata = pdev->dev.platform_data;
priv->mb0_id = 0x7ff;
- netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
+ netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
+
+ if (at91_is_sam9263(priv))
+ dev->sysfs_groups[0] = &at91_sysfs_attr_group;
dev_set_drvdata(&pdev->dev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1230,13 +1363,26 @@ static int __devexit at91_can_remove(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id at91_can_id_table[] = {
+ {
+ .name = "at91_can",
+ .driver_data = AT91_DEVTYPE_SAM9263,
+ }, {
+ .name = "at91sam9x5_can",
+ .driver_data = AT91_DEVTYPE_SAM9X5,
+ }, {
+ /* sentinel */
+ }
+};
+
static struct platform_driver at91_can_driver = {
- .probe = at91_can_probe,
- .remove = __devexit_p(at91_can_remove),
- .driver = {
- .name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
+ .probe = at91_can_probe,
+ .remove = __devexit_p(at91_can_remove),
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
},
+ .id_table = at91_can_id_table,
};
static int __init at91_can_module_init(void)
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index b6e890d..a1c5abc 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -79,8 +79,8 @@ static int bfin_can_set_bittiming(struct net_device *dev)
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
- bfin_write16(&reg->clock, clk);
- bfin_write16(&reg->timing, timing);
+ bfin_write(&reg->clock, clk);
+ bfin_write(&reg->timing, timing);
dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
clk, timing);
@@ -96,16 +96,16 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
int i;
/* disable interrupts */
- bfin_write16(&reg->mbim1, 0);
- bfin_write16(&reg->mbim2, 0);
- bfin_write16(&reg->gim, 0);
+ bfin_write(&reg->mbim1, 0);
+ bfin_write(&reg->mbim2, 0);
+ bfin_write(&reg->gim, 0);
/* reset can and enter configuration mode */
- bfin_write16(&reg->control, SRS | CCR);
+ bfin_write(&reg->control, SRS | CCR);
SSYNC();
- bfin_write16(&reg->control, CCR);
+ bfin_write(&reg->control, CCR);
SSYNC();
- while (!(bfin_read16(&reg->control) & CCA)) {
+ while (!(bfin_read(&reg->control) & CCA)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -119,33 +119,33 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
* by writing to CAN Mailbox Configuration Registers 1 and 2
* For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
*/
- bfin_write16(&reg->mc1, 0);
- bfin_write16(&reg->mc2, 0);
+ bfin_write(&reg->mc1, 0);
+ bfin_write(&reg->mc2, 0);
/* Set Mailbox Direction */
- bfin_write16(&reg->md1, 0xFFFF); /* mailbox 1-16 are RX */
- bfin_write16(&reg->md2, 0); /* mailbox 17-32 are TX */
+ bfin_write(&reg->md1, 0xFFFF); /* mailbox 1-16 are RX */
+ bfin_write(&reg->md2, 0); /* mailbox 17-32 are TX */
/* RECEIVE_STD_CHL */
for (i = 0; i < 2; i++) {
- bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
- bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
- bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
- bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
- bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
+ bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
+ bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
+ bfin_write(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
+ bfin_write(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
+ bfin_write(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
}
/* RECEIVE_EXT_CHL */
for (i = 0; i < 2; i++) {
- bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
- bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
- bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
- bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
- bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
+ bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
+ bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
+ bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
+ bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
+ bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
}
- bfin_write16(&reg->mc2, BIT(TRANSMIT_CHL - 16));
- bfin_write16(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+ bfin_write(&reg->mc2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
SSYNC();
priv->can.state = CAN_STATE_STOPPED;
@@ -160,9 +160,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
* leave configuration mode
*/
- bfin_write16(&reg->control, bfin_read16(&reg->control) & ~CCR);
+ bfin_write(&reg->control, bfin_read(&reg->control) & ~CCR);
- while (bfin_read16(&reg->status) & CCA) {
+ while (bfin_read(&reg->status) & CCA) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -174,25 +174,25 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
* clear _All_ tx and rx interrupts
*/
- bfin_write16(&reg->mbtif1, 0xFFFF);
- bfin_write16(&reg->mbtif2, 0xFFFF);
- bfin_write16(&reg->mbrif1, 0xFFFF);
- bfin_write16(&reg->mbrif2, 0xFFFF);
+ bfin_write(&reg->mbtif1, 0xFFFF);
+ bfin_write(&reg->mbtif2, 0xFFFF);
+ bfin_write(&reg->mbrif1, 0xFFFF);
+ bfin_write(&reg->mbrif2, 0xFFFF);
/*
* clear global interrupt status register
*/
- bfin_write16(&reg->gis, 0x7FF); /* overwrites with '1' */
+ bfin_write(&reg->gis, 0x7FF); /* overwrites with '1' */
/*
* Initialize Interrupts
* - set bits in the mailbox interrupt mask register
* - global interrupt mask
*/
- bfin_write16(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
- bfin_write16(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+ bfin_write(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
- bfin_write16(&reg->gim, EPIM | BOIM | RMLIM);
+ bfin_write(&reg->gim, EPIM | BOIM | RMLIM);
SSYNC();
}
@@ -242,37 +242,28 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* fill id */
if (id & CAN_EFF_FLAG) {
- bfin_write16(&reg->chl[TRANSMIT_CHL].id0, id);
- if (id & CAN_RTR_FLAG)
- writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR,
- &reg->chl[TRANSMIT_CHL].id1);
- else
- writew(((id & 0x1FFF0000) >> 16) | IDE | AME,
- &reg->chl[TRANSMIT_CHL].id1);
-
- } else {
- if (id & CAN_RTR_FLAG)
- writew((id << 2) | AME | RTR,
- &reg->chl[TRANSMIT_CHL].id1);
- else
- bfin_write16(&reg->chl[TRANSMIT_CHL].id1,
- (id << 2) | AME);
- }
+ bfin_write(&reg->chl[TRANSMIT_CHL].id0, id);
+ val = ((id & 0x1FFF0000) >> 16) | IDE;
+ } else
+ val = (id << 2);
+ if (id & CAN_RTR_FLAG)
+ val |= RTR;
+ bfin_write(&reg->chl[TRANSMIT_CHL].id1, val | AME);
/* fill payload */
for (i = 0; i < 8; i += 2) {
val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
((6 - i) < dlc ? (data[6 - i] << 8) : 0);
- bfin_write16(&reg->chl[TRANSMIT_CHL].data[i], val);
+ bfin_write(&reg->chl[TRANSMIT_CHL].data[i], val);
}
/* fill data length code */
- bfin_write16(&reg->chl[TRANSMIT_CHL].dlc, dlc);
+ bfin_write(&reg->chl[TRANSMIT_CHL].dlc, dlc);
can_put_echo_skb(skb, dev, 0);
/* set transmit request */
- bfin_write16(&reg->trs2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(&reg->trs2, BIT(TRANSMIT_CHL - 16));
return 0;
}
@@ -295,26 +286,26 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc)
/* get id */
if (isrc & BIT(RECEIVE_EXT_CHL)) {
/* extended frame format (EFF) */
- cf->can_id = ((bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id1)
+ cf->can_id = ((bfin_read(&reg->chl[RECEIVE_EXT_CHL].id1)
& 0x1FFF) << 16)
- + bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id0);
+ + bfin_read(&reg->chl[RECEIVE_EXT_CHL].id0);
cf->can_id |= CAN_EFF_FLAG;
obj = RECEIVE_EXT_CHL;
} else {
/* standard frame format (SFF) */
- cf->can_id = (bfin_read16(&reg->chl[RECEIVE_STD_CHL].id1)
+ cf->can_id = (bfin_read(&reg->chl[RECEIVE_STD_CHL].id1)
& 0x1ffc) >> 2;
obj = RECEIVE_STD_CHL;
}
- if (bfin_read16(&reg->chl[obj].id1) & RTR)
+ if (bfin_read(&reg->chl[obj].id1) & RTR)
cf->can_id |= CAN_RTR_FLAG;
/* get data length code */
- cf->can_dlc = get_can_dlc(bfin_read16(&reg->chl[obj].dlc) & 0xF);
+ cf->can_dlc = get_can_dlc(bfin_read(&reg->chl[obj].dlc) & 0xF);
/* get payload */
for (i = 0; i < 8; i += 2) {
- val = bfin_read16(&reg->chl[obj].data[i]);
+ val = bfin_read(&reg->chl[obj].data[i]);
cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
}
@@ -368,7 +359,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
- u16 cec = bfin_read16(&reg->cec);
+ u16 cec = bfin_read(&reg->cec);
u8 rxerr = cec;
u8 txerr = cec >> 8;
@@ -419,23 +410,23 @@ irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
struct net_device_stats *stats = &dev->stats;
u16 status, isrc;
- if ((irq == priv->tx_irq) && bfin_read16(&reg->mbtif2)) {
+ if ((irq == priv->tx_irq) && bfin_read(&reg->mbtif2)) {
/* transmission complete interrupt */
- bfin_write16(&reg->mbtif2, 0xFFFF);
+ bfin_write(&reg->mbtif2, 0xFFFF);
stats->tx_packets++;
- stats->tx_bytes += bfin_read16(&reg->chl[TRANSMIT_CHL].dlc);
+ stats->tx_bytes += bfin_read(&reg->chl[TRANSMIT_CHL].dlc);
can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
- } else if ((irq == priv->rx_irq) && bfin_read16(&reg->mbrif1)) {
+ } else if ((irq == priv->rx_irq) && bfin_read(&reg->mbrif1)) {
/* receive interrupt */
- isrc = bfin_read16(&reg->mbrif1);
- bfin_write16(&reg->mbrif1, 0xFFFF);
+ isrc = bfin_read(&reg->mbrif1);
+ bfin_write(&reg->mbrif1, 0xFFFF);
bfin_can_rx(dev, isrc);
- } else if ((irq == priv->err_irq) && bfin_read16(&reg->gis)) {
+ } else if ((irq == priv->err_irq) && bfin_read(&reg->gis)) {
/* error interrupt */
- isrc = bfin_read16(&reg->gis);
- status = bfin_read16(&reg->esr);
- bfin_write16(&reg->gis, 0x7FF);
+ isrc = bfin_read(&reg->gis);
+ status = bfin_read(&reg->esr);
+ bfin_write(&reg->gis, 0x7FF);
bfin_can_err(dev, isrc, status);
} else {
return IRQ_NONE;
@@ -640,9 +631,9 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
if (netif_running(dev)) {
/* enter sleep mode */
- bfin_write16(&reg->control, bfin_read16(&reg->control) | SMR);
+ bfin_write(&reg->control, bfin_read(&reg->control) | SMR);
SSYNC();
- while (!(bfin_read16(&reg->intr) & SMACK)) {
+ while (!(bfin_read(&reg->intr) & SMACK)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -663,7 +654,7 @@ static int bfin_can_resume(struct platform_device *pdev)
if (netif_running(dev)) {
/* leave sleep mode */
- bfin_write16(&reg->intr, 0);
+ bfin_write(&reg->intr, 0);
SSYNC();
}
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 6195868..91d1b5a 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -26,7 +26,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -34,7 +33,6 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/list.h>
-#include <linux/delay.h>
#include <linux/io.h>
#include <linux/can.h>
@@ -448,8 +446,12 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
priv->write_reg(priv, &priv->regs->ifregs[iface].mask1,
IFX_WRITE_LOW_16BIT(mask));
+
+ /* According to C_CAN documentation, the reserved bit
+ * in IFx_MASK2 register is fixed 1
+ */
priv->write_reg(priv, &priv->regs->ifregs[iface].mask2,
- IFX_WRITE_HIGH_16BIT(mask));
+ IFX_WRITE_HIGH_16BIT(mask) | BIT(13));
priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
IFX_WRITE_LOW_16BIT(id));
@@ -762,9 +764,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
msg_ctrl_save = priv->read_reg(priv,
&priv->regs->ifregs[0].msg_cntrl);
- if (msg_ctrl_save & IF_MCONT_EOB)
- return num_rx_pkts;
-
if (msg_ctrl_save & IF_MCONT_MSGLST) {
c_can_handle_lost_msg_obj(dev, 0, msg_obj);
num_rx_pkts++;
@@ -772,6 +771,9 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
continue;
}
+ if (msg_ctrl_save & IF_MCONT_EOB)
+ return num_rx_pkts;
+
if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
continue;
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index cc90824..0b5c6f8 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -20,7 +20,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -28,7 +27,6 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/list.h>
-#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index cc3ea0d..db9100f 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -150,7 +150,19 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
- bt->sjw = 1;
+
+ /* check for sjw user settings */
+ if (!bt->sjw || !btc->sjw_max)
+ bt->sjw = 1;
+ else {
+ /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+ if (bt->sjw > btc->sjw_max)
+ bt->sjw = btc->sjw_max;
+ /* bt->sjw must not be higher than tseg2 */
+ if (tseg2 < bt->sjw)
+ bt->sjw = tseg2;
+ }
+
bt->brp = best_brp;
/* real bit-rate */
bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
@@ -208,7 +220,7 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt)
return 0;
}
-int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
+static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
{
struct can_priv *priv = netdev_priv(dev);
int err;
@@ -340,7 +352,7 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx)
BUG_ON(idx >= priv->echo_skb_max);
if (priv->echo_skb[idx]) {
- kfree_skb(priv->echo_skb[idx]);
+ dev_kfree_skb_any(priv->echo_skb[idx]);
priv->echo_skb[idx] = NULL;
}
}
@@ -456,6 +468,11 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
skb->protocol = htons(ETH_P_CAN);
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
memset(*cf, 0, sizeof(struct can_frame));
@@ -593,10 +610,14 @@ static int can_changelink(struct net_device *dev,
if (dev->flags & IFF_UP)
return -EBUSY;
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
- if (cm->flags & ~priv->ctrlmode_supported)
+
+ /* check whether changed bits are allowed to be modified */
+ if (cm->mask & ~priv->ctrlmode_supported)
return -EOPNOTSUPP;
+
+ /* clear bits to be modified and copy the flag values */
priv->ctrlmode &= ~cm->mask;
- priv->ctrlmode |= cm->flags;
+ priv->ctrlmode |= (cm->flags & cm->mask);
}
if (data[IFLA_CAN_BITTIMING]) {
@@ -646,14 +667,14 @@ static size_t can_get_size(const struct net_device *dev)
size_t size;
size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */
- size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */
+ size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
- size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */
- size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */
+ size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */
+ size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
- size += sizeof(struct can_berr_counter);
+ size += nla_total_size(sizeof(struct can_berr_counter));
if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */
- size += sizeof(struct can_bittiming_const);
+ size += nla_total_size(sizeof(struct can_bittiming_const));
return size;
}
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 1767811..b1f354f 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -33,10 +33,9 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
-#include <mach/clock.h>
-
#define DRV_NAME "flexcan"
/* 8 for RX fifo and 2 error handling */
@@ -61,7 +60,7 @@
#define FLEXCAN_MCR_BCC BIT(16)
#define FLEXCAN_MCR_LPRIO_EN BIT(13)
#define FLEXCAN_MCR_AEN BIT(12)
-#define FLEXCAN_MCR_MAXMB(x) ((x) & 0xf)
+#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x1f)
#define FLEXCAN_MCR_IDAM_A (0 << 8)
#define FLEXCAN_MCR_IDAM_B (1 << 8)
#define FLEXCAN_MCR_IDAM_C (2 << 8)
@@ -121,7 +120,9 @@
(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
/* FLEXCAN interrupt flag register (IFLAG) bits */
-#define FLEXCAN_TX_BUF_ID 8
+/* Errata ERR005829 step7: Reserve first valid MB */
+#define FLEXCAN_TX_BUF_RESERVED 8
+#define FLEXCAN_TX_BUF_ID 9
#define FLEXCAN_IFLAG_BUF(x) BIT(x)
#define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7)
#define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6)
@@ -132,6 +133,17 @@
/* FLEXCAN message buffers */
#define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24)
+#define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24)
+#define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24)
+#define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24)
+#define FLEXCAN_MB_CODE_RX_OVERRRUN (0x6 << 24)
+#define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24)
+
+#define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24)
+#define FLEXCAN_MB_CODE_TX_ABORT (0x9 << 24)
+#define FLEXCAN_MB_CODE_TX_DATA (0xc << 24)
+#define FLEXCAN_MB_CODE_TX_TANSWER (0xe << 24)
+
#define FLEXCAN_MB_CNT_SRR BIT(22)
#define FLEXCAN_MB_CNT_IDE BIT(21)
#define FLEXCAN_MB_CNT_RTR BIT(20)
@@ -192,6 +204,31 @@ static struct can_bittiming_const flexcan_bittiming_const = {
};
/*
+ * Abstract off the read/write for arm versus ppc.
+ */
+#if defined(__BIG_ENDIAN)
+static inline u32 flexcan_read(void __iomem *addr)
+{
+ return in_be32(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+ out_be32(addr, val);
+}
+#else
+static inline u32 flexcan_read(void __iomem *addr)
+{
+ return readl(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+ writel(val, addr);
+}
+#endif
+
+/*
* Swtich transceiver on or off
*/
static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on)
@@ -212,9 +249,9 @@ static inline void flexcan_chip_enable(struct flexcan_priv *priv)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg &= ~FLEXCAN_MCR_MDIS;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
udelay(10);
}
@@ -224,9 +261,9 @@ static inline void flexcan_chip_disable(struct flexcan_priv *priv)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg |= FLEXCAN_MCR_MDIS;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
}
static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -234,7 +271,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
{
const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base;
- u32 reg = readl(&regs->ecr);
+ u32 reg = flexcan_read(&regs->ecr);
bec->txerr = (reg >> 0) & 0xff;
bec->rxerr = (reg >> 8) & 0xff;
@@ -268,15 +305,23 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (cf->can_dlc > 0) {
u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
- writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
+ flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
}
if (cf->can_dlc > 3) {
u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
- writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
+ flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
}
- writel(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
- writel(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+ flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
+ flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+
+ /* Errata ERR005829 step8:
+ * Write twice INACTIVE(0x8) code to first MB.
+ */
+ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+ &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+ &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
kfree_skb(skb);
@@ -464,8 +509,8 @@ static void flexcan_read_fifo(const struct net_device *dev,
struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
u32 reg_ctrl, reg_id;
- reg_ctrl = readl(&mb->can_ctrl);
- reg_id = readl(&mb->can_id);
+ reg_ctrl = flexcan_read(&mb->can_ctrl);
+ reg_id = flexcan_read(&mb->can_id);
if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
else
@@ -475,12 +520,12 @@ static void flexcan_read_fifo(const struct net_device *dev,
cf->can_id |= CAN_RTR_FLAG;
cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
- *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0]));
- *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1]));
+ *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0]));
+ *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1]));
/* mark as read */
- writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
- readl(&regs->timer);
+ flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
+ flexcan_read(&regs->timer);
}
static int flexcan_read_frame(struct net_device *dev)
@@ -516,17 +561,17 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
* The error bits are cleared on read,
* use saved value from irq handler.
*/
- reg_esr = readl(&regs->esr) | priv->reg_esr;
+ reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
/* handle state changes */
work_done += flexcan_poll_state(dev, reg_esr);
/* handle RX-FIFO */
- reg_iflag1 = readl(&regs->iflag1);
+ reg_iflag1 = flexcan_read(&regs->iflag1);
while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
work_done < quota) {
work_done += flexcan_read_frame(dev);
- reg_iflag1 = readl(&regs->iflag1);
+ reg_iflag1 = flexcan_read(&regs->iflag1);
}
/* report bus errors */
@@ -536,8 +581,8 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
if (work_done < quota) {
napi_complete(napi);
/* enable IRQs */
- writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
- writel(priv->reg_ctrl_default, &regs->ctrl);
+ flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+ flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
}
return work_done;
@@ -551,9 +596,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg_iflag1, reg_esr;
- reg_iflag1 = readl(&regs->iflag1);
- reg_esr = readl(&regs->esr);
- writel(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
+ reg_iflag1 = flexcan_read(&regs->iflag1);
+ reg_esr = flexcan_read(&regs->esr);
+ flexcan_write(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
/*
* schedule NAPI in case of:
@@ -569,16 +614,16 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
* save them for later use.
*/
priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
- writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE,
- &regs->imask1);
- writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+ flexcan_write(FLEXCAN_IFLAG_DEFAULT &
+ ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
+ flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
&regs->ctrl);
napi_schedule(&priv->napi);
}
/* FIFO overflow */
if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
- writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
+ flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
dev->stats.rx_over_errors++;
dev->stats.rx_errors++;
}
@@ -587,7 +632,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
/* tx_bytes is incremented in flexcan_start_xmit */
stats->tx_packets++;
- writel((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
+ /* after sending a RTR frame mailbox is in RX mode */
+ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+ &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+ flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
netif_wake_queue(dev);
}
@@ -601,7 +649,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- reg = readl(&regs->ctrl);
+ reg = flexcan_read(&regs->ctrl);
reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
FLEXCAN_CTRL_RJW(0x3) |
FLEXCAN_CTRL_PSEG1(0x7) |
@@ -625,11 +673,11 @@ static void flexcan_set_bittiming(struct net_device *dev)
reg |= FLEXCAN_CTRL_SMP;
dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg);
- writel(reg, &regs->ctrl);
+ flexcan_write(reg, &regs->ctrl);
/* print chip status */
dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
- readl(&regs->mcr), readl(&regs->ctrl));
+ flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
}
/*
@@ -642,18 +690,18 @@ static int flexcan_chip_start(struct net_device *dev)
{
struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base;
- unsigned int i;
int err;
u32 reg_mcr, reg_ctrl;
+ int i;
/* enable module */
flexcan_chip_enable(priv);
/* soft reset */
- writel(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+ flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
udelay(10);
- reg_mcr = readl(&regs->mcr);
+ reg_mcr = flexcan_read(&regs->mcr);
if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
dev_err(dev->dev.parent,
"Failed to softreset can module (mcr=0x%08x)\n",
@@ -675,12 +723,14 @@ static int flexcan_chip_start(struct net_device *dev)
* choose format C
*
*/
- reg_mcr = readl(&regs->mcr);
+ reg_mcr = flexcan_read(&regs->mcr);
+ reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
- FLEXCAN_MCR_IDAM_C;
+ FLEXCAN_MCR_IDAM_C |
+ FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
- writel(reg_mcr, &regs->mcr);
+ flexcan_write(reg_mcr, &regs->mcr);
/*
* CTRL
@@ -698,7 +748,7 @@ static int flexcan_chip_start(struct net_device *dev)
* (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
* warning or bus passive interrupts.
*/
- reg_ctrl = readl(&regs->ctrl);
+ reg_ctrl = flexcan_read(&regs->ctrl);
reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK;
@@ -706,38 +756,42 @@ static int flexcan_chip_start(struct net_device *dev)
/* save for later use */
priv->reg_ctrl_default = reg_ctrl;
dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
- writel(reg_ctrl, &regs->ctrl);
-
- for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) {
- writel(0, &regs->cantxfg[i].can_ctrl);
- writel(0, &regs->cantxfg[i].can_id);
- writel(0, &regs->cantxfg[i].data[0]);
- writel(0, &regs->cantxfg[i].data[1]);
+ flexcan_write(reg_ctrl, &regs->ctrl);
- /* put MB into rx queue */
- writel(FLEXCAN_MB_CNT_CODE(0x4), &regs->cantxfg[i].can_ctrl);
+ /* clear and invalidate all mailboxes first */
+ for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) {
+ flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
+ &regs->cantxfg[i].can_ctrl);
}
+ /* Errata ERR005829: mark first TX mailbox as INACTIVE */
+ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+ &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+
+ /* mark TX mailbox as INACTIVE */
+ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+ &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+
/* acceptance mask/acceptance code (accept everything) */
- writel(0x0, &regs->rxgmask);
- writel(0x0, &regs->rx14mask);
- writel(0x0, &regs->rx15mask);
+ flexcan_write(0x0, &regs->rxgmask);
+ flexcan_write(0x0, &regs->rx14mask);
+ flexcan_write(0x0, &regs->rx15mask);
flexcan_transceiver_switch(priv, 1);
/* synchronize with the can bus */
- reg_mcr = readl(&regs->mcr);
+ reg_mcr = flexcan_read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_HALT;
- writel(reg_mcr, &regs->mcr);
+ flexcan_write(reg_mcr, &regs->mcr);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* enable FIFO interrupts */
- writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+ flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
/* print chip status */
dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n",
- __func__, readl(&regs->mcr), readl(&regs->ctrl));
+ __func__, flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
return 0;
@@ -758,13 +812,15 @@ static void flexcan_chip_stop(struct net_device *dev)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- /* Disable all interrupts */
- writel(0, &regs->imask1);
-
/* Disable + halt module */
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
+
+ /* Disable all interrupts */
+ flexcan_write(0, &regs->imask1);
+ flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+ &regs->ctrl);
flexcan_transceiver_switch(priv, 0);
priv->can.state = CAN_STATE_STOPPED;
@@ -790,12 +846,14 @@ static int flexcan_open(struct net_device *dev)
/* start chip and queuing */
err = flexcan_chip_start(dev);
if (err)
- goto out_close;
+ goto out_free_irq;
napi_enable(&priv->napi);
netif_start_queue(dev);
return 0;
+ out_free_irq:
+ free_irq(dev->irq, dev);
out_close:
close_candev(dev);
out:
@@ -856,24 +914,24 @@ static int __devinit register_flexcandev(struct net_device *dev)
/* select "bus clock", chip must be disabled */
flexcan_chip_disable(priv);
- reg = readl(&regs->ctrl);
+ reg = flexcan_read(&regs->ctrl);
reg |= FLEXCAN_CTRL_CLK_SRC;
- writel(reg, &regs->ctrl);
+ flexcan_write(reg, &regs->ctrl);
flexcan_chip_enable(priv);
/* set freeze, halt and activate FIFO, restrict register access */
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
/*
* Currently we only support newer versions of this core
* featuring a RX FIFO. Older cores found on some Coldfire
* derivates are not yet supported.
*/
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
if (!(reg & FLEXCAN_MCR_FEN)) {
dev_err(dev->dev.parent,
"Could not enable RX FIFO, unsupported core\n");
@@ -901,16 +959,29 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
struct net_device *dev;
struct flexcan_priv *priv;
struct resource *mem;
- struct clk *clk;
+ struct clk *clk = NULL;
void __iomem *base;
resource_size_t mem_size;
int err, irq;
+ u32 clock_freq = 0;
+
+ if (pdev->dev.of_node) {
+ const __be32 *clock_freq_p;
+
+ clock_freq_p = of_get_property(pdev->dev.of_node,
+ "clock-frequency", NULL);
+ if (clock_freq_p)
+ clock_freq = be32_to_cpup(clock_freq_p);
+ }
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "no clock defined\n");
- err = PTR_ERR(clk);
- goto failed_clock;
+ if (!clock_freq) {
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "no clock defined\n");
+ err = PTR_ERR(clk);
+ goto failed_clock;
+ }
+ clock_freq = clk_get_rate(clk);
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -943,7 +1014,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
dev->flags |= IFF_ECHO; /* we support local echo in hardware */
priv = netdev_priv(dev);
- priv->can.clock.freq = clk_get_rate(clk);
+ priv->can.clock.freq = clock_freq;
priv->can.bittiming_const = &flexcan_bittiming_const;
priv->can.do_set_mode = flexcan_set_mode;
priv->can.do_get_berr_counter = flexcan_get_berr_counter;
@@ -978,7 +1049,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
failed_map:
release_mem_region(mem->start, mem_size);
failed_get:
- clk_put(clk);
+ if (clk)
+ clk_put(clk);
failed_clock:
return err;
}
@@ -990,21 +1062,34 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
struct resource *mem;
unregister_flexcandev(dev);
+ netif_napi_del(&priv->napi);
platform_set_drvdata(pdev, NULL);
iounmap(priv->base);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
- clk_put(priv->clk);
+ if (priv->clk)
+ clk_put(priv->clk);
free_candev(dev);
return 0;
}
+static struct of_device_id flexcan_of_match[] = {
+ {
+ .compatible = "fsl,p1010-flexcan",
+ },
+ {},
+};
+
static struct platform_driver flexcan_driver = {
- .driver.name = DRV_NAME,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = flexcan_of_match,
+ },
.probe = flexcan_probe,
.remove = __devexit_p(flexcan_remove),
};
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index b4159a6..46194bc 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -22,6 +22,7 @@
#include <linux/can/error.h>
#include <linux/mfd/janz.h>
+#include <asm/io.h>
/* the DPM has 64k of memory, organized into 256x 256 byte pages */
#define DPM_NUM_PAGES 256
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 92feac6..ec4a311 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -62,7 +62,7 @@ static enum can_state state_map[] = {
static int mscan_set_mode(struct net_device *dev, u8 mode)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
int ret = 0;
int i;
u8 canctl1;
@@ -138,7 +138,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
static int mscan_start(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u8 canrflg;
int err;
@@ -178,7 +178,7 @@ static int mscan_restart(struct net_device *dev)
struct mscan_priv *priv = netdev_priv(dev);
if (priv->type == MSCAN_TYPE_MPC5121) {
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
@@ -199,7 +199,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct can_frame *frame = (struct can_frame *)skb->data;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
int i, rtr, buf_id;
u32 can_id;
@@ -261,11 +261,13 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
void __iomem *data = &regs->tx.dsr1_0;
u16 *payload = (u16 *)frame->data;
- /* It is safe to write into dsr[dlc+1] */
- for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
+ for (i = 0; i < frame->can_dlc / 2; i++) {
out_be16(data, *payload++);
data += 2 + _MSCAN_RESERVED_DSR_SIZE;
}
+ /* write remaining byte if necessary */
+ if (frame->can_dlc & 1)
+ out_8(data, frame->data[frame->can_dlc - 1]);
}
out_8(&regs->tx.dlr, frame->can_dlc);
@@ -305,7 +307,7 @@ static enum can_state check_set_state(struct net_device *dev, u8 canrflg)
static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u32 can_id;
int i;
@@ -330,10 +332,13 @@ static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
void __iomem *data = &regs->rx.dsr1_0;
u16 *payload = (u16 *)frame->data;
- for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
+ for (i = 0; i < frame->can_dlc / 2; i++) {
*payload++ = in_be16(data);
data += 2 + _MSCAN_RESERVED_DSR_SIZE;
}
+ /* read remaining byte if necessary */
+ if (frame->can_dlc & 1)
+ frame->data[frame->can_dlc - 1] = in_8(data);
}
out_8(&regs->canrflg, MSCAN_RXF);
@@ -343,7 +348,7 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
u8 canrflg)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
enum can_state old_state;
@@ -406,7 +411,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
{
struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
struct net_device *dev = napi->dev;
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
int npackets = 0;
int ret = 1;
@@ -453,7 +458,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
u8 cantier, cantflg, canrflg;
irqreturn_t ret = IRQ_NONE;
@@ -537,7 +542,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
static int mscan_do_set_bittiming(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct can_bittiming *bt = &priv->can.bittiming;
u8 btr0, btr1;
@@ -559,7 +564,7 @@ static int mscan_open(struct net_device *dev)
{
int ret;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
/* common open */
ret = open_candev(dev);
@@ -598,7 +603,7 @@ exit_napi_disable:
static int mscan_close(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
netif_stop_queue(dev);
napi_disable(&priv->napi);
@@ -622,7 +627,7 @@ static const struct net_device_ops mscan_netdev_ops = {
int register_mscandev(struct net_device *dev, int mscan_clksrc)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u8 ctl1;
ctl1 = in_8(&regs->canctl1);
@@ -659,7 +664,7 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)
void unregister_mscandev(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
mscan_set_mode(dev, MSCAN_INIT_MODE);
clrbits8(&regs->canctl1, MSCAN_CANE);
unregister_candev(dev);
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 6fdc031..fe9e64d 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -29,6 +29,13 @@ config CAN_SJA1000_OF_PLATFORM
OpenFirmware bindings, e.g. if you have a PowerPC based system
you may want to enable this option.
+config CAN_EMS_PCMCIA
+ tristate "EMS CPC-CARD Card"
+ depends on PCMCIA
+ ---help---
+ This driver is for the one or two channel CPC-CARD cards from
+ EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
config CAN_EMS_PCI
tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card"
depends on PCI
@@ -37,6 +44,13 @@ config CAN_EMS_PCI
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
(http://www.ems-wuensche.de).
+config CAN_PEAK_PCI
+ tristate "PEAK PCAN PCI/PCIe Cards"
+ depends on PCI
+ ---help---
+ This driver is for the PCAN PCI/PCIe cards (1, 2, 3 or 4 channels)
+ from PEAK Systems (http://www.peak-system.com).
+
config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
depends on PCI
diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile
index 2c591eb..0604f24 100644
--- a/drivers/net/can/sja1000/Makefile
+++ b/drivers/net/can/sja1000/Makefile
@@ -6,8 +6,10 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000.o
obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
+obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
+obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o
obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index 231385b..c31c2d6 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -309,7 +309,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
*/
if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
REG_CR_BASICCAN_INITIAL &&
- (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
+ (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) &&
(priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
flag = 1;
@@ -321,7 +321,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
* See states on p. 23 of the Datasheet.
*/
if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
- priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
+ priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL &&
priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
return flag;
@@ -408,7 +408,7 @@ static void plx_pci_del_card(struct pci_dev *pdev)
struct sja1000_priv *priv;
int i = 0;
- for (i = 0; i < card->channels; i++) {
+ for (i = 0; i < PLX_PCI_MAX_CHAN; i++) {
dev = card->net_dev[i];
if (!dev)
continue;
@@ -536,7 +536,6 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
if (err) {
dev_err(&pdev->dev, "Registering device failed "
"(err=%d)\n", err);
- free_sja1000dev(dev);
goto failure_cleanup;
}
@@ -549,6 +548,7 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
dev_err(&pdev->dev, "Channel #%d not detected\n",
i + 1);
free_sja1000dev(dev);
+ card->net_dev[i] = NULL;
}
}
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index f501bba..568b821 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -40,8 +40,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
@@ -93,15 +91,20 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
*/
spin_lock_irqsave(&priv->cmdreg_lock, flags);
priv->write_reg(priv, REG_CMR, val);
- priv->read_reg(priv, REG_SR);
+ priv->read_reg(priv, SJA1000_REG_SR);
spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
}
+static int sja1000_is_absent(struct sja1000_priv *priv)
+{
+ return (priv->read_reg(priv, REG_MOD) == 0xFF);
+}
+
static int sja1000_probe_chip(struct net_device *dev)
{
struct sja1000_priv *priv = netdev_priv(dev);
- if (priv->reg_base && (priv->read_reg(priv, 0) == 0xFF)) {
+ if (priv->reg_base && sja1000_is_absent(priv)) {
printk(KERN_INFO "%s: probing @0x%lX failed\n",
DRV_NAME, dev->base_addr);
return 0;
@@ -485,16 +488,19 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
uint8_t isrc, status;
int n = 0;
- /* Shared interrupts and IRQ off? */
- if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
- return IRQ_NONE;
-
if (priv->pre_irq)
priv->pre_irq(priv);
+ /* Shared interrupts and IRQ off? */
+ if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
+ goto out;
+
while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
- n++;
- status = priv->read_reg(priv, REG_SR);
+
+ status = priv->read_reg(priv, SJA1000_REG_SR);
+ /* check for absent controller due to hw unplug */
+ if (status == 0xFF && sja1000_is_absent(priv))
+ goto out;
if (isrc & IRQ_WUI)
dev_warn(dev->dev.parent, "wakeup interrupt\n");
@@ -510,7 +516,10 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
/* receive interrupt */
while (status & SR_RBS) {
sja1000_rx(dev);
- status = priv->read_reg(priv, REG_SR);
+ status = priv->read_reg(priv, SJA1000_REG_SR);
+ /* check for absent controller */
+ if (status == 0xFF && sja1000_is_absent(priv))
+ goto out;
}
}
if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
@@ -518,8 +527,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
if (sja1000_err(dev, isrc, status))
break;
}
+ n++;
}
-
+out:
if (priv->post_irq)
priv->post_irq(priv);
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index de8e778..2a79543 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -40,13 +40,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#ifndef SJA1000_DEV_H
#define SJA1000_DEV_H
+#include <linux/irqreturn.h>
#include <linux/can/dev.h>
#include <linux/can/platform/sja1000.h>
@@ -57,7 +56,7 @@
/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
#define REG_MOD 0x00
#define REG_CMR 0x01
-#define REG_SR 0x02
+#define SJA1000_REG_SR 0x02
#define REG_IR 0x03
#define REG_IER 0x04
#define REG_ALC 0x0B
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 9793df6..1ee5f0c 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -29,7 +29,7 @@
* nxp,external-clock-frequency = <16000000>;
* };
*
- * See "Documentation/powerpc/dts-bindings/can/sja1000.txt" for further
+ * See "Documentation/devicetree/bindings/net/can/sja1000.txt" for further
* information.
*/
@@ -38,6 +38,7 @@
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <linux/can/dev.h>
#include <linux/of_platform.h>
@@ -93,8 +94,8 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
struct net_device *dev;
struct sja1000_priv *priv;
struct resource res;
- const u32 *prop;
- int err, irq, res_size, prop_size;
+ u32 prop;
+ int err, irq, res_size;
void __iomem *base;
err = of_address_to_resource(np, 0, &res);
@@ -135,27 +136,27 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
priv->read_reg = sja1000_ofp_read_reg;
priv->write_reg = sja1000_ofp_write_reg;
- prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->can.clock.freq = *prop / 2;
+ err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
+ if (!err)
+ priv->can.clock.freq = prop / 2;
else
priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
- prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= *prop & OCR_MODE_MASK;
+ err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
+ if (!err)
+ priv->ocr |= prop & OCR_MODE_MASK;
else
priv->ocr |= OCR_MODE_NORMAL; /* default */
- prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+ err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
+ if (!err)
+ priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
else
priv->ocr |= OCR_TX0_PULLDOWN; /* default */
- prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)) && *prop) {
- u32 divider = priv->can.clock.freq * 2 / *prop;
+ err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
+ if (!err && prop) {
+ u32 divider = priv->can.clock.freq * 2 / prop;
if (divider > 1)
priv->cdr |= divider / 2 - 1;
@@ -165,8 +166,7 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
priv->cdr |= CDR_CLK_OFF; /* default */
}
- prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
- if (!prop)
+ if (!of_property_read_bool(np, "nxp,no-comparator-bypass"))
priv->cdr |= CDR_CBP; /* default */
priv->irq_flags = IRQF_SHARED;
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 1b49df6..a979b00 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -35,8 +35,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
@@ -56,6 +54,7 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/can.h>
static __initdata const char banner[] =
@@ -95,10 +94,6 @@ struct slcan {
unsigned long flags; /* Flag values/ mode etc */
#define SLF_INUSE 0 /* Channel in use */
#define SLF_ERROR 1 /* Parity, etc. error */
-
- unsigned char leased;
- dev_t line;
- pid_t pid;
};
static struct net_device **slcan_devs;
@@ -142,21 +137,6 @@ static struct net_device **slcan_devs;
* STANDARD SLCAN DECAPSULATION *
************************************************************************/
-static int asc2nibble(char c)
-{
-
- if ((c >= '0') && (c <= '9'))
- return c - '0';
-
- if ((c >= 'A') && (c <= 'F'))
- return c - 'A' + 10;
-
- if ((c >= 'a') && (c <= 'f'))
- return c - 'a' + 10;
-
- return 16; /* error */
-}
-
/* Send one completely decapsulated can_frame to the network layer */
static void slc_bump(struct slcan *sl)
{
@@ -195,18 +175,16 @@ static void slc_bump(struct slcan *sl)
*(u64 *) (&cf.data) = 0; /* clear payload */
for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
-
- tmp = asc2nibble(sl->rbuff[dlc_pos++]);
- if (tmp > 0x0F)
+ tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
+ if (tmp < 0)
return;
cf.data[i] = (tmp << 4);
- tmp = asc2nibble(sl->rbuff[dlc_pos++]);
- if (tmp > 0x0F)
+ tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
+ if (tmp < 0)
return;
cf.data[i] |= tmp;
}
-
skb = dev_alloc_skb(sizeof(struct can_frame));
if (!skb)
return;
@@ -217,7 +195,7 @@ static void slc_bump(struct slcan *sl)
skb->ip_summed = CHECKSUM_UNNECESSARY;
memcpy(skb_put(skb, sizeof(struct can_frame)),
&cf, sizeof(struct can_frame));
- netif_rx(skb);
+ netif_rx_ni(skb);
sl->dev->stats.rx_packets++;
sl->dev->stats.rx_bytes += cf.can_dlc;
@@ -462,7 +440,7 @@ static void slc_sync(void)
break;
sl = netdev_priv(dev);
- if (sl->tty || sl->leased)
+ if (sl->tty)
continue;
if (dev->flags & IFF_UP)
dev_close(dev);
@@ -473,12 +451,10 @@ static void slc_sync(void)
static struct slcan *slc_alloc(dev_t line)
{
int i;
+ char name[IFNAMSIZ];
struct net_device *dev = NULL;
struct slcan *sl;
- if (slcan_devs == NULL)
- return NULL; /* Master array missing ! */
-
for (i = 0; i < maxdev; i++) {
dev = slcan_devs[i];
if (dev == NULL)
@@ -490,25 +466,12 @@ static struct slcan *slc_alloc(dev_t line)
if (i >= maxdev)
return NULL;
- if (dev) {
- sl = netdev_priv(dev);
- if (test_bit(SLF_INUSE, &sl->flags)) {
- unregister_netdevice(dev);
- dev = NULL;
- slcan_devs[i] = NULL;
- }
- }
-
- if (!dev) {
- char name[IFNAMSIZ];
- sprintf(name, "slcan%d", i);
-
- dev = alloc_netdev(sizeof(*sl), name, slc_setup);
- if (!dev)
- return NULL;
- dev->base_addr = i;
- }
+ sprintf(name, "slcan%d", i);
+ dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+ if (!dev)
+ return NULL;
+ dev->base_addr = i;
sl = netdev_priv(dev);
/* Initialize channel control data */
@@ -565,8 +528,6 @@ static int slcan_open(struct tty_struct *tty)
sl->tty = tty;
tty->disc_data = sl;
- sl->line = tty_devnum(tty);
- sl->pid = current->pid;
if (!test_bit(SLF_INUSE, &sl->flags)) {
/* Perform the low-level SLCAN initialization. */
@@ -617,8 +578,6 @@ static void slcan_close(struct tty_struct *tty)
tty->disc_data = NULL;
sl->tty = NULL;
- if (!sl->leased)
- sl->line = 0;
/* Flush network side */
unregister_netdev(sl->dev);
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
index b520784..3105961 100644
--- a/drivers/net/can/softing/softing_fw.c
+++ b/drivers/net/can/softing/softing_fw.c
@@ -20,6 +20,7 @@
#include <linux/firmware.h>
#include <linux/sched.h>
#include <asm/div64.h>
+#include <asm/io.h>
#include "softing.h"
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 60a49e5..09a8b86 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -17,10 +17,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "softing.h"
@@ -799,7 +799,7 @@ static __devinit int softing_pdev_probe(struct platform_device *pdev)
if (!pres)
goto platform_resource_failed;
card->dpram_phys = pres->start;
- card->dpram_size = pres->end - pres->start + 1;
+ card->dpram_size = resource_size(pres);
card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size);
if (!card->dpram) {
dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 10b2394..1ef9df8 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -46,6 +46,7 @@
#include <linux/skbuff.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/io.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
@@ -503,9 +504,9 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
spin_unlock_irqrestore(&priv->mbx_lock, flags);
/* Prepare mailbox for transmission */
+ data = cf->can_dlc | (get_tx_head_prio(priv) << 8);
if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */
data |= HECC_CANMCF_RTR;
- data |= get_tx_head_prio(priv) << 8;
hecc_write_mbx(priv, mbxno, HECC_CANMCF, data);
if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
@@ -923,6 +924,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
priv->can.do_get_state = ti_hecc_get_state;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+ spin_lock_init(&priv->mbx_lock);
ndev->irq = irq->start;
ndev->flags |= IFF_ECHO;
platform_set_drvdata(pdev, ndev);
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index eb8b0e6..9ecf098 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -1097,6 +1097,7 @@ static void esd_usb2_disconnect(struct usb_interface *intf)
}
}
unlink_all_urbs(dev);
+ kfree(dev);
}
}
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index a30b8f4..f93e2d6 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -37,8 +37,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index e66aceb..7cb2785 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -261,7 +261,7 @@ static const struct net_device_ops e100_netdev_ops = {
.ndo_start_xmit = e100_send_packet,
.ndo_tx_timeout = e100_tx_timeout,
.ndo_get_stats = e100_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = e100_ioctl,
.ndo_set_mac_address = e100_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 0d28378..2a5a34d 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -36,7 +36,7 @@
#include <linux/tcp.h>
#include <linux/semaphore.h>
#include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define SIXPACK_VERSION "Revision: 0.3.0"
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 99cdce3..a974727 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -76,6 +76,7 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
#include <linux/jiffies.h>
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index d92fe6c..e349d86 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -66,6 +66,7 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/hdlcdrv.h>
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 52b1425..ce555d9 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -36,7 +36,7 @@
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index a4a3516..3b3a7e0 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case HDLCDRVCTL_CALIBRATE:
if(!capable(CAP_SYS_RAWIO))
return -EPERM;
+ if (bi.data.calibrate > INT_MAX / s->par.bitrate)
+ return -EINVAL;
s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
return 0;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 96a98d2..e4260ab 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -1060,6 +1060,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
case SIOCYAMGCFG:
+ memset(&yi, 0, sizeof(yi));
yi.cfg.mask = 0xffffffff;
yi.cfg.iobase = yp->iobase;
yi.cfg.irq = yp->irq;
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 25bb2a0..d423d18 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -183,7 +183,7 @@ config OLD_BELKIN_DONGLE
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. If you want to compile it as a module, choose
M here. Some information is contained in the comments
- at the top of <file:drivers/net/irda/old_belkin.c>.
+ at the top of <file:drivers/net/irda/old_belkin-sir.c>.
config ACT200L_DONGLE
tristate "ACTiSYS IR-200L dongle"
@@ -314,7 +314,7 @@ config TOSHIBA_FIR
config AU1000_FIR
tristate "Alchemy Au1000 SIR/FIR"
- depends on SOC_AU1000 && IRDA
+ depends on IRDA && MIPS_ALCHEMY
config SMC_IRCC_FIR
tristate "SMSC IrCC (EXPERIMENTAL)"
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index d532dde..963067d 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 174cafa..b45b2cc 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -152,6 +152,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 7a963d4..b56636d 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -52,6 +52,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/pnp.h>
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 001ed0a..d0851df 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -12,6 +12,8 @@
* Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
*
*/
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c
index 4488bd5..d275e27 100644
--- a/drivers/net/irda/sh_irda.c
+++ b/drivers/net/irda/sh_irda.c
@@ -2,7 +2,7 @@
* SuperH IrDA Driver
*
* Copyright (C) 2010 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* Based on sh_sir.c
* Copyright (C) 2009 Renesas Solutions Corp.
@@ -22,8 +22,11 @@
* - DMA transfer support
* - FIFO mode support
*/
+#include <linux/io.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
@@ -142,8 +145,8 @@ struct sh_irda_xir_func {
struct sh_irda_self {
void __iomem *membase;
- unsigned int irq;
- struct clk *clk;
+ unsigned int irq;
+ struct platform_device *pdev;
struct net_device *ndev;
@@ -262,7 +265,7 @@ static int sh_irda_set_baudrate(struct sh_irda_self *self, int baudrate)
return 0;
}
-static int xir_get_rcv_length(struct sh_irda_self *self)
+static int sh_irda_get_rcv_length(struct sh_irda_self *self)
{
return RFL_MASK & sh_irda_read(self, IRRFLR);
}
@@ -272,47 +275,47 @@ static int xir_get_rcv_length(struct sh_irda_self *self)
* NONE MODE
*
*=====================================*/
-static int xir_fre(struct sh_irda_self *self)
+static int sh_irda_xir_fre(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: frame recv\n");
return 0;
}
-static int xir_trov(struct sh_irda_self *self)
+static int sh_irda_xir_trov(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: buffer ram over\n");
return 0;
}
-static int xir_9(struct sh_irda_self *self)
+static int sh_irda_xir_9(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: time over\n");
return 0;
}
-static int xir_8(struct sh_irda_self *self)
+static int sh_irda_xir_8(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: framing error\n");
return 0;
}
-static int xir_fte(struct sh_irda_self *self)
+static int sh_irda_xir_fte(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: frame transmit end\n");
return 0;
}
-static struct sh_irda_xir_func xir_func = {
- .xir_fre = xir_fre,
- .xir_trov = xir_trov,
- .xir_9 = xir_9,
- .xir_8 = xir_8,
- .xir_fte = xir_fte,
+static struct sh_irda_xir_func sh_irda_xir_func = {
+ .xir_fre = sh_irda_xir_fre,
+ .xir_trov = sh_irda_xir_trov,
+ .xir_9 = sh_irda_xir_9,
+ .xir_8 = sh_irda_xir_8,
+ .xir_fte = sh_irda_xir_fte,
};
/*=====================================
@@ -321,12 +324,12 @@ static struct sh_irda_xir_func xir_func = {
*
* MIR/FIR are not supported now
*=====================================*/
-static struct sh_irda_xir_func mfir_func = {
- .xir_fre = xir_fre,
- .xir_trov = xir_trov,
- .xir_9 = xir_9,
- .xir_8 = xir_8,
- .xir_fte = xir_fte,
+static struct sh_irda_xir_func sh_irda_mfir_func = {
+ .xir_fre = sh_irda_xir_fre,
+ .xir_trov = sh_irda_xir_trov,
+ .xir_9 = sh_irda_xir_9,
+ .xir_8 = sh_irda_xir_8,
+ .xir_fte = sh_irda_xir_fte,
};
/*=====================================
@@ -334,12 +337,12 @@ static struct sh_irda_xir_func mfir_func = {
* SIR MODE
*
*=====================================*/
-static int sir_fre(struct sh_irda_self *self)
+static int sh_irda_sir_fre(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
u16 data16;
u8 *data = (u8 *)&data16;
- int len = xir_get_rcv_length(self);
+ int len = sh_irda_get_rcv_length(self);
int i, j;
if (len > IRDARAM_LEN)
@@ -362,7 +365,7 @@ static int sir_fre(struct sh_irda_self *self)
return 0;
}
-static int sir_trov(struct sh_irda_self *self)
+static int sh_irda_sir_trov(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -371,7 +374,7 @@ static int sir_trov(struct sh_irda_self *self)
return 0;
}
-static int sir_tot(struct sh_irda_self *self)
+static int sh_irda_sir_tot(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -381,7 +384,7 @@ static int sir_tot(struct sh_irda_self *self)
return 0;
}
-static int sir_fer(struct sh_irda_self *self)
+static int sh_irda_sir_fer(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -390,7 +393,7 @@ static int sir_fer(struct sh_irda_self *self)
return 0;
}
-static int sir_fte(struct sh_irda_self *self)
+static int sh_irda_sir_fte(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -400,12 +403,12 @@ static int sir_fte(struct sh_irda_self *self)
return 0;
}
-static struct sh_irda_xir_func sir_func = {
- .xir_fre = sir_fre,
- .xir_trov = sir_trov,
- .xir_9 = sir_tot,
- .xir_8 = sir_fer,
- .xir_fte = sir_fte,
+static struct sh_irda_xir_func sh_irda_sir_func = {
+ .xir_fre = sh_irda_sir_fre,
+ .xir_trov = sh_irda_sir_trov,
+ .xir_9 = sh_irda_sir_tot,
+ .xir_8 = sh_irda_sir_fer,
+ .xir_fte = sh_irda_sir_fte,
};
static void sh_irda_set_mode(struct sh_irda_self *self, enum sh_irda_mode mode)
@@ -419,22 +422,22 @@ static void sh_irda_set_mode(struct sh_irda_self *self, enum sh_irda_mode mode)
case SH_IRDA_SIR:
name = "SIR";
data = TMD_SIR;
- func = &sir_func;
+ func = &sh_irda_sir_func;
break;
case SH_IRDA_MIR:
name = "MIR";
data = TMD_MIR;
- func = &mfir_func;
+ func = &sh_irda_mfir_func;
break;
case SH_IRDA_FIR:
name = "FIR";
data = TMD_FIR;
- func = &mfir_func;
+ func = &sh_irda_mfir_func;
break;
default:
- name = "NONE";
- data = 0;
- func = &xir_func;
+ name = "NONE";
+ data = 0;
+ func = &sh_irda_xir_func;
break;
}
@@ -692,7 +695,7 @@ static int sh_irda_open(struct net_device *ndev)
struct sh_irda_self *self = netdev_priv(ndev);
int err;
- clk_enable(self->clk);
+ pm_runtime_get_sync(&self->pdev->dev);
err = sh_irda_crc_init(self);
if (err)
goto open_err;
@@ -716,7 +719,7 @@ static int sh_irda_open(struct net_device *ndev)
return 0;
open_err:
- clk_disable(self->clk);
+ pm_runtime_put_sync(&self->pdev->dev);
return err;
}
@@ -732,6 +735,7 @@ static int sh_irda_stop(struct net_device *ndev)
}
netif_stop_queue(ndev);
+ pm_runtime_put_sync(&self->pdev->dev);
dev_info(&ndev->dev, "stoped\n");
@@ -784,11 +788,8 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
if (err)
goto err_mem_2;
- self->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(self->clk)) {
- dev_err(&pdev->dev, "cannot get irda clock\n");
- goto err_mem_3;
- }
+ self->pdev = pdev;
+ pm_runtime_enable(&pdev->dev);
irda_init_max_qos_capabilies(&self->qos);
@@ -818,8 +819,7 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
goto exit;
err_mem_4:
- clk_put(self->clk);
-err_mem_3:
+ pm_runtime_disable(&pdev->dev);
sh_irda_remove_iobuf(self);
err_mem_2:
iounmap(self->membase);
@@ -838,7 +838,7 @@ static int __devexit sh_irda_remove(struct platform_device *pdev)
return 0;
unregister_netdev(ndev);
- clk_put(self->clk);
+ pm_runtime_disable(&pdev->dev);
sh_irda_remove_iobuf(self);
iounmap(self->membase);
free_netdev(ndev);
@@ -847,11 +847,29 @@ static int __devexit sh_irda_remove(struct platform_device *pdev)
return 0;
}
+static int sh_irda_runtime_nop(struct device *dev)
+{
+ /* Runtime PM callback shared between ->runtime_suspend()
+ * and ->runtime_resume(). Simply returns success.
+ *
+ * This driver re-initializes all registers after
+ * pm_runtime_get_sync() anyway so there is no need
+ * to save and restore registers here.
+ */
+ return 0;
+}
+
+static const struct dev_pm_ops sh_irda_pm_ops = {
+ .runtime_suspend = sh_irda_runtime_nop,
+ .runtime_resume = sh_irda_runtime_nop,
+};
+
static struct platform_driver sh_irda_driver = {
- .probe = sh_irda_probe,
- .remove = __devexit_p(sh_irda_remove),
- .driver = {
- .name = DRIVER_NAME,
+ .probe = sh_irda_probe,
+ .remove = __devexit_p(sh_irda_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = &sh_irda_pm_ops,
},
};
@@ -868,6 +886,6 @@ static void __exit sh_irda_exit(void)
module_init(sh_irda_init);
module_exit(sh_irda_exit);
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("SuperH IrDA driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c
index 52a7c86..ed7d7d6 100644
--- a/drivers/net/irda/sh_sir.c
+++ b/drivers/net/irda/sh_sir.c
@@ -12,6 +12,8 @@
* published by the Free Software Foundation.
*/
+#include <linux/io.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -511,7 +513,7 @@ static void sh_sir_tx(struct sh_sir_self *self, int phase)
static int sh_sir_read_data(struct sh_sir_self *self)
{
- u16 val;
+ u16 val = 0;
int timeout = 1024;
while (timeout--) {
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index ddec154..43e9ab4 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -11,6 +11,7 @@
*
********************************************************************/
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 6a4826a..8b1c348 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -49,6 +49,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
@@ -2404,8 +2405,6 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
* addresses making a subsystem device table necessary.
*/
#ifdef CONFIG_PCI
-#define PCIID_VENDOR_INTEL 0x8086
-#define PCIID_VENDOR_ALI 0x10b9
static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = {
/*
* Subsystems needing entries:
@@ -2415,7 +2414,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
*/
{
/* Guessed entry */
- .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
.subvendor = 0x103c,
.subdevice = 0x08bc,
@@ -2428,7 +2427,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
.name = "HP nx5000 family",
},
{
- .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
.subvendor = 0x103c,
.subdevice = 0x088c,
@@ -2442,7 +2441,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
.name = "HP nc8000 family",
},
{
- .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
.subvendor = 0x103c,
.subdevice = 0x0890,
@@ -2455,7 +2454,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
.name = "HP nc6000 family",
},
{
- .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
.subvendor = 0x0e11,
.subdevice = 0x0860,
@@ -2470,7 +2469,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
},
{
/* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
- .vendor = PCIID_VENDOR_INTEL,
+ .vendor = PCI_VENDOR_ID_INTEL,
.device = 0x24c0,
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any" */
@@ -2483,7 +2482,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
.name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
},
{
- .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
+ .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801CAM ISA bridge */
.device = 0x248c,
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any" */
@@ -2497,7 +2496,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
},
{
/* 82801DBM (ICH4-M) LPC Interface Bridge */
- .vendor = PCIID_VENDOR_INTEL,
+ .vendor = PCI_VENDOR_ID_INTEL,
.device = 0x24cc,
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any" */
@@ -2511,7 +2510,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
},
{
/* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
- .vendor = PCIID_VENDOR_ALI,
+ .vendor = PCI_VENDOR_ID_AL,
.device = 0x1533,
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any" */
diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c
index 99e1ec0..19ad460 100644
--- a/drivers/net/irda/toim3232-sir.c
+++ b/drivers/net/irda/toim3232-sir.c
@@ -78,7 +78,7 @@
* Target hardware: IRWave IR320ST-2
*
* The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic
- * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever.
+ * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transceiver.
* It uses a hex inverter and some discrete components to buffer and
* line convert the RS232 down to 5V.
*
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index f504b26..6d64790 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -46,6 +46,7 @@ F02 Oct/28/02: Add SB device ID for 3147 and 3177.
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index c6f5848..f903a6a 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -210,7 +210,7 @@ static void DisableDmaChannel(unsigned int channel)
break;
default:
break;
- }; //Switch
+ }
}
static unsigned char ReadLPCReg(int iRegNum)
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index c3d0738..9021d01 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 1f9c3f08..c436660 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -47,6 +47,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/gfp.h>
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index d84c422..e8be47d 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -553,7 +553,7 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
/*
* There is no BCM5481 specification available, so down
* here is everything we know about "register 0x18". This
- * at least helps BCM5481 to successfuly receive packets
+ * at least helps BCM5481 to successfully receive packets
* on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
* says: "This sets delay between the RXD and RXC signals
* instead of using trace lengths to achieve timing".
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 364cd67..bb335ab 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -35,16 +35,15 @@
#define LAYER4 0x02
#define LAYER2 0x01
#define MAX_RXTS 64
-#define N_EXT_TS 1
+#define N_EXT_TS 6
#define PSF_PTPVER 2
#define PSF_EVNT 0x4000
#define PSF_RX 0x2000
#define PSF_TX 0x1000
#define EXT_EVENT 1
-#define EXT_GPIO 1
-#define CAL_EVENT 2
-#define CAL_GPIO 9
-#define CAL_TRIGGER 2
+#define CAL_EVENT 7
+#define CAL_TRIGGER 1
+#define PER_TRIGGER 6
/* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16
@@ -131,16 +130,30 @@ struct dp83640_clock {
/* globals */
+enum {
+ CALIBRATE_GPIO,
+ PEROUT_GPIO,
+ EXTTS0_GPIO,
+ EXTTS1_GPIO,
+ EXTTS2_GPIO,
+ EXTTS3_GPIO,
+ EXTTS4_GPIO,
+ EXTTS5_GPIO,
+ GPIO_TABLE_SIZE
+};
+
static int chosen_phy = -1;
-static ushort cal_gpio = 4;
+static ushort gpio_tab[GPIO_TABLE_SIZE] = {
+ 1, 2, 3, 4, 8, 9, 10, 11
+};
module_param(chosen_phy, int, 0444);
-module_param(cal_gpio, ushort, 0444);
+module_param_array(gpio_tab, ushort, NULL, 0444);
MODULE_PARM_DESC(chosen_phy, \
"The address of the PHY to use for the ancillary clock features");
-MODULE_PARM_DESC(cal_gpio, \
- "Which GPIO line to use for synchronizing multiple PHYs");
+MODULE_PARM_DESC(gpio_tab, \
+ "Which GPIO line to use for which purpose: cal,perout,extts1,...,extts6");
/* a list of clocks and a mutex to protect it */
static LIST_HEAD(phyter_clocks);
@@ -235,6 +248,61 @@ static u64 phy2txts(struct phy_txts *p)
return ns;
}
+static void periodic_output(struct dp83640_clock *clock,
+ struct ptp_clock_request *clkreq, bool on)
+{
+ struct dp83640_private *dp83640 = clock->chosen;
+ struct phy_device *phydev = dp83640->phydev;
+ u32 sec, nsec, period;
+ u16 gpio, ptp_trig, trigger, val;
+
+ gpio = on ? gpio_tab[PEROUT_GPIO] : 0;
+ trigger = PER_TRIGGER;
+
+ ptp_trig = TRIG_WR |
+ (trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT |
+ (gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT |
+ TRIG_PER |
+ TRIG_PULSE;
+
+ val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
+
+ if (!on) {
+ val |= TRIG_DIS;
+ mutex_lock(&clock->extreg_lock);
+ ext_write(0, phydev, PAGE5, PTP_TRIG, ptp_trig);
+ ext_write(0, phydev, PAGE4, PTP_CTL, val);
+ mutex_unlock(&clock->extreg_lock);
+ return;
+ }
+
+ sec = clkreq->perout.start.sec;
+ nsec = clkreq->perout.start.nsec;
+ period = clkreq->perout.period.sec * 1000000000UL;
+ period += clkreq->perout.period.nsec;
+
+ mutex_lock(&clock->extreg_lock);
+
+ ext_write(0, phydev, PAGE5, PTP_TRIG, ptp_trig);
+
+ /*load trigger*/
+ val |= TRIG_LOAD;
+ ext_write(0, phydev, PAGE4, PTP_CTL, val);
+ ext_write(0, phydev, PAGE4, PTP_TDR, nsec & 0xffff); /* ns[15:0] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, nsec >> 16); /* ns[31:16] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, sec & 0xffff); /* sec[15:0] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, sec >> 16); /* sec[31:16] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, period & 0xffff); /* ns[15:0] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, period >> 16); /* ns[31:16] */
+
+ /*enable trigger*/
+ val &= ~TRIG_LOAD;
+ val |= TRIG_EN;
+ ext_write(0, phydev, PAGE4, PTP_CTL, val);
+
+ mutex_unlock(&clock->extreg_lock);
+}
+
/* ptp clock methods */
static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
@@ -338,19 +406,30 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
struct dp83640_clock *clock =
container_of(ptp, struct dp83640_clock, caps);
struct phy_device *phydev = clock->chosen->phydev;
- u16 evnt;
+ int index;
+ u16 evnt, event_num, gpio_num;
switch (rq->type) {
case PTP_CLK_REQ_EXTTS:
- if (rq->extts.index != 0)
+ index = rq->extts.index;
+ if (index < 0 || index >= N_EXT_TS)
return -EINVAL;
- evnt = EVNT_WR | (EXT_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+ event_num = EXT_EVENT + index;
+ evnt = EVNT_WR | (event_num & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
if (on) {
- evnt |= (EXT_GPIO & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
+ gpio_num = gpio_tab[EXTTS0_GPIO + index];
+ evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
evnt |= EVNT_RISE;
}
ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
return 0;
+
+ case PTP_CLK_REQ_PEROUT:
+ if (rq->perout.index != 0)
+ return -EINVAL;
+ periodic_output(clock, rq, on);
+ return 0;
+
default:
break;
}
@@ -441,9 +520,10 @@ static void recalibrate(struct dp83640_clock *clock)
struct list_head *this;
struct dp83640_private *tmp;
struct phy_device *master = clock->chosen->phydev;
- u16 cfg0, evnt, ptp_trig, trigger, val;
+ u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val;
trigger = CAL_TRIGGER;
+ cal_gpio = gpio_tab[CALIBRATE_GPIO];
mutex_lock(&clock->extreg_lock);
@@ -542,11 +622,17 @@ static void recalibrate(struct dp83640_clock *clock)
/* time stamping methods */
+static inline u16 exts_chan_to_edata(int ch)
+{
+ return 1 << ((ch + EXT_EVENT) * 2);
+}
+
static int decode_evnt(struct dp83640_private *dp83640,
void *data, u16 ests)
{
struct phy_txts *phy_txts;
struct ptp_clock_event event;
+ int i, parsed;
int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
u16 ext_status = 0;
@@ -568,14 +654,25 @@ static int decode_evnt(struct dp83640_private *dp83640,
dp83640->edata.ns_lo = phy_txts->ns_lo;
}
+ if (ext_status) {
+ parsed = words + 2;
+ } else {
+ parsed = words + 1;
+ i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT;
+ ext_status = exts_chan_to_edata(i);
+ }
+
event.type = PTP_CLOCK_EXTTS;
- event.index = 0;
event.timestamp = phy2txts(&dp83640->edata);
- ptp_clock_event(dp83640->clock->ptp_clock, &event);
+ for (i = 0; i < N_EXT_TS; i++) {
+ if (ext_status & exts_chan_to_edata(i)) {
+ event.index = i;
+ ptp_clock_event(dp83640->clock->ptp_clock, &event);
+ }
+ }
- words = ext_status ? words + 2 : words + 1;
- return words * sizeof(u16);
+ return parsed * sizeof(u16);
}
static void decode_rxts(struct dp83640_private *dp83640,
@@ -589,7 +686,7 @@ static void decode_rxts(struct dp83640_private *dp83640,
prune_rx_ts(dp83640);
if (list_empty(&dp83640->rxpool)) {
- pr_warning("dp83640: rx timestamp pool is empty\n");
+ pr_debug("dp83640: rx timestamp pool is empty\n");
goto out;
}
rxts = list_first_entry(&dp83640->rxpool, struct rxts, list);
@@ -612,7 +709,7 @@ static void decode_txts(struct dp83640_private *dp83640,
skb = skb_dequeue(&dp83640->tx_queue);
if (!skb) {
- pr_warning("dp83640: have timestamp but tx_queue empty\n");
+ pr_debug("dp83640: have timestamp but tx_queue empty\n");
return;
}
ns = phy2txts(phy_txts);
@@ -664,6 +761,41 @@ static void decode_status_frame(struct dp83640_private *dp83640,
}
}
+static int is_sync(struct sk_buff *skb, int type)
+{
+ u8 *data = skb->data, *msgtype;
+ unsigned int offset = 0;
+
+ switch (type) {
+ case PTP_CLASS_V1_IPV4:
+ case PTP_CLASS_V2_IPV4:
+ offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+ break;
+ case PTP_CLASS_V1_IPV6:
+ case PTP_CLASS_V2_IPV6:
+ offset = OFF_PTP6;
+ break;
+ case PTP_CLASS_V2_L2:
+ offset = ETH_HLEN;
+ break;
+ case PTP_CLASS_V2_VLAN:
+ offset = ETH_HLEN + VLAN_HLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ if (type & PTP_CLASS_V1)
+ offset += OFF_PTP_CONTROL;
+
+ if (skb->len < offset + 1)
+ return 0;
+
+ msgtype = data + offset;
+
+ return (*msgtype & 0xf) == 0;
+}
+
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{
u16 *seqid;
@@ -740,7 +872,7 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
clock->caps.max_adj = 1953124;
clock->caps.n_alarm = 0;
clock->caps.n_ext_ts = N_EXT_TS;
- clock->caps.n_per_out = 0;
+ clock->caps.n_per_out = 1;
clock->caps.pps = 0;
clock->caps.adjfreq = ptp_dp83640_adjfreq;
clock->caps.adjtime = ptp_dp83640_adjtime;
@@ -920,16 +1052,10 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
if (cfg.flags) /* reserved for future extensions */
return -EINVAL;
- switch (cfg.tx_type) {
- case HWTSTAMP_TX_OFF:
- dp83640->hwts_tx_en = 0;
- break;
- case HWTSTAMP_TX_ON:
- dp83640->hwts_tx_en = 1;
- break;
- default:
+ if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ONESTEP_SYNC)
return -ERANGE;
- }
+
+ dp83640->hwts_tx_en = cfg.tx_type;
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
@@ -984,6 +1110,9 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
if (dp83640->hwts_tx_en)
txcfg0 |= TX_TS_EN;
+ if (dp83640->hwts_tx_en == HWTSTAMP_TX_ONESTEP_SYNC)
+ txcfg0 |= SYNC_1STEP | CHK_1STEP;
+
if (dp83640->hwts_rx_en)
rxcfg0 |= RX_TS_EN;
@@ -1066,12 +1195,24 @@ static void dp83640_txtstamp(struct phy_device *phydev,
{
struct dp83640_private *dp83640 = phydev->priv;
- if (!dp83640->hwts_tx_en) {
+ switch (dp83640->hwts_tx_en) {
+
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ if (is_sync(skb, type)) {
+ skb_complete_tx_timestamp(skb, NULL);
+ return;
+ }
+ /* fall through */
+ case HWTSTAMP_TX_ON:
+ skb_queue_tail(&dp83640->tx_queue, skb);
+ schedule_work(&dp83640->ts_work);
+ break;
+
+ case HWTSTAMP_TX_OFF:
+ default:
skb_complete_tx_timestamp(skb, NULL);
- return;
+ break;
}
- skb_queue_tail(&dp83640->tx_queue, skb);
- schedule_work(&dp83640->ts_work);
}
static struct phy_driver dp83640_driver = {
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 9a09e24..b142300 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -30,10 +30,17 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers");
+MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IC1001 PHY drivers");
MODULE_AUTHOR("Michael Barkowski");
MODULE_LICENSE("GPL");
+/* IP101A/IP1001 */
+#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
+#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
+#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */
+#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
+#define IP101A_APS_ON 2 /* IP101A APS Mode bit */
+
static int ip175c_config_init(struct phy_device *phydev)
{
int err, i;
@@ -42,36 +49,36 @@ static int ip175c_config_init(struct phy_device *phydev)
if (full_reset_performed == 0) {
/* master reset */
- err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+ err = mdiobus_write(phydev->bus, 30, 0, 0x175c);
if (err < 0)
return err;
/* ensure no bus delays overlap reset period */
- err = phydev->bus->read(phydev->bus, 30, 0);
+ err = mdiobus_read(phydev->bus, 30, 0);
/* data sheet specifies reset period is 2 msec */
mdelay(2);
/* enable IP175C mode */
- err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+ err = mdiobus_write(phydev->bus, 29, 31, 0x175c);
if (err < 0)
return err;
/* Set MII0 speed and duplex (in PHY mode) */
- err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+ err = mdiobus_write(phydev->bus, 29, 22, 0x420);
if (err < 0)
return err;
/* reset switch ports */
for (i = 0; i < 5; i++) {
- err = phydev->bus->write(phydev->bus, i,
- MII_BMCR, BMCR_RESET);
+ err = mdiobus_write(phydev->bus, i,
+ MII_BMCR, BMCR_RESET);
if (err < 0)
return err;
}
for (i = 0; i < 5; i++)
- err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+ err = mdiobus_read(phydev->bus, i, MII_BMCR);
mdelay(2);
@@ -89,31 +96,62 @@ static int ip175c_config_init(struct phy_device *phydev)
return 0;
}
-static int ip1001_config_init(struct phy_device *phydev)
+static int ip1xx_reset(struct phy_device *phydev)
{
- int err, value;
+ int err, bmcr;
/* Software Reset PHY */
- value = phy_read(phydev, MII_BMCR);
- value |= BMCR_RESET;
- err = phy_write(phydev, MII_BMCR, value);
+ bmcr = phy_read(phydev, MII_BMCR);
+ bmcr |= BMCR_RESET;
+ err = phy_write(phydev, MII_BMCR, bmcr);
if (err < 0)
return err;
do {
- value = phy_read(phydev, MII_BMCR);
- } while (value & BMCR_RESET);
+ bmcr = phy_read(phydev, MII_BMCR);
+ } while (bmcr & BMCR_RESET);
- /* Additional delay (2ns) used to adjust RX clock phase
- * at GMII/ RGMII interface */
- value = phy_read(phydev, 16);
- value |= 0x3;
+ return err;
+}
- err = phy_write(phydev, 16, value);
- if (err < 0)
- return err;
+static int ip1001_config_init(struct phy_device *phydev)
+{
+ int c;
+
+ c = ip1xx_reset(phydev);
+ if (c < 0)
+ return c;
+
+ /* Enable Auto Power Saving mode */
+ c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2);
+ c |= IP1001_APS_ON;
+ if (c < 0)
+ return c;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+ /* Additional delay (2ns) used to adjust RX clock phase
+ * at RGMII interface */
+ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
+ c |= IP1001_PHASE_SEL_MASK;
+ c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
+ }
- return err;
+ return c;
+}
+
+static int ip101a_config_init(struct phy_device *phydev)
+{
+ int c;
+
+ c = ip1xx_reset(phydev);
+ if (c < 0)
+ return c;
+
+ /* Enable Auto Power Saving mode */
+ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
+ c |= IP101A_APS_ON;
+
+ return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
}
static int ip175c_read_status(struct phy_device *phydev)
@@ -162,6 +200,20 @@ static struct phy_driver ip1001_driver = {
.driver = { .owner = THIS_MODULE,},
};
+static struct phy_driver ip101a_driver = {
+ .phy_id = 0x02430c54,
+ .name = "ICPlus IP101A",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause,
+ .config_init = &ip101a_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .driver = { .owner = THIS_MODULE,},
+};
+
static int __init icplus_init(void)
{
int ret = 0;
@@ -170,12 +222,17 @@ static int __init icplus_init(void)
if (ret < 0)
return -ENODEV;
+ ret = phy_driver_register(&ip101a_driver);
+ if (ret < 0)
+ return -ENODEV;
+
return phy_driver_register(&ip175c_driver);
}
static void __exit icplus_exit(void)
{
phy_driver_unregister(&ip1001_driver);
+ phy_driver_unregister(&ip101a_driver);
phy_driver_unregister(&ip175c_driver);
}
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
index 0620ba9..04bb8fc 100644
--- a/drivers/net/phy/national.c
+++ b/drivers/net/phy/national.c
@@ -25,8 +25,9 @@
/* DP83865 phy identifier values */
#define DP83865_PHY_ID 0x20005c7a
-#define DP83865_INT_MASK_REG 0x15
-#define DP83865_INT_MASK_STATUS 0x14
+#define DP83865_INT_STATUS 0x14
+#define DP83865_INT_MASK 0x15
+#define DP83865_INT_CLEAR 0x17
#define DP83865_INT_REMOTE_FAULT 0x0008
#define DP83865_INT_ANE_COMPLETED 0x0010
@@ -68,21 +69,25 @@ static int ns_config_intr(struct phy_device *phydev)
int err;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
- err = phy_write(phydev, DP83865_INT_MASK_REG,
+ err = phy_write(phydev, DP83865_INT_MASK,
DP83865_INT_MASK_DEFAULT);
else
- err = phy_write(phydev, DP83865_INT_MASK_REG, 0);
+ err = phy_write(phydev, DP83865_INT_MASK, 0);
return err;
}
static int ns_ack_interrupt(struct phy_device *phydev)
{
- int ret = phy_read(phydev, DP83865_INT_MASK_STATUS);
+ int ret = phy_read(phydev, DP83865_INT_STATUS);
if (ret < 0)
return ret;
- return 0;
+ /* Clear the interrupt status bit by writing a “1â€
+ * to the corresponding bit in INT_CLEAR (2:0 are reserved) */
+ ret = phy_write(phydev, DP83865_INT_CLEAR, ret & ~0x7);
+
+ return ret;
}
static void ns_giga_speed_fallback(struct phy_device *phydev, int mode)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index a475957..3cbda08 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -33,7 +33,7 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index ff109fe..83a5a5a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -213,7 +213,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
/* Grab the bits from PHYIR1, and put them
* in the upper half */
- phy_reg = bus->read(bus, addr, MII_PHYSID1);
+ phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
if (phy_reg < 0)
return -EIO;
@@ -221,7 +221,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
*phy_id = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = bus->read(bus, addr, MII_PHYSID2);
+ phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
if (phy_reg < 0)
return -EIO;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index a4eae75..f414ffb 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -14,6 +14,7 @@
*
*/
#include <linux/phy.h>
+#include <linux/module.h>
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX 0x2000
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 5d8f6e1..0ec8e09 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -3,7 +3,7 @@
*
* Author: Kriston Carson
*
- * Copyright (c) 2005 Freescale Semiconductor, Inc.
+ * Copyright (c) 2005, 2009 Freescale Semiconductor, 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
@@ -61,32 +61,42 @@ MODULE_DESCRIPTION("Vitesse PHY driver");
MODULE_AUTHOR("Kriston Carson");
MODULE_LICENSE("GPL");
-static int vsc824x_config_init(struct phy_device *phydev)
+int vsc824x_add_skew(struct phy_device *phydev)
{
- int extcon;
int err;
-
- err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
- MII_VSC8244_AUXCONSTAT_INIT);
- if (err < 0)
- return err;
+ int extcon;
extcon = phy_read(phydev, MII_VSC8244_EXT_CON1);
if (extcon < 0)
- return err;
+ return extcon;
extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK |
MII_VSC8244_EXTCON1_RX_SKEW_MASK);
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- extcon |= (MII_VSC8244_EXTCON1_TX_SKEW |
- MII_VSC8244_EXTCON1_RX_SKEW);
+ extcon |= (MII_VSC8244_EXTCON1_TX_SKEW |
+ MII_VSC8244_EXTCON1_RX_SKEW);
err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon);
return err;
}
+EXPORT_SYMBOL(vsc824x_add_skew);
+
+static int vsc824x_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
+ MII_VSC8244_AUXCONSTAT_INIT);
+ if (err < 0)
+ return err;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ err = vsc824x_add_skew(phydev);
+
+ return err;
+}
static int vsc824x_ack_interrupt(struct phy_device *phydev)
{
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index ff32bef..ef9fdf3 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -282,7 +282,7 @@ static const struct net_device_ops xl_netdev_ops = {
.ndo_stop = xl_close,
.ndo_start_xmit = xl_xmit,
.ndo_change_mtu = xl_change_mtu,
- .ndo_set_multicast_list = xl_set_rx_mode,
+ .ndo_set_rx_mode = xl_set_rx_mode,
.ndo_set_mac_address = xl_set_mac_address,
};
@@ -304,7 +304,7 @@ static int __devinit xl_probe(struct pci_dev *pdev,
if ((i = pci_request_regions(pdev,"3c359"))) {
return i ;
- } ;
+ }
/*
* Allowing init_trdev to allocate the private data will align
@@ -1773,7 +1773,9 @@ static void xl_wait_misr_flags(struct net_device *dev)
if (readb(xl_mmio + MMIO_MACDATA) != 0) { /* Misr not clear */
for (i=0; i<6; i++) {
writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
- while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */
+ while (readb(xl_mmio + MMIO_MACDATA) != 0) {
+ ; /* Empty Loop */
+ }
}
}
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index c4137b0..c7e0149 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -4,9 +4,9 @@
# So far, we only have PCI, ISA, and MCA token ring devices
menuconfig TR
- tristate "Token Ring driver support"
+ bool "Token Ring driver support"
depends on NETDEVICES && !UML
- depends on (PCI || ISA || MCA || CCW)
+ depends on (PCI || ISA || MCA || CCW || PCMCIA)
select LLC
help
Token Ring is IBM's way of communication on a local network; the
@@ -20,6 +20,17 @@ menuconfig TR
if TR
+config PCMCIA_IBMTR
+ tristate "IBM PCMCIA tokenring adapter support"
+ depends on IBMTR!=y && PCMCIA
+ ---help---
+ Say Y here if you intend to attach this type of Token Ring PCMCIA
+ card to your computer. You then also need to say Y to "Token Ring
+ driver support".
+
+ To compile this driver as a module, choose M here: the module will be
+ called ibmtr_cs.
+
config IBMTR
tristate "IBM Tropic chipset based adapter support"
depends on ISA || MCA
diff --git a/drivers/net/tokenring/Makefile b/drivers/net/tokenring/Makefile
index c88b0a5..f1be8d9 100644
--- a/drivers/net/tokenring/Makefile
+++ b/drivers/net/tokenring/Makefile
@@ -2,14 +2,15 @@
# Makefile for drivers/net/tokenring
#
-obj-$(CONFIG_IBMTR) += ibmtr.o
-obj-$(CONFIG_IBMOL) += olympic.o
-obj-$(CONFIG_IBMLS) += lanstreamer.o
-obj-$(CONFIG_TMS380TR) += tms380tr.o
-obj-$(CONFIG_ABYSS) += abyss.o
-obj-$(CONFIG_MADGEMC) += madgemc.o
-obj-$(CONFIG_PROTEON) += proteon.o
-obj-$(CONFIG_TMSPCI) += tmspci.o
-obj-$(CONFIG_SKISA) += skisa.o
-obj-$(CONFIG_SMCTR) += smctr.o
+obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o
+obj-$(CONFIG_IBMTR) += ibmtr.o
+obj-$(CONFIG_IBMOL) += olympic.o
+obj-$(CONFIG_IBMLS) += lanstreamer.o
+obj-$(CONFIG_TMS380TR) += tms380tr.o
+obj-$(CONFIG_ABYSS) += abyss.o
+obj-$(CONFIG_MADGEMC) += madgemc.o
+obj-$(CONFIG_PROTEON) += proteon.o
+obj-$(CONFIG_TMSPCI) += tmspci.o
+obj-$(CONFIG_SKISA) += skisa.o
+obj-$(CONFIG_SMCTR) += smctr.o
obj-$(CONFIG_3C359) += 3c359.o
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 4786497..b5c8c18 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -123,6 +123,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
/* some 95 OS send many non UI frame; this allow removing the warning */
#define TR_FILTERNONUI 1
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
@@ -177,7 +178,7 @@ static char __devinit *adapter_def(char type)
case 0xD: return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter";
case 0xC: return "Auto 16/4 Adapter";
default: return "adapter (unknown type)";
- };
+ }
};
#define TRC_INIT 0x01 /* Trace initialization & PROBEs */
@@ -822,7 +823,7 @@ static const struct net_device_ops trdev_netdev_ops = {
.ndo_open = tok_open,
.ndo_stop = tok_close,
.ndo_start_xmit = tok_send_packet,
- .ndo_set_multicast_list = tok_set_multicast_list,
+ .ndo_set_rx_mode = tok_set_multicast_list,
.ndo_change_mtu = ibmtr_change_mtu,
};
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 9354ca9..8d71e0d 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -231,7 +231,7 @@ static const struct net_device_ops streamer_netdev_ops = {
#if STREAMER_IOCTL
.ndo_do_ioctl = streamer_ioctl,
#endif
- .ndo_set_multicast_list = streamer_set_rx_mode,
+ .ndo_set_rx_mode = streamer_set_rx_mode,
.ndo_set_mac_address = streamer_set_mac_address,
};
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 2bedc0a..6153cfd 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -418,7 +418,7 @@ static irqreturn_t madgemc_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
/* Make sure its really us. -- the Madge way */
pending = inb(dev->base_addr + MC_CONTROL_REG0);
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index e3855ae..fd8dce9 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -201,7 +201,7 @@ static const struct net_device_ops olympic_netdev_ops = {
.ndo_stop = olympic_close,
.ndo_start_xmit = olympic_xmit,
.ndo_change_mtu = olympic_change_mtu,
- .ndo_set_multicast_list = olympic_set_rx_mode,
+ .ndo_set_rx_mode = olympic_set_rx_mode,
.ndo_set_mac_address = olympic_set_mac_address,
};
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index d9044ab..029846a 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3623,7 +3623,7 @@ static const struct net_device_ops smctr_netdev_ops = {
.ndo_start_xmit = smctr_send_packet,
.ndo_tx_timeout = smctr_timeout,
.ndo_get_stats = smctr_get_stats,
- .ndo_set_multicast_list = smctr_set_multicast_list,
+ .ndo_set_rx_mode = smctr_set_multicast_list,
};
static int __init smctr_probe1(struct net_device *dev, int ioaddr)
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 7930203..65e9cf3 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -2289,7 +2289,7 @@ const struct net_device_ops tms380tr_netdev_ops = {
.ndo_start_xmit = tms380tr_send_packet,
.ndo_tx_timeout = tms380tr_timeout,
.ndo_get_stats = tms380tr_get_stats,
- .ndo_set_multicast_list = tms380tr_set_multicast_list,
+ .ndo_set_rx_mode = tms380tr_set_multicast_list,
.ndo_set_mac_address = tms380tr_set_mac_address,
};
EXPORT_SYMBOL(tms380tr_netdev_ops);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 0ef676d..28ceef2 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -24,6 +24,7 @@
*
*/
+#include <linux/module.h>
#include <net/ip6_checksum.h>
#include "vmxnet3_int.h"
@@ -405,10 +406,8 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
struct vmxnet3_tx_buf_info *tbi;
- union Vmxnet3_GenericDesc *gdesc;
tbi = tq->buf_info + tq->tx_ring.next2comp;
- gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
if (tbi->skb) {
@@ -656,10 +655,11 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
- frag->page = rbi->page;
+ __skb_frag_set_page(frag, rbi->page);
frag->page_offset = 0;
- frag->size = rcd->len;
- skb->data_len += frag->size;
+ skb_frag_size_set(frag, rcd->len);
+ skb->data_len += rcd->len;
+ skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
}
@@ -746,21 +746,21 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
tbi = tq->buf_info + tq->tx_ring.next2fill;
tbi->map_type = VMXNET3_MAP_PAGE;
- tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+ 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
- tbi->len = frag->size;
+ tbi->len = skb_frag_size(frag);
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
- gdesc->dword[2] = cpu_to_le32(dw2 | frag->size);
+ gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
gdesc->dword[3] = 0;
dev_dbg(&adapter->netdev->dev,
@@ -921,7 +921,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
skb_shinfo(skb)->nr_frags + 1;
- ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP));
+ ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
ctx.mss = skb_shinfo(skb)->gso_size;
if (ctx.mss) {
@@ -1274,18 +1274,18 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
skb = ctx->skb;
if (rcd->eop) {
skb->len += skb->data_len;
- skb->truesize += skb->data_len;
vmxnet3_rx_csum(adapter, skb,
(union Vmxnet3_GenericDesc *)rcd);
skb->protocol = eth_type_trans(skb, adapter->netdev);
- if (unlikely(adapter->vlan_grp && rcd->ts)) {
- vlan_hwaccel_receive_skb(skb,
- adapter->vlan_grp, rcd->tci);
- } else {
+ if (unlikely(rcd->ts))
+ __vlan_hwaccel_put_tag(skb, rcd->tci);
+
+ if (adapter->netdev->features & NETIF_F_LRO)
netif_receive_skb(skb);
- }
+ else
+ napi_gro_receive(&rq->napi, skb);
ctx->skb = NULL;
}
@@ -1734,11 +1734,20 @@ vmxnet3_netpoll(struct net_device *netdev)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
- vmxnet3_disable_all_intrs(adapter);
-
- vmxnet3_do_poll(adapter, adapter->rx_queue[0].rx_ring[0].size);
- vmxnet3_enable_all_intrs(adapter);
+ switch (adapter->intr.type) {
+#ifdef CONFIG_PCI_MSI
+ case VMXNET3_IT_MSIX: {
+ int i;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ vmxnet3_msix_rx(0, &adapter->rx_queue[i]);
+ break;
+ }
+#endif
+ case VMXNET3_IT_MSI:
+ default:
+ vmxnet3_intr(0, adapter->netdev);
+ break;
+ }
}
#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -1906,94 +1915,38 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
}
}
+
static void
-vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
{
- struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- struct Vmxnet3_DriverShared *shared = adapter->shared;
u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
-
- if (grp) {
- /* add vlan rx stripping. */
- if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
- int i;
- adapter->vlan_grp = grp;
-
- /*
- * Clear entire vfTable; then enable untagged pkts.
- * Note: setting one entry in vfTable to non-zero turns
- * on VLAN rx filtering.
- */
- for (i = 0; i < VMXNET3_VFT_SIZE; i++)
- vfTable[i] = 0;
-
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- } else {
- printk(KERN_ERR "%s: vlan_rx_register when device has "
- "no NETIF_F_HW_VLAN_RX\n", netdev->name);
- }
- } else {
- /* remove vlan rx stripping. */
- struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
- adapter->vlan_grp = NULL;
+ u16 vid;
- if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
- int i;
+ /* allow untagged pkts */
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
- /* clear entire vfTable; this also disables
- * VLAN rx filtering
- */
- vfTable[i] = 0;
- }
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- }
- }
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
}
static void
-vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
+vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
- if (adapter->vlan_grp) {
- u16 vid;
+ struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+ if (!(netdev->flags & IFF_PROMISC)) {
u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- bool activeVlan = false;
+ unsigned long flags;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (vlan_group_get_device(adapter->vlan_grp, vid)) {
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
- activeVlan = true;
- }
- }
- if (activeVlan) {
- /* continue to allow untagged pkts */
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- }
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
}
-}
-
-static void
-vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
- struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
-
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ set_bit(vid, adapter->active_vlans);
}
@@ -2001,14 +1954,19 @@ static void
vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
- VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ if (!(netdev->flags & IFF_PROMISC)) {
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ unsigned long flags;
+
+ VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ }
+
+ clear_bit(vid, adapter->active_vlans);
}
@@ -2045,8 +2003,14 @@ vmxnet3_set_mc(struct net_device *netdev)
u8 *new_table = NULL;
u32 new_mode = VMXNET3_RXM_UCAST;
- if (netdev->flags & IFF_PROMISC)
+ if (netdev->flags & IFF_PROMISC) {
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable));
+
new_mode |= VMXNET3_RXM_PROMISC;
+ } else {
+ vmxnet3_restore_vlan(adapter);
+ }
if (netdev->flags & IFF_BROADCAST)
new_mode |= VMXNET3_RXM_BCAST;
@@ -2080,6 +2044,8 @@ vmxnet3_set_mc(struct net_device *netdev)
rxConf->rxMode = cpu_to_le32(new_mode);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_RX_MODE);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
}
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
@@ -2689,12 +2655,13 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64)
netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX |
- NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_LRO;
+ NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_LRO;
if (dma64)
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_TX;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ netdev->hw_features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features = netdev->hw_features &
+ ~(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+ netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_FILTER;
netdev_info(adapter->netdev,
"features: sg csum vlan jf tso tsoIPv6 lro%s\n",
@@ -2912,10 +2879,9 @@ vmxnet3_probe_device(struct pci_dev *pdev,
.ndo_set_mac_address = vmxnet3_set_mac_addr,
.ndo_change_mtu = vmxnet3_change_mtu,
.ndo_set_features = vmxnet3_set_features,
- .ndo_get_stats = vmxnet3_get_stats,
+ .ndo_get_stats64 = vmxnet3_get_stats64,
.ndo_tx_timeout = vmxnet3_tx_timeout,
- .ndo_set_multicast_list = vmxnet3_set_mc,
- .ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
+ .ndo_set_rx_mode = vmxnet3_set_mc,
.ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3038,6 +3004,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
goto err_ver;
}
+ SET_NETDEV_DEV(netdev, &pdev->dev);
vmxnet3_declare_features(adapter, dma64);
adapter->dev_number = atomic_read(&devices_found);
@@ -3083,7 +3050,6 @@ vmxnet3_probe_device(struct pci_dev *pdev,
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
- SET_NETDEV_DEV(netdev, &pdev->dev);
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index dc959fe..e662cbc 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -113,15 +113,15 @@ vmxnet3_global_stats[] = {
};
-struct net_device_stats *
-vmxnet3_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
struct vmxnet3_adapter *adapter;
struct vmxnet3_tq_driver_stats *drvTxStats;
struct vmxnet3_rq_driver_stats *drvRxStats;
struct UPT1_TxStats *devTxStats;
struct UPT1_RxStats *devRxStats;
- struct net_device_stats *net_stats = &netdev->stats;
unsigned long flags;
int i;
@@ -132,36 +132,36 @@ vmxnet3_get_stats(struct net_device *netdev)
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- memset(net_stats, 0, sizeof(*net_stats));
for (i = 0; i < adapter->num_tx_queues; i++) {
devTxStats = &adapter->tqd_start[i].stats;
drvTxStats = &adapter->tx_queue[i].stats;
- net_stats->tx_packets += devTxStats->ucastPktsTxOK +
- devTxStats->mcastPktsTxOK +
- devTxStats->bcastPktsTxOK;
- net_stats->tx_bytes += devTxStats->ucastBytesTxOK +
- devTxStats->mcastBytesTxOK +
- devTxStats->bcastBytesTxOK;
- net_stats->tx_errors += devTxStats->pktsTxError;
- net_stats->tx_dropped += drvTxStats->drop_total;
+ stats->tx_packets += devTxStats->ucastPktsTxOK +
+ devTxStats->mcastPktsTxOK +
+ devTxStats->bcastPktsTxOK;
+ stats->tx_bytes += devTxStats->ucastBytesTxOK +
+ devTxStats->mcastBytesTxOK +
+ devTxStats->bcastBytesTxOK;
+ stats->tx_errors += devTxStats->pktsTxError;
+ stats->tx_dropped += drvTxStats->drop_total;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
devRxStats = &adapter->rqd_start[i].stats;
drvRxStats = &adapter->rx_queue[i].stats;
- net_stats->rx_packets += devRxStats->ucastPktsRxOK +
- devRxStats->mcastPktsRxOK +
- devRxStats->bcastPktsRxOK;
+ stats->rx_packets += devRxStats->ucastPktsRxOK +
+ devRxStats->mcastPktsRxOK +
+ devRxStats->bcastPktsRxOK;
- net_stats->rx_bytes += devRxStats->ucastBytesRxOK +
- devRxStats->mcastBytesRxOK +
- devRxStats->bcastBytesRxOK;
+ stats->rx_bytes += devRxStats->ucastBytesRxOK +
+ devRxStats->mcastBytesRxOK +
+ devRxStats->bcastBytesRxOK;
- net_stats->rx_errors += devRxStats->pktsRxError;
- net_stats->rx_dropped += drvRxStats->drop_total;
- net_stats->multicast += devRxStats->mcastPktsRxOK;
+ stats->rx_errors += devRxStats->pktsRxError;
+ stats->rx_dropped += drvRxStats->drop_total;
+ stats->multicast += devRxStats->mcastPktsRxOK;
}
- return net_stats;
+
+ return stats;
}
static int
@@ -268,7 +268,7 @@ int vmxnet3_set_features(struct net_device *netdev, u32 features)
unsigned long flags;
u32 changed = features ^ netdev->features;
- if (changed & (NETIF_F_RXCSUM|NETIF_F_LRO)) {
+ if (changed & (NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_RX)) {
if (features & NETIF_F_RXCSUM)
adapter->shared->devRead.misc.uptFeatures |=
UPT1_F_RXCSUM;
@@ -284,6 +284,13 @@ int vmxnet3_set_features(struct net_device *netdev, u32 features)
adapter->shared->devRead.misc.uptFeatures &=
~UPT1_F_LRO;
+ if (features & NETIF_F_HW_VLAN_RX)
+ adapter->shared->devRead.misc.uptFeatures |=
+ UPT1_F_RXVLAN;
+ else
+ adapter->shared->devRead.misc.uptFeatures &=
+ ~UPT1_F_RXVLAN;
+
spin_lock_irqsave(&adapter->cmd_lock, flags);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_FEATURE);
@@ -551,7 +558,7 @@ out:
static int
vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info,
- void *rules)
+ u32 *rules)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
switch (info->cmd) {
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 862be05..8df921b 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -27,6 +27,7 @@
#ifndef _VMXNET3_INT_H
#define _VMXNET3_INT_H
+#include <linux/bitops.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
@@ -316,7 +317,7 @@ struct vmxnet3_intr {
struct vmxnet3_adapter {
struct vmxnet3_tx_queue tx_queue[VMXNET3_DEVICE_MAX_TX_QUEUES];
struct vmxnet3_rx_queue rx_queue[VMXNET3_DEVICE_MAX_RX_QUEUES];
- struct vlan_group *vlan_grp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct vmxnet3_intr intr;
spinlock_t cmd_lock;
struct Vmxnet3_DriverShared *shared;
@@ -324,7 +325,6 @@ struct vmxnet3_adapter {
struct Vmxnet3_TxQueueDesc *tqd_start; /* all tx queue desc */
struct Vmxnet3_RxQueueDesc *rqd_start; /* all rx queue desc */
struct net_device *netdev;
- struct net_device_stats net_stats;
struct pci_dev *pdev;
u8 __iomem *hw_addr0; /* for BAR 0 */
@@ -408,7 +408,9 @@ vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
-extern struct net_device_stats *vmxnet3_get_stats(struct net_device *netdev);
+
+extern struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
extern char vmxnet3_driver_name[];
#endif
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 4ac85a0..54f995f 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -14,6 +14,8 @@
* Moxa C101 User's Manual
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -313,44 +315,44 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
int result;
if (irq<3 || irq>15 || irq == 6) /* FIXME */ {
- printk(KERN_ERR "c101: invalid IRQ value\n");
+ pr_err("invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) {
- printk(KERN_ERR "c101: invalid RAM value\n");
+ pr_err("invalid RAM value\n");
return -ENODEV;
}
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "c101: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
return -ENOBUFS;
}
card->dev = alloc_hdlcdev(card);
if (!card->dev) {
- printk(KERN_ERR "c101: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
kfree(card);
return -ENOBUFS;
}
if (request_irq(irq, sca_intr, 0, devname, card)) {
- printk(KERN_ERR "c101: could not allocate IRQ\n");
+ pr_err("could not allocate IRQ\n");
c101_destroy_card(card);
return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
- printk(KERN_ERR "c101: could not request RAM window\n");
+ pr_err("could not request RAM window\n");
c101_destroy_card(card);
return -EBUSY;
}
card->phy_winbase = winbase;
card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
if (!card->win0base) {
- printk(KERN_ERR "c101: could not map I/O address\n");
+ pr_err("could not map I/O address\n");
c101_destroy_card(card);
return -EFAULT;
}
@@ -381,7 +383,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
result = register_hdlc_device(dev);
if (result) {
- printk(KERN_WARNING "c101: unable to register hdlc device\n");
+ pr_warn("unable to register hdlc device\n");
c101_destroy_card(card);
return result;
}
@@ -389,10 +391,8 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
sca_init_port(card); /* Set up C101 memory */
set_carrier(card);
- printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
- " using %u TX + %u RX packets rings\n",
- dev->name, card->irq,
- card->tx_ring_buffers, card->rx_ring_buffers);
+ netdev_info(dev, "Moxa C101 on IRQ%u, using %u TX + %u RX packets rings\n",
+ card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
*new_card = card;
new_card = &card->next_card;
@@ -405,12 +405,12 @@ static int __init c101_init(void)
{
if (hw == NULL) {
#ifdef MODULE
- printk(KERN_INFO "c101: no card initialized\n");
+ pr_info("no card initialized\n");
#endif
return -EINVAL; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
do {
unsigned long irq, ram;
@@ -428,7 +428,7 @@ static int __init c101_init(void)
return first_card ? 0 : -EINVAL;
}while(*hw++ == ':');
- printk(KERN_ERR "c101: invalid hardware parameters\n");
+ pr_err("invalid hardware parameters\n");
return first_card ? 0 : -EINVAL;
}
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6fb6f8e..6aed238 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -74,6 +74,8 @@
* The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -361,14 +363,13 @@ static int __init cosa_init(void)
if (cosa_major > 0) {
if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
- printk(KERN_WARNING "cosa: unable to get major %d\n",
- cosa_major);
+ pr_warn("unable to get major %d\n", cosa_major);
err = -EIO;
goto out;
}
} else {
if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
- printk(KERN_WARNING "cosa: unable to register chardev\n");
+ pr_warn("unable to register chardev\n");
err = -EIO;
goto out;
}
@@ -378,7 +379,7 @@ static int __init cosa_init(void)
for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
cosa_probe(io[i], irq[i], dma[i]);
if (!nr_cards) {
- printk(KERN_WARNING "cosa: no devices found.\n");
+ pr_warn("no devices found\n");
unregister_chrdev(cosa_major, "cosa");
err = -ENODEV;
goto out;
@@ -447,26 +448,25 @@ static int cosa_probe(int base, int irq, int dma)
/* Checking validity of parameters: */
/* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
- printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq);
+ pr_info("invalid IRQ %d\n", irq);
return -1;
}
/* I/O address should be between 0x100 and 0x3ff and should be
* multiple of 8. */
if (base < 0x100 || base > 0x3ff || base & 0x7) {
- printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n",
- base);
+ pr_info("invalid I/O address 0x%x\n", base);
return -1;
}
/* DMA should be 0,1 or 3-7 */
if (dma < 0 || dma == 4 || dma > 7) {
- printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma);
+ pr_info("invalid DMA %d\n", dma);
return -1;
}
/* and finally, on 16-bit COSA DMA should be 4-7 and
* I/O base should not be multiple of 0x10 */
if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
- printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch"
- " (base=0x%x, dma=%d)\n", base, dma);
+ pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n",
+ base, dma);
return -1;
}
@@ -479,7 +479,7 @@ static int cosa_probe(int base, int irq, int dma)
return -1;
if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
- printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base);
+ printk(KERN_DEBUG "probe at 0x%x failed.\n", base);
err = -1;
goto err_out;
}
@@ -492,8 +492,7 @@ static int cosa_probe(int base, int irq, int dma)
else {
/* Print a warning only if we are not autoprobing */
#ifndef COSA_ISA_AUTOPROBE
- printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n",
- base);
+ pr_info("valid signature not found at 0x%x\n", base);
#endif
err = -1;
goto err_out;
@@ -501,14 +500,14 @@ static int cosa_probe(int base, int irq, int dma)
/* Update the name of the region now we know the type of card */
release_region(base, is_8bit(cosa)?2:4);
if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) {
- printk(KERN_DEBUG "cosa: changing name at 0x%x failed.\n", base);
+ printk(KERN_DEBUG "changing name at 0x%x failed.\n", base);
return -1;
}
/* Now do IRQ autoprobe */
if (irq < 0) {
unsigned long irqs;
-/* printk(KERN_INFO "IRQ autoprobe\n"); */
+/* pr_info("IRQ autoprobe\n"); */
irqs = probe_irq_on();
/*
* Enable interrupt on tx buffer empty (it sure is)
@@ -526,13 +525,13 @@ static int cosa_probe(int base, int irq, int dma)
cosa_getdata8(cosa);
if (irq < 0) {
- printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",
+ pr_info("multiple interrupts obtained (%d, board at 0x%x)\n",
irq, cosa->datareg);
err = -1;
goto err_out;
}
if (irq == 0) {
- printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",
+ pr_info("no interrupt obtained (board at 0x%x)\n",
cosa->datareg);
/* return -1; */
}
@@ -579,8 +578,7 @@ static int cosa_probe(int base, int irq, int dma)
/* Register the network interface */
if (!(chan->netdev = alloc_hdlcdev(chan))) {
- printk(KERN_WARNING "%s: alloc_hdlcdev failed.\n",
- chan->name);
+ pr_warn("%s: alloc_hdlcdev failed\n", chan->name);
goto err_hdlcdev;
}
dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
@@ -591,14 +589,14 @@ static int cosa_probe(int base, int irq, int dma)
chan->netdev->irq = chan->cosa->irq;
chan->netdev->dma = chan->cosa->dma;
if (register_hdlc_device(chan->netdev)) {
- printk(KERN_WARNING "%s: register_hdlc_device()"
- " failed.\n", chan->netdev->name);
+ netdev_warn(chan->netdev,
+ "register_hdlc_device() failed\n");
free_netdev(chan->netdev);
goto err_hdlcdev;
}
}
- printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
+ pr_info("cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
cosa->num, cosa->id_string, cosa->type,
cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
@@ -618,8 +616,7 @@ err_out1:
free_irq(cosa->irq, cosa);
err_out:
release_region(cosa->datareg,is_8bit(cosa)?2:4);
- printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
- cosa->num);
+ pr_notice("cosa%d: allocating resources failed\n", cosa->num);
return err;
}
@@ -641,14 +638,14 @@ static int cosa_net_open(struct net_device *dev)
unsigned long flags;
if (!(chan->cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- chan->cosa->name, chan->cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ chan->cosa->name, chan->cosa->firmware_status);
return -EPERM;
}
spin_lock_irqsave(&chan->cosa->lock, flags);
if (chan->usage != 0) {
- printk(KERN_WARNING "%s: cosa_net_open called with usage count"
- " %d\n", chan->name, chan->usage);
+ pr_warn("%s: cosa_net_open called with usage count %d\n",
+ chan->name, chan->usage);
spin_unlock_irqrestore(&chan->cosa->lock, flags);
return -EBUSY;
}
@@ -736,8 +733,7 @@ static char *cosa_net_setup_rx(struct channel_data *chan, int size)
kfree_skb(chan->rx_skb);
chan->rx_skb = dev_alloc_skb(size);
if (chan->rx_skb == NULL) {
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
- chan->name);
+ pr_notice("%s: Memory squeeze, dropping packet\n", chan->name);
chan->netdev->stats.rx_dropped++;
return NULL;
}
@@ -748,8 +744,7 @@ static char *cosa_net_setup_rx(struct channel_data *chan, int size)
static int cosa_net_rx_done(struct channel_data *chan)
{
if (!chan->rx_skb) {
- printk(KERN_WARNING "%s: rx_done with empty skb!\n",
- chan->name);
+ pr_warn("%s: rx_done with empty skb!\n", chan->name);
chan->netdev->stats.rx_errors++;
chan->netdev->stats.rx_frame_errors++;
return 0;
@@ -768,8 +763,7 @@ static int cosa_net_rx_done(struct channel_data *chan)
static int cosa_net_tx_done(struct channel_data *chan, int size)
{
if (!chan->tx_skb) {
- printk(KERN_WARNING "%s: tx_done with empty skb!\n",
- chan->name);
+ pr_warn("%s: tx_done with empty skb!\n", chan->name);
chan->netdev->stats.tx_errors++;
chan->netdev->stats.tx_aborted_errors++;
return 1;
@@ -794,15 +788,15 @@ static ssize_t cosa_read(struct file *file,
char *kbuf;
if (!(cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
if (mutex_lock_interruptible(&chan->rlock))
return -ERESTARTSYS;
if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
- printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+ pr_info("%s: cosa_read() - OOM\n", cosa->name);
mutex_unlock(&chan->rlock);
return -ENOMEM;
}
@@ -869,8 +863,8 @@ static ssize_t cosa_write(struct file *file,
char *kbuf;
if (!(cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
if (down_interruptible(&chan->wsem))
@@ -881,8 +875,8 @@ static ssize_t cosa_write(struct file *file,
/* Allocate the buffer */
if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {
- printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",
- cosa->name);
+ pr_notice("%s: cosa_write() OOM - dropping packet\n",
+ cosa->name);
up(&chan->wsem);
return -ENOMEM;
}
@@ -932,7 +926,7 @@ static int chrdev_tx_done(struct channel_data *chan, int size)
static unsigned int cosa_poll(struct file *file, poll_table *poll)
{
- printk(KERN_INFO "cosa_poll is here\n");
+ pr_info("cosa_poll is here\n");
return 0;
}
@@ -1017,15 +1011,14 @@ static inline int cosa_reset(struct cosa_data *cosa)
{
char idstring[COSA_MAX_ID_STRING];
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START);
if (cosa_reset_and_read_id(cosa, idstring) < 0) {
- printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);
+ pr_notice("cosa%d: reset failed\n", cosa->num);
return -EIO;
}
- printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,
- idstring);
+ pr_info("cosa%d: resetting device: %s\n", cosa->num, idstring);
cosa->firmware_status |= COSA_FW_RESET;
return 0;
}
@@ -1037,11 +1030,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->name, cosa->usage);
if (!(cosa->firmware_status & COSA_FW_RESET)) {
- printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
@@ -1059,11 +1052,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
i = download(cosa, d.code, d.len, d.addr);
if (i < 0) {
- printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: microcode download failed: %d\n",
+ cosa->num, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
+ pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
cosa->num, d.len, d.addr);
cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD;
return 0;
@@ -1076,12 +1069,11 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: readmem requested with "
- "cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: readmem requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
if (!(cosa->firmware_status & COSA_FW_RESET)) {
- printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
@@ -1093,11 +1085,10 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
i = readmem(cosa, d.code, d.len, d.addr);
if (i < 0) {
- printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: reading memory failed: %d\n", cosa->num, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
+ pr_info("cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
cosa->num, d.len, d.addr);
cosa->firmware_status |= COSA_FW_RESET;
return 0;
@@ -1109,23 +1100,22 @@ static inline int cosa_start(struct cosa_data *cosa, int address)
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD))
!= (COSA_FW_RESET|COSA_FW_DOWNLOAD)) {
- printk(KERN_NOTICE "%s: download the microcode and/or reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: download the microcode and/or reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
cosa->firmware_status &= ~COSA_FW_RESET;
if ((i=startmicrocode(cosa, address)) < 0) {
- printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n",
- cosa->num, address, i);
+ pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n",
+ cosa->num, address, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n",
- cosa->num, address);
+ pr_info("cosa%d: starting microcode at 0x%04x\n", cosa->num, address);
cosa->startaddr = address;
cosa->firmware_status |= COSA_FW_START;
return 0;
@@ -1255,11 +1245,11 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
#ifdef DEBUG_DATA
int i;
- printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num,
- chan->num, len);
+ pr_info("cosa%dc%d: starting tx(0x%x)",
+ chan->cosa->num, chan->num, len);
for (i=0; i<len; i++)
- printk(" %02x", buf[i]&0xff);
- printk("\n");
+ pr_cont(" %02x", buf[i]&0xff);
+ pr_cont("\n");
#endif
spin_lock_irqsave(&cosa->lock, flags);
chan->txbuf = buf;
@@ -1353,7 +1343,7 @@ static void cosa_kick(struct cosa_data *cosa)
if (test_bit(TXBIT, &cosa->rxtx))
s = "TX DMA";
- printk(KERN_INFO "%s: %s timeout - restarting.\n", cosa->name, s);
+ pr_info("%s: %s timeout - restarting\n", cosa->name, s);
spin_lock_irqsave(&cosa->lock, flags);
cosa->rxtx = 0;
@@ -1387,7 +1377,7 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
return 0;
if ((b^ (b+len)) & 0x10000) {
if (count++ < 5)
- printk(KERN_INFO "%s: packet spanning a 64k boundary\n",
+ pr_info("%s: packet spanning a 64k boundary\n",
chan->name);
return 0;
}
@@ -1498,8 +1488,7 @@ static int readmem(struct cosa_data *cosa, char __user *microcode, int length, i
char c;
int i;
if ((i=get_wait_data(cosa)) == -1) {
- printk (KERN_INFO "cosa: 0x%04x bytes remaining\n",
- length);
+ pr_info("0x%04x bytes remaining\n", length);
return -11;
}
c=i;
@@ -1582,14 +1571,15 @@ static int get_wait_data(struct cosa_data *cosa)
short r;
r = cosa_getdata8(cosa);
#if 0
- printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries);
+ pr_info("get_wait_data returning after %d retries\n",
+ 999-retries);
#endif
return r;
}
/* sleep if not ready to read */
schedule_timeout_interruptible(1);
}
- printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+ pr_info("timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
return -1;
}
@@ -1607,7 +1597,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
if (cosa_getstatus(cosa) & SR_TX_RDY) {
cosa_putdata8(cosa, data);
#if 0
- printk(KERN_INFO "Putdata: %d retries\n", 999-retries);
+ pr_info("Putdata: %d retries\n", 999-retries);
#endif
return 0;
}
@@ -1616,7 +1606,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
schedule_timeout_interruptible(1);
#endif
}
- printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+ pr_info("cosa%d: timeout in put_wait_data (status 0x%x)\n",
cosa->num, cosa_getstatus(cosa));
return -1;
}
@@ -1636,13 +1626,13 @@ static int puthexnumber(struct cosa_data *cosa, int number)
sprintf(temp, "%04X", number);
for (i=0; i<4; i++) {
if (put_wait_data(cosa, temp[i]) == -1) {
- printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: puthexnumber failed to write byte %d\n",
+ cosa->num, i);
return -1-2*i;
}
if (get_wait_data(cosa) != temp[i]) {
- printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n",
+ cosa->num, i);
return -2-2*i;
}
}
@@ -1687,8 +1677,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
{
unsigned long flags, flags1;
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n",
- cosa->num, status);
+ pr_info("cosa%d: SR_DOWN_REQUEST status=0x%04x\n", cosa->num, status);
#endif
spin_lock_irqsave(&cosa->lock, flags);
set_bit(TXBIT, &cosa->rxtx);
@@ -1696,8 +1685,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
/* flow control, see the comment above */
int i=0;
if (!cosa->txbitmap) {
- printk(KERN_WARNING "%s: No channel wants data "
- "in TX IRQ. Expect DMA timeout.",
+ pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n",
cosa->name);
put_driver_status_nolock(cosa);
clear_bit(TXBIT, &cosa->rxtx);
@@ -1780,14 +1768,14 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
if (cosa->busmaster) {
unsigned long addr = virt_to_bus(cosa->txbuf);
int count=0;
- printk(KERN_INFO "busmaster IRQ\n");
+ pr_info("busmaster IRQ\n");
while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
count++;
udelay(10);
if (count > 1000) break;
}
- printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
- printk(KERN_INFO "ready after %d loops\n", count);
+ pr_info("status %x\n", cosa_getstatus(cosa));
+ pr_info("ready after %d loops\n", count);
cosa_putdata16(cosa, (addr >> 16)&0xffff);
count = 0;
@@ -1796,7 +1784,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
if (count > 1000) break;
udelay(10);
}
- printk(KERN_INFO "ready after %d loops\n", count);
+ pr_info("ready after %d loops\n", count);
cosa_putdata16(cosa, addr &0xffff);
flags1 = claim_dma_lock();
set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
@@ -1824,7 +1812,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
{
unsigned long flags;
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num);
+ pr_info("cosa%d: SR_UP_REQUEST\n", cosa->num);
#endif
spin_lock_irqsave(&cosa->lock, flags);
@@ -1847,7 +1835,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
debug_data_in(cosa, cosa->rxsize & 0xff);
#endif
#if 0
- printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ pr_info("cosa%d: receive rxsize = (0x%04x)\n",
cosa->num, cosa->rxsize);
#endif
}
@@ -1857,12 +1845,12 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
debug_data_in(cosa, cosa->rxsize);
#endif
#if 0
- printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ pr_info("cosa%d: receive rxsize = (0x%04x)\n",
cosa->num, cosa->rxsize);
#endif
}
if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
- printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n",
+ pr_warn("%s: rx for unknown channel (0x%04x)\n",
cosa->name, cosa->rxsize);
spin_unlock_irqrestore(&cosa->lock, flags);
goto reject;
@@ -1877,7 +1865,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
if (!cosa->rxbuf) {
reject: /* Reject the packet */
- printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
+ pr_info("cosa%d: rejecting packet on channel %d\n",
cosa->num, cosa->rxchan->num);
cosa->rxbuf = cosa->bouncebuf;
}
@@ -1924,11 +1912,11 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status)
#ifdef DEBUG_DATA
{
int i;
- printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num,
- cosa->rxchan->num, cosa->rxsize);
+ pr_info("cosa%dc%d: done rx(0x%x)",
+ cosa->num, cosa->rxchan->num, cosa->rxsize);
for (i=0; i<cosa->rxsize; i++)
- printk (" %02x", cosa->rxbuf[i]&0xff);
- printk("\n");
+ pr_cont(" %02x", cosa->rxbuf[i]&0xff);
+ pr_cont("\n");
}
#endif
/* Packet for unknown channel? */
@@ -1940,8 +1928,7 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status)
if (cosa->rxchan->rx_done(cosa->rxchan))
clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
} else {
- printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n",
- cosa->num);
+ pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num);
}
/*
* Clear the RXBIT, TXBIT and IRQBIT (the latest should be
@@ -1963,8 +1950,7 @@ static irqreturn_t cosa_interrupt(int irq, void *cosa_)
again:
status = cosa_getstatus(cosa);
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num,
- status & 0xff);
+ pr_info("cosa%d: got IRQ, status 0x%02x\n", cosa->num, status & 0xff);
#endif
#ifdef DEBUG_IO
debug_status_in(cosa, status);
@@ -1985,15 +1971,15 @@ again:
udelay(100);
goto again;
}
- printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
+ pr_info("cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
cosa->num, status & 0xff, count);
}
#ifdef DEBUG_IRQS
if (count)
- printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n",
+ pr_info("%s: %d-times got unknown status in IRQ\n",
cosa->name, count);
else
- printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
+ pr_info("%s: returning from IRQ\n", cosa->name);
#endif
return IRQ_HANDLED;
}
@@ -2024,41 +2010,41 @@ static void debug_status_in(struct cosa_data *cosa, int status)
s = "NO_REQ";
break;
}
- printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n",
+ pr_info("%s: IO: status -> 0x%02x (%s%s%s%s)\n",
cosa->name,
status,
- status & SR_USR_RQ ? "USR_RQ|":"",
- status & SR_TX_RDY ? "TX_RDY|":"",
- status & SR_RX_RDY ? "RX_RDY|":"",
+ status & SR_USR_RQ ? "USR_RQ|" : "",
+ status & SR_TX_RDY ? "TX_RDY|" : "",
+ status & SR_RX_RDY ? "RX_RDY|" : "",
s);
}
static void debug_status_out(struct cosa_data *cosa, int status)
{
- printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
+ pr_info("%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
cosa->name,
status,
- status & SR_RX_DMA_ENA ? "RXDMA|":"!rxdma|",
- status & SR_TX_DMA_ENA ? "TXDMA|":"!txdma|",
- status & SR_RST ? "RESET|":"",
- status & SR_USR_INT_ENA ? "USRINT|":"!usrint|",
- status & SR_TX_INT_ENA ? "TXINT|":"!txint|",
- status & SR_RX_INT_ENA ? "RXINT":"!rxint");
+ status & SR_RX_DMA_ENA ? "RXDMA|" : "!rxdma|",
+ status & SR_TX_DMA_ENA ? "TXDMA|" : "!txdma|",
+ status & SR_RST ? "RESET|" : "",
+ status & SR_USR_INT_ENA ? "USRINT|" : "!usrint|",
+ status & SR_TX_INT_ENA ? "TXINT|" : "!txint|",
+ status & SR_RX_INT_ENA ? "RXINT" : "!rxint");
}
static void debug_data_in(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data);
+ pr_info("%s: IO: data -> 0x%04x\n", cosa->name, data);
}
static void debug_data_out(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data);
+ pr_info("%s: IO: data <- 0x%04x\n", cosa->name, data);
}
static void debug_data_cmd(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n",
+ pr_info("%s: IO: data <- 0x%04x (%s|%s)\n",
cosa->name, data,
data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 164c362..2a3ecae 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -48,6 +48,8 @@
* Aug 8, 1998 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h> /* __init */
#include <linux/module.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
@@ -81,10 +83,9 @@ static u16 checksum(u8 *buf, u32 len);
/* Global Data */
/* private data */
-static const char modname[] = "cycx_drv";
static const char fullname[] = "Cyclom 2X Support Module";
-static const char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
- "<acme@conectiva.com.br>";
+static const char copyright[] =
+ "(c) 1998-2003 Arnaldo Carvalho de Melo <acme@conectiva.com.br>";
/* Hardware configuration options.
* These are arrays of configuration options used by verification routines.
@@ -110,8 +111,8 @@ static const long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
static int __init cycx_drv_init(void)
{
- printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
- copyright);
+ pr_info("%s v%u.%u %s\n",
+ fullname, MOD_VERSION, MOD_RELEASE, copyright);
return 0;
}
@@ -139,18 +140,16 @@ int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase)
/* Verify IRQ configuration options */
if (!get_option_index(cycx_2x_irq_options, hw->irq)) {
- printk(KERN_ERR "%s: IRQ %d is invalid!\n", modname, hw->irq);
+ pr_err("IRQ %d is invalid!\n", hw->irq);
return -EINVAL;
}
/* Setup adapter dual-port memory window and test memory */
if (!dpmbase) {
- printk(KERN_ERR "%s: you must specify the dpm address!\n",
- modname);
+ pr_err("you must specify the dpm address!\n");
return -EINVAL;
} else if (!get_option_index(cyc2x_dpmbase_options, dpmbase)) {
- printk(KERN_ERR "%s: memory address 0x%lX is invalid!\n",
- modname, dpmbase);
+ pr_err("memory address 0x%lX is invalid!\n", dpmbase);
return -EINVAL;
}
@@ -158,13 +157,12 @@ int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase)
hw->dpmsize = CYCX_WINDOWSIZE;
if (!detect_cyc2x(hw->dpmbase)) {
- printk(KERN_ERR "%s: adapter Cyclom 2X not found at "
- "address 0x%lX!\n", modname, dpmbase);
+ pr_err("adapter Cyclom 2X not found at address 0x%lX!\n",
+ dpmbase);
return -EINVAL;
}
- printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n",
- modname, dpmbase);
+ pr_info("found Cyclom 2X card at address 0x%lX\n", dpmbase);
/* Load firmware. If loader fails then shut down adapter */
err = load_cyc2x(hw, cfm, len);
@@ -339,7 +337,7 @@ static int cycx_data_boot(void __iomem *addr, u8 *code, u32 len)
for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
if (buffer_load(addr, code + i,
min_t(u32, CFM_LOAD_BUFSZ, (len - i))) < 0) {
- printk(KERN_ERR "%s: Error !!\n", modname);
+ pr_err("Error !!\n");
return -1;
}
@@ -370,7 +368,7 @@ static int cycx_code_boot(void __iomem *addr, u8 *code, u32 len)
for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
if (buffer_load(addr, code + i,
min_t(u32, CFM_LOAD_BUFSZ, (len - i)))) {
- printk(KERN_ERR "%s: Error !!\n", modname);
+ pr_err("Error !!\n");
return -1;
}
@@ -391,23 +389,20 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
u16 cksum;
/* Announce */
- printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname,
- cfm->signature);
+ pr_info("firmware signature=\"%s\"\n", cfm->signature);
/* Verify firmware signature */
if (strcmp(cfm->signature, CFM_SIGNATURE)) {
- printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n",
- modname);
+ pr_err("load_cyc2x: not Cyclom-2X firmware!\n");
return -EINVAL;
}
- printk(KERN_INFO "%s: firmware version=%u\n", modname, cfm->version);
+ pr_info("firmware version=%u\n", cfm->version);
/* Verify firmware module format version */
if (cfm->version != CFM_VERSION) {
- printk(KERN_ERR "%s:%s: firmware format %u rejected! "
- "Expecting %u.\n",
- modname, __func__, cfm->version, CFM_VERSION);
+ pr_err("%s: firmware format %u rejected! Expecting %u.\n",
+ __func__, cfm->version, CFM_VERSION);
return -EINVAL;
}
@@ -419,23 +414,22 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
if (((len - sizeof(struct cycx_firmware) - 1) != cfm->info.codesize) ||
*/
if (cksum != cfm->checksum) {
- printk(KERN_ERR "%s:%s: firmware corrupted!\n",
- modname, __func__);
- printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
- len - (int)sizeof(struct cycx_firmware) - 1,
- cfm->info.codesize);
- printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
- cksum, cfm->checksum);
+ pr_err("%s: firmware corrupted!\n", __func__);
+ pr_err(" cdsize = 0x%x (expected 0x%lx)\n",
+ len - (int)sizeof(struct cycx_firmware) - 1,
+ cfm->info.codesize);
+ pr_err(" chksum = 0x%x (expected 0x%x)\n",
+ cksum, cfm->checksum);
return -EINVAL;
}
/* If everything is ok, set reset, data and code pointers */
img_hdr = (struct cycx_fw_header *)&cfm->image;
#ifdef FIRMWARE_DEBUG
- printk(KERN_INFO "%s:%s: image sizes\n", __func__, modname);
- printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
- printk(KERN_INFO " data=%lu\n", img_hdr->data_size);
- printk(KERN_INFO " code=%lu\n", img_hdr->code_size);
+ pr_info("%s: image sizes\n", __func__);
+ pr_info(" reset=%lu\n", img_hdr->reset_size);
+ pr_info(" data=%lu\n", img_hdr->data_size);
+ pr_info(" code=%lu\n", img_hdr->code_size);
#endif
reset_image = ((u8 *)img_hdr) + sizeof(struct cycx_fw_header);
data_image = reset_image + img_hdr->reset_size;
@@ -443,15 +437,14 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
/*---- Start load ----*/
/* Announce */
- printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname,
- cfm->descr[0] ? cfm->descr : "unknown firmware",
- cfm->info.codeid);
+ pr_info("loading firmware %s (ID=%u)...\n",
+ cfm->descr[0] ? cfm->descr : "unknown firmware",
+ cfm->info.codeid);
for (i = 0 ; i < 5 ; i++) {
/* Reset Cyclom hardware */
if (!reset_cyc2x(hw->dpmbase)) {
- printk(KERN_ERR "%s: dpm problem or board not found\n",
- modname);
+ pr_err("dpm problem or board not found\n");
return -EINVAL;
}
@@ -468,19 +461,19 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
msleep_interruptible(1 * 1000);
}
- printk(KERN_ERR "%s: reset not started.\n", modname);
+ pr_err("reset not started\n");
return -EINVAL;
reset_loaded:
/* Load data.bin */
if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) {
- printk(KERN_ERR "%s: cannot load data file.\n", modname);
+ pr_err("cannot load data file\n");
return -EINVAL;
}
/* Load code.bin */
if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) {
- printk(KERN_ERR "%s: cannot load code file.\n", modname);
+ pr_err("cannot load code file\n");
return -EINVAL;
}
@@ -493,7 +486,7 @@ reset_loaded:
/* Arthur Ganzert's tip: wait a while after the firmware loading...
seg abr 26 17:17:12 EST 1999 - acme */
msleep_interruptible(7 * 1000);
- printk(KERN_INFO "%s: firmware loaded!\n", modname);
+ pr_info("firmware loaded!\n");
/* enable interrupts */
cycx_inten(hw);
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 859dba9..81fbbad 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -40,6 +40,8 @@
* 1998/08/08 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/string.h> /* inline memset(), etc. */
@@ -50,6 +52,7 @@
#include <linux/wanrouter.h> /* WAN router definitions */
#include <linux/cyclomx.h> /* cyclomx common user API definitions */
#include <linux/init.h> /* __init (when not using as a module) */
+#include <linux/interrupt.h>
unsigned int cycx_debug;
@@ -106,7 +109,7 @@ static int __init cycx_init(void)
{
int cnt, err = -ENOMEM;
- printk(KERN_INFO "%s v%u.%u %s\n",
+ pr_info("%s v%u.%u %s\n",
cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE,
cycx_copyright);
@@ -132,9 +135,8 @@ static int __init cycx_init(void)
err = register_wan_device(wandev);
if (err) {
- printk(KERN_ERR "%s: %s registration failed with "
- "error %d!\n",
- cycx_drvname, card->devname, err);
+ pr_err("%s registration failed with error %d!\n",
+ card->devname, err);
break;
}
}
@@ -197,14 +199,13 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
rc = -EINVAL;
if (!conf->data_size || !conf->data) {
- printk(KERN_ERR "%s: firmware not found in configuration "
- "data!\n", wandev->name);
+ pr_err("%s: firmware not found in configuration data!\n",
+ wandev->name);
goto out;
}
if (conf->irq <= 0) {
- printk(KERN_ERR "%s: can't configure without IRQ!\n",
- wandev->name);
+ pr_err("%s: can't configure without IRQ!\n", wandev->name);
goto out;
}
@@ -212,8 +213,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
irq = conf->irq == 2 ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
- printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
- wandev->name, irq);
+ pr_err("%s: can't reserve IRQ %d!\n", wandev->name, irq);
goto out;
}
@@ -245,8 +245,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
break;
#endif
default:
- printk(KERN_ERR "%s: this firmware is not supported!\n",
- wandev->name);
+ pr_err("%s: this firmware is not supported!\n", wandev->name);
rc = -EINVAL;
}
@@ -287,8 +286,7 @@ static int cycx_wan_shutdown(struct wan_device *wandev)
card = wandev->private;
wandev->state = WAN_UNCONFIGURED;
cycx_down(&card->hw);
- printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
- wandev->irq);
+ pr_info("%s: irq %d being freed!\n", wandev->name, wandev->irq);
free_irq(wandev->irq, card);
out: return ret;
}
@@ -307,8 +305,8 @@ static irqreturn_t cycx_isr(int irq, void *dev_id)
goto out;
if (card->in_isr) {
- printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
- card->devname, card->wandev.irq);
+ pr_warn("%s: interrupt re-entrancy on IRQ %d!\n",
+ card->devname, card->wandev.irq);
goto out;
}
@@ -336,7 +334,7 @@ void cycx_set_state(struct cycx_device *card, int state)
string_state = "disconnected!";
break;
}
- printk(KERN_INFO "%s: link %s\n", card->devname, string_state);
+ pr_info("%s: link %s\n", card->devname, string_state);
card->wandev.state = state;
}
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index cf9e15f..06f3f63 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -76,6 +76,8 @@
* 1998/08/08 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define CYCLOMX_X25_DEBUG 1
#include <linux/ctype.h> /* isdigit() */
@@ -230,8 +232,8 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
/* Verify configuration ID */
if (conf->config_id != WANCONFIG_X25) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
+ pr_info("%s: invalid configuration ID %u!\n",
+ card->devname, conf->config_id);
return -EINVAL;
}
@@ -374,8 +376,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
int err = 0;
if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
+ pr_info("%s: invalid interface name!\n", card->devname);
return -EINVAL;
}
@@ -398,8 +399,8 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
if (len) {
if (len > WAN_ADDRESS_SZ) {
- printk(KERN_ERR "%s: %s local addr too long!\n",
- wandev->name, chan->name);
+ pr_err("%s: %s local addr too long!\n",
+ wandev->name, chan->name);
err = -EINVAL;
goto error;
} else {
@@ -429,15 +430,14 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
chan->lcn = lcn;
else {
- printk(KERN_ERR
- "%s: PVC %u is out of range on interface %s!\n",
- wandev->name, lcn, chan->name);
+ pr_err("%s: PVC %u is out of range on interface %s!\n",
+ wandev->name, lcn, chan->name);
err = -EINVAL;
goto error;
}
} else {
- printk(KERN_ERR "%s: invalid media address on interface %s!\n",
- wandev->name, chan->name);
+ pr_err("%s: invalid media address on interface %s!\n",
+ wandev->name, chan->name);
err = -EINVAL;
goto error;
}
@@ -607,9 +607,8 @@ static netdev_tx_t cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
++chan->ifstats.tx_dropped;
else if (chan->svc && chan->protocol &&
chan->protocol != ntohs(skb->protocol)) {
- printk(KERN_INFO
- "%s: unsupported Ethertype 0x%04X on interface %s!\n",
- card->devname, ntohs(skb->protocol), dev->name);
+ pr_info("%s: unsupported Ethertype 0x%04X on interface %s!\n",
+ card->devname, ntohs(skb->protocol), dev->name);
++chan->ifstats.tx_errors;
} else if (chan->protocol == ETH_P_IP) {
switch (chan->state) {
@@ -643,9 +642,8 @@ static netdev_tx_t cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
cycx_x25_chan_disconnect(dev);
goto free_packet;
default:
- printk(KERN_INFO
- "%s: unknown %d x25-iface request on %s!\n",
- card->devname, skb->data[0], dev->name);
+ pr_info("%s: unknown %d x25-iface request on %s!\n",
+ card->devname, skb->data[0], dev->name);
++chan->ifstats.tx_errors;
goto free_packet;
}
@@ -746,8 +744,7 @@ static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
card->buff_int_mode_unbusy = 1;
netif_wake_queue(dev);
} else
- printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
- card->devname, lcn);
+ pr_err("%s:ackvc for inexistent lcn %d\n", card->devname, lcn);
}
/* Receive interrupt handler.
@@ -780,8 +777,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
- card->devname, lcn);
+ pr_info("%s: receiving on orphaned LCN %d!\n",
+ card->devname, lcn);
return;
}
@@ -802,8 +799,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
bufsize +
dev->hard_header_len)) == NULL) {
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
+ pr_info("%s: no socket buffers available!\n",
+ card->devname);
chan->drop_sequence = 1;
++chan->ifstats.rx_dropped;
return;
@@ -826,8 +823,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
if (bitm)
chan->drop_sequence = 1;
- printk(KERN_INFO "%s: unexpectedly long packet sequence "
- "on interface %s!\n", card->devname, dev->name);
+ pr_info("%s: unexpectedly long packet sequence on interface %s!\n",
+ card->devname, dev->name);
++chan->ifstats.rx_length_errors;
return;
}
@@ -880,8 +877,8 @@ static void cycx_x25_irq_connect(struct cycx_device *card,
dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s: connect not expected: remote %s!\n",
- card->devname, rem);
+ pr_info("%s: connect not expected: remote %s!\n",
+ card->devname, rem);
return;
}
@@ -909,8 +906,8 @@ static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
if (!dev) {
/* Invalid channel, discard packet */
clear_bit(--key, (void*)&card->u.x.connection_keys);
- printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
- "key=%d!\n", card->devname, lcn, key);
+ pr_info("%s: connect confirm not expected: lcn %d, key=%d!\n",
+ card->devname, lcn, key);
return;
}
@@ -934,8 +931,8 @@ static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
- card->devname, lcn);
+ pr_info("%s:disconnect confirm not expected!:lcn %d\n",
+ card->devname, lcn);
return;
}
@@ -980,13 +977,13 @@ static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
- printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
- printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
- printk(KERN_INFO "Log message code=0x%X\n", msg_code);
- printk(KERN_INFO "Link=%d\n", link);
- printk(KERN_INFO "log code=0x%X\n", code);
- printk(KERN_INFO "log routine=0x%X\n", routine);
- printk(KERN_INFO "Message size=%d\n", size);
+ pr_info("cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
+ pr_info("cmd->buf=0x%X\n", cmd->buf);
+ pr_info("Log message code=0x%X\n", msg_code);
+ pr_info("Link=%d\n", link);
+ pr_info("log code=0x%X\n", code);
+ pr_info("log routine=0x%X\n", routine);
+ pr_info("Message size=%d\n", size);
hex_dump("Message", bf, toread);
#endif
}
@@ -1009,24 +1006,14 @@ static void cycx_x25_irq_stat(struct cycx_device *card,
static void cycx_x25_irq_spurious(struct cycx_device *card,
struct cycx_x25_cmd *cmd)
{
- printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
- card->devname, cmd->command);
+ pr_info("%s: spurious interrupt (0x%X)!\n",
+ card->devname, cmd->command);
}
#ifdef CYCLOMX_X25_DEBUG
static void hex_dump(char *msg, unsigned char *p, int len)
{
- unsigned char hex[1024],
- * phex = hex;
-
- if (len >= (sizeof(hex) / 2))
- len = (sizeof(hex) / 2) - 1;
-
- while (len--) {
- sprintf(phex, "%02x", *p++);
- phex += 2;
- }
-
- printk(KERN_INFO "%s: %s\n", msg, hex);
+ print_hex_dump(KERN_INFO, msg, DUMP_PREFIX_OFFSET, 16, 1,
+ p, len, true);
}
#endif
@@ -1203,8 +1190,8 @@ static int x25_place_call(struct cycx_device *card,
u8 key;
if (card->u.x.connection_keys == ~0U) {
- printk(KERN_INFO "%s: too many simultaneous connection "
- "requests!\n", card->devname);
+ pr_info("%s: too many simultaneous connection requests!\n",
+ card->devname);
return -EAGAIN;
}
@@ -1381,8 +1368,8 @@ static void cycx_x25_chan_timer(unsigned long d)
if (chan->state == WAN_CONNECTED)
cycx_x25_chan_disconnect(dev);
else
- printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
- chan->card->devname, __func__, dev->name);
+ pr_err("%s: %s for svc (%s) not connected!\n",
+ chan->card->devname, __func__, dev->name);
}
/* Set logical channel state. */
@@ -1433,8 +1420,8 @@ static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
break;
}
- printk(KERN_INFO "%s: interface %s %s\n", card->devname,
- dev->name, string_state);
+ pr_info("%s: interface %s %s\n",
+ card->devname, dev->name, string_state);
chan->state = state;
}
@@ -1488,7 +1475,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", __func__);
+ pr_err("%s: out of memory\n", __func__);
return;
}
@@ -1557,56 +1544,56 @@ static void reset_timer(struct net_device *dev)
#ifdef CYCLOMX_X25_DEBUG
static void cycx_x25_dump_config(struct cycx_x25_config *conf)
{
- printk(KERN_INFO "X.25 configuration\n");
- printk(KERN_INFO "-----------------\n");
- printk(KERN_INFO "link number=%d\n", conf->link);
- printk(KERN_INFO "line speed=%d\n", conf->speed);
- printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
- printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
- printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
- printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
- printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
- printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
- printk(KERN_INFO "my address=%d\n", conf->locaddr);
- printk(KERN_INFO "remote address=%d\n", conf->remaddr);
- printk(KERN_INFO "t1=%d seconds\n", conf->t1);
- printk(KERN_INFO "t2=%d seconds\n", conf->t2);
- printk(KERN_INFO "t21=%d seconds\n", conf->t21);
- printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
- printk(KERN_INFO "t23=%d seconds\n", conf->t23);
- printk(KERN_INFO "flags=0x%x\n", conf->flags);
+ pr_info("X.25 configuration\n");
+ pr_info("-----------------\n");
+ pr_info("link number=%d\n", conf->link);
+ pr_info("line speed=%d\n", conf->speed);
+ pr_info("clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
+ pr_info("# level 2 retransm.=%d\n", conf->n2);
+ pr_info("level 2 window=%d\n", conf->n2win);
+ pr_info("level 3 window=%d\n", conf->n3win);
+ pr_info("# logical channels=%d\n", conf->nvc);
+ pr_info("level 3 pkt len=%d\n", conf->pktlen);
+ pr_info("my address=%d\n", conf->locaddr);
+ pr_info("remote address=%d\n", conf->remaddr);
+ pr_info("t1=%d seconds\n", conf->t1);
+ pr_info("t2=%d seconds\n", conf->t2);
+ pr_info("t21=%d seconds\n", conf->t21);
+ pr_info("# PVCs=%d\n", conf->npvc);
+ pr_info("t23=%d seconds\n", conf->t23);
+ pr_info("flags=0x%x\n", conf->flags);
}
static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
{
- printk(KERN_INFO "X.25 statistics\n");
- printk(KERN_INFO "--------------\n");
- printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
- printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
- printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
- printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
- printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
- printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
- printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
- printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
- printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
- printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
+ pr_info("X.25 statistics\n");
+ pr_info("--------------\n");
+ pr_info("rx_crc_errors=%d\n", stats->rx_crc_errors);
+ pr_info("rx_over_errors=%d\n", stats->rx_over_errors);
+ pr_info("n2_tx_frames=%d\n", stats->n2_tx_frames);
+ pr_info("n2_rx_frames=%d\n", stats->n2_rx_frames);
+ pr_info("tx_timeouts=%d\n", stats->tx_timeouts);
+ pr_info("rx_timeouts=%d\n", stats->rx_timeouts);
+ pr_info("n3_tx_packets=%d\n", stats->n3_tx_packets);
+ pr_info("n3_rx_packets=%d\n", stats->n3_rx_packets);
+ pr_info("tx_aborts=%d\n", stats->tx_aborts);
+ pr_info("rx_aborts=%d\n", stats->rx_aborts);
}
static void cycx_x25_dump_devs(struct wan_device *wandev)
{
struct net_device *dev = wandev->dev;
- printk(KERN_INFO "X.25 dev states\n");
- printk(KERN_INFO "name: addr: txoff: protocol:\n");
- printk(KERN_INFO "---------------------------------------\n");
+ pr_info("X.25 dev states\n");
+ pr_info("name: addr: txoff: protocol:\n");
+ pr_info("---------------------------------------\n");
while(dev) {
struct cycx_x25_channel *chan = netdev_priv(dev);
- printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
- chan->name, chan->addr, netif_queue_stopped(dev),
- chan->protocol == ETH_P_IP ? "IP" : "X25");
+ pr_info("%-5.5s %-15.15s %d ETH_P_%s\n",
+ chan->name, chan->addr, netif_queue_stopped(dev),
+ chan->protocol == ETH_P_IP ? "IP" : "X25");
dev = chan->slave;
}
}
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index af44b93..02c939e 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -28,6 +28,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -112,8 +114,7 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
dlp = netdev_priv(dev);
if (!pskb_may_pull(skb, sizeof(*hdr))) {
- printk(KERN_NOTICE "%s: invalid data no header\n",
- dev->name);
+ netdev_notice(dev, "invalid data no header\n");
dev->stats.rx_errors++;
kfree_skb(skb);
return;
@@ -126,7 +127,8 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
if (hdr->control != FRAD_I_UI)
{
- printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control);
+ netdev_notice(dev, "Invalid header flag 0x%02X\n",
+ hdr->control);
dev->stats.rx_errors++;
}
else
@@ -135,14 +137,18 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
case FRAD_P_PADDING:
if (hdr->NLPID != FRAD_P_SNAP)
{
- printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID);
+ netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+ hdr->NLPID);
dev->stats.rx_errors++;
break;
}
if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
{
- printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]);
+ netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n",
+ hdr->OUI[0],
+ hdr->OUI[1],
+ hdr->OUI[2]);
dev->stats.rx_errors++;
break;
}
@@ -163,12 +169,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
case FRAD_P_SNAP:
case FRAD_P_Q933:
case FRAD_P_CLNP:
- printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad);
+ netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+ hdr->pad);
dev->stats.rx_errors++;
break;
default:
- printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad);
+ netdev_notice(dev, "Invalid pad byte 0x%02X\n",
+ hdr->pad);
dev->stats.rx_errors++;
break;
}
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index acb9ea8..058e169 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -80,6 +80,8 @@
* - misc crapectomy.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -99,6 +101,7 @@
#include <asm/irq.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/if_arp.h>
@@ -552,7 +555,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
schedule_timeout_uninterruptible(10);
rmb();
} while (++i > 0);
- printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+ netdev_err(dev, "%s timeout\n", msg);
done:
return (i >= 0) ? i : -EAGAIN;
}
@@ -568,18 +571,18 @@ static int dscc4_do_action(struct net_device *dev, char *msg)
u32 state = readl(ioaddr);
if (state & ArAck) {
- printk(KERN_DEBUG "%s: %s ack\n", dev->name, msg);
+ netdev_dbg(dev, "%s ack\n", msg);
writel(ArAck, ioaddr);
goto done;
} else if (state & Arf) {
- printk(KERN_ERR "%s: %s failed\n", dev->name, msg);
+ netdev_err(dev, "%s failed\n", msg);
writel(Arf, ioaddr);
i = -1;
goto done;
}
rmb();
} while (++i > 0);
- printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+ netdev_err(dev, "%s timeout\n", msg);
done:
return i;
}
@@ -635,7 +638,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG);
if (dscc4_do_action(dev, "Rdt") < 0)
- printk(KERN_ERR "%s: Tx reset failed\n", dev->name);
+ netdev_err(dev, "Tx reset failed\n");
}
#endif
@@ -721,22 +724,20 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
rc = pci_request_region(pdev, 0, "registers");
if (rc < 0) {
- printk(KERN_ERR "%s: can't reserve MMIO region (regs)\n",
- DRV_NAME);
+ pr_err("can't reserve MMIO region (regs)\n");
goto err_disable_0;
}
rc = pci_request_region(pdev, 1, "LBI interface");
if (rc < 0) {
- printk(KERN_ERR "%s: can't reserve MMIO region (lbi)\n",
- DRV_NAME);
+ pr_err("can't reserve MMIO region (lbi)\n");
goto err_free_mmio_region_1;
}
ioaddr = pci_ioremap_bar(pdev, 0);
if (!ioaddr) {
- printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
- DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
- (unsigned long long)pci_resource_start(pdev, 0));
+ pr_err("cannot remap MMIO region %llx @ %llx\n",
+ (unsigned long long)pci_resource_len(pdev, 0),
+ (unsigned long long)pci_resource_start(pdev, 0));
rc = -EIO;
goto err_free_mmio_regions_2;
}
@@ -756,7 +757,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
rc = request_irq(pdev->irq, dscc4_irq, IRQF_SHARED, DRV_NAME, priv->root);
if (rc < 0) {
- printk(KERN_WARNING "%s: IRQ %d busy\n", DRV_NAME, pdev->irq);
+ pr_warn("IRQ %d busy\n", pdev->irq);
goto err_release_4;
}
@@ -903,7 +904,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
root = kcalloc(dev_per_card, sizeof(*root), GFP_KERNEL);
if (!root) {
- printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME);
+ pr_err("can't allocate data\n");
goto err_out;
}
@@ -915,7 +916,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
ppriv = kzalloc(sizeof(*ppriv), GFP_KERNEL);
if (!ppriv) {
- printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME);
+ pr_err("can't allocate private data\n");
goto err_free_dev;
}
@@ -951,7 +952,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
ret = register_hdlc_device(d);
if (ret < 0) {
- printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+ pr_err("unable to register\n");
dscc4_release_ring(dpriv);
goto err_unregister;
}
@@ -1004,7 +1005,7 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv)
if (settings->loopback && (settings->clock_type != CLOCK_INT)) {
struct net_device *dev = dscc4_to_dev(dpriv);
- printk(KERN_INFO "%s: loopback requires clock\n", dev->name);
+ netdev_info(dev, "loopback requires clock\n");
return -1;
}
return 0;
@@ -1077,7 +1078,7 @@ static int dscc4_open(struct net_device *dev)
scc_patchl(0, PowerUp, dpriv, dev, CCR0);
scc_patchl(0, 0x00050000, dpriv, dev, CCR2);
scc_writel(EventsMask, dpriv, dev, IMR);
- printk(KERN_INFO "%s: up again.\n", dev->name);
+ netdev_info(dev, "up again\n");
goto done;
}
@@ -1094,11 +1095,11 @@ static int dscc4_open(struct net_device *dev)
* situations.
*/
if (scc_readl_star(dpriv, dev) & SccBusy) {
- printk(KERN_ERR "%s busy. Try later\n", dev->name);
+ netdev_err(dev, "busy - try later\n");
ret = -EAGAIN;
goto err_out;
} else
- printk(KERN_INFO "%s: available. Good\n", dev->name);
+ netdev_info(dev, "available - good\n");
scc_writel(EventsMask, dpriv, dev, IMR);
@@ -1116,7 +1117,7 @@ static int dscc4_open(struct net_device *dev)
* reset is needed. Suggestions anyone ?
*/
if ((ret = dscc4_xpr_ack(dpriv)) < 0) {
- printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR");
+ pr_err("XPR timeout\n");
goto err_disable_scc_events;
}
@@ -1341,8 +1342,7 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EPERM;
if (dpriv->flags & FakeReset) {
- printk(KERN_INFO "%s: please reset the device"
- " before this command\n", dev->name);
+ netdev_info(dev, "please reset the device before this command\n");
return -EPERM;
}
if (copy_from_user(&dpriv->settings, line, size))
@@ -1505,8 +1505,7 @@ static irqreturn_t dscc4_irq(int irq, void *token)
writel(state, ioaddr + GSTAR);
if (state & Arf) {
- printk(KERN_ERR "%s: failure (Arf). Harass the maintener\n",
- dev->name);
+ netdev_err(dev, "failure (Arf). Harass the maintainer\n");
goto out;
}
state &= ~ArAck;
@@ -1514,7 +1513,7 @@ static irqreturn_t dscc4_irq(int irq, void *token)
if (debug > 0)
printk(KERN_DEBUG "%s: CfgIV\n", DRV_NAME);
if (priv->iqcfg[priv->cfg_cur++%IRQ_RING_SIZE] & cpu_to_le32(Arf))
- printk(KERN_ERR "%s: %s failed\n", dev->name, "CFG");
+ netdev_err(dev, "CFG failed\n");
if (!(state &= ~Cfg))
goto out;
}
@@ -1595,8 +1594,8 @@ try:
++dpriv->tx_dirty;
} else {
if (debug > 1)
- printk(KERN_ERR "%s Tx: NULL skb %d\n",
- dev->name, cur);
+ netdev_err(dev, "Tx: NULL skb %d\n",
+ cur);
}
/*
* If the driver ends sending crap on the wire, it
@@ -1615,7 +1614,7 @@ try:
* Transmit Data Underrun
*/
if (state & Xdu) {
- printk(KERN_ERR "%s: XDU. Ask maintainer\n", DRV_NAME);
+ netdev_err(dev, "Tx Data Underrun. Ask maintainer\n");
dpriv->flags = NeedIDT;
/* Tx reset */
writel(MTFi | Rdt,
@@ -1624,13 +1623,13 @@ try:
return;
}
if (state & Cts) {
- printk(KERN_INFO "%s: CTS transition\n", dev->name);
+ netdev_info(dev, "CTS transition\n");
if (!(state &= ~Cts)) /* DEBUG */
goto try;
}
if (state & Xmr) {
/* Frame needs to be sent again - FIXME */
- printk(KERN_ERR "%s: Xmr. Ask maintainer\n", DRV_NAME);
+ netdev_err(dev, "Tx ReTx. Ask maintainer\n");
if (!(state &= ~Xmr)) /* DEBUG */
goto try;
}
@@ -1648,7 +1647,7 @@ try:
break;
}
if (!i)
- printk(KERN_INFO "%s busy in irq\n", dev->name);
+ netdev_info(dev, "busy in irq\n");
scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id;
/* Keep this order: IDT before IDR */
@@ -1685,7 +1684,7 @@ try:
}
if (state & Cd) {
if (debug > 0)
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ netdev_info(dev, "CD transition\n");
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
@@ -1694,11 +1693,11 @@ try:
#ifdef DSCC4_POLLING
while (!dscc4_tx_poll(dpriv, dev));
#endif
- printk(KERN_INFO "%s: Tx Hi\n", dev->name);
+ netdev_info(dev, "Tx Hi\n");
state &= ~Hi;
}
if (state & Err) {
- printk(KERN_INFO "%s: Tx ERR\n", dev->name);
+ netdev_info(dev, "Tx ERR\n");
dev->stats.tx_errors++;
state &= ~Err;
}
@@ -1768,7 +1767,7 @@ try:
goto try;
}
if (state & Hi ) { /* HI bit */
- printk(KERN_INFO "%s: Rx Hi\n", dev->name);
+ netdev_info(dev, "Rx Hi\n");
state &= ~Hi;
goto try;
}
@@ -1799,7 +1798,7 @@ try:
goto try;
}
if (state & Cts) {
- printk(KERN_INFO "%s: CTS transition\n", dev->name);
+ netdev_info(dev, "CTS transition\n");
if (!(state &= ~Cts)) /* DEBUG */
goto try;
}
@@ -1858,14 +1857,12 @@ try:
sizeof(struct RxFD), scc_addr + CH0BRDA);
writel(MTFi|Rdr|Idr, scc_addr + CH0CFG);
if (dscc4_do_action(dev, "RDR") < 0) {
- printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
- dev->name, "RDR");
+ netdev_err(dev, "RDO recovery failed(RDR)\n");
goto rdo_end;
}
writel(MTFi|Idr, scc_addr + CH0CFG);
if (dscc4_do_action(dev, "IDR") < 0) {
- printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
- dev->name, "IDR");
+ netdev_err(dev, "RDO recovery failed(IDR)\n");
goto rdo_end;
}
rdo_end:
@@ -1874,7 +1871,7 @@ try:
goto try;
}
if (state & Cd) {
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ netdev_info(dev, "CD transition\n");
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 777d1a4..7a4c491 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/if.h>
#include <linux/hdlc.h>
#include <asm/io.h>
@@ -1664,10 +1665,9 @@ check_started_ok(struct fst_card_info *card)
* existing firmware etc so we just report it for the moment.
*/
if (FST_RDL(card, numberOfPorts) != card->nports) {
- pr_warning("Port count mismatch on card %d. "
- "Firmware thinks %d we say %d\n",
- card->card_no,
- FST_RDL(card, numberOfPorts), card->nports);
+ pr_warn("Port count mismatch on card %d. Firmware thinks %d we say %d\n",
+ card->card_no,
+ FST_RDL(card, numberOfPorts), card->nports);
}
}
@@ -1972,6 +1972,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
}
i = port->index;
+ memset(&sync, 0, sizeof(sync));
sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed);
/* Lucky card and linux use same encoding here */
sync.clock_type = FST_RDB(card, portConfig[i].internalClock) ==
diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c
index a3ea27c..33b67d8 100644
--- a/drivers/net/wan/hd64570.c
+++ b/drivers/net/wan/hd64570.c
@@ -582,8 +582,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_RX(phy_node(port)), card), port->rxin,
sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
@@ -593,8 +593,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->tx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
- printk("\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, ST: %02x %02x %02x %02x,"
" FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
index e305274..efc0db1 100644
--- a/drivers/net/wan/hd64572.c
+++ b/drivers/net/wan/hd64572.c
@@ -530,8 +530,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_RX(port->chan), card), port->rxin,
sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
@@ -541,8 +541,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
- printk("\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x,"
" ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 5d4bb61..10cc7df 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -22,6 +22,8 @@
* - proto->start() and stop() are called with spin_lock_irq held.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/hdlc.h>
#include <linux/if_arp.h>
@@ -130,10 +132,10 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
goto carrier_exit;
if (hdlc->carrier) {
- printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+ netdev_info(dev, "Carrier detected\n");
hdlc_proto_start(dev);
} else {
- printk(KERN_INFO "%s: Carrier lost\n", dev->name);
+ netdev_info(dev, "Carrier lost\n");
hdlc_proto_stop(dev);
}
@@ -165,10 +167,10 @@ int hdlc_open(struct net_device *dev)
spin_lock_irq(&hdlc->state_lock);
if (hdlc->carrier) {
- printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+ netdev_info(dev, "Carrier detected\n");
hdlc_proto_start(dev);
} else
- printk(KERN_INFO "%s: No carrier\n", dev->name);
+ netdev_info(dev, "No carrier\n");
hdlc->open = 1;
@@ -281,8 +283,8 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
if (size)
if ((dev_to_hdlc(dev)->state = kmalloc(size,
GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "Memory squeeze on"
- " hdlc_proto_attach()\n");
+ netdev_warn(dev,
+ "Memory squeeze on hdlc_proto_attach()\n");
module_put(proto->module);
return -ENOBUFS;
}
@@ -363,7 +365,7 @@ static int __init hdlc_module_init(void)
{
int result;
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
return result;
dev_add_pack(&hdlc_packet_type);
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b1e5e5b..3f20808 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -103,9 +103,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
skb = dev_alloc_skb(sizeof(struct hdlc_header) +
sizeof(struct cisco_packet));
if (!skb) {
- printk(KERN_WARNING
- "%s: Memory squeeze on cisco_keepalive_send()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on cisco_keepalive_send()\n");
return;
}
skb_reserve(skb, 4);
@@ -181,8 +179,8 @@ static int cisco_rx(struct sk_buff *skb)
CISCO_PACKET_LEN) &&
(skb->len != sizeof(struct hdlc_header) +
CISCO_BIG_PACKET_LEN)) {
- printk(KERN_INFO "%s: Invalid length of Cisco control"
- " packet (%d bytes)\n", dev->name, skb->len);
+ netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n",
+ skb->len);
goto rx_error;
}
@@ -217,8 +215,7 @@ static int cisco_rx(struct sk_buff *skb)
return NET_RX_SUCCESS;
case CISCO_ADDR_REPLY:
- printk(KERN_INFO "%s: Unexpected Cisco IP address "
- "reply\n", dev->name);
+ netdev_info(dev, "Unexpected Cisco IP address reply\n");
goto rx_error;
case CISCO_KEEPALIVE_REQ:
@@ -235,9 +232,8 @@ static int cisco_rx(struct sk_buff *skb)
min = sec / 60; sec -= min * 60;
hrs = min / 60; min -= hrs * 60;
days = hrs / 24; hrs -= days * 24;
- printk(KERN_INFO "%s: Link up (peer "
- "uptime %ud%uh%um%us)\n",
- dev->name, days, hrs, min, sec);
+ netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n",
+ days, hrs, min, sec);
netif_dormant_off(dev);
st->up = 1;
}
@@ -249,8 +245,7 @@ static int cisco_rx(struct sk_buff *skb)
} /* switch (keepalive type) */
} /* switch (protocol) */
- printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
- ntohs(data->protocol));
+ netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol));
dev_kfree_skb_any(skb);
return NET_RX_DROP;
@@ -272,7 +267,7 @@ static void cisco_timer(unsigned long arg)
if (st->up &&
time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) {
st->up = 0;
- printk(KERN_INFO "%s: Link down\n", dev->name);
+ netdev_info(dev, "Link down\n");
netif_dormant_on(dev);
}
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 13f9997..eb20281 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -446,15 +446,14 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
static inline void fr_log_dlci_active(pvc_device *pvc)
{
- printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
- pvc->frad->name,
- pvc->dlci,
- pvc->main ? pvc->main->name : "",
- pvc->main && pvc->ether ? " " : "",
- pvc->ether ? pvc->ether->name : "",
- pvc->state.new ? " new" : "",
- !pvc->state.exist ? "deleted" :
- pvc->state.active ? "active" : "inactive");
+ netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n",
+ pvc->dlci,
+ pvc->main ? pvc->main->name : "",
+ pvc->main && pvc->ether ? " " : "",
+ pvc->ether ? pvc->ether->name : "",
+ pvc->state.new ? " new" : "",
+ !pvc->state.exist ? "deleted" :
+ pvc->state.active ? "active" : "inactive");
}
@@ -481,16 +480,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
if (dce && fullrep) {
len += state(hdlc)->dce_pvc_count * (2 + stat_len);
if (len > HDLC_MAX_MRU) {
- printk(KERN_WARNING "%s: Too many PVCs while sending "
- "LMI full report\n", dev->name);
+ netdev_warn(dev, "Too many PVCs while sending LMI full report\n");
return;
}
}
skb = dev_alloc_skb(len);
if (!skb) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on fr_lmi_send()\n");
return;
}
memset(skb->data, 0, len);
@@ -615,8 +612,7 @@ static void fr_timer(unsigned long arg)
state(hdlc)->last_errors <<= 1; /* Shift the list */
if (state(hdlc)->request) {
if (state(hdlc)->reliable)
- printk(KERN_INFO "%s: No LMI status reply "
- "received\n", dev->name);
+ netdev_info(dev, "No LMI status reply received\n");
state(hdlc)->last_errors |= 1;
}
@@ -628,8 +624,7 @@ static void fr_timer(unsigned long arg)
}
if (state(hdlc)->reliable != reliable) {
- printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
- reliable ? "" : "un");
+ netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un");
fr_set_link_state(reliable, dev);
}
@@ -665,33 +660,32 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
LMI_CCITT_CISCO_LENGTH)) {
- printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
+ netdev_info(dev, "Short LMI frame\n");
return 1;
}
if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
NLPID_CCITT_ANSI_LMI)) {
- printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
- dev->name);
+ netdev_info(dev, "Received non-LMI frame with LMI DLCI\n");
return 1;
}
if (skb->data[4] != LMI_CALLREF) {
- printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
- dev->name, skb->data[4]);
+ netdev_info(dev, "Invalid LMI Call reference (0x%02X)\n",
+ skb->data[4]);
return 1;
}
if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
- printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
- dev->name, skb->data[5]);
+ netdev_info(dev, "Invalid LMI Message type (0x%02X)\n",
+ skb->data[5]);
return 1;
}
if (lmi == LMI_ANSI) {
if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
- printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
- " message (0x%02X)\n", dev->name, skb->data[6]);
+ netdev_info(dev, "Not ANSI locking shift in LMI message (0x%02X)\n",
+ skb->data[6]);
return 1;
}
i = 7;
@@ -700,34 +694,34 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
LMI_ANSI_CISCO_REPTYPE)) {
- printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
- dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI Report type IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_REPT_LEN) {
- printk(KERN_INFO "%s: Invalid LMI Report type IE length"
- " (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI Report type IE length (%u)\n",
+ skb->data[i]);
return 1;
}
reptype = skb->data[++i];
if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
- printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
- dev->name, reptype);
+ netdev_info(dev, "Unsupported LMI Report type (0x%02X)\n",
+ reptype);
return 1;
}
if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
LMI_ANSI_CISCO_ALIVE)) {
- printk(KERN_INFO "%s: Not an LMI Link integrity verification"
- " IE (0x%02X)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_INTEG_LEN) {
- printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
- " IE length (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n",
+ skb->data[i]);
return 1;
}
i++;
@@ -801,14 +795,14 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
LMI_ANSI_CISCO_PVCSTAT)) {
- printk(KERN_INFO "%s: Not an LMI PVC status IE"
- " (0x%02X)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI PVC status IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != stat_len) {
- printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
- " (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI PVC status IE length (%u)\n",
+ skb->data[i]);
return 1;
}
i++;
@@ -829,9 +823,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc = add_pvc(dev, dlci);
if (!pvc && !no_ram) {
- printk(KERN_WARNING
- "%s: Memory squeeze on fr_lmi_recv()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on fr_lmi_recv()\n");
no_ram = 1;
}
@@ -902,8 +894,8 @@ static int fr_rx(struct sk_buff *skb)
pvc = find_pvc(hdlc, dlci);
if (!pvc) {
#ifdef DEBUG_PKT
- printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
- frad->name, dlci);
+ netdev_info(frad, "No PVC for received frame's DLCI %d\n",
+ dlci);
#endif
dev_kfree_skb_any(skb);
return NET_RX_DROP;
@@ -962,14 +954,14 @@ static int fr_rx(struct sk_buff *skb)
break;
default:
- printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
- "PID=%x\n", frad->name, oui, pid);
+ netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n",
+ oui, pid);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
} else {
- printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
- "length = %i\n", frad->name, data[3], skb->len);
+ netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n",
+ data[3], skb->len);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
@@ -1073,8 +1065,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
int used;
if ((pvc = add_pvc(frad, dlci)) == NULL) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
- frad->name);
+ netdev_warn(frad, "Memory squeeze on fr_add_pvc()\n");
return -ENOBUFS;
}
@@ -1090,8 +1081,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
dev = alloc_netdev(0, "pvc%d", pvc_setup);
if (!dev) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
- frad->name);
+ netdev_warn(frad, "Memory squeeze on fr_pvc()\n");
delete_unused_pvcs(hdlc);
return -ENOBUFS;
}
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 941f053..0d76455 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -223,8 +223,7 @@ static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code,
skb = dev_alloc_skb(sizeof(struct hdlc_header) +
sizeof(struct cp_header) + magic_len + len);
if (!skb) {
- printk(KERN_WARNING "%s: out of memory in ppp_tx_cp()\n",
- dev->name);
+ netdev_warn(dev, "out of memory in ppp_tx_cp()\n");
return;
}
skb_reserve(skb, sizeof(struct hdlc_header));
@@ -345,7 +344,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data);
if (old_state != OPENED && proto->state == OPENED) {
- printk(KERN_INFO "%s: %s up\n", dev->name, proto_name(pid));
+ netdev_info(dev, "%s up\n", proto_name(pid));
if (pid == PID_LCP) {
netif_dormant_off(dev);
ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL);
@@ -356,7 +355,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
}
}
if (old_state == OPENED && proto->state != OPENED) {
- printk(KERN_INFO "%s: %s down\n", dev->name, proto_name(pid));
+ netdev_info(dev, "%s down\n", proto_name(pid));
if (pid == PID_LCP) {
netif_dormant_on(dev);
ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL);
@@ -516,37 +515,37 @@ static int ppp_rx(struct sk_buff *skb)
switch (cp->code) {
case CP_CONF_REQ:
ppp_cp_parse_cr(dev, pid, cp->id, len, skb->data);
- goto out;
+ break;
case CP_CONF_ACK:
if (cp->id == proto->cr_id)
ppp_cp_event(dev, pid, RCA, 0, 0, 0, NULL);
- goto out;
+ break;
case CP_CONF_REJ:
case CP_CONF_NAK:
if (cp->id == proto->cr_id)
ppp_cp_event(dev, pid, RCN, 0, 0, 0, NULL);
- goto out;
+ break;
case CP_TERM_REQ:
ppp_cp_event(dev, pid, RTR, 0, cp->id, 0, NULL);
- goto out;
+ break;
case CP_TERM_ACK:
ppp_cp_event(dev, pid, RTA, 0, 0, 0, NULL);
- goto out;
+ break;
case CP_CODE_REJ:
ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, 0, NULL);
- goto out;
+ break;
default:
len += sizeof(struct cp_header);
if (len > dev->mtu)
len = dev->mtu;
ppp_cp_event(dev, pid, RUC, 0, 0, len, cp);
- goto out;
+ break;
}
goto out;
@@ -585,7 +584,7 @@ static void ppp_timer(unsigned long arg)
break;
if (time_after(jiffies, ppp->last_pong +
ppp->keepalive_timeout * HZ)) {
- printk(KERN_INFO "%s: Link down\n", proto->dev->name);
+ netdev_info(proto->dev, "Link down\n");
ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL);
ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL);
} else { /* send keep-alive packet */
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 70527e5..a49aec5 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -34,7 +34,7 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", dev->name);
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -106,9 +106,8 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send connect confirm. msg to level 3 */
x25_connected(dev, 0);
else
- printk(KERN_ERR "%s: LAPB connect request "
- "failed, error code = %i\n",
- dev->name, result);
+ netdev_err(dev, "LAPB connect request failed, error code = %i\n",
+ result);
}
break;
@@ -118,9 +117,8 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send disconnect confirm. msg to level 3 */
x25_disconnected(dev, 0);
else
- printk(KERN_ERR "%s: LAPB disconnect request "
- "failed, error code = %i\n",
- dev->name, result);
+ netdev_err(dev, "LAPB disconnect request failed, error code = %i\n",
+ result);
}
break;
@@ -136,15 +134,15 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
static int x25_open(struct net_device *dev)
{
- struct lapb_register_struct cb;
int result;
-
- cb.connect_confirmation = x25_connected;
- cb.connect_indication = x25_connected;
- cb.disconnect_confirmation = x25_disconnected;
- cb.disconnect_indication = x25_disconnected;
- cb.data_indication = x25_data_indication;
- cb.data_transmit = x25_data_transmit;
+ static const struct lapb_register_struct cb = {
+ .connect_confirmation = x25_connected,
+ .connect_indication = x25_connected,
+ .disconnect_confirmation = x25_disconnected,
+ .disconnect_indication = x25_disconnected,
+ .data_indication = x25_data_indication,
+ .data_transmit = x25_data_transmit,
+ };
result = lapb_register(dev, &cb);
if (result != LAPB_OK)
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index e817583..3d80e42 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -20,6 +20,8 @@
* Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -192,8 +194,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
*/
if (!request_region(iobase, 8, "Comtrol SV11")) {
- printk(KERN_WARNING "hostess: I/O 0x%X already in use.\n",
- iobase);
+ pr_warn("I/O 0x%X already in use\n", iobase);
return NULL;
}
@@ -221,7 +222,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
"Hostess SV11", sv) < 0) {
- printk(KERN_WARNING "hostess: IRQ %d already in use.\n", irq);
+ pr_warn("IRQ %d already in use\n", irq);
goto err_irq;
}
@@ -255,7 +256,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
*/
if (z8530_init(sv)) {
- printk(KERN_ERR "Z8530 series device not found.\n");
+ pr_err("Z8530 series device not found\n");
enable_irq(irq);
goto free_dma;
}
@@ -282,7 +283,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
netdev->irq = irq;
if (register_hdlc_device(netdev)) {
- printk(KERN_ERR "hostess: unable to register HDLC device.\n");
+ pr_err("unable to register HDLC device\n");
free_netdev(netdev);
goto free_dma;
}
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 78c51ab..3f575af 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -8,6 +8,8 @@
* as published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/cdev.h>
@@ -359,9 +361,8 @@ static void hss_npe_send(struct port *port, struct msg *msg, const char* what)
{
u32 *val = (u32*)msg;
if (npe_send_message(port->npe, msg, what)) {
- printk(KERN_CRIT "HSS-%i: unable to send command [%08X:%08X]"
- " to %s\n", port->id, val[0], val[1],
- npe_name(port->npe));
+ pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n",
+ port->id, val[0], val[1], npe_name(port->npe));
BUG();
}
}
@@ -448,8 +449,7 @@ static void hss_config(struct port *port)
if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") ||
/* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */
msg.cmd != PORT_CONFIG_LOAD || msg.data32) {
- printk(KERN_CRIT "HSS-%i: HSS_LOAD_CONFIG failed\n",
- port->id);
+ pr_crit("HSS-%i: HSS_LOAD_CONFIG failed\n", port->id);
BUG();
}
@@ -478,8 +478,7 @@ static u32 hss_get_status(struct port *port)
msg.hss_port = port->id;
hss_npe_send(port, &msg, "PORT_ERROR_READ");
if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) {
- printk(KERN_CRIT "HSS-%i: unable to read HSS status\n",
- port->id);
+ pr_crit("HSS-%i: unable to read HSS status\n", port->id);
BUG();
}
@@ -737,9 +736,8 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
dev->stats.rx_errors++;
break;
default: /* FIXME - remove printk */
- printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X"
- " errors %u\n", dev->name, desc->status,
- desc->error_count);
+ netdev_err(dev, "hss_hdlc_poll: status 0x%02X errors %u\n",
+ desc->status, desc->error_count);
dev->stats.rx_errors++;
}
@@ -1128,8 +1126,8 @@ static int hss_hdlc_close(struct net_device *dev)
buffs--;
if (buffs)
- printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
- " left in NPE\n", dev->name, buffs);
+ netdev_crit(dev, "unable to drain RX queue, %i buffer(s) left in NPE\n",
+ buffs);
buffs = TX_DESCS;
while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0)
@@ -1144,8 +1142,8 @@ static int hss_hdlc_close(struct net_device *dev)
} while (++i < MAX_CLOSE_WAIT);
if (buffs)
- printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
- "left in NPE\n", dev->name, buffs);
+ netdev_crit(dev, "unable to drain TX queue, %i buffer(s) left in NPE\n",
+ buffs);
#if DEBUG_CLOSE
if (!buffs)
printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
@@ -1365,7 +1363,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
platform_set_drvdata(pdev, port);
- printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id);
+ netdev_info(dev, "HSS-%i\n", port->id);
return 0;
err_free_netdev:
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index eec463f..7beeb9b 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -20,6 +20,8 @@
* 2000-11-14 Henner Eisen dev_hold/put, NETDEV_GOING_DOWN support
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -165,13 +167,11 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
break;
case X25_IFACE_CONNECT:
if ((err = lapb_connect_request(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_connect_request "
- "error: %d\n", err);
+ pr_err("lapb_connect_request error: %d\n", err);
goto drop;
case X25_IFACE_DISCONNECT:
if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_disconnect_request "
- "err: %d\n", err);
+ pr_err("lapb_disconnect_request err: %d\n", err);
/* Fall thru */
default:
goto drop;
@@ -180,7 +180,7 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
skb_pull(skb, 1);
if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
- printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
+ pr_err("lapb_data_request error - %d\n", err);
goto drop;
}
out:
@@ -220,7 +220,7 @@ static void lapbeth_connected(struct net_device *dev, int reason)
struct sk_buff *skb = dev_alloc_skb(1);
if (!skb) {
- printk(KERN_ERR "lapbeth: out of memory\n");
+ pr_err("out of memory\n");
return;
}
@@ -237,7 +237,7 @@ static void lapbeth_disconnected(struct net_device *dev, int reason)
struct sk_buff *skb = dev_alloc_skb(1);
if (!skb) {
- printk(KERN_ERR "lapbeth: out of memory\n");
+ pr_err("out of memory\n");
return;
}
@@ -259,14 +259,13 @@ static int lapbeth_set_mac_address(struct net_device *dev, void *addr)
}
-static struct lapb_register_struct lapbeth_callbacks = {
+static const struct lapb_register_struct lapbeth_callbacks = {
.connect_confirmation = lapbeth_connected,
.connect_indication = lapbeth_connected,
.disconnect_confirmation = lapbeth_disconnected,
.disconnect_indication = lapbeth_disconnected,
.data_indication = lapbeth_data_indication,
.data_transmit = lapbeth_data_transmit,
-
};
/*
@@ -277,7 +276,7 @@ static int lapbeth_open(struct net_device *dev)
int err;
if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
- printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
+ pr_err("lapb_register error: %d\n", err);
return -ENODEV;
}
@@ -292,7 +291,7 @@ static int lapbeth_close(struct net_device *dev)
netif_stop_queue(dev);
if ((err = lapb_unregister(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
+ pr_err("lapb_unregister error: %d\n", err);
return 0;
}
diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h
index 01ad452..a1d202d 100644
--- a/drivers/net/wan/lmc/lmc_var.h
+++ b/drivers/net/wan/lmc/lmc_var.h
@@ -380,7 +380,7 @@ struct lmc___softc {
/* CSR6 settings */
#define OPERATION_MODE 0x00000200 /* Full Duplex */
#define PROMISC_MODE 0x00000040 /* Promiscuous Mode */
-#define RECIEVE_ALL 0x40000000 /* Receive All */
+#define RECEIVE_ALL 0x40000000 /* Receive All */
#define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames */
/* Dec control registers CSR6 as well */
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 17d408f..5129ad5 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -16,6 +16,8 @@
* SDL Inc. PPP/HDLC/CISCO driver
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -341,57 +343,57 @@ static int __init n2_run(unsigned long io, unsigned long irq,
int i;
if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) {
- printk(KERN_ERR "n2: invalid I/O port value\n");
+ pr_err("invalid I/O port value\n");
return -ENODEV;
}
if (irq < 3 || irq > 15 || irq == 6) /* FIXME */ {
- printk(KERN_ERR "n2: invalid IRQ value\n");
+ pr_err("invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) {
- printk(KERN_ERR "n2: invalid RAM value\n");
+ pr_err("invalid RAM value\n");
return -ENODEV;
}
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "n2: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
return -ENOBUFS;
}
card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
if (!card->ports[0].dev || !card->ports[1].dev) {
- printk(KERN_ERR "n2: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
n2_destroy_card(card);
return -ENOMEM;
}
if (!request_region(io, N2_IOPORTS, devname)) {
- printk(KERN_ERR "n2: I/O port region in use\n");
+ pr_err("I/O port region in use\n");
n2_destroy_card(card);
return -EBUSY;
}
card->io = io;
if (request_irq(irq, sca_intr, 0, devname, card)) {
- printk(KERN_ERR "n2: could not allocate IRQ\n");
+ pr_err("could not allocate IRQ\n");
n2_destroy_card(card);
return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) {
- printk(KERN_ERR "n2: could not request RAM window\n");
+ pr_err("could not request RAM window\n");
n2_destroy_card(card);
return -EBUSY;
}
card->phy_winbase = winbase;
card->winbase = ioremap(winbase, USE_WINDOWSIZE);
if (!card->winbase) {
- printk(KERN_ERR "n2: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
n2_destroy_card(card);
return -EFAULT;
}
@@ -413,7 +415,7 @@ static int __init n2_run(unsigned long io, unsigned long irq,
break;
default:
- printk(KERN_ERR "n2: invalid window size\n");
+ pr_err("invalid window size\n");
n2_destroy_card(card);
return -ENODEV;
}
@@ -433,12 +435,12 @@ static int __init n2_run(unsigned long io, unsigned long irq,
card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) *
(card->tx_ring_buffers + card->rx_ring_buffers);
- printk(KERN_INFO "n2: RISCom/N2 %u KB RAM, IRQ%u, "
- "using %u TX + %u RX packets rings\n", card->ram_size / 1024,
- card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("RISCom/N2 %u KB RAM, IRQ%u, using %u TX + %u RX packets rings\n",
+ card->ram_size / 1024, card->irq,
+ card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "n2: RAM test failed\n");
+ pr_err("RAM test failed\n");
n2_destroy_card(card);
return -EIO;
}
@@ -474,16 +476,14 @@ static int __init n2_run(unsigned long io, unsigned long irq,
port->card = card;
if (register_hdlc_device(dev)) {
- printk(KERN_WARNING "n2: unable to register hdlc "
- "device\n");
+ pr_warn("unable to register hdlc device\n");
port->card = NULL;
n2_destroy_card(card);
return -ENOBUFS;
}
sca_init_port(port); /* Set up SCA memory */
- printk(KERN_INFO "%s: RISCom/N2 node %d\n",
- dev->name, port->phy_node);
+ netdev_info(dev, "RISCom/N2 node %d\n", port->phy_node);
}
*new_card = card;
@@ -498,12 +498,12 @@ static int __init n2_init(void)
{
if (hw==NULL) {
#ifdef MODULE
- printk(KERN_INFO "n2: no card initialized\n");
+ pr_info("no card initialized\n");
#endif
return -EINVAL; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
do {
unsigned long io, irq, ram;
@@ -541,7 +541,7 @@ static int __init n2_init(void)
return first_card ? 0 : -EINVAL;
}while(*hw++ == ':');
- printk(KERN_ERR "n2: invalid hardware parameters\n");
+ pr_err("invalid hardware parameters\n");
return first_card ? 0 : -EINVAL;
}
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 9617d3d..1eeedd6 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -212,6 +212,8 @@ static const char rcsid[] =
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -3242,7 +3244,7 @@ static inline void show_version(void)
rcsdate++;
tmp = strrchr(rcsdate, ' ');
*tmp = '\0';
- printk(KERN_INFO "Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
+ pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
} /* show_version */
static const struct net_device_ops cpc_netdev_ops = {
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 1c65d1c..d47d2cd 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -755,7 +755,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch));
- cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty;
+ cpc_tty = pc300dev->cpc_tty;
while (1) {
rx_len = 0;
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index c7ab3be..c49c1b3 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -17,6 +17,8 @@
* PC300/X21 cards.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -318,7 +320,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -328,7 +330,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
- printk(KERN_ERR "pc300: invalid card EEPROM parameters\n");
+ pr_err("invalid card EEPROM parameters\n");
pc300_pci_remove_one(pdev);
return -EFAULT;
}
@@ -345,7 +347,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
if (card->plxbase == NULL ||
card->scabase == NULL ||
card->rambase == NULL) {
- printk(KERN_ERR "pc300: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
pc300_pci_remove_one(pdev);
}
@@ -370,7 +372,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
for (i = 0; i < card->n_ports; i++)
if (!(card->ports[i].netdev = alloc_hdlcdev(&card->ports[i]))) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pc300_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -411,15 +413,14 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
card->buff_offset = card->n_ports * sizeof(pkt_desc) *
(card->tx_ring_buffers + card->rx_ring_buffers);
- printk(KERN_INFO "pc300: PC300/%s, %u KB RAM at 0x%x, IRQ%u, "
- "using %u TX + %u RX packets rings\n",
- card->type == PC300_X21 ? "X21" :
- card->type == PC300_TE ? "TE" : "RSV",
- ramsize / 1024, ramphys, pdev->irq,
- card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("PC300/%s, %u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+ card->type == PC300_X21 ? "X21" :
+ card->type == PC300_TE ? "TE" : "RSV",
+ ramsize / 1024, ramphys, pdev->irq,
+ card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "pc300: RAM test failed\n");
+ pr_err("RAM test failed\n");
pc300_pci_remove_one(pdev);
return -EFAULT;
}
@@ -429,8 +430,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
/* Allocate IRQ */
if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pc300", card)) {
- printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n",
- pdev->irq);
+ pr_warn("could not allocate IRQ%d\n", pdev->irq);
pc300_pci_remove_one(pdev);
return -EBUSY;
}
@@ -466,15 +466,13 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
sca_init_port(port);
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "pc300: unable to register hdlc "
- "device\n");
+ pr_err("unable to register hdlc device\n");
port->card = NULL;
pc300_pci_remove_one(pdev);
return -ENOBUFS;
}
- printk(KERN_INFO "%s: PC300 channel %d\n",
- dev->name, port->chan);
+ netdev_info(dev, "PC300 channel %d\n", port->chan);
}
return 0;
}
@@ -505,11 +503,11 @@ static struct pci_driver pc300_pci_driver = {
static int __init pc300_init_module(void)
{
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
- printk(KERN_ERR "pc300: Invalid PCI clock frequency\n");
+ pr_err("Invalid PCI clock frequency\n");
return -EINVAL;
}
if (use_crystal_clock != 0 && use_crystal_clock != 1) {
- printk(KERN_ERR "pc300: Invalid 'use_crystal_clock' value\n");
+ pr_err("Invalid 'use_crystal_clock' value\n");
return -EINVAL;
}
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index fd73759..1ce2116 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -14,6 +14,8 @@
* PLX Technology Inc. PCI9052 Data Book
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -297,7 +299,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -306,7 +308,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card->ports[0].netdev = alloc_hdlcdev(&card->ports[0]);
card->ports[1].netdev = alloc_hdlcdev(&card->ports[1]);
if (!card->ports[0].netdev || !card->ports[1].netdev) {
- printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci200_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -314,7 +316,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
- printk(KERN_ERR "pci200syn: invalid card EEPROM parameters\n");
+ pr_err("invalid card EEPROM parameters\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -331,7 +333,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
if (card->plxbase == NULL ||
card->scabase == NULL ||
card->rambase == NULL) {
- printk(KERN_ERR "pci200syn: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -357,12 +359,12 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers +
card->rx_ring_buffers);
- printk(KERN_INFO "pci200syn: %u KB RAM at 0x%x, IRQ%u, using %u TX +"
- " %u RX packets rings\n", ramsize / 1024, ramphys,
- pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("%u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+ ramsize / 1024, ramphys,
+ pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "pci200syn: RAM test failed\n");
+ pr_err("RAM test failed\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -373,8 +375,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
/* Allocate IRQ */
if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pci200syn", card)) {
- printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
- pdev->irq);
+ pr_warn("could not allocate IRQ%d\n", pdev->irq);
pci200_pci_remove_one(pdev);
return -EBUSY;
}
@@ -400,15 +401,13 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
port->card = card;
sca_init_port(port);
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "pci200syn: unable to register hdlc "
- "device\n");
+ pr_err("unable to register hdlc device\n");
port->card = NULL;
pci200_pci_remove_one(pdev);
return -ENOBUFS;
}
- printk(KERN_INFO "%s: PCI200SYN channel %d\n",
- dev->name, port->chan);
+ netdev_info(dev, "PCI200SYN channel %d\n", port->chan);
}
sca_flush(card);
@@ -435,7 +434,7 @@ static struct pci_driver pci200_pci_driver = {
static int __init pci200_init_module(void)
{
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
- printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
+ pr_err("Invalid PCI clock frequency\n");
return -EINVAL;
}
return pci_register_driver(&pci200_pci_driver);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index cff13a9..783168c 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -37,6 +37,8 @@
* Known problem: this driver wasn't tested on multiprocessor machine.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
@@ -200,8 +202,8 @@ sbni_isa_probe( struct net_device *dev )
return 0;
else {
- printk( KERN_ERR "sbni: base address 0x%lx is busy, or adapter "
- "is malfunctional!\n", dev->base_addr );
+ pr_err("base address 0x%lx is busy, or adapter is malfunctional!\n",
+ dev->base_addr);
return -ENODEV;
}
}
@@ -210,7 +212,7 @@ static const struct net_device_ops sbni_netdev_ops = {
.ndo_open = sbni_open,
.ndo_stop = sbni_close,
.ndo_start_xmit = sbni_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = sbni_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
@@ -226,7 +228,6 @@ static void __init sbni_devsetup(struct net_device *dev)
int __init sbni_probe(int unit)
{
struct net_device *dev;
- static unsigned version_printed __initdata = 0;
int err;
dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup);
@@ -250,8 +251,7 @@ int __init sbni_probe(int unit)
free_netdev(dev);
return err;
}
- if( version_printed++ == 0 )
- printk( KERN_INFO "%s", version );
+ pr_info_once("%s", version);
return 0;
}
@@ -303,7 +303,6 @@ sbni_pci_probe( struct net_device *dev )
!= NULL ) {
int pci_irq_line;
unsigned long pci_ioaddr;
- u16 subsys;
if( pdev->vendor != SBNI_PCI_VENDOR &&
pdev->device != SBNI_PCI_DEVICE )
@@ -314,9 +313,7 @@ sbni_pci_probe( struct net_device *dev )
/* Avoid already found cards from previous calls */
if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
- pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
-
- if (subsys != 2)
+ if (pdev->subsystem_device != 2)
continue;
/* Dual adapter is present */
@@ -326,9 +323,9 @@ sbni_pci_probe( struct net_device *dev )
}
if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
- printk( KERN_WARNING
- " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
- " You should use the PCI BIOS setup to assign a valid IRQ line.\n",
+ pr_warn(
+"WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+"You should use the PCI BIOS setup to assign a valid IRQ line.\n",
pci_irq_line );
/* avoiding re-enable dual adapters */
@@ -372,8 +369,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
outb( 0, ioaddr + CSR0 );
if( !irq ) {
- printk( KERN_ERR "%s: can't detect device irq!\n",
- dev->name );
+ pr_err("%s: can't detect device irq!\n", dev->name);
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
@@ -386,7 +382,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
/* Fill in sbni-specific dev fields. */
nl = netdev_priv(dev);
if( !nl ) {
- printk( KERN_ERR "%s: unable to get memory!\n", dev->name );
+ pr_err("%s: unable to get memory!\n", dev->name);
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
@@ -415,21 +411,21 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
if( inb( ioaddr + CSR0 ) & 0x01 )
nl->state |= FL_SLOW_MODE;
- printk( KERN_NOTICE "%s: ioaddr %#lx, irq %d, "
- "MAC: 00:ff:01:%02x:%02x:%02x\n",
- dev->name, dev->base_addr, dev->irq,
- ((u8 *) dev->dev_addr) [3],
- ((u8 *) dev->dev_addr) [4],
- ((u8 *) dev->dev_addr) [5] );
+ pr_notice("%s: ioaddr %#lx, irq %d, MAC: 00:ff:01:%02x:%02x:%02x\n",
+ dev->name, dev->base_addr, dev->irq,
+ ((u8 *)dev->dev_addr)[3],
+ ((u8 *)dev->dev_addr)[4],
+ ((u8 *)dev->dev_addr)[5]);
- printk( KERN_NOTICE "%s: speed %d, receive level ", dev->name,
- ( (nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
- / (1 << nl->csr1.rate) );
+ pr_notice("%s: speed %d",
+ dev->name,
+ ((nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
+ / (1 << nl->csr1.rate));
if( nl->delta_rxl == 0 )
- printk( "0x%x (fixed)\n", nl->cur_rxl_index );
+ pr_cont(", receive level 0x%x (fixed)\n", nl->cur_rxl_index);
else
- printk( "(auto)\n");
+ pr_cont(", receive level (auto)\n");
#ifdef CONFIG_SBNI_MULTILINE
nl->master = dev;
@@ -568,7 +564,7 @@ handle_channel( struct net_device *dev )
*/
csr0 = inb( ioaddr + CSR0 );
if( !(csr0 & TR_RDY) || (csr0 & RC_RDY) )
- printk( KERN_ERR "%s: internal error!\n", dev->name );
+ netdev_err(dev, "internal error!\n");
/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
if( req_ans || nl->tx_frameno != 0 )
@@ -851,7 +847,7 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev )
/* nl->tx_buf_p == NULL here! */
if( nl->tx_buf_p )
- printk( KERN_ERR "%s: memory leak!\n", dev->name );
+ netdev_err(dev, "memory leak!\n");
nl->outpos = 0;
nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
@@ -1179,16 +1175,15 @@ sbni_open( struct net_device *dev )
((struct net_local *) (netdev_priv(*p)))
->second = dev;
- printk( KERN_NOTICE "%s: using shared irq "
- "with %s\n", dev->name, (*p)->name );
+ netdev_notice(dev, "using shared irq with %s\n",
+ (*p)->name);
nl->state |= FL_SECONDARY;
goto handler_attached;
}
}
if( request_irq(dev->irq, sbni_interrupt, IRQF_SHARED, dev->name, dev) ) {
- printk( KERN_ERR "%s: unable to get IRQ %d.\n",
- dev->name, dev->irq );
+ netdev_err(dev, "unable to get IRQ %d\n", dev->irq);
return -EAGAIN;
}
@@ -1220,8 +1215,8 @@ sbni_close( struct net_device *dev )
struct net_local *nl = netdev_priv(dev);
if( nl->second && nl->second->flags & IFF_UP ) {
- printk( KERN_NOTICE "Secondary channel (%s) is active!\n",
- nl->second->name );
+ netdev_notice(dev, "Secondary channel (%s) is active!\n",
+ nl->second->name);
return -EBUSY;
}
@@ -1363,8 +1358,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
return -EFAULT;
slave_dev = dev_get_by_name(&init_net, slave_name );
if( !slave_dev || !(slave_dev->flags & IFF_UP) ) {
- printk( KERN_ERR "%s: trying to enslave non-active "
- "device %s\n", dev->name, slave_name );
+ netdev_err(dev, "trying to enslave non-active device %s\n",
+ slave_name);
return -EPERM;
}
@@ -1417,8 +1412,7 @@ enslave( struct net_device *dev, struct net_device *slave_dev )
spin_unlock( &snl->lock );
spin_unlock( &nl->lock );
- printk( KERN_NOTICE "%s: slave device (%s) attached.\n",
- dev->name, slave_dev->name );
+ netdev_notice(dev, "slave device (%s) attached\n", slave_dev->name);
return 0;
}
@@ -1547,7 +1541,7 @@ sbni_setup( char *p )
break;
}
bad_param:
- printk( KERN_ERR "Error in sbni kernel parameter!\n" );
+ pr_err("Error in sbni kernel parameter!\n");
return 0;
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3f4e2b5..c853161 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -32,6 +32,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -350,24 +352,24 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
case SDLA_RET_MODEM:
state = data;
if (*state & SDLA_MODEM_DCD_LOW)
- printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name);
+ netdev_info(dev, "Modem DCD unexpectedly low!\n");
if (*state & SDLA_MODEM_CTS_LOW)
- printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name);
+ netdev_info(dev, "Modem CTS unexpectedly low!\n");
/* I should probably do something about this! */
break;
case SDLA_RET_CHANNEL_OFF:
- printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name);
+ netdev_info(dev, "Channel became inoperative!\n");
/* same here */
break;
case SDLA_RET_CHANNEL_ON:
- printk(KERN_INFO "%s: Channel became operative!\n", dev->name);
+ netdev_info(dev, "Channel became operative!\n");
/* same here */
break;
case SDLA_RET_DLCI_STATUS:
- printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name);
+ netdev_info(dev, "Status change reported by Access Node\n");
len /= sizeof(struct _dlci_stat);
for(pstatus = data, i=0;i < len;i++,pstatus++)
{
@@ -382,29 +384,32 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
sprintf(line, "unknown status: %02X", pstatus->flags);
state = line;
}
- printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
+ netdev_info(dev, "DLCI %i: %s\n",
+ pstatus->dlci, state);
/* same here */
}
break;
case SDLA_RET_DLCI_UNKNOWN:
- printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name);
+ netdev_info(dev, "Received unknown DLCIs:");
len /= sizeof(short);
for(pdlci = data,i=0;i < len;i++,pdlci++)
- printk(" %i", *pdlci);
- printk("\n");
+ pr_cont(" %i", *pdlci);
+ pr_cont("\n");
break;
case SDLA_RET_TIMEOUT:
- printk(KERN_ERR "%s: Command timed out!\n", dev->name);
+ netdev_err(dev, "Command timed out!\n");
break;
case SDLA_RET_BUF_OVERSIZE:
- printk(KERN_INFO "%s: Bc/CIR overflow, acceptable size is %i\n", dev->name, len);
+ netdev_info(dev, "Bc/CIR overflow, acceptable size is %i\n",
+ len);
break;
case SDLA_RET_BUF_TOO_BIG:
- printk(KERN_INFO "%s: Buffer size over specified max of %i\n", dev->name, len);
+ netdev_info(dev, "Buffer size over specified max of %i\n",
+ len);
break;
case SDLA_RET_CHANNEL_INACTIVE:
@@ -415,7 +420,8 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
break;
default:
- printk(KERN_DEBUG "%s: Cmd 0x%2.2X generated return code 0x%2.2X\n", dev->name, cmd, ret);
+ netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
+ cmd, ret);
/* Further processing could be done here */
break;
}
@@ -678,12 +684,14 @@ static netdev_tx_t sdla_transmit(struct sk_buff *skb,
case ARPHRD_FRAD:
if (skb->dev->type != ARPHRD_DLCI)
{
- printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+ netdev_warn(dev, "Non DLCI device, type %i, tried to send on FRAD module\n",
+ skb->dev->type);
accept = 0;
}
break;
default:
- printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
+ netdev_warn(dev, "unknown firmware type 0x%04X\n",
+ dev->type);
accept = 0;
break;
}
@@ -807,7 +815,8 @@ static void sdla_receive(struct net_device *dev)
if (i == CONFIG_DLCI_MAX)
{
- printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci);
+ netdev_notice(dev, "Received packet from invalid DLCI %i, ignoring\n",
+ dlci);
dev->stats.rx_errors++;
success = 0;
}
@@ -819,7 +828,7 @@ static void sdla_receive(struct net_device *dev)
skb = dev_alloc_skb(len + sizeof(struct frhdr));
if (skb == NULL)
{
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ netdev_notice(dev, "Memory squeeze, dropping packet\n");
dev->stats.rx_dropped++;
success = 0;
}
@@ -880,8 +889,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id)
if (!flp->initialized)
{
- printk(KERN_WARNING "%s: irq %d for uninitialized device.\n",
- dev->name, dev->irq);
+ netdev_warn(dev, "irq %d for uninitialized device\n", dev->irq);
return IRQ_NONE;
}
@@ -901,7 +909,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id)
case SDLA_INTR_TX:
case SDLA_INTR_COMPLETE:
case SDLA_INTR_TIMER:
- printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);
+ netdev_warn(dev, "invalid irq flag 0x%02X\n", byte);
break;
}
@@ -1347,7 +1355,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
return -EINVAL;
if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
- printk(KERN_WARNING "SDLA: io-port 0x%04lx in use\n", dev->base_addr);
+ pr_warn("io-port 0x%04lx in use\n", dev->base_addr);
return -EINVAL;
}
base = map->base_addr;
@@ -1412,7 +1420,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
}
}
- printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
+ netdev_notice(dev, "Unknown card type\n");
err = -ENODEV;
goto fail;
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index e91457d..0b4fd05 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -12,6 +12,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -190,7 +192,7 @@ static int slvl_setup(struct slvl_device *sv, int iobase, int irq)
dev->irq = irq;
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "sealevel: unable to register HDLC device\n");
+ pr_err("unable to register HDLC device\n");
free_netdev(dev);
return -1;
}
@@ -215,8 +217,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
*/
if (!request_region(iobase, 8, "Sealevel 4021")) {
- printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n",
- iobase);
+ pr_warn("I/O 0x%X already in use\n", iobase);
return NULL;
}
@@ -267,7 +268,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
"SeaLevel", dev) < 0) {
- printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+ pr_warn("IRQ %d already in use\n", irq);
goto err_request_irq;
}
@@ -292,7 +293,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
*/
if (z8530_init(dev) != 0) {
- printk(KERN_ERR "Z8530 series device not found.\n");
+ pr_err("Z8530 series device not found\n");
enable_irq(irq);
goto free_hw;
}
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index db73a7b..c643d77 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -13,6 +13,8 @@
* - wanXL100 will require minor driver modifications, no access to hw
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -22,6 +24,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/hdlc.h>
@@ -101,9 +104,8 @@ static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr,
{
dma_addr_t addr = pci_map_single(pdev, ptr, size, direction);
if (addr + size > 0x100000000LL)
- printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory"
- " at 0x%LX!\n", pci_name(pdev),
- (unsigned long long)addr);
+ pr_crit("%s: pci_map_single() returned memory at 0x%llx!\n",
+ pci_name(pdev), (unsigned long long)addr);
return addr;
}
@@ -146,8 +148,8 @@ static inline void wanxl_cable_intr(port_t *port)
}
dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE";
}
- printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
- port->dev->name, pm, dte, cable, dsr, dcd);
+ netdev_info(port->dev, "%s%s module, %s cable%s%s\n",
+ pm, dte, cable, dsr, dcd);
if (value & STATUS_CABLE_DCD)
netif_carrier_on(port->dev);
@@ -197,8 +199,8 @@ static inline void wanxl_rx_intr(card_t *card)
while (desc = &card->status->rx_descs[card->rx_in],
desc->stat != PACKET_EMPTY) {
if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
- printk(KERN_CRIT "wanXL %s: received packet for"
- " nonexistent port\n", pci_name(card->pdev));
+ pr_crit("%s: received packet for nonexistent port\n",
+ pci_name(card->pdev));
else {
struct sk_buff *skb = card->rx_skbs[card->rx_in];
port_t *port = &card->ports[desc->stat &
@@ -282,7 +284,7 @@ static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name);
#endif
netif_stop_queue(dev);
- spin_unlock_irq(&port->lock);
+ spin_unlock(&port->lock);
return NETDEV_TX_BUSY; /* request packet to be queued */
}
@@ -353,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
ifr->ifr_settings.size = size; /* data size wanted */
return -ENOBUFS;
}
+ memset(&line, 0, sizeof(line));
line.clock_type = get_status(port)->clocking;
line.clock_rate = 0;
line.loopback = 0;
@@ -396,7 +399,7 @@ static int wanxl_open(struct net_device *dev)
int i;
if (get_status(port)->open) {
- printk(KERN_ERR "%s: port already open\n", dev->name);
+ netdev_err(dev, "port already open\n");
return -EIO;
}
if ((i = hdlc_open(dev)) != 0)
@@ -416,7 +419,7 @@ static int wanxl_open(struct net_device *dev)
}
} while (time_after(timeout, jiffies));
- printk(KERN_ERR "%s: unable to open port\n", dev->name);
+ netdev_err(dev, "unable to open port\n");
/* ask the card to close the port, should it be still alive */
writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr);
return -EFAULT;
@@ -442,7 +445,7 @@ static int wanxl_close(struct net_device *dev)
} while (time_after(timeout, jiffies));
if (get_status(port)->open)
- printk(KERN_ERR "%s: unable to close port\n", dev->name);
+ netdev_err(dev, "unable to close port\n");
netif_stop_queue(dev);
@@ -567,11 +570,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
int i, ports, alloc_size;
#ifndef MODULE
- static int printed_version;
- if (!printed_version) {
- printed_version++;
- printk(KERN_INFO "%s\n", version);
- }
+ pr_info_once("%s\n", version);
#endif
i = pci_enable_device(pdev);
@@ -587,7 +586,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
work on most platforms */
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(28)) ||
pci_set_dma_mask(pdev, DMA_BIT_MASK(28))) {
- printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+ pr_err("No usable DMA configuration\n");
return -EIO;
}
@@ -606,8 +605,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
alloc_size = sizeof(card_t) + ports * sizeof(port_t);
card = kzalloc(alloc_size, GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
- pci_name(pdev));
+ pr_err("%s: unable to allocate memory\n", pci_name(pdev));
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -634,7 +632,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
to indicate the card can do 32-bit DMA addressing */
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) ||
pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
- printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+ pr_err("No usable DMA configuration\n");
wanxl_pci_remove_one(pdev);
return -EIO;
}
@@ -644,7 +642,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card->plx = ioremap_nocache(plx_phy, 0x70);
if (!card->plx) {
- printk(KERN_ERR "wanxl: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
wanxl_pci_remove_one(pdev);
return -EFAULT;
}
@@ -656,8 +654,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
timeout = jiffies + 20 * HZ;
while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) {
if (time_before(timeout, jiffies)) {
- printk(KERN_WARNING "wanXL %s: timeout waiting for"
- " PUTS to complete\n", pci_name(pdev));
+ pr_warn("%s: timeout waiting for PUTS to complete\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -668,8 +666,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
break;
default:
- printk(KERN_WARNING "wanXL %s: PUTS test 0x%X"
- " failed\n", pci_name(pdev), stat & 0x30);
+ pr_warn("%s: PUTS test 0x%X failed\n",
+ pci_name(pdev), stat & 0x30);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -687,17 +685,16 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
/* sanity check the board's reported memory size */
if (ramsize < BUFFERS_ADDR +
(TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) {
- printk(KERN_WARNING "wanXL %s: no enough on-board RAM"
- " (%u bytes detected, %u bytes required)\n",
- pci_name(pdev), ramsize, BUFFERS_ADDR +
- (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
+ pr_warn("%s: no enough on-board RAM (%u bytes detected, %u bytes required)\n",
+ pci_name(pdev), ramsize,
+ BUFFERS_ADDR +
+ (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) {
- printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap"
- " Mode\n", pci_name(pdev));
+ pr_warn("%s: unable to Set Byte Swap Mode\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -714,7 +711,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware));
if (!mem) {
- printk(KERN_ERR "wanxl: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
wanxl_pci_remove_one(pdev);
return -EFAULT;
}
@@ -733,8 +730,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
writel(0, card->plx + PLX_MAILBOX_5);
if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) {
- printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n",
- pci_name(pdev));
+ pr_warn("%s: unable to Abort and Jump\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -748,8 +744,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
}while (time_after(timeout, jiffies));
if (!stat) {
- printk(KERN_WARNING "wanXL %s: timeout while initializing card "
- "firmware\n", pci_name(pdev));
+ pr_warn("%s: timeout while initializing card firmware\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -758,13 +754,13 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
ramsize = stat;
#endif
- printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
- pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
+ pr_info("%s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
+ pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
/* Allocate IRQ */
if (request_irq(pdev->irq, wanxl_intr, IRQF_SHARED, "wanXL", card)) {
- printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n",
- pci_name(pdev), pdev->irq);
+ pr_warn("%s: could not allocate IRQ%i\n",
+ pci_name(pdev), pdev->irq);
wanxl_pci_remove_one(pdev);
return -EBUSY;
}
@@ -775,8 +771,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
port_t *port = &card->ports[i];
struct net_device *dev = alloc_hdlcdev(port);
if (!dev) {
- printk(KERN_ERR "wanXL %s: unable to allocate"
- " memory\n", pci_name(pdev));
+ pr_err("%s: unable to allocate memory\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -792,8 +788,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
port->node = i;
get_status(port)->clocking = CLOCK_EXT;
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "wanXL %s: unable to register hdlc"
- " device\n", pci_name(pdev));
+ pr_err("%s: unable to register hdlc device\n",
+ pci_name(pdev));
free_netdev(dev);
wanxl_pci_remove_one(pdev);
return -ENOBUFS;
@@ -801,11 +797,11 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card->n_ports++;
}
- printk(KERN_INFO "wanXL %s: port", pci_name(pdev));
+ pr_info("%s: port", pci_name(pdev));
for (i = 0; i < ports; i++)
- printk("%s #%i: %s", i ? "," : "", i,
- card->ports[i].dev->name);
- printk("\n");
+ pr_cont("%s #%i: %s",
+ i ? "," : "", i, card->ports[i].dev->name);
+ pr_cont("\n");
for (i = 0; i < ports; i++)
wanxl_cable_intr(&card->ports[i]); /* get carrier status etc.*/
@@ -835,7 +831,7 @@ static struct pci_driver wanxl_pci_driver = {
static int __init wanxl_init_module(void)
{
#ifdef MODULE
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
#endif
return pci_register_driver(&wanxl_pci_driver);
}
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 24297b2..8a10bb7 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -14,6 +14,8 @@
* 2000-10-29 Henner Eisen lapb_data_indication() return status.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <asm/system.h>
@@ -96,7 +98,7 @@ static struct x25_asy *x25_asy_alloc(void)
x25_asy_devs[i] = dev;
return sl;
} else {
- printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
+ pr_warn("%s(): register_netdev() failure\n", __func__);
free_netdev(dev);
}
}
@@ -114,8 +116,7 @@ static void x25_asy_free(struct x25_asy *sl)
sl->xbuff = NULL;
if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
- printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
- sl->dev->name);
+ netdev_err(sl->dev, "x25_asy_free for already free unit\n");
}
static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
@@ -128,8 +129,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL) {
- printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
- dev->name);
+ netdev_warn(dev, "unable to grow X.25 buffers, MTU change cancelled\n");
kfree(xbuff);
kfree(rbuff);
return -ENOMEM;
@@ -198,8 +198,7 @@ static void x25_asy_bump(struct x25_asy *sl)
skb = dev_alloc_skb(count+1);
if (skb == NULL) {
- printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
- sl->dev->name);
+ netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
dev->stats.rx_dropped++;
return;
}
@@ -287,9 +286,9 @@ static void x25_asy_timeout(struct net_device *dev)
/* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
- (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
- "bad line quality" : "driver error");
+ netdev_warn(dev, "transmit timed out, %s?\n",
+ (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
sl->xleft = 0;
clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
x25_asy_unlock(sl);
@@ -306,8 +305,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
int err;
if (!netif_running(sl->dev)) {
- printk(KERN_ERR "%s: xmit call when iface is down\n",
- dev->name);
+ netdev_err(dev, "xmit call when iface is down\n");
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -318,13 +316,15 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
case X25_IFACE_CONNECT: /* Connection request .. do nothing */
err = lapb_connect_request(dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+ netdev_err(dev, "lapb_connect_request error: %d\n",
+ err);
kfree_skb(skb);
return NETDEV_TX_OK;
case X25_IFACE_DISCONNECT: /* do nothing - hang up ?? */
err = lapb_disconnect_request(dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+ netdev_err(dev, "lapb_disconnect_request error: %d\n",
+ err);
default:
kfree_skb(skb);
return NETDEV_TX_OK;
@@ -343,7 +343,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
err = lapb_data_request(dev, skb);
if (err != LAPB_OK) {
- printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
+ netdev_err(dev, "lapb_data_request error: %d\n", err);
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -378,7 +378,7 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
spin_lock(&sl->lock);
if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
spin_unlock(&sl->lock);
- printk(KERN_ERR "x25_asy: tbusy drop\n");
+ netdev_err(dev, "tbusy drop\n");
kfree_skb(skb);
return;
}
@@ -404,7 +404,7 @@ static void x25_asy_connected(struct net_device *dev, int reason)
skb = dev_alloc_skb(1);
if (skb == NULL) {
- printk(KERN_ERR "x25_asy: out of memory\n");
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -423,7 +423,7 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
skb = dev_alloc_skb(1);
if (skb == NULL) {
- printk(KERN_ERR "x25_asy: out of memory\n");
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -434,14 +434,13 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
netif_rx(skb);
}
-static struct lapb_register_struct x25_asy_callbacks = {
+static const struct lapb_register_struct x25_asy_callbacks = {
.connect_confirmation = x25_asy_connected,
.connect_indication = x25_asy_connected,
.disconnect_confirmation = x25_asy_disconnected,
.disconnect_indication = x25_asy_disconnected,
.data_indication = x25_asy_data_indication,
.data_transmit = x25_asy_data_transmit,
-
};
@@ -603,8 +602,8 @@ static void x25_asy_close_tty(struct tty_struct *tty)
err = lapb_unregister(sl->dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
- err);
+ pr_err("x25_asy_close: lapb_unregister error: %d\n",
+ err);
tty->disc_data = NULL;
sl->tty = NULL;
@@ -782,14 +781,13 @@ static int __init init_x25_asy(void)
if (x25_asy_maxdev < 4)
x25_asy_maxdev = 4; /* Sanity */
- printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
- "(dynamic channels, max=%d).\n", x25_asy_maxdev);
+ pr_info("X.25 async: version 0.00 ALPHA (dynamic channels, max=%d)\n",
+ x25_asy_maxdev);
x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
GFP_KERNEL);
if (!x25_asy_devs) {
- printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
- "array! Uaargh! (-> No X.25 available)\n");
+ pr_warn("Can't allocate x25_asy_ctrls[] array! Uaargh! (-> No X.25 available)\n");
return -ENOMEM;
}
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 0806232..0e57690 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -36,6 +36,8 @@
* Synchronous mode without DMA is unlikely to pass about 2400 baud.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -365,7 +367,7 @@ static void z8530_rx(struct z8530_channel *c)
c->count=0;
if(stat&Rx_OVR)
{
- printk(KERN_WARNING "%s: overrun\n", c->dev->name);
+ pr_warn("%s: overrun\n", c->dev->name);
c->rx_overrun++;
}
if(stat&CRC_ERR)
@@ -464,12 +466,12 @@ static void z8530_status(struct z8530_channel *chan)
if (altered & chan->dcdcheck)
{
if (status & chan->dcdcheck) {
- printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+ pr_info("%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
if (chan->netdevice)
netif_carrier_on(chan->netdevice);
} else {
- printk(KERN_INFO "%s: DCD lost\n", chan->dev->name);
+ pr_info("%s: DCD lost\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
z8530_flush_fifo(chan);
if (chan->netdevice)
@@ -538,12 +540,12 @@ static void z8530_dma_tx(struct z8530_channel *chan)
{
if(!chan->dma_tx)
{
- printk(KERN_WARNING "Hey who turned the DMA off?\n");
+ pr_warn("Hey who turned the DMA off?\n");
z8530_tx(chan);
return;
}
/* This shouldn't occur in DMA mode */
- printk(KERN_ERR "DMA tx - bogus event!\n");
+ pr_err("DMA tx - bogus event!\n");
z8530_tx(chan);
}
@@ -585,12 +587,12 @@ static void z8530_dma_status(struct z8530_channel *chan)
if (altered & chan->dcdcheck)
{
if (status & chan->dcdcheck) {
- printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+ pr_info("%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
if (chan->netdevice)
netif_carrier_on(chan->netdevice);
} else {
- printk(KERN_INFO "%s:DCD lost\n", chan->dev->name);
+ pr_info("%s: DCD lost\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
z8530_flush_fifo(chan);
if (chan->netdevice)
@@ -712,7 +714,7 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
if(locker)
{
- printk(KERN_ERR "IRQ re-enter\n");
+ pr_err("IRQ re-enter\n");
return IRQ_NONE;
}
locker=1;
@@ -758,7 +760,8 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
}
spin_unlock(&dev->lock);
if(work==5000)
- printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);
+ pr_err("%s: interrupt jammed - abort(0x%X)!\n",
+ dev->name, intr);
/* Ok all done */
locker=0;
return IRQ_HANDLED;
@@ -1225,7 +1228,7 @@ static const char *z8530_type_name[]={
void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
{
- printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
+ pr_info("%s: %s found at %s 0x%lX, IRQ %d\n",
dev->name,
z8530_type_name[dev->type],
mapping,
@@ -1621,8 +1624,7 @@ static void z8530_rx_done(struct z8530_channel *c)
else
/* Can't occur as we dont reenable the DMA irq until
after the flip is done */
- printk(KERN_WARNING "%s: DMA flip overrun!\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "DMA flip overrun!\n");
release_dma_lock(flags);
@@ -1637,8 +1639,7 @@ static void z8530_rx_done(struct z8530_channel *c)
skb = dev_alloc_skb(ct);
if (skb == NULL) {
c->netdevice->stats.rx_dropped++;
- printk(KERN_WARNING "%s: Memory squeeze.\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "Memory squeeze\n");
} else {
skb_put(skb, ct);
skb_copy_to_linear_data(skb, rxb, ct);
@@ -1678,8 +1679,7 @@ static void z8530_rx_done(struct z8530_channel *c)
c->skb2 = dev_alloc_skb(c->mtu);
if (c->skb2 == NULL)
- printk(KERN_WARNING "%s: memory squeeze.\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "memory squeeze\n");
else
skb_put(c->skb2, c->mtu);
c->netdevice->stats.rx_packets++;
@@ -1693,7 +1693,7 @@ static void z8530_rx_done(struct z8530_channel *c)
c->rx_function(c, skb);
} else {
c->netdevice->stats.rx_dropped++;
- printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name);
+ netdev_err(c->netdevice, "Lost a frame\n");
}
}
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c
index 727d728..2fea02b 100644
--- a/drivers/net/wimax/i2400m/control.c
+++ b/drivers/net/wimax/i2400m/control.c
@@ -78,6 +78,8 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/wimax/i2400m.h>
+#include <linux/export.h>
+#include <linux/moduleparam.h>
#define D_SUBMODULE control
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index 9c70b5f..129ba36 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -26,6 +26,7 @@
#include <linux/etherdevice.h>
#include <linux/spinlock.h>
#include <linux/device.h>
+#include <linux/export.h>
#include "i2400m.h"
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index 85dadd5..7cbd7d2 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -158,6 +158,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/usb.h>
+#include <linux/export.h>
#include "i2400m.h"
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 5eacc65..c421a61 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -155,7 +155,7 @@
#include <linux/netdevice.h>
#include <linux/completion.h>
#include <linux/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <net/wimax.h>
#include <linux/wimax/i2400m.h>
#include <asm/byteorder.h>
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
index 0a99863..4697cf3 100644
--- a/drivers/net/wimax/i2400m/netdev.c
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -76,6 +76,7 @@
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
+#include <linux/export.h>
#include "i2400m.h"
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c
index 2f94a87..37becfc 100644
--- a/drivers/net/wimax/i2400m/rx.c
+++ b/drivers/net/wimax/i2400m/rx.c
@@ -149,6 +149,8 @@
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/workqueue.h>
+#include <linux/export.h>
+#include <linux/moduleparam.h>
#include "i2400m.h"
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index be428ca..21a9edd 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -55,6 +55,7 @@
#include <linux/mmc/sdio_func.h>
#include "i2400m-sdio.h"
#include <linux/wimax/i2400m.h>
+#include <linux/module.h>
#define D_SUBMODULE main
#include "sdio-debug-levels.h"
diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c
index 4b30ed1..4b9ecb2 100644
--- a/drivers/net/wimax/i2400m/tx.c
+++ b/drivers/net/wimax/i2400m/tx.c
@@ -245,6 +245,7 @@
*/
#include <linux/netdevice.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "i2400m.h"
diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c
index e325768..b78ee67 100644
--- a/drivers/net/wimax/i2400m/usb-rx.c
+++ b/drivers/net/wimax/i2400m/usb-rx.c
@@ -277,7 +277,7 @@ retry:
d_printf(1, dev, "RX: size changed to %d, received %d, "
"copied %d, capacity %ld\n",
rx_size, read_size, rx_skb->len,
- (long) (skb_end_pointer(new_skb) - new_skb->head));
+ (long) skb_end_offset(new_skb));
goto retry;
}
/* In most cases, it happens due to the hardware scheduling a
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 0ddc8db..6bb7f3c 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -67,6 +67,7 @@
#include <linux/wimax/i2400m.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <linux/module.h>
#define D_SUBMODULE usb
@@ -602,7 +603,7 @@ void i2400mu_disconnect(struct usb_interface *iface)
*
* As well, the device might refuse going to sleep for whichever
* reason. In this case we just fail. For system suspend/hibernate,
- * we *can't* fail. We check PM_EVENT_AUTO to see if the
+ * we *can't* fail. We check PMSG_IS_AUTO to see if the
* suspend call comes from the USB stack or from the system and act
* in consequence.
*
@@ -618,7 +619,7 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
struct i2400m *i2400m = &i2400mu->i2400m;
#ifdef CONFIG_PM
- if (pm_msg.event & PM_EVENT_AUTO)
+ if (PMSG_IS_AUTO(pm_msg))
is_autosuspend = 1;
#endif
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index ea99827..e5be7e70 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -24,7 +24,6 @@
#include "debug.h"
#include "base.h"
#include "reg.h"
-#include "debug.h"
/* return bus cachesize in 4B word units */
static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
@@ -35,8 +34,8 @@ static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
static bool
ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
- struct ath5k_softc *sc = common->priv;
- struct platform_device *pdev = to_platform_device(sc->dev);
+ struct ath5k_hw *ah = common->priv;
+ struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
u16 *eeprom, *eeprom_end;
@@ -56,8 +55,7 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
int ath5k_hw_read_srev(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
- struct platform_device *pdev = to_platform_device(sc->dev);
+ struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
ah->ah_mac_srev = bcfg->devid;
return 0;
@@ -65,12 +63,11 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
{
- struct ath5k_softc *sc = ah->ah_sc;
- struct platform_device *pdev = to_platform_device(sc->dev);
+ struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
u8 *cfg_mac;
- if (to_platform_device(sc->dev)->id == 0)
+ if (to_platform_device(ah->dev)->id == 0)
cfg_mac = bcfg->config->wlan0_mac;
else
cfg_mac = bcfg->config->wlan1_mac;
@@ -90,7 +87,7 @@ static const struct ath_bus_ops ath_ahb_bus_ops = {
static int ath_ahb_probe(struct platform_device *pdev)
{
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
- struct ath5k_softc *sc;
+ struct ath5k_hw *ah;
struct ieee80211_hw *hw;
struct resource *res;
void __iomem *mem;
@@ -127,19 +124,19 @@ static int ath_ahb_probe(struct platform_device *pdev)
irq = res->start;
- hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
if (hw == NULL) {
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
ret = -ENOMEM;
goto err_out;
}
- sc = hw->priv;
- sc->hw = hw;
- sc->dev = &pdev->dev;
- sc->iobase = mem;
- sc->irq = irq;
- sc->devid = bcfg->devid;
+ ah = hw->priv;
+ ah->hw = hw;
+ ah->dev = &pdev->dev;
+ ah->iobase = mem;
+ ah->irq = irq;
+ ah->devid = bcfg->devid;
if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
/* Enable WMAC AHB arbitration */
@@ -155,7 +152,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
/* Enable WMAC DMA access (assuming 5312 or 231x*/
/* TODO: check other platforms */
reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
- if (to_platform_device(sc->dev)->id == 0)
+ if (to_platform_device(ah->dev)->id == 0)
reg |= AR5K_AR5312_ENABLE_WLAN0;
else
reg |= AR5K_AR5312_ENABLE_WLAN1;
@@ -166,13 +163,13 @@ static int ath_ahb_probe(struct platform_device *pdev)
* used as pass-through. Disable 2 GHz support in the
* driver for it
*/
- if (to_platform_device(sc->dev)->id == 0 &&
- (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
- (BD_WLAN1|BD_WLAN0))
- __set_bit(ATH_STAT_2G_DISABLED, sc->status);
+ if (to_platform_device(ah->dev)->id == 0 &&
+ (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
+ (BD_WLAN1 | BD_WLAN0))
+ __set_bit(ATH_STAT_2G_DISABLED, ah->status);
}
- ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
+ ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
if (ret != 0) {
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
ret = -ENODEV;
@@ -194,13 +191,13 @@ static int ath_ahb_remove(struct platform_device *pdev)
{
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
- struct ath5k_softc *sc;
+ struct ath5k_hw *ah;
u32 reg;
if (!hw)
return 0;
- sc = hw->priv;
+ ah = hw->priv;
if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
/* Disable WMAC AHB arbitration */
@@ -210,15 +207,16 @@ static int ath_ahb_remove(struct platform_device *pdev)
} else {
/*Stop DMA access */
reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
- if (to_platform_device(sc->dev)->id == 0)
+ if (to_platform_device(ah->dev)->id == 0)
reg &= ~AR5K_AR5312_ENABLE_WLAN0;
else
reg &= ~AR5K_AR5312_ENABLE_WLAN1;
__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
}
- ath5k_deinit_softc(sc);
+ ath5k_deinit_ah(ah);
platform_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(hw);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index f915f40..bea90e6 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -15,7 +15,6 @@
*/
#include "ath5k.h"
-#include "base.h"
#include "reg.h"
#include "debug.h"
#include "ani.h"
@@ -74,7 +73,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
static const s8 fr[] = { -78, -80 };
#endif
if (level < 0 || level >= ARRAY_SIZE(sz)) {
- ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
+ ATH5K_ERR(ah, "noise immunity level %d out of range",
level);
return;
}
@@ -88,8 +87,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG,
AR5K_PHY_SIG_FIRPWR, fr[level]);
- ah->ah_sc->ani_state.noise_imm_level = level;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+ ah->ani_state.noise_imm_level = level;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
}
@@ -105,8 +104,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
if (level < 0 || level >= ARRAY_SIZE(val) ||
- level > ah->ah_sc->ani_state.max_spur_level) {
- ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range",
+ level > ah->ani_state.max_spur_level) {
+ ATH5K_ERR(ah, "spur immunity level %d out of range",
level);
return;
}
@@ -114,8 +113,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]);
- ah->ah_sc->ani_state.spur_level = level;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+ ah->ani_state.spur_level = level;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
}
@@ -130,15 +129,15 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
static const int val[] = { 0, 4, 8 };
if (level < 0 || level >= ARRAY_SIZE(val)) {
- ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
+ ATH5K_ERR(ah, "firstep level %d out of range", level);
return;
}
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG,
AR5K_PHY_SIG_FIRSTEP, val[level]);
- ah->ah_sc->ani_state.firstep_level = level;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+ ah->ani_state.firstep_level = level;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
}
@@ -178,8 +177,8 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR,
AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN);
- ah->ah_sc->ani_state.ofdm_weak_sig = on;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s",
+ ah->ani_state.ofdm_weak_sig = on;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s",
on ? "on" : "off");
}
@@ -195,8 +194,8 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on)
static const int val[] = { 8, 6 };
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR,
AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]);
- ah->ah_sc->ani_state.cck_weak_sig = on;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s",
+ ah->ani_state.cck_weak_sig = on;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s",
on ? "on" : "off");
}
@@ -218,7 +217,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
{
int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)",
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "raise immunity (%s)",
ofdm_trigger ? "ODFM" : "CCK");
/* first: raise noise immunity */
@@ -229,13 +228,13 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
/* only OFDM: raise spur immunity level */
if (ofdm_trigger &&
- as->spur_level < ah->ah_sc->ani_state.max_spur_level) {
+ as->spur_level < ah->ani_state.max_spur_level) {
ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1);
return;
}
/* AP mode */
- if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) {
+ if (ah->opmode == NL80211_IFTYPE_AP) {
if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL)
ath5k_ani_set_firstep_level(ah, as->firstep_level + 1);
return;
@@ -248,7 +247,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
* don't shut out a remote node by raising immunity too high. */
if (rssi > ATH5K_ANI_RSSI_THR_HIGH) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"beacon RSSI high");
/* only OFDM: beacon RSSI is high, we can disable ODFM weak
* signal detection */
@@ -265,7 +264,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
} else if (rssi > ATH5K_ANI_RSSI_THR_LOW) {
/* beacon RSSI in mid range, we need OFDM weak signal detect,
* but can raise firstep level */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"beacon RSSI mid");
if (ofdm_trigger && as->ofdm_weak_sig == false)
ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
@@ -275,7 +274,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
} else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) {
/* beacon RSSI is low. in B/G mode turn of OFDM weak signal
* detect and zero firstep level to maximize CCK sensitivity */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"beacon RSSI low, 2GHz");
if (ofdm_trigger && as->ofdm_weak_sig == true)
ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
@@ -303,9 +302,9 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
{
int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity");
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "lower immunity");
- if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) {
+ if (ah->opmode == NL80211_IFTYPE_AP) {
/* AP mode */
if (as->firstep_level > 0) {
ath5k_ani_set_firstep_level(ah, as->firstep_level - 1);
@@ -464,7 +463,7 @@ ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as)
void
ath5k_ani_calibration(struct ath5k_hw *ah)
{
- struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+ struct ath5k_ani_state *as = &ah->ani_state;
int listen, ofdm_high, ofdm_low, cck_high, cck_low;
/* get listen time since last call and add it to the counter because we
@@ -483,9 +482,9 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000;
cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"listen %d (now %d)", as->listen_time, listen);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"check high ofdm %d/%d cck %d/%d",
as->ofdm_errors, ofdm_high, as->cck_errors, cck_high);
@@ -498,7 +497,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
} else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) {
/* If more than 5 (TODO: why 5?) periods have passed and we got
* relatively little errors we can try to lower immunity */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"check low ofdm %d/%d cck %d/%d",
as->ofdm_errors, ofdm_low, as->cck_errors, cck_low);
@@ -525,7 +524,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
void
ath5k_ani_mib_intr(struct ath5k_hw *ah)
{
- struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+ struct ath5k_ani_state *as = &ah->ani_state;
/* nothing to do here if HW does not have PHY error counters - they
* can't be the reason for the MIB interrupt then */
@@ -536,7 +535,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT);
ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);
- if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
+ if (ah->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
return;
/* If one of the errors triggered, we can get a superfluous second
@@ -547,7 +546,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH ||
as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
}
@@ -561,16 +560,16 @@ void
ath5k_ani_phy_error_report(struct ath5k_hw *ah,
enum ath5k_phy_error_code phyerr)
{
- struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+ struct ath5k_ani_state *as = &ah->ani_state;
if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) {
as->ofdm_errors++;
if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH)
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
} else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) {
as->cck_errors++;
if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
}
}
@@ -630,20 +629,25 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
if (ah->ah_version < AR5K_AR5212)
return;
+ if (mode < ATH5K_ANI_MODE_OFF || mode > ATH5K_ANI_MODE_AUTO) {
+ ATH5K_ERR(ah, "ANI mode %d out of range", mode);
+ return;
+ }
+
/* clear old state information */
- memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state));
+ memset(&ah->ani_state, 0, sizeof(ah->ani_state));
/* older hardware has more spur levels than newer */
if (ah->ah_mac_srev < AR5K_SREV_AR2414)
- ah->ah_sc->ani_state.max_spur_level = 7;
+ ah->ani_state.max_spur_level = 7;
else
- ah->ah_sc->ani_state.max_spur_level = 2;
+ ah->ani_state.max_spur_level = 2;
/* initial values for our ani parameters */
if (mode == ATH5K_ANI_MODE_OFF) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n");
- } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI off\n");
+ } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) {
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"ANI manual low -> high sensitivity\n");
ath5k_ani_set_noise_immunity_level(ah, 0);
ath5k_ani_set_spur_immunity_level(ah, 0);
@@ -651,17 +655,17 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
ath5k_ani_set_cck_weak_signal_detection(ah, true);
} else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"ANI manual high -> low sensitivity\n");
ath5k_ani_set_noise_immunity_level(ah,
ATH5K_ANI_MAX_NOISE_IMM_LVL);
ath5k_ani_set_spur_immunity_level(ah,
- ah->ah_sc->ani_state.max_spur_level);
+ ah->ani_state.max_spur_level);
ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
ath5k_ani_set_cck_weak_signal_detection(ah, false);
} else if (mode == ATH5K_ANI_MODE_AUTO) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n");
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI auto\n");
ath5k_ani_set_noise_immunity_level(ah, 0);
ath5k_ani_set_spur_immunity_level(ah, 0);
ath5k_ani_set_firstep_level(ah, 0);
@@ -687,7 +691,7 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
~AR5K_RX_FILTER_PHYERR);
}
- ah->ah_sc->ani_state.ani_mode = mode;
+ ah->ani_state.ani_mode = mode;
}
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h
index 0340153..7358b6c 100644
--- a/drivers/net/wireless/ath/ath5k/ani.h
+++ b/drivers/net/wireless/ath/ath5k/ani.h
@@ -16,6 +16,10 @@
#ifndef ANI_H
#define ANI_H
+#include "../ath.h"
+
+enum ath5k_phy_error_code;
+
/* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */
#define ATH5K_ANI_LISTEN_PERIOD 100
#define ATH5K_ANI_OFDM_TRIG_HIGH 500
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index bb50700..fecbcd9 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -18,14 +18,16 @@
#ifndef _ATH5K_H
#define _ATH5K_H
-/* TODO: Clean up channel debuging -doesn't work anyway- and start
+/* TODO: Clean up channel debugging (doesn't work anyway) and start
* working on reg. control code using all available eeprom information
- * -rev. engineering needed- */
+ * (rev. engineering needed) */
#define CHAN_DEBUG 0
#include <linux/io.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/average.h>
+#include <linux/leds.h>
#include <net/mac80211.h>
/* RX/TX descriptor hw structs
@@ -36,43 +38,46 @@
* TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
* and clean up common bits, then introduce set/get functions in eeprom.c */
#include "eeprom.h"
+#include "debug.h"
#include "../ath.h"
+#include "ani.h"
/* PCI IDs */
-#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
-#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
-#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
-#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
-#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
-#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
-#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
-#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
-#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
-#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
/****************************\
GENERIC DRIVER DEFINITIONS
\****************************/
-#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__)
+#define ATH5K_PRINTF(fmt, ...) \
+ printk(KERN_WARNING "%s: " fmt, __func__, ##__VA_ARGS__)
#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
printk(_level "ath5k %s: " _fmt, \
@@ -126,13 +131,6 @@
#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
-/* Access to PHY registers */
-#define AR5K_PHY_READ(ah, _reg) \
- ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
-
-#define AR5K_PHY_WRITE(ah, _reg, _val) \
- ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
-
/* Access QCU registers per queue */
#define AR5K_REG_READ_Q(ah, _reg, _queue) \
(ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
@@ -155,13 +153,12 @@
} while (0)
/*
- * Some tuneable values (these should be changeable by the user)
+ * Some tunable values (these should be changeable by the user)
* TODO: Make use of them and add more options OR use debug/configfs
*/
#define AR5K_TUNE_DMA_BEACON_RESP 2
#define AR5K_TUNE_SW_BEACON_RESP 10
#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
-#define AR5K_TUNE_RADAR_ALERT false
#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1)
#define AR5K_TUNE_REGISTER_TIMEOUT 20000
@@ -170,8 +167,8 @@
#define AR5K_TUNE_RSSI_THRES 129
/* This must be set when setting the RSSI threshold otherwise it can
* prevent a reset. If AR5K_RSSI_THR is read after writing to it
- * the BMISS_THRES will be seen as 0, seems harware doesn't keep
- * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * the BMISS_THRES will be seen as 0, seems hardware doesn't keep
+ * track of it. Max value depends on hardware. For AR5210 this is just 7.
* For AR5211+ this seems to be up to 255. */
#define AR5K_TUNE_BMISS_THRES 7
#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
@@ -290,17 +287,6 @@ enum ath5k_radio {
* Common silicon revision/version values
*/
-enum ath5k_srev_type {
- AR5K_VERSION_MAC,
- AR5K_VERSION_RAD,
-};
-
-struct ath5k_srev_name {
- const char *sr_name;
- enum ath5k_srev_type sr_type;
- u_int sr_val;
-};
-
#define AR5K_SREV_UNKNOWN 0xffff
#define AR5K_SREV_AR5210 0x00 /* Crete */
@@ -361,7 +347,7 @@ struct ath5k_srev_name {
/*
* Some of this information is based on Documentation from:
*
- * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG
+ * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG
*
* Modulation for Atheros' eXtended Range - range enhancing extension that is
* supposed to double the distance an Atheros client device can keep a
@@ -374,12 +360,12 @@ struct ath5k_srev_name {
* they are exclusive.
*
*/
-#define MODULATION_XR 0x00000200
+#define MODULATION_XR 0x00000200
/*
* Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
* throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
* signaling rate achieved through the bonding of two 54Mbit/s 802.11g
- * channels. To use this feature your Access Point must also suport it.
+ * channels. To use this feature your Access Point must also support it.
* There is also a distinction between "static" and "dynamic" turbo modes:
*
* - Static: is the dumb version: devices set to this mode stick to it until
@@ -419,7 +405,6 @@ enum ath5k_driver_mode {
AR5K_MODE_11A = 0,
AR5K_MODE_11B = 1,
AR5K_MODE_11G = 2,
- AR5K_MODE_XR = 0,
AR5K_MODE_MAX = 3
};
@@ -495,9 +480,9 @@ enum ath5k_tx_queue {
*/
enum ath5k_tx_queue_subtype {
AR5K_WME_AC_BK = 0, /*Background traffic*/
- AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
- AR5K_WME_AC_VI, /*Video traffic*/
- AR5K_WME_AC_VO, /*Voice traffic*/
+ AR5K_WME_AC_BE, /*Best-effort (normal) traffic*/
+ AR5K_WME_AC_VI, /*Video traffic*/
+ AR5K_WME_AC_VO, /*Voice traffic*/
};
/*
@@ -537,6 +522,27 @@ enum ath5k_tx_queue_id {
#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
/*
+ * Data transmit queue state. One of these exists for each
+ * hardware transmit queue. Packets sent to us from above
+ * are assigned to queues based on their priority. Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+ unsigned int qnum; /* hardware q number */
+ u32 *link; /* link ptr in last TX desc */
+ struct list_head q; /* transmit queue */
+ spinlock_t lock; /* lock on q and link */
+ bool setup;
+ int txq_len; /* number of queued buffers */
+ int txq_max; /* max allowed num of queued buffers */
+ bool txq_poll_mark;
+ unsigned int txq_stuck; /* informational counter */
+};
+
+/*
* A struct to hold tx queue's parameters
*/
struct ath5k_txq_info {
@@ -616,8 +622,8 @@ struct ath5k_rx_status {
#define AR5K_RXERR_FIFO 0x04
#define AR5K_RXERR_DECRYPT 0x08
#define AR5K_RXERR_MIC 0x10
-#define AR5K_RXKEYIX_INVALID ((u8) - 1)
-#define AR5K_TXKEYIX_INVALID ((u32) - 1)
+#define AR5K_RXKEYIX_INVALID ((u8) -1)
+#define AR5K_TXKEYIX_INVALID ((u32) -1)
/**************************\
@@ -668,32 +674,6 @@ struct ath5k_gain {
#define AR5K_SLOT_TIME_20 880
#define AR5K_SLOT_TIME_MAX 0xffff
-/* channel_flags */
-#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
-#define CHANNEL_CCK 0x0020 /* CCK channel */
-#define CHANNEL_OFDM 0x0040 /* OFDM channel */
-#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
-#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
-#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
-#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
-#define CHANNEL_XR 0x0800 /* XR channel */
-
-#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
-#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
-#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
-#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
-
-#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ)
-
-#define CHANNEL_MODES CHANNEL_ALL
-
-/*
- * Used internaly for reset_tx_queue).
- * Also see struct struct ieee80211_channel.
- */
-#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0)
-#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0)
-
/*
* The following structure is used to map 2GHz channels to
* 5GHz Atheros channels.
@@ -710,7 +690,7 @@ struct ath5k_athchan_2ghz {
\******************/
/**
- * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
+ * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32.
*
* The rate code is used to get the RX rate or set the TX rate on the
* hardware descriptors. It is also used for internal modulation control
@@ -767,6 +747,7 @@ struct ath5k_athchan_2ghz {
*/
#define AR5K_KEYCACHE_SIZE 8
+extern int ath5k_modparam_nohwcrypt;
/***********************\
HW RELATED DEFINITIONS
@@ -775,11 +756,11 @@ struct ath5k_athchan_2ghz {
/*
* Misc definitions
*/
-#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
+#define AR5K_RSSI_EP_MULTIPLIER (1 << 7)
#define AR5K_ASSERT_ENTRY(_e, _s) do { \
if (_e >= _s) \
- return (false); \
+ return false; \
} while (0)
/*
@@ -790,52 +771,52 @@ struct ath5k_athchan_2ghz {
* enum ath5k_int - Hardware interrupt masks helpers
*
* @AR5K_INT_RX: mask to identify received frame interrupts, of type
- * AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ * AR5K_ISR_RXOK or AR5K_ISR_RXERR
* @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
* @AR5K_INT_RXNOFRM: No frame received (?)
* @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
- * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
- * LinkPtr is NULL. For more details, refer to:
- * http://www.freepatentsonline.com/20030225739.html
+ * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ * LinkPtr is NULL. For more details, refer to:
+ * http://www.freepatentsonline.com/20030225739.html
* @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
- * Note that Rx overrun is not always fatal, on some chips we can continue
- * operation without reseting the card, that's why int_fatal is not
- * common for all chips.
+ * Note that Rx overrun is not always fatal, on some chips we can continue
+ * operation without resetting the card, that's why int_fatal is not
+ * common for all chips.
* @AR5K_INT_TX: mask to identify received frame interrupts, of type
- * AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ * AR5K_ISR_TXOK or AR5K_ISR_TXERR
* @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
* @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
- * We currently do increments on interrupt by
- * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ * We currently do increments on interrupt by
+ * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
* @AR5K_INT_MIB: Indicates the either Management Information Base counters or
* one of the PHY error counters reached the maximum value and should be
* read and cleared.
* @AR5K_INT_RXPHY: RX PHY Error
* @AR5K_INT_RXKCM: RX Key cache miss
* @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
- * beacon that must be handled in software. The alternative is if you
- * have VEOL support, in that case you let the hardware deal with things.
+ * beacon that must be handled in software. The alternative is if you
+ * have VEOL support, in that case you let the hardware deal with things.
* @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
- * beacons from the AP have associated with, we should probably try to
- * reassociate. When in IBSS mode this might mean we have not received
- * any beacons from any local stations. Note that every station in an
- * IBSS schedules to send beacons at the Target Beacon Transmission Time
- * (TBTT) with a random backoff.
+ * beacons from the AP have associated with, we should probably try to
+ * reassociate. When in IBSS mode this might mean we have not received
+ * any beacons from any local stations. Note that every station in an
+ * IBSS schedules to send beacons at the Target Beacon Transmission Time
+ * (TBTT) with a random backoff.
* @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
* @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
- * until properly handled
+ * until properly handled
* @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
- * errors. These types of errors we can enable seem to be of type
- * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ * errors. These types of errors we can enable seem to be of type
+ * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
* @AR5K_INT_GLOBAL: Used to clear and set the IER
* @AR5K_INT_NOCARD: signals the card has been removed
- * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
- * bit value
+ * @AR5K_INT_COMMON: common interrupts shared among MACs with the same
+ * bit value
*
* These are mapped to take advantage of some common bits
* between the MACs, to be able to set intr properties
* easier. Some of them are not used yet inside hw.c. Most map
- * to the respective hw interrupt value as they are common amogst different
+ * to the respective hw interrupt value as they are common among different
* MACs.
*/
enum ath5k_int {
@@ -944,41 +925,12 @@ enum ath5k_power_mode {
#define AR5K_SOFTLED_ON 0
#define AR5K_SOFTLED_OFF 1
-/*
- * Chipset capabilities -see ath5k_hw_get_capability-
- * get_capability function is not yet fully implemented
- * in ath5k so most of these don't work yet...
- * TODO: Implement these & merge with _TUNE_ stuff above
- */
-enum ath5k_capability_type {
- AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
- AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
- AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
- AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
- AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
- AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
- AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
- AR5K_CAP_COMPRESSION = 8, /* Supports compression */
- AR5K_CAP_BURST = 9, /* Supports packet bursting */
- AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
- AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
- AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
- AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
- AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
- AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
- AR5K_CAP_XR = 16, /* Supports XR mode */
- AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
- AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
- AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
- AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
-};
-
/* XXX: we *may* move cap_range stuff to struct wiphy */
struct ath5k_capabilities {
/*
* Supported PHY modes
- * (ie. CHANNEL_A, CHANNEL_B, ...)
+ * (ie. AR5K_MODE_11A, AR5K_MODE_11B, ...)
*/
DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
@@ -1009,25 +961,71 @@ struct ath5k_capabilities {
/* size of noise floor history (keep it a power of two) */
#define ATH5K_NF_CAL_HIST_MAX 8
-struct ath5k_nfcal_hist
-{
+struct ath5k_nfcal_hist {
s16 index; /* current index into nfval */
s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
};
-/**
- * struct avg_val - Helper structure for average calculation
- * @avg: contains the actual average value
- * @avg_weight: is used internally during calculation to prevent rounding errors
+#define ATH5K_LED_MAX_NAME_LEN 31
+
+/*
+ * State for LED triggers
*/
-struct ath5k_avg_val {
- int avg;
- int avg_weight;
+struct ath5k_led {
+ char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */
+ struct ath5k_hw *ah; /* driver state */
+ struct led_classdev led_dev; /* led classdev */
};
-/***************************************\
- HARDWARE ABSTRACTION LAYER STRUCTURE
-\***************************************/
+/* Rfkill */
+struct ath5k_rfkill {
+ /* GPIO PIN for rfkill */
+ u16 gpio;
+ /* polarity of rfkill GPIO PIN */
+ bool polarity;
+ /* RFKILL toggle tasklet */
+ struct tasklet_struct toggleq;
+};
+
+/* statistics */
+struct ath5k_statistics {
+ /* antenna use */
+ unsigned int antenna_rx[5]; /* frames count per antenna RX */
+ unsigned int antenna_tx[5]; /* frames count per antenna TX */
+
+ /* frame errors */
+ unsigned int rx_all_count; /* all RX frames, including errors */
+ unsigned int tx_all_count; /* all TX frames, including errors */
+ unsigned int rx_bytes_count; /* all RX bytes, including errored pkts
+ * and the MAC headers for each packet
+ */
+ unsigned int tx_bytes_count; /* all TX bytes, including errored pkts
+ * and the MAC headers and padding for
+ * each packet.
+ */
+ unsigned int rxerr_crc;
+ unsigned int rxerr_phy;
+ unsigned int rxerr_phy_code[32];
+ unsigned int rxerr_fifo;
+ unsigned int rxerr_decrypt;
+ unsigned int rxerr_mic;
+ unsigned int rxerr_proc;
+ unsigned int rxerr_jumbo;
+ unsigned int txerr_retry;
+ unsigned int txerr_fifo;
+ unsigned int txerr_filt;
+
+ /* MIB counters */
+ unsigned int ack_fail;
+ unsigned int rts_fail;
+ unsigned int rts_ok;
+ unsigned int fcs_error;
+ unsigned int beacons;
+
+ unsigned int mib_intr;
+ unsigned int rxorn_intr;
+ unsigned int rxeol_intr;
+};
/*
* Misc defines
@@ -1036,12 +1034,112 @@ struct ath5k_avg_val {
#define AR5K_MAX_GPIO 10
#define AR5K_MAX_RF_BANKS 8
-/* TODO: Clean up and merge with ath5k_softc */
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX (26 + 26 + 26 + 200 + 200)
+#else
+#define ATH_CHAN_MAX (14 + 14 + 14 + 252 + 20)
+#endif
+
+#define ATH_RXBUF 40 /* number of RX buffers */
+#define ATH_TXBUF 200 /* number of TX buffers */
+#define ATH_BCBUF 4 /* number of beacon buffers */
+#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
+#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
+
+/* Driver state associated with an instance of a device */
struct ath5k_hw {
struct ath_common common;
- struct ath5k_softc *ah_sc;
- void __iomem *ah_iobase;
+ struct pci_dev *pdev;
+ struct device *dev; /* for dma mapping */
+ int irq;
+ u16 devid;
+ void __iomem *iobase; /* address of the device */
+ struct mutex lock; /* dev-level lock */
+ struct ieee80211_hw *hw; /* IEEE 802.11 common */
+ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+ struct ieee80211_channel channels[ATH_CHAN_MAX];
+ struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+ s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+ enum nl80211_iftype opmode;
+
+#ifdef CONFIG_ATH5K_DEBUG
+ struct ath5k_dbg_info debug; /* debug info */
+#endif /* CONFIG_ATH5K_DEBUG */
+
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
+ struct ath5k_desc *desc; /* TX/RX descriptors */
+ dma_addr_t desc_daddr; /* DMA (physical) address */
+ size_t desc_len; /* size of TX/RX descriptors */
+
+ DECLARE_BITMAP(status, 6);
+#define ATH_STAT_INVALID 0 /* disable hardware accesses */
+#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
+#define ATH_STAT_PROMISC 2
+#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
+#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
+#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */
+
+ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
+ struct ieee80211_channel *curchan; /* current h/w channel */
+
+ u16 nvifs;
+
+ enum ath5k_int imask; /* interrupt mask copy */
+
+ spinlock_t irqlock;
+ bool rx_pending; /* rx tasklet pending */
+ bool tx_pending; /* tx tasklet pending */
+
+ u8 bssidmask[ETH_ALEN];
+
+ unsigned int led_pin, /* GPIO pin for driving LED */
+ led_on; /* pin setting for LED on */
+
+ struct work_struct reset_work; /* deferred chip reset */
+
+ struct list_head rxbuf; /* receive buffer */
+ spinlock_t rxbuflock;
+ u32 *rxlink; /* link ptr in last RX desc */
+ struct tasklet_struct rxtq; /* rx intr tasklet */
+ struct ath5k_led rx_led; /* rx led */
+
+ struct list_head txbuf; /* transmit buffer */
+ spinlock_t txbuflock;
+ unsigned int txbuf_len; /* buf count in txbuf list */
+ struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
+ struct tasklet_struct txtq; /* tx intr tasklet */
+ struct ath5k_led tx_led; /* tx led */
+
+ struct ath5k_rfkill rf_kill;
+
+ struct tasklet_struct calib; /* calibration tasklet */
+
+ spinlock_t block; /* protects beacon */
+ struct tasklet_struct beacontq; /* beacon intr tasklet */
+ struct list_head bcbuf; /* beacon buffer */
+ struct ieee80211_vif *bslot[ATH_BCBUF];
+ u16 num_ap_vifs;
+ u16 num_adhoc_vifs;
+ unsigned int bhalq, /* SW q for outgoing beacons */
+ bmisscount, /* missed beacon transmits */
+ bintval, /* beacon interval in TU */
+ bsent;
+ unsigned int nexttbtt; /* next beacon time in TU */
+ struct ath5k_txq *cabq; /* content after beacon */
+
+ int power_level; /* Requested tx power in dBm */
+ bool assoc; /* associate state */
+ bool enable_beacon; /* true if beacons are on */
+
+ struct ath5k_statistics stats;
+
+ struct ath5k_ani_state ani_state;
+ struct tasklet_struct ani_tasklet; /* ANI calibration */
+
+ struct delayed_work tx_complete_work;
+
+ struct survey_info survey; /* collected survey info */
enum ath5k_int ah_imr;
@@ -1051,10 +1149,8 @@ struct ath5k_hw {
enum ath5k_version ah_version;
enum ath5k_radio ah_radio;
- u32 ah_phy;
u32 ah_mac_srev;
u16 ah_mac_version;
- u16 ah_mac_revision;
u16 ah_phy_revision;
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
@@ -1065,6 +1161,8 @@ struct ath5k_hw {
u8 ah_retry_long;
u8 ah_retry_short;
+ u32 ah_use_32khz_clock;
+
u8 ah_coverage_class;
bool ah_ack_bitrate_high;
u8 ah_bwmode;
@@ -1120,12 +1218,6 @@ struct ath5k_hw {
bool txp_setup;
} ah_txpower;
- struct {
- bool r_enabled;
- int r_last_alert;
- struct ieee80211_channel r_last_channel;
- } ah_radar;
-
struct ath5k_nfcal_hist ah_nfcal_hist;
/* average beacon RSSI in our BSS (used by ANI) */
@@ -1168,47 +1260,24 @@ struct ath_bus_ops {
extern const struct ieee80211_ops ath5k_hw_ops;
/* Initialization and detach functions */
-int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops);
-void ath5k_deinit_softc(struct ath5k_softc *sc);
-int ath5k_hw_init(struct ath5k_softc *sc);
+int ath5k_hw_init(struct ath5k_hw *ah);
void ath5k_hw_deinit(struct ath5k_hw *ah);
-int ath5k_sysfs_register(struct ath5k_softc *sc);
-void ath5k_sysfs_unregister(struct ath5k_softc *sc);
-
-/* base.c */
-struct ath5k_buf;
-struct ath5k_txq;
-
-void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
-void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ath5k_txq *txq);
-int ath5k_init_hw(struct ath5k_softc *sc);
-int ath5k_stop_hw(struct ath5k_softc *sc);
-void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
- struct ieee80211_vif *vif);
-int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_config(struct ath5k_softc *sc);
-void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+int ath5k_sysfs_register(struct ath5k_hw *ah);
+void ath5k_sysfs_unregister(struct ath5k_hw *ah);
/*Chip id helper functions */
-const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
int ath5k_hw_read_srev(struct ath5k_hw *ah);
/* LED functions */
-int ath5k_init_leds(struct ath5k_softc *sc);
-void ath5k_led_enable(struct ath5k_softc *sc);
-void ath5k_led_off(struct ath5k_softc *sc);
-void ath5k_unregister_leds(struct ath5k_softc *sc);
+int ath5k_init_leds(struct ath5k_hw *ah);
+void ath5k_led_enable(struct ath5k_hw *ah);
+void ath5k_led_off(struct ath5k_hw *ah);
+void ath5k_unregister_leds(struct ath5k_hw *ah);
/* Reset Functions */
-int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel);
int ath5k_hw_on_hold(struct ath5k_hw *ah);
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool fast, bool skip_pcu);
@@ -1253,7 +1322,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate, bool shortpre);
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
-extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* RX filter control*/
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
@@ -1318,9 +1387,6 @@ void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
/* Misc functions TODO: Cleanup */
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
- enum ath5k_capability_type cap_type, u32 capability,
- u32 *result);
int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
@@ -1331,13 +1397,13 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
/* PHY functions */
/* Misc PHY functions */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band);
int ath5k_hw_phy_disable(struct ath5k_hw *ah);
/* Gain_F optimization */
enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
/* PHY/RF channel functions */
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
+bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel);
/* PHY calibration */
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
@@ -1356,17 +1422,17 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
u8 mode, bool fast);
/*
- * Functions used internaly
+ * Functions used internally
*/
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
{
- return &ah->common;
+ return &ah->common;
}
static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
{
- return &(ath5k_hw_common(ah)->regulatory);
+ return &(ath5k_hw_common(ah)->regulatory);
}
#ifdef CONFIG_ATHEROS_AR231X
@@ -1377,10 +1443,10 @@ static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
/* On AR2315 and AR2317 the PCI clock domain registers
* are outside of the WMAC register space */
if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
- (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
+ (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
return AR5K_AR2315_PCI_BASE + reg;
- return ah->ah_iobase + reg;
+ return ah->iobase + reg;
}
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
@@ -1397,12 +1463,12 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
- return ioread32(ah->ah_iobase + reg);
+ return ioread32(ah->iobase + reg);
}
static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
{
- iowrite32(val, ah->ah_iobase + reg);
+ iowrite32(val, ah->iobase + reg);
}
#endif
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 1588401..91627dd 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -25,7 +25,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/**
* ath5k_hw_post - Power On Self Test helper function
@@ -59,7 +58,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
cur_val = ath5k_hw_reg_read(ah, cur_reg);
if (cur_val != var_pattern) {
- ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+ ATH5K_ERR(ah, "POST Failed !!!\n");
return -EAGAIN;
}
@@ -74,7 +73,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
cur_val = ath5k_hw_reg_read(ah, cur_reg);
if (cur_val != var_pattern) {
- ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+ ATH5K_ERR(ah, "POST Failed !!!\n");
return -EAGAIN;
}
@@ -95,18 +94,18 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
/**
* ath5k_hw_init - Check if hw is supported and init the needed structs
*
- * @sc: The &struct ath5k_softc we got from the driver's init_softc function
+ * @ah: The &struct ath5k_hw associated with the device
*
* Check if the device is supported, perform a POST and initialize the needed
* structs. Returns -ENOMEM if we don't have memory for the needed structs,
* -ENODEV if the device is not supported or prints an error msg if something
* else went wrong.
*/
-int ath5k_hw_init(struct ath5k_softc *sc)
+int ath5k_hw_init(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
+ static const u8 zero_mac[ETH_ALEN] = { };
struct ath_common *common = ath5k_hw_common(ah);
- struct pci_dev *pdev = sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
struct ath5k_eeprom_info *ee;
int ret;
u32 srev;
@@ -114,7 +113,6 @@ int ath5k_hw_init(struct ath5k_softc *sc)
/*
* HW information
*/
- ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
ah->ah_imr = 0;
@@ -122,8 +120,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ah->ah_retry_long = AR5K_INIT_RETRY_LONG;
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
ah->ah_noise_floor = -95; /* until first NF calibration is run */
- sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
- ah->ah_current_channel = &sc->channels[0];
+ ah->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+ ah->ah_current_channel = &ah->channels[0];
/*
* Find the mac version
@@ -137,9 +135,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)
else
ah->ah_version = AR5K_AR5212;
- /* Get the MAC revision */
+ /* Get the MAC version */
ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
- ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
/* Fill the ath5k_hw struct with the needed functions */
ret = ath5k_hw_init_desc_functions(ah);
@@ -147,7 +144,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
goto err;
/* Bring device out of sleep and reset its units */
- ret = ath5k_hw_nic_wakeup(ah, 0, true);
+ ret = ath5k_hw_nic_wakeup(ah, NULL);
if (ret)
goto err;
@@ -155,8 +152,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
0xffffffff;
ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_5GHZ);
- ah->ah_phy = AR5K_PHY(0);
+ IEEE80211_BAND_5GHZ);
/* Try to identify radio chip based on its srev */
switch (ah->ah_radio_5ghz_revision & 0xf0) {
@@ -164,14 +160,14 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ah->ah_radio = AR5K_RF5111;
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
+ IEEE80211_BAND_2GHZ);
break;
case AR5K_SREV_RAD_5112:
case AR5K_SREV_RAD_2112:
ah->ah_radio = AR5K_RF5112;
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
+ IEEE80211_BAND_2GHZ);
break;
case AR5K_SREV_RAD_2413:
ah->ah_radio = AR5K_RF2413;
@@ -191,7 +187,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
break;
case AR5K_SREV_RAD_5424:
if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
- ah->ah_mac_version == AR5K_SREV_AR2417){
+ ah->ah_mac_version == AR5K_SREV_AR2417) {
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
} else {
@@ -208,45 +204,44 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ah->ah_radio = AR5K_RF5111;
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
+ IEEE80211_BAND_2GHZ);
} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
- ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
- ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
+ ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
} else if (srev == AR5K_SREV_AR5213A &&
- ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
ah->ah_radio = AR5K_RF5112;
ah->ah_single_chip = false;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) ||
- ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
+ ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
- ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
- ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
} else {
- ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
+ ATH5K_ERR(ah, "Couldn't identify radio revision.\n");
ret = -ENODEV;
goto err;
}
}
- /* Return on unsuported chips (unsupported eeprom etc) */
- if ((srev >= AR5K_SREV_AR5416) &&
- (srev < AR5K_SREV_AR2425)) {
- ATH5K_ERR(sc, "Device not yet supported.\n");
+ /* Return on unsupported chips (unsupported eeprom etc) */
+ if ((srev >= AR5K_SREV_AR5416) && (srev < AR5K_SREV_AR2425)) {
+ ATH5K_ERR(ah, "Device not yet supported.\n");
ret = -ENODEV;
goto err;
}
@@ -268,7 +263,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
*/
ret = ath5k_eeprom_init(ah);
if (ret) {
- ATH5K_ERR(sc, "unable to init EEPROM\n");
+ ATH5K_ERR(ah, "unable to init EEPROM\n");
goto err;
}
@@ -285,7 +280,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
- /* If serdes programing is enabled, increase PCI-E
+ /* If serdes programming is enabled, increase PCI-E
* tx power for systems with long trace from host
* to minicard connector. */
if (ee->ee_serdes)
@@ -309,17 +304,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)
/* Get misc capabilities */
ret = ath5k_hw_set_capabilities(ah);
if (ret) {
- ATH5K_ERR(sc, "unable to get device capabilities\n");
+ ATH5K_ERR(ah, "unable to get device capabilities\n");
goto err;
}
- if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
+ if (test_bit(ATH_STAT_2G_DISABLED, ah->status)) {
__clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
__clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
}
/* Crypto settings */
- common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+ common->keymax = (ah->ah_version == AR5K_AR5210 ?
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
if (srev >= AR5K_SREV_AR5212_V4 &&
@@ -334,12 +329,12 @@ int ath5k_hw_init(struct ath5k_softc *sc)
}
/* MAC address is cleared until add_interface */
- ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
+ ath5k_hw_set_lladdr(ah, zero_mac);
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
ath5k_hw_set_bssid(ah);
- ath5k_hw_set_opmode(ah, sc->opmode);
+ ath5k_hw_set_opmode(ah, ah->opmode);
ath5k_hw_rfgain_opt_init(ah);
@@ -360,7 +355,7 @@ err:
*/
void ath5k_hw_deinit(struct ath5k_hw *ah)
{
- __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
+ __set_bit(ATH_STAT_INVALID, ah->status);
if (ah->ah_rf_banks != NULL)
kfree(ah->ah_rf_banks);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 1ae8913..b346d04 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/hardirq.h>
#include <linux/if.h>
#include <linux/io.h>
@@ -51,6 +52,7 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
+#include <linux/nl80211.h>
#include <net/ieee80211_radiotap.h>
@@ -60,6 +62,8 @@
#include "reg.h"
#include "debug.h"
#include "ani.h"
+#include "ath5k.h"
+#include "../regd.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -85,10 +89,8 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
static int ath5k_init(struct ieee80211_hw *hw);
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
bool skip_pcu);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
@@ -239,8 +241,8 @@ static const struct ath_ops ath5k_common_ops = {
static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
- struct ath5k_softc *sc = hw->priv;
- struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah);
+ struct ath5k_hw *ah = hw->priv;
+ struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
return ath_reg_notifier_apply(wiphy, request, regulatory);
}
@@ -273,24 +275,22 @@ static unsigned int
ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
unsigned int mode, unsigned int max)
{
- unsigned int count, size, chfreq, freq, ch;
+ unsigned int count, size, freq, ch;
enum ieee80211_band band;
switch (mode) {
case AR5K_MODE_11A:
/* 1..220, but 2GHz frequencies are filtered by check_channel */
size = 220;
- chfreq = CHANNEL_5GHZ;
band = IEEE80211_BAND_5GHZ;
break;
case AR5K_MODE_11B:
case AR5K_MODE_11G:
size = 26;
- chfreq = CHANNEL_2GHZ;
band = IEEE80211_BAND_2GHZ;
break;
default:
- ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
+ ATH5K_WARN(ah, "bad mode, not copying channels\n");
return 0;
}
@@ -301,26 +301,19 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
if (freq == 0) /* mapping failed - not a standard channel */
continue;
+ /* Write channel info, needed for ath5k_channel_ok() */
+ channels[count].center_freq = freq;
+ channels[count].band = band;
+ channels[count].hw_value = mode;
+
/* Check if channel is supported by the chipset */
- if (!ath5k_channel_ok(ah, freq, chfreq))
+ if (!ath5k_channel_ok(ah, &channels[count]))
continue;
if (!modparam_all_channels &&
!ath5k_is_standard_channel(ch, band))
continue;
- /* Write channel info and increment counter */
- channels[count].center_freq = freq;
- channels[count].band = band;
- switch (mode) {
- case AR5K_MODE_11A:
- case AR5K_MODE_11G:
- channels[count].hw_value = chfreq | CHANNEL_OFDM;
- break;
- case AR5K_MODE_11B:
- channels[count].hw_value = CHANNEL_B;
- }
-
count++;
}
@@ -328,51 +321,50 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
}
static void
-ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
+ath5k_setup_rate_idx(struct ath5k_hw *ah, struct ieee80211_supported_band *b)
{
u8 i;
for (i = 0; i < AR5K_MAX_RATES; i++)
- sc->rate_idx[b->band][i] = -1;
+ ah->rate_idx[b->band][i] = -1;
for (i = 0; i < b->n_bitrates; i++) {
- sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
+ ah->rate_idx[b->band][b->bitrates[i].hw_value] = i;
if (b->bitrates[i].hw_value_short)
- sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
+ ah->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
}
}
static int
ath5k_setup_bands(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ieee80211_supported_band *sband;
int max_c, count_c = 0;
int i;
- BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
- max_c = ARRAY_SIZE(sc->channels);
+ BUILD_BUG_ON(ARRAY_SIZE(ah->sbands) < IEEE80211_NUM_BANDS);
+ max_c = ARRAY_SIZE(ah->channels);
/* 2GHz band */
- sband = &sc->sbands[IEEE80211_BAND_2GHZ];
+ sband = &ah->sbands[IEEE80211_BAND_2GHZ];
sband->band = IEEE80211_BAND_2GHZ;
- sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
+ sband->bitrates = &ah->rates[IEEE80211_BAND_2GHZ][0];
- if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
+ if (test_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode)) {
/* G mode */
memcpy(sband->bitrates, &ath5k_rates[0],
sizeof(struct ieee80211_rate) * 12);
sband->n_bitrates = 12;
- sband->channels = sc->channels;
+ sband->channels = ah->channels;
sband->n_channels = ath5k_setup_channels(ah, sband->channels,
AR5K_MODE_11G, max_c);
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
count_c = sband->n_channels;
max_c -= count_c;
- } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
+ } else if (test_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode)) {
/* B mode */
memcpy(sband->bitrates, &ath5k_rates[0],
sizeof(struct ieee80211_rate) * 4);
@@ -391,7 +383,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
}
}
- sband->channels = sc->channels;
+ sband->channels = ah->channels;
sband->n_channels = ath5k_setup_channels(ah, sband->channels,
AR5K_MODE_11B, max_c);
@@ -399,27 +391,27 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
count_c = sband->n_channels;
max_c -= count_c;
}
- ath5k_setup_rate_idx(sc, sband);
+ ath5k_setup_rate_idx(ah, sband);
/* 5GHz band, A mode */
- if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
- sband = &sc->sbands[IEEE80211_BAND_5GHZ];
+ if (test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
+ sband = &ah->sbands[IEEE80211_BAND_5GHZ];
sband->band = IEEE80211_BAND_5GHZ;
- sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
+ sband->bitrates = &ah->rates[IEEE80211_BAND_5GHZ][0];
memcpy(sband->bitrates, &ath5k_rates[4],
sizeof(struct ieee80211_rate) * 8);
sband->n_bitrates = 8;
- sband->channels = &sc->channels[count_c];
+ sband->channels = &ah->channels[count_c];
sband->n_channels = ath5k_setup_channels(ah, sband->channels,
AR5K_MODE_11A, max_c);
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
}
- ath5k_setup_rate_idx(sc, sband);
+ ath5k_setup_rate_idx(ah, sband);
- ath5k_debug_dump_bands(sc);
+ ath5k_debug_dump_bands(ah);
return 0;
}
@@ -429,14 +421,14 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
* To accomplish this we must first cleanup any pending DMA,
* then restart stuff after a la ath5k_init.
*
- * Called with sc->lock.
+ * Called with ah->lock.
*/
int
-ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan)
{
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"channel set, resetting (%u -> %u MHz)\n",
- sc->curchan->center_freq, chan->center_freq);
+ ah->curchan->center_freq, chan->center_freq);
/*
* To switch channels clear any pending DMA operations;
@@ -444,7 +436,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- return ath5k_reset(sc, chan, true);
+ return ath5k_reset(ah, chan, true);
}
void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -488,10 +480,10 @@ void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
}
void
-ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
struct ieee80211_vif *vif)
{
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_vif_iter_data iter_data;
u32 rfilt;
@@ -510,41 +502,41 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
ath5k_vif_iter(&iter_data, vif->addr, vif);
/* Get list of all active MAC addresses */
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+ ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
&iter_data);
- memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
+ memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
- sc->opmode = iter_data.opmode;
- if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
+ ah->opmode = iter_data.opmode;
+ if (ah->opmode == NL80211_IFTYPE_UNSPECIFIED)
/* Nothing active, default to station mode */
- sc->opmode = NL80211_IFTYPE_STATION;
+ ah->opmode = NL80211_IFTYPE_STATION;
- ath5k_hw_set_opmode(sc->ah, sc->opmode);
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
- sc->opmode, ath_opmode_to_string(sc->opmode));
+ ath5k_hw_set_opmode(ah, ah->opmode);
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+ ah->opmode, ath_opmode_to_string(ah->opmode));
if (iter_data.need_set_hw_addr && iter_data.found_active)
- ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
+ ath5k_hw_set_lladdr(ah, iter_data.active_mac);
- if (ath5k_hw_hasbssidmask(sc->ah))
- ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+ if (ath5k_hw_hasbssidmask(ah))
+ ath5k_hw_set_bssid_mask(ah, ah->bssidmask);
/* Set up RX Filter */
if (iter_data.n_stas > 1) {
/* If you have multiple STA interfaces connected to
* different APs, ARPs are not received (most of the time?)
- * Enabling PROMISC appears to fix that probem.
+ * Enabling PROMISC appears to fix that problem.
*/
- sc->filter_flags |= AR5K_RX_FILTER_PROM;
+ ah->filter_flags |= AR5K_RX_FILTER_PROM;
}
- rfilt = sc->filter_flags;
- ath5k_hw_set_rx_filter(sc->ah, rfilt);
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+ rfilt = ah->filter_flags;
+ ath5k_hw_set_rx_filter(ah, rfilt);
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
}
static inline int
-ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
+ath5k_hw_to_driver_rix(struct ath5k_hw *ah, int hw_rix)
{
int rix;
@@ -553,7 +545,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
"hw_rix out of bounds: %x\n", hw_rix))
return 0;
- rix = sc->rate_idx[sc->curchan->band][hw_rix];
+ rix = ah->rate_idx[ah->curchan->band][hw_rix];
if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
rix = 0;
@@ -565,9 +557,9 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
\***************/
static
-struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
+struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_hw *ah, dma_addr_t *skb_addr)
{
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
struct sk_buff *skb;
/*
@@ -579,17 +571,17 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
GFP_ATOMIC);
if (!skb) {
- ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+ ATH5K_ERR(ah, "can't alloc skbuff of size %u\n",
common->rx_bufsize);
return NULL;
}
- *skb_addr = dma_map_single(sc->dev,
+ *skb_addr = dma_map_single(ah->dev,
skb->data, common->rx_bufsize,
DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) {
- ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+ if (unlikely(dma_mapping_error(ah->dev, *skb_addr))) {
+ ATH5K_ERR(ah, "%s: DMA mapping failed\n", __func__);
dev_kfree_skb(skb);
return NULL;
}
@@ -597,15 +589,14 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
}
static int
-ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_rxbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
- struct ath5k_hw *ah = sc->ah;
struct sk_buff *skb = bf->skb;
struct ath5k_desc *ds;
int ret;
if (!skb) {
- skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
+ skb = ath5k_rx_skb_alloc(ah, &bf->skbaddr);
if (!skb)
return -ENOMEM;
bf->skb = skb;
@@ -631,13 +622,13 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds->ds_data = bf->skbaddr;
ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
if (ret) {
- ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__);
+ ATH5K_ERR(ah, "%s: could not setup RX desc\n", __func__);
return ret;
}
- if (sc->rxlink != NULL)
- *sc->rxlink = bf->daddr;
- sc->rxlink = &ds->ds_link;
+ if (ah->rxlink != NULL)
+ *ah->rxlink = bf->daddr;
+ ah->rxlink = &ds->ds_link;
return 0;
}
@@ -665,10 +656,9 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
}
static int
-ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
struct ath5k_txq *txq, int padsize)
{
- struct ath5k_hw *ah = sc->ah;
struct ath5k_desc *ds = bf->desc;
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -684,10 +674,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
/* XXX endianness */
- bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+ bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
DMA_TO_DEVICE);
- rate = ieee80211_get_tx_rate(sc->hw, info);
+ rate = ieee80211_get_tx_rate(ah->hw, info);
if (!rate) {
ret = -EINVAL;
goto err_unmap;
@@ -711,20 +701,20 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
}
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= AR5K_TXDESC_RTSENA;
- cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
- duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
+ cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value;
+ duration = le16_to_cpu(ieee80211_rts_duration(ah->hw,
info->control.vif, pktlen, info));
}
if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
flags |= AR5K_TXDESC_CTSENA;
- cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
- duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
+ cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value;
+ duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw,
info->control.vif, pktlen, info));
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), padsize,
get_hw_packet_type(skb),
- (sc->power_level * 2),
+ (ah->power_level * 2),
hw_rate,
info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
cts_rate, duration);
@@ -734,7 +724,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
memset(mrr_rate, 0, sizeof(mrr_rate));
memset(mrr_tries, 0, sizeof(mrr_tries));
for (i = 0; i < 3; i++) {
- rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
+ rate = ieee80211_get_alt_retry_rate(ah->hw, info, i);
if (!rate)
break;
@@ -765,7 +755,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
return 0;
err_unmap:
- dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
+ dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
return ret;
}
@@ -774,7 +764,7 @@ err_unmap:
\*******************/
static int
-ath5k_desc_alloc(struct ath5k_softc *sc)
+ath5k_desc_alloc(struct ath5k_hw *ah)
{
struct ath5k_desc *ds;
struct ath5k_buf *bf;
@@ -783,69 +773,68 @@ ath5k_desc_alloc(struct ath5k_softc *sc)
int ret;
/* allocate descriptors */
- sc->desc_len = sizeof(struct ath5k_desc) *
+ ah->desc_len = sizeof(struct ath5k_desc) *
(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
- sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len,
- &sc->desc_daddr, GFP_KERNEL);
- if (sc->desc == NULL) {
- ATH5K_ERR(sc, "can't allocate descriptors\n");
+ ah->desc = dma_alloc_coherent(ah->dev, ah->desc_len,
+ &ah->desc_daddr, GFP_KERNEL);
+ if (ah->desc == NULL) {
+ ATH5K_ERR(ah, "can't allocate descriptors\n");
ret = -ENOMEM;
goto err;
}
- ds = sc->desc;
- da = sc->desc_daddr;
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
- ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
+ ds = ah->desc;
+ da = ah->desc_daddr;
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
+ ds, ah->desc_len, (unsigned long long)ah->desc_daddr);
bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
sizeof(struct ath5k_buf), GFP_KERNEL);
if (bf == NULL) {
- ATH5K_ERR(sc, "can't allocate bufptr\n");
+ ATH5K_ERR(ah, "can't allocate bufptr\n");
ret = -ENOMEM;
goto err_free;
}
- sc->bufptr = bf;
+ ah->bufptr = bf;
- INIT_LIST_HEAD(&sc->rxbuf);
+ INIT_LIST_HEAD(&ah->rxbuf);
for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
bf->desc = ds;
bf->daddr = da;
- list_add_tail(&bf->list, &sc->rxbuf);
+ list_add_tail(&bf->list, &ah->rxbuf);
}
- INIT_LIST_HEAD(&sc->txbuf);
- sc->txbuf_len = ATH_TXBUF;
- for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
- da += sizeof(*ds)) {
+ INIT_LIST_HEAD(&ah->txbuf);
+ ah->txbuf_len = ATH_TXBUF;
+ for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
bf->desc = ds;
bf->daddr = da;
- list_add_tail(&bf->list, &sc->txbuf);
+ list_add_tail(&bf->list, &ah->txbuf);
}
/* beacon buffers */
- INIT_LIST_HEAD(&sc->bcbuf);
+ INIT_LIST_HEAD(&ah->bcbuf);
for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) {
bf->desc = ds;
bf->daddr = da;
- list_add_tail(&bf->list, &sc->bcbuf);
+ list_add_tail(&bf->list, &ah->bcbuf);
}
return 0;
err_free:
- dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
+ dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr);
err:
- sc->desc = NULL;
+ ah->desc = NULL;
return ret;
}
void
-ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
BUG_ON(!bf);
if (!bf->skb)
return;
- dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
+ dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len,
DMA_TO_DEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
@@ -854,15 +843,14 @@ ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
}
void
-ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
BUG_ON(!bf);
if (!bf->skb)
return;
- dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
+ dma_unmap_single(ah->dev, bf->skbaddr, common->rx_bufsize,
DMA_FROM_DEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
@@ -871,24 +859,24 @@ ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
}
static void
-ath5k_desc_free(struct ath5k_softc *sc)
+ath5k_desc_free(struct ath5k_hw *ah)
{
struct ath5k_buf *bf;
- list_for_each_entry(bf, &sc->txbuf, list)
- ath5k_txbuf_free_skb(sc, bf);
- list_for_each_entry(bf, &sc->rxbuf, list)
- ath5k_rxbuf_free_skb(sc, bf);
- list_for_each_entry(bf, &sc->bcbuf, list)
- ath5k_txbuf_free_skb(sc, bf);
+ list_for_each_entry(bf, &ah->txbuf, list)
+ ath5k_txbuf_free_skb(ah, bf);
+ list_for_each_entry(bf, &ah->rxbuf, list)
+ ath5k_rxbuf_free_skb(ah, bf);
+ list_for_each_entry(bf, &ah->bcbuf, list)
+ ath5k_txbuf_free_skb(ah, bf);
/* Free memory associated with all descriptors */
- dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
- sc->desc = NULL;
- sc->desc_daddr = 0;
+ dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr);
+ ah->desc = NULL;
+ ah->desc_daddr = 0;
- kfree(sc->bufptr);
- sc->bufptr = NULL;
+ kfree(ah->bufptr);
+ ah->bufptr = NULL;
}
@@ -897,10 +885,9 @@ ath5k_desc_free(struct ath5k_softc *sc)
\**************/
static struct ath5k_txq *
-ath5k_txq_setup(struct ath5k_softc *sc,
+ath5k_txq_setup(struct ath5k_hw *ah,
int qtype, int subtype)
{
- struct ath5k_hw *ah = sc->ah;
struct ath5k_txq *txq;
struct ath5k_txq_info qi = {
.tqi_subtype = subtype,
@@ -934,13 +921,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
*/
return ERR_PTR(qnum);
}
- if (qnum >= ARRAY_SIZE(sc->txqs)) {
- ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
- qnum, ARRAY_SIZE(sc->txqs));
- ath5k_hw_release_tx_queue(ah, qnum);
- return ERR_PTR(-EINVAL);
- }
- txq = &sc->txqs[qnum];
+ txq = &ah->txqs[qnum];
if (!txq->setup) {
txq->qnum = qnum;
txq->link = NULL;
@@ -952,7 +933,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
txq->txq_poll_mark = false;
txq->txq_stuck = 0;
}
- return &sc->txqs[qnum];
+ return &ah->txqs[qnum];
}
static int
@@ -972,18 +953,17 @@ ath5k_beaconq_setup(struct ath5k_hw *ah)
}
static int
-ath5k_beaconq_config(struct ath5k_softc *sc)
+ath5k_beaconq_config(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
struct ath5k_txq_info qi;
int ret;
- ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
+ ret = ath5k_hw_get_tx_queueprops(ah, ah->bhalq, &qi);
if (ret)
goto err;
- if (sc->opmode == NL80211_IFTYPE_AP ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+ if (ah->opmode == NL80211_IFTYPE_AP ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
/*
* Always burst out beacon and CAB traffic
* (aifs = cwmin = cwmax = 0)
@@ -991,7 +971,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
qi.tqi_aifs = 0;
qi.tqi_cw_min = 0;
qi.tqi_cw_max = 0;
- } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+ } else if (ah->opmode == NL80211_IFTYPE_ADHOC) {
/*
* Adhoc mode; backoff between 0 and (2 * cw_min).
*/
@@ -1000,17 +980,17 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN;
}
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
- ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
+ ret = ath5k_hw_set_tx_queueprops(ah, ah->bhalq, &qi);
if (ret) {
- ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
+ ATH5K_ERR(ah, "%s: unable to update parameters for beacon "
"hardware queue!\n", __func__);
goto err;
}
- ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */
+ ret = ath5k_hw_reset_tx_queue(ah, ah->bhalq); /* push to h/w */
if (ret)
goto err;
@@ -1019,7 +999,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
if (ret)
goto err;
- qi.tqi_ready_time = (sc->bintval * 80) / 100;
+ qi.tqi_ready_time = (ah->bintval * 80) / 100;
ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
if (ret)
goto err;
@@ -1032,7 +1012,7 @@ err:
/**
* ath5k_drain_tx_buffs - Empty tx buffers
*
- * @sc The &struct ath5k_softc
+ * @ah The &struct ath5k_hw
*
* Empty tx buffers from all queues in preparation
* of a reset or during shutdown.
@@ -1041,26 +1021,26 @@ err:
* we do not need to block ath5k_tx_tasklet
*/
static void
-ath5k_drain_tx_buffs(struct ath5k_softc *sc)
+ath5k_drain_tx_buffs(struct ath5k_hw *ah)
{
struct ath5k_txq *txq;
struct ath5k_buf *bf, *bf0;
int i;
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
- if (sc->txqs[i].setup) {
- txq = &sc->txqs[i];
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+ if (ah->txqs[i].setup) {
+ txq = &ah->txqs[i];
spin_lock_bh(&txq->lock);
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
- ath5k_debug_printtxbuf(sc, bf);
+ ath5k_debug_printtxbuf(ah, bf);
- ath5k_txbuf_free_skb(sc, bf);
+ ath5k_txbuf_free_skb(ah, bf);
- spin_lock_bh(&sc->txbuflock);
- list_move_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
+ spin_lock_bh(&ah->txbuflock);
+ list_move_tail(&bf->list, &ah->txbuf);
+ ah->txbuf_len++;
txq->txq_len--;
- spin_unlock_bh(&sc->txbuflock);
+ spin_unlock_bh(&ah->txbuflock);
}
txq->link = NULL;
txq->txq_poll_mark = false;
@@ -1070,14 +1050,14 @@ ath5k_drain_tx_buffs(struct ath5k_softc *sc)
}
static void
-ath5k_txq_release(struct ath5k_softc *sc)
+ath5k_txq_release(struct ath5k_hw *ah)
{
- struct ath5k_txq *txq = sc->txqs;
+ struct ath5k_txq *txq = ah->txqs;
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++, txq++)
if (txq->setup) {
- ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
+ ath5k_hw_release_tx_queue(ah, txq->qnum);
txq->setup = false;
}
}
@@ -1091,33 +1071,32 @@ ath5k_txq_release(struct ath5k_softc *sc)
* Enable the receive h/w following a reset.
*/
static int
-ath5k_rx_start(struct ath5k_softc *sc)
+ath5k_rx_start(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_buf *bf;
int ret;
common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
common->cachelsz, common->rx_bufsize);
- spin_lock_bh(&sc->rxbuflock);
- sc->rxlink = NULL;
- list_for_each_entry(bf, &sc->rxbuf, list) {
- ret = ath5k_rxbuf_setup(sc, bf);
+ spin_lock_bh(&ah->rxbuflock);
+ ah->rxlink = NULL;
+ list_for_each_entry(bf, &ah->rxbuf, list) {
+ ret = ath5k_rxbuf_setup(ah, bf);
if (ret != 0) {
- spin_unlock_bh(&sc->rxbuflock);
+ spin_unlock_bh(&ah->rxbuflock);
goto err;
}
}
- bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+ bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list);
ath5k_hw_set_rxdp(ah, bf->daddr);
- spin_unlock_bh(&sc->rxbuflock);
+ spin_unlock_bh(&ah->rxbuflock);
ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
- ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */
+ ath5k_update_bssid_mask_and_opmode(ah, NULL); /* set filters, etc. */
ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
return 0;
@@ -1133,21 +1112,19 @@ err:
* does.
*/
static void
-ath5k_rx_stop(struct ath5k_softc *sc)
+ath5k_rx_stop(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
- ath5k_debug_printrxbuffs(sc, ah);
+ ath5k_debug_printrxbuffs(ah);
}
static unsigned int
-ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_rx_decrypted(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_rx_status *rs)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int keyix, hlen;
@@ -1174,10 +1151,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb,
static void
-ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb,
struct ieee80211_rx_status *rxs)
{
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
u64 tsf, bc_tstamp;
u32 hw_tu;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -1190,11 +1167,11 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
* have updated the local TSF. We have to work around various
* hardware bugs, though...
*/
- tsf = ath5k_hw_get_tsf64(sc->ah);
+ tsf = ath5k_hw_get_tsf64(ah);
bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
hw_tu = TSF_TO_TU(tsf);
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
(unsigned long long)bc_tstamp,
(unsigned long long)rxs->mactime,
@@ -1213,7 +1190,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
* received, not like mac80211 which defines it at the start.
*/
if (bc_tstamp > rxs->mactime) {
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"fixing mactime from %llx to %llx\n",
(unsigned long long)rxs->mactime,
(unsigned long long)tsf);
@@ -1226,25 +1203,24 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
* beacons. This also takes care of synchronizing beacon sending
* times with other stations.
*/
- if (hw_tu >= sc->nexttbtt)
- ath5k_beacon_update_timers(sc, bc_tstamp);
+ if (hw_tu >= ah->nexttbtt)
+ ath5k_beacon_update_timers(ah, bc_tstamp);
/* Check if the beacon timers are still correct, because a TSF
* update might have created a window between them - for a
* longer description see the comment of this function: */
- if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) {
- ath5k_beacon_update_timers(sc, bc_tstamp);
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ if (!ath5k_hw_check_beacon_timers(ah, ah->bintval)) {
+ ath5k_beacon_update_timers(ah, bc_tstamp);
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"fixed beacon timers after beacon receive\n");
}
}
}
static void
-ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
+ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
/* only beacons from our BSSID */
@@ -1263,16 +1239,15 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
*/
static int ath5k_common_padpos(struct sk_buff *skb)
{
- struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 frame_control = hdr->frame_control;
int padpos = 24;
- if (ieee80211_has_a4(frame_control)) {
+ if (ieee80211_has_a4(frame_control))
padpos += ETH_ALEN;
- }
- if (ieee80211_is_data_qos(frame_control)) {
+
+ if (ieee80211_is_data_qos(frame_control))
padpos += IEEE80211_QOS_CTL_LEN;
- }
return padpos;
}
@@ -1286,13 +1261,13 @@ static int ath5k_add_padding(struct sk_buff *skb)
int padpos = ath5k_common_padpos(skb);
int padsize = padpos & 3;
- if (padsize && skb->len>padpos) {
+ if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize)
return -1;
skb_push(skb, padsize);
- memmove(skb->data, skb->data+padsize, padpos);
+ memmove(skb->data, skb->data + padsize, padpos);
return padsize;
}
@@ -1317,7 +1292,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)
int padpos = ath5k_common_padpos(skb);
int padsize = padpos & 3;
- if (padsize && skb->len>=padpos+padsize) {
+ if (padsize && skb->len >= padpos + padsize) {
memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
return padsize;
@@ -1327,7 +1302,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)
}
static void
-ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_rx_status *rs)
{
struct ieee80211_rx_status *rxs;
@@ -1353,44 +1328,44 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
* timestamp (beginning of phy frame, data frame, end of rx?).
* The only thing we know is that it is hardware specific...
* On AR5213 it seems the rx timestamp is at the end of the
- * frame, but i'm not sure.
+ * frame, but I'm not sure.
*
* NOTE: mac80211 defines mactime at the beginning of the first
* data symbol. Since we don't have any time references it's
* impossible to comply to that. This affects IBSS merge only
* right now, so it's not too bad...
*/
- rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp);
+ rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp);
rxs->flag |= RX_FLAG_MACTIME_MPDU;
- rxs->freq = sc->curchan->center_freq;
- rxs->band = sc->curchan->band;
+ rxs->freq = ah->curchan->center_freq;
+ rxs->band = ah->curchan->band;
- rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi;
+ rxs->signal = ah->ah_noise_floor + rs->rs_rssi;
rxs->antenna = rs->rs_antenna;
if (rs->rs_antenna > 0 && rs->rs_antenna < 5)
- sc->stats.antenna_rx[rs->rs_antenna]++;
+ ah->stats.antenna_rx[rs->rs_antenna]++;
else
- sc->stats.antenna_rx[0]++; /* invalid */
+ ah->stats.antenna_rx[0]++; /* invalid */
- rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate);
- rxs->flag |= ath5k_rx_decrypted(sc, skb, rs);
+ rxs->rate_idx = ath5k_hw_to_driver_rix(ah, rs->rs_rate);
+ rxs->flag |= ath5k_rx_decrypted(ah, skb, rs);
if (rxs->rate_idx >= 0 && rs->rs_rate ==
- sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
+ ah->sbands[ah->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
rxs->flag |= RX_FLAG_SHORTPRE;
- trace_ath5k_rx(sc, skb);
+ trace_ath5k_rx(ah, skb);
- ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi);
+ ath5k_update_beacon_rssi(ah, skb, rs->rs_rssi);
/* check beacons in IBSS mode */
- if (sc->opmode == NL80211_IFTYPE_ADHOC)
- ath5k_check_ibss_tsf(sc, skb, rxs);
+ if (ah->opmode == NL80211_IFTYPE_ADHOC)
+ ath5k_check_ibss_tsf(ah, skb, rxs);
- ieee80211_rx(sc->hw, skb);
+ ieee80211_rx(ah->hw, skb);
}
/** ath5k_frame_receive_ok() - Do we want to receive this frame or not?
@@ -1399,20 +1374,20 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
* statistics. Return true if we want this frame, false if not.
*/
static bool
-ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
+ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
{
- sc->stats.rx_all_count++;
- sc->stats.rx_bytes_count += rs->rs_datalen;
+ ah->stats.rx_all_count++;
+ ah->stats.rx_bytes_count += rs->rs_datalen;
if (unlikely(rs->rs_status)) {
if (rs->rs_status & AR5K_RXERR_CRC)
- sc->stats.rxerr_crc++;
+ ah->stats.rxerr_crc++;
if (rs->rs_status & AR5K_RXERR_FIFO)
- sc->stats.rxerr_fifo++;
+ ah->stats.rxerr_fifo++;
if (rs->rs_status & AR5K_RXERR_PHY) {
- sc->stats.rxerr_phy++;
+ ah->stats.rxerr_phy++;
if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32)
- sc->stats.rxerr_phy_code[rs->rs_phyerr]++;
+ ah->stats.rxerr_phy_code[rs->rs_phyerr]++;
return false;
}
if (rs->rs_status & AR5K_RXERR_DECRYPT) {
@@ -1426,13 +1401,13 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
*
* XXX do key cache faulting
*/
- sc->stats.rxerr_decrypt++;
+ ah->stats.rxerr_decrypt++;
if (rs->rs_keyix == AR5K_RXKEYIX_INVALID &&
!(rs->rs_status & AR5K_RXERR_CRC))
return true;
}
if (rs->rs_status & AR5K_RXERR_MIC) {
- sc->stats.rxerr_mic++;
+ ah->stats.rxerr_mic++;
return true;
}
@@ -1442,25 +1417,26 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
}
if (unlikely(rs->rs_more)) {
- sc->stats.rxerr_jumbo++;
+ ah->stats.rxerr_jumbo++;
return false;
}
return true;
}
static void
-ath5k_set_current_imask(struct ath5k_softc *sc)
+ath5k_set_current_imask(struct ath5k_hw *ah)
{
- enum ath5k_int imask = sc->imask;
+ enum ath5k_int imask;
unsigned long flags;
- spin_lock_irqsave(&sc->irqlock, flags);
- if (sc->rx_pending)
+ spin_lock_irqsave(&ah->irqlock, flags);
+ imask = ah->imask;
+ if (ah->rx_pending)
imask &= ~AR5K_INT_RX_ALL;
- if (sc->tx_pending)
+ if (ah->tx_pending)
imask &= ~AR5K_INT_TX_ALL;
- ath5k_hw_set_imr(sc->ah, imask);
- spin_unlock_irqrestore(&sc->irqlock, flags);
+ ath5k_hw_set_imr(ah, imask);
+ spin_unlock_irqrestore(&ah->irqlock, flags);
}
static void
@@ -1469,39 +1445,38 @@ ath5k_tasklet_rx(unsigned long data)
struct ath5k_rx_status rs = {};
struct sk_buff *skb, *next_skb;
dma_addr_t next_skb_addr;
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = (void *)data;
struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_buf *bf;
struct ath5k_desc *ds;
int ret;
- spin_lock(&sc->rxbuflock);
- if (list_empty(&sc->rxbuf)) {
- ATH5K_WARN(sc, "empty rx buf pool\n");
+ spin_lock(&ah->rxbuflock);
+ if (list_empty(&ah->rxbuf)) {
+ ATH5K_WARN(ah, "empty rx buf pool\n");
goto unlock;
}
do {
- bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+ bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list);
BUG_ON(bf->skb == NULL);
skb = bf->skb;
ds = bf->desc;
/* bail if HW is still using self-linked descriptor */
- if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
+ if (ath5k_hw_get_rxdp(ah) == bf->daddr)
break;
- ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+ ret = ah->ah_proc_rx_desc(ah, ds, &rs);
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
- ATH5K_ERR(sc, "error in processing rx descriptor\n");
- sc->stats.rxerr_proc++;
+ ATH5K_ERR(ah, "error in processing rx descriptor\n");
+ ah->stats.rxerr_proc++;
break;
}
- if (ath5k_receive_frame_ok(sc, &rs)) {
- next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
+ if (ath5k_receive_frame_ok(ah, &rs)) {
+ next_skb = ath5k_rx_skb_alloc(ah, &next_skb_addr);
/*
* If we can't replace bf->skb with a new skb under
@@ -1510,24 +1485,24 @@ ath5k_tasklet_rx(unsigned long data)
if (!next_skb)
goto next;
- dma_unmap_single(sc->dev, bf->skbaddr,
+ dma_unmap_single(ah->dev, bf->skbaddr,
common->rx_bufsize,
DMA_FROM_DEVICE);
skb_put(skb, rs.rs_datalen);
- ath5k_receive_frame(sc, skb, &rs);
+ ath5k_receive_frame(ah, skb, &rs);
bf->skb = next_skb;
bf->skbaddr = next_skb_addr;
}
next:
- list_move_tail(&bf->list, &sc->rxbuf);
- } while (ath5k_rxbuf_setup(sc, bf) == 0);
+ list_move_tail(&bf->list, &ah->rxbuf);
+ } while (ath5k_rxbuf_setup(ah, bf) == 0);
unlock:
- spin_unlock(&sc->rxbuflock);
- sc->rx_pending = false;
- ath5k_set_current_imask(sc);
+ spin_unlock(&ah->rxbuflock);
+ ah->rx_pending = false;
+ ath5k_set_current_imask(ah);
}
@@ -1539,12 +1514,12 @@ void
ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_buf *bf;
unsigned long flags;
int padsize;
- trace_ath5k_tx(sc, skb, txq);
+ trace_ath5k_tx(ah, skb, txq);
/*
* The hardware expects the header padded to 4 byte boundaries.
@@ -1552,36 +1527,37 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
padsize = ath5k_add_padding(skb);
if (padsize < 0) {
- ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
+ ATH5K_ERR(ah, "tx hdrlen not %%4: not enough"
" headroom to pad");
goto drop_packet;
}
- if (txq->txq_len >= txq->txq_max)
+ if (txq->txq_len >= txq->txq_max &&
+ txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX)
ieee80211_stop_queue(hw, txq->qnum);
- spin_lock_irqsave(&sc->txbuflock, flags);
- if (list_empty(&sc->txbuf)) {
- ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ spin_lock_irqsave(&ah->txbuflock, flags);
+ if (list_empty(&ah->txbuf)) {
+ ATH5K_ERR(ah, "no further txbuf available, dropping packet\n");
+ spin_unlock_irqrestore(&ah->txbuflock, flags);
ieee80211_stop_queues(hw);
goto drop_packet;
}
- bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+ bf = list_first_entry(&ah->txbuf, struct ath5k_buf, list);
list_del(&bf->list);
- sc->txbuf_len--;
- if (list_empty(&sc->txbuf))
+ ah->txbuf_len--;
+ if (list_empty(&ah->txbuf))
ieee80211_stop_queues(hw);
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ spin_unlock_irqrestore(&ah->txbuflock, flags);
bf->skb = skb;
- if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
+ if (ath5k_txbuf_setup(ah, bf, txq, padsize)) {
bf->skb = NULL;
- spin_lock_irqsave(&sc->txbuflock, flags);
- list_add_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ spin_lock_irqsave(&ah->txbuflock, flags);
+ list_add_tail(&bf->list, &ah->txbuf);
+ ah->txbuf_len++;
+ spin_unlock_irqrestore(&ah->txbuflock, flags);
goto drop_packet;
}
return;
@@ -1591,15 +1567,15 @@ drop_packet:
}
static void
-ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_txq *txq, struct ath5k_tx_status *ts)
{
struct ieee80211_tx_info *info;
u8 tries[3];
int i;
- sc->stats.tx_all_count++;
- sc->stats.tx_bytes_count += skb->len;
+ ah->stats.tx_all_count++;
+ ah->stats.tx_bytes_count += skb->len;
info = IEEE80211_SKB_CB(skb);
tries[0] = info->status.rates[0].count;
@@ -1619,15 +1595,15 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
info->status.rates[ts->ts_final_idx + 1].idx = -1;
if (unlikely(ts->ts_status)) {
- sc->stats.ack_fail++;
+ ah->stats.ack_fail++;
if (ts->ts_status & AR5K_TXERR_FILT) {
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- sc->stats.txerr_filt++;
+ ah->stats.txerr_filt++;
}
if (ts->ts_status & AR5K_TXERR_XRETRY)
- sc->stats.txerr_retry++;
+ ah->stats.txerr_retry++;
if (ts->ts_status & AR5K_TXERR_FIFO)
- sc->stats.txerr_fifo++;
+ ah->stats.txerr_fifo++;
} else {
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ack_signal = ts->ts_rssi;
@@ -1643,16 +1619,16 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
ath5k_remove_padding(skb);
if (ts->ts_antenna > 0 && ts->ts_antenna < 5)
- sc->stats.antenna_tx[ts->ts_antenna]++;
+ ah->stats.antenna_tx[ts->ts_antenna]++;
else
- sc->stats.antenna_tx[0]++; /* invalid */
+ ah->stats.antenna_tx[0]++; /* invalid */
- trace_ath5k_tx_complete(sc, skb, txq, ts);
- ieee80211_tx_status(sc->hw, skb);
+ trace_ath5k_tx_complete(ah, skb, txq, ts);
+ ieee80211_tx_status(ah->hw, skb);
}
static void
-ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
{
struct ath5k_tx_status ts = {};
struct ath5k_buf *bf, *bf0;
@@ -1669,11 +1645,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
if (bf->skb != NULL) {
ds = bf->desc;
- ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ ret = ah->ah_proc_tx_desc(ah, ds, &ts);
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
- ATH5K_ERR(sc,
+ ATH5K_ERR(ah,
"error %d while processing "
"queue %u\n", ret, txq->qnum);
break;
@@ -1682,9 +1658,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
skb = bf->skb;
bf->skb = NULL;
- dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
+ dma_unmap_single(ah->dev, bf->skbaddr, skb->len,
DMA_TO_DEVICE);
- ath5k_tx_frame_completed(sc, skb, txq, &ts);
+ ath5k_tx_frame_completed(ah, skb, txq, &ts);
}
/*
@@ -1693,31 +1669,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
* host memory and moved on.
* Always keep the last descriptor to avoid HW races...
*/
- if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) {
- spin_lock(&sc->txbuflock);
- list_move_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
+ if (ath5k_hw_get_txdp(ah, txq->qnum) != bf->daddr) {
+ spin_lock(&ah->txbuflock);
+ list_move_tail(&bf->list, &ah->txbuf);
+ ah->txbuf_len++;
txq->txq_len--;
- spin_unlock(&sc->txbuflock);
+ spin_unlock(&ah->txbuflock);
}
}
spin_unlock(&txq->lock);
if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4)
- ieee80211_wake_queue(sc->hw, txq->qnum);
+ ieee80211_wake_queue(ah->hw, txq->qnum);
}
static void
ath5k_tasklet_tx(unsigned long data)
{
int i;
- struct ath5k_softc *sc = (void *)data;
+ struct ath5k_hw *ah = (void *)data;
- for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
- if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
- ath5k_tx_processq(sc, &sc->txqs[i]);
+ for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)
+ if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i)))
+ ath5k_tx_processq(ah, &ah->txqs[i]);
- sc->tx_pending = false;
- ath5k_set_current_imask(sc);
+ ah->tx_pending = false;
+ ath5k_set_current_imask(ah);
}
@@ -1729,25 +1705,24 @@ ath5k_tasklet_tx(unsigned long data)
* Setup the beacon frame for transmit.
*/
static int
-ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ath5k_hw *ah = sc->ah;
struct ath5k_desc *ds;
int ret = 0;
u8 antenna;
u32 flags;
const int padsize = 0;
- bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+ bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
DMA_TO_DEVICE);
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
"skbaddr %llx\n", skb, skb->data, skb->len,
(unsigned long long)bf->skbaddr);
- if (dma_mapping_error(sc->dev, bf->skbaddr)) {
- ATH5K_ERR(sc, "beacon DMA mapping failed\n");
+ if (dma_mapping_error(ah->dev, bf->skbaddr)) {
+ ATH5K_ERR(ah, "beacon DMA mapping failed\n");
dev_kfree_skb_any(skb);
bf->skb = NULL;
return -EIO;
@@ -1757,7 +1732,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
antenna = ah->ah_tx_ant;
flags = AR5K_TXDESC_NOACK;
- if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
+ if (ah->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
ds->ds_link = bf->daddr; /* self-linked */
flags |= AR5K_TXDESC_VEOL;
} else
@@ -1769,7 +1744,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* 4 beacons to make sure everybody hears our AP.
* When a client tries to associate, hw will keep
* track of the tx antenna to be used for this client
- * automaticaly, based on ACKed packets.
+ * automatically, based on ACKed packets.
*
* Note: AP still listens and transmits RTS on the
* default antenna which is supposed to be an omni.
@@ -1782,7 +1757,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* on all of them.
*/
if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP)
- antenna = sc->bsent & 4 ? 2 : 1;
+ antenna = ah->bsent & 4 ? 2 : 1;
/* FIXME: If we are in g mode and rate is a CCK rate
@@ -1791,8 +1766,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds->ds_data = bf->skbaddr;
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb), padsize,
- AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
- ieee80211_get_tx_rate(sc->hw, info)->hw_value,
+ AR5K_PKT_TYPE_BEACON, (ah->power_level * 2),
+ ieee80211_get_tx_rate(ah->hw, info)->hw_value,
1, AR5K_TXKEYIX_INVALID,
antenna, flags, 0, 0);
if (ret)
@@ -1800,7 +1775,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
return 0;
err_unmap:
- dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
+ dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
return ret;
}
@@ -1815,7 +1790,7 @@ int
ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
int ret;
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_vif *avf = (void *)vif->drv_priv;
struct sk_buff *skb;
@@ -1831,9 +1806,9 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
goto out;
}
- ath5k_txbuf_free_skb(sc, avf->bbuf);
+ ath5k_txbuf_free_skb(ah, avf->bbuf);
avf->bbuf->skb = skb;
- ret = ath5k_beacon_setup(sc, avf->bbuf);
+ ret = ath5k_beacon_setup(ah, avf->bbuf);
out:
return ret;
}
@@ -1847,16 +1822,15 @@ out:
* or user context from ath5k_beacon_config.
*/
static void
-ath5k_beacon_send(struct ath5k_softc *sc)
+ath5k_beacon_send(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
struct ieee80211_vif *vif;
struct ath5k_vif *avf;
struct ath5k_buf *bf;
struct sk_buff *skb;
int err;
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "in beacon_send\n");
/*
* Check if the previous beacon has gone out. If
@@ -1865,38 +1839,38 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* indicate a problem and should not occur. If we
* miss too many consecutive beacons reset the device.
*/
- if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
- sc->bmisscount++;
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
- "missed %u consecutive beacons\n", sc->bmisscount);
- if (sc->bmisscount > 10) { /* NB: 10 is a guess */
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ if (unlikely(ath5k_hw_num_tx_pending(ah, ah->bhalq) != 0)) {
+ ah->bmisscount++;
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
+ "missed %u consecutive beacons\n", ah->bmisscount);
+ if (ah->bmisscount > 10) { /* NB: 10 is a guess */
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"stuck beacon time (%u missed)\n",
- sc->bmisscount);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ah->bmisscount);
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"stuck beacon, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
}
return;
}
- if (unlikely(sc->bmisscount != 0)) {
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ if (unlikely(ah->bmisscount != 0)) {
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"resume beacon xmit after %u misses\n",
- sc->bmisscount);
- sc->bmisscount = 0;
+ ah->bmisscount);
+ ah->bmisscount = 0;
}
- if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf);
- int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
- vif = sc->bslot[(slot + 1) % ATH_BCBUF];
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ int slot = ((tsftu % ah->bintval) * ATH_BCBUF) / ah->bintval;
+ vif = ah->bslot[(slot + 1) % ATH_BCBUF];
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"tsf %llx tsftu %x intval %u slot %u vif %p\n",
- (unsigned long long)tsf, tsftu, sc->bintval, slot, vif);
+ (unsigned long long)tsf, tsftu, ah->bintval, slot, vif);
} else /* only one interface */
- vif = sc->bslot[0];
+ vif = ah->bslot[0];
if (!vif)
return;
@@ -1909,45 +1883,49 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* This should never fail since we check above that no frames
* are still pending on the queue.
*/
- if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) {
- ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
+ if (unlikely(ath5k_hw_stop_beacon_queue(ah, ah->bhalq))) {
+ ATH5K_WARN(ah, "beacon queue %u didn't start/stop ?\n", ah->bhalq);
/* NB: hw still stops DMA, so proceed */
}
/* refresh the beacon for AP or MESH mode */
- if (sc->opmode == NL80211_IFTYPE_AP ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT) {
- err = ath5k_beacon_update(sc->hw, vif);
+ if (ah->opmode == NL80211_IFTYPE_AP ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ err = ath5k_beacon_update(ah->hw, vif);
if (err)
return;
}
- if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
- sc->opmode == NL80211_IFTYPE_MONITOR)) {
- ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf->skb);
+ if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
+ ah->opmode == NL80211_IFTYPE_MONITOR)) {
+ ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf->skb);
return;
}
- trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]);
+ trace_ath5k_tx(ah, bf->skb, &ah->txqs[ah->bhalq]);
- ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
- ath5k_hw_start_tx_dma(ah, sc->bhalq);
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
- sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
+ ath5k_hw_set_txdp(ah, ah->bhalq, bf->daddr);
+ ath5k_hw_start_tx_dma(ah, ah->bhalq);
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
+ ah->bhalq, (unsigned long long)bf->daddr, bf->desc);
- skb = ieee80211_get_buffered_bc(sc->hw, vif);
+ skb = ieee80211_get_buffered_bc(ah->hw, vif);
while (skb) {
- ath5k_tx_queue(sc->hw, skb, sc->cabq);
- skb = ieee80211_get_buffered_bc(sc->hw, vif);
+ ath5k_tx_queue(ah->hw, skb, ah->cabq);
+
+ if (ah->cabq->txq_len >= ah->cabq->txq_max)
+ break;
+
+ skb = ieee80211_get_buffered_bc(ah->hw, vif);
}
- sc->bsent++;
+ ah->bsent++;
}
/**
* ath5k_beacon_update_timers - update beacon timers
*
- * @sc: struct ath5k_softc pointer we are operating on
+ * @ah: struct ath5k_hw pointer we are operating on
* @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
* beacon timer update based on the current HW TSF.
*
@@ -1961,17 +1939,16 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* function to have it all together in one place.
*/
void
-ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
{
- struct ath5k_hw *ah = sc->ah;
u32 nexttbtt, intval, hw_tu, bc_tu;
u64 hw_tsf;
- intval = sc->bintval & AR5K_BEACON_PERIOD;
- if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
if (intval < 15)
- ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
intval);
}
if (WARN_ON(!intval))
@@ -1984,7 +1961,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
hw_tsf = ath5k_hw_get_tsf64(ah);
hw_tu = TSF_TO_TU(hw_tsf);
-#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
+#define FUDGE (AR5K_TUNE_SW_BEACON_RESP + 3)
/* We use FUDGE to make sure the next TBTT is ahead of the current TU.
* Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
* configuration we need to make sure it is bigger than that. */
@@ -2010,7 +1987,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
* automatically update the TSF and then we need to reconfigure
* the timers.
*/
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"need to wait for HW TSF sync\n");
return;
} else {
@@ -2025,7 +2002,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
}
#undef FUDGE
- sc->nexttbtt = nexttbtt;
+ ah->nexttbtt = nexttbtt;
intval |= AR5K_BEACON_ENA;
ath5k_hw_init_beacon(ah, nexttbtt, intval);
@@ -2035,20 +2012,20 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
* of this function
*/
if (bc_tsf == -1)
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"reconfigured timers based on HW TSF\n");
else if (bc_tsf == 0)
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"reset HW TSF and timers\n");
else
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"updated timers based on beacon TSF\n");
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
(unsigned long long) bc_tsf,
(unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
intval & AR5K_BEACON_PERIOD,
intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
@@ -2057,22 +2034,21 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
/**
* ath5k_beacon_config - Configure the beacon queues and interrupts
*
- * @sc: struct ath5k_softc pointer we are operating on
+ * @ah: struct ath5k_hw pointer we are operating on
*
* In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
* interrupts to detect TSF updates only.
*/
void
-ath5k_beacon_config(struct ath5k_softc *sc)
+ath5k_beacon_config(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
unsigned long flags;
- spin_lock_irqsave(&sc->block, flags);
- sc->bmisscount = 0;
- sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
+ spin_lock_irqsave(&ah->block, flags);
+ ah->bmisscount = 0;
+ ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
- if (sc->enable_beacon) {
+ if (ah->enable_beacon) {
/*
* In IBSS mode we use a self-linked tx descriptor and let the
* hardware send the beacons automatically. We have to load it
@@ -2080,50 +2056,50 @@ ath5k_beacon_config(struct ath5k_softc *sc)
* We use the SWBA interrupt only to keep track of the beacon
* timers in order to detect automatic TSF updates.
*/
- ath5k_beaconq_config(sc);
+ ath5k_beaconq_config(ah);
- sc->imask |= AR5K_INT_SWBA;
+ ah->imask |= AR5K_INT_SWBA;
- if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+ if (ah->opmode == NL80211_IFTYPE_ADHOC) {
if (ath5k_hw_hasveol(ah))
- ath5k_beacon_send(sc);
+ ath5k_beacon_send(ah);
} else
- ath5k_beacon_update_timers(sc, -1);
+ ath5k_beacon_update_timers(ah, -1);
} else {
- ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq);
+ ath5k_hw_stop_beacon_queue(ah, ah->bhalq);
}
- ath5k_hw_set_imr(ah, sc->imask);
+ ath5k_hw_set_imr(ah, ah->imask);
mmiowb();
- spin_unlock_irqrestore(&sc->block, flags);
+ spin_unlock_irqrestore(&ah->block, flags);
}
static void ath5k_tasklet_beacon(unsigned long data)
{
- struct ath5k_softc *sc = (struct ath5k_softc *) data;
+ struct ath5k_hw *ah = (struct ath5k_hw *) data;
/*
* Software beacon alert--time to send a beacon.
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
- * transmission time) in order to detect wether
+ * transmission time) in order to detect whether
* automatic TSF updates happened.
*/
- if (sc->opmode == NL80211_IFTYPE_ADHOC) {
- /* XXX: only if VEOL suppported */
- u64 tsf = ath5k_hw_get_tsf64(sc->ah);
- sc->nexttbtt += sc->bintval;
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ if (ah->opmode == NL80211_IFTYPE_ADHOC) {
+ /* XXX: only if VEOL supported */
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ ah->nexttbtt += ah->bintval;
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"SWBA nexttbtt: %x hw_tu: %x "
"TSF: %llx\n",
- sc->nexttbtt,
+ ah->nexttbtt,
TSF_TO_TU(tsf),
(unsigned long long) tsf);
} else {
- spin_lock(&sc->block);
- ath5k_beacon_send(sc);
- spin_unlock(&sc->block);
+ spin_lock(&ah->block);
+ ath5k_beacon_send(ah);
+ spin_unlock(&ah->block);
}
}
@@ -2140,12 +2116,12 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
/* run ANI only when full calibration is not active */
ah->ah_cal_next_ani = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
} else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
ah->ah_cal_next_full = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
- tasklet_schedule(&ah->ah_sc->calib);
+ tasklet_schedule(&ah->calib);
}
/* we could use SWI to generate enough interrupts to meet our
* calibration interval requirements, if necessary:
@@ -2153,44 +2129,43 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
}
static void
-ath5k_schedule_rx(struct ath5k_softc *sc)
+ath5k_schedule_rx(struct ath5k_hw *ah)
{
- sc->rx_pending = true;
- tasklet_schedule(&sc->rxtq);
+ ah->rx_pending = true;
+ tasklet_schedule(&ah->rxtq);
}
static void
-ath5k_schedule_tx(struct ath5k_softc *sc)
+ath5k_schedule_tx(struct ath5k_hw *ah)
{
- sc->tx_pending = true;
- tasklet_schedule(&sc->txtq);
+ ah->tx_pending = true;
+ tasklet_schedule(&ah->txtq);
}
-irqreturn_t
+static irqreturn_t
ath5k_intr(int irq, void *dev_id)
{
- struct ath5k_softc *sc = dev_id;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = dev_id;
enum ath5k_int status;
unsigned int counter = 1000;
- if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
+ if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) ||
((ath5k_get_bus_type(ah) != ATH_AHB) &&
!ath5k_hw_is_intr_pending(ah))))
return IRQ_NONE;
do {
ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
- ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
- status, sc->imask);
+ ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
+ status, ah->imask);
if (unlikely(status & AR5K_INT_FATAL)) {
/*
* Fatal errors are unrecoverable.
* Typically these are caused by DMA errors.
*/
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"fatal int, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
} else if (unlikely(status & AR5K_INT_RXORN)) {
/*
* Receive buffers are full. Either the bus is busy or
@@ -2201,45 +2176,44 @@ ath5k_intr(int irq, void *dev_id)
* We don't know exactly which versions need a reset -
* this guess is copied from the HAL.
*/
- sc->stats.rxorn_intr++;
+ ah->stats.rxorn_intr++;
if (ah->ah_mac_srev < AR5K_SREV_AR5212) {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"rx overrun, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
- }
- else
- ath5k_schedule_rx(sc);
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
+ } else
+ ath5k_schedule_rx(ah);
} else {
- if (status & AR5K_INT_SWBA) {
- tasklet_hi_schedule(&sc->beacontq);
- }
+ if (status & AR5K_INT_SWBA)
+ tasklet_hi_schedule(&ah->beacontq);
+
if (status & AR5K_INT_RXEOL) {
/*
* NB: the hardware should re-read the link when
* RXE bit is written, but it doesn't work at
* least on older hardware revs.
*/
- sc->stats.rxeol_intr++;
+ ah->stats.rxeol_intr++;
}
if (status & AR5K_INT_TXURN) {
/* bump tx trigger level */
ath5k_hw_update_tx_triglevel(ah, true);
}
if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
- ath5k_schedule_rx(sc);
+ ath5k_schedule_rx(ah);
if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
| AR5K_INT_TXERR | AR5K_INT_TXEOL))
- ath5k_schedule_tx(sc);
+ ath5k_schedule_tx(ah);
if (status & AR5K_INT_BMISS) {
/* TODO */
}
if (status & AR5K_INT_MIB) {
- sc->stats.mib_intr++;
+ ah->stats.mib_intr++;
ath5k_hw_update_mib_counters(ah);
ath5k_ani_mib_intr(ah);
}
if (status & AR5K_INT_GPIO)
- tasklet_schedule(&sc->rf_kill.toggleq);
+ tasklet_schedule(&ah->rf_kill.toggleq);
}
@@ -2248,11 +2222,11 @@ ath5k_intr(int irq, void *dev_id)
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
- if (sc->rx_pending || sc->tx_pending)
- ath5k_set_current_imask(sc);
+ if (ah->rx_pending || ah->tx_pending)
+ ath5k_set_current_imask(ah);
if (unlikely(!counter))
- ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+ ATH5K_WARN(ah, "too many interrupts, giving up for now\n");
ath5k_intr_calibration_poll(ah);
@@ -2266,28 +2240,27 @@ ath5k_intr(int irq, void *dev_id)
static void
ath5k_tasklet_calibrate(unsigned long data)
{
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = (void *)data;
/* Only full calibration for now */
ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
- ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
- ieee80211_frequency_to_channel(sc->curchan->center_freq),
- sc->curchan->hw_value);
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+ ieee80211_frequency_to_channel(ah->curchan->center_freq),
+ ah->curchan->hw_value);
if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
/*
* Rfgain is out of bounds, reset the chip
* to load new gain values.
*/
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "calibration, resetting\n");
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
}
- if (ath5k_hw_phy_calibrate(ah, sc->curchan))
- ATH5K_ERR(sc, "calibration of channel %u failed\n",
+ if (ath5k_hw_phy_calibrate(ah, ah->curchan))
+ ATH5K_ERR(ah, "calibration of channel %u failed\n",
ieee80211_frequency_to_channel(
- sc->curchan->center_freq));
+ ah->curchan->center_freq));
/* Noise floor calibration interrupts rx/tx path while I/Q calibration
* doesn't.
@@ -2306,8 +2279,7 @@ ath5k_tasklet_calibrate(unsigned long data)
static void
ath5k_tasklet_ani(unsigned long data)
{
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = (void *)data;
ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
ath5k_ani_calibration(ah);
@@ -2318,21 +2290,21 @@ ath5k_tasklet_ani(unsigned long data)
static void
ath5k_tx_complete_poll_work(struct work_struct *work)
{
- struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+ struct ath5k_hw *ah = container_of(work, struct ath5k_hw,
tx_complete_work.work);
struct ath5k_txq *txq;
int i;
bool needreset = false;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
- if (sc->txqs[i].setup) {
- txq = &sc->txqs[i];
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+ if (ah->txqs[i].setup) {
+ txq = &ah->txqs[i];
spin_lock_bh(&txq->lock);
if (txq->txq_len > 1) {
if (txq->txq_poll_mark) {
- ATH5K_DBG(sc, ATH5K_DEBUG_XMIT,
+ ATH5K_DBG(ah, ATH5K_DEBUG_XMIT,
"TX queue stuck %d\n",
txq->qnum);
needreset = true;
@@ -2348,14 +2320,14 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
}
if (needreset) {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"TX queues stuck, resetting\n");
- ath5k_reset(sc, NULL, true);
+ ath5k_reset(ah, NULL, true);
}
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
}
@@ -2364,16 +2336,16 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
* Initialization routines *
\*************************/
-int
-ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
+int __devinit
+ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
{
- struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_hw *hw = ah->hw;
struct ath_common *common;
int ret;
int csz;
/* Initialize driver private data */
- SET_IEEE80211_DEV(hw, sc->dev);
+ SET_IEEE80211_DEV(hw, ah->dev);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
@@ -2396,39 +2368,30 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
* Mark the device as detached to avoid processing
* interrupts until setup is complete.
*/
- __set_bit(ATH_STAT_INVALID, sc->status);
+ __set_bit(ATH_STAT_INVALID, ah->status);
- sc->opmode = NL80211_IFTYPE_STATION;
- sc->bintval = 1000;
- mutex_init(&sc->lock);
- spin_lock_init(&sc->rxbuflock);
- spin_lock_init(&sc->txbuflock);
- spin_lock_init(&sc->block);
- spin_lock_init(&sc->irqlock);
+ ah->opmode = NL80211_IFTYPE_STATION;
+ ah->bintval = 1000;
+ mutex_init(&ah->lock);
+ spin_lock_init(&ah->rxbuflock);
+ spin_lock_init(&ah->txbuflock);
+ spin_lock_init(&ah->block);
+ spin_lock_init(&ah->irqlock);
/* Setup interrupt handler */
- ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+ ret = request_irq(ah->irq, ath5k_intr, IRQF_SHARED, "ath", ah);
if (ret) {
- ATH5K_ERR(sc, "request_irq failed\n");
+ ATH5K_ERR(ah, "request_irq failed\n");
goto err;
}
- /* If we passed the test, malloc an ath5k_hw struct */
- sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
- if (!sc->ah) {
- ret = -ENOMEM;
- ATH5K_ERR(sc, "out of memory\n");
- goto err_irq;
- }
-
- sc->ah->ah_sc = sc;
- sc->ah->ah_iobase = sc->iobase;
- common = ath5k_hw_common(sc->ah);
+ common = ath5k_hw_common(ah);
common->ops = &ath5k_common_ops;
common->bus_ops = bus_ops;
- common->ah = sc->ah;
+ common->ah = ah;
common->hw = hw;
- common->priv = sc;
+ common->priv = ah;
+ common->clockrate = 40;
/*
* Cache line size is used to size and align various
@@ -2440,12 +2403,12 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
spin_lock_init(&common->cc_lock);
/* Initialize device */
- ret = ath5k_hw_init(sc);
+ ret = ath5k_hw_init(ah);
if (ret)
- goto err_free_ah;
+ goto err_irq;
/* set up multi-rate retry capabilities */
- if (sc->ah->ah_version == AR5K_AR5212) {
+ if (ah->ah_version == AR5K_AR5212) {
hw->max_rates = 4;
hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT,
AR5K_INIT_RETRY_LONG);
@@ -2458,77 +2421,74 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
if (ret)
goto err_ah;
- ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
- sc->ah->ah_mac_srev,
- sc->ah->ah_phy_revision);
+ ATH5K_INFO(ah, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_MAC, ah->ah_mac_srev),
+ ah->ah_mac_srev,
+ ah->ah_phy_revision);
- if (!sc->ah->ah_single_chip) {
+ if (!ah->ah_single_chip) {
/* Single chip radio (!RF5111) */
- if (sc->ah->ah_radio_5ghz_revision &&
- !sc->ah->ah_radio_2ghz_revision) {
+ if (ah->ah_radio_5ghz_revision &&
+ !ah->ah_radio_2ghz_revision) {
/* No 5GHz support -> report 2GHz radio */
if (!test_bit(AR5K_MODE_11A,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
/* No 2GHz support (5110 and some
- * 5Ghz only cards) -> report 5Ghz radio */
+ * 5GHz only cards) -> report 5GHz radio */
} else if (!test_bit(AR5K_MODE_11B,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
/* Multiband radio */
} else {
- ATH5K_INFO(sc, "RF%s multiband radio found"
+ ATH5K_INFO(ah, "RF%s multiband radio found"
" (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
}
}
/* Multi chip radio (RF5111 - RF2111) ->
* report both 2GHz/5GHz radios */
- else if (sc->ah->ah_radio_5ghz_revision &&
- sc->ah->ah_radio_2ghz_revision){
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ else if (ah->ah_radio_5ghz_revision &&
+ ah->ah_radio_2ghz_revision) {
+ ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
+ ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_2ghz_revision),
- sc->ah->ah_radio_2ghz_revision);
+ ah->ah_radio_2ghz_revision),
+ ah->ah_radio_2ghz_revision);
}
}
- ath5k_debug_init_device(sc);
+ ath5k_debug_init_device(ah);
/* ready to process interrupts */
- __clear_bit(ATH_STAT_INVALID, sc->status);
+ __clear_bit(ATH_STAT_INVALID, ah->status);
return 0;
err_ah:
- ath5k_hw_deinit(sc->ah);
-err_free_ah:
- kfree(sc->ah);
+ ath5k_hw_deinit(ah);
err_irq:
- free_irq(sc->irq, sc);
+ free_irq(ah->irq, ah);
err:
return ret;
}
static int
-ath5k_stop_locked(struct ath5k_softc *sc)
+ath5k_stop_locked(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
- test_bit(ATH_STAT_INVALID, sc->status));
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "invalid %u\n",
+ test_bit(ATH_STAT_INVALID, ah->status));
/*
* Shutdown the hardware and driver:
@@ -2545,37 +2505,36 @@ ath5k_stop_locked(struct ath5k_softc *sc)
* Note that some of this work is not possible if the
* hardware is gone (invalid).
*/
- ieee80211_stop_queues(sc->hw);
+ ieee80211_stop_queues(ah->hw);
- if (!test_bit(ATH_STAT_INVALID, sc->status)) {
- ath5k_led_off(sc);
+ if (!test_bit(ATH_STAT_INVALID, ah->status)) {
+ ath5k_led_off(ah);
ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->irq);
- ath5k_rx_stop(sc);
+ synchronize_irq(ah->irq);
+ ath5k_rx_stop(ah);
ath5k_hw_dma_stop(ah);
- ath5k_drain_tx_buffs(sc);
+ ath5k_drain_tx_buffs(ah);
ath5k_hw_phy_disable(ah);
}
return 0;
}
-int
-ath5k_init_hw(struct ath5k_softc *sc)
+int ath5k_start(struct ieee80211_hw *hw)
{
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_common *common = ath5k_hw_common(ah);
int ret, i;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "mode %d\n", ah->opmode);
/*
* Stop anything previously setup. This is safe
* no matter this is the first time through or not.
*/
- ath5k_stop_locked(sc);
+ ath5k_stop_locked(ah);
/*
* The basic interface to setting the hardware in a good
@@ -2584,12 +2543,12 @@ ath5k_init_hw(struct ath5k_softc *sc)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- sc->curchan = sc->hw->conf.channel;
- sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+ ah->curchan = ah->hw->conf.channel;
+ ah->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
- ret = ath5k_reset(sc, NULL, false);
+ ret = ath5k_reset(ah, NULL, false);
if (ret)
goto done;
@@ -2606,29 +2565,29 @@ ath5k_init_hw(struct ath5k_softc *sc)
* rate */
ah->ah_ack_bitrate_high = true;
- for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
- sc->bslot[i] = NULL;
+ for (i = 0; i < ARRAY_SIZE(ah->bslot); i++)
+ ah->bslot[i] = NULL;
ret = 0;
done:
mmiowb();
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
return ret;
}
-static void stop_tasklets(struct ath5k_softc *sc)
+static void ath5k_stop_tasklets(struct ath5k_hw *ah)
{
- sc->rx_pending = false;
- sc->tx_pending = false;
- tasklet_kill(&sc->rxtq);
- tasklet_kill(&sc->txtq);
- tasklet_kill(&sc->calib);
- tasklet_kill(&sc->beacontq);
- tasklet_kill(&sc->ani_tasklet);
+ ah->rx_pending = false;
+ ah->tx_pending = false;
+ tasklet_kill(&ah->rxtq);
+ tasklet_kill(&ah->txtq);
+ tasklet_kill(&ah->calib);
+ tasklet_kill(&ah->beacontq);
+ tasklet_kill(&ah->ani_tasklet);
}
/*
@@ -2637,14 +2596,14 @@ static void stop_tasklets(struct ath5k_softc *sc)
* if another thread does a system call and the thread doing the
* stop is preempted).
*/
-int
-ath5k_stop_hw(struct ath5k_softc *sc)
+void ath5k_stop(struct ieee80211_hw *hw)
{
+ struct ath5k_hw *ah = hw->priv;
int ret;
- mutex_lock(&sc->lock);
- ret = ath5k_stop_locked(sc);
- if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+ mutex_lock(&ah->lock);
+ ret = ath5k_stop_locked(ah);
+ if (ret == 0 && !test_bit(ATH_STAT_INVALID, ah->status)) {
/*
* Don't set the card in full sleep mode!
*
@@ -2665,82 +2624,78 @@ ath5k_stop_hw(struct ath5k_softc *sc)
* and Sam's HAL do anyway). Instead Perform a full reset
* on the device (same as initial state after attach) and
* leave it idle (keep MAC/BB on warm reset) */
- ret = ath5k_hw_on_hold(sc->ah);
+ ret = ath5k_hw_on_hold(ah);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"putting device to sleep\n");
}
mmiowb();
- mutex_unlock(&sc->lock);
-
- stop_tasklets(sc);
+ mutex_unlock(&ah->lock);
- cancel_delayed_work_sync(&sc->tx_complete_work);
+ ath5k_stop_tasklets(ah);
- ath5k_rfkill_hw_stop(sc->ah);
+ cancel_delayed_work_sync(&ah->tx_complete_work);
- return ret;
+ ath5k_rfkill_hw_stop(ah);
}
/*
* Reset the hardware. If chan is not NULL, then also pause rx/tx
* and change to the given channel.
*
- * This should be called with sc->lock.
+ * This should be called with ah->lock.
*/
static int
-ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
bool skip_pcu)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
int ret, ani_mode;
bool fast;
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n");
ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->irq);
- stop_tasklets(sc);
+ synchronize_irq(ah->irq);
+ ath5k_stop_tasklets(ah);
/* Save ani mode and disable ANI during
* reset. If we don't we might get false
* PHY error interrupts. */
- ani_mode = ah->ah_sc->ani_state.ani_mode;
+ ani_mode = ah->ani_state.ani_mode;
ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
/* We are going to empty hw queues
* so we should also free any remaining
* tx buffers */
- ath5k_drain_tx_buffs(sc);
+ ath5k_drain_tx_buffs(ah);
if (chan)
- sc->curchan = chan;
+ ah->curchan = chan;
fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast,
- skip_pcu);
+ ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu);
if (ret) {
- ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+ ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret);
goto err;
}
- ret = ath5k_rx_start(sc);
+ ret = ath5k_rx_start(ah);
if (ret) {
- ATH5K_ERR(sc, "can't start recv logic\n");
+ ATH5K_ERR(ah, "can't start recv logic\n");
goto err;
}
ath5k_ani_init(ah, ani_mode);
- ah->ah_cal_next_full = jiffies;
+ ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100);
ah->ah_cal_next_ani = jiffies;
ah->ah_cal_next_nf = jiffies;
ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
/* clear survey data and cycle counters */
- memset(&sc->survey, 0, sizeof(sc->survey));
+ memset(&ah->survey, 0, sizeof(ah->survey));
spin_lock_bh(&common->cc_lock);
ath_hw_cycle_counters_update(common);
memset(&common->cc_survey, 0, sizeof(common->cc_survey));
@@ -2756,12 +2711,12 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
*
* XXX needed?
*/
-/* ath5k_chan_change(sc, c); */
+/* ath5k_chan_change(ah, c); */
- ath5k_beacon_config(sc);
+ ath5k_beacon_config(ah);
/* intrs are enabled by ath5k_beacon_config */
- ieee80211_wake_queues(sc->hw);
+ ieee80211_wake_queues(ah->hw);
return 0;
err:
@@ -2770,20 +2725,19 @@ err:
static void ath5k_reset_work(struct work_struct *work)
{
- struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+ struct ath5k_hw *ah = container_of(work, struct ath5k_hw,
reset_work);
- mutex_lock(&sc->lock);
- ath5k_reset(sc, NULL, true);
- mutex_unlock(&sc->lock);
+ mutex_lock(&ah->lock);
+ ath5k_reset(ah, NULL, true);
+ mutex_unlock(&ah->lock);
}
-static int
+static int __devinit
ath5k_init(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
struct ath5k_txq *txq;
u8 mac[ETH_ALEN] = {};
@@ -2802,26 +2756,26 @@ ath5k_init(struct ieee80211_hw *hw)
if (ret < 0)
goto err;
if (ret > 0)
- __set_bit(ATH_STAT_MRRETRY, sc->status);
+ __set_bit(ATH_STAT_MRRETRY, ah->status);
/*
* Collect the channel list. The 802.11 layer
- * is resposible for filtering this list based
+ * is responsible for filtering this list based
* on settings like the phy mode and regulatory
* domain restrictions.
*/
ret = ath5k_setup_bands(hw);
if (ret) {
- ATH5K_ERR(sc, "can't get channels\n");
+ ATH5K_ERR(ah, "can't get channels\n");
goto err;
}
/*
* Allocate tx+rx descriptors and populate the lists.
*/
- ret = ath5k_desc_alloc(sc);
+ ret = ath5k_desc_alloc(ah);
if (ret) {
- ATH5K_ERR(sc, "can't allocate descriptors\n");
+ ATH5K_ERR(ah, "can't allocate descriptors\n");
goto err;
}
@@ -2833,14 +2787,14 @@ ath5k_init(struct ieee80211_hw *hw)
*/
ret = ath5k_beaconq_setup(ah);
if (ret < 0) {
- ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+ ATH5K_ERR(ah, "can't setup a beacon xmit queue\n");
goto err_desc;
}
- sc->bhalq = ret;
- sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
- if (IS_ERR(sc->cabq)) {
- ATH5K_ERR(sc, "can't setup cab queue\n");
- ret = PTR_ERR(sc->cabq);
+ ah->bhalq = ret;
+ ah->cabq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_CAB, 0);
+ if (IS_ERR(ah->cabq)) {
+ ATH5K_ERR(ah, "can't setup cab queue\n");
+ ret = PTR_ERR(ah->cabq);
goto err_bhal;
}
@@ -2849,97 +2803,96 @@ ath5k_init(struct ieee80211_hw *hw)
if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) {
/* This order matches mac80211's queue priority, so we can
* directly use the mac80211 queue number without any mapping */
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
hw->queues = 4;
} else {
/* older hardware (5210) can only support one data queue */
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
hw->queues = 1;
}
- tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
- tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
- tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
- tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
- tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
+ tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah);
+ tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah);
+ tasklet_init(&ah->calib, ath5k_tasklet_calibrate, (unsigned long)ah);
+ tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah);
+ tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah);
- INIT_WORK(&sc->reset_work, ath5k_reset_work);
- INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
+ INIT_WORK(&ah->reset_work, ath5k_reset_work);
+ INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work);
ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
if (ret) {
- ATH5K_ERR(sc, "unable to read address from EEPROM\n");
+ ATH5K_ERR(ah, "unable to read address from EEPROM\n");
goto err_queues;
}
SET_IEEE80211_PERM_ADDR(hw, mac);
- memcpy(&sc->lladdr, mac, ETH_ALEN);
/* All MAC address bits matter for ACKs */
- ath5k_update_bssid_mask_and_opmode(sc, NULL);
+ ath5k_update_bssid_mask_and_opmode(ah, NULL);
regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
if (ret) {
- ATH5K_ERR(sc, "can't initialize regulatory system\n");
+ ATH5K_ERR(ah, "can't initialize regulatory system\n");
goto err_queues;
}
ret = ieee80211_register_hw(hw);
if (ret) {
- ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+ ATH5K_ERR(ah, "can't register ieee80211 hw\n");
goto err_queues;
}
if (!ath_is_world_regd(regulatory))
regulatory_hint(hw->wiphy, regulatory->alpha2);
- ath5k_init_leds(sc);
+ ath5k_init_leds(ah);
- ath5k_sysfs_register(sc);
+ ath5k_sysfs_register(ah);
return 0;
err_queues:
- ath5k_txq_release(sc);
+ ath5k_txq_release(ah);
err_bhal:
- ath5k_hw_release_tx_queue(ah, sc->bhalq);
+ ath5k_hw_release_tx_queue(ah, ah->bhalq);
err_desc:
- ath5k_desc_free(sc);
+ ath5k_desc_free(ah);
err:
return ret;
}
void
-ath5k_deinit_softc(struct ath5k_softc *sc)
+ath5k_deinit_ah(struct ath5k_hw *ah)
{
- struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_hw *hw = ah->hw;
/*
* NB: the order of these is important:
@@ -2955,23 +2908,23 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
* Other than that, it's straightforward...
*/
ieee80211_unregister_hw(hw);
- ath5k_desc_free(sc);
- ath5k_txq_release(sc);
- ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
- ath5k_unregister_leds(sc);
+ ath5k_desc_free(ah);
+ ath5k_txq_release(ah);
+ ath5k_hw_release_tx_queue(ah, ah->bhalq);
+ ath5k_unregister_leds(ah);
- ath5k_sysfs_unregister(sc);
+ ath5k_sysfs_unregister(ah);
/*
* NB: can't reclaim these until after ieee80211_ifdetach
* returns because we'll get called back to reclaim node
* state and potentially want to use them.
*/
- ath5k_hw_deinit(sc->ah);
- free_irq(sc->irq, sc);
+ ath5k_hw_deinit(ah);
+ free_irq(ah->irq, ah);
}
bool
-ath_any_vif_assoc(struct ath5k_softc *sc)
+ath5k_any_vif_assoc(struct ath5k_hw *ah)
{
struct ath5k_vif_iter_data iter_data;
iter_data.hw_macaddr = NULL;
@@ -2979,16 +2932,15 @@ ath_any_vif_assoc(struct ath5k_softc *sc)
iter_data.need_set_hw_addr = false;
iter_data.found_active = true;
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+ ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
&iter_data);
return iter_data.any_assoc;
}
void
-set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
u32 rfilt;
rfilt = ath5k_hw_get_rx_filter(ah);
if (enable)
@@ -2996,5 +2948,5 @@ set_beacon_filter(struct ieee80211_hw *hw, bool enable)
else
rfilt &= ~AR5K_RX_FILTER_BEACON;
ath5k_hw_set_rx_filter(ah, rfilt);
- sc->filter_flags = rfilt;
+ ah->filter_flags = rfilt;
}
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index b294f33..6c94c7f 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -38,29 +38,27 @@
/*
* Definitions for the Atheros Wireless LAN controller driver.
*/
-#ifndef _DEV_ATH_ATHVAR_H
-#define _DEV_ATH_ATHVAR_H
-
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/wireless.h>
-#include <linux/if_ether.h>
-#include <linux/leds.h>
-#include <linux/rfkill.h>
-#include <linux/workqueue.h>
-
-#include "ath5k.h"
-#include "debug.h"
-#include "ani.h"
-
-#include "../regd.h"
-#include "../ath.h"
+#ifndef _DEV_ATH5K_BASE_H
+#define _DEV_ATH5K_BASE_H
+
+struct ieee80211_vif;
+struct ieee80211_hw;
+struct ath5k_hw;
+struct ath5k_txq;
+struct ieee80211_channel;
+struct ath_bus_ops;
+enum nl80211_iftype;
+
+enum ath5k_srev_type {
+ AR5K_VERSION_MAC,
+ AR5K_VERSION_RAD,
+};
-#define ATH_RXBUF 40 /* number of RX buffers */
-#define ATH_TXBUF 200 /* number of TX buffers */
-#define ATH_BCBUF 4 /* number of beacon buffers */
-#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
-#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
+struct ath5k_srev_name {
+ const char *sr_name;
+ enum ath5k_srev_type sr_type;
+ u_int sr_val;
+};
struct ath5k_buf {
struct list_head list;
@@ -70,199 +68,11 @@ struct ath5k_buf {
dma_addr_t skbaddr;/* physical addr of skb data */
};
-/*
- * Data transmit queue state. One of these exists for each
- * hardware transmit queue. Packets sent to us from above
- * are assigned to queues based on their priority. Not all
- * devices support a complete set of hardware transmit queues.
- * For those devices the array sc_ac2q will map multiple
- * priorities to fewer hardware queues (typically all to one
- * hardware queue).
- */
-struct ath5k_txq {
- unsigned int qnum; /* hardware q number */
- u32 *link; /* link ptr in last TX desc */
- struct list_head q; /* transmit queue */
- spinlock_t lock; /* lock on q and link */
- bool setup;
- int txq_len; /* number of queued buffers */
- int txq_max; /* max allowed num of queued buffers */
- bool txq_poll_mark;
- unsigned int txq_stuck; /* informational counter */
-};
-
-#define ATH5K_LED_MAX_NAME_LEN 31
-
-/*
- * State for LED triggers
- */
-struct ath5k_led
-{
- char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */
- struct ath5k_softc *sc; /* driver state */
- struct led_classdev led_dev; /* led classdev */
-};
-
-/* Rfkill */
-struct ath5k_rfkill {
- /* GPIO PIN for rfkill */
- u16 gpio;
- /* polarity of rfkill GPIO PIN */
- bool polarity;
- /* RFKILL toggle tasklet */
- struct tasklet_struct toggleq;
-};
-
-/* statistics */
-struct ath5k_statistics {
- /* antenna use */
- unsigned int antenna_rx[5]; /* frames count per antenna RX */
- unsigned int antenna_tx[5]; /* frames count per antenna TX */
-
- /* frame errors */
- unsigned int rx_all_count; /* all RX frames, including errors */
- unsigned int tx_all_count; /* all TX frames, including errors */
- unsigned int rx_bytes_count; /* all RX bytes, including errored pks
- * and the MAC headers for each packet
- */
- unsigned int tx_bytes_count; /* all TX bytes, including errored pkts
- * and the MAC headers and padding for
- * each packet.
- */
- unsigned int rxerr_crc;
- unsigned int rxerr_phy;
- unsigned int rxerr_phy_code[32];
- unsigned int rxerr_fifo;
- unsigned int rxerr_decrypt;
- unsigned int rxerr_mic;
- unsigned int rxerr_proc;
- unsigned int rxerr_jumbo;
- unsigned int txerr_retry;
- unsigned int txerr_fifo;
- unsigned int txerr_filt;
-
- /* MIB counters */
- unsigned int ack_fail;
- unsigned int rts_fail;
- unsigned int rts_ok;
- unsigned int fcs_error;
- unsigned int beacons;
-
- unsigned int mib_intr;
- unsigned int rxorn_intr;
- unsigned int rxeol_intr;
-};
-
-#if CHAN_DEBUG
-#define ATH_CHAN_MAX (26+26+26+200+200)
-#else
-#define ATH_CHAN_MAX (14+14+14+252+20)
-#endif
-
struct ath5k_vif {
bool assoc; /* are we associated or not */
enum nl80211_iftype opmode;
int bslot;
struct ath5k_buf *bbuf; /* beacon buffer */
- u8 lladdr[ETH_ALEN];
-};
-
-/* Software Carrier, keeps track of the driver state
- * associated with an instance of a device */
-struct ath5k_softc {
- struct pci_dev *pdev;
- struct device *dev; /* for dma mapping */
- int irq;
- u16 devid;
- void __iomem *iobase; /* address of the device */
- struct mutex lock; /* dev-level lock */
- struct ieee80211_hw *hw; /* IEEE 802.11 common */
- struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
- struct ieee80211_channel channels[ATH_CHAN_MAX];
- struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
- s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
- enum nl80211_iftype opmode;
- struct ath5k_hw *ah; /* Atheros HW */
-
-#ifdef CONFIG_ATH5K_DEBUG
- struct ath5k_dbg_info debug; /* debug info */
-#endif /* CONFIG_ATH5K_DEBUG */
-
- struct ath5k_buf *bufptr; /* allocated buffer ptr */
- struct ath5k_desc *desc; /* TX/RX descriptors */
- dma_addr_t desc_daddr; /* DMA (physical) address */
- size_t desc_len; /* size of TX/RX descriptors */
-
- DECLARE_BITMAP(status, 6);
-#define ATH_STAT_INVALID 0 /* disable hardware accesses */
-#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
-#define ATH_STAT_PROMISC 2
-#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
-#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
-#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */
-
- unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
- struct ieee80211_channel *curchan; /* current h/w channel */
-
- u16 nvifs;
-
- enum ath5k_int imask; /* interrupt mask copy */
-
- spinlock_t irqlock;
- bool rx_pending; /* rx tasklet pending */
- bool tx_pending; /* tx tasklet pending */
-
- u8 lladdr[ETH_ALEN];
- u8 bssidmask[ETH_ALEN];
-
- unsigned int led_pin, /* GPIO pin for driving LED */
- led_on; /* pin setting for LED on */
-
- struct work_struct reset_work; /* deferred chip reset */
-
- unsigned int rxbufsize; /* rx size based on mtu */
- struct list_head rxbuf; /* receive buffer */
- spinlock_t rxbuflock;
- u32 *rxlink; /* link ptr in last RX desc */
- struct tasklet_struct rxtq; /* rx intr tasklet */
- struct ath5k_led rx_led; /* rx led */
-
- struct list_head txbuf; /* transmit buffer */
- spinlock_t txbuflock;
- unsigned int txbuf_len; /* buf count in txbuf list */
- struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
- struct tasklet_struct txtq; /* tx intr tasklet */
- struct ath5k_led tx_led; /* tx led */
-
- struct ath5k_rfkill rf_kill;
-
- struct tasklet_struct calib; /* calibration tasklet */
-
- spinlock_t block; /* protects beacon */
- struct tasklet_struct beacontq; /* beacon intr tasklet */
- struct list_head bcbuf; /* beacon buffer */
- struct ieee80211_vif *bslot[ATH_BCBUF];
- u16 num_ap_vifs;
- u16 num_adhoc_vifs;
- unsigned int bhalq, /* SW q for outgoing beacons */
- bmisscount, /* missed beacon transmits */
- bintval, /* beacon interval in TU */
- bsent;
- unsigned int nexttbtt; /* next beacon time in TU */
- struct ath5k_txq *cabq; /* content after beacon */
-
- int power_level; /* Requested tx power in dbm */
- bool assoc; /* associate state */
- bool enable_beacon; /* true if beacons are on */
-
- struct ath5k_statistics stats;
-
- struct ath5k_ani_state ani_state;
- struct tasklet_struct ani_tasklet; /* ANI calibration */
-
- struct delayed_work tx_complete_work;
-
- struct survey_info survey; /* collected survey info */
};
struct ath5k_vif_iter_data {
@@ -275,12 +85,35 @@ struct ath5k_vif_iter_data {
enum nl80211_iftype opmode;
int n_stas;
};
+
void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
+bool ath5k_any_vif_assoc(struct ath5k_hw *ah);
+
+int ath5k_start(struct ieee80211_hw *hw);
+void ath5k_stop(struct ieee80211_hw *hw);
+
+void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf);
+int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void ath5k_beacon_config(struct ath5k_hw *ah);
+void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
+ struct ieee80211_vif *vif);
+int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
+void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
+void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
+void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ath5k_txq *txq);
+
+const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
+
+int ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops);
+void ath5k_deinit_ah(struct ath5k_hw *ah);
+/* Check whether BSSID mask is supported */
+#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212)
-#define ath5k_hw_hasbssidmask(_ah) \
- (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
-#define ath5k_hw_hasveol(_ah) \
- (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+/* Check whether virtual EOL is supported */
+#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210)
-#endif
+#endif /* _DEV_ATH5K_BASE_H */
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index 7dd88e1..810fba9 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -24,7 +24,7 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
+#include "../regd.h"
/*
* Fill the capabilities struct
@@ -52,8 +52,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
__set_bit(AR5K_MODE_11A, caps->cap_mode);
} else {
/*
- * XXX The tranceiver supports frequencies from 4920 to 6100GHz
- * XXX and from 2312 to 2732GHz. There are problems with the
+ * XXX The transceiver supports frequencies from 4920 to 6100MHz
+ * XXX and from 2312 to 2732MHz. There are problems with the
* XXX current ieee80211 implementation because the IEEE
* XXX channel mapping does not support negative channel
* XXX numbers (2312MHz is channel -19). Of course, this
@@ -112,51 +112,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
return 0;
}
-/* Main function used by the driver part to check caps */
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
- enum ath5k_capability_type cap_type,
- u32 capability, u32 *result)
-{
- switch (cap_type) {
- case AR5K_CAP_NUM_TXQUEUES:
- if (result) {
- if (ah->ah_version == AR5K_AR5210)
- *result = AR5K_NUM_TX_QUEUES_NOQCU;
- else
- *result = AR5K_NUM_TX_QUEUES;
- goto yes;
- }
- case AR5K_CAP_VEOL:
- goto yes;
- case AR5K_CAP_COMPRESSION:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- case AR5K_CAP_BURST:
- goto yes;
- case AR5K_CAP_TPC:
- goto yes;
- case AR5K_CAP_BSSIDMASK:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- case AR5K_CAP_XR:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- default:
- goto no;
- }
-
-no:
- return -EINVAL;
-yes:
- return 0;
-}
-
/*
* TODO: Following functions should be part of a new function
* set_capability
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 0bf7313..8c5ce8b 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -57,20 +57,20 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*/
+#include <linux/export.h>
+#include <linux/moduleparam.h>
-#include "base.h"
+#include <linux/seq_file.h>
+#include <linux/list.h>
#include "debug.h"
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
static unsigned int ath5k_debug;
module_param_named(debug, ath5k_debug, uint, 0);
-#ifdef CONFIG_ATH5K_DEBUG
-
-#include <linux/seq_file.h>
-#include "reg.h"
-#include "ani.h"
-
static int ath5k_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
@@ -157,10 +157,10 @@ static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
static int reg_show(struct seq_file *seq, void *p)
{
- struct ath5k_softc *sc = seq->private;
+ struct ath5k_hw *ah = seq->private;
struct reg *r = p;
seq_printf(seq, "%-25s0x%08x\n", r->name,
- ath5k_hw_reg_read(sc->ah, r->addr));
+ ath5k_hw_reg_read(ah, r->addr));
return 0;
}
@@ -197,43 +197,42 @@ static const struct file_operations fops_registers = {
static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = file->private_data;
char buf[500];
unsigned int len = 0;
unsigned int v;
u64 tsf;
- v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_BEACON);
+ len += snprintf(buf + len, sizeof(buf) - len,
"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
- "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
+ "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
- "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
+ "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER0 (TBTT)", v, v);
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER1 (DMA)", v, v >> 3);
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER2 (SWBA)", v, v >> 3);
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER3 (ATIM)", v, v);
- tsf = ath5k_hw_get_tsf64(sc->ah);
- len += snprintf(buf+len, sizeof(buf)-len,
+ tsf = ath5k_hw_get_tsf64(ah);
+ len += snprintf(buf + len, sizeof(buf) - len,
"TSF\t\t0x%016llx\tTU: %08x\n",
(unsigned long long)tsf, TSF_TO_TU(tsf));
@@ -247,8 +246,7 @@ static ssize_t write_file_beacon(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
@@ -279,9 +277,9 @@ static ssize_t write_file_reset(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ struct ath5k_hw *ah = file->private_data;
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
return count;
}
@@ -318,23 +316,23 @@ static const struct {
static ssize_t read_file_debug(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
unsigned int i;
- len += snprintf(buf+len, sizeof(buf)-len,
- "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%10s %c 0x%08x - %s\n", dbg_info[i].name,
- sc->debug.level & dbg_info[i].level ? '+' : ' ',
+ ah->debug.level & dbg_info[i].level ? '+' : ' ',
dbg_info[i].level, dbg_info[i].desc);
}
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%10s %c 0x%08x - %s\n", dbg_info[i].name,
- sc->debug.level == dbg_info[i].level ? '+' : ' ',
+ ah->debug.level == dbg_info[i].level ? '+' : ' ',
dbg_info[i].level, dbg_info[i].desc);
if (len > sizeof(buf))
@@ -347,7 +345,7 @@ static ssize_t write_file_debug(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
unsigned int i;
char buf[20];
@@ -357,7 +355,7 @@ static ssize_t write_file_debug(struct file *file,
for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
if (strncmp(buf, dbg_info[i].name,
strlen(dbg_info[i].name)) == 0) {
- sc->debug.level ^= dbg_info[i].level; /* toggle bit */
+ ah->debug.level ^= dbg_info[i].level; /* toggle bit */
break;
}
}
@@ -378,66 +376,66 @@ static const struct file_operations fops_debug = {
static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
unsigned int i;
unsigned int v;
- len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
- sc->ah->ah_ant_mode);
- len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
- sc->ah->ah_def_ant);
- len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
- sc->ah->ah_tx_ant);
+ len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
+ ah->ah_ant_mode);
+ len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
+ ah->ah_def_ant);
+ len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
+ ah->ah_tx_ant);
- len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n");
- for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
+ for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
+ len += snprintf(buf + len, sizeof(buf) - len,
"[antenna %d]\t%d\t%d\n",
- i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
+ i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
}
- len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
- sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);
+ len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
+ ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
- v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
- v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
(v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
if (len > sizeof(buf))
@@ -450,7 +448,7 @@ static ssize_t write_file_antenna(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
unsigned int i;
char buf[20];
@@ -458,18 +456,18 @@ static ssize_t write_file_antenna(struct file *file,
return -EFAULT;
if (strncmp(buf, "diversity", 9) == 0) {
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
printk(KERN_INFO "ath5k debug: enable diversity\n");
} else if (strncmp(buf, "fixed-a", 7) == 0) {
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
} else if (strncmp(buf, "fixed-b", 7) == 0) {
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
printk(KERN_INFO "ath5k debug: fixed antenna B\n");
} else if (strncmp(buf, "clear", 5) == 0) {
- for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
- sc->stats.antenna_rx[i] = 0;
- sc->stats.antenna_tx[i] = 0;
+ for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
+ ah->stats.antenna_rx[i] = 0;
+ ah->stats.antenna_tx[i] = 0;
}
printk(KERN_INFO "ath5k debug: cleared antenna stats\n");
}
@@ -489,42 +487,42 @@ static const struct file_operations fops_antenna = {
static ssize_t read_file_misc(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
- u32 filt = ath5k_hw_get_rx_filter(sc->ah);
+ u32 filt = ath5k_hw_get_rx_filter(ah);
- len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
- sc->bssidmask);
- len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
+ len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
+ ah->bssidmask);
+ len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
filt);
if (filt & AR5K_RX_FILTER_UCAST)
- len += snprintf(buf+len, sizeof(buf)-len, " UCAST");
+ len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
if (filt & AR5K_RX_FILTER_MCAST)
- len += snprintf(buf+len, sizeof(buf)-len, " MCAST");
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
if (filt & AR5K_RX_FILTER_BCAST)
- len += snprintf(buf+len, sizeof(buf)-len, " BCAST");
+ len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
if (filt & AR5K_RX_FILTER_CONTROL)
- len += snprintf(buf+len, sizeof(buf)-len, " CONTROL");
+ len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
if (filt & AR5K_RX_FILTER_BEACON)
- len += snprintf(buf+len, sizeof(buf)-len, " BEACON");
+ len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
if (filt & AR5K_RX_FILTER_PROM)
- len += snprintf(buf+len, sizeof(buf)-len, " PROM");
+ len += snprintf(buf + len, sizeof(buf) - len, " PROM");
if (filt & AR5K_RX_FILTER_XRPOLL)
- len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL");
+ len += snprintf(buf + len, sizeof(buf) - len, " XRPOLL");
if (filt & AR5K_RX_FILTER_PROBEREQ)
- len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ");
+ len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
if (filt & AR5K_RX_FILTER_PHYERR_5212)
- len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212");
+ len += snprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
if (filt & AR5K_RX_FILTER_RADARERR_5212)
- len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212");
+ len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
if (filt & AR5K_RX_FILTER_PHYERR_5211)
- snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
+ snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
if (filt & AR5K_RX_FILTER_RADARERR_5211)
- len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211");
+ len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
- len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n",
- ath_opmode_to_string(sc->opmode), sc->opmode);
+ len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
+ ath_opmode_to_string(ah->opmode), ah->opmode);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -544,71 +542,71 @@ static const struct file_operations fops_misc = {
static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_statistics *st = &sc->stats;
+ struct ath5k_hw *ah = file->private_data;
+ struct ath5k_statistics *st = &ah->stats;
char buf[700];
unsigned int len = 0;
int i;
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"RX\n---------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
st->rxerr_crc,
st->rx_all_count > 0 ?
- st->rxerr_crc*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
+ st->rxerr_crc * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
st->rxerr_phy,
st->rx_all_count > 0 ?
- st->rxerr_phy*100/st->rx_all_count : 0);
+ st->rxerr_phy * 100 / st->rx_all_count : 0);
for (i = 0; i < 32; i++) {
if (st->rxerr_phy_code[i])
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
" phy_err[%u]\t%u\n",
i, st->rxerr_phy_code[i]);
}
- len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
st->rxerr_fifo,
st->rx_all_count > 0 ?
- st->rxerr_fifo*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
+ st->rxerr_fifo * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
st->rxerr_decrypt,
st->rx_all_count > 0 ?
- st->rxerr_decrypt*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
+ st->rxerr_decrypt * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
st->rxerr_mic,
st->rx_all_count > 0 ?
- st->rxerr_mic*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
+ st->rxerr_mic * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
st->rxerr_proc,
st->rx_all_count > 0 ?
- st->rxerr_proc*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
+ st->rxerr_proc * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
st->rxerr_jumbo,
st->rx_all_count > 0 ?
- st->rxerr_jumbo*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
+ st->rxerr_jumbo * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
st->rx_all_count);
- len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
st->rx_bytes_count);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nTX\n---------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
st->txerr_retry,
st->tx_all_count > 0 ?
- st->txerr_retry*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
+ st->txerr_retry * 100 / st->tx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
st->txerr_fifo,
st->tx_all_count > 0 ?
- st->txerr_fifo*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
+ st->txerr_fifo * 100 / st->tx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
st->txerr_filt,
st->tx_all_count > 0 ?
- st->txerr_filt*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
+ st->txerr_filt * 100 / st->tx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
st->tx_all_count);
- len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
st->tx_bytes_count);
if (len > sizeof(buf))
@@ -621,8 +619,8 @@ static ssize_t write_file_frameerrors(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_statistics *st = &sc->stats;
+ struct ath5k_hw *ah = file->private_data;
+ struct ath5k_statistics *st = &ah->stats;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
@@ -660,100 +658,104 @@ static const struct file_operations fops_frameerrors = {
static ssize_t read_file_ani(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_statistics *st = &sc->stats;
- struct ath5k_ani_state *as = &sc->ani_state;
+ struct ath5k_hw *ah = file->private_data;
+ struct ath5k_statistics *st = &ah->stats;
+ struct ath5k_ani_state *as = &ah->ani_state;
char buf[700];
unsigned int len = 0;
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"HW has PHY error counters:\t%s\n",
- sc->ah->ah_capabilities.cap_has_phyerr_counters ?
+ ah->ah_capabilities.cap_has_phyerr_counters ?
"yes" : "no");
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"HW max spur immunity level:\t%d\n",
as->max_spur_level);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nANI state\n--------------------------------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t");
+ len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
switch (as->ani_mode) {
case ATH5K_ANI_MODE_OFF:
- len += snprintf(buf+len, sizeof(buf)-len, "OFF\n");
+ len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");
break;
case ATH5K_ANI_MODE_MANUAL_LOW:
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"MANUAL LOW\n");
break;
case ATH5K_ANI_MODE_MANUAL_HIGH:
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"MANUAL HIGH\n");
break;
case ATH5K_ANI_MODE_AUTO:
- len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n");
+ len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");
break;
default:
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"??? (not good)\n");
break;
}
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"noise immunity level:\t\t%d\n",
as->noise_imm_level);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"spur immunity level:\t\t%d\n",
as->spur_level);
- len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "firstep level:\t\t\t%d\n",
as->firstep_level);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"OFDM weak signal detection:\t%s\n",
as->ofdm_weak_sig ? "on" : "off");
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"CCK weak signal detection:\t%s\n",
as->cck_weak_sig ? "on" : "off");
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nMIB INTERRUPTS:\t\t%u\n",
st->mib_intr);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"beacon RSSI average:\t%d\n",
- (int)ewma_read(&sc->ah->ah_beacon_rssi_avg));
+ (int)ewma_read(&ah->ah_beacon_rssi_avg));
#define CC_PRINT(_struct, _field) \
_struct._field, \
_struct.cycles > 0 ? \
- _struct._field*100/_struct.cycles : 0
+ _struct._field * 100 / _struct.cycles : 0
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "profcnt tx\t\t%u\t(%d%%)\n",
CC_PRINT(as->last_cc, tx_frame));
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "profcnt rx\t\t%u\t(%d%%)\n",
CC_PRINT(as->last_cc, rx_frame));
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "profcnt busy\t\t%u\t(%d%%)\n",
CC_PRINT(as->last_cc, rx_busy));
#undef CC_PRINT
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
as->last_cc.cycles);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"listen time\t\t%d\tlast: %d\n",
as->listen_time, as->last_listen);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
as->ofdm_errors, as->last_ofdm_errors,
as->sum_ofdm_errors);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"CCK errors\t\t%u\tlast: %u\tsum: %u\n",
as->cck_errors, as->last_cck_errors,
as->sum_cck_errors);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1),
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1)));
- len += snprintf(buf+len, sizeof(buf)-len,
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2),
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2)));
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
if (len > sizeof(buf))
len = sizeof(buf);
@@ -765,42 +767,42 @@ static ssize_t write_file_ani(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
return -EFAULT;
if (strncmp(buf, "sens-low", 8) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
} else if (strncmp(buf, "sens-high", 9) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
} else if (strncmp(buf, "ani-off", 7) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
} else if (strncmp(buf, "ani-on", 6) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
} else if (strncmp(buf, "noise-low", 9) == 0) {
- ath5k_ani_set_noise_immunity_level(sc->ah, 0);
+ ath5k_ani_set_noise_immunity_level(ah, 0);
} else if (strncmp(buf, "noise-high", 10) == 0) {
- ath5k_ani_set_noise_immunity_level(sc->ah,
+ ath5k_ani_set_noise_immunity_level(ah,
ATH5K_ANI_MAX_NOISE_IMM_LVL);
} else if (strncmp(buf, "spur-low", 8) == 0) {
- ath5k_ani_set_spur_immunity_level(sc->ah, 0);
+ ath5k_ani_set_spur_immunity_level(ah, 0);
} else if (strncmp(buf, "spur-high", 9) == 0) {
- ath5k_ani_set_spur_immunity_level(sc->ah,
- sc->ani_state.max_spur_level);
+ ath5k_ani_set_spur_immunity_level(ah,
+ ah->ani_state.max_spur_level);
} else if (strncmp(buf, "fir-low", 7) == 0) {
- ath5k_ani_set_firstep_level(sc->ah, 0);
+ ath5k_ani_set_firstep_level(ah, 0);
} else if (strncmp(buf, "fir-high", 8) == 0) {
- ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
+ ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
} else if (strncmp(buf, "ofdm-off", 8) == 0) {
- ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false);
+ ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
} else if (strncmp(buf, "ofdm-on", 7) == 0) {
- ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true);
+ ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
} else if (strncmp(buf, "cck-off", 7) == 0) {
- ath5k_ani_set_cck_weak_signal_detection(sc->ah, false);
+ ath5k_ani_set_cck_weak_signal_detection(ah, false);
} else if (strncmp(buf, "cck-on", 6) == 0) {
- ath5k_ani_set_cck_weak_signal_detection(sc->ah, true);
+ ath5k_ani_set_cck_weak_signal_detection(ah, true);
}
return count;
}
@@ -819,7 +821,7 @@ static const struct file_operations fops_ani = {
static ssize_t read_file_queue(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
@@ -827,13 +829,13 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
struct ath5k_buf *bf, *bf0;
int i, n;
- len += snprintf(buf+len, sizeof(buf)-len,
- "available txbuffers: %d\n", sc->txbuf_len);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "available txbuffers: %d\n", ah->txbuf_len);
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
- txq = &sc->txqs[i];
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+ txq = &ah->txqs[i];
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%02d: %ssetup\n", i, txq->setup ? "" : "not ");
if (!txq->setup)
@@ -845,9 +847,9 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
n++;
spin_unlock_bh(&txq->lock);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
" len: %d bufs: %d\n", txq->txq_len, n);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
" stuck: %d\n", txq->txq_stuck);
}
@@ -861,16 +863,16 @@ static ssize_t write_file_queue(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
return -EFAULT;
if (strncmp(buf, "start", 5) == 0)
- ieee80211_wake_queues(sc->hw);
+ ieee80211_wake_queues(ah->hw);
else if (strncmp(buf, "stop", 4) == 0)
- ieee80211_stop_queues(sc->hw);
+ ieee80211_stop_queues(ah->hw);
return count;
}
@@ -886,54 +888,57 @@ static const struct file_operations fops_queue = {
void
-ath5k_debug_init_device(struct ath5k_softc *sc)
+ath5k_debug_init_device(struct ath5k_hw *ah)
{
struct dentry *phydir;
- sc->debug.level = ath5k_debug;
+ ah->debug.level = ath5k_debug;
- phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
+ phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
if (!phydir)
- return;
+ return;
- debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah,
&fops_debug);
- debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
+ debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers);
- debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
&fops_beacon);
- debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
+ debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
- debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
&fops_antenna);
- debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
+ debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc);
- debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah,
&fops_frameerrors);
- debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
+ debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani);
- debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah,
&fops_queue);
+
+ debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir,
+ &ah->ah_use_32khz_clock);
}
/* functions used in other places */
void
-ath5k_debug_dump_bands(struct ath5k_softc *sc)
+ath5k_debug_dump_bands(struct ath5k_hw *ah)
{
unsigned int b, i;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
+ if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
return;
- BUG_ON(!sc->sbands);
+ BUG_ON(!ah->sbands);
for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
- struct ieee80211_supported_band *band = &sc->sbands[b];
+ struct ieee80211_supported_band *band = &ah->sbands[b];
char bname[6];
switch (band->band) {
case IEEE80211_BAND_2GHZ:
@@ -983,41 +988,41 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
}
void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
{
struct ath5k_desc *ds;
struct ath5k_buf *bf;
struct ath5k_rx_status rs = {};
int status;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
+ if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
return;
printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
- ath5k_hw_get_rxdp(ah), sc->rxlink);
+ ath5k_hw_get_rxdp(ah), ah->rxlink);
- spin_lock_bh(&sc->rxbuflock);
- list_for_each_entry(bf, &sc->rxbuf, list) {
+ spin_lock_bh(&ah->rxbuflock);
+ list_for_each_entry(bf, &ah->rxbuf, list) {
ds = bf->desc;
status = ah->ah_proc_rx_desc(ah, ds, &rs);
if (!status)
ath5k_debug_printrxbuf(bf, status == 0, &rs);
}
- spin_unlock_bh(&sc->rxbuflock);
+ spin_unlock_bh(&ah->rxbuflock);
}
void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
struct ath5k_desc *ds = bf->desc;
struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
struct ath5k_tx_status ts = {};
int done;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
+ if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
return;
- done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
+ done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
@@ -1026,5 +1031,3 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
}
-
-#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 193dd2d..0a3f916 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -61,7 +61,6 @@
#ifndef _ATH5K_DEBUG_H
#define _ATH5K_DEBUG_H
-struct ath5k_softc;
struct ath5k_hw;
struct sk_buff;
struct ath5k_buf;
@@ -127,39 +126,39 @@ enum ath5k_debug_level {
} while (0)
void
-ath5k_debug_init_device(struct ath5k_softc *sc);
+ath5k_debug_init_device(struct ath5k_hw *ah);
void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah);
void
-ath5k_debug_dump_bands(struct ath5k_softc *sc);
+ath5k_debug_dump_bands(struct ath5k_hw *ah);
void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf);
#else /* no debugging */
#include <linux/compiler.h>
-static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+static inline __printf(3, 4) void
+ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {}
-static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
+static inline __printf(3, 4) void
+ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...)
{}
static inline void
-ath5k_debug_init_device(struct ath5k_softc *sc) {}
+ath5k_debug_init_device(struct ath5k_hw *ah) {}
static inline void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah) {}
static inline void
-ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
+ath5k_debug_dump_bands(struct ath5k_hw *ah) {}
static inline void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf) {}
#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index f82383b..7e88dda 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -24,7 +24,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/************************\
@@ -55,12 +54,12 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
* noise on the channel, so it is important to avoid this.
*/
if (unlikely(tx_tries0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ ATH5K_ERR(ah, "zero retries\n");
WARN_ON(1);
return -EINVAL;
}
if (unlikely(tx_rate0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ ATH5K_ERR(ah, "zero rate\n");
WARN_ON(1);
return -EINVAL;
}
@@ -203,12 +202,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
* noise on the channel, so it is important to avoid this.
*/
if (unlikely(tx_tries0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ ATH5K_ERR(ah, "zero retries\n");
WARN_ON(1);
return -EINVAL;
}
if (unlikely(tx_rate0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ ATH5K_ERR(ah, "zero rate\n");
WARN_ON(1);
return -EINVAL;
}
@@ -316,7 +315,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
(tx_rate2 == 0 && tx_tries2 != 0) ||
(tx_rate3 == 0 && tx_tries3 != 0))) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ ATH5K_ERR(ah, "zero rate\n");
WARN_ON(1);
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h
index 2509d0b..cfd529b5 100644
--- a/drivers/net/wireless/ath/ath5k/desc.h
+++ b/drivers/net/wireless/ath/ath5k/desc.h
@@ -58,11 +58,11 @@ struct ath5k_hw_rx_status {
#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* reception success */
#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */
#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210 0x00000008 /* [5210] FIFO overrun */
-#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decyption CRC failure */
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decryption CRC failure */
#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 /* PHY error */
#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */
-#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decyption key index */
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decryption key index */
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 /* 13 bit of TSF */
#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 21091c2..2481f9c 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -25,7 +25,7 @@
*
* Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
* handle queue setup for 5210 chipset (rest are handled on qcu.c).
- * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * Also we setup interrupt mask register (IMR) and read the various interrupt
* status registers (ISR).
*
* TODO: Handle SISR on 5211+ and introduce a function to return the queue
@@ -35,7 +35,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*********\
@@ -73,7 +72,7 @@ static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
udelay(100);
if (!i)
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"failed to stop RX DMA !\n");
return i ? 0 : -EBUSY;
@@ -100,7 +99,7 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
{
if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"tried to set RXDP while rx was active !\n");
return -EIO;
}
@@ -243,7 +242,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
udelay(100);
if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"queue %i didn't stop !\n", queue);
/* Check for pending frames */
@@ -258,7 +257,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* For 2413+ order PCU to drop packets using
* QUIET mechanism */
if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
- pending){
+ pending) {
/* Set periodicity and duration */
ath5k_hw_reg_write(ah,
AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
@@ -295,7 +294,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
if (pending)
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"quiet mechanism didn't work q:%i !\n",
queue);
}
@@ -309,7 +308,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* Clear register */
ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
if (pending) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"tx dma didn't stop (q:%i, frm:%i) !\n",
queue, pending);
return -EBUSY;
@@ -333,7 +332,7 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
int ret;
ret = ath5k_hw_stop_tx_dma(ah, queue);
if (ret) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"beacon queue didn't stop !\n");
return -EIO;
}
@@ -726,7 +725,7 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
int_mask |= AR5K_IMR_RXDOPPLER;
/* Note: Per queue interrupt masks
- * are set via reset_tx_queue (qcu.c) */
+ * are set via ath5k_hw_reset_tx_queue() (qcu.c) */
ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
@@ -783,7 +782,7 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)
* for all PCI-E cards to be safe).
*
* XXX: need to check 5210 for this
- * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * TODO: Check out tx trigger level, it's always 64 on dumps but I
* guess we can tweak it and see how it goes ;-)
*/
if (ah->ah_version != AR5K_AR5210) {
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 392771f..cd708c1 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -26,7 +26,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/******************\
@@ -105,7 +104,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
* big still, waiting on a better value.
*/
if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
- ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
+ ATH5K_ERR(ah, "Invalid max custom EEPROM size: "
"%d (0x%04x) max expected: %d (0x%04x)\n",
eep_max, eep_max,
3 * AR5K_EEPROM_INFO_MAX,
@@ -119,7 +118,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
cksum ^= val;
}
if (cksum != AR5K_EEPROM_INFO_CKSUM) {
- ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
+ ATH5K_ERR(ah, "Invalid EEPROM "
"checksum: 0x%04x eep_max: 0x%04x (%s)\n",
cksum, eep_max,
eep_max == AR5K_EEPROM_INFO_MAX ?
@@ -223,14 +222,14 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
ah->ah_ant_ctl[mode][AR5K_ANT_CTL] =
(ee->ee_ant_control[mode][0] << 4);
ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] =
- ee->ee_ant_control[mode][1] |
- (ee->ee_ant_control[mode][2] << 6) |
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
(ee->ee_ant_control[mode][3] << 12) |
(ee->ee_ant_control[mode][4] << 18) |
(ee->ee_ant_control[mode][5] << 24);
ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] =
- ee->ee_ant_control[mode][6] |
- (ee->ee_ant_control[mode][7] << 6) |
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
(ee->ee_ant_control[mode][8] << 12) |
(ee->ee_ant_control[mode][9] << 18) |
(ee->ee_ant_control[mode][10] << 24);
@@ -255,7 +254,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
ee->ee_n_piers[mode] = 0;
AR5K_EEPROM_READ(o++, val);
ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
ee->ee_ob[mode][3] = (val >> 5) & 0x7;
ee->ee_db[mode][3] = (val >> 2) & 0x7;
@@ -349,7 +348,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
/* Note: >= v5 have bg freq piers on another location
* so these freq piers are ignored for >= v5 (should be 0xff
* anyway) */
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
break;
@@ -422,7 +421,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
goto done;
- switch (mode){
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
@@ -436,7 +435,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
- if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+ if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >= 2)
ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
break;
case AR5K_EEPROM_MODE_11G:
@@ -516,7 +515,7 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
u16 val;
ee->ee_n_piers[mode] = 0;
- while(i < max) {
+ while (i < max) {
AR5K_EEPROM_READ(o++, val);
freq1 = val & 0xff;
@@ -602,7 +601,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
struct ath5k_chan_pcal_info *pcal;
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11B:
pcal = ee->ee_pwr_cal_b;
break;
@@ -634,7 +633,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
/* Used to match PCDAC steps with power values on RF5111 chips
* (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
* steps that match with the power values we read from eeprom. On
- * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * older eeprom versions (< 3.2) these steps are equally spaced at
* 10% of the pcdac curve -until the curve reaches its maximum-
* (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
* these 11 steps are spaced in a different way. This function returns
@@ -644,10 +643,12 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
static inline void
ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
{
- static const u16 intercepts3[] =
- { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
- static const u16 intercepts3_2[] =
- { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+ static const u16 intercepts3[] = {
+ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100
+ };
+ static const u16 intercepts3_2[] = {
+ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
+ };
const u16 *ip;
int i;
@@ -762,7 +763,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
/* Fill raw dataset
* (convert power to 0.25dB units
- * for RF5112 combatibility) */
+ * for RF5112 compatibility) */
for (point = 0; point < pd->pd_points; point++) {
/* Absolute values */
@@ -796,7 +797,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
u16 val;
offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
return 0;
@@ -882,7 +883,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
* Read power calibration for RF5112 chips
*
* For RF5112 we have 4 XPD -eXternal Power Detector- curves
- * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * for each calibrated channel on 0, -6, -12 and -18dBm but we only
* use the higher (3) and the lower (0) curves. Each curve has 0.5dB
* power steps on x axis and PCDAC steps on y axis and looks like a
* linear function. To recreate the curve and pass the power values
@@ -1163,7 +1164,7 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
{
u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11G:
if (AR5K_EEPROM_HDR_11B(ee->ee_header))
offset += ath5k_pdgains_size_2413(ee,
@@ -1239,7 +1240,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
/* Fill raw dataset
* convert all pwr levels to
- * quarter dB for RF5112 combatibility */
+ * quarter dB for RF5112 compatibility */
pd->pd_step[0] = pcinfo->pddac_i[pdg];
pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
@@ -1620,8 +1621,8 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
rep = ee->ee_ctl_pwr;
- for(i = 0; i < ee->ee_ctls; i++) {
- switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+ for (i = 0; i < ee->ee_ctls; i++) {
+ switch (ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
case AR5K_CTL_11A:
case AR5K_CTL_TURBO:
ctl_mode = AR5K_EEPROM_MODE_11A;
@@ -1778,13 +1779,12 @@ ath5k_eeprom_detach(struct ath5k_hw *ah)
int
ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
{
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
- case CHANNEL_XR:
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
return AR5K_EEPROM_MODE_11A;
- case CHANNEL_G:
+ case AR5K_MODE_11G:
return AR5K_EEPROM_MODE_11G;
- case CHANNEL_B:
+ case AR5K_MODE_11B:
return AR5K_EEPROM_MODE_11B;
default:
return -1;
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 6511c27..dc2bcfe 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -50,7 +50,7 @@
#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
-#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2GHz (ar5211_rfregs) */
#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
@@ -75,11 +75,11 @@
#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz */
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2GHz */
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for < 2W power consumption */
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) /* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */
#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5GHz */
/* Newer EEPROMs are using a different offset */
#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
@@ -120,7 +120,7 @@
#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) /* disable fast frames */
#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) /* disable bursting */
#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) /* max number of QCUs. defaults to 10 */
-#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heayy clipping */
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heavy clipping */
#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) /* key cache size. defaults to 128 */
#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
@@ -223,7 +223,7 @@
#define AR5K_EEPROM_CCK_OFDM_DELTA 15
#define AR5K_EEPROM_N_IQ_CAL 2
/* 5GHz/2GHz */
-enum ath5k_eeprom_freq_bands{
+enum ath5k_eeprom_freq_bands {
AR5K_EEPROM_BAND_5GHZ = 0,
AR5K_EEPROM_BAND_2GHZ = 1,
AR5K_EEPROM_N_FREQ_BANDS,
@@ -270,7 +270,7 @@ enum ath5k_ctl_mode {
/* Per channel calibration data, used for power table setup */
struct ath5k_chan_pcal_info_rf5111 {
- /* Power levels in half dbm units
+ /* Power levels in half dBm units
* for one power curve. */
u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
/* PCDAC table steps
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c
index bc90503..8592978 100644
--- a/drivers/net/wireless/ath/ath5k/gpio.c
+++ b/drivers/net/wireless/ath/ath5k/gpio.c
@@ -23,7 +23,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*
* Set led state
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index e49340d..1ffecc0 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -22,7 +22,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*
* Mode-independent initial register writes
@@ -113,8 +112,8 @@ static const struct ath5k_ini ar5210_ini[] = {
{ AR5K_PHY(28), 0x0000000f },
{ AR5K_PHY(29), 0x00000080 },
{ AR5K_PHY(30), 0x00000004 },
- { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
- { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
+ { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
+ { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
{ AR5K_PHY(65), 0x00000000 },
{ AR5K_PHY(66), 0x00000000 },
{ AR5K_PHY(67), 0x00800000 },
@@ -549,7 +548,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
{ AR5K_DIAG_SW_5211, 0x00000000 },
{ AR5K_ADDAC_TEST, 0x00000000 },
{ AR5K_DEFAULT_ANTENNA, 0x00000000 },
- { AR5K_FRAME_CTL_QOSM, 0x000fc78f },
+ { AR5K_FRAME_CTL_QOSM, 0x000fc78f },
{ AR5K_XRMODE, 0x2a82301a },
{ AR5K_XRDELAY, 0x05dc01e0 },
{ AR5K_XRTIMEOUT, 0x1f402710 },
@@ -760,9 +759,9 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
static const struct ath5k_ini rf5111_ini_common_end[] = {
{ AR5K_DCU_FP, 0x00000000 },
- { AR5K_PHY_AGC, 0x00000000 },
- { AR5K_PHY_ADC_CTL, 0x00022ffe },
- { 0x983c, 0x00020100 },
+ { AR5K_PHY_AGC, 0x00000000 },
+ { AR5K_PHY_ADC_CTL, 0x00022ffe },
+ { 0x983c, 0x00020100 },
{ AR5K_PHY_GAIN_OFFSET, 0x1284613c },
{ AR5K_PHY_PAPD_PROBE, 0x00004883 },
{ 0x9940, 0x00000004 },
@@ -1409,7 +1408,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
* Write initial register settings
*/
- /* For AR5212 and combatible */
+ /* For AR5212 and compatible */
if (ah->ah_version == AR5K_AR5212) {
/* First set of mode-specific settings */
@@ -1542,7 +1541,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
/* AR5K_MODE_11B */
if (mode > 2) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"unsupported channel mode: %d\n", mode);
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 576edf2..c1151c7 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -41,18 +41,17 @@
#include <linux/pci.h>
#include "ath5k.h"
-#include "base.h"
-#define ATH_SDEVICE(subv,subd) \
+#define ATH_SDEVICE(subv, subd) \
.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
.subvendor = (subv), .subdevice = (subd)
-#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
+#define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity))
#define ATH_PIN(data) ((data) >> 8)
#define ATH_POLARITY(data) ((data) & 0xff)
/* Devices we match on for LED config info (typically laptops) */
-static const struct pci_device_id ath5k_led_devices[] = {
+static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = {
/* AR5211 */
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
/* HP Compaq nc6xx, nc4000, nx6000 */
@@ -86,26 +85,26 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ }
};
-void ath5k_led_enable(struct ath5k_softc *sc)
+void ath5k_led_enable(struct ath5k_hw *ah)
{
- if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
- ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
- ath5k_led_off(sc);
+ if (test_bit(ATH_STAT_LEDSOFT, ah->status)) {
+ ath5k_hw_set_gpio_output(ah, ah->led_pin);
+ ath5k_led_off(ah);
}
}
-static void ath5k_led_on(struct ath5k_softc *sc)
+static void ath5k_led_on(struct ath5k_hw *ah)
{
- if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+ if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
return;
- ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
+ ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on);
}
-void ath5k_led_off(struct ath5k_softc *sc)
+void ath5k_led_off(struct ath5k_hw *ah)
{
- if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+ if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
return;
- ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
+ ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on);
}
static void
@@ -116,27 +115,27 @@ ath5k_led_brightness_set(struct led_classdev *led_dev,
led_dev);
if (brightness == LED_OFF)
- ath5k_led_off(led->sc);
+ ath5k_led_off(led->ah);
else
- ath5k_led_on(led->sc);
+ ath5k_led_on(led->ah);
}
static int
-ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
+ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led,
const char *name, char *trigger)
{
int err;
- led->sc = sc;
+ led->ah = ah;
strncpy(led->name, name, sizeof(led->name));
led->led_dev.name = led->name;
led->led_dev.default_trigger = trigger;
led->led_dev.brightness_set = ath5k_led_brightness_set;
- err = led_classdev_register(sc->dev, &led->led_dev);
+ err = led_classdev_register(ah->dev, &led->led_dev);
if (err) {
- ATH5K_WARN(sc, "could not register LED %s\n", name);
- led->sc = NULL;
+ ATH5K_WARN(ah, "could not register LED %s\n", name);
+ led->ah = NULL;
}
return err;
}
@@ -144,30 +143,30 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
static void
ath5k_unregister_led(struct ath5k_led *led)
{
- if (!led->sc)
+ if (!led->ah)
return;
led_classdev_unregister(&led->led_dev);
- ath5k_led_off(led->sc);
- led->sc = NULL;
+ ath5k_led_off(led->ah);
+ led->ah = NULL;
}
-void ath5k_unregister_leds(struct ath5k_softc *sc)
+void ath5k_unregister_leds(struct ath5k_hw *ah)
{
- ath5k_unregister_led(&sc->rx_led);
- ath5k_unregister_led(&sc->tx_led);
+ ath5k_unregister_led(&ah->rx_led);
+ ath5k_unregister_led(&ah->tx_led);
}
-int ath5k_init_leds(struct ath5k_softc *sc)
+int __devinit ath5k_init_leds(struct ath5k_hw *ah)
{
int ret = 0;
- struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_hw *hw = ah->hw;
#ifndef CONFIG_ATHEROS_AR231X
- struct pci_dev *pdev = sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1];
const struct pci_device_id *match;
- if (!sc->pdev)
+ if (!ah->pdev)
return 0;
#ifdef CONFIG_ATHEROS_AR231X
@@ -176,24 +175,24 @@ int ath5k_init_leds(struct ath5k_softc *sc)
match = pci_match_id(&ath5k_led_devices[0], pdev);
#endif
if (match) {
- __set_bit(ATH_STAT_LEDSOFT, sc->status);
- sc->led_pin = ATH_PIN(match->driver_data);
- sc->led_on = ATH_POLARITY(match->driver_data);
+ __set_bit(ATH_STAT_LEDSOFT, ah->status);
+ ah->led_pin = ATH_PIN(match->driver_data);
+ ah->led_on = ATH_POLARITY(match->driver_data);
}
- if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+ if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
goto out;
- ath5k_led_enable(sc);
+ ath5k_led_enable(ah);
snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
- ret = ath5k_register_led(sc, &sc->rx_led, name,
+ ret = ath5k_register_led(ah, &ah->rx_led, name,
ieee80211_get_rx_led_name(hw));
if (ret)
goto out;
snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
- ret = ath5k_register_led(sc, &sc->tx_led, name,
+ ret = ath5k_register_led(ah, &ah->tx_led, name,
ieee80211_get_tx_led_name(hw));
out:
return ret;
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 807bd64..6ed4c07 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -41,13 +41,13 @@
*
*/
+#include <net/mac80211.h>
#include <asm/unaligned.h>
+#include "ath5k.h"
#include "base.h"
#include "reg.h"
-extern int ath5k_modparam_nohwcrypt;
-
/********************\
* Mac80211 functions *
\********************/
@@ -55,44 +55,30 @@ extern int ath5k_modparam_nohwcrypt;
static void
ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
u16 qnum = skb_get_queue_mapping(skb);
- if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
+ if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) {
dev_kfree_skb_any(skb);
return;
}
- ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
-}
-
-
-static int
-ath5k_start(struct ieee80211_hw *hw)
-{
- return ath5k_init_hw(hw->priv);
-}
-
-
-static void
-ath5k_stop(struct ieee80211_hw *hw)
-{
- ath5k_stop_hw(hw->priv);
+ ath5k_tx_queue(hw, skb, &ah->txqs[qnum]);
}
static int
ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
int ret;
struct ath5k_vif *avf = (void *)vif->drv_priv;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
if ((vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC)
- && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+ && (ah->num_ap_vifs + ah->num_adhoc_vifs) >= ATH_BCBUF) {
ret = -ELNRNG;
goto end;
}
@@ -102,9 +88,9 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
* We would need to operate the HW in ad-hoc mode to allow TSF updates
* for the IBSS, but this breaks with additional AP or STA interfaces
* at the moment. */
- if (sc->num_adhoc_vifs ||
- (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
- ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+ if (ah->num_adhoc_vifs ||
+ (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
ret = -ELNRNG;
goto end;
}
@@ -121,8 +107,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
goto end;
}
- sc->nvifs++;
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
+ ah->nvifs++;
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
/* Assign the vap/adhoc to a beacon xmit slot. */
if ((avf->opmode == NL80211_IFTYPE_AP) ||
@@ -130,38 +116,35 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
(avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
int slot;
- WARN_ON(list_empty(&sc->bcbuf));
- avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+ WARN_ON(list_empty(&ah->bcbuf));
+ avf->bbuf = list_first_entry(&ah->bcbuf, struct ath5k_buf,
list);
list_del(&avf->bbuf->list);
avf->bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++) {
- if (!sc->bslot[slot]) {
+ if (!ah->bslot[slot]) {
avf->bslot = slot;
break;
}
}
- BUG_ON(sc->bslot[avf->bslot] != NULL);
- sc->bslot[avf->bslot] = vif;
+ BUG_ON(ah->bslot[avf->bslot] != NULL);
+ ah->bslot[avf->bslot] = vif;
if (avf->opmode == NL80211_IFTYPE_AP)
- sc->num_ap_vifs++;
+ ah->num_ap_vifs++;
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
- sc->num_adhoc_vifs++;
+ ah->num_adhoc_vifs++;
}
/* Any MAC address is fine, all others are included through the
* filter.
*/
- memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
- ath5k_hw_set_lladdr(sc->ah, vif->addr);
-
- memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
+ ath5k_hw_set_lladdr(ah, vif->addr);
- ath5k_update_bssid_mask_and_opmode(sc, vif);
+ ath5k_update_bssid_mask_and_opmode(ah, vif);
ret = 0;
end:
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -170,31 +153,31 @@ static void
ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_vif *avf = (void *)vif->drv_priv;
unsigned int i;
- mutex_lock(&sc->lock);
- sc->nvifs--;
+ mutex_lock(&ah->lock);
+ ah->nvifs--;
if (avf->bbuf) {
- ath5k_txbuf_free_skb(sc, avf->bbuf);
- list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+ ath5k_txbuf_free_skb(ah, avf->bbuf);
+ list_add_tail(&avf->bbuf->list, &ah->bcbuf);
for (i = 0; i < ATH_BCBUF; i++) {
- if (sc->bslot[i] == vif) {
- sc->bslot[i] = NULL;
+ if (ah->bslot[i] == vif) {
+ ah->bslot[i] = NULL;
break;
}
}
avf->bbuf = NULL;
}
if (avf->opmode == NL80211_IFTYPE_AP)
- sc->num_ap_vifs--;
+ ah->num_ap_vifs--;
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
- sc->num_adhoc_vifs--;
+ ah->num_adhoc_vifs--;
- ath5k_update_bssid_mask_and_opmode(sc, NULL);
- mutex_unlock(&sc->lock);
+ ath5k_update_bssid_mask_and_opmode(ah, NULL);
+ mutex_unlock(&ah->lock);
}
@@ -204,23 +187,22 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
static int
ath5k_config(struct ieee80211_hw *hw, u32 changed)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
int ret = 0;
int i;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- ret = ath5k_chan_set(sc, conf->channel);
+ ret = ath5k_chan_set(ah, conf->channel);
if (ret < 0)
goto unlock;
}
if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
- (sc->power_level != conf->power_level)) {
- sc->power_level = conf->power_level;
+ (ah->power_level != conf->power_level)) {
+ ah->power_level = conf->power_level;
/* Half dB steps */
ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
@@ -254,7 +236,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
unlock:
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -264,12 +246,11 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, u32 changes)
{
struct ath5k_vif *avf = (void *)vif->drv_priv;
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_common *common = ath5k_hw_common(ah);
unsigned long flags;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
if (changes & BSS_CHANGED_BSSID) {
/* Cache for later use during resets */
@@ -280,7 +261,7 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (changes & BSS_CHANGED_BEACON_INT)
- sc->bintval = bss_conf->beacon_int;
+ ah->bintval = bss_conf->beacon_int;
if (changes & BSS_CHANGED_ERP_SLOT) {
int slot_time;
@@ -294,16 +275,16 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (changes & BSS_CHANGED_ASSOC) {
avf->assoc = bss_conf->assoc;
if (bss_conf->assoc)
- sc->assoc = bss_conf->assoc;
+ ah->assoc = bss_conf->assoc;
else
- sc->assoc = ath_any_vif_assoc(sc);
+ ah->assoc = ath5k_any_vif_assoc(ah);
- if (sc->opmode == NL80211_IFTYPE_STATION)
- set_beacon_filter(hw, sc->assoc);
- ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+ if (ah->opmode == NL80211_IFTYPE_STATION)
+ ath5k_set_beacon_filter(hw, ah->assoc);
+ ath5k_hw_set_ledstate(ah, ah->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
if (bss_conf->assoc) {
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
"Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
common->curaid = bss_conf->aid;
@@ -313,19 +294,19 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (changes & BSS_CHANGED_BEACON) {
- spin_lock_irqsave(&sc->block, flags);
+ spin_lock_irqsave(&ah->block, flags);
ath5k_beacon_update(hw, vif);
- spin_unlock_irqrestore(&sc->block, flags);
+ spin_unlock_irqrestore(&ah->block, flags);
}
if (changes & BSS_CHANGED_BEACON_ENABLED)
- sc->enable_beacon = bss_conf->enable_beacon;
+ ah->enable_beacon = bss_conf->enable_beacon;
if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON_INT))
- ath5k_beacon_config(sc);
+ ath5k_beacon_config(ah);
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
}
@@ -350,7 +331,7 @@ ath5k_prepare_multicast(struct ieee80211_hw *hw,
mfilt[pos / 32] |= (1 << (pos % 32));
/* XXX: we might be able to just do this instead,
* but not sure, needs testing, if we do use this we'd
- * neet to inform below to not reset the mcast */
+ * need to inform below not to reset the mcast */
/* ath5k_hw_set_mcast_filterindex(ah,
* ha->addr[5]); */
}
@@ -386,12 +367,11 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC)
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
u32 mfilt[2], rfilt;
struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
mfilt[0] = multicast;
mfilt[1] = multicast >> 32;
@@ -409,12 +389,12 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
if (*new_flags & FIF_PROMISC_IN_BSS)
- __set_bit(ATH_STAT_PROMISC, sc->status);
+ __set_bit(ATH_STAT_PROMISC, ah->status);
else
- __clear_bit(ATH_STAT_PROMISC, sc->status);
+ __clear_bit(ATH_STAT_PROMISC, ah->status);
}
- if (test_bit(ATH_STAT_PROMISC, sc->status))
+ if (test_bit(ATH_STAT_PROMISC, ah->status))
rfilt |= AR5K_RX_FILTER_PROM;
/* Note, AR5K_RX_FILTER_MCAST is already enabled */
@@ -429,7 +409,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
* and probes for any BSSID */
- if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
+ if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (ah->nvifs > 1))
rfilt |= AR5K_RX_FILTER_BEACON;
/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
@@ -444,7 +424,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
- switch (sc->opmode) {
+ switch (ah->opmode) {
case NL80211_IFTYPE_MESH_POINT:
rfilt |= AR5K_RX_FILTER_CONTROL |
AR5K_RX_FILTER_BEACON |
@@ -457,7 +437,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
AR5K_RX_FILTER_BEACON;
break;
case NL80211_IFTYPE_STATION:
- if (sc->assoc)
+ if (ah->assoc)
rfilt |= AR5K_RX_FILTER_BEACON;
default:
break;
@@ -466,14 +446,14 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
iter_data.hw_macaddr = NULL;
iter_data.n_stas = 0;
iter_data.need_set_hw_addr = false;
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+ ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
&iter_data);
/* Set up RX Filter */
if (iter_data.n_stas > 1) {
/* If you have multiple STA interfaces connected to
* different APs, ARPs are not received (most of the time?)
- * Enabling PROMISC appears to fix that probem.
+ * Enabling PROMISC appears to fix that problem.
*/
rfilt |= AR5K_RX_FILTER_PROM;
}
@@ -485,9 +465,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
/* Set the cached hw filter flags, this will later actually
* be set in HW */
- sc->filter_flags = rfilt;
+ ah->filter_flags = rfilt;
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
}
@@ -496,8 +476,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_common *common = ath5k_hw_common(ah);
int ret = 0;
@@ -518,7 +497,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EINVAL;
}
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
switch (cmd) {
case SET_KEY:
@@ -542,7 +521,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
mmiowb();
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -550,17 +529,17 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
static void
ath5k_sw_scan_start(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- if (!sc->assoc)
- ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
+ struct ath5k_hw *ah = hw->priv;
+ if (!ah->assoc)
+ ath5k_hw_set_ledstate(ah, AR5K_LED_SCAN);
}
static void
ath5k_sw_scan_complete(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+ struct ath5k_hw *ah = hw->priv;
+ ath5k_hw_set_ledstate(ah, ah->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
}
@@ -569,33 +548,32 @@ static int
ath5k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
/* Force update */
- ath5k_hw_update_mib_counters(sc->ah);
+ ath5k_hw_update_mib_counters(ah);
- stats->dot11ACKFailureCount = sc->stats.ack_fail;
- stats->dot11RTSFailureCount = sc->stats.rts_fail;
- stats->dot11RTSSuccessCount = sc->stats.rts_ok;
- stats->dot11FCSErrorCount = sc->stats.fcs_error;
+ stats->dot11ACKFailureCount = ah->stats.ack_fail;
+ stats->dot11RTSFailureCount = ah->stats.rts_fail;
+ stats->dot11RTSSuccessCount = ah->stats.rts_ok;
+ stats->dot11FCSErrorCount = ah->stats.fcs_error;
return 0;
}
static int
-ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_txq_info qi;
int ret = 0;
if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
return 0;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
ath5k_hw_get_tx_queueprops(ah, queue, &qi);
@@ -604,65 +582,65 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
qi.tqi_cw_max = params->cw_max;
qi.tqi_burst_time = params->txop;
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
"Configure tx [queue %d], "
"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
queue, params->aifs, params->cw_min,
params->cw_max, params->txop);
if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
- ATH5K_ERR(sc,
+ ATH5K_ERR(ah,
"Unable to update hardware queue %u!\n", queue);
ret = -EIO;
} else
ath5k_hw_reset_tx_queue(ah, queue);
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
static u64
-ath5k_get_tsf(struct ieee80211_hw *hw)
+ath5k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- return ath5k_hw_get_tsf64(sc->ah);
+ return ath5k_hw_get_tsf64(ah);
}
static void
-ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+ath5k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- ath5k_hw_set_tsf64(sc->ah, tsf);
+ ath5k_hw_set_tsf64(ah, tsf);
}
static void
-ath5k_reset_tsf(struct ieee80211_hw *hw)
+ath5k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
/*
* in IBSS mode we need to update the beacon timers too.
* this will also reset the TSF if we call it with 0
*/
- if (sc->opmode == NL80211_IFTYPE_ADHOC)
- ath5k_beacon_update_timers(sc, 0);
+ if (ah->opmode == NL80211_IFTYPE_ADHOC)
+ ath5k_beacon_update_timers(ah, 0);
else
- ath5k_hw_reset_tsf(sc->ah);
+ ath5k_hw_reset_tsf(ah);
}
static int
ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
struct ath_cycle_counters *cc = &common->cc_survey;
unsigned int div = common->clockrate * 1000;
@@ -672,18 +650,18 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
spin_lock_bh(&common->cc_lock);
ath_hw_cycle_counters_update(common);
if (cc->cycles > 0) {
- sc->survey.channel_time += cc->cycles / div;
- sc->survey.channel_time_busy += cc->rx_busy / div;
- sc->survey.channel_time_rx += cc->rx_frame / div;
- sc->survey.channel_time_tx += cc->tx_frame / div;
+ ah->survey.channel_time += cc->cycles / div;
+ ah->survey.channel_time_busy += cc->rx_busy / div;
+ ah->survey.channel_time_rx += cc->rx_frame / div;
+ ah->survey.channel_time_tx += cc->tx_frame / div;
}
memset(cc, 0, sizeof(*cc));
spin_unlock_bh(&common->cc_lock);
- memcpy(survey, &sc->survey, sizeof(*survey));
+ memcpy(survey, &ah->survey, sizeof(*survey));
survey->channel = conf->channel;
- survey->noise = sc->ah->ah_noise_floor;
+ survey->noise = ah->ah_noise_floor;
survey->filled = SURVEY_INFO_NOISE_DBM |
SURVEY_INFO_CHANNEL_TIME |
SURVEY_INFO_CHANNEL_TIME_BUSY |
@@ -707,25 +685,25 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
static void
ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- mutex_lock(&sc->lock);
- ath5k_hw_set_coverage_class(sc->ah, coverage_class);
- mutex_unlock(&sc->lock);
+ mutex_lock(&ah->lock);
+ ath5k_hw_set_coverage_class(ah, coverage_class);
+ mutex_unlock(&ah->lock);
}
static int
ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
if (tx_ant == 1 && rx_ant == 1)
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
else if (tx_ant == 2 && rx_ant == 2)
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
else
return -EINVAL;
return 0;
@@ -735,9 +713,9 @@ ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int
ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- switch (sc->ah->ah_ant_mode) {
+ switch (ah->ah_ant_mode) {
case AR5K_ANTMODE_FIXED_A:
*tx_ant = 1; *rx_ant = 1; break;
case AR5K_ANTMODE_FIXED_B:
@@ -752,9 +730,9 @@ ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
static void ath5k_get_ringparam(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- *tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
+ *tx = ah->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
*tx_max = ATH5K_TXQ_LEN_MAX;
*rx = *rx_max = ATH_RXBUF;
@@ -763,7 +741,7 @@ static void ath5k_get_ringparam(struct ieee80211_hw *hw,
static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
u16 qnum;
/* only support setting tx ring size for now */
@@ -774,16 +752,16 @@ static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
if (!tx || tx > ATH5K_TXQ_LEN_MAX)
return -EINVAL;
- for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) {
- if (!sc->txqs[qnum].setup)
+ for (qnum = 0; qnum < ARRAY_SIZE(ah->txqs); qnum++) {
+ if (!ah->txqs[qnum].setup)
continue;
- if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
- sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
+ if (ah->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
+ ah->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
continue;
- sc->txqs[qnum].txq_max = tx;
- if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max)
- ieee80211_stop_queue(hw, sc->txqs[qnum].qnum);
+ ah->txqs[qnum].txq_max = tx;
+ if (ah->txqs[qnum].txq_len >= ah->txqs[qnum].txq_max)
+ ieee80211_stop_queue(hw, ah->txqs[qnum].qnum);
}
return 0;
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index f2c0c23..dfa48eb 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -18,6 +18,7 @@
#include <linux/pci.h>
#include <linux/pci-aspm.h>
#include <linux/etherdevice.h>
+#include <linux/module.h>
#include "../ath.h"
#include "ath5k.h"
#include "debug.h"
@@ -34,12 +35,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
{ PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */
{ PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */
{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
- { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 compatible */
{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
@@ -51,10 +52,10 @@ MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
/* return bus cachesize in 4B word units */
static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
{
- struct ath5k_softc *sc = (struct ath5k_softc *) common->priv;
+ struct ath5k_hw *ah = (struct ath5k_hw *) common->priv;
u8 u8tmp;
- pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
+ pci_read_config_byte(ah->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
*csz = (int)u8tmp;
/*
@@ -156,7 +157,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
void __iomem *mem;
- struct ath5k_softc *sc;
+ struct ath5k_hw *ah;
struct ieee80211_hw *hw;
int ret;
u8 csz;
@@ -234,7 +235,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
mem = pci_iomap(pdev, 0, 0);
if (!mem) {
- dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+ dev_err(&pdev->dev, "cannot remap PCI memory region\n");
ret = -EIO;
goto err_reg;
}
@@ -243,7 +244,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
* Allocate hw (mac80211 main struct)
* and hw->priv (driver private data)
*/
- hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(*ah), &ath5k_hw_ops);
if (hw == NULL) {
dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
ret = -ENOMEM;
@@ -252,16 +253,16 @@ ath5k_pci_probe(struct pci_dev *pdev,
dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
- sc = hw->priv;
- sc->hw = hw;
- sc->pdev = pdev;
- sc->dev = &pdev->dev;
- sc->irq = pdev->irq;
- sc->devid = id->device;
- sc->iobase = mem; /* So we can unmap it on detach */
+ ah = hw->priv;
+ ah->hw = hw;
+ ah->pdev = pdev;
+ ah->dev = &pdev->dev;
+ ah->irq = pdev->irq;
+ ah->devid = id->device;
+ ah->iobase = mem; /* So we can unmap it on detach */
/* Initialize */
- ret = ath5k_init_softc(sc, &ath_pci_bus_ops);
+ ret = ath5k_init_ah(ah, &ath_pci_bus_ops);
if (ret)
goto err_free;
@@ -285,10 +286,10 @@ static void __devexit
ath5k_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- ath5k_deinit_softc(sc);
- pci_iounmap(pdev, sc->iobase);
+ ath5k_deinit_ah(ah);
+ pci_iounmap(pdev, ah->iobase);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
ieee80211_free_hw(hw);
@@ -299,9 +300,9 @@ static int ath5k_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- ath5k_led_off(sc);
+ ath5k_led_off(ah);
return 0;
}
@@ -309,7 +310,7 @@ static int ath5k_pci_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
/*
* Suspend/Resume resets the PCI configuration space, so we have to
@@ -318,7 +319,7 @@ static int ath5k_pci_resume(struct device *dev)
*/
pci_write_config_byte(pdev, 0x41, 0);
- ath5k_led_enable(sc);
+ ath5k_led_enable(ah);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 712a9ac..a7eafa3 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -29,10 +29,9 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*
- * AR5212+ can use higher rates for ack transmition
+ * AR5212+ can use higher rates for ack transmission
* based on current tx rate instead of the base rate.
* It does this to better utilize channel usage.
* This is a mapping between G rates (that cover both
@@ -77,14 +76,13 @@ static const unsigned int ack_rates_high[] =
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate, bool shortpre)
{
- struct ath5k_softc *sc = ah->ah_sc;
int sifs, preamble, plcp_bits, sym_time;
int bitrate, bits, symbols, symbol_bits;
int dur;
/* Fallback */
if (!ah->ah_bwmode) {
- __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
+ __le16 raw_dur = ieee80211_generic_frame_duration(ah->hw,
NULL, len, rate);
/* subtract difference between long and short preamble */
@@ -153,7 +151,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
case AR5K_BWMODE_DEFAULT:
default:
slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
- if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)
+ if ((channel->hw_value == AR5K_MODE_11B) && !ah->ah_short_slot)
slot_time = AR5K_INIT_SLOT_TIME_B;
break;
}
@@ -184,7 +182,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
case AR5K_BWMODE_DEFAULT:
sifs = AR5K_INIT_SIFS_DEFAULT_BG;
default:
- if (channel->hw_value & CHANNEL_5GHZ)
+ if (channel->band == IEEE80211_BAND_5GHZ)
sifs = AR5K_INIT_SIFS_DEFAULT_A;
break;
}
@@ -205,7 +203,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
*/
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
{
- struct ath5k_statistics *stats = &ah->ah_sc->stats;
+ struct ath5k_statistics *stats = &ah->stats;
/* Read-And-Clear */
stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
@@ -240,25 +238,24 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
struct ieee80211_rate *rate;
unsigned int i;
/* 802.11g covers both OFDM and CCK */
u8 band = IEEE80211_BAND_2GHZ;
/* Write rate duration table */
- for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
+ for (i = 0; i < ah->sbands[band].n_bitrates; i++) {
u32 reg;
u16 tx_time;
if (ah->ah_ack_bitrate_high)
- rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
+ rate = &ah->sbands[band].bitrates[ack_rates_high[i]];
/* CCK -> 1Mb */
else if (i < 4)
- rate = &sc->sbands[band].bitrates[0];
+ rate = &ah->sbands[band].bitrates[0];
/* OFDM -> 6Mb */
else
- rate = &sc->sbands[band].bitrates[4];
+ rate = &ah->sbands[band].bitrates[4];
/* Set ACK timeout */
reg = AR5K_RATE_DUR(rate->hw_value);
@@ -534,9 +531,9 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
local_irq_restore(flags);
- WARN_ON( i == ATH5K_MAX_TSF_READ );
+ WARN_ON(i == ATH5K_MAX_TSF_READ);
- return (((u64)tsf_upper1 << 32) | tsf_lower);
+ return ((u64)tsf_upper1 << 32) | tsf_lower;
}
/**
@@ -586,7 +583,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
/*
* Set the additional timers by mode
*/
- switch (ah->ah_sc->opmode) {
+ switch (ah->opmode) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_STATION:
/* In STA mode timer1 is used as next wakeup
@@ -623,8 +620,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
* Set the beacon register and enable all timers.
*/
/* When in AP or Mesh Point mode zero timer0 to start TSF */
- if (ah->ah_sc->opmode == NL80211_IFTYPE_AP ||
- ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT)
+ if (ah->opmode == NL80211_IFTYPE_AP ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT)
ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
@@ -643,14 +640,14 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
/* Flush any pending BMISS interrupts on ISR by
* performing a clear-on-write operation on PISR
* register for the BMISS bit (writing a bit on
- * ISR togles a reset for that bit and leaves
- * the rest bits intact) */
+ * ISR toggles a reset for that bit and leaves
+ * the remaining bits intact) */
if (ah->ah_version == AR5K_AR5210)
ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
else
ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
- /* TODO: Set enchanced sleep registers on AR5212
+ /* TODO: Set enhanced sleep registers on AR5212
* based on vif->bss_conf params, until then
* disable power save reporting.*/
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
@@ -738,7 +735,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
/* NOTE: SWBA is different. Having a wrong window there does not
- * stop us from sending data and this condition is catched thru
+ * stop us from sending data and this condition is caught by
* other means (SWBA interrupt) */
if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
@@ -814,7 +811,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
struct ath_common *common = ath5k_hw_common(ah);
u32 pcu_reg, beacon_reg, low_id, high_id;
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
/* Preserve rest settings */
pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
@@ -890,13 +887,13 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* XXX: rethink this after new mode changes to
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->nvifs)
+ ah->nvifs)
ath5k_hw_write_rate_duration(ah);
/* Set RSSI/BRSSI thresholds
*
* Note: If we decide to set this value
- * dynamicaly, have in mind that when AR5K_RSSI_THR
+ * dynamically, have in mind that when AR5K_RSSI_THR
* register is read it might return 0x40 if we haven't
* wrote anything to it plus BMISS RSSI threshold is zeroed.
* So doing a save/restore procedure here isn't the right
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 5544191..01cb72d 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -22,12 +22,13 @@
#include <linux/delay.h>
#include <linux/slab.h>
+#include <asm/unaligned.h>
#include "ath5k.h"
#include "reg.h"
-#include "base.h"
#include "rfbuffer.h"
#include "rfgain.h"
+#include "../regd.h"
/******************\
@@ -37,7 +38,7 @@
/*
* Get the PHY Chip revision
*/
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band)
{
unsigned int i;
u32 srev;
@@ -46,11 +47,11 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
/*
* Set the radio chip access register
*/
- switch (chan) {
- case CHANNEL_2GHZ:
+ switch (band) {
+ case IEEE80211_BAND_2GHZ:
ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
break;
- case CHANNEL_5GHZ:
+ case IEEE80211_BAND_5GHZ:
ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
break;
default:
@@ -83,14 +84,16 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
/*
* Check if a channel is supported
*/
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel)
{
+ u16 freq = channel->center_freq;
+
/* Check if the channel is in our supported range */
- if (flags & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
(freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
return true;
- } else if (flags & CHANNEL_5GHZ)
+ } else if (channel->band == IEEE80211_BAND_5GHZ)
if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
(freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
return true;
@@ -105,6 +108,7 @@ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
if ((ah->ah_radio == AR5K_RF5112) ||
(ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2413) ||
(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
refclk_freq = 40;
else
@@ -173,7 +177,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
data = ath5k_hw_bitswap(val, num_bits);
for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
- position = 0, entry++) {
+ position = 0, entry++) {
last_bit = (position + bits_left > 8) ? 8 :
position + bits_left;
@@ -222,7 +226,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
ds_coef_exp, ds_coef_man, clock;
BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
- !(channel->hw_value & CHANNEL_OFDM));
+ (channel->hw_value == AR5K_MODE_11B));
/* Get coefficient
* ALGO: coef = (5 * clock / carrier_freq) / 2
@@ -296,7 +300,7 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
u32 delay;
delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
AR5K_PHY_RX_DELAY_M;
- delay = (channel->hw_value & CHANNEL_CCK) ?
+ delay = (channel->hw_value == AR5K_MODE_11B) ?
((delay << 2) / 22) : (delay / 10);
if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
delay = delay << 1;
@@ -363,7 +367,7 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
return 0;
}
-/* Schedule a gain probe check on the next transmited packet.
+/* Schedule a gain probe check on the next transmitted packet.
* That means our next packet is going to be sent with lower
* tx power and a Peak to Average Power Detector (PAPD) will try
* to measure the gain.
@@ -472,7 +476,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
level[0] = 0;
level[1] = (step == 63) ? 50 : step + 4;
level[2] = (step != 63) ? 64 : level[0];
- level[3] = level[2] + 50 ;
+ level[3] = level[2] + 50;
ah->ah_gain.g_high = level[3] -
(step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
@@ -549,7 +553,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
for (ah->ah_gain.g_target = ah->ah_gain.g_current;
ah->ah_gain.g_target <= ah->ah_gain.g_low &&
- ah->ah_gain.g_step_idx < go->go_steps_count-1;
+ ah->ah_gain.g_step_idx < go->go_steps_count - 1;
g_step = &go->go_step[ah->ah_gain.g_step_idx])
ah->ah_gain.g_target -= 2 *
(go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
@@ -560,7 +564,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
}
done:
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"ret %d, gain step %u, current gain %u, target gain %u\n",
ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
ah->ah_gain.g_target);
@@ -614,13 +618,13 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
ath5k_hw_rf_gainf_corr(ah);
ah->ah_gain.g_current =
ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
- (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+ (ah->ah_gain.g_current - ah->ah_gain.g_f_corr) :
0;
}
/* Check if measurement is ok and if we need
* to adjust gain, schedule a gain adjustment,
- * else switch back to the acive state */
+ * else switch back to the active state */
if (ath5k_hw_rf_check_gainf_readback(ah) &&
AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
ath5k_hw_rf_gainf_adjust(ah)) {
@@ -772,7 +776,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
GFP_KERNEL);
if (ah->ah_rf_banks == NULL) {
- ATH5K_ERR(ah->ah_sc, "out of memory\n");
+ ATH5K_ERR(ah, "out of memory\n");
return -ENOMEM;
}
}
@@ -782,7 +786,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
for (i = 0; i < ah->ah_rf_banks_size; i++) {
if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
- ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+ ATH5K_ERR(ah, "invalid bank\n");
return -EINVAL;
}
@@ -796,9 +800,9 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
}
/* Set Output and Driver bias current (OB/DB) */
- if (channel->hw_value & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
- if (channel->hw_value & CHANNEL_CCK)
+ if (channel->hw_value == AR5K_MODE_11B)
ee_mode = AR5K_EEPROM_MODE_11B;
else
ee_mode = AR5K_EEPROM_MODE_11G;
@@ -807,7 +811,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
* use b_OB and b_DB parameters stored
* in eeprom on ee->ee_ob[ee_mode][0]
*
- * For all other chips we use OB/DB for 2Ghz
+ * For all other chips we use OB/DB for 2GHz
* stored in the b/g modal section just like
* 802.11a on ee->ee_ob[ee_mode][1] */
if ((ah->ah_radio == AR5K_RF5111) ||
@@ -823,7 +827,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
AR5K_RF_DB_2GHZ, true);
/* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
- } else if ((channel->hw_value & CHANNEL_5GHZ) ||
+ } else if ((channel->band == IEEE80211_BAND_5GHZ) ||
(ah->ah_radio == AR5K_RF5111)) {
/* For 11a, Turbo and XR we need to choose
@@ -855,7 +859,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
if (ah->ah_radio == AR5K_RF5111) {
/* Set gain_F settings according to current step */
- if (channel->hw_value & CHANNEL_OFDM) {
+ if (channel->hw_value != AR5K_MODE_11B) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
AR5K_PHY_FRAME_CTL_TX_CLIP,
@@ -912,7 +916,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
if (ah->ah_radio == AR5K_RF5112) {
/* Set gain_F settings according to current step */
- if (channel->hw_value & CHANNEL_OFDM) {
+ if (channel->hw_value != AR5K_MODE_11B) {
ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
AR5K_RF_MIXGAIN_OVR, true);
@@ -970,17 +974,20 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
}
/* Lower synth voltage on Rev 2 */
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_HIGH_VC_CP, true);
+ if (ah->ah_radio == AR5K_RF5112 &&
+ (ah->ah_radio_5ghz_revision & AR5K_SREV_REV) > 0) {
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_HIGH_VC_CP, true);
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_MID_VC_CP, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_MID_VC_CP, true);
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_LOW_VC_CP, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_LOW_VC_CP, true);
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_PUSH_UP, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_PUSH_UP, true);
+ }
/* Decrease power consumption on 5213+ BaseBand */
if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
@@ -1021,7 +1028,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
}
if (ah->ah_radio == AR5K_RF5413 &&
- channel->hw_value & CHANNEL_2GHZ) {
+ channel->band == IEEE80211_BAND_2GHZ) {
ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
true);
@@ -1133,7 +1140,7 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
*/
data0 = data1 = 0;
- if (channel->hw_value & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
/* Map 2GHz channel to 5GHz Atheros channel ID */
ret = ath5k_hw_rf5111_chan2athchan(
ieee80211_frequency_to_channel(channel->center_freq),
@@ -1259,12 +1266,11 @@ static int ath5k_hw_channel(struct ath5k_hw *ah,
{
int ret;
/*
- * Check bounds supported by the PHY (we don't care about regultory
- * restrictions at this point). Note: hw_value already has the band
- * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
- * of the band by that */
- if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
- ATH5K_ERR(ah->ah_sc,
+ * Check bounds supported by the PHY (we don't care about regulatory
+ * restrictions at this point).
+ */
+ if (!ath5k_channel_ok(ah, channel)) {
+ ATH5K_ERR(ah,
"channel frequency (%u MHz) out of supported "
"band range\n",
channel->center_freq);
@@ -1331,7 +1337,7 @@ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)
{
struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist;
- hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1);
+ hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX - 1);
hist->nfval[hist->index] = noise_floor;
}
@@ -1344,18 +1350,18 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {
for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) {
- if (sort[j] > sort[j-1]) {
+ if (sort[j] > sort[j - 1]) {
tmp = sort[j];
- sort[j] = sort[j-1];
- sort[j-1] = tmp;
+ sort[j] = sort[j - 1];
+ sort[j - 1] = tmp;
}
}
}
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"cal %d:%d\n", i, sort[i]);
}
- return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2];
+ return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2];
}
/*
@@ -1378,7 +1384,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
/* keep last value if calibration hasn't completed */
if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"NF did not complete in calibration window\n");
return;
@@ -1391,7 +1397,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
threshold = ee->ee_noise_floor_thr[ee_mode];
if (nf > threshold) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"noise floor failure detected; "
"read %d, threshold %d\n",
nf, threshold);
@@ -1428,7 +1434,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
ah->ah_noise_floor = nf;
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"noise floor calibrated: %d\n", nf);
}
@@ -1516,7 +1522,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+ ATH5K_ERR(ah, "calibration timeout (%uMHz)\n",
channel->center_freq);
return ret;
}
@@ -1551,7 +1557,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE,
"iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr);
if (i_pwr && q_pwr)
break;
@@ -1577,7 +1583,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
q_coff = (i_pwr / q_coffd) - 128;
q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE,
"new I:%d Q:%d (i_coffd:%x q_coffd:%x)",
i_coff, q_coff, i_coffd, q_coffd);
@@ -1604,11 +1610,13 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
int ret;
if (ah->ah_radio == AR5K_RF5110)
- ret = ath5k_hw_rf5110_calibrate(ah, channel);
- else {
- ret = ath5k_hw_rf511x_iq_calibrate(ah);
+ return ath5k_hw_rf5110_calibrate(ah, channel);
+
+ ret = ath5k_hw_rf511x_iq_calibrate(ah);
+
+ if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) &&
+ (channel->hw_value != AR5K_MODE_11B))
ath5k_hw_request_rfgain_probe(ah);
- }
return ret;
}
@@ -1634,7 +1642,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
/* Convert current frequency to fbin value (the same way channels
* are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale
* up by 2 so we can compare it later */
- if (channel->hw_value & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
chan_fbin = (channel->center_freq - 2300) * 10;
freq_band = AR5K_EEPROM_BAND_2GHZ;
} else {
@@ -1696,7 +1704,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
spur_freq_sigma_delta = (spur_delta_phase >> 10);
symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4;
default:
- if (channel->hw_value == CHANNEL_A) {
+ if (channel->band == IEEE80211_BAND_5GHZ) {
/* Both sample_freq and chip_freq are 40MHz */
spur_delta_phase = (spur_offset << 17) / 25;
spur_freq_sigma_delta =
@@ -1815,7 +1823,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
} else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &
AR5K_PHY_IQ_SPUR_FILT_EN) {
- /* Clean up spur mitigation settings and disable fliter */
+ /* Clean up spur mitigation settings and disable filter */
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
AR5K_PHY_BIN_MASK_CTL_RATE, 0);
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ,
@@ -1960,7 +1968,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
ee_mode = ath5k_eeprom_mode_from_channel(channel);
if (ee_mode < 0) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid channel: %d\n", channel->center_freq);
return;
}
@@ -2080,7 +2088,7 @@ ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
* always 1 instead of 1.25, 1.75 etc). We scale up by 100
* to have some accuracy both for 0.5 and 0.25 steps.
*/
- ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
+ ratio = ((100 * y_right - 100 * y_left) / (x_right - x_left));
/* Now scale down to be in range */
result = y_left + (ratio * (target - x_left) / 100);
@@ -2159,7 +2167,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax,
u8 *vpd_table, u8 type)
{
u8 idx[2] = { 0, 1 };
- s16 pwr_i = 2*pmin;
+ s16 pwr_i = 2 * pmin;
int i;
if (num_points < 2)
@@ -2219,15 +2227,20 @@ ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
idx_l = 0;
idx_r = 0;
- if (!(channel->hw_value & CHANNEL_OFDM)) {
+ switch (channel->hw_value) {
+ case AR5K_EEPROM_MODE_11A:
+ pcinfo = ee->ee_pwr_cal_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case AR5K_EEPROM_MODE_11B:
pcinfo = ee->ee_pwr_cal_b;
mode = AR5K_EEPROM_MODE_11B;
- } else if (channel->hw_value & CHANNEL_2GHZ) {
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ default:
pcinfo = ee->ee_pwr_cal_g;
mode = AR5K_EEPROM_MODE_11G;
- } else {
- pcinfo = ee->ee_pwr_cal_a;
- mode = AR5K_EEPROM_MODE_11A;
+ break;
}
max = ee->ee_n_piers[mode] - 1;
@@ -2296,15 +2309,20 @@ ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
idx_l = 0;
idx_r = 0;
- if (!(channel->hw_value & CHANNEL_OFDM)) {
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
+ rpinfo = ee->ee_rate_tpwr_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case AR5K_MODE_11B:
rpinfo = ee->ee_rate_tpwr_b;
mode = AR5K_EEPROM_MODE_11B;
- } else if (channel->hw_value & CHANNEL_2GHZ) {
+ break;
+ case AR5K_MODE_11G:
+ default:
rpinfo = ee->ee_rate_tpwr_g;
mode = AR5K_EEPROM_MODE_11G;
- } else {
- rpinfo = ee->ee_rate_tpwr_a;
- mode = AR5K_EEPROM_MODE_11A;
+ break;
}
max = ee->ee_rate_target_pwr_num[mode] - 1;
@@ -2385,24 +2403,22 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band);
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
ctl_mode |= AR5K_CTL_TURBO;
else
ctl_mode |= AR5K_CTL_11A;
break;
- case CHANNEL_G:
+ case AR5K_MODE_11G:
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
ctl_mode |= AR5K_CTL_TURBOG;
else
ctl_mode |= AR5K_CTL_11G;
break;
- case CHANNEL_B:
+ case AR5K_MODE_11B:
ctl_mode |= AR5K_CTL_11B;
break;
- case CHANNEL_XR:
- /* Fall through */
default:
return;
}
@@ -2437,7 +2453,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
}
if (edge_pwr)
- ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
+ ah->ah_txpower.txp_max_pwr = 4 * min(edge_pwr, max_chan_pwr);
}
@@ -2456,7 +2472,7 @@ static void
ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
s16 *table_max)
{
- u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
s16 min_pwr, max_pwr;
@@ -2475,8 +2491,8 @@ ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
/* Copy values from pcdac_tmp */
pwr_idx = min_pwr;
- for (i = 0 ; pwr_idx <= max_pwr &&
- pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
+ for (i = 0; pwr_idx <= max_pwr &&
+ pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
pcdac_out[pcdac_i++] = pcdac_tmp[i];
pwr_idx++;
}
@@ -2502,7 +2518,7 @@ static void
ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
s16 *table_max, u8 pdcurves)
{
- u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
u8 *pcdac_low_pwr;
u8 *pcdac_high_pwr;
u8 *pcdac_tmp;
@@ -2510,8 +2526,8 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
s16 max_pwr_idx;
s16 min_pwr_idx;
s16 mid_pwr_idx = 0;
- /* Edge flag turs on the 7nth bit on the PCDAC
- * to delcare the higher power curve (force values
+ /* Edge flag turns on the 7nth bit on the PCDAC
+ * to declare the higher power curve (force values
* to be greater than 64). If we only have one curve
* we don't need to set this, if we have 2 curves and
* fill the table backwards this can also be used to
@@ -2552,7 +2568,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
}
/* This is used when setting tx power*/
- ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
+ ah->ah_txpower.txp_min_idx = min_pwr_idx / 2;
/* Fill Power to PCDAC table backwards */
pwr = max_pwr_idx;
@@ -2561,14 +2577,14 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
* edge flag and set pcdac_tmp to lower
* power curve.*/
if (edge_flag == 0x40 &&
- (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
+ (2 * pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
edge_flag = 0x00;
pcdac_tmp = pcdac_low_pwr;
- pwr = mid_pwr_idx/2;
+ pwr = mid_pwr_idx / 2;
}
/* Don't go below 1, extrapolate below if we have
- * already swithced to the lower power curve -or
+ * already switched to the lower power curve -or
* we only have one curve and edge_flag is zero
* anyway */
if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
@@ -2596,7 +2612,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
static void
ath5k_write_pcdac_table(struct ath5k_hw *ah)
{
- u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
int i;
/*
@@ -2604,8 +2620,8 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah)
*/
for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
ath5k_hw_reg_write(ah,
- (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
- (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
+ (((pcdac_out[2 * i + 0] << 8 | 0xff) & 0xffff) << 0) |
+ (((pcdac_out[2 * i + 1] << 8 | 0xff) & 0xffff) << 16),
AR5K_PHY_PCDAC_TXPOWER(i));
}
}
@@ -2788,12 +2804,8 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
* Write TX power values
*/
for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
- ath5k_hw_reg_write(ah,
- ((pdadc_out[4*i + 0] & 0xff) << 0) |
- ((pdadc_out[4*i + 1] & 0xff) << 8) |
- ((pdadc_out[4*i + 2] & 0xff) << 16) |
- ((pdadc_out[4*i + 3] & 0xff) << 24),
- AR5K_PHY_PDADC_TXPOWER(i));
+ u32 val = get_unaligned_le32(&pdadc_out[4 * i]);
+ ath5k_hw_reg_write(ah, val, AR5K_PHY_PDADC_TXPOWER(i));
}
}
@@ -2805,7 +2817,7 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
/*
* This is the main function that uses all of the above
* to set PCDAC/PDADC table on hw for the current channel.
- * This table is used for tx power calibration on the basband,
+ * This table is used for tx power calibration on the baseband,
* without it we get weird tx power levels and in some cases
* distorted spectral mask
*/
@@ -3116,13 +3128,13 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
int ret;
if (txpower > AR5K_TUNE_MAX_TXPOWER) {
- ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
+ ATH5K_ERR(ah, "invalid tx power: %u\n", txpower);
return -EINVAL;
}
ee_mode = ath5k_eeprom_mode_from_channel(channel);
if (ee_mode < 0) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid channel: %d\n", channel->center_freq);
return -EINVAL;
}
@@ -3223,7 +3235,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
{
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
+ ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER,
"changing txpower to %d\n", txpower);
return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower);
@@ -3289,7 +3301,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
/* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 &&
- channel->hw_value & CHANNEL_OFDM) {
+ channel->hw_value != AR5K_MODE_11B) {
ret = ath5k_hw_write_ofdm_timings(ah, channel);
if (ret)
@@ -3434,7 +3446,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
* during ath5k_phy_calibrate) */
if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL, 0, false)) {
- ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+ ATH5K_ERR(ah, "gain calibration timeout (%uMHz)\n",
channel->center_freq);
}
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index b18c502..ff3d348 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -23,7 +23,6 @@ Queue Control Unit, DFS Control Unit Functions
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/******************\
@@ -168,13 +167,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
} else {
switch (queue_type) {
case AR5K_TX_QUEUE_DATA:
- for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
- ah->ah_txq[queue].tqi_type !=
- AR5K_TX_QUEUE_INACTIVE; queue++) {
-
- if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
- return -EINVAL;
- }
+ queue = queue_info->tqi_subtype;
break;
case AR5K_TX_QUEUE_UAPSD:
queue = AR5K_TX_QUEUE_ID_UAPSD;
@@ -185,13 +178,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
case AR5K_TX_QUEUE_CAB:
queue = AR5K_TX_QUEUE_ID_CAB;
break;
- case AR5K_TX_QUEUE_XR_DATA:
- if (ah->ah_version != AR5K_AR5212)
- ATH5K_ERR(ah->ah_sc,
- "XR data queues only supported in"
- " 5212!\n");
- queue = AR5K_TX_QUEUE_ID_XR_DATA;
- break;
default:
return -EINVAL;
}
@@ -510,7 +496,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
{
struct ieee80211_channel *channel = ah->ah_current_channel;
- struct ath5k_softc *sc = ah->ah_sc;
struct ieee80211_rate *rate;
u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
@@ -545,10 +530,10 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
*
* Also we have different lowest rate for 802.11a
*/
- if (channel->hw_value & CHANNEL_5GHZ)
- rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
+ if (channel->band == IEEE80211_BAND_5GHZ)
+ rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
else
- rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+ rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
@@ -622,7 +607,7 @@ int ath5k_hw_init_queues(struct ath5k_hw *ah)
for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
ret = ath5k_hw_reset_tx_queue(ah, i);
if (ret) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"failed to reset TX queue #%d\n", i);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index d12b827..f5c1000 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -72,7 +72,7 @@
#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
-#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
+#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
@@ -170,7 +170,7 @@
#define AR5K_TXCFG_SDMAMR_S 0
#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
-#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Trigger level mask */
#define AR5K_TXCFG_TXFULL_S 4
#define AR5K_TXCFG_TXFULL_0B 0x00000000
#define AR5K_TXCFG_TXFULL_64B 0x00000010
@@ -283,16 +283,16 @@
*/
#define AR5K_ISR 0x001c /* Register Address [5210] */
#define AR5K_PISR 0x0080 /* Register Address [5211+] */
-#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly received */
+#define AR5K_ISR_RXOK 0x00000001 /* Frame successfully received */
#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
-#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
+#define AR5K_ISR_TXOK 0x00000040 /* Frame successfully transmitted */
#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
-#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) */
#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
@@ -303,7 +303,7 @@
#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
-#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
@@ -377,16 +377,16 @@
*/
#define AR5K_IMR 0x0020 /* Register Address [5210] */
#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
-#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly received*/
+#define AR5K_IMR_RXOK 0x00000001 /* Frame successfully received*/
#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
-#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
+#define AR5K_IMR_TXOK 0x00000040 /* Frame successfully transmitted*/
#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
-#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout)*/
#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
@@ -397,7 +397,7 @@
#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
-#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/
#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */
@@ -601,7 +601,7 @@
* QCU misc registers
*/
#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
-#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
+#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame scheduling mask */
#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */
@@ -653,13 +653,13 @@
* registers [5211+]
*
* These registers control the various characteristics of each queue
- * for 802.11e (WME) combatibility so they go together with
+ * for 802.11e (WME) compatibility so they go together with
* QCU registers in pairs. For each queue we have a QCU mask register,
* (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
* a retry limit register (0x1080 - 0x10ac), a channel time register
* (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
* a sequence number register (0x1140 - 0x116c). It seems that "global"
- * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * registers here affect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
* We use the same macros here for easier register access.
*
*/
@@ -779,7 +779,7 @@
* and it's used for generating pseudo-random
* number sequences.
*
- * (If i understand corectly, random numbers are
+ * (If i understand correctly, random numbers are
* used for idle sensing -multiplied with cwmin/max etc-)
*/
#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
@@ -1007,7 +1007,7 @@
#define AR5K_PCIE_WAEN 0x407c
/*
- * PCI-E Serializer/Desirializer
+ * PCI-E Serializer/Deserializer
* registers
*/
#define AR5K_PCIE_SERDES 0x4080
@@ -1227,7 +1227,7 @@
AR5K_USEC_5210 : AR5K_USEC_5211)
#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */
#define AR5K_USEC_1_S 0
-#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */
+#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32MHz clock */
#define AR5K_USEC_32_S 7
#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
#define AR5K_USEC_TX_LATENCY_5211_S 14
@@ -1328,16 +1328,16 @@
#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
-#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
-#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
-#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
-#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
-#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
-#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
-#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
+#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
+#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
+#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
+#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
+#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
+#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
+#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
-#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
+#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
#define AR5K_RX_FILTER_PHYERR \
@@ -1461,7 +1461,7 @@
* ADDAC test register [5211+]
*/
#define AR5K_ADDAC_TEST 0x8054 /* Register Address */
-#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
+#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */
#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */
#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */
@@ -1632,7 +1632,7 @@
#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */
#define AR5K_SLEEP0_NEXT_DTIM_S 0
#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */
-#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */
+#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enhanced sleep control */
#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */
#define AR5K_SLEEP0_CABTO_S 24
@@ -1657,7 +1657,7 @@
/*
* TX power control (TPC) register
*
- * XXX: PCDAC steps (0.5dbm) or DBM ?
+ * XXX: PCDAC steps (0.5dBm) or dBm ?
*
*/
#define AR5K_TXPC 0x80e8 /* Register Address */
@@ -1673,7 +1673,7 @@
/*
* Profile count registers
*
- * These registers can be cleared and freezed with ATH5K_MIBC, but they do not
+ * These registers can be cleared and frozen with ATH5K_MIBC, but they do not
* generate a MIB interrupt.
* Instead of overflowing, they shift by one bit to the right. All registers
* shift together, i.e. when one reaches the max, all shift at the same time by
@@ -1838,7 +1838,7 @@
#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
-#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */
+#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32kHz external) */
#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */
#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */
@@ -2002,7 +2002,7 @@
#define AR5K_PHY_AGCCTL_OFDM_DIV_DIS 0x00000008 /* Disable antenna diversity on OFDM modes */
#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */
#define AR5K_PHY_AGCTL_FLTR_CAL 0x00010000 /* Allow filter calibration (?) */
-#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
+#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automatically */
/*
* PHY noise floor status register (CCA = Clear Channel Assessment)
@@ -2038,7 +2038,7 @@
#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24
/* Low thresholds */
-#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
+#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001
#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00
#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8
@@ -2089,7 +2089,7 @@
*
* It's obvious from the code that 0x989c is the buffer register but
* for the other special registers that we write to after sending each
- * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * packet, i have no idea. So I'll name them BUFFER_CONTROL_X registers
* for now. It's interesting that they are also used for some other operations.
*/
@@ -2259,12 +2259,13 @@
#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */
#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */
-#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
- AR5K_PHY_FRAME_CTL_TXURN_ERR | \
- AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
- AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
- AR5K_PHY_FRAME_CTL_PARITY_ERR | \
- AR5K_PHY_FRAME_CTL_TIMING_ERR
+#define AR5K_PHY_FRAME_CTL_INI \
+ (AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+ AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+ AR5K_PHY_FRAME_CTL_TIMING_ERR)
/*
* PHY Tx Power adjustment register [5212A+]
@@ -2281,22 +2282,22 @@
#define AR5K_PHY_RADAR 0x9954
#define AR5K_PHY_RADAR_ENABLE 0x00000001
#define AR5K_PHY_RADAR_DISABLE 0x00000000
-#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
5-bits, units unknown {0..31}
(? MHz ?) */
#define AR5K_PHY_RADAR_INBANDTHR_S 1
-#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
+#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
6-bits, dBm range {0..63}
in dBm units. */
#define AR5K_PHY_RADAR_PRSSI_THR_S 6
-#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
+#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
6-bits, dBm range {0..63}
in dBm units. */
#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12
-#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
+#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
6-bits, dBm range {0..63}
in dBm units. */
#define AR5K_PHY_RADAR_RSSI_THR_S 18
@@ -2339,7 +2340,7 @@
#define AR5K_PHY_RESTART_DIV_GC_S 18
/*
- * RF Bus access request register (for synth-oly channel switching)
+ * RF Bus access request register (for synth-only channel switching)
*/
#define AR5K_PHY_RFBUS_REQ 0x997C
#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001
@@ -2381,7 +2382,7 @@
*/
#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
-#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
+#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplifier Gain table base address */
#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
/*
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 126a4ea..2abac25 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -25,12 +25,11 @@
#include <asm/unaligned.h>
-#include <linux/pci.h> /* To determine if a card is pci-e */
+#include <linux/pci.h> /* To determine if a card is pci-e */
#include <linux/log2.h>
#include <linux/platform_device.h>
#include "ath5k.h"
#include "reg.h"
-#include "base.h"
#include "debug.h"
@@ -102,12 +101,18 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
/*
* Set core clock frequency
*/
- if (channel->hw_value & CHANNEL_5GHZ)
- clock = 40; /* 802.11a */
- else if (channel->hw_value & CHANNEL_CCK)
- clock = 22; /* 802.11b */
- else
- clock = 44; /* 802.11g */
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
+ clock = 40;
+ break;
+ case AR5K_MODE_11B:
+ clock = 22;
+ break;
+ case AR5K_MODE_11G:
+ default:
+ clock = 44;
+ break;
+ }
/* Use clock multiplier for non-default
* bwmode */
@@ -142,10 +147,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
/* Set 32MHz USEC counter */
if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_radio == AR5K_RF2316) ||
- (ah->ah_radio == AR5K_RF2317))
- /* Remain on 40MHz clock ? */
+ (ah->ah_radio == AR5K_RF2413) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_radio == AR5K_RF2317))
+ /* Remain on 40MHz clock ? */
sclock = 40 - 1;
else
sclock = 32 - 1;
@@ -213,7 +219,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
usec_reg = (usec | sclock | txlat | rxlat);
ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
- /* On 5112 set tx frane to tx data start delay */
+ /* On 5112 set tx frame to tx data start delay */
if (ah->ah_radio == AR5K_RF5112) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
AR5K_PHY_RF_CTL2_TXF2TXD_START,
@@ -233,7 +239,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- u32 scal, spending;
+ u32 scal, spending, sclock;
/* Only set 32KHz settings if we have an external
* 32KHz crystal present */
@@ -317,6 +323,15 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
/* Set up tsf increment on each cycle */
AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_radio == AR5K_RF2317))
+ sclock = 40 - 1;
+ else
+ sclock = 32 - 1;
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
}
}
@@ -375,20 +390,20 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
{
u32 mask = flags ? flags : ~0U;
- volatile u32 *reg;
+ u32 __iomem *reg;
u32 regval;
u32 val = 0;
/* ah->ah_mac_srev is not available at this point yet */
- if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
- reg = (u32 *) AR5K_AR2315_RESET;
+ if (ah->devid >= AR5K_SREV_AR2315_R6) {
+ reg = (u32 __iomem *) AR5K_AR2315_RESET;
if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR2315_RESET_WMAC;
if (mask & AR5K_RESET_CTL_BASEBAND)
val |= AR5K_AR2315_RESET_BB_WARM;
} else {
- reg = (u32 *) AR5K_AR5312_RESET;
- if (to_platform_device(ah->ah_sc->dev)->id == 0) {
+ reg = (u32 __iomem *) AR5K_AR5312_RESET;
+ if (to_platform_device(ah->dev)->id == 0) {
if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR5312_RESET_WMAC0;
if (mask & AR5K_RESET_CTL_BASEBAND)
@@ -520,7 +535,7 @@ commit:
*/
int ath5k_hw_on_hold(struct ath5k_hw *ah)
{
- struct pci_dev *pdev = ah->ah_sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
u32 bus_flags;
int ret;
@@ -530,7 +545,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
/* Make sure device is awake */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
return ret;
}
@@ -539,7 +554,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
*
* Note: putting PCI core on warm reset on PCI-E cards
* results card to hang and always return 0xffff... so
- * we ingore that flag for PCI-E cards. On PCI cards
+ * we ignore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
*/
bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
@@ -555,14 +570,14 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
}
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
+ ATH5K_ERR(ah, "failed to put device on warm reset\n");
return -EIO;
}
/* ...wakeup again!*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
+ ATH5K_ERR(ah, "failed to put device on hold\n");
return ret;
}
@@ -571,10 +586,11 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
/*
* Bring up MAC + PHY Chips and program PLL
+ * Channel is NULL for the initial wakeup.
*/
-int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
{
- struct pci_dev *pdev = ah->ah_sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
u32 turbo, mode, clock, bus_flags;
int ret;
@@ -582,11 +598,11 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
mode = 0;
clock = 0;
- if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) {
+ if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) {
/* Wakeup the device */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
return ret;
}
}
@@ -596,7 +612,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
*
* Note: putting PCI core on warm reset on PCI-E cards
* results card to hang and always return 0xffff... so
- * we ingore that flag for PCI-E cards. On PCI cards
+ * we ignore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
*/
bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
@@ -616,18 +632,18 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to reset the MAC Chip\n");
return -EIO;
}
/* ...wakeup again!...*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to resume the MAC Chip\n");
return ret;
}
- /* ...reset configuration regiter on Wisoc ...
+ /* ...reset configuration register on Wisoc ...
* ...clear reset control register and pull device out of
* warm reset on others */
if (ath5k_get_bus_type(ah) == ATH_AHB)
@@ -636,13 +652,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
ret = ath5k_hw_nic_reset(ah, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n");
return -EIO;
}
/* On initialization skip PLL programming since we don't have
* a channel / mode set yet */
- if (initial)
+ if (!channel)
return 0;
if (ah->ah_version != AR5K_AR5210) {
@@ -658,13 +674,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
clock = AR5K_PHY_PLL_RF5111; /*Zero*/
}
- if (flags & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
mode |= AR5K_PHY_MODE_FREQ_2GHZ;
clock |= AR5K_PHY_PLL_44MHZ;
- if (flags & CHANNEL_CCK) {
+ if (channel->hw_value == AR5K_MODE_11B) {
mode |= AR5K_PHY_MODE_MOD_CCK;
- } else if (flags & CHANNEL_OFDM) {
+ } else {
/* XXX Dynamic OFDM/CCK is not supported by the
* AR5211 so we set MOD_OFDM for plain g (no
* CCK headers) operation. We need to test
@@ -676,35 +692,24 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
mode |= AR5K_PHY_MODE_MOD_OFDM;
else
mode |= AR5K_PHY_MODE_MOD_DYN;
- } else {
- ATH5K_ERR(ah->ah_sc,
- "invalid radio modulation mode\n");
- return -EINVAL;
}
- } else if (flags & CHANNEL_5GHZ) {
- mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+ } else if (channel->band == IEEE80211_BAND_5GHZ) {
+ mode |= (AR5K_PHY_MODE_FREQ_5GHZ |
+ AR5K_PHY_MODE_MOD_OFDM);
/* Different PLL setting for 5413 */
if (ah->ah_radio == AR5K_RF5413)
clock = AR5K_PHY_PLL_40MHZ_5413;
else
clock |= AR5K_PHY_PLL_40MHZ;
-
- if (flags & CHANNEL_OFDM)
- mode |= AR5K_PHY_MODE_MOD_OFDM;
- else {
- ATH5K_ERR(ah->ah_sc,
- "invalid radio modulation mode\n");
- return -EINVAL;
- }
} else {
- ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
+ ATH5K_ERR(ah, "invalid radio frequency mode\n");
return -EINVAL;
}
/*XXX: Can bwmode be used with dynamic mode ?
* (I don't think it supports 44MHz) */
- /* On 2425 initvals TURBO_SHORT is not pressent */
+ /* On 2425 initvals TURBO_SHORT is not present */
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
turbo = AR5K_PHY_TURBO_MODE |
(ah->ah_radio == AR5K_RF2425) ? 0 :
@@ -812,7 +817,7 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
u32 data;
ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
AR5K_PHY_CCKTXCTL);
- if (channel->hw_value & CHANNEL_5GHZ)
+ if (channel->band == IEEE80211_BAND_5GHZ)
data = 0xffb81020;
else
data = 0xffb80d20;
@@ -895,7 +900,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
/* Set CCK to OFDM power delta on tx power
* adjustment register */
if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
- if (channel->hw_value == CHANNEL_G)
+ if (channel->hw_value == AR5K_MODE_11G)
ath5k_hw_reg_write(ah,
AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
@@ -1066,7 +1071,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* RF Bus grant won't work if we have pending
* frames */
if (ret && fast) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"DMA didn't stop, falling back to normal reset\n");
fast = 0;
/* Non fatal, just continue with
@@ -1074,40 +1079,26 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ret = 0;
}
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
- mode = AR5K_MODE_11A;
+ mode = channel->hw_value;
+ switch (mode) {
+ case AR5K_MODE_11A:
break;
- case CHANNEL_G:
-
+ case AR5K_MODE_11G:
if (ah->ah_version <= AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"G mode not available on 5210/5211");
return -EINVAL;
}
-
- mode = AR5K_MODE_11G;
break;
- case CHANNEL_B:
-
+ case AR5K_MODE_11B:
if (ah->ah_version < AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"B mode not available on 5210");
return -EINVAL;
}
-
- mode = AR5K_MODE_11B;
- break;
- case CHANNEL_XR:
- if (ah->ah_version == AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
- "XR mode not available on 5211");
- return -EINVAL;
- }
- mode = AR5K_MODE_XR;
break;
default:
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid channel: %d\n", channel->center_freq);
return -EINVAL;
}
@@ -1119,13 +1110,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
if (fast) {
ret = ath5k_hw_phy_init(ah, channel, mode, true);
if (ret) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"fast chan change failed, falling back to normal reset\n");
/* Non fatal, can happen eg.
* on mode change */
ret = 0;
} else {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"fast chan change successful\n");
return 0;
}
@@ -1190,7 +1181,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}
/* Wakeup the device */
- ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ ret = ath5k_hw_nic_wakeup(ah, channel);
if (ret)
return ret;
@@ -1258,7 +1249,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*/
ret = ath5k_hw_phy_init(ah, channel, mode, false);
if (ret) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"failed to initialize PHY (%i) !\n", ret);
return ret;
}
@@ -1277,11 +1268,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ath5k_hw_dma_init(ah);
- /* Enable 32KHz clock function for AR5212+ chips
+ /*
+ * Enable 32KHz clock function for AR5212+ chips
* Set clocks to 32KHz operation and use an
* external 32KHz crystal when sleeping if one
- * exists */
- if (ah->ah_version == AR5K_AR5212 &&
+ * exists.
+ * Disabled by default because it is also disabled in
+ * other drivers and it is known to cause stability
+ * issues on some devices
+ */
+ if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 &&
op_mode != NL80211_IFTYPE_AP)
ath5k_hw_set_sleep_clock(ah, true);
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
index 16b67e8..5d11c23 100644
--- a/drivers/net/wireless/ath/ath5k/rfbuffer.h
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -254,7 +254,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = {
/* RFX112 (Derby 1) */
-/* BANK 6 len pos col */
+/* BANK 6 len pos col */
#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 }
#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 }
@@ -495,7 +495,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
/* BANK 2 len pos col */
#define AR5K_RF2413_RF_TURBO { 1, 1, 2 }
-/* BANK 6 len pos col */
+/* BANK 6 len pos col */
#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 }
#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 }
diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h
index 1354d8c..ebfae05 100644
--- a/drivers/net/wireless/ath/ath5k/rfgain.h
+++ b/drivers/net/wireless/ath/ath5k/rfgain.h
@@ -30,7 +30,7 @@ struct ath5k_ini_rfgain {
/* Initial RF Gain settings for RF5111 */
static const struct ath5k_ini_rfgain rfgain_5111[] = {
- /* 5Ghz 2Ghz */
+ /* 5GHz 2GHz */
{ AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
{ AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
{ AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
@@ -99,7 +99,7 @@ static const struct ath5k_ini_rfgain rfgain_5111[] = {
/* Initial RF Gain settings for RF5112 */
static const struct ath5k_ini_rfgain rfgain_5112[] = {
- /* 5Ghz 2Ghz */
+ /* 5GHz 2GHz */
{ AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
{ AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
{ AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
@@ -305,7 +305,7 @@ static const struct ath5k_ini_rfgain rfgain_2316[] = {
/* Initial RF Gain settings for RF5413 */
static const struct ath5k_ini_rfgain rfgain_5413[] = {
- /* 5Ghz 2Ghz */
+ /* 5GHz 2GHz */
{ AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
{ AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
{ AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
@@ -452,7 +452,7 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = {
/* Check if our current measurement is inside our
* current variable attenuation window */
-#define AR5K_GAIN_CHECK_ADJUST(_g) \
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
struct ath5k_gain_opt_step {
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c
index 41a877b..270a319 100644
--- a/drivers/net/wireless/ath/ath5k/rfkill.c
+++ b/drivers/net/wireless/ath/ath5k/rfkill.c
@@ -33,89 +33,84 @@
* THE POSSIBILITY OF SUCH DAMAGES.
*/
-#include "base.h"
+#include "ath5k.h"
-static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+static inline void ath5k_rfkill_disable(struct ath5k_hw *ah)
{
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
- sc->rf_kill.gpio, sc->rf_kill.polarity);
- ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
- ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
+ ah->rf_kill.gpio, ah->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
+ ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity);
}
-static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+static inline void ath5k_rfkill_enable(struct ath5k_hw *ah)
{
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
- sc->rf_kill.gpio, sc->rf_kill.polarity);
- ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
- ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
+ ah->rf_kill.gpio, ah->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
+ ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity);
}
-static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable)
+static inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable)
{
- struct ath5k_hw *ah = sc->ah;
u32 curval;
- ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
- curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
- ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+ ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);
+ curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio);
+ ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ?
!!curval : !curval);
}
static bool
-ath5k_is_rfkill_set(struct ath5k_softc *sc)
+ath5k_is_rfkill_set(struct ath5k_hw *ah)
{
/* configuring GPIO for input for some reason disables rfkill */
- /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
- return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
- sc->rf_kill.polarity;
+ /*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/
+ return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) ==
+ ah->rf_kill.polarity;
}
static void
ath5k_tasklet_rfkill_toggle(unsigned long data)
{
- struct ath5k_softc *sc = (void *)data;
+ struct ath5k_hw *ah = (void *)data;
bool blocked;
- blocked = ath5k_is_rfkill_set(sc);
- wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked);
+ blocked = ath5k_is_rfkill_set(ah);
+ wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked);
}
void
ath5k_rfkill_hw_start(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
-
/* read rfkill GPIO configuration from EEPROM header */
- sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
- sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
+ ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
+ ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
- tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
- (unsigned long)sc);
+ tasklet_init(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
+ (unsigned long)ah);
- ath5k_rfkill_disable(sc);
+ ath5k_rfkill_disable(ah);
/* enable interrupt for rfkill switch */
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
- ath5k_rfkill_set_intr(sc, true);
+ ath5k_rfkill_set_intr(ah, true);
}
void
ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
-
/* disable interrupt for rfkill switch */
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
- ath5k_rfkill_set_intr(sc, false);
+ ath5k_rfkill_set_intr(ah, false);
- tasklet_kill(&sc->rf_kill.toggleq);
+ tasklet_kill(&ah->rf_kill.toggleq);
/* enable RFKILL when stopping HW so Wifi LED is turned off */
- ath5k_rfkill_enable(sc);
+ ath5k_rfkill_enable(ah);
}
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index a073cdc..9364da7 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -1,7 +1,6 @@
#include <linux/device.h>
#include <linux/pci.h>
-#include "base.h"
#include "ath5k.h"
#include "reg.h"
@@ -11,8 +10,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
char *buf) \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
- struct ath5k_softc *sc = hw->priv; \
- return snprintf(buf, PAGE_SIZE, "%d\n", get); \
+ struct ath5k_hw *ah = hw->priv; \
+ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
} \
\
static ssize_t ath5k_attr_store_##name(struct device *dev, \
@@ -20,11 +19,13 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \
const char *buf, size_t count) \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
- struct ath5k_softc *sc = hw->priv; \
- int val; \
+ struct ath5k_hw *ah = hw->priv; \
+ int val, ret; \
\
- val = (int)simple_strtoul(buf, NULL, 10); \
- set(sc->ah, val); \
+ ret = kstrtoint(buf, 10, &val); \
+ if (ret < 0) \
+ return ret; \
+ set(ah, val); \
return count; \
} \
static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \
@@ -36,25 +37,25 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
char *buf) \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
- struct ath5k_softc *sc = hw->priv; \
- return snprintf(buf, PAGE_SIZE, "%d\n", get); \
+ struct ath5k_hw *ah = hw->priv; \
+ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
} \
static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
/*** ANI ***/
-SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init);
-SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level,
+SIMPLE_SHOW_STORE(ani_mode, ah->ani_state.ani_mode, ath5k_ani_init);
+SIMPLE_SHOW_STORE(noise_immunity_level, ah->ani_state.noise_imm_level,
ath5k_ani_set_noise_immunity_level);
-SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level,
+SIMPLE_SHOW_STORE(spur_level, ah->ani_state.spur_level,
ath5k_ani_set_spur_immunity_level);
-SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level,
+SIMPLE_SHOW_STORE(firstep_level, ah->ani_state.firstep_level,
ath5k_ani_set_firstep_level);
-SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig,
+SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, ah->ani_state.ofdm_weak_sig,
ath5k_ani_set_ofdm_weak_signal_detection);
-SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig,
+SIMPLE_SHOW_STORE(cck_weak_signal_detection, ah->ani_state.cck_weak_sig,
ath5k_ani_set_cck_weak_signal_detection);
-SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level);
+SIMPLE_SHOW(spur_level_max, ah->ani_state.max_spur_level);
static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
struct device_attribute *attr,
@@ -96,14 +97,14 @@ static struct attribute_group ath5k_attribute_group_ani = {
/*** register / unregister ***/
int
-ath5k_sysfs_register(struct ath5k_softc *sc)
+ath5k_sysfs_register(struct ath5k_hw *ah)
{
- struct device *dev = sc->dev;
+ struct device *dev = ah->dev;
int err;
err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
if (err) {
- ATH5K_ERR(sc, "failed to create sysfs group\n");
+ ATH5K_ERR(ah, "failed to create sysfs group\n");
return err;
}
@@ -111,9 +112,9 @@ ath5k_sysfs_register(struct ath5k_softc *sc)
}
void
-ath5k_sysfs_unregister(struct ath5k_softc *sc)
+ath5k_sysfs_unregister(struct ath5k_hw *ah)
{
- struct device *dev = sc->dev;
+ struct device *dev = ah->dev;
sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
}
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index 2de68ad..39f002e 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -2,7 +2,6 @@
#define __TRACE_ATH5K_H
#include <linux/tracepoint.h>
-#include "base.h"
#ifndef CONFIG_ATH5K_TRACER
#undef TRACE_EVENT
@@ -11,23 +10,22 @@ static inline void trace_ ## name(proto) {}
#endif
struct sk_buff;
-
-#define PRIV_ENTRY __field(struct ath5k_softc *, priv)
-#define PRIV_ASSIGN __entry->priv = priv
+struct ath5k_txq;
+struct ath5k_tx_status;
#undef TRACE_SYSTEM
#define TRACE_SYSTEM ath5k
TRACE_EVENT(ath5k_rx,
- TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb),
+ TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb),
TP_ARGS(priv, skb),
TP_STRUCT__entry(
- PRIV_ENTRY
+ __field(struct ath5k_hw *, priv)
__field(unsigned long, skbaddr)
__dynamic_array(u8, frame, skb->len)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ __entry->priv = priv;
__entry->skbaddr = (unsigned long) skb;
memcpy(__get_dynamic_array(frame), skb->data, skb->len);
),
@@ -37,20 +35,20 @@ TRACE_EVENT(ath5k_rx,
);
TRACE_EVENT(ath5k_tx,
- TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+ TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb,
struct ath5k_txq *q),
TP_ARGS(priv, skb, q),
TP_STRUCT__entry(
- PRIV_ENTRY
+ __field(struct ath5k_hw *, priv)
__field(unsigned long, skbaddr)
__field(u8, qnum)
__dynamic_array(u8, frame, skb->len)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ __entry->priv = priv;
__entry->skbaddr = (unsigned long) skb;
__entry->qnum = (u8) q->qnum;
memcpy(__get_dynamic_array(frame), skb->data, skb->len);
@@ -63,13 +61,13 @@ TRACE_EVENT(ath5k_tx,
);
TRACE_EVENT(ath5k_tx_complete,
- TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+ TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb,
struct ath5k_txq *q, struct ath5k_tx_status *ts),
TP_ARGS(priv, skb, q, ts),
TP_STRUCT__entry(
- PRIV_ENTRY
+ __field(struct ath5k_hw *, priv)
__field(unsigned long, skbaddr)
__field(u8, qnum)
__field(u8, ts_status)
@@ -78,7 +76,7 @@ TRACE_EVENT(ath5k_tx_complete,
),
TP_fast_assign(
- PRIV_ASSIGN;
+ __entry->priv = priv;
__entry->skbaddr = (unsigned long) skb;
__entry->qnum = (u8) q->qnum;
__entry->ts_status = ts->ts_status;
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index d9c08c6..f4ed4d8 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -50,13 +50,17 @@ config ATH9K_DEBUGFS
Also required for changing debug message flags at run time.
-config ATH9K_RATE_CONTROL
+config ATH9K_LEGACY_RATE_CONTROL
bool "Atheros ath9k rate control"
depends on ATH9K
- default y
+ default n
---help---
Say Y, if you want to use the ath9k specific rate control
- module instead of minstrel_ht.
+ module instead of minstrel_ht. Be warned that there are various
+ issues with the ath9k RC and minstrel is a more robust algorithm.
+ Note that even if this option is selected, "ath9k_rate_control"
+ has to be passed to mac80211 using the module parameter,
+ ieee80211_default_rc_algo.
config ATH9K_HTC
tristate "Atheros HTC based wireless cards support"
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 05a6fad..1cdb246 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -5,7 +5,7 @@ ath9k-y += beacon.o \
recv.o \
xmit.o \
-ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
+ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
@@ -21,6 +21,7 @@ ath9k_hw-y:= \
ar5008_phy.o \
ar9002_calib.o \
ar9003_calib.o \
+ ar9003_rtt.o \
calib.o \
eeprom.o \
eeprom_def.o \
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 5b49cd0..5e47ca6 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -19,6 +19,7 @@
#include <linux/nl80211.h>
#include <linux/platform_device.h>
#include <linux/ath9k_platform.h>
+#include <linux/module.h>
#include "ath9k.h"
static const struct platform_device_id ath9k_platform_id_table[] = {
@@ -27,6 +28,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
.driver_data = AR5416_AR9100_DEVID,
},
{
+ .name = "ar933x_wmac",
+ .driver_data = AR9300_DEVID_AR9330,
+ },
+ {
.name = "ar934x_wmac",
.driver_data = AR9300_DEVID_AR9340,
},
@@ -129,7 +134,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
goto err_free_hw;
}
- ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops);
+ ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
if (ret) {
dev_err(&pdev->dev, "failed to initialize device\n");
goto err_irq;
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 4e4e7c3..a639b94 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -15,6 +15,7 @@
*/
#include <linux/kernel.h>
+#include <linux/export.h>
#include "hw.h"
#include "hw-ops.h"
@@ -273,7 +274,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
immunityLevel, aniState->noiseFloor,
aniState->rssiThrLow, aniState->rssiThrHigh);
- aniState->ofdmNoiseImmunityLevel = immunityLevel;
+ if (aniState->update_ani)
+ aniState->ofdmNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -346,7 +348,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
- aniState->cckNoiseImmunityLevel = immunityLevel;
+ if (aniState->update_ani)
+ aniState->cckNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -588,6 +591,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
+ aniState->update_ani = false;
ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
}
@@ -604,6 +608,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
+ aniState->update_ani = true;
ath9k_hw_set_ofdm_nil(ah,
aniState->ofdmNoiseImmunityLevel);
ath9k_hw_set_cck_nil(ah,
@@ -638,7 +643,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
listenTime = ath_hw_get_listen_time(common);
if (listenTime <= 0) {
- ah->stats.ast_ani_lneg++;
+ ah->stats.ast_ani_lneg_or_lzero++;
ath9k_ani_restart(ah);
return false;
}
@@ -887,6 +892,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ani->ofdmWeakSigDetectOff =
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+ ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
+ ani->update_ani = false;
}
/*
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index dbab5b9..83029d6 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -122,6 +122,7 @@ struct ar5416AniState {
u8 firstepLevel;
u8 ofdmWeakSigDetectOff;
u8 cckWeakSigThreshold;
+ bool update_ani;
u32 listenTime;
int32_t rssiThrLow;
int32_t rssiThrHigh;
@@ -148,8 +149,7 @@ struct ar5416Stats {
u32 ast_ani_ofdmerrs;
u32 ast_ani_cckerrs;
u32 ast_ani_reset;
- u32 ast_ani_lzero;
- u32 ast_ani_lneg;
+ u32 ast_ani_lneg_or_lzero;
u32 avgbrssi;
struct ath9k_mib_stats ast_mibstats;
};
@@ -159,7 +159,5 @@ void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah);
-int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
- struct ath9k_channel *chan);
#endif /* ANI_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
index 234617c..f81e7fc 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
@@ -14,70 +14,71 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static const u32 ar5416Modes[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0},
- {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de},
- {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
- {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
- {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134},
- {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
- {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
- {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
- {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
- {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
- {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120},
- {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
- {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
- {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
- {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
- {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
- {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
- {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
- {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
- {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
- {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
- {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
- {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
- {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
- {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
- {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134},
+ {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
+ {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+ {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+ {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+ {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+ {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120},
+ {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar5416Common[][2] = {
@@ -668,6 +669,6 @@ static const u32 ar5416Addac[][2] = {
{0x0000989c, 0x00000000},
{0x0000989c, 0x00000000},
{0x0000989c, 0x00000000},
- {0x000098cc, 0x00000000},
+ {0x000098c4, 0x00000000},
};
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 0f23b1a..0a3c7c8 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -624,6 +624,11 @@ static void ar5008_hw_init_bb(struct ath_hw *ah,
else
synthDelay /= 10;
+ if (IS_CHAN_HALF_RATE(chan))
+ synthDelay *= 2;
+ else if (IS_CHAN_QUARTER_RATE(chan))
+ synthDelay *= 4;
+
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
udelay(synthDelay + BASE_ACTIVATE_DELAY);
@@ -696,8 +701,10 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
}
- if (!AR_SREV_5416_20_OR_LATER(ah) ||
- AR_SREV_9280_20_OR_LATER(ah))
+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+ if (AR_SREV_9280_20_OR_LATER(ah))
return;
/*
* Disable BB clock gating
@@ -753,10 +760,8 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
static int ar5008_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
int i, regWrites = 0;
- struct ieee80211_channel *channel = chan->chan;
u32 modesIndex, freqIndex;
switch (chan->chanmode) {
@@ -794,7 +799,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
/* Write ADDAC shifts */
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
- ah->eep_ops->set_addac(ah, chan);
+ if (ah->eep_ops->set_addac)
+ ah->eep_ops->set_addac(ah, chan);
REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
@@ -872,14 +878,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
ar5008_hw_set_channel_regs(ah, chan);
ar5008_hw_init_chain_masks(ah);
ath9k_olc_init(ah);
-
- /* Set TX power */
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
+ ath9k_hw_apply_txpower(ah, chan);
/* Write analog registers */
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
@@ -979,24 +978,6 @@ static void ar5008_restore_chainmask(struct ath_hw *ah)
}
}
-static void ar5008_set_diversity(struct ath_hw *ah, bool value)
-{
- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
- if (value)
- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- else
- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
-static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- if (chan && IS_CHAN_5GHZ(chan))
- return 0x1450;
- return 0x1458;
-}
-
static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -1626,7 +1607,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->rfbus_req = ar5008_hw_rfbus_req;
priv_ops->rfbus_done = ar5008_hw_rfbus_done;
priv_ops->restore_chainmask = ar5008_restore_chainmask;
- priv_ops->set_diversity = ar5008_set_diversity;
priv_ops->do_getnf = ar5008_hw_do_getnf;
priv_ops->set_radar_params = ar5008_hw_set_radar_params;
@@ -1636,9 +1616,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
} else
priv_ops->ani_control = ar5008_hw_ani_control_old;
- if (AR_SREV_9100(ah))
- priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
- else if (AR_SREV_9160_10_OR_LATER(ah))
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
else
priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
index 6d2e2f3..e8bdc75 100644
--- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
@@ -14,73 +14,74 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static const u32 ar5416Modes_9100[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
- {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
- {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
- {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204},
- {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
- {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e},
- {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff},
- {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
- {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
- {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
- {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
- {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00},
- {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
- {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
- {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
- {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
- {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
- {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
- {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
- {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
- {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
- {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
- {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
- {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
- {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
- {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes_9100[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+ {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204},
+ {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
+ {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e},
+ {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff},
+ {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+ {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar5416Common_9100[][2] = {
@@ -666,71 +667,72 @@ static const u32 ar5416Addac_9100[][2] = {
{0x000098cc, 0x00000000},
};
-static const u32 ar5416Modes_9160[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
- {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
- {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
- {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
- {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
- {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
- {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
- {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
- {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
- {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00},
- {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
- {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
- {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
- {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
- {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
- {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
- {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
- {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
- {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
- {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
- {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
- {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
- {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
- {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes_9160[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+ {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+ {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar5416Common_9160[][2] = {
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 2d394af..88279e3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -868,9 +868,6 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
/* Do PA Calibration */
ar9002_hw_pa_cal(ah, true);
- /* Do NF Calibration after DC offset and other calibrations */
- ath9k_hw_start_nfcal(ah, true);
-
if (ah->caldata)
ah->caldata->nfcal_pending = true;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 30bf703..d190411 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/moduleparam.h>
#include "hw.h"
#include "ar5008_initvals.h"
#include "ar9001_initvals.h"
@@ -30,7 +31,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9271(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
- ARRAY_SIZE(ar9271Modes_9271), 6);
+ ARRAY_SIZE(ar9271Modes_9271), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
@@ -41,21 +42,21 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only,
- ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
+ ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
- ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
+ ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
ar9271Modes_high_power_tx_gain_9271,
- ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
+ ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
ar9271Modes_normal_power_tx_gain_9271,
- ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
+ ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
return;
}
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
- ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
+ ARRAY_SIZE(ar9287Modes_9287_1_1), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
ARRAY_SIZE(ar9287Common_9287_1_1), 2);
if (ah->config.pcie_clock_req)
@@ -71,7 +72,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
- ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+ ARRAY_SIZE(ar9285Modes_9285_1_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
ARRAY_SIZE(ar9285Common_9285_1_2), 2);
@@ -87,7 +88,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
}
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
- ARRAY_SIZE(ar9280Modes_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_9280_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2);
@@ -105,7 +106,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
- ARRAY_SIZE(ar5416Modes_9160), 6);
+ ARRAY_SIZE(ar5416Modes_9160), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
ARRAY_SIZE(ar5416Common_9160), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
@@ -134,7 +135,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
}
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
- ARRAY_SIZE(ar5416Modes_9100), 6);
+ ARRAY_SIZE(ar5416Modes_9100), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
ARRAY_SIZE(ar5416Common_9100), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
@@ -157,7 +158,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar5416Addac_9100), 2);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
- ARRAY_SIZE(ar5416Modes), 6);
+ ARRAY_SIZE(ar5416Modes), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
ARRAY_SIZE(ar5416Common), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
@@ -226,19 +227,19 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_13db_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5);
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_23db_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
}
}
@@ -253,15 +254,15 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2,
- ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
}
}
@@ -270,14 +271,14 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1,
- ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
+ ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5);
else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1,
- ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
+ ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
} else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
@@ -289,24 +290,24 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_high_power,
ARRAY_SIZE(
- ar9285Modes_XE2_0_high_power), 6);
+ ar9285Modes_XE2_0_high_power), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE(
- ar9285Modes_high_power_tx_gain_9285_1_2), 6);
+ ar9285Modes_high_power_tx_gain_9285_1_2), 5);
}
} else {
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_normal_power,
ARRAY_SIZE(
- ar9285Modes_XE2_0_normal_power), 6);
+ ar9285Modes_XE2_0_normal_power), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE(
- ar9285Modes_original_tx_gain_9285_1_2), 6);
+ ar9285Modes_original_tx_gain_9285_1_2), 5);
}
}
}
@@ -322,17 +323,13 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
- int restore,
- int power_off)
+ bool power_off)
{
u8 i;
u32 val;
- if (ah->is_pciexpress != true || ah->aspm_enabled != true)
- return;
-
/* Nothing to do on restore for 11N */
- if (!restore) {
+ if (!power_off /* !restore */) {
if (AR_SREV_9280_20_OR_LATER(ah)) {
/*
* AR9280 2.0 or later chips use SerDes values from the
@@ -514,45 +511,6 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
}
}
-/*
- * If Async FIFO is enabled, the following counters change as MAC now runs
- * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
- *
- * The values below tested for ht40 2 chain.
- * Overwrite the delay/timeouts initialized in process ini.
- */
-void ar9002_hw_update_async_fifo(struct ath_hw *ah)
-{
- if (AR_SREV_9287_13_OR_LATER(ah)) {
- REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
- AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
- REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
- AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
- REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
- AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
-
- REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
- REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
-
- REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
- AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
- REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
- AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
- }
-}
-
-/*
- * We don't enable WEP aggregation on mac80211 but we keep this
- * around for HAL unification purposes.
- */
-void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
-{
- if (AR_SREV_9287_13_OR_LATER(ah)) {
- REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
- AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
- }
-}
-
/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
void ar9002_hw_attach_ops(struct ath_hw *ah)
{
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
index 7573257..863db32 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
@@ -14,53 +14,54 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static const u32 ar9280Modes_9280_2[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
- {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
- {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
- {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
- {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
- {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
- {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
- {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
- {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
- {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
- {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000},
- {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
- {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000},
- {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
+static const u32 ar9280Modes_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b},
+ {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
+ {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+ {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+ {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
+ {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
+ {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000},
+ {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+ {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000},
+ {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
};
static const u32 ar9280Common_9280_2[][2] = {
@@ -424,471 +425,476 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
{0x00009918, 0x0000000b, 0x00000016},
};
-static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
- {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
- {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
- {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
- {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
- {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
- {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
- {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
- {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
- {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
- {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
- {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
- {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
- {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
- {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
- {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
- {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
- {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
- {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
- {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
- {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
- {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
- {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
- {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
- {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
- {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
- {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
- {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
- {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
- {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
- {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
- {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
- {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
- {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
- {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
- {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
- {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
- {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
- {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
- {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
- {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
- {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
- {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
- {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
- {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
- {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
- {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
- {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
- {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10},
- {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80},
- {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84},
- {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88},
- {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c},
- {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90},
- {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94},
- {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98},
- {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4},
- {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8},
- {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac},
- {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0},
- {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4},
- {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1},
- {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5},
- {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9},
- {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad},
- {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1},
- {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5},
- {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2},
- {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6},
- {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa},
- {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae},
- {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2},
- {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6},
- {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3},
- {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7},
- {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab},
- {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf},
- {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3},
- {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7},
- {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3},
- {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7},
- {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb},
- {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf},
- {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3},
- {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7},
- {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+ {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
};
-static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
- {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
- {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
- {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
- {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
- {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
- {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
- {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
- {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
- {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
- {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
- {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
- {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
- {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
- {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
- {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
- {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
- {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
- {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
- {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
- {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
- {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
- {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
- {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
- {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
- {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
- {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
- {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
- {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
- {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
- {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
- {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
- {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
- {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
- {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
- {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
- {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
- {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
- {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
- {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
- {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
- {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
- {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
- {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
- {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
- {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
- {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
- {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
- {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
- {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
- {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
- {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
- {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
- {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c},
- {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310},
- {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384},
- {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388},
- {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324},
- {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704},
- {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4},
- {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8},
- {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710},
- {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714},
- {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720},
- {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724},
- {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728},
- {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c},
- {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0},
- {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4},
- {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8},
- {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0},
- {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4},
- {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8},
- {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5},
- {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9},
- {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad},
- {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1},
- {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5},
- {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9},
- {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5},
- {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9},
- {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1},
- {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5},
- {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9},
- {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6},
- {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca},
- {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce},
- {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2},
- {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6},
- {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3},
- {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7},
- {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb},
- {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf},
- {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7},
- {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
+static const u32 ar9280Modes_original_rxgain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000},
+ {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
};
-static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
- {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
- {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
- {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
- {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
- {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
- {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
- {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
- {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
- {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
- {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
- {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
- {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
- {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
- {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
- {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
- {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
- {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
- {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
- {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
- {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
- {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
- {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
- {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
- {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
- {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
- {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
- {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
- {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
- {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
- {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
- {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
- {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
- {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
- {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
- {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
- {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
- {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
- {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
- {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
- {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
- {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
- {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
- {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
- {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
- {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
- {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
- {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
- {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
- {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
- {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
- {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
- {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
- {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
- {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
- {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
- {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
- {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
- {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310},
- {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314},
- {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320},
- {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324},
- {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328},
- {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c},
- {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330},
- {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334},
- {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321},
- {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325},
- {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329},
- {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d},
- {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331},
- {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335},
- {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322},
- {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326},
- {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a},
- {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e},
- {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332},
- {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336},
- {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323},
- {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327},
- {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b},
- {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f},
- {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333},
- {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337},
- {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343},
- {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347},
- {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b},
- {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f},
- {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353},
- {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357},
- {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
- {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+ {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
+ {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
};
-static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
- {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
- {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002},
- {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008},
- {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010},
- {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012},
- {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014},
- {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a},
- {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211},
- {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
- {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411},
- {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413},
- {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811},
- {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813},
- {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14},
- {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50},
- {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c},
- {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a},
- {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92},
- {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2},
- {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5},
- {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54},
- {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5},
- {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
- {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
- {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
- {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
- {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
- {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
- {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652},
+ {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002},
+ {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008},
+ {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010},
+ {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012},
+ {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014},
+ {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a},
+ {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211},
+ {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+ {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411},
+ {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413},
+ {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811},
+ {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813},
+ {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14},
+ {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50},
+ {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c},
+ {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a},
+ {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92},
+ {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2},
+ {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5},
+ {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54},
+ {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5},
+ {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+ {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+ {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+ {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+ {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+ {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+ {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
};
-static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
- {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
- {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
- {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009},
- {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b},
- {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
- {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048},
- {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a},
- {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211},
- {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
- {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b},
- {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412},
- {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414},
- {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a},
- {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649},
- {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b},
- {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49},
- {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48},
- {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a},
- {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88},
- {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a},
- {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9},
- {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42},
- {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
- {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
- {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
- {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
- {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
- {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
- {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652},
+ {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
+ {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009},
+ {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b},
+ {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
+ {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048},
+ {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a},
+ {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211},
+ {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+ {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b},
+ {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412},
+ {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414},
+ {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a},
+ {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649},
+ {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b},
+ {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49},
+ {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48},
+ {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a},
+ {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88},
+ {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a},
+ {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9},
+ {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42},
+ {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+ {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+ {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+ {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+ {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+ {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+ {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
};
static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
@@ -947,309 +953,310 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9285Modes_9285_1_2[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
- {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
- {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
- {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18},
- {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
- {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
- {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
- {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
- {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+static const u32 ar9285Modes_9285_1_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+ {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20},
+ {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+ {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
};
static const u32 ar9285Common_9285_1_2[][2] = {
@@ -1572,164 +1579,168 @@ static const u32 ar9285Common_9285_1_2[][2] = {
{0x00007870, 0x10142c00},
};
-static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
- {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
- {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
- {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
- {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
- {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
- {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
- {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
- {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
- {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
- {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+ {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+ {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+ {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+ {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
+ {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+ {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+ {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+ {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+ {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
};
-static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
- {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
- {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
- {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
- {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
- {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
- {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
- {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
- {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
- {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
- {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
- {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+static const u32 ar9285Modes_original_tx_gain_9285_1_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+ {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+ {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+ {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+ {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+ {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
+ {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+ {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+ {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+ {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+ {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
};
-static const u32 ar9285Modes_XE2_0_normal_power[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
- {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
- {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae},
- {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
- {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
- {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
- {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
- {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
- {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
- {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
- {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
- {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+static const u32 ar9285Modes_XE2_0_normal_power[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+ {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+ {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+ {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+ {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+ {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
+ {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+ {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+ {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+ {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+ {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
};
-static const u32 ar9285Modes_XE2_0_high_power[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
- {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
- {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
- {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
- {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
- {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
- {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
- {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
- {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
- {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
- {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+static const u32 ar9285Modes_XE2_0_high_power[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+ {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+ {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+ {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+ {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
+ {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+ {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+ {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+ {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+ {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
};
static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
@@ -1760,50 +1771,51 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9287Modes_9287_1_1[][6] = {
- {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001},
- {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
- {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18},
- {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881},
- {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010},
- {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
- {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
- {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210},
- {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce},
- {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c},
- {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444},
- {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
- {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar9287Modes_9287_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300},
+ {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001},
+ {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0},
+ {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2},
+ {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20},
+ {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881},
+ {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898},
+ {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210},
+ {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce},
+ {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c},
+ {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4},
+ {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444},
+ {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+ {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar9287Common_9287_1_1[][2] = {
@@ -2189,313 +2201,315 @@ static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = {
{0x0000a1fc, 0xca9228ee},
};
-static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002},
- {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a},
- {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c},
- {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b},
- {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a},
- {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a},
- {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a},
- {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a},
- {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
- {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a},
- {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a},
- {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c},
- {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc},
- {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4},
- {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc},
- {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede},
- {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
- {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e},
- {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e},
- {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062},
- {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064},
- {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4},
- {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa},
- {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac},
- {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4},
- {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4},
- {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134},
- {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174},
- {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c},
- {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e},
- {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be},
- {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000},
+static const u32 ar9287Modes_tx_gain_9287_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b},
+ {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a},
+ {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c},
+ {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc},
+ {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4},
+ {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc},
+ {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede},
+ {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e},
+ {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e},
+ {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e},
+ {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062},
+ {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064},
+ {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4},
+ {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa},
+ {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac},
+ {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4},
+ {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4},
+ {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134},
+ {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174},
+ {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c},
+ {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e},
+ {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be},
+ {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000},
};
-static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = {
- {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
- {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
- {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
- {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
- {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
- {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
- {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
- {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
- {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
- {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
- {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
- {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
- {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
- {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
- {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
- {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
- {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
- {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
- {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
- {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
- {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
- {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
- {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
- {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
- {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
- {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
- {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
- {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
- {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
- {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
- {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
- {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
- {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
- {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
- {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
- {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
- {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
- {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
- {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
- {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
- {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
- {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
- {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
- {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
- {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
- {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
- {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
- {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
- {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
- {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
- {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
- {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
- {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
- {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
- {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
- {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
- {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
- {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
- {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
- {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
- {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
- {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
- {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
- {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
- {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
- {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
- {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
- {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
- {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
- {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
- {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
- {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
- {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
- {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
- {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
- {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
- {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
- {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
- {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
- {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
- {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
- {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
- {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
- {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
- {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
- {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
- {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
- {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
- {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
- {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
- {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
- {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
- {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
- {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
- {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
- {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
- {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
- {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
- {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
- {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
- {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
- {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
- {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
- {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
- {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
- {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
- {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
- {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
- {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
- {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
- {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
- {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
- {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
- {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
- {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
- {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
- {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
- {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
- {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
- {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
- {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
- {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
- {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
- {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
- {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
- {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
- {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
- {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
- {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
- {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
- {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
- {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
- {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
- {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
- {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
- {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
- {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
- {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
- {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
- {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
- {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
- {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
- {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
- {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
- {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
- {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
- {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
- {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
- {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
- {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
- {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
- {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
- {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
- {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
- {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
- {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
- {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
- {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
- {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
- {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
- {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
- {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
- {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
- {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
- {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
- {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
- {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
- {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
- {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
- {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
- {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
- {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
- {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
- {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
- {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
- {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
- {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
- {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
- {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
- {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
- {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
- {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
- {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
- {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
- {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
- {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
- {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
- {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
- {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
- {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
- {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
- {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
- {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
- {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
- {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
- {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
- {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
- {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
- {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
- {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
- {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
- {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
- {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
- {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
- {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
- {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
- {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
- {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
+static const u32 ar9287Modes_rx_gain_9287_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+ {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+ {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+ {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+ {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+ {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+ {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+ {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+ {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+ {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+ {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+ {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+ {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+ {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+ {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+ {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+ {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+ {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+ {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+ {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+ {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+ {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+ {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+ {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+ {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+ {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+ {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+ {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+ {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+ {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+ {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+ {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+ {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+ {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+ {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+ {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+ {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+ {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+ {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+ {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+ {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+ {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+ {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+ {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+ {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+ {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+ {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+ {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+ {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+ {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+ {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+ {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+ {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+ {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+ {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+ {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+ {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+ {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+ {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+ {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+ {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+ {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
+ {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
};
static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {
@@ -2526,310 +2540,311 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9271Modes_9271[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
- {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
- {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
- {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
- {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
- {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
- {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
- {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
- {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
- {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+static const u32 ar9271Modes_9271[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+ {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
+ {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+ {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
};
static const u32 ar9271Common_9271[][2] = {
@@ -3175,91 +3190,95 @@ static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = {
{0x0000a1fc, 0xca9228ee},
};
-static const u32 ar9271Modes_9271_1_0_only[][6] = {
- {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+static const u32 ar9271Modes_9271_1_0_only[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
};
-static const u32 ar9271Modes_9271_ANI_reg[][6] = {
- {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
- {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
- {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
- {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+static const u32 ar9271Modes_9271_ANI_reg[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
};
-static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000},
- {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
- {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
- {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
- {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
- {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652},
- {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
- {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
- {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
- {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
- {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
- {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+static const u32 ar9271Modes_normal_power_tx_gain_9271[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610},
+ {0x0000a314, 0x00000000, 0x00000000, 0x00024650, 0x00024650},
+ {0x0000a318, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x000316d2, 0x000316d2},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00039758, 0x00039758},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e},
+ {0x0000a334, 0x000368de, 0x000368de, 0x0004979f, 0x0004979f},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0004d7df, 0x0004d7df},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
+ {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21c652, 0x0a21c652},
+ {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
+ {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+ {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
};
-static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000},
- {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
- {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
- {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6},
- {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652},
- {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063},
- {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
- {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
- {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
- {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+static const u32 ar9271Modes_high_power_tx_gain_9271[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80},
+ {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
+ {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
+ {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063},
+ {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+ {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+ {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+ {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
};
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 077e8a6..f4caeb3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -15,6 +15,7 @@
*/
#include "hw.h"
+#include <linux/export.h>
#define AR_BufLen 0x00000fff
@@ -28,11 +29,6 @@ static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
((struct ath_desc*) ds)->ds_link = ds_link;
}
-static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
-{
- *ds_link = &((struct ath_desc *)ds)->ds_link;
-}
-
static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
@@ -80,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
mask2 |= ATH9K_INT_CST;
if (isr2 & AR_ISR_S2_TSFOOR)
mask2 |= ATH9K_INT_TSFOOR;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR_S2, isr2);
+ isr &= ~AR_ISR_BCNMISC;
+ }
}
- isr = REG_READ(ah, AR_ISR_RAC);
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+ isr = REG_READ(ah, AR_ISR_RAC);
+
if (isr == 0xffffffff) {
*masked = 0;
return false;
@@ -101,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
*masked |= ATH9K_INT_TX;
- s0_s = REG_READ(ah, AR_ISR_S0_S);
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+ s0_s = REG_READ(ah, AR_ISR_S0_S);
+ s1_s = REG_READ(ah, AR_ISR_S1_S);
+ } else {
+ s0_s = REG_READ(ah, AR_ISR_S0);
+ REG_WRITE(ah, AR_ISR_S0, s0_s);
+ s1_s = REG_READ(ah, AR_ISR_S1);
+ REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+ isr &= ~(AR_ISR_TXOK |
+ AR_ISR_TXDESC |
+ AR_ISR_TXERR |
+ AR_ISR_TXEOL);
+ }
+
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
- s1_s = REG_READ(ah, AR_ISR_S1_S);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
}
@@ -118,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
*masked |= mask2;
}
- if (AR_SREV_9100(ah))
- return true;
-
- if (isr & AR_ISR_GENTMR) {
+ if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
u32 s5_s;
- s5_s = REG_READ(ah, AR_ISR_S5_S);
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+ s5_s = REG_READ(ah, AR_ISR_S5_S);
+ } else {
+ s5_s = REG_READ(ah, AR_ISR_S5);
+ }
+
ah->intr_gen_timer_trigger =
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
@@ -137,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
*masked |= ATH9K_INT_TIM_TIMER;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR_S5, s5_s);
+ isr &= ~AR_ISR_GENTMR;
+ }
+ }
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR, isr);
+ REG_READ(ah, AR_ISR);
}
+ if (AR_SREV_9100(ah))
+ return true;
+
if (sync_cause) {
fatal_int =
(sync_cause &
@@ -175,33 +205,104 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true;
}
-static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu)
+static void
+ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
{
struct ar5416_desc *ads = AR5416DESC(ds);
+ u32 ctl1, ctl6;
- ads->ds_data = buf_addr;
-
- if (is_firstseg) {
- ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
- } else if (is_lastseg) {
- ads->ds_ctl0 = 0;
- ads->ds_ctl1 = seglen;
- ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
- ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
- } else {
- ads->ds_ctl0 = 0;
- ads->ds_ctl1 = seglen | AR_TxMore;
- ads->ds_ctl2 = 0;
- ads->ds_ctl3 = 0;
- }
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+ ACCESS_ONCE(ads->ds_link) = i->link;
+ ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
+
+ ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
+ ctl6 = SM(i->keytype, AR_EncrType);
+
+ if (AR_SREV_9285(ah)) {
+ ads->ds_ctl8 = 0;
+ ads->ds_ctl9 = 0;
+ ads->ds_ctl10 = 0;
+ ads->ds_ctl11 = 0;
+ }
+
+ if ((i->is_first || i->is_last) &&
+ i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
+ ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
+ | set11nTries(i->rates, 1)
+ | set11nTries(i->rates, 2)
+ | set11nTries(i->rates, 3)
+ | (i->dur_update ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
+ | set11nRate(i->rates, 1)
+ | set11nRate(i->rates, 2)
+ | set11nRate(i->rates, 3);
+ } else {
+ ACCESS_ONCE(ads->ds_ctl2) = 0;
+ ACCESS_ONCE(ads->ds_ctl3) = 0;
+ }
+
+ if (!i->is_first) {
+ ACCESS_ONCE(ads->ds_ctl0) = 0;
+ ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+ ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+ return;
+ }
+
+ ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
+ | SM(i->type, AR_FrameType)
+ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ switch (i->aggr) {
+ case AGGR_BUF_FIRST:
+ ctl6 |= SM(i->aggr_len, AR_AggrLen);
+ /* fall through */
+ case AGGR_BUF_MIDDLE:
+ ctl1 |= AR_IsAggr | AR_MoreAggr;
+ ctl6 |= SM(i->ndelim, AR_PadDelim);
+ break;
+ case AGGR_BUF_LAST:
+ ctl1 |= AR_IsAggr;
+ break;
+ case AGGR_BUF_NONE:
+ break;
+ }
+
+ ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
+ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(i->txpower, AR_XmitPower)
+ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+ ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+ ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+
+ if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
+ return;
+
+ ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
+ | set11nPktDurRTSCTS(i->rates, 1);
+
+ ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
+ | set11nPktDurRTSCTS(i->rates, 3);
+
+ ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
+ | set11nRateFlags(i->rates, 1)
+ | set11nRateFlags(i->rates, 2)
+ | set11nRateFlags(i->rates, 3)
+ | SM(i->rtscts_rate, AR_RTSCTSRate);
}
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
@@ -276,145 +377,6 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return 0;
}
-static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType, u32 flags)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- if (txPower > 63)
- txPower = 63;
-
- ads->ds_ctl0 = (pktLen & AR_FrameLen)
- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(txPower, AR_XmitPower)
- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
- | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
-
- ads->ds_ctl1 =
- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
- | SM(type, AR_FrameType)
- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
- ads->ds_ctl6 = SM(keyType, AR_EncrType);
-
- if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
- ads->ds_ctl8 = 0;
- ads->ds_ctl9 = 0;
- ads->ds_ctl10 = 0;
- ads->ds_ctl11 = 0;
- }
-}
-
-static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- if (val)
- ads->ds_ctl0 |= AR_ClrDestMask;
- else
- ads->ds_ctl0 &= ~AR_ClrDestMask;
-}
-
-static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
- struct ar5416_desc *last_ads = AR5416DESC(lastds);
- u32 ds_ctl0;
-
- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
- ds_ctl0 = ads->ds_ctl0;
-
- if (flags & ATH9K_TXDESC_RTSENA) {
- ds_ctl0 &= ~AR_CTSEnable;
- ds_ctl0 |= AR_RTSEnable;
- } else {
- ds_ctl0 &= ~AR_RTSEnable;
- ds_ctl0 |= AR_CTSEnable;
- }
-
- ads->ds_ctl0 = ds_ctl0;
- } else {
- ads->ds_ctl0 =
- (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
- }
-
- ads->ds_ctl2 = set11nTries(series, 0)
- | set11nTries(series, 1)
- | set11nTries(series, 2)
- | set11nTries(series, 3)
- | (durUpdateEn ? AR_DurUpdateEna : 0)
- | SM(0, AR_BurstDur);
-
- ads->ds_ctl3 = set11nRate(series, 0)
- | set11nRate(series, 1)
- | set11nRate(series, 2)
- | set11nRate(series, 3);
-
- ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
- | set11nPktDurRTSCTS(series, 1);
-
- ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
- | set11nPktDurRTSCTS(series, 3);
-
- ads->ds_ctl7 = set11nRateFlags(series, 0)
- | set11nRateFlags(series, 1)
- | set11nRateFlags(series, 2)
- | set11nRateFlags(series, 3)
- | SM(rtsctsRate, AR_RTSCTSRate);
- last_ads->ds_ctl2 = ads->ds_ctl2;
- last_ads->ds_ctl3 = ads->ds_ctl3;
-}
-
-static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
- u32 aggrLen)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
- ads->ds_ctl6 &= ~AR_AggrLen;
- ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
-}
-
-static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
- u32 numDelims)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
- unsigned int ctl6;
-
- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
- ctl6 = ads->ds_ctl6;
- ctl6 &= ~AR_PadDelim;
- ctl6 |= SM(numDelims, AR_PadDelim);
- ads->ds_ctl6 = ctl6;
-}
-
-static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 |= AR_IsAggr;
- ads->ds_ctl1 &= ~AR_MoreAggr;
- ads->ds_ctl6 &= ~AR_PadDelim;
-}
-
-static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
@@ -437,15 +399,7 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops->rx_enable = ar9002_hw_rx_enable;
ops->set_desc_link = ar9002_hw_set_desc_link;
- ops->get_desc_link = ar9002_hw_get_desc_link;
ops->get_isr = ar9002_hw_get_isr;
- ops->fill_txdesc = ar9002_hw_fill_txdesc;
+ ops->set_txdesc = ar9002_set_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc;
- ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
- ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
- ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
- ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
- ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
- ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
- ops->set_clrdmask = ar9002_hw_set_clrdmask;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 2fe0a34..3cbbb03 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -111,7 +111,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
case 0:
- if ((freq % 20) == 0)
+ if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
+ aModeRefSel = 0;
+ else if ((freq % 20) == 0)
aModeRefSel = 3;
else if ((freq % 10) == 0)
aModeRefSel = 2;
@@ -129,8 +131,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
channelSel = CHANSEL_5G(freq);
/* RefDivA setting */
- REG_RMW_FIELD(ah, AR_AN_SYNTH9,
- AR_AN_SYNTH9_REFDIVA, refDivA);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
+ AR_AN_SYNTH9_REFDIVA,
+ AR_AN_SYNTH9_REFDIVA_S, refDivA);
}
@@ -447,26 +450,27 @@ static void ar9002_olc_init(struct ath_hw *ah)
static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
+ int ref_div = 5;
+ int pll_div = 0x2c;
u32 pll;
- pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+ if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
+ if (AR_SREV_9280_20(ah)) {
+ ref_div = 10;
+ pll_div = 0x50;
+ } else {
+ pll_div = 0x28;
+ }
+ }
+
+ pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
+ pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
- if (chan && IS_CHAN_5GHZ(chan)) {
- if (IS_CHAN_A_FAST_CLOCK(ah, chan))
- pll = 0x142c;
- else if (AR_SREV_9280_20(ah))
- pll = 0x2850;
- else
- pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
- } else {
- pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
- }
-
return pll;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index c84c493..498a3c1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -24,108 +24,108 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {
{0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
- {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
- {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
- {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
{0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
};
static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+ {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+ {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+ {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
- {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
- {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
- {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
- {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
- {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
- {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
- {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
@@ -190,7 +190,7 @@ static const u32 ar9300_2p2_radio_core[][2] = {
{0x00016288, 0x05a20408},
{0x0001628c, 0x00038c07},
{0x00016290, 0x00000004},
- {0x00016294, 0x458aa14f},
+ {0x00016294, 0x458a214f},
{0x00016380, 0x00000000},
{0x00016384, 0x00000000},
{0x00016388, 0x00800700},
@@ -636,7 +636,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
- {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
+ {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
@@ -653,8 +653,8 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
- {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
@@ -761,7 +761,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x0000a3ec, 0x20202020},
{0x0000a3f0, 0x00000000},
{0x0000a3f4, 0x00000246},
- {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3f8, 0x0c9bd380},
{0x0000a3fc, 0x000f0f01},
{0x0000a400, 0x8fa91f01},
{0x0000a404, 0x00000000},
@@ -780,7 +780,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x0000a43c, 0x00100000},
{0x0000a440, 0x00000000},
{0x0000a444, 0x00000000},
- {0x0000a448, 0x06000080},
+ {0x0000a448, 0x05000080},
{0x0000a44c, 0x00000001},
{0x0000a450, 0x00010000},
{0x0000a458, 0x00000000},
@@ -928,15 +928,15 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
- {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
- {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
@@ -1500,8 +1500,6 @@ static const u32 ar9300_2p2_mac_core[][2] = {
{0x0000816c, 0x00000000},
{0x000081c0, 0x00000000},
{0x000081c4, 0x33332210},
- {0x000081c8, 0x00000000},
- {0x000081cc, 0x00000000},
{0x000081ec, 0x00000000},
{0x000081f0, 0x00000000},
{0x000081f4, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 7c2aaad..3965356 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -17,8 +17,9 @@
#include "hw.h"
#include "hw-ops.h"
#include "ar9003_phy.h"
+#include "ar9003_rtt.h"
-#define MAX_MEASUREMENT 8
+#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
#define MAX_MAG_DELTA 11
#define MAX_PHS_DELTA 10
@@ -615,11 +616,10 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
{
int mp_max = -64, max_idx = 0;
int mp_min = 63, min_idx = 0;
- int mp_avg = 0, i, outlier_idx = 0;
+ int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
/* find min/max mismatch across all calibrated gains */
for (i = 0; i < nmeasurement; i++) {
- mp_avg += mp_coeff[i];
if (mp_coeff[i] > mp_max) {
mp_max = mp_coeff[i];
max_idx = i;
@@ -632,10 +632,20 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
/* find average (exclude max abs value) */
for (i = 0; i < nmeasurement; i++) {
if ((abs(mp_coeff[i]) < abs(mp_max)) ||
- (abs(mp_coeff[i]) < abs(mp_min)))
+ (abs(mp_coeff[i]) < abs(mp_min))) {
mp_avg += mp_coeff[i];
+ mp_count++;
+ }
}
- mp_avg /= (nmeasurement - 1);
+
+ /*
+ * finding mean magnitude/phase if possible, otherwise
+ * just use the last value as the mean
+ */
+ if (mp_count)
+ mp_avg /= mp_count;
+ else
+ mp_avg = mp_coeff[nmeasurement - 1];
/* detect outlier */
if (abs(mp_max - mp_min) > max_delta) {
@@ -650,10 +660,12 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
u8 num_chains,
- struct coeff *coeff)
+ struct coeff *coeff,
+ bool is_reusable)
{
int i, im, nmeasurement;
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
@@ -703,7 +715,13 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
coeff->iqc_coeff[0]);
+
+ if (caldata)
+ caldata->tx_corr_coeff[im][i] =
+ coeff->iqc_coeff[0];
}
+ if (caldata)
+ caldata->num_measures[i] = nmeasurement;
}
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
@@ -711,8 +729,10 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
- return;
+ if (caldata)
+ caldata->done_txiqcal_once = is_reusable;
+ return;
}
static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
@@ -739,7 +759,7 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
return true;
}
-static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
{
struct ath_common *common = ath9k_hw_common(ah);
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
@@ -828,7 +848,8 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
coeff.phs_coeff[i][im] -= 128;
}
}
- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
+ ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains,
+ &coeff, is_reusable);
return;
@@ -836,23 +857,135 @@ tx_iqcal_fail:
ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
return;
}
+
+static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
+{
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+ int i, im;
+
+ memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
+ for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
+ tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
+ if (!AR_SREV_9485(ah)) {
+ tx_corr_coeff[i * 2][1] =
+ tx_corr_coeff[(i * 2) + 1][1] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
+
+ tx_corr_coeff[i * 2][2] =
+ tx_corr_coeff[(i * 2) + 1][2] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
+ }
+ }
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+ continue;
+
+ for (im = 0; im < caldata->num_measures[i]; im++) {
+ if ((im % 2) == 0)
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+ AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
+ caldata->tx_corr_coeff[im][i]);
+ else
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+ AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
+ caldata->tx_corr_coeff[im][i]);
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+ AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+ AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+}
+
+static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_rtt_hist *hist;
+ u32 *table;
+ int i;
+ bool restore;
+
+ if (!ah->caldata)
+ return false;
+
+ hist = &ah->caldata->rtt_hist;
+ if (!hist->num_readings)
+ return false;
+
+ ar9003_hw_rtt_enable(ah);
+ ar9003_hw_rtt_set_mask(ah, 0x00);
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->rxchainmask & (1 << i)))
+ continue;
+ table = &hist->table[i][hist->num_readings][0];
+ ar9003_hw_rtt_load_hist(ah, i, table);
+ }
+ restore = ar9003_hw_rtt_force_restore(ah);
+ ar9003_hw_rtt_disable(ah);
+
+ return restore;
+}
+
static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_hw_capabilities *pCap = &ah->caps;
- int val;
- bool txiqcal_done = false;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ bool txiqcal_done = false, txclcal_done = false;
+ bool is_reusable = true, status = true;
+ bool run_rtt_cal = false, run_agc_cal;
+ bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
+ u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
+ AR_PHY_AGC_CONTROL_FLTR_CAL |
+ AR_PHY_AGC_CONTROL_PKDET_CAL;
+ int i, j;
+ u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
+ AR_PHY_CL_TAB_1,
+ AR_PHY_CL_TAB_2 };
+
+ /* Use chip chainmask only for calibration */
+ ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+
+ if (rtt) {
+ if (!ar9003_hw_rtt_restore(ah, chan))
+ run_rtt_cal = true;
+
+ ath_dbg(common, ATH_DBG_CALIBRATE, "RTT restore %s\n",
+ run_rtt_cal ? "failed" : "succeed");
+ }
+ run_agc_cal = run_rtt_cal;
- val = REG_READ(ah, AR_ENT_OTP);
- ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
+ if (run_rtt_cal) {
+ ar9003_hw_rtt_enable(ah);
+ ar9003_hw_rtt_set_mask(ah, 0x00);
+ ar9003_hw_rtt_clear_hist(ah);
+ }
- /* Configure rx/tx chains before running AGC/TxiQ cals */
- if (val & AR_ENT_OTP_CHAIN2_DISABLE)
- ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
- else
- ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
- pCap->tx_chainmask);
+ if (rtt && !run_rtt_cal) {
+ agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
+ agc_supp_cals &= agc_ctrl;
+ agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
+ AR_PHY_AGC_CONTROL_FLTR_CAL |
+ AR_PHY_AGC_CONTROL_PKDET_CAL);
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+ }
+
+ if (ah->enabled_cals & TX_CL_CAL) {
+ if (caldata && caldata->done_txclcal_once)
+ REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
+ AR_PHY_CL_CAL_ENABLE);
+ else {
+ REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL,
+ AR_PHY_CL_CAL_ENABLE);
+ run_agc_cal = true;
+ }
+ }
+
+ if (!(ah->enabled_cals & TX_IQ_CAL))
+ goto skip_tx_iqcal;
/* Do Tx IQ Calibration */
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
@@ -863,35 +996,100 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
* For AR9485 or later chips, TxIQ cal runs as part of
* AGC calibration
*/
- if (AR_SREV_9485_OR_LATER(ah))
- txiqcal_done = true;
- else {
- txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
- udelay(5);
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
- }
-
- /* Calibrate the AGC */
- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
- REG_READ(ah, AR_PHY_AGC_CONTROL) |
- AR_PHY_AGC_CONTROL_CAL);
-
- /* Poll for offset calibration complete */
- if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
- 0, AH_WAIT_TIMEOUT)) {
+ if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
+ if (caldata && !caldata->done_txiqcal_once)
+ REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+ else
+ REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+ txiqcal_done = run_agc_cal = true;
+ goto skip_tx_iqcal;
+ } else if (caldata && !caldata->done_txiqcal_once)
+ run_agc_cal = true;
+
+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+ udelay(5);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+skip_tx_iqcal:
+ if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
+ /* Calibrate the AGC */
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_CAL);
+
+ /* Poll for offset calibration complete */
+ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_CAL,
+ 0, AH_WAIT_TIMEOUT);
+ }
+ if (rtt && !run_rtt_cal) {
+ agc_ctrl |= agc_supp_cals;
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+ }
+
+ if (!status) {
+ if (run_rtt_cal)
+ ar9003_hw_rtt_disable(ah);
+
ath_dbg(common, ATH_DBG_CALIBRATE,
- "offset calibration failed to complete in 1ms; noisy environment?\n");
+ "offset calibration failed to complete in 1ms;"
+ "noisy environment?\n");
return false;
}
if (txiqcal_done)
- ar9003_hw_tx_iq_cal_post_proc(ah);
+ ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+ else if (caldata && caldata->done_txiqcal_once)
+ ar9003_hw_tx_iq_cal_reload(ah);
+
+#define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j))
+ if (caldata && (ah->enabled_cals & TX_CL_CAL)) {
+ txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_CLC_SUCCESS);
+ if (caldata->done_txclcal_once) {
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+ continue;
+ for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
+ REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
+ caldata->tx_clcal[i][j]);
+ }
+ } else if (is_reusable && txclcal_done) {
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+ continue;
+ for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
+ caldata->tx_clcal[i][j] =
+ REG_READ(ah,
+ CL_TAB_ENTRY(cl_idx[i]));
+ }
+ caldata->done_txclcal_once = true;
+ }
+ }
+#undef CL_TAB_ENTRY
+
+ if (run_rtt_cal && caldata) {
+ struct ath9k_rtt_hist *hist = &caldata->rtt_hist;
+ if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) {
+ u32 *table;
+
+ hist->num_readings++;
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->rxchainmask & (1 << i)))
+ continue;
+ table = &hist->table[i][hist->num_readings][0];
+ ar9003_hw_rtt_fill_hist(ah, i, table);
+ }
+ }
- /* Revert chainmasks to their original values before NF cal */
- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+ ar9003_hw_rtt_disable(ah);
+ }
- ath9k_hw_start_nfcal(ah, true);
+ /* Revert chainmask to runtime parameters */
+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
/* Initialize list pointers */
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
@@ -917,8 +1115,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
if (ah->cal_list_curr)
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
- if (ah->caldata)
- ah->caldata->CalValid = 0;
+ if (caldata)
+ caldata->CalValid = 0;
return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 417106b..c41eb9d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9003_phy.h"
#include "ar9003_eeprom.h"
@@ -21,25 +22,6 @@
#define COMP_HDR_LEN 4
#define COMP_CKSUM_LEN 2
-#define AR_CH0_TOP (0x00016288)
-#define AR_CH0_TOP_XPABIASLVL (0x300)
-#define AR_CH0_TOP_XPABIASLVL_S (8)
-
-#define AR_CH0_THERM (0x00016290)
-#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
-#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
-#define AR_CH0_THERM_XPASHORT2GND 0x4
-#define AR_CH0_THERM_XPASHORT2GND_S 2
-
-#define AR_SWITCH_TABLE_COM_ALL (0xffff)
-#define AR_SWITCH_TABLE_COM_ALL_S (0)
-
-#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
-#define AR_SWITCH_TABLE_COM2_ALL_S (0)
-
-#define AR_SWITCH_TABLE_ALL (0xfff)
-#define AR_SWITCH_TABLE_ALL_S (0)
-
#define LE16(x) __constant_cpu_to_le16(x)
#define LE32(x) __constant_cpu_to_le32(x)
@@ -157,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -359,7 +341,7 @@ static const struct ar9300_eeprom ar9300_default = {
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -734,7 +716,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -936,7 +918,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -1312,7 +1294,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.papdRateMaskHt20 = LE32(0x80c080),
.papdRateMaskHt40 = LE32(0x80c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -1461,7 +1443,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
@@ -1514,7 +1496,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -1890,7 +1872,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -2092,7 +2074,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -2467,7 +2449,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.papdRateMaskHt20 = LE32(0x0c80C080),
.papdRateMaskHt40 = LE32(0x0080C080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -2616,7 +2598,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
@@ -2669,7 +2651,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -3006,15 +2988,13 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
switch (param) {
case EEP_MAC_LSW:
- return eep->macAddr[0] << 8 | eep->macAddr[1];
+ return get_unaligned_be16(eep->macAddr);
case EEP_MAC_MID:
- return eep->macAddr[2] << 8 | eep->macAddr[3];
+ return get_unaligned_be16(eep->macAddr + 2);
case EEP_MAC_MSW:
- return eep->macAddr[4] << 8 | eep->macAddr[5];
+ return get_unaligned_be16(eep->macAddr + 4);
case EEP_REG_0:
return le16_to_cpu(pBase->regDmn[0]);
- case EEP_REG_1:
- return le16_to_cpu(pBase->regDmn[1]);
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -3038,7 +3018,11 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
case EEP_CHAIN_MASK_REDUCE:
return (pBase->miscConfiguration >> 0x3) & 0x1;
case EEP_ANT_DIV_CTL1:
- return le32_to_cpu(eep->base_ext1.ant_div_control);
+ return eep->base_ext1.ant_div_control;
+ case EEP_ANTENNA_GAIN_5G:
+ return eep->modalHeader5G.antennaGain;
+ case EEP_ANTENNA_GAIN_2G:
+ return eep->modalHeader2G.antennaGain;
default:
return 0;
}
@@ -3317,13 +3301,15 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
word = kzalloc(2048, GFP_KERNEL);
if (!word)
- return -1;
+ return -ENOMEM;
memcpy(mptr, &ar9300_default, mdata_size);
read = ar9300_read_eeprom;
if (AR_SREV_9485(ah))
cptr = AR9300_BASE_ADDR_4K;
+ else if (AR_SREV_9330(ah))
+ cptr = AR9300_BASE_ADDR_512;
else
cptr = AR9300_BASE_ADDR;
ath_dbg(common, ATH_DBG_EEPROM,
@@ -3378,8 +3364,7 @@ found:
osize = length;
read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
- mchecksum = word[COMP_HDR_LEN + osize] |
- (word[COMP_HDR_LEN + osize + 1] << 8);
+ mchecksum = get_unaligned_le16(&word[COMP_HDR_LEN + osize]);
ath_dbg(common, ATH_DBG_EEPROM,
"checksum %x %x\n", checksum, mchecksum);
if (checksum == mchecksum) {
@@ -3416,6 +3401,133 @@ static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
return true;
}
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size,
+ struct ar9300_modal_eep_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
+ PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
+ PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
+ PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
+ PR_EEP("Ant. Common Control2", le32_to_cpu(modal_hdr->antCtrlCommon2));
+ PR_EEP("Ant. Gain", modal_hdr->antennaGain);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 xatten1DB", modal_hdr->xatten1DB[0]);
+ PR_EEP("Chain1 xatten1DB", modal_hdr->xatten1DB[1]);
+ PR_EEP("Chain2 xatten1DB", modal_hdr->xatten1DB[2]);
+ PR_EEP("Chain0 xatten1Margin", modal_hdr->xatten1Margin[0]);
+ PR_EEP("Chain1 xatten1Margin", modal_hdr->xatten1Margin[1]);
+ PR_EEP("Chain2 xatten1Margin", modal_hdr->xatten1Margin[2]);
+ PR_EEP("Temp Slope", modal_hdr->tempSlope);
+ PR_EEP("Volt Slope", modal_hdr->voltSlope);
+ PR_EEP("spur Channels0", modal_hdr->spurChans[0]);
+ PR_EEP("spur Channels1", modal_hdr->spurChans[1]);
+ PR_EEP("spur Channels2", modal_hdr->spurChans[2]);
+ PR_EEP("spur Channels3", modal_hdr->spurChans[3]);
+ PR_EEP("spur Channels4", modal_hdr->spurChans[4]);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+ PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("txClip", modal_hdr->txClip);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("Chain0 ob", modal_hdr->ob[0]);
+ PR_EEP("Chain1 ob", modal_hdr->ob[1]);
+ PR_EEP("Chain2 ob", modal_hdr->ob[2]);
+
+ PR_EEP("Chain0 db_stage2", modal_hdr->db_stage2[0]);
+ PR_EEP("Chain1 db_stage2", modal_hdr->db_stage2[1]);
+ PR_EEP("Chain2 db_stage2", modal_hdr->db_stage2[2]);
+ PR_EEP("Chain0 db_stage3", modal_hdr->db_stage3[0]);
+ PR_EEP("Chain1 db_stage3", modal_hdr->db_stage3[1]);
+ PR_EEP("Chain2 db_stage3", modal_hdr->db_stage3[2]);
+ PR_EEP("Chain0 db_stage4", modal_hdr->db_stage4[0]);
+ PR_EEP("Chain1 db_stage4", modal_hdr->db_stage4[1]);
+ PR_EEP("Chain2 db_stage4", modal_hdr->db_stage4[2]);
+
+ return len;
+}
+
+static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct ar9300_base_eep_hdr *pBase;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ar9003_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader2G);
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "5GHz modal Header");
+ len += ar9003_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader5G);
+ goto out;
+ }
+
+ pBase = &eep->baseEepHeader;
+
+ PR_EEP("EEPROM Version", ah->eeprom.ar9300_eep.eepromVersion);
+ PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
+ PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
+ PR_EEP("TX Mask", (pBase->txrxMask >> 4));
+ PR_EEP("RX Mask", (pBase->txrxMask & 0x0f));
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & 0x01));
+ PR_EEP("RF Silent", pBase->rfSilent);
+ PR_EEP("BT option", pBase->blueToothOptions);
+ PR_EEP("Device Cap", pBase->deviceCap);
+ PR_EEP("Device Type", pBase->deviceType);
+ PR_EEP("Power Table Offset", pBase->pwrTableOffset);
+ PR_EEP("Tuning Caps1", pBase->params_for_tuning_caps[0]);
+ PR_EEP("Tuning Caps2", pBase->params_for_tuning_caps[1]);
+ PR_EEP("Enable Tx Temp Comp", !!(pBase->featureEnable & BIT(0)));
+ PR_EEP("Enable Tx Volt Comp", !!(pBase->featureEnable & BIT(1)));
+ PR_EEP("Enable fast clock", !!(pBase->featureEnable & BIT(2)));
+ PR_EEP("Enable doubling", !!(pBase->featureEnable & BIT(3)));
+ PR_EEP("Internal regulator", !!(pBase->featureEnable & BIT(4)));
+ PR_EEP("Enable Paprd", !!(pBase->featureEnable & BIT(5)));
+ PR_EEP("Driver Strength", !!(pBase->miscConfiguration & BIT(0)));
+ PR_EEP("Chain mask Reduce", (pBase->miscConfiguration >> 0x3) & 0x1);
+ PR_EEP("Write enable Gpio", pBase->eepromWriteEnableGpio);
+ PR_EEP("WLAN Disable Gpio", pBase->wlanDisableGpio);
+ PR_EEP("WLAN LED Gpio", pBase->wlanLedGpio);
+ PR_EEP("Rx Band Select Gpio", pBase->rxBandSelectGpio);
+ PR_EEP("Tx Gain", pBase->txrxgain >> 4);
+ PR_EEP("Rx Gain", pBase->txrxgain & 0xf);
+ PR_EEP("SW Reg", le32_to_cpu(pBase->swreg));
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ ah->eeprom.ar9300_eep.macAddr);
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
/* XXX: review hardware docs */
static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
{
@@ -3442,8 +3554,10 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
{
int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
+ else if (AR_SREV_9462(ah))
+ REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
else {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
REG_RMW_FIELD(ah, AR_CH0_THERM,
@@ -3454,6 +3568,19 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
}
}
+static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is_2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ __le32 val;
+
+ if (is_2ghz)
+ val = eep->modalHeader2G.switchcomspdt;
+ else
+ val = eep->modalHeader5G.switchcomspdt;
+ return le32_to_cpu(val);
+}
+
+
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@@ -3498,7 +3625,7 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
{
int chain;
- u32 regval;
+ u32 regval, value;
u32 ant_div_ctl1;
static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = {
AR_PHY_SWITCH_CHAIN_0,
@@ -3506,9 +3633,42 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
AR_PHY_SWITCH_CHAIN_2,
};
- u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
+ if (AR_SREV_9485(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0))
+ ath9k_hw_cfg_output(ah, AR9300_EXT_LNA_CTL_GPIO_AR9485,
+ AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
- REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
+ value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
+
+ if (AR_SREV_9462(ah)) {
+ if (AR_SREV_9462_10(ah)) {
+ value &= ~AR_SWITCH_TABLE_COM_SPDT;
+ value |= 0x00100000;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_AR9462_ALL, value);
+ } else
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL, value);
+
+
+ /*
+ * AR9462 defines new switch table for BT/WLAN,
+ * here's new field name in XXX.ref for both 2G and 5G.
+ * Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
+ * 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX
+ * SWITCH_TABLE_COM_SPDT_WLAN_RX
+ *
+ * 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX
+ * SWITCH_TABLE_COM_SPDT_WLAN_TX
+ *
+ * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+ * SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+ */
+ if (AR_SREV_9462_20_OR_LATER(ah)) {
+ value = ar9003_switch_com_spdt_get(ah, is2ghz);
+ REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
+ AR_SWITCH_TABLE_COM_SPDT_ALL, value);
+ }
value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
@@ -3523,7 +3683,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
}
}
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
/*
* main_lnaconf, alt_lnaconf, main_tb, alt_tb
@@ -3708,9 +3868,10 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
{
int internal_regulator =
ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
+ u32 reg_val;
if (internal_regulator) {
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
int reg_pmu_set;
reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
@@ -3718,9 +3879,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
- reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
- (2 << 14) | (6 << 17) | (1 << 20) |
- (3 << 24) | (1 << 28);
+ if (AR_SREV_9330(ah)) {
+ if (ah->is_clk_25mhz) {
+ reg_pmu_set = (3 << 1) | (8 << 4) |
+ (3 << 8) | (1 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24);
+ } else {
+ reg_pmu_set = (4 << 1) | (7 << 4) |
+ (3 << 8) | (1 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24);
+ }
+ } else {
+ reg_pmu_set = (5 << 1) | (7 << 4) |
+ (2 << 8) | (2 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24) | (1 << 28);
+ }
REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
@@ -3737,13 +3913,16 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
+ } else if (AR_SREV_9462(ah)) {
+ reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+ REG_WRITE(ah, AR_PHY_PMU1, reg_val);
} else {
/* Internal regulator is ON. Write swreg register. */
- int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+ reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah, AR_RTC_REG_CONTROL1) &
(~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
- REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
+ REG_WRITE(ah, AR_RTC_REG_CONTROL0, reg_val);
/* Set REG_CONTROL1.SWREG_PROGRAM */
REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah,
@@ -3751,25 +3930,27 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
}
} else {
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
while (REG_READ_FIELD(ah, AR_PHY_PMU2,
- AR_PHY_PMU2_PGM))
+ AR_PHY_PMU2_PGM))
udelay(10);
REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
- AR_PHY_PMU1_PWD))
+ AR_PHY_PMU1_PWD))
udelay(10);
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
- AR_PHY_PMU2_PGM))
+ AR_PHY_PMU2_PGM))
udelay(10);
- } else
- REG_WRITE(ah, AR_RTC_SLEEP_CLK,
- (REG_READ(ah,
- AR_RTC_SLEEP_CLK) |
- AR_RTC_FORCE_SWREG_PRD));
+ } else if (AR_SREV_9462(ah))
+ REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+ else {
+ reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) |
+ AR_RTC_FORCE_SWREG_PRD;
+ REG_WRITE(ah, AR_RTC_SLEEP_CLK, reg_val);
+ }
}
}
@@ -3795,9 +3976,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_drive_strength_apply(ah);
ar9003_hw_atten_apply(ah, chan);
- if (!AR_SREV_9340(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
ar9003_hw_internal_regulator_apply(ah);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
ar9003_hw_apply_tuning_caps(ah);
}
@@ -4044,7 +4225,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
/* Write the power for duplicated frames - HT40 */
/* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
- REG_WRITE(ah, 0xa3e0,
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(8),
POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
@@ -4349,6 +4530,12 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
tempSlope = eep->modalHeader5G.tempSlope;
REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
+
+ if (AR_SREV_9462_20(ah))
+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
+ AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope);
+
+
REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
temperature[0]);
@@ -4583,20 +4770,14 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 *pPwrArray, u16 cfgCtl,
- u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
+ u8 antenna_reduction,
u16 powerLimit)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] = {
- 0, 3, 6, 9, MAX_RATE_POWER
- };
int i;
- int16_t twiceLargestAntenna;
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
};
@@ -4614,28 +4795,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
bool is2ghz = IS_CHAN_2GHZ(chan);
ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- /* Compute TxPower reduction due to Antenna Gain */
- if (is2ghz)
- twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
- else
- twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
-
- twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
- twiceLargestAntenna, 0);
-
- /*
- * scaledPower is the minimum of the user input power level
- * and the regulatory allowed power level
- */
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = powerLimit - antenna_reduction;
/*
* Reduce scaled Power by number of chains active to get
@@ -4822,7 +4982,6 @@ static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -4875,7 +5034,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
ar9003_hw_set_power_per_rate_table(ah, chan,
targetPowerValT2, cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
@@ -4905,25 +5063,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
"TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
}
- /*
- * This is the TX power we send back to driver core,
- * and it can use to pass to userspace to display our
- * currently configured TX power setting.
- *
- * Since power is rate dependent, use one of the indices
- * from the AR9300_Rates enum to select an entry from
- * targetPowerValT2[] to report. Currently returns the
- * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
- * as CCK power is less interesting (?).
- */
- i = ALL_TARGET_LEGACY_6_24; /* legacy */
- if (IS_CHAN_HT40(chan))
- i = ALL_TARGET_HT40_0_8_16; /* ht40 */
- else if (IS_CHAN_HT20(chan))
- i = ALL_TARGET_HT20_0_8_16; /* ht20 */
-
- ah->txpower_limit = targetPowerValT2[i];
- regulatory->max_power_level = targetPowerValT2[i];
+ ah->txpower_limit = regulatory->max_power_level;
/* Write target power array to registers */
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
@@ -4998,6 +5138,7 @@ const struct eeprom_ops eep_ar9300_ops = {
.check_eeprom = ath9k_hw_ar9300_check_eeprom,
.get_eeprom = ath9k_hw_ar9300_get_eeprom,
.fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
+ .dump_eeprom = ath9k_hw_ar9003_dump_eeprom,
.get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
.set_board_values = ath9k_hw_ar9300_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index 7f7bc94..69bcdb6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -233,7 +233,8 @@ struct ar9300_modal_eep_header {
u8 thresh62;
__le32 papdRateMaskHt20;
__le32 papdRateMaskHt40;
- u8 futureModal[10];
+ __le16 switchcomspdt;
+ u8 futureModal[8];
} __packed;
struct ar9300_cal_data_per_freq_op_loop {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 7e02fb4..979d225 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -19,6 +19,11 @@
#include "ar9003_2p2_initvals.h"
#include "ar9485_initvals.h"
#include "ar9340_initvals.h"
+#include "ar9330_1p1_initvals.h"
+#include "ar9330_1p2_initvals.h"
+#include "ar9580_1p0_initvals.h"
+#include "ar9462_1p0_initvals.h"
+#include "ar9462_2p0_initvals.h"
/* General hardware code for the AR9003 hadware family */
@@ -29,7 +34,118 @@
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
- if (AR_SREV_9340(ah)) {
+#define AR9462_BB_CTX_COEFJ(x) \
+ ar9462_##x##_baseband_core_txfir_coeff_japan_2484
+
+#define AR9462_BBC_TXIFR_COEFFJ \
+ ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+ if (AR_SREV_9330_11(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9331_1p1_mac_core,
+ ARRAY_SIZE(ar9331_1p1_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9331_1p1_mac_postamble,
+ ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9331_1p1_baseband_core,
+ ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9331_1p1_baseband_postamble,
+ ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9331_1p1_radio_core,
+ ARRAY_SIZE(ar9331_1p1_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9331_1p1_soc_preamble,
+ ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9331_1p1_soc_postamble,
+ ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+ 5);
+
+ /* additional clock settings */
+ if (ah->is_clk_25mhz)
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p1_xtal_25M,
+ ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p1_xtal_40M,
+ ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
+ } else if (AR_SREV_9330_12(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9331_1p2_mac_core,
+ ARRAY_SIZE(ar9331_1p2_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9331_1p2_mac_postamble,
+ ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9331_1p2_baseband_core,
+ ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9331_1p2_baseband_postamble,
+ ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9331_1p2_radio_core,
+ ARRAY_SIZE(ar9331_1p2_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9331_1p2_soc_preamble,
+ ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9331_1p2_soc_postamble,
+ ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+ 5);
+
+ /* additional clock settings */
+ if (ah->is_clk_25mhz)
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p2_xtal_25M,
+ ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p2_xtal_40M,
+ ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
+ } else if (AR_SREV_9340(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -145,6 +261,182 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ar9485_1_1_pcie_phy_clkreq_disable_L1,
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
2);
+ } else if (AR_SREV_9462_10(ah)) {
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_1p0_mac_core,
+ ARRAY_SIZE(ar9462_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9462_1p0_mac_postamble,
+ ARRAY_SIZE(ar9462_1p0_mac_postamble),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9462_1p0_baseband_core,
+ ARRAY_SIZE(ar9462_1p0_baseband_core),
+ 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9462_1p0_baseband_postamble,
+ ARRAY_SIZE(ar9462_1p0_baseband_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9462_1p0_radio_core,
+ ARRAY_SIZE(ar9462_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9462_1p0_radio_postamble,
+ ARRAY_SIZE(ar9462_1p0_radio_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9462_1p0_soc_preamble,
+ ARRAY_SIZE(ar9462_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9462_1p0_soc_postamble,
+ ARRAY_SIZE(ar9462_1p0_soc_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_1p0), 2);
+
+ /* Awake -> Sleep Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9462_pcie_phy_clkreq_disable_L1_1p0,
+ ARRAY_SIZE(ar9462_pcie_phy_clkreq_disable_L1_1p0),
+ 2);
+
+ /* Sleep -> Awake Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+ ar9462_pcie_phy_clkreq_disable_L1_1p0,
+ ARRAY_SIZE(ar9462_pcie_phy_clkreq_disable_L1_1p0),
+ 2);
+
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9462_modes_fast_clock_1p0,
+ ARRAY_SIZE(ar9462_modes_fast_clock_1p0), 3);
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ AR9462_BB_CTX_COEFJ(1p0),
+ ARRAY_SIZE(AR9462_BB_CTX_COEFJ(1p0)), 2);
+
+ } else if (AR_SREV_9462_20(ah)) {
+
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core,
+ ARRAY_SIZE(ar9462_2p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9462_2p0_mac_postamble,
+ ARRAY_SIZE(ar9462_2p0_mac_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9462_2p0_baseband_core,
+ ARRAY_SIZE(ar9462_2p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9462_2p0_baseband_postamble,
+ ARRAY_SIZE(ar9462_2p0_baseband_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9462_2p0_radio_core,
+ ARRAY_SIZE(ar9462_2p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9462_2p0_radio_postamble,
+ ARRAY_SIZE(ar9462_2p0_radio_postamble), 5);
+ INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
+ ar9462_2p0_radio_postamble_sys2ant,
+ ARRAY_SIZE(ar9462_2p0_radio_postamble_sys2ant),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9462_2p0_soc_preamble,
+ ARRAY_SIZE(ar9462_2p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9462_2p0_soc_postamble,
+ ARRAY_SIZE(ar9462_2p0_soc_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_2p0), 2);
+
+ INIT_INI_ARRAY(&ah->ini_BTCOEX_MAX_TXPWR,
+ ar9462_2p0_BTCOEX_MAX_TXPWR_table,
+ ARRAY_SIZE(ar9462_2p0_BTCOEX_MAX_TXPWR_table),
+ 2);
+
+ /* Awake -> Sleep Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9462_pciephy_clkreq_disable_L1_2p0,
+ ARRAY_SIZE(ar9462_pciephy_clkreq_disable_L1_2p0),
+ 2);
+ /* Sleep -> Awake Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+ ar9462_pciephy_clkreq_disable_L1_2p0,
+ ARRAY_SIZE(ar9462_pciephy_clkreq_disable_L1_2p0),
+ 2);
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9462_modes_fast_clock_2p0,
+ ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
+
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ AR9462_BB_CTX_COEFJ(2p0),
+ ARRAY_SIZE(AR9462_BB_CTX_COEFJ(2p0)), 2);
+
+ INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ,
+ ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2);
+
+ } else if (AR_SREV_9580(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9580_1p0_mac_core,
+ ARRAY_SIZE(ar9580_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9580_1p0_mac_postamble,
+ ARRAY_SIZE(ar9580_1p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9580_1p0_baseband_core,
+ ARRAY_SIZE(ar9580_1p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9580_1p0_baseband_postamble,
+ ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9580_1p0_radio_core,
+ ARRAY_SIZE(ar9580_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9580_1p0_radio_postamble,
+ ARRAY_SIZE(ar9580_1p0_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9580_1p0_soc_preamble,
+ ARRAY_SIZE(ar9580_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9580_1p0_soc_postamble,
+ ARRAY_SIZE(ar9580_1p0_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9580_1p0_rx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_low_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9580_1p0_modes_fast_clock,
+ ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
+ 3);
} else {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -215,118 +507,293 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
}
}
+static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485_modes_lowest_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_lowest_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
+ 5);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_low_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_modes_low_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_low_ob_db_tx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_modes_low_ob_db_tx_gain_table_2p0),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+ 5);
+}
+
+static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_high_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_high_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
+ 5);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_high_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_modes_high_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_high_ob_db_tx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_modes_high_ob_db_tx_gain_table_2p0),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+ 5);
+}
+
+static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_low_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_low_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_low_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_low_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_low_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+ 5);
+}
+
+static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_power_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_power_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_high_power_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_high_power_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_power_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
+ 5);
+}
+
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485_modes_lowest_ob_db_tx_gain_1_1,
- ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode0(ah);
break;
case 1:
- if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485Modes_high_ob_db_tx_gain_1_1,
- ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_high_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode1(ah);
break;
case 2:
- if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485Modes_low_ob_db_tx_gain_1_1,
- ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_low_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode2(ah);
break;
case 3:
- if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485Modes_high_power_tx_gain_1_1,
- ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_high_power_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode3(ah);
break;
}
}
+static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+ 2);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+ 2);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485_common_rx_gain_1_1,
+ ARRAY_SIZE(ar9485_common_rx_gain_1_1),
+ 2);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9580_1p0_rx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_rx_gain_table),
+ 2);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_2p0),
+ 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+ 2);
+}
+
+static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_wo_xlna_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+ 2);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_wo_xlna_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+ 2);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_wo_xlna_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485Common_wo_xlna_rx_gain_1_1,
+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+ 2);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_wo_xlna_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_wo_xlna_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0),
+ 2);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9580_1p0_wo_xlna_rx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
+ 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_wo_xlna_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+ 2);
+}
+
+static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
+{
+ if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_mixed_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_mixed_rx_gain_table_1p0), 2);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_mixed_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_mixed_rx_gain_table_2p0), 2);
+}
+
static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9340Common_rx_gain_table_1p0,
- ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
- 2);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9485Common_wo_xlna_rx_gain_1_1,
- ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
- 2);
- else
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_rx_gain_table_2p2,
- ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
- 2);
+ ar9003_rx_gain_table_mode0(ah);
break;
case 1:
- if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9340Common_wo_xlna_rx_gain_table_1p0,
- ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
- 2);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9485Common_wo_xlna_rx_gain_1_1,
- ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
- 2);
- else
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_wo_xlna_rx_gain_table_2p2,
- ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
- 2);
+ ar9003_rx_gain_table_mode1(ah);
+ break;
+ case 2:
+ ar9003_rx_gain_table_mode2(ah);
break;
}
}
@@ -348,14 +815,10 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
- int restore,
- int power_off)
+ bool power_off)
{
- if (ah->is_pciexpress != true || ah->aspm_enabled != true)
- return;
-
/* Nothing to do on restore for 11N */
- if (!restore) {
+ if (!power_off /* !restore */) {
/* set bit 19 to allow forcing of pcie core into L1 state */
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 7880dca..f5ae3c6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -13,6 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/export.h>
#include "hw.h"
#include "ar9003_mac.h"
@@ -21,6 +22,132 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw)
REG_WRITE(hw, AR_CR, 0);
}
+static void
+ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
+{
+ struct ar9003_txc *ads = ds;
+ int checksum = 0;
+ u32 val, ctl12, ctl17;
+
+ val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
+ (1 << AR_TxRxDesc_S) |
+ (1 << AR_CtrlStat_S) |
+ (i->qcu << AR_TxQcuNum_S) | 0x17;
+
+ checksum += val;
+ ACCESS_ONCE(ads->info) = val;
+
+ checksum += i->link;
+ ACCESS_ONCE(ads->link) = i->link;
+
+ checksum += i->buf_addr[0];
+ ACCESS_ONCE(ads->data0) = i->buf_addr[0];
+ checksum += i->buf_addr[1];
+ ACCESS_ONCE(ads->data1) = i->buf_addr[1];
+ checksum += i->buf_addr[2];
+ ACCESS_ONCE(ads->data2) = i->buf_addr[2];
+ checksum += i->buf_addr[3];
+ ACCESS_ONCE(ads->data3) = i->buf_addr[3];
+
+ checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl3) = val;
+ checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl5) = val;
+ checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl7) = val;
+ checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl9) = val;
+
+ checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
+ ACCESS_ONCE(ads->ctl10) = checksum;
+
+ if (i->is_first || i->is_last) {
+ ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
+ | set11nTries(i->rates, 1)
+ | set11nTries(i->rates, 2)
+ | set11nTries(i->rates, 3)
+ | (i->dur_update ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
+ | set11nRate(i->rates, 1)
+ | set11nRate(i->rates, 2)
+ | set11nRate(i->rates, 3);
+ } else {
+ ACCESS_ONCE(ads->ctl13) = 0;
+ ACCESS_ONCE(ads->ctl14) = 0;
+ }
+
+ ads->ctl20 = 0;
+ ads->ctl21 = 0;
+ ads->ctl22 = 0;
+
+ ctl17 = SM(i->keytype, AR_EncrType);
+ if (!i->is_first) {
+ ACCESS_ONCE(ads->ctl11) = 0;
+ ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
+ ACCESS_ONCE(ads->ctl15) = 0;
+ ACCESS_ONCE(ads->ctl16) = 0;
+ ACCESS_ONCE(ads->ctl17) = ctl17;
+ ACCESS_ONCE(ads->ctl18) = 0;
+ ACCESS_ONCE(ads->ctl19) = 0;
+ return;
+ }
+
+ ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
+ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(i->txpower, AR_XmitPower)
+ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+ | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
+ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+ ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
+ SM(i->keyix, AR_DestIdx) : 0)
+ | SM(i->type, AR_FrameType)
+ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
+ switch (i->aggr) {
+ case AGGR_BUF_FIRST:
+ ctl17 |= SM(i->aggr_len, AR_AggrLen);
+ /* fall through */
+ case AGGR_BUF_MIDDLE:
+ ctl12 |= AR_IsAggr | AR_MoreAggr;
+ ctl17 |= SM(i->ndelim, AR_PadDelim);
+ break;
+ case AGGR_BUF_LAST:
+ ctl12 |= AR_IsAggr;
+ break;
+ case AGGR_BUF_NONE:
+ break;
+ }
+
+ val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
+ ctl12 |= SM(val, AR_PAPRDChainMask);
+
+ ACCESS_ONCE(ads->ctl12) = ctl12;
+ ACCESS_ONCE(ads->ctl17) = ctl17;
+
+ ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
+ | set11nPktDurRTSCTS(i->rates, 1);
+
+ ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
+ | set11nPktDurRTSCTS(i->rates, 3);
+
+ ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
+ | set11nRateFlags(i->rates, 1)
+ | set11nRateFlags(i->rates, 2)
+ | set11nRateFlags(i->rates, 3)
+ | SM(i->rtscts_rate, AR_RTSCTSRate);
+
+ ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
+}
+
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
{
int checksum;
@@ -43,13 +170,6 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
}
-static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
-{
- struct ar9003_txc *ads = ds;
-
- *ds_link = &ads->link;
-}
-
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
@@ -192,50 +312,10 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true;
}
-static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
- unsigned int descid = 0;
-
- ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
- (1 << AR_TxRxDesc_S) |
- (1 << AR_CtrlStat_S) |
- (qcu << AR_TxQcuNum_S) | 0x17;
-
- ads->data0 = buf_addr;
- ads->data1 = 0;
- ads->data2 = 0;
- ads->data3 = 0;
-
- ads->ctl3 = (seglen << AR_BufLen_S);
- ads->ctl3 &= AR_BufLen;
-
- /* Fill in pointer checksum and descriptor id */
- ads->ctl10 = ar9003_calc_ptr_chksum(ads);
- ads->ctl10 |= (descid << AR_TxDescId_S);
-
- if (is_firstseg) {
- ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
- } else if (is_lastseg) {
- ads->ctl11 = 0;
- ads->ctl12 = 0;
- ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
- ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
- } else {
- /* XXX Intermediate descriptor in a multi-descriptor frame.*/
- ads->ctl11 = 0;
- ads->ctl12 = AR_TxMore;
- ads->ctl13 = 0;
- ads->ctl14 = 0;
- }
-}
-
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
+ struct ar9003_txc *txc = (struct ar9003_txc *) ds;
struct ar9003_txs *ads;
u32 status;
@@ -245,7 +325,11 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
if ((status & AR_TxDone) == 0)
return -EINPROGRESS;
- ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+ if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
+ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+ else
+ return -ENOENT;
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
@@ -259,7 +343,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
- ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
@@ -313,202 +396,15 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return 0;
}
-static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
- u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
- u32 keyIx, enum ath9k_key_type keyType, u32 flags)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- if (txpower > ah->txpower_limit)
- txpower = ah->txpower_limit;
-
- if (txpower > 63)
- txpower = 63;
-
- ads->ctl11 = (pktlen & AR_FrameLen)
- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(txpower, AR_XmitPower)
- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
- | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
-
- ads->ctl12 =
- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
- | SM(type, AR_FrameType)
- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
- ads->ctl17 = SM(keyType, AR_EncrType) |
- (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
- ads->ctl18 = 0;
- ads->ctl19 = AR_Not_Sounding;
-
- ads->ctl20 = 0;
- ads->ctl21 = 0;
- ads->ctl22 = 0;
-}
-
-static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- if (val)
- ads->ctl11 |= AR_ClrDestMask;
- else
- ads->ctl11 &= ~AR_ClrDestMask;
-}
-
-static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
- struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
- u_int32_t ctl11;
-
- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
- ctl11 = ads->ctl11;
-
- if (flags & ATH9K_TXDESC_RTSENA) {
- ctl11 &= ~AR_CTSEnable;
- ctl11 |= AR_RTSEnable;
- } else {
- ctl11 &= ~AR_RTSEnable;
- ctl11 |= AR_CTSEnable;
- }
-
- ads->ctl11 = ctl11;
- } else {
- ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
- }
-
- ads->ctl13 = set11nTries(series, 0)
- | set11nTries(series, 1)
- | set11nTries(series, 2)
- | set11nTries(series, 3)
- | (durUpdateEn ? AR_DurUpdateEna : 0)
- | SM(0, AR_BurstDur);
-
- ads->ctl14 = set11nRate(series, 0)
- | set11nRate(series, 1)
- | set11nRate(series, 2)
- | set11nRate(series, 3);
-
- ads->ctl15 = set11nPktDurRTSCTS(series, 0)
- | set11nPktDurRTSCTS(series, 1);
-
- ads->ctl16 = set11nPktDurRTSCTS(series, 2)
- | set11nPktDurRTSCTS(series, 3);
-
- ads->ctl18 = set11nRateFlags(series, 0)
- | set11nRateFlags(series, 1)
- | set11nRateFlags(series, 2)
- | set11nRateFlags(series, 3)
- | SM(rtsctsRate, AR_RTSCTSRate);
- ads->ctl19 = AR_Not_Sounding;
-
- last_ads->ctl13 = ads->ctl13;
- last_ads->ctl14 = ads->ctl14;
-}
-
-static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
- u32 aggrLen)
-{
-#define FIRST_DESC_NDELIMS 60
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
-
- if (ah->ent_mode & AR_ENT_OTP_MPSD) {
- u32 ctl17, ndelim;
- /*
- * Add delimiter when using RTS/CTS with aggregation
- * and non enterprise AR9003 card
- */
- ctl17 = ads->ctl17;
- ndelim = MS(ctl17, AR_PadDelim);
-
- if (ndelim < FIRST_DESC_NDELIMS) {
- aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
- ndelim = FIRST_DESC_NDELIMS;
- }
-
- ctl17 &= ~AR_AggrLen;
- ctl17 |= SM(aggrLen, AR_AggrLen);
-
- ctl17 &= ~AR_PadDelim;
- ctl17 |= SM(ndelim, AR_PadDelim);
-
- ads->ctl17 = ctl17;
- } else {
- ads->ctl17 &= ~AR_AggrLen;
- ads->ctl17 |= SM(aggrLen, AR_AggrLen);
- }
-}
-
-static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
- u32 numDelims)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
- unsigned int ctl17;
-
- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
-
- /*
- * We use a stack variable to manipulate ctl6 to reduce uncached
- * read modify, modfiy, write.
- */
- ctl17 = ads->ctl17;
- ctl17 &= ~AR_PadDelim;
- ctl17 |= SM(numDelims, AR_PadDelim);
- ads->ctl17 = ctl17;
-}
-
-static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- ads->ctl12 |= AR_IsAggr;
- ads->ctl12 &= ~AR_MoreAggr;
- ads->ctl17 &= ~AR_PadDelim;
-}
-
-static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
-void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains)
-{
- struct ar9003_txc *ads = ds;
-
- ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
-}
-EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc);
-
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
ops->rx_enable = ar9003_hw_rx_enable;
ops->set_desc_link = ar9003_hw_set_desc_link;
- ops->get_desc_link = ar9003_hw_get_desc_link;
ops->get_isr = ar9003_hw_get_isr;
- ops->fill_txdesc = ar9003_hw_fill_txdesc;
+ ops->set_txdesc = ar9003_set_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc;
- ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
- ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
- ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
- ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
- ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
- ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
- ops->set_clrdmask = ar9003_hw_set_clrdmask;
}
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
@@ -535,17 +431,18 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
/* TODO: byte swap on big endian for ar9300_10 */
- if ((rxsp->status11 & AR_RxDone) == 0)
- return -EINPROGRESS;
+ if (!rxs) {
+ if ((rxsp->status11 & AR_RxDone) == 0)
+ return -EINPROGRESS;
- if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
- return -EINVAL;
+ if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
+ return -EINVAL;
- if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
- return -EINPROGRESS;
+ if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
+ return -EINPROGRESS;
- if (!rxs)
return 0;
+ }
rxs->rs_status = 0;
rxs->rs_flags = 0;
@@ -629,10 +526,11 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (rxsp->status11 & AR_MichaelErr)
rxs->rs_status |= ATH9K_RXERR_MIC;
- else if (rxsp->status11 & AR_KeyMiss)
- rxs->rs_status |= ATH9K_RXERR_DECRYPT;
}
+ if (rxsp->status11 & AR_KeyMiss)
+ rxs->rs_status |= ATH9K_RXERR_KEYMISS;
+
return 0;
}
EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index e4d6a87..a4450cb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -14,23 +14,47 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/export.h>
#include "hw.h"
#include "ar9003_phy.h"
void ar9003_paprd_enable(struct ath_hw *ah, bool val)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ /*
+ * 3 bits for modalHeader5G.papdRateMaskHt20
+ * is used for sub-band disabling of PAPRD.
+ * 5G band is divided into 3 sub-bands -- upper,
+ * middle, lower.
+ * if bit 30 of modalHeader5G.papdRateMaskHt20 is set
+ * -- disable PAPRD for upper band 5GHz
+ * if bit 29 of modalHeader5G.papdRateMaskHt20 is set
+ * -- disable PAPRD for middle band 5GHz
+ * if bit 28 of modalHeader5G.papdRateMaskHt20 is set
+ * -- disable PAPRD for lower band 5GHz
+ */
+
+ if (IS_CHAN_5GHZ(chan)) {
+ if (chan->channel >= UPPER_5G_SUB_BAND_START) {
+ if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+ & BIT(30))
+ val = false;
+ } else if (chan->channel >= MID_5G_SUB_BAND_START) {
+ if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+ & BIT(29))
+ val = false;
+ } else {
+ if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+ & BIT(28))
+ val = false;
+ }
+ }
if (val) {
ah->paprd_table_write_done = true;
-
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- chan->chan->max_antenna_gain * 2,
- chan->chan->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
+ ath9k_hw_apply_txpower(ah, chan);
}
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
@@ -46,11 +70,10 @@ EXPORT_SYMBOL(ar9003_paprd_enable);
static int ar9003_get_training_power_2g(struct ath_hw *ah)
{
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
- struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
+ struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
+ scale = ar9003_get_paprd_scale_factor(ah, chan);
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
@@ -67,20 +90,10 @@ static int ar9003_get_training_power_2g(struct ath_hw *ah)
static int ar9003_get_training_power_5g(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
- struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
- if (chan->channel >= 5700)
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
- AR9300_PAPRD_SCALE_1);
- else if (chan->channel >= 5400)
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
- AR9300_PAPRD_SCALE_2);
- else
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
- AR9300_PAPRD_SCALE_1);
+ scale = ar9003_get_paprd_scale_factor(ah, chan);
if (IS_CHAN_HT40(chan))
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
@@ -94,7 +107,23 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
if (delta > scale)
return -1;
- power += 2 * get_streams(common->tx_chainmask);
+ switch (get_streams(ah->txchainmask)) {
+ case 1:
+ delta = 6;
+ break;
+ case 2:
+ delta = 4;
+ break;
+ case 3:
+ delta = 2;
+ break;
+ default:
+ delta = 0;
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "Invalid tx-chainmask: %u\n", ah->txchainmask);
+ }
+
+ power += delta;
return power;
}
@@ -112,22 +141,23 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_CTRL1_B2
};
int training_power;
- int i;
+ int i, val;
if (IS_CHAN_2GHZ(ah->curchan))
training_power = ar9003_get_training_power_2g(ah);
else
training_power = ar9003_get_training_power_5g(ah);
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "Training power: %d, Target power: %d\n",
+ training_power, ah->paprd_target_power);
+
if (training_power < 0) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"PAPRD target power delta out of range");
return -ERANGE;
}
ah->paprd_training_power = training_power;
- ath_dbg(common, ATH_DBG_CALIBRATE,
- "Training power: %d, Target power: %d\n",
- ah->paprd_training_power, ah->paprd_target_power);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
ah->paprd_ratemask);
@@ -171,8 +201,9 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);
+ val = AR_SREV_9462(ah) ? 0x91 : 147;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
- AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147);
+ AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
@@ -181,7 +212,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
- if (AR_SREV_9485(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9462(ah))
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
-3);
@@ -189,9 +220,10 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
-6);
+ val = AR_SREV_9462(ah) ? -10 : -15;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
- -15);
+ val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
@@ -230,7 +262,7 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
memset(index, 0, sizeof(ah->paprd_gain_table_index));
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
entry[i] = REG_READ(ah, reg);
index[i] = (entry[i] >> 24) & 0xff;
reg += 4;
@@ -240,13 +272,13 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
int target_power)
{
- int olpc_gain_delta = 0;
+ int olpc_gain_delta = 0, cl_gain_mod;
int alpha_therm, alpha_volt;
int therm_cal_value, volt_cal_value;
int therm_value, volt_value;
int thermal_gain_corr, voltage_gain_corr;
int desired_scale, desired_gain = 0;
- u32 reg;
+ u32 reg_olpc = 0, reg_cl_gain = 0;
REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
@@ -265,15 +297,29 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
- if (chain == 0)
- reg = AR_PHY_TPC_11_B0;
- else if (chain == 1)
- reg = AR_PHY_TPC_11_B1;
- else
- reg = AR_PHY_TPC_11_B2;
+ switch (chain) {
+ case 0:
+ reg_olpc = AR_PHY_TPC_11_B0;
+ reg_cl_gain = AR_PHY_CL_TAB_0;
+ break;
+ case 1:
+ reg_olpc = AR_PHY_TPC_11_B1;
+ reg_cl_gain = AR_PHY_CL_TAB_1;
+ break;
+ case 2:
+ reg_olpc = AR_PHY_TPC_11_B2;
+ reg_cl_gain = AR_PHY_CL_TAB_2;
+ break;
+ default:
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+ "Invalid chainmask: %d\n", chain);
+ break;
+ }
- olpc_gain_delta = REG_READ_FIELD(ah, reg,
+ olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
AR_PHY_TPC_11_OLPC_GAIN_DELTA);
+ cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
+ AR_PHY_CL_TAB_CL_GAIN_MOD);
if (olpc_gain_delta >= 128)
olpc_gain_delta = olpc_gain_delta - 256;
@@ -283,7 +329,7 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
(128 / 2)) / 128;
desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
- voltage_gain_corr + desired_scale;
+ voltage_gain_corr + desired_scale + cl_gain_mod;
return desired_gain;
}
@@ -707,6 +753,7 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
training_power);
if (ah->caps.tx_chainmask & BIT(2))
+ /* val AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL correct? */
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
training_power);
@@ -721,7 +768,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
gain_index = 0;
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
if (ah->paprd_gain_table_index[i] >= desired_gain)
break;
gain_index++;
@@ -795,7 +842,26 @@ EXPORT_SYMBOL(ar9003_paprd_init_table);
bool ar9003_paprd_is_done(struct ath_hw *ah)
{
- return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ int paprd_done, agc2_pwr;
+ paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+ if (paprd_done == 0x1) {
+ agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
+
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+ "AGC2_PWR = 0x%x training done = 0x%x\n",
+ agc2_pwr, paprd_done);
+ /*
+ * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
+ * when the training is completely done, otherwise retraining is
+ * done to make sure the value is in ideal range
+ */
+ if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
+ paprd_done = 0;
+ }
+
+ return !!paprd_done;
}
EXPORT_SYMBOL(ar9003_paprd_is_done);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index b8a26d2..f146824 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/export.h>
#include "hw.h"
#include "ar9003_phy.h"
@@ -75,7 +76,19 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
freq = centers.synth_center;
if (freq < 4800) { /* 2 GHz, fractional mode */
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah)) {
+ u32 chan_frac;
+ u32 div;
+
+ if (ah->is_clk_25mhz)
+ div = 75;
+ else
+ div = 120;
+
+ channelSel = (freq * 4) / div;
+ chan_frac = (((freq * 4) % div) * 0x20000) / div;
+ channelSel = (channelSel << 17) | chan_frac;
+ } else if (AR_SREV_9485(ah)) {
u32 chan_frac;
/*
@@ -104,7 +117,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
u32 chan_frac;
channelSel = (freq * 2) / 75;
- chan_frac = ((freq % 75) * 0x20000) / 75;
+ chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
channelSel = (channelSel << 17) | chan_frac;
} else {
channelSel = CHANSEL_5G(freq);
@@ -168,7 +181,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
* is out-of-band and can be ignored.
*/
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
IS_CHAN_2GHZ(chan));
if (spur_fbin_ptr[0] == 0) /* No spur */
@@ -193,7 +206,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
for (i = 0; i < max_spur_cnts; i++) {
negative = 0;
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
IS_CHAN_2GHZ(chan)) - synth_freq;
else
@@ -358,7 +371,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
else
spur_subchannel_sd = 0;
- spur_freq_sd = ((freq_offset + 10) << 9) / 11;
+ spur_freq_sd = (freq_offset << 9) / 11;
} else {
if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
@@ -367,7 +380,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
else
spur_subchannel_sd = 1;
- spur_freq_sd = ((freq_offset - 10) << 9) / 11;
+ spur_freq_sd = (freq_offset << 9) / 11;
}
@@ -470,7 +483,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
/* Enable 11n HT, 20 MHz */
- phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
+ phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |
AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
/* Configure baseband for dynamic 20/40 operation */
@@ -530,30 +543,20 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
{
- switch (rx) {
- case 0x5:
+ if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5)
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
AR_PHY_SWAP_ALT_CHAIN);
- case 0x3:
- case 0x1:
- case 0x2:
- case 0x7:
- REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
- REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
- break;
- default:
- break;
- }
+
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
- REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
- else
- REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+ tx = 3;
+ else if (AR_SREV_9462(ah))
+ /* xxx only when MCI support is enabled */
+ tx = 3;
- if (tx == 0x5) {
- REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
- AR_PHY_SWAP_ALT_CHAIN);
- }
+ REG_WRITE(ah, AR_SELFGEN_MASK, tx);
}
/*
@@ -580,6 +583,9 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
REG_WRITE(ah, AR_PCU_MISC_MODE2,
val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
+
+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
}
static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -613,9 +619,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
static int ar9003_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
unsigned int regWrites = 0, i;
- struct ieee80211_channel *channel = chan->chan;
u32 modesIndex;
switch (chan->chanmode) {
@@ -646,6 +650,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
+ if (i == ATH_INI_POST && AR_SREV_9462_20(ah))
+ ar9003_hw_prog_ini(ah,
+ &ah->ini_radio_post_sys2ant,
+ modesIndex);
}
REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
@@ -659,20 +667,33 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
REG_WRITE_ARRAY(&ah->iniModesAdditional,
modesIndex, regWrites);
+ if (AR_SREV_9330(ah))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+ if (AR_SREV_9462(ah))
+ ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
+
+ ah->modes_index = modesIndex;
ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+ ath9k_hw_apply_txpower(ah, chan);
- /* Set TX power */
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
+ if (AR_SREV_9462(ah)) {
+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
+ ah->enabled_cals |= TX_IQ_CAL;
+ else
+ ah->enabled_cals &= ~TX_IQ_CAL;
+
+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+ ah->enabled_cals |= TX_CL_CAL;
+ else
+ ah->enabled_cals &= ~TX_CL_CAL;
+ }
return 0;
}
@@ -770,16 +791,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
}
-static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
-{
- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
- if (value)
- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- else
- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
static bool ar9003_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
@@ -1078,7 +1089,10 @@ static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
{
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
- ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+ if (AR_SREV_9330(ah))
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
+ else
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
@@ -1200,8 +1214,17 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
- antconf->lna1_lna2_delta = -9;
- antconf->div_group = 2;
+
+ if (AR_SREV_9330_11(ah)) {
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 1;
+ } else if (AR_SREV_9485(ah)) {
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 2;
+ } else {
+ antconf->lna1_lna2_delta = -3;
+ antconf->div_group = 0;
+ }
}
static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
@@ -1230,6 +1253,73 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
}
+static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 *ini_reloaded)
+{
+ unsigned int regWrites = 0;
+ u32 modesIndex;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (modesIndex == ah->modes_index) {
+ *ini_reloaded = false;
+ goto set_rfmode;
+ }
+
+ ar9003_hw_prog_ini(ah, &ah->iniSOC[ATH_INI_POST], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
+ if (AR_SREV_9462_20(ah))
+ ar9003_hw_prog_ini(ah,
+ &ah->ini_radio_post_sys2ant,
+ modesIndex);
+
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+ /*
+ * For 5GHz channels requiring Fast Clock, apply
+ * different modal values.
+ */
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites);
+
+ if (AR_SREV_9330(ah))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
+ if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
+ REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+
+ ah->modes_index = modesIndex;
+ *ini_reloaded = true;
+
+set_rfmode:
+ ar9003_hw_set_rfmode(ah, chan);
+ return 0;
+}
+
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1254,11 +1344,11 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
priv_ops->rfbus_req = ar9003_hw_rfbus_req;
priv_ops->rfbus_done = ar9003_hw_rfbus_done;
- priv_ops->set_diversity = ar9003_hw_set_diversity;
priv_ops->ani_control = ar9003_hw_ani_control;
priv_ops->do_getnf = ar9003_hw_do_getnf;
priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+ priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 2364b5f..4e9b71b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -325,13 +325,17 @@
#define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200)
-#define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110
-#define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115
-#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125
-#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125
+#define AR_PHY_CCA_NOM_VAL_9300_2GHZ (AR_SREV_9462(ah) ? -127 : -110)
+#define AR_PHY_CCA_NOM_VAL_9300_5GHZ (AR_SREV_9462(ah) ? -127 : -115)
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ (AR_SREV_9462(ah) ? -127 : -125)
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ (AR_SREV_9462(ah) ? -127 : -125)
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100
+#define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118
+
+#define AR9300_EXT_LNA_CTL_GPIO_AR9485 9
+
/*
* AGC Field Definitions
*/
@@ -570,6 +574,8 @@
#define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300)
+#define AR_PHY_TX_IQCAL_CONTROL_0 (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+ 0x3c4 : 0x444))
#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + (AR_SREV_9485(ah) ? \
0x3c8 : 0x448))
#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + (AR_SREV_9485(ah) ? \
@@ -579,6 +585,7 @@
#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \
(AR_SREV_9485(ah) ? \
0x3d0 : 0x450) + ((_i) << 2))
+#define AR_PHY_RTT_CTRL (AR_SM_BASE + 0x380)
#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0)
#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4)
@@ -598,6 +605,17 @@
#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00
#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8
+/* AIC Registers */
+#define AR_PHY_AIC_CTRL_0_B0 (AR_SM_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B0 (AR_SM_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B0 (AR_SM_BASE + 0x4b8)
+#define AR_PHY_AIC_CTRL_3_B0 (AR_SM_BASE + 0x4bc)
+#define AR_PHY_AIC_STAT_0_B0 (AR_SM_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B0 (AR_SM_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
#define AR_PHY_65NM_CH0_SYNTH4 0x1608c
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002
@@ -607,7 +625,35 @@
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX4 0x1610c
-#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c)
+
+#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
+ ((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
+#define AR_CH0_TOP_XPABIASLVL (0x300)
+#define AR_CH0_TOP_XPABIASLVL_S (8)
+
+#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \
+ ((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
+
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+
+#define AR_SWITCH_TABLE_ALL (0xfff)
+#define AR_SWITCH_TABLE_ALL_S (0)
+
+#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\
+ (AR_SREV_9462(ah) ? 0x16294 : 0x1628c))
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
@@ -623,21 +669,23 @@
#define AR_PHY_65NM_CH2_RXTX1 0x16900
#define AR_PHY_65NM_CH2_RXTX2 0x16904
-#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
+ (AR_SREV_9462(ah) ? 0x16290 : 0x16284))
#define AR_CH0_TOP2_XPABIASLVL 0xf000
#define AR_CH0_TOP2_XPABIASLVL_S 12
-#define AR_CH0_XTAL (AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \
+ (AR_SREV_9462(ah) ? 0x16298 : 0x16290))
#define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
#define AR_CH0_XTAL_CAPOUTDAC_S 17
-#define AR_PHY_PMU1 0x16c40
+#define AR_PHY_PMU1 (AR_SREV_9462(ah) ? 0x16340 : 0x16c40)
#define AR_PHY_PMU1_PWD 0x1
#define AR_PHY_PMU1_PWD_S 0
-#define AR_PHY_PMU2 0x16c44
+#define AR_PHY_PMU2 (AR_SREV_9462(ah) ? 0x16344 : 0x16c44)
#define AR_PHY_PMU2_PGM 0x00200000
#define AR_PHY_PMU2_PGM_S 21
@@ -777,6 +825,22 @@
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
#define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004
+#define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION 0x00000001
+#define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S 0
+#define AR_PHY_RTT_CTRL_RESTORE_MASK 0x0000007E
+#define AR_PHY_RTT_CTRL_RESTORE_MASK_S 1
+#define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE 0x00000080
+#define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE_S 7
+#define AR_PHY_RTT_SW_RTT_TABLE_ACCESS 0x00000001
+#define AR_PHY_RTT_SW_RTT_TABLE_ACCESS_S 0
+#define AR_PHY_RTT_SW_RTT_TABLE_WRITE 0x00000002
+#define AR_PHY_RTT_SW_RTT_TABLE_WRITE_S 1
+#define AR_PHY_RTT_SW_RTT_TABLE_ADDR 0x0000001C
+#define AR_PHY_RTT_SW_RTT_TABLE_ADDR_S 2
+#define AR_PHY_RTT_SW_RTT_TABLE_DATA 0xFFFFFFF0
+#define AR_PHY_RTT_SW_RTT_TABLE_DATA_S 4
+#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL 0x80000000
+#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL_S 31
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
@@ -837,19 +901,42 @@
*/
#define AR_SM1_BASE 0xb200
-#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
-#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
-#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
-#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
-#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
-#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
-#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
-#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
-#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
-#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240)
+#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
+#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
+#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
+#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
+#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
+#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
+#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9462(ah) ? \
+ 0x280 : 0x240))
+#define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240)
+#define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff
+#define AR_PHY_TPC_19_B1_ALPHA_THERM_S 0
#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c)
#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2))
+/* SM 1 AIC Registers */
+
+#define AR_PHY_AIC_CTRL_0_B1 (AR_SM1_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B1 (AR_SM1_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B1 (AR_SM1_BASE + 0x4b8)
+#define AR_PHY_AIC_STAT_0_B1 (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B1 (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B1 (AR_SM1_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B1 (AR_SM1_BASE + 0x4cc)
+
+#define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0)
+#define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4)
+
+#define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + ((i) ? \
+ AR_SM1_BASE : AR_SM_BASE))
+#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + ((i) ? \
+ AR_SM1_BASE : AR_SM_BASE))
/*
* Channel 2 Register Map
*/
@@ -912,6 +999,13 @@
#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180)
+/* GLB Registers */
+#define AR_GLB_BASE 0x20000
+#define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44)
+#define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \
+ (AR_SREV_9462_20(_ah) ? 0x4c : 0x50))
+#define AR_GLB_STATUS (AR_GLB_BASE + 0x48)
+
/*
* Misc helper defines
*/
@@ -1119,6 +1213,7 @@
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
-void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
+#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
+#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0
#endif /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index f75068b..7c70cf2 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/completion.h>
@@ -54,8 +55,6 @@ struct ath_node;
(_l) &= ((_sz) - 1); \
} while (0)
-#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
-
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
@@ -78,30 +77,28 @@ struct ath_config {
sizeof(struct ath_buf_state)); \
} while (0)
-#define ATH_RXBUF_RESET(_bf) do { \
- (_bf)->bf_stale = false; \
- } while (0)
-
/**
* enum buffer_type - Buffer type flags
*
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
* @BUF_AGGR: Indicates whether the buffer can be aggregated
* (used in aggregation scheduling)
- * @BUF_XRETRY: To denote excessive retries of the buffer
*/
enum buffer_type {
BUF_AMPDU = BIT(0),
BUF_AGGR = BIT(1),
- BUF_XRETRY = BIT(2),
};
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
-#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
#define ATH_TXSTATUS_RING_SIZE 64
+#define DS2PHYS(_dd, _ds) \
+ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
struct ath_descdma {
void *dd_desc;
dma_addr_t dd_desc_paddr;
@@ -179,7 +176,7 @@ enum ATH_AGGR_STATUS {
struct ath_txq {
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
u32 axq_qnum; /* ath9k hardware queue number */
- u32 *axq_link;
+ void *axq_link;
struct list_head axq_q;
spinlock_t axq_lock;
u32 axq_depth;
@@ -188,7 +185,6 @@ struct ath_txq {
bool axq_tx_inprogress;
struct list_head axq_acq;
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
- struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
int pending_frames;
@@ -203,18 +199,19 @@ struct ath_atx_ac {
};
struct ath_frame_info {
+ struct ath_buf *bf;
int framelen;
- u32 keyix;
enum ath9k_key_type keytype;
+ u8 keyix;
u8 retries;
- u16 seqno;
};
struct ath_buf_state {
u8 bf_type;
u8 bfs_paprd;
+ u8 ndelim;
+ u16 seqno;
unsigned long bfs_paprd_timestamp;
- enum ath9k_internal_frame_type bfs_ftype;
};
struct ath_buf {
@@ -227,13 +224,12 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
- u16 bf_flags;
struct ath_buf_state bf_state;
};
struct ath_atx_tid {
struct list_head list;
- struct list_head buf_q;
+ struct sk_buff_head buf_q;
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
@@ -270,14 +266,11 @@ struct ath_node {
struct ath_tx_control {
struct ath_txq *txq;
struct ath_node *an;
- int if_id;
- enum ath9k_internal_frame_type frame_type;
u8 paprd;
};
#define ATH_TX_ERROR 0x01
-#define ATH_TX_XRETRY 0x02
-#define ATH_TX_BAR 0x04
+#define ATH_TX_BAR 0x02
/**
* @txq_map: Index is mac80211 queue number. This is
@@ -311,6 +304,7 @@ struct ath_rx {
struct ath_buf *rx_bufptr;
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+ struct ath_buf *buf_hold;
struct sk_buff *frag;
};
@@ -343,7 +337,8 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
-bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
+void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+ struct ath_node *an);
/********/
/* VIFs */
@@ -424,10 +419,12 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
+void ath_reset_work(struct work_struct *work);
void ath_hw_check(struct work_struct *work);
void ath_hw_pll_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);
+void ath_start_ani(struct ath_common *common);
/**********/
/* BTCOEX */
@@ -458,6 +455,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
#define ATH_LED_PIN_9287 8
#define ATH_LED_PIN_9300 10
#define ATH_LED_PIN_9485 6
+#define ATH_LED_PIN_9462 0
#ifdef CONFIG_MAC80211_LEDS
void ath_init_leds(struct ath_softc *sc);
@@ -557,8 +555,7 @@ struct ath_ant_comb {
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
-#define SC_OP_ENABLE_APM BIT(15)
-#define SC_OP_PRIM_STA_VIF BIT(16)
+#define SC_OP_PRIM_STA_VIF BIT(15)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
@@ -566,7 +563,6 @@ struct ath_ant_comb {
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
#define PS_WAIT_FOR_TX_ACK BIT(3)
#define PS_BEACON_SYNC BIT(4)
-#define PS_TSFOOR_SYNC BIT(5)
struct ath_rate_table;
@@ -579,7 +575,7 @@ struct ath9k_vif_iter_data {
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
- int nwds; /* number of nwd vifs */
+ int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
int nothers; /* number of vifs not specified above. */
};
@@ -604,6 +600,7 @@ struct ath_softc {
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_check_work;
+ struct work_struct hw_reset_work;
struct completion paprd_complete;
unsigned int hw_busy_count;
@@ -647,10 +644,10 @@ struct ath_softc {
struct ath_descdma txsdma;
struct ath_ant_comb ant_comb;
+ u8 ant_tx, ant_rx;
};
void ath9k_tasklet(unsigned long data);
-int ath_reset(struct ath_softc *sc, bool retry_tx);
int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@@ -664,17 +661,13 @@ extern int led_blink;
extern bool is_ath9k_unloaded;
irqreturn_t ath_isr(int irq, void *dev);
-void ath9k_init_crypto(struct ath_softc *sc);
-int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
- struct ath9k_channel *hchan);
+void ath9k_reload_chainmask_settings(struct ath_softc *sc);
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
bool ath9k_uses_beacons(int type);
#ifdef CONFIG_ATH9K_PCI
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index b109c47..2bbc83e 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#define FUDGE 2
@@ -72,44 +73,39 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
struct sk_buff *skb = bf->bf_mpdu;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_desc *ds;
- struct ath9k_11n_rate_series series[4];
- int flags, ctsrate = 0, ctsduration = 0;
+ struct ath_tx_info info;
struct ieee80211_supported_band *sband;
+ u8 chainmask = ah->txchainmask;
u8 rate = 0;
ath9k_reset_beacon_status(sc);
- ds = bf->bf_desc;
- flags = ATH9K_TXDESC_NOACK;
-
- ds->ds_link = 0;
-
sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
rate |= sband->bitrates[rateidx].hw_value_short;
- ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
- ATH9K_PKT_TYPE_BEACON,
- MAX_RATE_POWER,
- ATH9K_TXKEYIX_INVALID,
- ATH9K_KEY_TYPE_CLEAR,
- flags);
-
- /* NB: beacon's BufLen must be a multiple of 4 bytes */
- ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
- true, true, ds, bf->bf_buf_addr,
- sc->beacon.beaconq);
-
- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
- series[0].Tries = 1;
- series[0].Rate = rate;
- series[0].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[0].Rate);
- series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
- ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
- series, 4, 0);
+ memset(&info, 0, sizeof(info));
+ info.pkt_len = skb->len + FCS_LEN;
+ info.type = ATH9K_PKT_TYPE_BEACON;
+ info.txpower = MAX_RATE_POWER;
+ info.keyix = ATH9K_TXKEYIX_INVALID;
+ info.keytype = ATH9K_KEY_TYPE_CLEAR;
+ info.flags = ATH9K_TXDESC_NOACK;
+
+ info.buf_addr[0] = bf->bf_buf_addr;
+ info.buf_len[0] = roundup(skb->len, 4);
+
+ info.is_first = true;
+ info.is_last = true;
+
+ info.qcu = sc->beacon.beaconq;
+
+ info.rates[0].Tries = 1;
+ info.rates[0].Rate = rate;
+ info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
+
+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
}
static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -361,6 +357,7 @@ void ath_beacon_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL;
struct ieee80211_vif *vif;
+ struct ath_tx_status ts;
int slot;
u32 bfaddr, bc = 0;
@@ -385,7 +382,7 @@ void ath_beacon_tasklet(unsigned long data)
ath_dbg(common, ATH_DBG_BSTUCK,
"beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET;
- ath_reset(sc, true);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
return;
@@ -465,6 +462,11 @@ void ath_beacon_tasklet(unsigned long data)
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
}
}
@@ -497,7 +499,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
u32 nexttbtt, intval;
/* NB: the beacon interval is kept internally in TU's */
- intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
+ intval = TU_TO_USEC(conf->beacon_interval);
intval /= ATH_BCBUF; /* for staggered beacons */
nexttbtt = intval;
@@ -511,9 +513,11 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
/* Set the computed AP beacon timers */
ath9k_hw_disable_interrupts(ah);
+ sc->sc_flags |= SC_OP_TSF_RESET;
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
/*
@@ -544,7 +548,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
}
memset(&bs, 0, sizeof(bs));
- intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = conf->beacon_interval;
/*
* Setup dtim and cfp parameters according to
@@ -640,12 +644,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
ath9k_hw_set_sta_beacon_timers(ah, &bs);
ah->imask |= ATH9K_INT_BMISS;
- /*
- * If the beacon config is called beacause of TSFOOR,
- * Interrupts will be enabled back at the end of ath9k_tasklet
- */
- if (!(sc->ps_flags & PS_TSFOOR_SYNC))
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
static void ath_beacon_config_adhoc(struct ath_softc *sc,
@@ -653,22 +653,13 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- u32 tsf, delta, intval, nexttbtt;
+ u32 tsf, intval, nexttbtt;
ath9k_reset_beacon_status(sc);
- tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
- intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
-
- if (!sc->beacon.bc_tstamp)
- nexttbtt = tsf + intval;
- else {
- if (tsf > sc->beacon.bc_tstamp)
- delta = (tsf - sc->beacon.bc_tstamp);
- else
- delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
- nexttbtt = tsf + intval - (delta % intval);
- }
+ intval = TU_TO_USEC(conf->beacon_interval);
+ tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
+ nexttbtt = tsf + intval;
ath_dbg(common, ATH_DBG_BEACON,
"IBSS nexttbtt %u intval %u (%u)\n",
@@ -688,12 +679,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
ath9k_hw_disable_interrupts(ah);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
- /*
- * If the beacon config is called beacause of TSFOOR,
- * Interrupts will be enabled back at the end of ath9k_tasklet
- */
- if (!(sc->ps_flags & PS_TSFOOR_SYNC))
- ath9k_hw_set_interrupts(ah, ah->imask);
+
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
static bool ath9k_allow_beacon_config(struct ath_softc *sc,
@@ -834,11 +822,11 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
if (status) {
/* Re-enable beaconing */
ah->imask |= ATH9K_INT_SWBA;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
} else {
/* Disable SWBA interrupt */
ah->imask &= ~ATH9K_INT_SWBA;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
tasklet_kill(&sc->bcon_tasklet);
ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
}
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 41ce0b1..0122639 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/export.h>
#include "hw.h"
enum ath_bt_mode {
@@ -50,7 +51,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
.bt_first_slot_time = 5,
.bt_hold_rx_clear = true,
};
- u32 i;
+ u32 i, idx;
bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
if (AR_SREV_9300_20_OR_LATER(ah))
@@ -73,8 +74,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
AR_BT_DISABLE_BT_ANT;
- for (i = 0; i < 32; i++)
- ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
+ for (i = 0; i < 32; i++) {
+ idx = (debruijn32 << i) >> 27;
+ ah->hw_gen_timers.gen_timer_index[idx] = i;
+ }
}
EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 1f2f97f..5e522e4 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -16,6 +16,7 @@
#include "hw.h"
#include "hw-ops.h"
+#include <linux/export.h>
/* Common calibration code */
@@ -62,13 +63,26 @@ static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
return ath9k_hw_get_nf_limits(ah, chan)->nominal;
}
+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ s8 noise = ATH_DEFAULT_NOISE_FLOOR;
+
+ if (chan && chan->noisefloor) {
+ s8 delta = chan->noisefloor -
+ ATH9K_NF_CAL_NOISE_THRESH -
+ ath9k_hw_get_default_nf(ah, chan);
+ if (delta > 0)
+ noise += delta;
+ }
+ return noise;
+}
+EXPORT_SYMBOL(ath9k_hw_getchan_noise);
static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_hw_cal_data *cal,
int16_t *nfarray)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &common->hw->conf;
struct ath_nf_limits *limit;
struct ath9k_nfcal_hist *h;
bool high_nf_mid = false;
@@ -80,7 +94,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
- ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
continue;
h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
@@ -384,8 +398,10 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
caldata->nfcal_pending = false;
ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
chan->noisefloor = h[0].privNF;
+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
return true;
}
+EXPORT_SYMBOL(ath9k_hw_getnf);
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_channel *chan)
@@ -396,6 +412,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
ah->caldata->channel = chan->channel;
ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+ ah->caldata->chanmode = chan->chanmode;
h = ah->caldata->nfCalHist;
default_nf = ath9k_hw_get_default_nf(ah, chan);
for (i = 0; i < NUM_NF_READINGS; i++) {
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 1bef41d..e300a73 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -22,6 +22,9 @@
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
+/* Internal noise floor can vary by about 6db depending on the frequency */
+#define ATH9K_NF_CAL_NOISE_THRESH 6
+
#define NUM_NF_READINGS 6
#define ATH9K_NF_CAL_HIST_MAX 5
@@ -108,6 +111,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
void ath9k_hw_reset_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
#endif /* CALIB_H */
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index fa6bd2d..905f1b3 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -161,14 +161,42 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower)
{
- if (cur_txpow != new_txpow) {
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+
+ if (reg->power_limit != new_txpow) {
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
/* read back in case value is clamped */
- *txpower = ath9k_hw_regulatory(ah)->power_limit;
+ *txpower = reg->max_power_level;
}
}
EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+void ath9k_cmn_init_crypto(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i = 0;
+
+ /* Get the hardware key cache size. */
+ common->keymax = AR_KEYTABLE_SIZE;
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < common->keymax; i++)
+ ath_hw_keyreset(common, (u16) i);
+}
+EXPORT_SYMBOL(ath9k_cmn_init_crypto);
+
static int __init ath9k_cmn_init(void)
{
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 247f7f8..f1c32a5 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -62,3 +62,4 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
enum ath_stomp_type stomp_type);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower);
+void ath9k_cmn_init_crypto(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d55ffd7..2741203 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/export.h>
#include <asm/unaligned.h>
#include "ath9k.h"
@@ -95,11 +96,11 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
char buf[32];
unsigned int len;
- len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
+ len = sprintf(buf, "0x%08x\n", ah->txchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -107,7 +108,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
unsigned long mask;
char buf[32];
ssize_t len;
@@ -120,8 +121,8 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
- common->tx_chainmask = mask;
- sc->sc_ah->caps.tx_chainmask = mask;
+ ah->txchainmask = mask;
+ ah->caps.tx_chainmask = mask;
return count;
}
@@ -138,11 +139,11 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
char buf[32];
unsigned int len;
- len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
+ len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -150,7 +151,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
unsigned long mask;
char buf[32];
ssize_t len;
@@ -163,8 +164,8 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
- common->rx_chainmask = mask;
- sc->sc_ah->caps.rx_chainmask = mask;
+ ah->rxchainmask = mask;
+ ah->caps.rx_chainmask = mask;
return count;
}
@@ -176,6 +177,56 @@ static const struct file_operations fops_rx_chainmask = {
.llseek = default_llseek,
};
+static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ char buf[32];
+ unsigned int len;
+
+ len = sprintf(buf, "%d\n", common->disable_ani);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_disable_ani(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned long disable_ani;
+ char buf[32];
+ ssize_t len;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (strict_strtoul(buf, 0, &disable_ani))
+ return -EINVAL;
+
+ common->disable_ani = !!disable_ani;
+
+ if (disable_ani) {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ } else {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_disable_ani = {
+ .read = read_file_disable_ani,
+ .write = write_file_disable_ani,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
static ssize_t read_file_dma(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -473,9 +524,22 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
if (tmp & ATH9K_RX_FILTER_PHYRADAR)
len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
- len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
- else
- len += snprintf(buf + len, sizeof(buf) - len, "\n");
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "\n\nReset causes:\n"
+ " baseband hang: %d\n"
+ " baseband watchdog: %d\n"
+ " fatal hardware error interrupt: %d\n"
+ " tx hardware error: %d\n"
+ " tx path hang: %d\n"
+ " pll rx hang: %d\n",
+ sc->debug.stats.reset[RESET_TYPE_BB_HANG],
+ sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG],
+ sc->debug.stats.reset[RESET_TYPE_FATAL_INT],
+ sc->debug.stats.reset[RESET_TYPE_TX_ERROR],
+ sc->debug.stats.reset[RESET_TYPE_TX_HANG],
+ sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -550,6 +614,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("MPDUs Queued: ", queued);
PR("MPDUs Completed: ", completed);
+ PR("MPDUs XRetried: ", xretries);
PR("Aggregates: ", a_aggr);
PR("AMPDUs Queued HW:", a_queued_hw);
PR("AMPDUs Queued SW:", a_queued_sw);
@@ -587,7 +652,6 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PRQLE("axq_q empty: ", axq_q);
PRQLE("axq_acq empty: ", axq_acq);
- PRQLE("txq_fifo_pending: ", txq_fifo_pending);
for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
PRQLE(tmp, txq_fifo[i]);
@@ -661,7 +725,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf,
" tid: %p %s %s %i %p %p\n",
tid, tid->sched ? "sched" : "idle",
tid->paused ? "paused" : "running",
- list_empty(&tid->buf_q),
+ skb_queue_empty(&tid->buf_q),
tid->an, tid->ac);
if (len >= size)
goto done;
@@ -699,7 +763,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
char *buf;
unsigned int len = 0, size = 8000;
ssize_t retval = 0;
- const char *tmp;
unsigned int reg;
struct ath9k_vif_iter_data iter_data;
@@ -709,31 +772,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;
- switch (sc->sc_ah->opmode) {
- case NL80211_IFTYPE_ADHOC:
- tmp = "ADHOC";
- break;
- case NL80211_IFTYPE_MESH_POINT:
- tmp = "MESH";
- break;
- case NL80211_IFTYPE_AP:
- tmp = "AP";
- break;
- case NL80211_IFTYPE_STATION:
- tmp = "STATION";
- break;
- default:
- tmp = "???";
- break;
- }
-
ath9k_ps_wakeup(sc);
len += snprintf(buf + len, size - len,
"curbssid: %pM\n"
"OP-Mode: %s(%i)\n"
"Beacon-Timer-Register: 0x%x\n",
common->curbssid,
- tmp, (int)(sc->sc_ah->opmode),
+ ath_opmode_to_string(sc->sc_ah->opmode),
+ (int)(sc->sc_ah->opmode),
REG_READ(ah, AR_BEACON_PERIOD));
reg = REG_READ(ah, AR_TIMER_MODE);
@@ -794,20 +840,26 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
}
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, struct ath_txq *txq)
+ struct ath_tx_status *ts, struct ath_txq *txq,
+ unsigned int flags)
{
+#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
+ [sc->debug.tsidx].c)
int qnum = txq->axq_qnum;
TX_STAT_INC(qnum, tx_pkts_all);
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
if (bf_isampdu(bf)) {
- if (bf_isxretried(bf))
+ if (flags & ATH_TX_BAR)
TX_STAT_INC(qnum, a_xretries);
else
TX_STAT_INC(qnum, a_completed);
} else {
- TX_STAT_INC(qnum, completed);
+ if (ts->ts_status & ATH9K_TXERR_XRETRY)
+ TX_STAT_INC(qnum, xretries);
+ else
+ TX_STAT_INC(qnum, completed);
}
if (ts->ts_status & ATH9K_TXERR_FIFO)
@@ -822,6 +874,35 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
TX_STAT_INC(qnum, data_underrun);
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(qnum, delim_underrun);
+
+ spin_lock(&sc->debug.samp_lock);
+ TX_SAMP_DBG(jiffies) = jiffies;
+ TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
+ TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1;
+ TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2;
+ TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0;
+ TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1;
+ TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2;
+ TX_SAMP_DBG(rateindex) = ts->ts_rateindex;
+ TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK);
+ TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry;
+ TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry;
+ TX_SAMP_DBG(rssi) = ts->ts_rssi;
+ TX_SAMP_DBG(tid) = ts->tid;
+ TX_SAMP_DBG(qid) = ts->qid;
+
+ if (ts->ts_flags & ATH9K_TX_BA) {
+ TX_SAMP_DBG(ba_low) = ts->ba_low;
+ TX_SAMP_DBG(ba_high) = ts->ba_high;
+ } else {
+ TX_SAMP_DBG(ba_low) = 0;
+ TX_SAMP_DBG(ba_high) = 0;
+ }
+
+ sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
+ spin_unlock(&sc->debug.samp_lock);
+
+#undef TX_SAMP_DBG
}
static const struct file_operations fops_xmit = {
@@ -960,6 +1041,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{
#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
+#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\
+ [sc->debug.rsidx].c)
u32 phyerr;
@@ -995,8 +1078,25 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
+ spin_lock(&sc->debug.samp_lock);
+ RX_SAMP_DBG(jiffies) = jiffies;
+ RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
+ RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
+ RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
+ RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
+ RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
+ RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
+ RX_SAMP_DBG(antenna) = rs->rs_antenna;
+ RX_SAMP_DBG(rssi) = rs->rs_rssi;
+ RX_SAMP_DBG(rate) = rs->rs_rate;
+ RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon;
+
+ sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
+ spin_unlock(&sc->debug.samp_lock);
+
#undef RX_STAT_INC
#undef RX_PHY_ERR_INC
+#undef RX_SAMP_DBG
}
static const struct file_operations fops_recv = {
@@ -1128,6 +1228,389 @@ static const struct file_operations fops_regdump = {
.llseek = default_llseek,/* read accesses f_pos */
};
+static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &common->hw->conf;
+ u32 len = 0, size = 1500;
+ u32 i, j;
+ ssize_t retval = 0;
+ char *buf;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ u8 nread;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += snprintf(buf + len, size - len,
+ "Channel Noise Floor : %d\n", ah->noise);
+ len += snprintf(buf + len, size - len,
+ "Chain | privNF | # Readings | NF Readings\n");
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!(chainmask & (1 << i)) ||
+ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ continue;
+
+ nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
+ len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+ i, h[i].privNF, nread);
+ for (j = 0; j < nread; j++)
+ len += snprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += snprintf(buf + len, size - len, "\n");
+ }
+
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_dump_nfcal = {
+ .read = read_file_dump_nfcal,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ u32 len = 0, size = 1500;
+ ssize_t retval = 0;
+ char *buf;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_base_eeprom = {
+ .read = read_file_base_eeprom,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ u32 len = 0, size = 6000;
+ char *buf;
+ size_t retval;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_modal_eeprom = {
+ .read = read_file_modal_eeprom,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ unsigned long flags;
+ int i;
+
+ ath9k_ps_wakeup(sc);
+
+ spin_lock_bh(&sc->debug.samp_lock);
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath_hw_cycle_counters_update(common);
+
+ ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
+ ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
+ ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
+ ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ ATH_SAMP_DBG(noise) = ah->noise;
+
+ REG_WRITE_D(ah, AR_MACMISC,
+ ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+ (AR_MACMISC_MISC_OBS_BUS_1 <<
+ AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+ ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah,
+ AR_DMADBG_0 + (i * sizeof(u32)));
+
+ ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1);
+ ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR);
+
+ memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist,
+ sizeof(ATH_SAMP_DBG(nfCalHist)));
+
+ sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES;
+ spin_unlock_bh(&sc->debug.samp_lock);
+ ath9k_ps_restore(sc);
+
+#undef ATH_SAMP_DBG
+}
+
+static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
+{
+#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c
+ struct ath_softc *sc = inode->i_private;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &common->hw->conf;
+ struct ath_dbg_bb_mac_samp *bb_mac_samp;
+ struct ath9k_nfcal_hist *h;
+ int i, j, qcuOffset = 0, dcuOffset = 0;
+ u32 *qcuBase, *dcuBase, size = 30000, len = 0;
+ u32 sampidx = 0;
+ u8 *buf;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ u8 nread;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EAGAIN;
+
+ buf = vmalloc(size);
+ if (!buf)
+ return -ENOMEM;
+ bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+ if (!bb_mac_samp) {
+ vfree(buf);
+ return -ENOMEM;
+ }
+ /* Account the current state too */
+ ath9k_debug_samp_bb_mac(sc);
+
+ spin_lock_bh(&sc->debug.samp_lock);
+ memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
+ sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+ len += snprintf(buf + len, size - len,
+ "Current Sample Index: %d\n", sc->debug.sampidx);
+ spin_unlock_bh(&sc->debug.samp_lock);
+
+ len += snprintf(buf + len, size - len,
+ "Raw DMA Debug Dump:\n");
+ len += snprintf(buf + len, size - len, "Sample |\t");
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+ len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i);
+ len += snprintf(buf + len, size - len, "\n");
+
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ len += snprintf(buf + len, size - len, "%d\t", sampidx);
+
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+ len += snprintf(buf + len, size - len, " %08x\t",
+ ATH_SAMP_DBG(dma_dbg_reg_vals[i]));
+ len += snprintf(buf + len, size - len, "\n");
+ }
+ len += snprintf(buf + len, size - len, "\n");
+
+ len += snprintf(buf + len, size - len,
+ "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
+ dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
+
+ for (i = 0; i < ATH9K_NUM_QUEUES; i++,
+ qcuOffset += 4, dcuOffset += 5) {
+ if (i == 8) {
+ qcuOffset = 0;
+ qcuBase++;
+ }
+
+ if (i == 6) {
+ dcuOffset = 0;
+ dcuBase++;
+ }
+ if (!sc->debug.stats.txstats[i].queued)
+ continue;
+
+ len += snprintf(buf + len, size - len,
+ "%4d %7d %2x %1x %2x %2x\n",
+ sampidx, i,
+ (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+ (*qcuBase & (0x8 << qcuOffset)) >>
+ (qcuOffset + 3),
+ ATH_SAMP_DBG(dma_dbg_reg_vals[2]) &
+ (0x7 << (i * 3)) >> (i * 3),
+ (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+ }
+ len += snprintf(buf + len, size - len, "\n");
+ }
+ len += snprintf(buf + len, size - len,
+ "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp "
+ "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 "
+ "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n");
+
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
+ dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
+
+ len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22);
+ len += snprintf(buf + len, size - len, "%7x %8x ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3));
+ len += snprintf(buf + len, size - len, "%7x %7x ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27);
+ len += snprintf(buf + len, size - len, "%7d %12d ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10);
+ len += snprintf(buf + len, size - len, "%12d %12d ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12);
+ len += snprintf(buf + len, size - len, "%12d %12d ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17);
+ len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n",
+ ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr));
+ }
+
+ len += snprintf(buf + len, size - len,
+ "Sample ChNoise Chain privNF #Reading Readings\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ h = ATH_SAMP_DBG(nfCalHist);
+ if (!ATH_SAMP_DBG(noise))
+ continue;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!(chainmask & (1 << i)) ||
+ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ continue;
+
+ nread = AR_PHY_CCA_FILTERWINDOW_LENGTH -
+ h[i].invalidNFcount;
+ len += snprintf(buf + len, size - len,
+ "%4d %5d %4d\t %d\t %d\t",
+ sampidx, ATH_SAMP_DBG(noise),
+ i, h[i].privNF, nread);
+ for (j = 0; j < nread; j++)
+ len += snprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += snprintf(buf + len, size - len, "\n");
+ }
+ }
+ len += snprintf(buf + len, size - len, "\nCycle counters:\n"
+ "Sample Total Rxbusy Rxframes Txframes\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ if (!ATH_SAMP_DBG(cc.cycles))
+ continue;
+ len += snprintf(buf + len, size - len,
+ "%4d %08x %08x %08x %08x\n",
+ sampidx, ATH_SAMP_DBG(cc.cycles),
+ ATH_SAMP_DBG(cc.rx_busy),
+ ATH_SAMP_DBG(cc.rx_frame),
+ ATH_SAMP_DBG(cc.tx_frame));
+ }
+
+ len += snprintf(buf + len, size - len, "Tx status Dump :\n");
+ len += snprintf(buf + len, size - len,
+ "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb "
+ "isok rts_fail data_fail rate tid qid "
+ "ba_low ba_high tx_before(ms)\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
+ if (!ATH_SAMP_DBG(ts[i].jiffies))
+ continue;
+ len += snprintf(buf + len, size - len, "%-14d"
+ "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d "
+ "%-9d %-4d %-3d %-3d %08x %08x %-11d\n",
+ sampidx,
+ ATH_SAMP_DBG(ts[i].rssi_ctl0),
+ ATH_SAMP_DBG(ts[i].rssi_ctl1),
+ ATH_SAMP_DBG(ts[i].rssi_ctl2),
+ ATH_SAMP_DBG(ts[i].rssi_ext0),
+ ATH_SAMP_DBG(ts[i].rssi_ext1),
+ ATH_SAMP_DBG(ts[i].rssi_ext2),
+ ATH_SAMP_DBG(ts[i].rssi),
+ ATH_SAMP_DBG(ts[i].isok),
+ ATH_SAMP_DBG(ts[i].rts_fail_cnt),
+ ATH_SAMP_DBG(ts[i].data_fail_cnt),
+ ATH_SAMP_DBG(ts[i].rateindex),
+ ATH_SAMP_DBG(ts[i].tid),
+ ATH_SAMP_DBG(ts[i].qid),
+ ATH_SAMP_DBG(ts[i].ba_low),
+ ATH_SAMP_DBG(ts[i].ba_high),
+ jiffies_to_msecs(jiffies -
+ ATH_SAMP_DBG(ts[i].jiffies)));
+ }
+ }
+
+ len += snprintf(buf + len, size - len, "Rx status Dump :\n");
+ len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 "
+ "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
+ if (!ATH_SAMP_DBG(rs[i].jiffies))
+ continue;
+ len += snprintf(buf + len, size - len, "%-14d"
+ "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n",
+ sampidx,
+ ATH_SAMP_DBG(rs[i].rssi_ctl0),
+ ATH_SAMP_DBG(rs[i].rssi_ctl1),
+ ATH_SAMP_DBG(rs[i].rssi_ctl2),
+ ATH_SAMP_DBG(rs[i].rssi_ext0),
+ ATH_SAMP_DBG(rs[i].rssi_ext1),
+ ATH_SAMP_DBG(rs[i].rssi_ext2),
+ ATH_SAMP_DBG(rs[i].rssi),
+ ATH_SAMP_DBG(rs[i].is_mybeacon) ?
+ "True" : "False",
+ ATH_SAMP_DBG(rs[i].antenna),
+ ATH_SAMP_DBG(rs[i].rate),
+ jiffies_to_msecs(jiffies -
+ ATH_SAMP_DBG(rs[i].jiffies)));
+ }
+ }
+
+ vfree(bb_mac_samp);
+ file->private_data = buf;
+
+ return 0;
+#undef ATH_SAMP_DBG
+}
+
+static const struct file_operations fops_samps = {
+ .open = open_file_bb_mac_samps,
+ .read = ath9k_debugfs_read_buf,
+ .release = ath9k_debugfs_release_buf,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1160,6 +1643,8 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, sc, &fops_rx_chainmask);
debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
+ debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
+ sc->debug.debugfs_phy, sc, &fops_disable_ani);
debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
sc, &fops_regidx);
debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
@@ -1169,6 +1654,14 @@ int ath9k_init_debug(struct ath_hw *ah)
&ah->config.cwm_ignore_extcca);
debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_regdump);
+ debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_dump_nfcal);
+ debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_base_eeprom);
+ debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_modal_eeprom);
+ debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_samps);
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
@@ -1177,5 +1670,9 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
sc->debug.regidx = 0;
+ memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
+ sc->debug.sampidx = 0;
+ sc->debug.tsidx = 0;
+ sc->debug.rsidx = 0;
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 8ce6ad8..356352a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -25,8 +25,10 @@ struct ath_buf;
#ifdef CONFIG_ATH9K_DEBUGFS
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
+#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
#else
#define TX_STAT_INC(q, c) do { } while (0)
+#define RESET_STAT_INC(sc, type) do { } while (0)
#endif
#ifdef CONFIG_ATH9K_DEBUGFS
@@ -116,6 +118,7 @@ struct ath_tx_stats {
u32 tx_bytes_all;
u32 queued;
u32 completed;
+ u32 xretries;
u32 a_aggr;
u32 a_queued_hw;
u32 a_queued_sw;
@@ -170,23 +173,80 @@ struct ath_rx_stats {
u8 rs_antenna;
};
+enum ath_reset_type {
+ RESET_TYPE_BB_HANG,
+ RESET_TYPE_BB_WATCHDOG,
+ RESET_TYPE_FATAL_INT,
+ RESET_TYPE_TX_ERROR,
+ RESET_TYPE_TX_HANG,
+ RESET_TYPE_PLL_HANG,
+ __RESET_TYPE_MAX
+};
+
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
struct ath_rx_stats rxstats;
+ u32 reset[__RESET_TYPE_MAX];
+};
+
+#define ATH_DBG_MAX_SAMPLES 10
+struct ath_dbg_bb_mac_samp {
+ u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS];
+ u32 pcu_obs, pcu_cr, noise;
+ struct {
+ u64 jiffies;
+ int8_t rssi_ctl0;
+ int8_t rssi_ctl1;
+ int8_t rssi_ctl2;
+ int8_t rssi_ext0;
+ int8_t rssi_ext1;
+ int8_t rssi_ext2;
+ int8_t rssi;
+ bool isok;
+ u8 rts_fail_cnt;
+ u8 data_fail_cnt;
+ u8 rateindex;
+ u8 qid;
+ u8 tid;
+ u32 ba_low;
+ u32 ba_high;
+ } ts[ATH_DBG_MAX_SAMPLES];
+ struct {
+ u64 jiffies;
+ int8_t rssi_ctl0;
+ int8_t rssi_ctl1;
+ int8_t rssi_ctl2;
+ int8_t rssi_ext0;
+ int8_t rssi_ext1;
+ int8_t rssi_ext2;
+ int8_t rssi;
+ bool is_mybeacon;
+ u8 antenna;
+ u8 rate;
+ } rs[ATH_DBG_MAX_SAMPLES];
+ struct ath_cycle_counters cc;
+ struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
};
struct ath9k_debug {
struct dentry *debugfs_phy;
u32 regidx;
struct ath_stats stats;
+ spinlock_t samp_lock;
+ struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
+ u8 sampidx;
+ u8 tsidx;
+ u8 rsidx;
};
int ath9k_init_debug(struct ath_hw *ah);
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, struct ath_txq *txq);
+ struct ath_tx_status *ts, struct ath_txq *txq,
+ unsigned int flags);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
#else
@@ -196,6 +256,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0;
}
+static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+}
+
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
@@ -204,7 +268,8 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_buf *bf,
struct ath_tx_status *ts,
- struct ath_txq *txq)
+ struct ath_txq *txq,
+ unsigned int flags)
{
}
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index e61404d..e46f751 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
pPdGainBoundaries[i] =
min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
- if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
- minDelta = pPdGainBoundaries[0] - 23;
- pPdGainBoundaries[0] = 23;
- } else {
- minDelta = 0;
- }
+ minDelta = 0;
if (i == 0) {
if (AR_SREV_9280_20_OR_LATER(ah))
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index de99c0d..49abd34 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -104,16 +104,11 @@
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
-#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
-#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
-#define AR_EEPROM_RFSILENT_POLARITY 0x0002
-#define AR_EEPROM_RFSILENT_POLARITY_S 1
-
#define EEP_RFSILENT_ENABLED 0x0001
#define EEP_RFSILENT_ENABLED_S 0
#define EEP_RFSILENT_POLARITY 0x0002
#define EEP_RFSILENT_POLARITY_S 1
-#define EEP_RFSILENT_GPIO_SEL 0x001c
+#define EEP_RFSILENT_GPIO_SEL (AR_SREV_9462(ah) ? 0x00fc : 0x001c)
#define EEP_RFSILENT_GPIO_SEL_S 2
#define AR5416_OPFLAGS_11A 0x01
@@ -225,7 +220,6 @@ enum eeprom_param {
EEP_MAC_MID,
EEP_MAC_LSW,
EEP_REG_0,
- EEP_REG_1,
EEP_OP_CAP,
EEP_OP_MODE,
EEP_RF_SILENT,
@@ -253,7 +247,9 @@ enum eeprom_param {
EEP_PAPRD,
EEP_MODAL_VER,
EEP_ANT_DIV_CTL1,
- EEP_CHAIN_MASK_REDUCE
+ EEP_CHAIN_MASK_REDUCE,
+ EEP_ANTENNA_GAIN_2G,
+ EEP_ANTENNA_GAIN_5G
};
enum ar5416_rates {
@@ -649,14 +645,15 @@ struct eeprom_ops {
int (*check_eeprom)(struct ath_hw *hw);
u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
bool (*fill_eeprom)(struct ath_hw *hw);
+ u32 (*dump_eeprom)(struct ath_hw *hw, bool dump_base_hdr, u8 *buf,
+ u32 len, u32 size);
int (*get_eeprom_ver)(struct ath_hw *hw);
int (*get_eeprom_rev)(struct ath_hw *hw);
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
u16 cfgCtl, u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower, u8 powerLimit,
- bool test);
+ u8 powerLimit, bool test);
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 5b1e894..9a7520f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9002_phy.h"
@@ -71,6 +72,117 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_4k_fill_eeprom(ah);
}
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
+ struct modal_eep_4k_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+ PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+ PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+ PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
+ PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
+ PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+ PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("xpdGain", modal_hdr->xpdGain);
+ PR_EEP("External PD", modal_hdr->xpd);
+ PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+ PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+ PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+ PR_EEP("O/D Bias Version", modal_hdr->version);
+ PR_EEP("CCK OutputBias", modal_hdr->ob_0);
+ PR_EEP("BPSK OutputBias", modal_hdr->ob_1);
+ PR_EEP("QPSK OutputBias", modal_hdr->ob_2);
+ PR_EEP("16QAM OutputBias", modal_hdr->ob_3);
+ PR_EEP("64QAM OutputBias", modal_hdr->ob_4);
+ PR_EEP("CCK Driver1_Bias", modal_hdr->db1_0);
+ PR_EEP("BPSK Driver1_Bias", modal_hdr->db1_1);
+ PR_EEP("QPSK Driver1_Bias", modal_hdr->db1_2);
+ PR_EEP("16QAM Driver1_Bias", modal_hdr->db1_3);
+ PR_EEP("64QAM Driver1_Bias", modal_hdr->db1_4);
+ PR_EEP("CCK Driver2_Bias", modal_hdr->db2_0);
+ PR_EEP("BPSK Driver2_Bias", modal_hdr->db2_1);
+ PR_EEP("QPSK Driver2_Bias", modal_hdr->db2_2);
+ PR_EEP("16QAM Driver2_Bias", modal_hdr->db2_3);
+ PR_EEP("64QAM Driver2_Bias", modal_hdr->db2_4);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+ PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+ PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+ PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+ PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
+ PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
+ PR_EEP("Ant. Diversity ctl1", modal_hdr->antdiv_ctl1);
+ PR_EEP("Ant. Diversity ctl2", modal_hdr->antdiv_ctl2);
+ PR_EEP("TX Diversity", modal_hdr->tx_diversity);
+
+ return len;
+}
+
+static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ath9k_dump_4k_modal_eeprom(buf, len, size,
+ &eep->modalHeader);
+ goto out;
+ }
+
+ PR_EEP("Major Version", pBase->version >> 12);
+ PR_EEP("Minor Version", pBase->version & 0xFFF);
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+ PR_EEP("RegDomain2", pBase->regDmn[1]);
+ PR_EEP("TX Mask", pBase->txMask);
+ PR_EEP("RX Mask", pBase->rxMask);
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+ PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+ PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+ PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+ PR_EEP("TX Gain type", pBase->txGainType);
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
+
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
+
#undef SIZE_EEPROM_4K
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
@@ -203,15 +315,13 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_NFTHRESH_2:
return pModal->noiseFloorThreshCh[0];
case EEP_MAC_LSW:
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ return get_unaligned_be16(pBase->macAddr);
case EEP_MAC_MID:
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ return get_unaligned_be16(pBase->macAddr + 2);
case EEP_MAC_MSW:
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -237,18 +347,16 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_ANT_DIV_CTL1:
return pModal->antdiv_ctl1;
case EEP_TXGAIN_TYPE:
- if (ver_minor >= AR5416_EEP_MINOR_VER_19)
- return pBase->txGainType;
- else
- return AR5416_EEP_TXGAIN_ORIGINAL;
+ return pBase->txGainType;
+ case EEP_ANTENNA_GAIN_2G:
+ return pModal->antennaGainCh[0];
default:
return 0;
}
}
static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+ struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -297,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
- (i != 0)) {
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- } else
- regChainOffset = i * 0x1000;
+ regChainOffset = i * 0x1000;
if (pEepData->baseEepHeader.txMask & (1 << i)) {
pRawDataset = pEepData->calPierData2G[i];
@@ -315,26 +418,21 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
- REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
- | SM(gainBoundaries[0],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
- | SM(gainBoundaries[1],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
- | SM(gainBoundaries[2],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
- | SM(gainBoundaries[3],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
- }
+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
- ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
- ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
- ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
REG_WRITE(ah, regOffset, reg32);
ath_dbg(common, ATH_DBG_EEPROM,
@@ -358,16 +456,13 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
}
-
- *pTxPowerIndexOffset = 0;
}
static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
+ u16 antenna_reduction,
u16 powerLimit)
{
#define CMP_TEST_GRP \
@@ -376,20 +471,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
int i;
- int16_t twiceLargestAntenna;
u16 twiceMinEdgePower;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
u16 numCtlModes;
const u16 *pCtlMode;
u16 ctlMode, freq;
struct chan_centers centers;
struct cal_ctl_data_4k *rep;
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, MAX_RATE_POWER };
struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0}
};
@@ -407,19 +498,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers);
- twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
- twiceLargestAntenna = (int16_t)min(AntennaReduction -
- twiceLargestAntenna, 0);
-
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
- scaledPower = max((u16)0, scaledPower);
-
+ scaledPower = powerLimit - antenna_reduction;
numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
pCtlMode = ctlModesFor11g;
@@ -575,14 +654,12 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i;
@@ -596,14 +673,12 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
ath9k_hw_set_4k_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
- ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+ ath9k_hw_set_4k_power_cal_table(ah, chan);
regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
@@ -614,19 +689,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
if (test)
return;
- /* Update regulatory */
- i = rate6mb;
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- regulatory->max_power_level = ratesArray[i];
-
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
- }
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
ENABLE_REGWRITE_BUFFER(ah);
@@ -696,28 +760,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
-static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct modal_eep_4k_header *pModal;
- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- u8 biaslevel;
-
- if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
- return;
-
- if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
- return;
-
- pModal = &eep->modalHeader;
-
- if (pModal->xpaBiasLvl != 0xff) {
- biaslevel = pModal->xpaBiasLvl;
- INI_RA(&ah->iniAddac, 7, 1) =
- (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
- }
-}
-
static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
struct modal_eep_4k_header *pModal,
struct ar5416_eeprom_4k *eep,
@@ -785,6 +827,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
u8 txRxAttenLocal;
u8 ob[5], db1[5], db2[5];
u8 ant_div_control1, ant_div_control2;
+ u8 bb_desired_scale;
u32 regVal;
pModal = &eep->modalHeader;
@@ -1004,30 +1047,29 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
AR_PHY_SETTLING_SWITCH,
pModal->swSettleHt40);
}
- if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
- u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
- EEP_4K_BB_DESIRED_SCALE_MASK);
- if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
- u32 pwrctrl, mask, clr;
-
- mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
- pwrctrl = mask * bb_desired_scale;
- clr = mask * 0x1f;
- REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
- REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
-
- mask = BIT(0)|BIT(5)|BIT(15);
- pwrctrl = mask * bb_desired_scale;
- clr = mask * 0x1f;
- REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
-
- mask = BIT(0)|BIT(5);
- pwrctrl = mask * bb_desired_scale;
- clr = mask * 0x1f;
- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
- }
+
+ bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+ EEP_4K_BB_DESIRED_SCALE_MASK);
+ if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+ u32 pwrctrl, mask, clr;
+
+ mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+ mask = BIT(0)|BIT(5)|BIT(15);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+ mask = BIT(0)|BIT(5);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
}
}
@@ -1065,10 +1107,10 @@ const struct eeprom_ops eep_4k_ops = {
.check_eeprom = ath9k_hw_4k_check_eeprom,
.get_eeprom = ath9k_hw_4k_get_eeprom,
.fill_eeprom = ath9k_hw_4k_fill_eeprom,
+ .dump_eeprom = ath9k_hw_4k_dump_eeprom,
.get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
.set_board_values = ath9k_hw_4k_set_board_values,
- .set_addac = ath9k_hw_4k_set_addac,
.set_txpower = ath9k_hw_4k_set_txpower,
.get_spur_channel = ath9k_hw_4k_get_spur_channel
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 343fc9f..4f5c50a 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9002_phy.h"
@@ -75,6 +76,111 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_ar9287_fill_eeprom(ah);
}
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
+ struct modal_eep_ar9287_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+ PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
+ PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+ PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+ PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+ PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
+ PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+ PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+ PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+ PR_EEP("xpdGain", modal_hdr->xpdGain);
+ PR_EEP("External PD", modal_hdr->xpd);
+ PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+ PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
+ PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+ PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
+ PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+ PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+ PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
+ PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+ PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
+ PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+ PR_EEP("AR92x7 Version", modal_hdr->version);
+ PR_EEP("DriverBias1", modal_hdr->db1);
+ PR_EEP("DriverBias2", modal_hdr->db1);
+ PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
+ PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
+ PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
+ PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
+
+ return len;
+}
+
+static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ar9287_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader);
+ goto out;
+ }
+
+ PR_EEP("Major Version", pBase->version >> 12);
+ PR_EEP("Minor Version", pBase->version & 0xFFF);
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+ PR_EEP("RegDomain2", pBase->regDmn[1]);
+ PR_EEP("TX Mask", pBase->txMask);
+ PR_EEP("RX Mask", pBase->rxMask);
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+ PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+ PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+ PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+ PR_EEP("Power Table Offset", pBase->pwrTableOffset);
+ PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
+
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
+
static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
{
u32 sum = 0, el, integer;
@@ -195,15 +301,13 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
case EEP_NFTHRESH_2:
return pModal->noiseFloorThreshCh[0];
case EEP_MAC_LSW:
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ return get_unaligned_be16(pBase->macAddr);
case EEP_MAC_MID:
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ return get_unaligned_be16(pBase->macAddr + 2);
case EEP_MAC_MSW:
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -230,6 +334,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
return pBase->tempSensSlopePalOn;
else
return 0;
+ case EEP_ANTENNA_GAIN_2G:
+ return max_t(u8, pModal->antennaGainCh[0],
+ pModal->antennaGainCh[1]);
default:
return 0;
}
@@ -306,8 +413,7 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
}
static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+ struct ath9k_channel *chan)
{
struct cal_data_per_freq_ar9287 *pRawDataset;
struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
@@ -434,10 +540,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
(672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0)
- | ((pdadcValues[4*j + 1] & 0xFF) << 8)
- | ((pdadcValues[4*j + 2] & 0xFF) << 16)
- | ((pdadcValues[4*j + 3] & 0xFF) << 24);
+ reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
REG_WRITE(ah, regOffset, reg32);
regOffset += 4;
@@ -446,16 +549,13 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
}
-
- *pTxPowerIndexOffset = 0;
}
static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
+ u16 antenna_reduction,
u16 powerLimit)
{
#define CMP_CTL \
@@ -469,12 +569,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, MAX_RATE_POWER };
int i;
- int16_t twiceLargestAntenna;
struct cal_ctl_data_ar9287 *rep;
struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
targetPowerCck = {0, {0, 0, 0, 0} };
@@ -482,7 +578,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
targetPowerCckExt = {0, {0, 0, 0, 0} };
struct cal_target_power_ht targetPowerHt20,
targetPowerHt40 = {0, {0, 0, 0, 0} };
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11g[] = {
CTL_11B, CTL_11G, CTL_2GHT20,
CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
@@ -497,24 +593,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
tx_chainmask = ah->txchainmask;
ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- /* Compute TxPower reduction due to Antenna Gain */
- twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
- pEepData->modalHeader.antennaGainCh[1]);
- twiceLargestAntenna = (int16_t)min((AntennaReduction) -
- twiceLargestAntenna, 0);
-
- /*
- * scaledPower is the minimum of the user input power level
- * and the regulatory allowed power level.
- */
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = powerLimit - antenna_reduction;
/*
* Reduce scaled Power by number of chains active
@@ -715,14 +794,12 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i;
@@ -735,14 +812,12 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
- ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
+ ath9k_hw_set_ar9287_power_cal_table(ah, chan);
regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
@@ -753,17 +828,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
if (test)
return;
- if (IS_CHAN_2GHZ(chan))
- i = rate1l;
- else
- i = rate6mb;
-
- regulatory->max_power_level = ratesArray[i];
-
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
- }
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
ENABLE_REGWRITE_BUFFER(ah);
@@ -853,11 +919,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
-static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
-}
-
static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -1005,10 +1066,10 @@ const struct eeprom_ops eep_ar9287_ops = {
.check_eeprom = ath9k_hw_ar9287_check_eeprom,
.get_eeprom = ath9k_hw_ar9287_get_eeprom,
.fill_eeprom = ath9k_hw_ar9287_fill_eeprom,
+ .dump_eeprom = ath9k_hw_ar9287_dump_eeprom,
.get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
.set_board_values = ath9k_hw_ar9287_set_board_values,
- .set_addac = ath9k_hw_ar9287_set_addac,
.set_txpower = ath9k_hw_ar9287_set_txpower,
.get_spur_channel = ath9k_hw_ar9287_get_spur_channel
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 17f0a68..81e6296 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9002_phy.h"
@@ -132,6 +133,136 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
#undef SIZE_EEPROM_DEF
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
+ struct modal_eep_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+ PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
+ PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]);
+ PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+ PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+ PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
+ PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+ PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
+ PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]);
+ PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+ PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
+ PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
+ PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
+ PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]);
+ PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]);
+ PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+ PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+ PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
+ PR_EEP("xpdGain", modal_hdr->xpdGain);
+ PR_EEP("External PD", modal_hdr->xpd);
+ PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+ PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
+ PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]);
+ PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+ PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
+ PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]);
+ PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+ PR_EEP("Chain0 OutputBias", modal_hdr->ob);
+ PR_EEP("Chain0 DriverBias", modal_hdr->db);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain);
+ PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+ PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+ PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
+ PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]);
+ PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+ PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
+ PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]);
+ PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+ PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
+ PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]);
+ PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]);
+ PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
+ PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]);
+ PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]);
+ PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1);
+ PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);
+ PR_EEP("LNA Control", modal_hdr->lna_ctl);
+ PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]);
+ PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]);
+ PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]);
+
+ return len;
+}
+
+static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ath9k_def_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader[0]);
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "5GHz modal Header");
+ len += ath9k_def_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader[1]);
+ goto out;
+ }
+
+ PR_EEP("Major Version", pBase->version >> 12);
+ PR_EEP("Minor Version", pBase->version & 0xFFF);
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+ PR_EEP("RegDomain2", pBase->regDmn[1]);
+ PR_EEP("TX Mask", pBase->txMask);
+ PR_EEP("RX Mask", pBase->rxMask);
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+ PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+ PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+ PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+ PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
+
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
+
static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
{
struct ar5416_eeprom_def *eep =
@@ -269,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal = eep->modalHeader;
struct base_eep_header *pBase = &eep->baseEepHeader;
+ int band = 0;
switch (param) {
case EEP_NFTHRESH_5:
@@ -276,15 +408,13 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
case EEP_NFTHRESH_2:
return pModal[1].noiseFloorThreshCh[0];
case EEP_MAC_LSW:
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ return get_unaligned_be16(pBase->macAddr);
case EEP_MAC_MID:
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ return get_unaligned_be16(pBase->macAddr + 2);
case EEP_MAC_MSW:
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -336,6 +466,14 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return pBase->pwr_table_offset;
else
return AR5416_PWR_TABLE_OFFSET_DB;
+ case EEP_ANTENNA_GAIN_2G:
+ band = 1;
+ /* fall through */
+ case EEP_ANTENNA_GAIN_5G:
+ return max_t(u8, max_t(u8,
+ pModal[band].antennaGainCh[0],
+ pModal[band].antennaGainCh[1]),
+ pModal[band].antennaGainCh[2]);
default:
return 0;
}
@@ -416,8 +554,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
break;
}
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
else
regChainOffset = i * 0x1000;
@@ -434,9 +571,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
SM(pModal->iqCalQCh[i],
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
- ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
- regChainOffset, i);
+ ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+ regChainOffset, i);
}
if (AR_SREV_9280_20_OR_LATER(ah)) {
@@ -692,8 +828,7 @@ static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
}
static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+ struct ath9k_channel *chan)
{
#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
#define SM_PDGAIN_B(x, y) \
@@ -763,8 +898,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
xpdGainValues[2]);
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
(i != 0)) {
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
} else
@@ -805,36 +939,30 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
- if (OLC_FOR_AR9280_20_LATER) {
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(0x6,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
- SM_PD_GAIN(1) | SM_PD_GAIN(2) |
- SM_PD_GAIN(3) | SM_PD_GAIN(4));
- } else {
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
- SM_PDGAIN_B(0, 1) |
- SM_PDGAIN_B(1, 2) |
- SM_PDGAIN_B(2, 3) |
- SM_PDGAIN_B(3, 4));
- }
+ if (OLC_FOR_AR9280_20_LATER) {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(0x6,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+ SM_PD_GAIN(3) | SM_PD_GAIN(4));
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+ SM_PDGAIN_B(0, 1) |
+ SM_PDGAIN_B(1, 2) |
+ SM_PDGAIN_B(2, 3) |
+ SM_PDGAIN_B(3, 4));
}
-
ath9k_adjust_pdadc_values(ah, pwr_table_offset,
diff, pdadcValues);
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
- ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
- ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
- ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
REG_WRITE(ah, regOffset, reg32);
ath_dbg(common, ATH_DBG_EEPROM,
@@ -857,7 +985,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
}
}
- *pTxPowerIndexOffset = 0;
#undef SM_PD_GAIN
#undef SM_PDGAIN_B
}
@@ -866,21 +993,15 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
+ u16 antenna_reduction,
u16 powerLimit)
{
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, MAX_RATE_POWER };
-
int i;
- int16_t twiceLargestAntenna;
struct cal_ctl_data *rep;
struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0}
@@ -892,7 +1013,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
0, {0, 0, 0, 0}
};
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
};
@@ -911,27 +1032,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers);
- twiceLargestAntenna = max(
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
-
- twiceLargestAntenna = max((u8)twiceLargestAntenna,
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
-
- twiceLargestAntenna = (int16_t)min(AntennaReduction -
- twiceLargestAntenna, 0);
-
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = powerLimit - antenna_reduction;
switch (ar5416_get_ntxchains(tx_chainmask)) {
case 1:
@@ -1136,7 +1237,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
@@ -1145,7 +1245,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
struct modal_eep_header *pModal =
&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i, cck_ofdm_delta = 0;
@@ -1159,31 +1258,18 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ath9k_hw_set_def_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
- ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+ ath9k_hw_set_def_power_cal_table(ah, chan);
regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
if (ratesArray[i] > regulatory->max_power_level)
regulatory->max_power_level = ratesArray[i];
}
- if (!test) {
- i = rate6mb;
-
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- regulatory->max_power_level = ratesArray[i];
- }
-
switch(ar5416_get_ntxchains(ah->txchainmask)) {
case 1:
break;
@@ -1338,6 +1424,7 @@ const struct eeprom_ops eep_def_ops = {
.check_eeprom = ath9k_hw_def_check_eeprom,
.get_eeprom = ath9k_hw_def_get_eeprom,
.fill_eeprom = ath9k_hw_def_fill_eeprom,
+ .dump_eeprom = ath9k_hw_def_dump_eeprom,
.get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
.set_board_values = ath9k_hw_def_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index bc713fc..655576c 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -48,6 +48,8 @@ void ath_init_leds(struct ath_softc *sc)
sc->sc_ah->led_pin = ATH_LED_PIN_9485;
else if (AR_SREV_9300(sc->sc_ah))
sc->sc_ah->led_pin = ATH_LED_PIN_9300;
+ else if (AR_SREV_9462(sc->sc_ah))
+ sc->sc_ah->led_pin = ATH_LED_PIN_9462;
else
sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
}
@@ -82,9 +84,14 @@ void ath_init_leds(struct ath_softc *sc)
static bool ath_is_rfkill_set(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
+ bool is_blocked;
- return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
+ ath9k_ps_wakeup(sc);
+ is_blocked = ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
ah->rfkill_polarity;
+ ath9k_ps_restore(sc);
+
+ return is_blocked;
}
void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
@@ -148,7 +155,8 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
ath9k_hw_disable_interrupts(ah);
ah->imask |= ATH9K_INT_GENTIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
}
@@ -162,7 +170,8 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
if (timer_table->timer_mask.val == 0) {
ath9k_hw_disable_interrupts(ah);
ah->imask &= ~ATH9K_INT_GENTIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 5513c0a..77c8ded 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "htc.h"
/* identify firmware images */
@@ -50,6 +51,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
.driver_info = AR9280_USB }, /* Netgear WNDA3200 */
{ USB_DEVICE(0x083A, 0xA704),
.driver_info = AR9280_USB }, /* SMC Networks */
+ { USB_DEVICE(0x0411, 0x017f),
+ .driver_info = AR9280_USB }, /* Sony UWA-BR100 */
{ USB_DEVICE(0x0cf3, 0x20ff),
.driver_info = STORAGE_DEVICE },
@@ -128,12 +131,14 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
static void hif_usb_mgmt_cb(struct urb *urb)
{
struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
- struct hif_device_usb *hif_dev = cmd->hif_dev;
+ struct hif_device_usb *hif_dev;
bool txok = true;
if (!cmd || !cmd->skb || !cmd->hif_dev)
return;
+ hif_dev = cmd->hif_dev;
+
switch (urb->status) {
case 0:
break;
@@ -556,8 +561,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
ptr = (u8 *) skb->data;
- pkt_len = ptr[index] + (ptr[index+1] << 8);
- pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
+ pkt_len = get_unaligned_le16(ptr + index);
+ pkt_tag = get_unaligned_le16(ptr + index + 2);
if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
RX_STAT_INC(skb_dropped);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 5bc0220..09be407 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -22,6 +22,7 @@
#include <linux/firmware.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <net/mac80211.h>
@@ -521,8 +522,6 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv,
u8 enable_coex);
-void ath9k_htc_station_work(struct work_struct *work);
-void ath9k_htc_aggr_work(struct work_struct *work);
void ath9k_htc_ani_work(struct work_struct *work);
void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
@@ -542,7 +541,6 @@ int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
-void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv);
void ath9k_tx_failed_tasklet(unsigned long data);
void ath9k_htc_tx_cleanup_timer(unsigned long data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index aa6a731..57fe22b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -79,7 +79,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
memset(&bs, 0, sizeof(bs));
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
/*
@@ -194,7 +194,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
u8 cmd_rsp;
u64 tsf;
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
intval /= ATH9K_HTC_MAX_BCN_VIF;
nexttbtt = intval;
@@ -250,7 +250,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
u8 cmd_rsp;
u64 tsf;
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
nexttbtt = intval;
/*
@@ -427,7 +427,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
u16 intval;
int slot;
- intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = priv->cur_beacon_conf.beacon_interval;
tsf = be64_to_cpu(swba->tsf);
tsftu = TSF_TO_TU(tsf >> 32, tsf);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index aa48b3a..d3ff33c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -623,11 +623,8 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
pBase9287->openLoopPwrCntl);
}
- len += snprintf(buf + len, size - len,
- "%20s : %02X:%02X:%02X:%02X:%02X:%02X\n",
- "MacAddress",
- pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2],
- pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]);
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
if (len > size)
len = size;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index db2352e..e3a02eb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -228,8 +228,14 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
{
- return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
- priv->ah->rfkill_polarity;
+ bool is_blocked;
+
+ ath9k_htc_ps_wakeup(priv);
+ is_blocked = ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
+ priv->ah->rfkill_polarity;
+ ath9k_htc_ps_restore(priv);
+
+ return is_blocked;
}
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 403d33f..c6c3e1c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -28,6 +28,10 @@ int htc_modparam_nohwcrypt;
module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+static int ath9k_ps_enable;
+module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
+MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
+
#define CHAN2G(_freq, _idx) { \
.center_freq = (_freq), \
.hw_value = (_idx), \
@@ -509,8 +513,8 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv,
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
/* ath9k_htc supports only 1 or 2 stream devices */
- tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
- rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
+ tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
+ rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
@@ -572,25 +576,6 @@ err:
return -EINVAL;
}
-static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
-{
- struct ath_common *common = ath9k_hw_common(priv->ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = AR_KEYTABLE_SIZE;
-
- if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath_hw_keyreset(common, (u16) i);
-}
-
static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
{
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
@@ -620,9 +605,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
- common->tx_chainmask = priv->ah->caps.tx_chainmask;
- common->rx_chainmask = priv->ah->caps.rx_chainmask;
-
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
priv->ah->opmode = NL80211_IFTYPE_STATION;
@@ -666,7 +648,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
return -ENOMEM;
ah->hw_version.devid = devid;
- ah->hw_version.subsysid = 0; /* FIXME */
ah->hw_version.usbdev = drv_info;
ah->ah_flags |= AH_USE_EEPROM;
ah->reg_ops.read = ath9k_regread;
@@ -721,7 +702,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
priv->cur_beacon_conf.bslot[i] = NULL;
- ath9k_init_crypto(priv);
+ ath9k_cmn_init_crypto(ah);
ath9k_init_channels_rates(priv);
ath9k_init_misc(priv);
@@ -752,10 +733,13 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_HAS_RATE_CONTROL |
IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ if (ath9k_ps_enable)
+ hw->flags |= IEEE80211_HW_SUPPORTS_PS;
+
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7b77968..b6cd36c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -139,21 +139,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ath9k_vif_iter_data *iter_data = data;
int i;
- for (i = 0; i < ETH_ALEN; i++)
- iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+ if (iter_data->hw_macaddr != NULL) {
+ for (i = 0; i < ETH_ALEN; i++)
+ iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+ } else {
+ iter_data->hw_macaddr = mac;
+ }
}
-static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_vif_iter_data iter_data;
/*
- * Use the hardware MAC address as reference, the hardware uses it
- * together with the BSSID mask when matching addresses.
+ * Pick the MAC address of the first interface as the new hardware
+ * MAC address. The hardware will use it together with the BSSID mask
+ * when matching addresses.
*/
- iter_data.hw_macaddr = common->macaddr;
+ iter_data.hw_macaddr = NULL;
memset(&iter_data.mask, 0xff, ETH_ALEN);
if (vif)
@@ -164,6 +169,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
&iter_data);
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+
+ if (iter_data.hw_macaddr)
+ memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+
ath_hw_setbssidmask(common);
}
@@ -826,8 +835,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
if (longcal || shortcal)
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
- common->rx_chainmask,
- longcal);
+ ah->rxchainmask, longcal);
ath9k_htc_ps_restore(priv);
}
@@ -1101,7 +1109,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
goto out;
}
- ath9k_htc_set_bssid_mask(priv, vif);
+ ath9k_htc_set_mac_bssid_mask(priv, vif);
priv->vif_slot |= (1 << avp->index);
priv->nvifs++;
@@ -1164,7 +1172,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
ath9k_htc_set_opmode(priv);
- ath9k_htc_set_bssid_mask(priv, vif);
+ ath9k_htc_set_mac_bssid_mask(priv, vif);
/*
* Stop ANI only if there are no associated station interfaces.
@@ -1294,11 +1302,17 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
u32 rfilt;
mutex_lock(&priv->mutex);
- ath9k_htc_ps_wakeup(priv);
-
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
+ if (priv->op_flags & OP_INVALID) {
+ ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY,
+ "Unable to configure filter on invalid state\n");
+ mutex_unlock(&priv->mutex);
+ return;
+ }
+ ath9k_htc_ps_wakeup(priv);
+
priv->rxfilter = *total_flags;
rfilt = ath9k_htc_calcrxfilter(priv);
ath9k_hw_setrxfilter(priv->ah, rfilt);
@@ -1347,7 +1361,8 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
return ret;
}
-static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1558,7 +1573,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
}
-static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
+static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath9k_htc_priv *priv = hw->priv;
u64 tsf;
@@ -1572,7 +1588,8 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void ath9k_htc_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u64 tsf)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1583,7 +1600,8 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
mutex_unlock(&priv->mutex);
}
-static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
+static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1731,6 +1749,22 @@ out:
return ret;
}
+
+static int ath9k_htc_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+ struct ath_hw *ah = priv->ah;
+ struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
+
+ stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
+ stats->dot11RTSFailureCount = mib_stats->rts_bad;
+ stats->dot11FCSErrorCount = mib_stats->fcs_bad;
+ stats->dot11RTSSuccessCount = mib_stats->rts_good;
+
+ return 0;
+}
+
struct ieee80211_ops ath9k_htc_ops = {
.tx = ath9k_htc_tx,
.start = ath9k_htc_start,
@@ -1754,4 +1788,5 @@ struct ieee80211_ops ath9k_htc_ops = {
.rfkill_poll = ath9k_htc_rfkill_poll_state,
.set_coverage_class = ath9k_htc_set_coverage_class,
.set_bitrate_mask = ath9k_htc_set_bitrate_mask,
+ .get_stats = ath9k_htc_get_stats,
};
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 3f2c88f..9a57149 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1079,15 +1079,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
last_rssi = priv->rx.last_rssi;
- if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
- rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
- ATH_RSSI_EP_MULTIPLIER);
+ if (ieee80211_is_beacon(hdr->frame_control) &&
+ !is_zero_ether_addr(common->curbssid) &&
+ compare_ether_addr(hdr->addr3, common->curbssid) == 0) {
+ s8 rssi = rxbuf->rxstatus.rs_rssi;
- if (rxbuf->rxstatus.rs_rssi < 0)
- rxbuf->rxstatus.rs_rssi = 0;
+ if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+ rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
- if (ieee80211_is_beacon(fc))
- priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
+ if (rssi < 0)
+ rssi = 0;
+
+ priv->ah->stats.avgbrssi = rssi;
+ }
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
rx_status->band = hw->conf.channel->band;
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 2f3e072..e74c233 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -22,10 +22,12 @@
/* Hardware core and driver accessible callbacks */
static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
- int restore,
- int power_off)
+ bool power_off)
{
- ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off);
+ if (ah->aspm_enabled != true)
+ return;
+
+ ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off);
}
static inline void ath9k_hw_rxena(struct ath_hw *ah)
@@ -39,11 +41,6 @@ static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
ath9k_hw_ops(ah)->set_desc_link(ds, link);
}
-static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
- u32 **link)
-{
- ath9k_hw_ops(ah)->get_desc_link(ds, link);
-}
static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
@@ -57,13 +54,10 @@ static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
return ath9k_hw_ops(ah)->get_isr(ah, masked);
}
-static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu)
+static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
+ struct ath_tx_info *i)
{
- ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
- ds0, buf_addr, qcu);
+ return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
}
static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
@@ -72,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
}
-static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType,
- u32 flags)
-{
- ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
- keyType, flags);
-}
-
-static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
-{
- ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
- rtsctsRate, rtsctsDuration, series,
- nseries, flags);
-}
-
-static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
- u32 aggrLen)
-{
- ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
-}
-
-static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
- u32 numDelims)
-{
- ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
-}
-
-static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
- ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
-}
-
-static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
- ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
-}
-
-static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
- ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
-}
-
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf)
{
@@ -236,11 +181,6 @@ static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
}
-static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value)
-{
- return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
-}
-
static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
@@ -265,4 +205,11 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
}
+static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 *ini_reloaded)
+{
+ return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
+ ini_reloaded);
+}
#endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 9130a5a..c623527 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/unaligned.h>
#include "hw.h"
@@ -87,7 +88,10 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
unsigned int clockrate;
- if (!ah->curchan) /* should really check for CCK instead */
+ /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
+ clockrate = 117;
+ else if (!ah->curchan) /* should really check for CCK instead */
clockrate = ATH9K_CLOCK_RATE_CCK;
else if (conf->channel->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
@@ -99,6 +103,13 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
if (conf_is_ht40(conf))
clockrate *= 2;
+ if (ah->curchan) {
+ if (IS_CHAN_HALF_RATE(ah->curchan))
+ clockrate /= 2;
+ if (IS_CHAN_QUARTER_RATE(ah->curchan))
+ clockrate /= 4;
+ }
+
common->clockrate = clockrate;
}
@@ -251,6 +262,15 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
case AR5416_AR9100_DEVID:
ah->hw_version.macVersion = AR_SREV_VERSION_9100;
break;
+ case AR9300_DEVID_AR9330:
+ ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+ if (ah->get_mac_revision) {
+ ah->hw_version.macRev = ah->get_mac_revision();
+ } else {
+ val = REG_READ(ah, AR_SREV);
+ ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+ }
+ return;
case AR9300_DEVID_AR9340:
ah->hw_version.macVersion = AR_SREV_VERSION_9340;
val = REG_READ(ah, AR_SREV);
@@ -265,7 +285,12 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
ah->hw_version.macVersion =
(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
- ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+
+ if (AR_SREV_9462(ah))
+ ah->is_pciexpress = true;
+ else
+ ah->is_pciexpress = (val &
+ AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
} else {
if (!AR_SREV_9100(ah))
ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
@@ -409,7 +434,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
regulatory->country_code = CTRY_DEFAULT;
regulatory->power_limit = MAX_RATE_POWER;
- regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
ah->hw_version.magic = AR5416_MAGIC;
ah->hw_version.subvendorid = 0;
@@ -421,7 +445,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
if (AR_SREV_9100(ah))
ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
ah->enable_32kHz_clock = DONT_USE_32KHZ;
- ah->slottime = 20;
+ ah->slottime = ATH9K_SLOT_TIME_9;
ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED;
}
@@ -518,6 +542,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EIO;
}
+ if (AR_SREV_9462(ah))
+ ah->WARegVal &= ~AR_WA_D3_L1_DISABLE;
+
ath9k_hw_init_defaults(ah);
ath9k_hw_init_config(ah);
@@ -558,8 +585,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9287:
case AR_SREV_VERSION_9271:
case AR_SREV_VERSION_9300:
+ case AR_SREV_VERSION_9330:
case AR_SREV_VERSION_9485:
case AR_SREV_VERSION_9340:
+ case AR_SREV_VERSION_9462:
break;
default:
ath_err(common,
@@ -568,7 +597,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EOPNOTSUPP;
}
- if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9330(ah))
ah->is_pciexpress = false;
ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -582,10 +612,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_mode_regs(ah);
-
- if (ah->is_pciexpress)
- ath9k_hw_aspm_init(ah);
- else
+ if (!ah->is_pciexpress)
ath9k_hw_disablepcie(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -600,6 +627,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (r)
return r;
+ if (ah->is_pciexpress)
+ ath9k_hw_aspm_init(ah);
+
r = ath9k_hw_init_macaddr(ah);
if (r) {
ath_err(common, "Failed to initialize MAC address\n");
@@ -611,7 +641,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
else
ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
- ah->bb_watchdog_timeout_ms = 25;
+ if (AR_SREV_9330(ah))
+ ah->bb_watchdog_timeout_ms = 85;
+ else
+ ah->bb_watchdog_timeout_ms = 25;
common->state = ATH_HW_INITIALIZED;
@@ -637,7 +670,11 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR2427_DEVID_PCIE:
case AR9300_DEVID_PCIE:
case AR9300_DEVID_AR9485_PCIE:
+ case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340:
+ case AR9300_DEVID_AR9580:
+ case AR9300_DEVID_AR9462:
+ case AR9485_DEVID_AR1111:
break;
default:
if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -741,6 +778,39 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
udelay(1000);
+ } else if (AR_SREV_9330(ah)) {
+ u32 ddr_dpll2, pll_control2, kd;
+
+ if (ah->is_clk_25mhz) {
+ ddr_dpll2 = 0x18e82f01;
+ pll_control2 = 0xe04a3d;
+ kd = 0x1d;
+ } else {
+ ddr_dpll2 = 0x19e82f01;
+ pll_control2 = 0x886666;
+ kd = 0x3d;
+ }
+
+ /* program DDR PLL ki and kd value */
+ REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
+
+ /* program DDR PLL phase_shift */
+ REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+ AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+ udelay(1000);
+
+ /* program refdiv, nint, frac to RTC register */
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
+
+ /* program BB PLL kd and ki value */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
+
+ /* program BB PLL phase_shift */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+ AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
} else if (AR_SREV_9340(ah)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
@@ -782,7 +852,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
udelay(1000);
/* Switch the core clock for ar9271 to 117Mhz */
@@ -866,6 +936,13 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
}
}
+static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
+{
+ u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
+ val = min(val, (u32) 0xFFFF);
+ REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
+}
+
static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
{
u32 val = ath9k_hw_mac_to_clks(ah, us);
@@ -903,41 +980,98 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
void ath9k_hw_init_global_settings(struct ath_hw *ah)
{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
- int acktimeout;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &common->hw->conf;
+ const struct ath9k_channel *chan = ah->curchan;
+ int acktimeout, ctstimeout;
int slottime;
int sifstime;
+ int rx_lat = 0, tx_lat = 0, eifs = 0;
+ u32 reg;
ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
ah->misc_mode);
+ if (!chan)
+ return;
+
if (ah->misc_mode != 0)
REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
- if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
- sifstime = 16;
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ rx_lat = 41;
else
- sifstime = 10;
+ rx_lat = 37;
+ tx_lat = 54;
+
+ if (IS_CHAN_HALF_RATE(chan)) {
+ eifs = 175;
+ rx_lat *= 2;
+ tx_lat *= 2;
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ tx_lat += 11;
+
+ slottime = 13;
+ sifstime = 32;
+ } else if (IS_CHAN_QUARTER_RATE(chan)) {
+ eifs = 340;
+ rx_lat = (rx_lat * 4) - 1;
+ tx_lat *= 4;
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ tx_lat += 22;
+
+ slottime = 21;
+ sifstime = 64;
+ } else {
+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+ eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
+ reg = AR_USEC_ASYNC_FIFO;
+ } else {
+ eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
+ common->clockrate;
+ reg = REG_READ(ah, AR_USEC);
+ }
+ rx_lat = MS(reg, AR_USEC_RX_LAT);
+ tx_lat = MS(reg, AR_USEC_TX_LAT);
+
+ slottime = ah->slottime;
+ if (IS_CHAN_5GHZ(chan))
+ sifstime = 16;
+ else
+ sifstime = 10;
+ }
/* As defined by IEEE 802.11-2007 17.3.8.6 */
- slottime = ah->slottime + 3 * ah->coverage_class;
- acktimeout = slottime + sifstime;
+ acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+ ctstimeout = acktimeout;
/*
* Workaround for early ACK timeouts, add an offset to match the
- * initval's 64us ack timeout value.
+ * initval's 64us ack timeout value. Use 48us for the CTS timeout.
* This was initially only meant to work around an issue with delayed
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
+ if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {
acktimeout += 64 - sifstime - ah->slottime;
+ ctstimeout += 48 - sifstime - ah->slottime;
+ }
+
- ath9k_hw_setslottime(ah, ah->slottime);
+ ath9k_hw_set_sifs_time(ah, sifstime);
+ ath9k_hw_setslottime(ah, slottime);
ath9k_hw_set_ack_timeout(ah, acktimeout);
- ath9k_hw_set_cts_timeout(ah, acktimeout);
+ ath9k_hw_set_cts_timeout(ah, ctstimeout);
if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
+
+ REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
+ REG_RMW(ah, AR_USEC,
+ (common->clockrate - 1) |
+ SM(rx_lat, AR_USEC_RX_LAT) |
+ SM(tx_lat, AR_USEC_TX_LAT),
+ AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
+
}
EXPORT_SYMBOL(ath9k_hw_init_global_settings);
@@ -1133,6 +1267,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
rst_flags |= AR_RTC_RC_MAC_COLD;
}
+ if (AR_SREV_9330(ah)) {
+ int npend = 0;
+ int i;
+
+ /* AR9330 WAR:
+ * call external reset function to reset WMAC if:
+ * - doing a cold reset
+ * - we have pending frames in the TX queues
+ */
+
+ for (i = 0; i < AR_NUM_QCU; i++) {
+ npend = ath9k_hw_numtxpending(ah, i);
+ if (npend)
+ break;
+ }
+
+ if (ah->external_reset &&
+ (npend || type == ATH9K_RESET_COLD)) {
+ int reset_err = 0;
+
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+ "reset MAC via external reset\n");
+
+ reset_err = ah->external_reset();
+ if (reset_err) {
+ ath_err(ath9k_hw_common(ah),
+ "External reset failed, err=%d\n",
+ reset_err);
+ return false;
+ }
+
+ REG_WRITE(ah, AR_RTC_RESET, 1);
+ }
+ }
+
REG_WRITE(ah, AR_RTC_RC, rst_flags);
REGWRITE_BUFFER_FLUSH(ah);
@@ -1197,6 +1366,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
{
+
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
@@ -1238,11 +1408,17 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *channel = chan->chan;
u32 qnum;
int r;
+ bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+ bool band_switch, mode_diff;
+ u8 ini_reloaded;
+
+ band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) !=
+ (ah->curchan->channelFlags & (CHANNEL_2GHZ |
+ CHANNEL_5GHZ));
+ mode_diff = (chan->chanmode != ah->curchan->chanmode);
for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
if (ath9k_hw_numtxpending(ah, qnum)) {
@@ -1257,6 +1433,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false;
}
+ if (edma && (band_switch || mode_diff)) {
+ ath9k_hw_mark_phy_inactive(ah);
+ udelay(5);
+
+ ath9k_hw_init_pll(ah, NULL);
+
+ if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
+ ath_err(common, "Failed to do fast channel change\n");
+ return false;
+ }
+ }
+
ath9k_hw_set_channel_regs(ah, chan);
r = ath9k_hw_rf_set_freq(ah, chan);
@@ -1265,14 +1453,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false;
}
ath9k_hw_set_clockrate(ah);
-
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
-
+ ath9k_hw_apply_txpower(ah, chan);
ath9k_hw_rfbus_done(ah);
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -1280,6 +1461,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
ath9k_hw_spur_mitigate_freq(ah, chan);
+ if (edma && (band_switch || mode_diff)) {
+ ah->ah_flags |= AH_FASTCC;
+ if (band_switch || ini_reloaded)
+ ah->eep_ops->set_board_values(ah, chan);
+
+ ath9k_hw_init_bb(ah, chan);
+
+ if (band_switch || ini_reloaded)
+ ath9k_hw_init_cal(ah, chan);
+ ah->ah_flags &= ~AH_FASTCC;
+ }
+
return true;
}
@@ -1335,9 +1528,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
u32 macStaId1;
u64 tsf = 0;
int i, r;
-
- ah->txchainmask = common->tx_chainmask;
- ah->rxchainmask = common->rx_chainmask;
+ bool allow_fbs = false;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
@@ -1349,20 +1540,30 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (caldata &&
(chan->channel != caldata->channel ||
(chan->channelFlags & ~CHANNEL_CW_INT) !=
- (caldata->channelFlags & ~CHANNEL_CW_INT))) {
+ (caldata->channelFlags & ~CHANNEL_CW_INT) ||
+ chan->chanmode != caldata->chanmode)) {
/* Operating channel changed, reset channel calibration data */
memset(caldata, 0, sizeof(*caldata));
ath9k_init_nfcal_hist_buffer(ah, chan);
}
+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
+
+ if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
+ bChannelChange = false;
+
+ if (caldata &&
+ caldata->done_txiqcal_once &&
+ caldata->done_txclcal_once &&
+ caldata->rtt_hist.num_readings)
+ allow_fbs = true;
if (bChannelChange &&
(ah->chip_fullsleep != true) &&
(ah->curchan != NULL) &&
(chan->channel != ah->curchan->channel) &&
- ((chan->channelFlags & CHANNEL_ALL) ==
- (ah->curchan->channelFlags & CHANNEL_ALL)) &&
- (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
-
+ (allow_fbs ||
+ ((chan->channelFlags & CHANNEL_ALL) ==
+ (ah->curchan->channelFlags & CHANNEL_ALL)))) {
if (ath9k_hw_channel_change(ah, chan)) {
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
@@ -1506,9 +1707,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_global_settings(ah);
- if (!AR_SREV_9300_20_OR_LATER(ah)) {
- ar9002_hw_update_async_fifo(ah);
- ar9002_hw_enable_wep_aggregation(ah);
+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+ REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
+ AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+ REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
+ AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
}
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
@@ -1529,9 +1734,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_bb(ah, chan);
+ if (caldata) {
+ caldata->done_txiqcal_once = false;
+ caldata->done_txclcal_once = false;
+ caldata->rtt_hist.num_readings = 0;
+ }
if (!ath9k_hw_init_cal(ah, chan))
return -EIO;
+ ath9k_hw_loadnf(ah, chan);
+ ath9k_hw_start_nfcal(ah, true);
+
ENABLE_REGWRITE_BUFFER(ah);
ath9k_hw_restore_chainmask(ah);
@@ -1564,7 +1777,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
}
#ifdef __BIG_ENDIAN
- else if (AR_SREV_9340(ah))
+ else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
else
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -1598,25 +1811,41 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
{
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (setChip) {
+ if (AR_SREV_9462(ah)) {
+ REG_WRITE(ah, AR_TIMER_MODE,
+ REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00);
+ REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah,
+ AR_NDP2_TIMER_MODE) & 0xFFFFFF00);
+ REG_WRITE(ah, AR_SLP32_INC,
+ REG_READ(ah, AR_SLP32_INC) & 0xFFF00000);
+ /* xxx Required for WLAN only case ? */
+ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+ udelay(100);
+ }
+
/*
* Clear the RTC force wake bit to allow the
* mac to go to sleep.
*/
- REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+
+ if (AR_SREV_9462(ah))
+ udelay(100);
+
if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
/* Shutdown chip. Active low */
- if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
- REG_CLR_BIT(ah, (AR_RTC_RESET),
- AR_RTC_RESET_EN);
+ if (!AR_SREV_5416(ah) &&
+ !AR_SREV_9271(ah) && !AR_SREV_9462_10(ah)) {
+ REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+ udelay(2);
+ }
}
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
if (AR_SREV_9300_20_OR_LATER(ah))
- REG_WRITE(ah, AR_WA,
- ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+ REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
}
/*
@@ -1626,6 +1855,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
*/
static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
{
+ u32 val;
+
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (setChip) {
struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -1635,12 +1866,30 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
REG_WRITE(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_ON_INT);
} else {
+
+ /* When chip goes into network sleep, it could be waken
+ * up by MCI_INT interrupt caused by BT's HW messages
+ * (LNA_xxx, CONT_xxx) which chould be in a very fast
+ * rate (~100us). This will cause chip to leave and
+ * re-enter network sleep mode frequently, which in
+ * consequence will have WLAN MCI HW to generate lots of
+ * SYS_WAKING and SYS_SLEEPING messages which will make
+ * BT CPU to busy to process.
+ */
+ if (AR_SREV_9462(ah)) {
+ val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) &
+ ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK;
+ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val);
+ }
/*
* Clear the RTC force wake bit to allow the
* mac to go to sleep.
*/
REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_EN);
+
+ if (AR_SREV_9462(ah))
+ udelay(30);
}
}
@@ -1804,16 +2053,16 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
REG_WRITE(ah, AR_BEACON_PERIOD,
- TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ TU_TO_USEC(bs->bs_intval));
REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
- TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ TU_TO_USEC(bs->bs_intval));
REGWRITE_BUFFER_FLUSH(ah);
REG_RMW_FIELD(ah, AR_RSSI_THR,
AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
- beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
+ beaconintval = bs->bs_intval;
if (bs->bs_sleepduration > beaconintval)
beaconintval = bs->bs_sleepduration;
@@ -1868,12 +2117,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers);
/* HW Capabilities */
/*******************/
+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
+{
+ eeprom_chainmask &= chip_chainmask;
+ if (eeprom_chainmask)
+ return eeprom_chainmask;
+ else
+ return chip_chainmask;
+}
+
int ath9k_hw_fill_cap_info(struct ath_hw *ah)
{
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+ unsigned int chip_chainmask;
u16 eeval;
u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
@@ -1881,11 +2140,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
regulatory->current_rd = eeval;
- eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
- if (AR_SREV_9285_12_OR_LATER(ah))
- eeval |= AR9285_RDEXT_DEFAULT;
- regulatory->current_rd_ext = eeval;
-
if (ah->opmode != NL80211_IFTYPE_AP &&
ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
if (regulatory->current_rd == 0x64 ||
@@ -1910,6 +2164,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (eeval & AR5416_OPFLAGS_11G)
pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+ if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
+ chip_chainmask = 1;
+ else if (!AR_SREV_9280_20_OR_LATER(ah))
+ chip_chainmask = 7;
+ else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+ chip_chainmask = 3;
+ else
+ chip_chainmask = 7;
+
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
/*
* For AR9271 we will temporarilly uses the rx chainmax as read from
@@ -1926,6 +2189,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
/* Use rx_chainmask from EEPROM. */
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
+ pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+ pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+ ah->txchainmask = pCap->tx_chainmask;
+ ah->rxchainmask = pCap->rx_chainmask;
+
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
/* enable key search for every frame in an aggregate */
@@ -2006,7 +2274,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
- if (!AR_SREV_9485(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@@ -2019,10 +2287,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
} else {
pCap->tx_desc_len = sizeof(struct ath_desc);
- if (AR_SREV_9280_20(ah) &&
- ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
- AR5416_EEP_MINOR_VER_16) ||
- ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
+ if (AR_SREV_9280_20(ah))
pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
}
@@ -2048,7 +2313,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
/*
* enable the diversity-combining algorithm only when
@@ -2082,6 +2347,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
rx_chainmask >>= 1;
}
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ ah->enabled_cals |= TX_IQ_CAL;
+ if (!AR_SREV_9330(ah))
+ ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
+ }
+ if (AR_SREV_9462(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_RTT;
+
return 0;
}
@@ -2242,6 +2515,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
ENABLE_REGWRITE_BUFFER(ah);
+ if (AR_SREV_9462(ah))
+ bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
+
REG_WRITE(ah, AR_RX_FILTER, bits);
phybits = 0;
@@ -2283,20 +2559,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable);
+static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ enum eeprom_param gain_param;
+
+ if (IS_CHAN_2GHZ(chan))
+ gain_param = EEP_ANTENNA_GAIN_2G;
+ else
+ gain_param = EEP_ANTENNA_GAIN_5G;
+
+ return ah->eep_ops->get_eeprom(ah, gain_param);
+}
+
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ struct ieee80211_channel *channel;
+ int chan_pwr, new_pwr, max_gain;
+ int ant_gain, ant_reduction = 0;
+
+ if (!chan)
+ return;
+
+ channel = chan->chan;
+ chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
+ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
+
+ ant_gain = get_antenna_gain(ah, chan);
+ if (ant_gain > max_gain)
+ ant_reduction = ant_gain - max_gain;
+
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(reg, chan),
+ ant_reduction, new_pwr, false);
+}
+
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan;
- regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
+ reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
+ if (test)
+ channel->max_power = MAX_RATE_POWER / 2;
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), test);
+ ath9k_hw_apply_txpower(ah, chan);
+
+ if (test)
+ channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
}
EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
@@ -2495,6 +2807,20 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask);
+ if (AR_SREV_9462(ah)) {
+ /*
+ * Starting from AR9462, each generic timer can select which tsf
+ * to use. But we still follow the old rule, 0 - 7 use tsf and
+ * 8 - 15 use tsf2.
+ */
+ if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
+ REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+ (1 << timer->index));
+ else
+ REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+ (1 << timer->index));
+ }
+
/* Enable both trigger and thresh interrupt masks */
REG_SET_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
@@ -2597,7 +2923,10 @@ static struct {
{ AR_SREV_VERSION_9287, "9287" },
{ AR_SREV_VERSION_9271, "9271" },
{ AR_SREV_VERSION_9300, "9300" },
+ { AR_SREV_VERSION_9330, "9330" },
+ { AR_SREV_VERSION_9340, "9340" },
{ AR_SREV_VERSION_9485, "9485" },
+ { AR_SREV_VERSION_9462, "9462" },
};
/* For devices with external radios */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 9dc2666..8b1123d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -45,6 +45,10 @@
#define AR9300_DEVID_PCIE 0x0030
#define AR9300_DEVID_AR9340 0x0031
#define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9580 0x0033
+#define AR9300_DEVID_AR9462 0x0034
+#define AR9300_DEVID_AR9330 0x0035
+#define AR9485_DEVID_AR1111 0x0037
#define AR5416_AR9100_DEVID 0x000b
@@ -92,6 +96,12 @@
(_ah)->reg_ops.write_flush((_ah)); \
} while (0)
+#define PR_EEP(_s, _val) \
+ do { \
+ len += snprintf(buf + len, size - len, "%20s : %10d\n", \
+ _s, (_val)); \
+ } while (0)
+
#define SM(_v, _f) (((_v) << _f##_S) & _f)
#define MS(_v, _f) (((_v) & _f) >> _f##_S)
#define REG_RMW_FIELD(_a, _r, _f, _v) \
@@ -142,6 +152,8 @@
#define AR_KEYTABLE_SIZE 128
#define POWER_UP_TIME 10000
#define SPUR_RSSI_THRESH 40
+#define UPPER_5G_SUB_BAND_START 5700
+#define MID_5G_SUB_BAND_START 5400
#define CAB_TIMEOUT_VAL 10
#define BEACON_TIMEOUT_VAL 10
@@ -157,12 +169,13 @@
#define ATH9K_HW_RX_HP_QDEPTH 16
#define ATH9K_HW_RX_LP_QDEPTH 128
-#define PAPRD_GAIN_TABLE_ENTRIES 32
-#define PAPRD_TABLE_SZ 24
+#define PAPRD_GAIN_TABLE_ENTRIES 32
+#define PAPRD_TABLE_SZ 24
+#define PAPRD_IDEAL_AGC2_PWR_RANGE 0xe0
enum ath_hw_txq_subtype {
- ATH_TXQ_AC_BE = 0,
- ATH_TXQ_AC_BK = 1,
+ ATH_TXQ_AC_BK = 0,
+ ATH_TXQ_AC_BE = 1,
ATH_TXQ_AC_VI = 2,
ATH_TXQ_AC_VO = 3,
};
@@ -190,6 +203,7 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_2GHZ = BIT(13),
ATH9K_HW_CAP_5GHZ = BIT(14),
ATH9K_HW_CAP_APM = BIT(15),
+ ATH9K_HW_CAP_RTT = BIT(16),
};
struct ath9k_hw_capabilities {
@@ -325,18 +339,35 @@ enum ath9k_int {
CHANNEL_HT40PLUS | \
CHANNEL_HT40MINUS)
+#define MAX_RTT_TABLE_ENTRY 6
+#define RTT_HIST_MAX 3
+struct ath9k_rtt_hist {
+ u32 table[AR9300_MAX_CHAINS][RTT_HIST_MAX][MAX_RTT_TABLE_ENTRY];
+ u8 num_readings;
+};
+
+#define MAX_IQCAL_MEASUREMENT 8
+#define MAX_CL_TAB_ENTRY 16
+
struct ath9k_hw_cal_data {
u16 channel;
u32 channelFlags;
+ u32 chanmode;
int32_t CalValid;
int8_t iCoff;
int8_t qCoff;
bool paprd_done;
bool nfcal_pending;
bool nfcal_interference;
+ bool done_txiqcal_once;
+ bool done_txclcal_once;
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
+ u32 num_measures[AR9300_MAX_CHAINS];
+ int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS];
+ u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY];
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+ struct ath9k_rtt_hist rtt_hist;
};
struct ath9k_channel {
@@ -378,14 +409,6 @@ enum ath9k_power_mode {
ATH9K_PM_UNDEFINED
};
-enum ath9k_tp_scale {
- ATH9K_TP_SCALE_MAX = 0,
- ATH9K_TP_SCALE_50,
- ATH9K_TP_SCALE_25,
- ATH9K_TP_SCALE_12,
- ATH9K_TP_SCALE_MIN
-};
-
enum ser_reg_mode {
SER_REG_MODE_OFF = 0,
SER_REG_MODE_ON = 1,
@@ -402,7 +425,6 @@ struct ath9k_beacon_state {
u32 bs_nexttbtt;
u32 bs_nextdtim;
u32 bs_intval;
-#define ATH9K_BEACON_PERIOD 0x0000ffff
#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
u32 bs_dtimperiod;
u16 bs_cfpperiod;
@@ -435,7 +457,6 @@ struct ath9k_hw_version {
u16 phyRev;
u16 analog5GhzRev;
u16 analog2GhzRev;
- u16 subsysid;
enum ath_usb_dev usbdev;
};
@@ -574,7 +595,6 @@ struct ath_hw_private_ops {
bool (*rfbus_req)(struct ath_hw *ah);
void (*rfbus_done)(struct ath_hw *ah);
void (*restore_chainmask)(struct ath_hw *ah);
- void (*set_diversity)(struct ath_hw *ah, bool value);
u32 (*compute_pll_control)(struct ath_hw *ah,
struct ath9k_channel *chan);
bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
@@ -582,6 +602,8 @@ struct ath_hw_private_ops {
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
void (*set_radar_params)(struct ath_hw *ah,
struct ath_hw_radar_conf *conf);
+ int (*fast_chan_change)(struct ath_hw *ah, struct ath9k_channel *chan,
+ u8 *ini_reloaded);
/* ANI */
void (*ani_cache_ini_regs)(struct ath_hw *ah);
@@ -598,40 +620,18 @@ struct ath_hw_private_ops {
*/
struct ath_hw_ops {
void (*config_pci_powersave)(struct ath_hw *ah,
- int restore,
- int power_off);
+ bool power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
- void (*get_desc_link)(void *ds, u32 **link);
bool (*calibrate)(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
bool longcal);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
- void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu);
+ void (*set_txdesc)(struct ath_hw *ah, void *ds,
+ struct ath_tx_info *i);
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts);
- void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType,
- u32 flags);
- void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags);
- void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
- u32 aggrLen);
- void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
- u32 numDelims);
- void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
- void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
- void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
void (*antdiv_comb_conf_get)(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf);
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
@@ -645,9 +645,16 @@ struct ath_nf_limits {
s16 nominal;
};
+enum ath_cal_list {
+ TX_IQ_CAL = BIT(0),
+ TX_IQ_ON_AGC_CAL = BIT(1),
+ TX_CL_CAL = BIT(2),
+};
+
/* ah_flags */
#define AH_USE_EEPROM 0x1
#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
+#define AH_FASTCC 0x4
struct ath_hw {
struct ath_ops reg_ops;
@@ -688,6 +695,7 @@ struct ath_hw {
enum nl80211_iftype opmode;
enum ath9k_power_mode power_mode;
+ s8 noise;
struct ath9k_hw_cal_data *caldata;
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
@@ -701,8 +709,10 @@ struct ath_hw {
u32 txdesc_interrupt_mask;
u32 txeol_interrupt_mask;
u32 txurn_interrupt_mask;
+ atomic_t intr_ref_cnt;
bool chip_fullsleep;
u32 atim_window;
+ u32 modes_index;
/* Calibration */
u32 supp_cals;
@@ -741,6 +751,7 @@ struct ath_hw {
int32_t sign[AR5416_MAX_CHAINS];
} meas3;
u16 cal_samples;
+ u8 enabled_cals;
u32 sta_id1_defaults;
u32 misc_mode;
@@ -817,11 +828,14 @@ struct ath_hw {
struct ar5416IniArray iniModes_9271_1_0_only;
struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484;
+ struct ar5416IniArray ini_japan2484;
struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray iniModes_high_power_tx_gain_9271;
struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
+ struct ar5416IniArray ini_radio_post_sys2ant;
+ struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
@@ -861,6 +875,8 @@ struct ath_hw {
u32 ent_mode;
bool is_clk_25mhz;
+ int (*get_mac_revision)(void);
+ int (*external_reset)(void);
};
struct ath_bus_ops {
@@ -973,6 +989,7 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah);
/* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent);
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
/*
* Code Specific to AR5008, AR9001 or AR9002,
@@ -981,8 +998,6 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
int ar9002_hw_rf_claim(struct ath_hw *ah);
void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
-void ar9002_hw_update_async_fifo(struct ath_hw *ah);
-void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
/*
* Code specific to AR9003, we stuff these here to avoid callbacks
@@ -1002,6 +1017,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
int ar9003_paprd_init_table(struct ath_hw *ah);
bool ar9003_paprd_is_done(struct ath_hw *ah);
void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains);
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
/* Hardware family op attach helpers */
void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
@@ -1027,10 +1043,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
-#define ATH_PCIE_CAP_LINK_CTRL 0x70
-#define ATH_PCIE_CAP_LINK_L0S 1
-#define ATH_PCIE_CAP_LINK_L1 2
-
#define ATH9K_CLOCK_RATE_CCK 22
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index d6059a2..1355d71 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -14,8 +14,10 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/ath9k_platform.h>
+#include <linux/module.h>
#include "ath9k.h"
@@ -42,6 +44,10 @@ static int ath9k_btcoex_enable;
module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
+static int ath9k_ps_enable;
+module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
+MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
+
bool is_ath9k_unloaded;
/* We use the hw_value as an index into our private channel structure */
@@ -196,6 +202,19 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
return val;
}
+static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset,
+ u32 set, u32 clr)
+{
+ u32 val;
+
+ val = ioread32(sc->mem + reg_offset);
+ val &= ~clr;
+ val |= set;
+ iowrite32(val, sc->mem + reg_offset);
+
+ return val;
+}
+
static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -204,16 +223,12 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl
unsigned long uninitialized_var(flags);
u32 val;
- if (ah->config.serialize_regmode == SER_REG_MODE_ON)
+ if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
spin_lock_irqsave(&sc->sc_serial_rw, flags);
-
- val = ioread32(sc->mem + reg_offset);
- val &= ~clr;
- val |= set;
- iowrite32(val, sc->mem + reg_offset);
-
- if (ah->config.serialize_regmode == SER_REG_MODE_ON)
+ val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+ } else
+ val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
return val;
}
@@ -245,7 +260,7 @@ static void setup_ht_cap(struct ath_softc *sc,
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
- if (AR_SREV_9485(ah))
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
max_streams = 1;
else if (AR_SREV_9300_20_OR_LATER(ah))
max_streams = 3;
@@ -260,8 +275,8 @@ static void setup_ht_cap(struct ath_softc *sc,
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
- tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
- rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
+ tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
+ rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
@@ -298,10 +313,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
struct list_head *head, const char *name,
int nbuf, int ndesc, bool is_tx)
{
-#define DS2PHYS(_dd, _ds) \
- ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u8 *ds;
struct ath_buf *bf;
@@ -396,34 +407,6 @@ fail2:
fail:
memset(dd, 0, sizeof(*dd));
return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
-}
-
-void ath9k_init_crypto(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = AR_KEYTABLE_SIZE;
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath_hw_keyreset(common, (u16) i);
-
- /*
- * Check whether the separate key cache entries
- * are required to handle both tx+rx MIC keys.
- * With split mic keys the number of stations is limited
- * to 27 otherwise 59.
- */
- if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
}
static int ath9k_init_btcoex(struct ath_softc *sc)
@@ -519,7 +502,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
-
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -529,10 +511,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->sc_flags |= SC_OP_RXAGGR;
}
- common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
- common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
-
- ath9k_hw_set_diversity(sc->sc_ah, true);
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
@@ -546,7 +524,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
}
-static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
+static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
struct ath9k_platform_data *pdata = sc->dev->platform_data;
@@ -561,10 +539,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
ah->hw = sc->hw;
ah->hw_version.devid = devid;
- ah->hw_version.subsysid = subsysid;
ah->reg_ops.read = ath9k_ioread32;
ah->reg_ops.write = ath9k_iowrite32;
ah->reg_ops.rmw = ath9k_reg_rmw;
+ atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah;
if (!pdata) {
@@ -575,6 +553,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
sc->sc_ah->gpio_val = pdata->gpio_val;
sc->sc_ah->led_pin = pdata->led_pin;
ah->is_clk_25mhz = pdata->is_clk_25mhz;
+ ah->get_mac_revision = pdata->get_mac_revision;
+ ah->external_reset = pdata->external_reset;
}
common = ath9k_hw_common(ah);
@@ -585,6 +565,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
common->priv = sc;
common->debug_mask = ath9k_debug;
common->btcoex_enabled = ath9k_btcoex_enable == 1;
+ common->disable_ani = false;
spin_lock_init(&common->cc_lock);
spin_lock_init(&sc->sc_serial_rw);
@@ -592,6 +573,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
mutex_init(&sc->mutex);
#ifdef CONFIG_ATH9K_DEBUGFS
spin_lock_init(&sc->nodes_lock);
+ spin_lock_init(&sc->debug.samp_lock);
INIT_LIST_HEAD(&sc->nodes);
#endif
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
@@ -625,7 +607,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
if (ret)
goto err_btcoex;
- ath9k_init_crypto(sc);
+ ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_init_misc(sc);
return 0;
@@ -649,7 +631,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
struct ath_hw *ah = sc->sc_ah;
- struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
int i;
sband = &sc->sbands[band];
@@ -658,17 +639,14 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
ah->curchan = &ah->channels[chan->hw_value];
ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
- chan->max_power = reg->max_power_level / 2;
}
}
static void ath9k_init_txpower_limits(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_channel *curchan = ah->curchan;
- ah->txchainmask = common->tx_chainmask;
if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
@@ -677,18 +655,33 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc)
ah->curchan = curchan;
}
+void ath9k_reload_chainmask_settings(struct ath_softc *sc)
+{
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
+ return;
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+}
+
+
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+ if (ath9k_ps_enable)
+ hw->flags |= IEEE80211_HW_SUPPORTS_PS;
+
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
@@ -716,9 +709,15 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
-#ifdef CONFIG_ATH9K_RATE_CONTROL
- hw->rate_control_algorithm = "ath9k_rate_control";
-#endif
+ hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
+ hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+
+ /* single chain devices with rx diversity */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
+
+ sc->ant_rx = hw->wiphy->available_antennas_rx;
+ sc->ant_tx = hw->wiphy->available_antennas_tx;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
@@ -727,17 +726,12 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ];
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
- }
+ ath9k_reload_chainmask_settings(sc);
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
-int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = sc->hw;
@@ -747,7 +741,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
struct ath_regulatory *reg;
/* Bring up device */
- error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
+ error = ath9k_init_softc(devid, sc, bus_ops);
if (error != 0)
goto error_init;
@@ -782,6 +776,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
ARRAY_SIZE(ath9k_tpt_blink));
#endif
+ INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+ INIT_WORK(&sc->hw_check_work, ath_hw_check);
+ INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+ INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)
@@ -800,9 +799,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
goto error_world;
}
- INIT_WORK(&sc->hw_check_work, ath_hw_check);
- INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
- INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
ath_init_leds(sc);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index b6b523a..167c7f6 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -16,6 +16,7 @@
#include "hw.h"
#include "hw-ops.h"
+#include <linux/export.h>
static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
struct ath9k_tx_queue_info *qi)
@@ -62,18 +63,6 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
}
EXPORT_SYMBOL(ath9k_hw_txstart);
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
- ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
- ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
- ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
- ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-}
-EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
-
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
{
u32 npend;
@@ -322,14 +311,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
q = ATH9K_NUM_TX_QUEUES - 3;
break;
case ATH9K_TX_QUEUE_DATA:
- for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
- if (ah->txq[q].tqi_type ==
- ATH9K_TX_QUEUE_INACTIVE)
- break;
- if (q == ATH9K_NUM_TX_QUEUES) {
- ath_err(common, "No available TX queue\n");
- return -1;
- }
+ q = qinfo->tqi_subtype;
break;
default:
ath_err(common, "Invalid TX queue type: %u\n", type);
@@ -345,21 +327,8 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
}
memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
qi->tqi_type = type;
- if (qinfo == NULL) {
- qi->tqi_qflags =
- TXQ_FLAG_TXOKINT_ENABLE
- | TXQ_FLAG_TXERRINT_ENABLE
- | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
- qi->tqi_aifs = INIT_AIFS;
- qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
- qi->tqi_cwmax = INIT_CWMAX;
- qi->tqi_shretry = INIT_SH_RETRY;
- qi->tqi_lgretry = INIT_LG_RETRY;
- qi->tqi_physCompBuf = 0;
- } else {
- qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
- (void) ath9k_hw_set_txq_props(ah, q, qinfo);
- }
+ qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+ (void) ath9k_hw_set_txq_props(ah, q, qinfo);
return q;
}
@@ -564,7 +533,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
- struct ath_rx_status *rs, u64 tsf)
+ struct ath_rx_status *rs)
{
struct ar5416_desc ads;
struct ar5416_desc *adsp = AR5416DESC(ds);
@@ -609,7 +578,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
else
rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
- rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
+ rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
@@ -645,10 +614,11 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
- else if (ads.ds_rxstatus8 & AR_KeyMiss)
- rs->rs_status |= ATH9K_RXERR_DECRYPT;
}
+ if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_KEYMISS;
+
return 0;
}
EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
@@ -800,6 +770,11 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
+ if (!(ah->imask & ATH9K_INT_GLOBAL))
+ atomic_set(&ah->intr_ref_cnt, -1);
+ else
+ atomic_dec(&ah->intr_ref_cnt);
+
ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
(void) REG_READ(ah, AR_IER);
@@ -821,6 +796,13 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
if (!(ah->imask & ATH9K_INT_GLOBAL))
return;
+ if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
+ ath_dbg(common, ATH_DBG_INTERRUPT,
+ "Do not enable IER ref count %d\n",
+ atomic_read(&ah->intr_ref_cnt));
+ return;
+ }
+
if (AR_SREV_9340(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
@@ -840,9 +822,9 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
+void ath9k_hw_set_interrupts(struct ath_hw *ah)
{
- enum ath9k_int omask = ah->imask;
+ enum ath9k_int ints = ah->imask;
u32 mask, mask2;
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
@@ -850,9 +832,8 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
if (!(ints & ATH9K_INT_GLOBAL))
ath9k_hw_disable_interrupts(ah);
- ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
+ ath_dbg(common, ATH_DBG_INTERRUPT, "New interrupt mask 0x%x\n", ints);
- /* TODO: global int Ref count */
mask = ints & ATH9K_INT_COMMON;
mask2 = 0;
@@ -929,9 +910,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
}
- if (ints & ATH9K_INT_GLOBAL)
- ath9k_hw_enable_interrupts(ah);
-
return;
}
EXPORT_SYMBOL(ath9k_hw_set_interrupts);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 8e848c4..11dbd14 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -17,10 +17,6 @@
#ifndef MAC_H
#define MAC_H
-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
- MS(ads->ds_rxstatus0, AR_RxRate) : \
- (ads->ds_rxstatus3 >> 2) & 0xFF)
-
#define set11nTries(_series, _index) \
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
@@ -79,9 +75,10 @@
#define ATH9K_TXERR_XTXOP 0x08
#define ATH9K_TXERR_TIMER_EXPIRED 0x10
#define ATH9K_TX_ACKED 0x20
+#define ATH9K_TX_FLUSH 0x40
#define ATH9K_TXERR_MASK \
(ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \
- ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
+ ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED | ATH9K_TX_FLUSH)
#define ATH9K_TX_BA 0x01
#define ATH9K_TX_PWRMGMT 0x02
@@ -146,6 +143,7 @@ struct ath_rx_status {
u8 rs_moreaggr;
u8 rs_num_delims;
u8 rs_flags;
+ bool is_mybeacon;
u32 evm0;
u32 evm1;
u32 evm2;
@@ -184,6 +182,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_FIFO 0x04
#define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10
+#define ATH9K_RXERR_KEYMISS 0x20
#define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02
@@ -194,7 +193,7 @@ struct ath_htc_rx_status {
#define ATH9K_RX_DECRYPT_BUSY 0x40
#define ATH9K_RXKEYIX_INVALID ((u8)-1)
-#define ATH9K_TXKEYIX_INVALID ((u32)-1)
+#define ATH9K_TXKEYIX_INVALID ((u8)-1)
enum ath9k_phyerr {
ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */
@@ -262,7 +261,11 @@ struct ath_desc {
#define ATH9K_TXDESC_VMF 0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
#define ATH9K_TXDESC_LOWRXCHAIN 0x0400
-#define ATH9K_TXDESC_LDPC 0x00010000
+#define ATH9K_TXDESC_LDPC 0x0800
+#define ATH9K_TXDESC_CLRDMASK 0x1000
+
+#define ATH9K_TXDESC_PAPRD 0x70000
+#define ATH9K_TXDESC_PAPRD_S 16
#define ATH9K_RXDESC_INTREQ 0x0020
@@ -643,6 +646,7 @@ enum ath9k_rx_filter {
ATH9K_RX_FILTER_PSPOLL = 0x00004000,
ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
+ ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
};
#define ATH9K_RATESERIES_RTS_CTS 0x0001
@@ -658,6 +662,13 @@ struct ath9k_11n_rate_series {
u32 RateFlags;
};
+enum aggr_type {
+ AGGR_BUF_NONE,
+ AGGR_BUF_FIRST,
+ AGGR_BUF_MIDDLE,
+ AGGR_BUF_LAST,
+};
+
enum ath9k_key_type {
ATH9K_KEY_TYPE_CLEAR,
ATH9K_KEY_TYPE_WEP,
@@ -665,6 +676,33 @@ enum ath9k_key_type {
ATH9K_KEY_TYPE_TKIP,
};
+struct ath_tx_info {
+ u8 qcu;
+
+ bool is_first;
+ bool is_last;
+
+ enum aggr_type aggr;
+ u8 ndelim;
+ u16 aggr_len;
+
+ dma_addr_t link;
+ int pkt_len;
+ u32 flags;
+
+ dma_addr_t buf_addr[4];
+ int buf_len[4];
+
+ struct ath9k_11n_rate_series rates[4];
+ u8 rtscts_rate;
+ bool dur_update;
+
+ enum ath9k_pkt_type type;
+ enum ath9k_key_type keytype;
+ u8 keyix;
+ u8 txpower;
+};
+
struct ath_hw;
struct ath9k_channel;
enum ath9k_int;
@@ -672,7 +710,6 @@ enum ath9k_int;
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
@@ -687,7 +724,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
- struct ath_rx_status *rs, u64 tsf);
+ struct ath_rx_status *rs);
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
@@ -699,7 +736,7 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
+void ath9k_hw_set_interrupts(struct ath_hw *ah);
void ath9k_hw_enable_interrupts(struct ath_hw *ah);
void ath9k_hw_disable_interrupts(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 806748a..8d64c16 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -62,14 +62,12 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
if (txq->axq_depth || !list_empty(&txq->axq_acq))
pending = true;
- else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
- pending = !list_empty(&txq->txq_fifo_pending);
spin_unlock_bh(&txq->axq_lock);
return pending;
}
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
{
unsigned long flags;
bool ret;
@@ -113,30 +111,35 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
void ath9k_ps_restore(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ enum ath9k_power_mode mode;
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (--sc->ps_usecount != 0)
goto unlock;
- spin_lock(&common->cc_lock);
- ath_hw_cycle_counters_update(common);
- spin_unlock(&common->cc_lock);
-
if (sc->ps_idle)
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+ mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA |
PS_WAIT_FOR_TX_ACK)))
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+ mode = ATH9K_PM_NETWORK_SLEEP;
+ else
+ goto unlock;
+
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ spin_unlock(&common->cc_lock);
+
+ ath9k_hw_setpower(sc->sc_ah, mode);
unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
-static void ath_start_ani(struct ath_common *common)
+void ath_start_ani(struct ath_common *common)
{
struct ath_hw *ah = common->ah;
unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -165,7 +168,7 @@ static void ath_update_survey_nf(struct ath_softc *sc, int channel)
if (chan->noisefloor) {
survey->filled |= SURVEY_INFO_NOISE_DBM;
- survey->noise = chan->noisefloor;
+ survey->noise = ath9k_hw_getchan_noise(ah, chan);
}
}
@@ -214,103 +217,171 @@ static int ath_update_survey_stats(struct ath_softc *sc)
return ret;
}
-/*
- * Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
- struct ath9k_channel *hchan)
+static void __ath_cancel_work(struct ath_softc *sc)
{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &common->hw->conf;
- bool fastcc = true, stopped;
- struct ieee80211_channel *channel = hw->conf.channel;
- struct ath9k_hw_cal_data *caldata = NULL;
- int r;
-
- if (sc->sc_flags & SC_OP_INVALID)
- return -EIO;
-
- sc->hw_busy_count = 0;
-
- del_timer_sync(&common->ani.timer);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
+}
- ath9k_ps_wakeup(sc);
-
- spin_lock_bh(&sc->sc_pcu_lock);
+static void ath_cancel_work(struct ath_softc *sc)
+{
+ __ath_cancel_work(sc);
+ cancel_work_sync(&sc->hw_reset_work);
+}
- /*
- * This is only performed if the channel settings have
- * actually changed.
- *
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
- * hardware at the new frequency, and then re-enable
- * the relevant bits of the h/w.
- */
- ath9k_hw_disable_interrupts(ah);
- stopped = ath_drain_all_txq(sc, false);
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool ret = true;
- if (!ath_stoprecv(sc))
- stopped = false;
+ ieee80211_stop_queues(sc->hw);
- if (!ath9k_hw_check_alive(ah))
- stopped = false;
+ sc->hw_busy_count = 0;
+ del_timer_sync(&common->ani.timer);
- /* XXX: do not flush receive queue here. We don't want
- * to flush data frames already in queue because of
- * changing channel. */
+ ath9k_debug_samp_bb_mac(sc);
+ ath9k_hw_disable_interrupts(ah);
- if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
- fastcc = false;
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ ret &= ath_stoprecv(sc);
+ ret &= ath_drain_all_txq(sc, retry_tx);
+ } else {
+ ret &= ath_drain_all_txq(sc, retry_tx);
+ ret &= ath_stoprecv(sc);
+ }
- if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
- caldata = &sc->caldata;
+ if (!flush) {
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ } else {
+ ath_flushrecv(sc);
+ }
- ath_dbg(common, ATH_DBG_CONFIG,
- "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
- sc->sc_ah->curchan->channel,
- channel->center_freq, conf_is_ht40(conf),
- fastcc);
+ return ret;
+}
- r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
- if (r) {
- ath_err(common,
- "Unable to reset channel (%u MHz), reset status %d\n",
- channel->center_freq, r);
- goto ps_restore;
- }
+static bool ath_complete_reset(struct ath_softc *sc, bool start)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
- r = -EIO;
- goto ps_restore;
+ return false;
}
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
if (sc->sc_flags & SC_OP_BEACONS)
ath_set_beacon(sc);
+
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
- ath_start_ani(common);
+ if (!common->disable_ani)
+ ath_start_ani(common);
}
- ps_restore:
- ieee80211_wake_queues(hw);
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) {
+ struct ath_hw_antcomb_conf div_ant_conf;
+ u8 lna_conf;
+
+ ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+
+ if (sc->ant_rx == 1)
+ lna_conf = ATH_ANT_DIV_COMB_LNA1;
+ else
+ lna_conf = ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.main_lna_conf = lna_conf;
+ div_ant_conf.alt_lna_conf = lna_conf;
+
+ ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
+ }
+
+ ieee80211_wake_queues(sc->hw);
+
+ return true;
+}
+
+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
+ bool retry_tx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_cal_data *caldata = NULL;
+ bool fastcc = true;
+ bool flush = false;
+ int r;
+
+ __ath_cancel_work(sc);
+
+ spin_lock_bh(&sc->sc_pcu_lock);
+
+ if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
+ fastcc = false;
+ caldata = &sc->caldata;
+ }
+
+ if (!hchan) {
+ fastcc = false;
+ flush = true;
+ hchan = ah->curchan;
+ }
+
+ if (fastcc && !ath9k_hw_check_alive(ah))
+ fastcc = false;
+ if (!ath_prepare_reset(sc, retry_tx, flush))
+ fastcc = false;
+
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Reset to %u MHz, HT40: %d fastcc: %d\n",
+ hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
+ CHANNEL_HT40PLUS)),
+ fastcc);
+
+ r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+ if (r) {
+ ath_err(common,
+ "Unable to reset channel, reset status %d\n", r);
+ goto out;
+ }
+
+ if (!ath_complete_reset(sc, true))
+ r = -EIO;
+
+out:
spin_unlock_bh(&sc->sc_pcu_lock);
+ return r;
+}
+
+
+/*
+ * Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+ struct ath9k_channel *hchan)
+{
+ int r;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EIO;
+
+ ath9k_ps_wakeup(sc);
+
+ r = ath_reset_internal(sc, hchan, false);
ath9k_ps_restore(sc);
+
return r;
}
@@ -318,7 +389,6 @@ static void ath_paprd_activate(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_hw_cal_data *caldata = ah->caldata;
- struct ath_common *common = ath9k_hw_common(ah);
int chain;
if (!caldata || !caldata->paprd_done)
@@ -327,7 +397,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(common->tx_chainmask & BIT(chain)))
+ if (!(ah->txchainmask & BIT(chain)))
continue;
ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -361,7 +431,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0) {
- ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n");
+ ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");
dev_kfree_skb_any(skb);
return false;
}
@@ -370,7 +440,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
if (!time_left)
- ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
+ ath_dbg(common, ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
@@ -394,12 +464,14 @@ void ath_paprd_calibrate(struct work_struct *work)
if (!caldata)
return;
+ ath9k_ps_wakeup(sc);
+
if (ar9003_paprd_init_table(ah) < 0)
- return;
+ goto fail_paprd;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
- return;
+ goto fail_paprd;
skb_put(skb, len);
memset(skb->data, 0, len);
@@ -411,9 +483,8 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
- ath9k_ps_wakeup(sc);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(common->tx_chainmask & BIT(chain)))
+ if (!(ah->txchainmask & BIT(chain)))
continue;
chain_ok = 0;
@@ -431,11 +502,18 @@ void ath_paprd_calibrate(struct work_struct *work)
if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
- if (!ar9003_paprd_is_done(ah))
+ if (!ar9003_paprd_is_done(ah)) {
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "PAPRD not yet done on chain %d\n", chain);
break;
+ }
- if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
+ if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "PAPRD create curve failed on chain %d\n",
+ chain);
break;
+ }
chain_ok = 1;
}
@@ -515,24 +593,19 @@ void ath_ani_calibrate(unsigned long data)
common->ani.checkani_timer = timestamp;
}
- /* Skip all processing if there's nothing to do. */
- if (longcal || shortcal || aniflag) {
- /* Call ANI routine if necessary */
- if (aniflag) {
- spin_lock_irqsave(&common->cc_lock, flags);
- ath9k_hw_ani_monitor(ah, ah->curchan);
- ath_update_survey_stats(sc);
- spin_unlock_irqrestore(&common->cc_lock, flags);
- }
+ /* Call ANI routine if necessary */
+ if (aniflag) {
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath9k_hw_ani_monitor(ah, ah->curchan);
+ ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+ }
- /* Perform calibration if necessary */
- if (longcal || shortcal) {
- common->ani.caldone =
- ath9k_hw_calibrate(ah,
- ah->curchan,
- common->rx_chainmask,
- longcal);
- }
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ common->ani.caldone =
+ ath9k_hw_calibrate(ah, ah->curchan,
+ ah->rxchainmask, longcal);
}
ath9k_ps_restore(sc);
@@ -543,6 +616,7 @@ set_timer:
* The interval must be the shortest necessary to satisfy ANI,
* short calibration and long calibration.
*/
+ ath9k_debug_samp_bb_mac(sc);
cal_interval = ATH_LONG_CALINTERVAL;
if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval,
@@ -562,7 +636,6 @@ set_timer:
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an;
- struct ath_hw *ah = sc->sc_ah;
an = (struct ath_node *)sta->drv_priv;
#ifdef CONFIG_ATH9K_DEBUGFS
@@ -571,9 +644,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
spin_unlock(&sc->nodes_lock);
an->sta = sta;
#endif
- if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
- sc->sc_flags |= SC_OP_ENABLE_APM;
-
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
@@ -597,78 +667,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
ath_tx_node_cleanup(sc, an);
}
-void ath_hw_check(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- unsigned long flags;
- int busy;
-
- ath9k_ps_wakeup(sc);
- if (ath9k_hw_check_alive(sc->sc_ah))
- goto out;
-
- spin_lock_irqsave(&common->cc_lock, flags);
- busy = ath_update_survey_stats(sc);
- spin_unlock_irqrestore(&common->cc_lock, flags);
-
- ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
- "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
- if (busy >= 99) {
- if (++sc->hw_busy_count >= 3)
- ath_reset(sc, true);
- } else if (busy >= 0)
- sc->hw_busy_count = 0;
-
-out:
- ath9k_ps_restore(sc);
-}
-
-static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
-{
- static int count;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- if (pll_sqsum >= 0x40000) {
- count++;
- if (count == 3) {
- /* Rx is hung for more than 500ms. Reset it */
- ath_dbg(common, ATH_DBG_RESET,
- "Possible RX hang, resetting");
- ath_reset(sc, true);
- count = 0;
- }
- } else
- count = 0;
-}
-
-void ath_hw_pll_work(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc,
- hw_pll_work.work);
- u32 pll_sqsum;
-
- /*
- * ensure that the PLL WAR is executed only
- * after the STA is associated (or) if the
- * beaconing had started in interfaces that
- * uses beacons.
- */
- if (!(sc->sc_flags & SC_OP_BEACONS))
- return;
-
- if (AR_SREV_9485(sc->sc_ah)) {
-
- ath9k_ps_wakeup(sc);
- pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
- ath9k_ps_restore(sc);
-
- ath_hw_pll_rx_hang_check(sc, pll_sqsum);
-
- ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
- }
-}
-
void ath9k_tasklet(unsigned long data)
{
@@ -679,14 +677,24 @@ void ath9k_tasklet(unsigned long data)
u32 status = sc->intrstatus;
u32 rxmask;
+ ath9k_ps_wakeup(sc);
+ spin_lock(&sc->sc_pcu_lock);
+
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
- ath_reset(sc, true);
- return;
- }
+#ifdef CONFIG_ATH9K_DEBUGFS
+ enum ath_reset_type type;
- ath9k_ps_wakeup(sc);
- spin_lock(&sc->sc_pcu_lock);
+ if (status & ATH9K_INT_FATAL)
+ type = RESET_TYPE_FATAL_INT;
+ else
+ type = RESET_TYPE_BB_WATCHDOG;
+
+ RESET_STAT_INC(sc, type);
+#endif
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ goto out;
+ }
/*
* Only run the baseband hang check if beacons stop working in AP or
@@ -706,8 +714,7 @@ void ath9k_tasklet(unsigned long data)
*/
ath_dbg(common, ATH_DBG_PS,
"TSFOOR - Sync with next Beacon\n");
- sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC |
- PS_TSFOOR_SYNC;
+ sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
}
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
@@ -736,6 +743,7 @@ void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah);
+out:
/* re-enable hardware interrupt */
ath9k_hw_enable_interrupts(ah);
@@ -826,11 +834,9 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true);
- if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (status & ATH9K_INT_RXEOL) {
- ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
- ath9k_hw_set_interrupts(ah, ah->imask);
- }
+ if (status & ATH9K_INT_RXEOL) {
+ ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+ ath9k_hw_set_interrupts(ah);
}
if (status & ATH9K_INT_MIB) {
@@ -877,7 +883,7 @@ chip_reset:
#undef SCHED_INTR
}
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
+static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -886,8 +892,9 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
+ atomic_set(&ah->intr_ref_cnt, -1);
- ath9k_hw_configpcipowersave(ah, 0, 0);
+ ath9k_hw_configpcipowersave(ah, false);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
@@ -899,27 +906,13 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
channel->center_freq, r);
}
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
- if (ath_startrecv(sc) != 0) {
- ath_err(common, "Unable to restart recv logic\n");
- goto out;
- }
- if (sc->sc_flags & SC_OP_BEACONS)
- ath_set_beacon(sc); /* restart beacons */
-
- /* Re-Enable interrupts */
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath_complete_reset(sc, true);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
- ieee80211_wake_queues(hw);
- ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
-
-out:
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
@@ -932,11 +925,10 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
int r;
ath9k_ps_wakeup(sc);
- cancel_delayed_work_sync(&sc->hw_pll_work);
- spin_lock_bh(&sc->sc_pcu_lock);
+ ath_cancel_work(sc);
- ieee80211_stop_queues(hw);
+ spin_lock_bh(&sc->sc_pcu_lock);
/*
* Keep the LED on when the radio is disabled
@@ -947,13 +939,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
- /* Disable interrupts */
- ath9k_hw_disable_interrupts(ah);
-
- ath_drain_all_txq(sc, false); /* clear pending tx frames */
-
- ath_stoprecv(sc); /* turn off frame recv */
- ath_flushrecv(sc); /* flush recv queue */
+ ath_prepare_reset(sc, false, true);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
@@ -967,55 +953,19 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_phy_disable(ah);
- ath9k_hw_configpcipowersave(ah, 1, 1);
+ ath9k_hw_configpcipowersave(ah, true);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
-int ath_reset(struct ath_softc *sc, bool retry_tx)
+static int ath_reset(struct ath_softc *sc, bool retry_tx)
{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hw *hw = sc->hw;
int r;
- sc->hw_busy_count = 0;
-
- /* Stop ANI */
- del_timer_sync(&common->ani.timer);
-
ath9k_ps_wakeup(sc);
- spin_lock_bh(&sc->sc_pcu_lock);
-
- ieee80211_stop_queues(hw);
-
- ath9k_hw_disable_interrupts(ah);
- ath_drain_all_txq(sc, retry_tx);
- ath_stoprecv(sc);
- ath_flushrecv(sc);
-
- r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
- if (r)
- ath_err(common,
- "Unable to reset hardware; reset status %d\n", r);
-
- if (ath_startrecv(sc) != 0)
- ath_err(common, "Unable to start recv logic\n");
-
- /*
- * We may be doing a reset in response to a request
- * that changes the channel so update any state that
- * might change as a result.
- */
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-
- if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
- ath_set_beacon(sc); /* restart beacons */
-
- ath9k_hw_set_interrupts(ah, ah->imask);
+ r = ath_reset_internal(sc, NULL, retry_tx);
if (retry_tx) {
int i;
@@ -1028,16 +978,94 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
}
}
- ieee80211_wake_queues(hw);
- spin_unlock_bh(&sc->sc_pcu_lock);
-
- /* Start ANI */
- ath_start_ani(common);
ath9k_ps_restore(sc);
return r;
}
+void ath_reset_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
+
+ ath_reset(sc, true);
+}
+
+void ath_hw_check(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned long flags;
+ int busy;
+
+ ath9k_ps_wakeup(sc);
+ if (ath9k_hw_check_alive(sc->sc_ah))
+ goto out;
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+ busy = ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
+ "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+ if (busy >= 99) {
+ if (++sc->hw_busy_count >= 3) {
+ RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
+
+ } else if (busy >= 0)
+ sc->hw_busy_count = 0;
+
+out:
+ ath9k_ps_restore(sc);
+}
+
+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+{
+ static int count;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ if (pll_sqsum >= 0x40000) {
+ count++;
+ if (count == 3) {
+ /* Rx is hung for more than 500ms. Reset it */
+ ath_dbg(common, ATH_DBG_RESET,
+ "Possible RX hang, resetting");
+ RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ count = 0;
+ }
+ } else
+ count = 0;
+}
+
+void ath_hw_pll_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ hw_pll_work.work);
+ u32 pll_sqsum;
+
+ /*
+ * ensure that the PLL WAR is executed only
+ * after the STA is associated (or) if the
+ * beaconing had started in interfaces that
+ * uses beacons.
+ */
+ if (!(sc->sc_flags & SC_OP_BEACONS))
+ return;
+
+ if (AR_SREV_9485(sc->sc_ah)) {
+
+ ath9k_ps_wakeup(sc);
+ pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+ ath9k_ps_restore(sc);
+
+ ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+ }
+}
+
/**********************/
/* mac80211 callbacks */
/**********************/
@@ -1065,7 +1093,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
init_channel = ath9k_cmn_get_curchannel(hw, ah);
/* Reset SERDES registers */
- ath9k_hw_configpcipowersave(ah, 0, 0);
+ ath9k_hw_configpcipowersave(ah, false);
/*
* The basic interface to setting the hardware in a good
@@ -1084,28 +1112,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
goto mutex_unlock;
}
- /*
- * This is needed only to setup initial state
- * but it's best done after a reset.
- */
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-
- /*
- * Setup the hardware after reset:
- * The receive engine is set going.
- * Frame transmit is handled entirely
- * in the frame output path; there's nothing to do
- * here except setup the interrupt mask.
- */
- if (ath_startrecv(sc) != 0) {
- ath_err(common, "Unable to start recv logic\n");
- r = -EIO;
- spin_unlock_bh(&sc->sc_pcu_lock);
- goto mutex_unlock;
- }
- spin_unlock_bh(&sc->sc_pcu_lock);
-
/* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
ATH9K_INT_RXORN | ATH9K_INT_FATAL |
@@ -1128,11 +1134,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
/* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
- ath9k_hw_set_interrupts(ah, ah->imask);
- ieee80211_wake_queues(hw);
+ if (!ath_complete_reset(sc, false)) {
+ r = -EIO;
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ goto mutex_unlock;
+ }
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+ spin_unlock_bh(&sc->sc_pcu_lock);
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
!ah->btcoex_hw.enabled) {
@@ -1140,8 +1149,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
AR_STOMP_LOW_WLAN_WGHT);
ath9k_hw_btcoex_enable(ah);
- if (common->bus_ops->bt_coex_prep)
- common->bus_ops->bt_coex_prep(common);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_resume(sc);
}
@@ -1227,10 +1234,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex);
- cancel_delayed_work_sync(&sc->tx_complete_work);
- cancel_delayed_work_sync(&sc->hw_pll_work);
- cancel_work_sync(&sc->paprd_work);
- cancel_work_sync(&sc->hw_check_work);
+ ath_cancel_work(sc);
if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
@@ -1270,7 +1274,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah);
- ath9k_hw_configpcipowersave(ah, 1, 1);
spin_unlock_bh(&sc->sc_pcu_lock);
@@ -1357,8 +1360,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
struct ath_common *common = ath9k_hw_common(ah);
/*
- * Use the hardware MAC address as reference, the hardware uses it
- * together with the BSSID mask when matching addresses.
+ * Pick the MAC address of the first interface as the new hardware
+ * MAC address. The hardware will use it together with the BSSID mask
+ * when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
iter_data->hw_macaddr = common->macaddr;
@@ -1418,13 +1422,17 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ah->imask &= ~ATH9K_INT_TSFOOR;
}
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
/* Set up ANI */
- if ((iter_data.naps + iter_data.nadhocs) > 0) {
+ if (iter_data.naps > 0) {
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_flags |= SC_OP_ANI_RUN;
- ath_start_ani(common);
+
+ if (!common->disable_ani) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
} else {
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
@@ -1491,15 +1499,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
}
}
- if ((ah->opmode == NL80211_IFTYPE_ADHOC) ||
- ((vif->type == NL80211_IFTYPE_ADHOC) &&
- sc->nvifs > 0)) {
- ath_err(common, "Cannot create ADHOC interface when other"
- " interfaces already exist.\n");
- ret = -EINVAL;
- goto out;
- }
-
ath_dbg(common, ATH_DBG_CONFIG,
"Attach a VIF of type: %d\n", vif->type);
@@ -1589,7 +1588,7 @@ static void ath9k_enable_ps(struct ath_softc *sc)
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
ah->imask |= ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
}
ath9k_hw_setrxabort(ah, 1);
}
@@ -1609,7 +1608,7 @@ static void ath9k_disable_ps(struct ath_softc *sc)
PS_WAIT_FOR_TX_ACK);
if (ah->imask & ATH9K_INT_TIM_TIMER) {
ah->imask &= ~ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
}
}
@@ -1688,14 +1687,14 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
"Set channel: %d MHz type: %d\n",
curchan->center_freq, conf->channel_type);
- ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, conf->channel_type);
-
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
+ ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+ curchan, conf->channel_type);
+
/*
* If the operating channel changes, change the survey in-use flags
* along with it.
@@ -1847,8 +1846,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
switch (cmd) {
case STA_NOTIFY_SLEEP:
an->sleeping = true;
- if (ath_tx_aggr_sleep(sc, an))
- ieee80211_sta_set_tim(sta);
+ ath_tx_aggr_sleep(sta, sc, an);
break;
case STA_NOTIFY_AWAKE:
an->sleeping = false;
@@ -1857,7 +1855,8 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
}
}
-static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int ath9k_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath_softc *sc = hw->priv;
@@ -1968,50 +1967,38 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
- switch (sc->sc_ah->opmode) {
- case NL80211_IFTYPE_ADHOC:
- /* There can be only one vif available */
+ /*
+ * Skip iteration if primary station vif's bss info
+ * was not changed
+ */
+ if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
+ return;
+
+ if (bss_conf->assoc) {
+ sc->sc_flags |= SC_OP_PRIM_STA_VIF;
+ avp->primary_sta_vif = true;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
- /* configure beacon */
- if (bss_conf->enable_beacon)
- ath_beacon_config(sc, vif);
- break;
- case NL80211_IFTYPE_STATION:
- /*
- * Skip iteration if primary station vif's bss info
- * was not changed
- */
- if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
- break;
-
- if (bss_conf->assoc) {
- sc->sc_flags |= SC_OP_PRIM_STA_VIF;
- avp->primary_sta_vif = true;
- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
- common->curaid = bss_conf->aid;
- ath9k_hw_write_associd(sc->sc_ah);
- ath_dbg(common, ATH_DBG_CONFIG,
+ ath_dbg(common, ATH_DBG_CONFIG,
"Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
- ath_beacon_config(sc, vif);
- /*
- * Request a re-configuration of Beacon related timers
- * on the receipt of the first Beacon frame (i.e.,
- * after time sync with the AP).
- */
- sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
- /* Reset rssi stats */
- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ ath_beacon_config(sc, vif);
+ /*
+ * Request a re-configuration of Beacon related timers
+ * on the receipt of the first Beacon frame (i.e.,
+ * after time sync with the AP).
+ */
+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+ /* Reset rssi stats */
+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ if (!common->disable_ani) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
}
- break;
- default:
- break;
+
}
}
@@ -2021,6 +2008,9 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
+ if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
/* Reconfigure bss info */
if (avp->primary_sta_vif && !bss_conf->assoc) {
ath_dbg(common, ATH_DBG_CONFIG,
@@ -2039,12 +2029,12 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
* None of station vifs are associated.
* Clear bssid & aid
*/
- if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
- !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
+ if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
ath9k_hw_write_associd(sc->sc_ah);
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
+ memset(&sc->caldata, 0, sizeof(sc->caldata));
}
}
@@ -2070,6 +2060,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
common->curbssid, common->curaid);
}
+ if (changed & BSS_CHANGED_IBSS) {
+ /* There can be only one vif available */
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+
+ if (bss_conf->ibss_joined) {
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+ if (!common->disable_ani) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
+ } else {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ }
+ }
+
/* Enable transmission of beacons (AP, IBSS, MESH) */
if ((changed & BSS_CHANGED_BEACON) ||
((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
@@ -2146,7 +2156,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath9k_ps_restore(sc);
}
-static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
+static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath_softc *sc = hw->priv;
u64 tsf;
@@ -2160,7 +2170,9 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void ath9k_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u64 tsf)
{
struct ath_softc *sc = hw->priv;
@@ -2171,7 +2183,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
mutex_unlock(&sc->mutex);
}
-static void ath9k_reset_tsf(struct ieee80211_hw *hw)
+static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath_softc *sc = hw->priv;
@@ -2296,6 +2308,12 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
mutex_lock(&sc->mutex);
cancel_delayed_work_sync(&sc->tx_complete_work);
+ if (ah->ah_flags & AH_UNPLUGGED) {
+ ath_dbg(common, ATH_DBG_ANY, "Device has been unplugged!\n");
+ mutex_unlock(&sc->mutex);
+ return;
+ }
+
if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
mutex_unlock(&sc->mutex);
@@ -2329,8 +2347,10 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
spin_lock_bh(&sc->sc_pcu_lock);
drain_txq = ath_drain_all_txq(sc, false);
spin_unlock_bh(&sc->sc_pcu_lock);
+
if (!drain_txq)
ath_reset(sc, false);
+
ath9k_ps_restore(sc);
ieee80211_wake_queues(hw);
@@ -2354,7 +2374,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
return false;
}
-int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
@@ -2393,6 +2413,73 @@ skip:
return sc->beacon.tx_last;
}
+static int ath9k_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
+
+ stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
+ stats->dot11RTSFailureCount = mib_stats->rts_bad;
+ stats->dot11FCSErrorCount = mib_stats->fcs_bad;
+ stats->dot11RTSSuccessCount = mib_stats->rts_good;
+ return 0;
+}
+
+static u32 fill_chainmask(u32 cap, u32 new)
+{
+ u32 filled = 0;
+ int i;
+
+ for (i = 0; cap && new; i++, cap >>= 1) {
+ if (!(cap & BIT(0)))
+ continue;
+
+ if (new & BIT(0))
+ filled |= BIT(i);
+
+ new >>= 1;
+ }
+
+ return filled;
+}
+
+static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (!rx_ant || !tx_ant)
+ return -EINVAL;
+
+ sc->ant_rx = rx_ant;
+ sc->ant_tx = tx_ant;
+
+ if (ah->caps.rx_chainmask == 1)
+ return 0;
+
+ /* AR9100 runs into calibration issues if not all rx chains are enabled */
+ if (AR_SREV_9100(ah))
+ ah->rxchainmask = 0x7;
+ else
+ ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
+
+ ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
+ ath9k_reload_chainmask_settings(sc);
+
+ return 0;
+}
+
+static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+ struct ath_softc *sc = hw->priv;
+
+ *tx_ant = sc->ant_tx;
+ *rx_ant = sc->ant_rx;
+ return 0;
+}
+
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2417,5 +2504,8 @@ struct ieee80211_ops ath9k_ops = {
.set_coverage_class = ath9k_set_coverage_class,
.flush = ath9k_flush,
.tx_frames_pending = ath9k_tx_frames_pending,
- .tx_last_beacon = ath9k_tx_last_beacon,
+ .tx_last_beacon = ath9k_tx_last_beacon,
+ .get_stats = ath9k_get_stats,
+ .set_antenna = ath9k_set_antenna,
+ .get_antenna = ath9k_get_antenna,
};
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index be4ea13..f7e17a0 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -18,6 +18,7 @@
#include <linux/pci.h>
#include <linux/pci-aspm.h>
#include <linux/ath9k_platform.h>
+#include <linux/module.h>
#include "ath9k.h"
static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
@@ -32,9 +33,13 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */
+ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
+ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */
+ { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */
{ 0 }
};
+
/* return bus cachesize in 4B word units */
static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
{
@@ -88,23 +93,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
return true;
}
-/*
- * Bluetooth coexistance requires disabling ASPM.
- */
-static void ath_pci_bt_coex_prep(struct ath_common *common)
-{
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- struct pci_dev *pdev = to_pci_dev(sc->dev);
- u8 aspm;
-
- if (!pci_is_pcie(pdev))
- return;
-
- pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
- aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);
- pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
-}
-
static void ath_pci_extn_synch_enable(struct ath_common *common)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
@@ -116,6 +104,7 @@ static void ath_pci_extn_synch_enable(struct ath_common *common)
pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
}
+/* Need to be called after we discover btcoex capabilities */
static void ath_pci_aspm_init(struct ath_common *common)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
@@ -125,19 +114,39 @@ static void ath_pci_aspm_init(struct ath_common *common)
int pos;
u8 aspm;
- if (!pci_is_pcie(pdev))
+ pos = pci_pcie_cap(pdev);
+ if (!pos)
return;
parent = pdev->bus->self;
- if (WARN_ON(!parent))
+ if (!parent)
return;
+ if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
+ (AR_SREV_9285(ah))) {
+ /* Bluetooth coexistance requires disabling ASPM for AR9285. */
+ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
+ aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+ pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
+
+ /*
+ * Both upstream and downstream PCIe components should
+ * have the same ASPM settings.
+ */
+ pos = pci_pcie_cap(parent);
+ pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
+ aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+ pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);
+
+ return;
+ }
+
pos = pci_pcie_cap(parent);
pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
ah->aspm_enabled = true;
/* Initialize PCIe PM and SERDES registers. */
- ath9k_hw_configpcipowersave(ah, 0, 0);
+ ath9k_hw_configpcipowersave(ah, false);
}
}
@@ -145,7 +154,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
.ath_bus_type = ATH_PCI,
.read_cachesize = ath_pci_read_cachesize,
.eeprom_read = ath_pci_eeprom_read,
- .bt_coex_prep = ath_pci_bt_coex_prep,
.extn_synch_en = ath_pci_extn_synch_enable,
.aspm_init = ath_pci_aspm_init,
};
@@ -156,7 +164,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct ath_softc *sc;
struct ieee80211_hw *hw;
u8 csz;
- u16 subsysid;
u32 val;
int ret = 0;
char hw_name[64];
@@ -250,8 +257,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->irq = pdev->irq;
- pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
- ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
+ ret = ath9k_init_device(id->device, sc, &ath_pci_bus_ops);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize device\n");
goto err_init;
@@ -330,17 +336,17 @@ static int ath_pci_resume(struct device *device)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ ath9k_ps_wakeup(sc);
/* Enable LED */
ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
/*
* Reset key cache to sane defaults (all entries cleared) instead of
* semi-random values after suspend/resume.
*/
- ath9k_ps_wakeup(sc);
- ath9k_init_crypto(sc);
+ ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_ps_restore(sc);
sc->ps_idle = true;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 9d965e3..64af11f 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -16,6 +16,7 @@
*/
#include <linux/slab.h>
+#include <linux/export.h>
#include "ath9k.h"
@@ -379,7 +380,30 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
};
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
- struct ieee80211_tx_rate *rate);
+ struct ieee80211_tx_rate *rate)
+{
+ int rix = 0, i = 0;
+ static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
+
+ if (!(rate->flags & IEEE80211_TX_RC_MCS))
+ return rate->idx;
+
+ while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
+ rix++; i++;
+ }
+
+ rix += rate->idx + rate_table->mcs_start;
+
+ if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+ (rate->flags & IEEE80211_TX_RC_SHORT_GI))
+ rix = rate_table->info[rix].ht_index;
+ else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ rix = rate_table->info[rix].sgi_index;
+ else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rix = rate_table->info[rix].cw40index;
+
+ return rix;
+}
static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
struct ath_rate_priv *ath_rc_priv)
@@ -533,7 +557,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
[valid_rate_count] = j;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
- hi = A_MAX(hi, j);
+ hi = max(hi, j);
}
}
}
@@ -569,7 +593,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
- hi = A_MAX(hi, j);
+ hi = max(hi, j);
}
}
@@ -580,7 +604,8 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
const struct ath_rate_table *rate_table,
- int *is_probing)
+ int *is_probing,
+ bool legacy)
{
u32 best_thruput, this_thruput, now_msec;
u8 rate, next_rate, best_rate, maxindex, minindex;
@@ -601,6 +626,8 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
u8 per_thres;
rate = ath_rc_priv->valid_rate_index[index];
+ if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY))
+ continue;
if (rate > ath_rc_priv->rate_max_phy)
continue;
@@ -744,7 +771,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate *rates = tx_info->control.rates;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
- u8 try_per_rate, i = 0, rix;
+ u8 try_per_rate, i = 0, rix, high_rix;
int is_probe = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
@@ -763,7 +790,9 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate = 4;
rate_table = ath_rc_priv->rate_table;
- rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
+ &is_probe, false);
+ high_rix = rix;
/*
* If we're in HT mode and both us and our peer supports LDPC.
@@ -799,10 +828,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
}
/* Fill in the other rates for multirate retry */
- for ( ; i < 4; i++) {
- /* Use twice the number of tries for the last MRR segment. */
- if (i + 1 == 4)
- try_per_rate = 8;
+ for ( ; i < 3; i++) {
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
/* All other rates in the series have RTS enabled */
@@ -810,6 +836,24 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate, rix, 1);
}
+ /* Use twice the number of tries for the last MRR segment. */
+ try_per_rate = 8;
+
+ /*
+ * Use a legacy rate as last retry to ensure that the frame
+ * is tried in both MCS and legacy rates.
+ */
+ if ((rates[2].flags & IEEE80211_TX_RC_MCS) &&
+ (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) ||
+ (ath_rc_priv->per[high_rix] > 45)))
+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
+ &is_probe, true);
+ else
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+
+ /* All other rates in the series have RTS enabled */
+ ath_rc_rate_set_series(rate_table, &rates[i], txrc,
+ try_per_rate, rix, 1);
/*
* NB:Change rate series to enable aggregation when operating
* at lower MCS rates. When first rate in series is MCS2
@@ -1080,31 +1124,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
}
-static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
- struct ieee80211_tx_rate *rate)
-{
- int rix = 0, i = 0;
- static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
-
- if (!(rate->flags & IEEE80211_TX_RC_MCS))
- return rate->idx;
-
- while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
- rix++; i++;
- }
-
- rix += rate->idx + rate_table->mcs_start;
-
- if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
- (rate->flags & IEEE80211_TX_RC_SHORT_GI))
- rix = rate_table->info[rix].ht_index;
- else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- rix = rate_table->info[rix].sgi_index;
- else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- rix = rate_table->info[rix].cw40index;
-
- return rix;
-}
static void ath_rc_tx_status(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
@@ -1228,7 +1247,7 @@ static void ath_rc_init(struct ath_softc *sc,
ht_mcs,
ath_rc_priv->ht_cap);
}
- hi = A_MAX(hi, hthi);
+ hi = max(hi, hthi);
}
ath_rc_priv->rate_table_size = hi + 1;
@@ -1346,12 +1365,6 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
return;
- if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
- tx_info->status.ampdu_ack_len =
- (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
- tx_info->status.ampdu_len = 1;
- }
-
if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
tx_status = 1;
@@ -1488,7 +1501,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
if (rc->rate_table == NULL)
return 0;
- max = 80 + rc->rate_table->rate_cnt * 1024 + 1;
+ max = 80 + rc->rate_table_size * 1024 + 1;
buf = kmalloc(max, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
@@ -1498,7 +1511,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
"HT", "MCS", "Rate",
"Success", "Retries", "XRetries", "PER");
- for (i = 0; i < rc->rate_table->rate_cnt; i++) {
+ for (i = 0; i < rc->rate_table_size; i++) {
u32 ratekbps = rc->rate_table->info[i].ratekbps;
struct ath_rc_stats *stats = &rc->rcstats[i];
char mcs[5];
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index c3d8502..e8e1901 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -221,13 +221,7 @@ struct ath_rate_priv {
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};
-enum ath9k_internal_frame_type {
- ATH9K_IFT_NOT_INTERNAL,
- ATH9K_IFT_PAUSE,
- ATH9K_IFT_UNPAUSE
-};
-
-#ifdef CONFIG_ATH9K_RATE_CONTROL
+#ifdef CONFIG_ATH9K_LEGACY_RATE_CONTROL
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
#else
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 932b3ab..8326c14 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#include "ar9003_mac.h"
@@ -39,6 +40,7 @@ static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
result = true;
break;
case 1:
+ case 2:
if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
(curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
(alt_rssi_avg >= (main_rssi_avg - 5))) ||
@@ -76,8 +78,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
struct ath_desc *ds;
struct sk_buff *skb;
- ATH_RXBUF_RESET(bf);
-
ds = bf->bf_desc;
ds->ds_link = 0; /* link to null */
ds->ds_data = bf->bf_buf_addr;
@@ -104,6 +104,14 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
sc->rx.rxlink = &ds->ds_link;
}
+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
+{
+ if (sc->rx.buf_hold)
+ ath_rx_buf_link(sc, sc->rx.buf_hold);
+
+ sc->rx.buf_hold = bf;
+}
+
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
{
/* XXX block beacon interrupts */
@@ -151,7 +159,6 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
skb = bf->bf_mpdu;
- ATH_RXBUF_RESET(bf);
memset(skb->data, 0, ah->caps.rx_status_len);
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
ah->caps.rx_status_len, DMA_TO_DEVICE);
@@ -203,14 +210,22 @@ static void ath_rx_remove_buffer(struct ath_softc *sc,
static void ath_rx_edma_cleanup(struct ath_softc *sc)
{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf;
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- if (bf->bf_mpdu)
+ if (bf->bf_mpdu) {
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
+ common->rx_bufsize,
+ DMA_BIDIRECTIONAL);
dev_kfree_skb_any(bf->bf_mpdu);
+ bf->bf_buf_addr = 0;
+ bf->bf_mpdu = NULL;
+ }
}
INIT_LIST_HEAD(&sc->rx.rxbuf);
@@ -482,6 +497,7 @@ int ath_startrecv(struct ath_softc *sc)
if (list_empty(&sc->rx.rxbuf))
goto start_recv;
+ sc->rx.buf_hold = NULL;
sc->rx.rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
ath_rx_buf_link(sc, bf);
@@ -573,22 +589,11 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
{
- struct ieee80211_mgmt *mgmt;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
if (skb->len < 24 + 8 + 2 + 2)
return;
- mgmt = (struct ieee80211_mgmt *)skb->data;
- if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) {
- /* TODO: This doesn't work well if you have stations
- * associated to two different APs because curbssid
- * is just the last AP that any of the stations associated
- * with.
- */
- return; /* not from our current AP */
- }
-
sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
if (sc->ps_flags & PS_BEACON_SYNC) {
@@ -596,7 +601,6 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
ath_dbg(common, ATH_DBG_PS,
"Reconfigure Beacon timers based on timestamp from the AP\n");
ath_set_beacon(sc);
- sc->ps_flags &= ~PS_TSFOOR_SYNC;
}
if (ath_beacon_dtim_pending_cab(skb)) {
@@ -625,7 +629,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
}
}
-static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
+static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
{
struct ieee80211_hdr *hdr;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -634,7 +638,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
/* Process Beacon and CAB receive in PS state */
if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc))
- && ieee80211_is_beacon(hdr->frame_control))
+ && mybeacon)
ath_rx_ps_beacon(sc, skb);
else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
(ieee80211_is_data(hdr->frame_control) ||
@@ -744,6 +748,9 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
}
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+ if (bf == sc->rx.buf_hold)
+ return NULL;
+
ds = bf->bf_desc;
/*
@@ -757,7 +764,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
- ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
+ ret = ath9k_hw_rxprocdesc(ah, ds, rs);
if (ret == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
@@ -783,11 +790,12 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
*/
tds = tbf->bf_desc;
- ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
+ ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
}
+ list_del(&bf->list);
if (!bf->bf_mpdu)
return bf;
@@ -810,16 +818,31 @@ static bool ath9k_rx_accept(struct ath_common *common,
struct ath_rx_status *rx_stats,
bool *decrypt_error)
{
-#define is_mc_or_valid_tkip_keyix ((is_mc || \
- (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
- test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
-
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ bool is_mc, is_valid_tkip, strip_mic, mic_error;
struct ath_hw *ah = common->ah;
__le16 fc;
u8 rx_status_len = ah->caps.rx_status_len;
fc = hdr->frame_control;
+ is_mc = !!is_multicast_ether_addr(hdr->addr1);
+ is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
+ test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+ strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
+ !(rx_stats->rs_status &
+ (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_KEYMISS));
+
+ /*
+ * Key miss events are only relevant for pairwise keys where the
+ * descriptor does contain a valid key index. This has been observed
+ * mostly with CCMP encryption.
+ */
+ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
+ !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
+ rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
if (!rx_stats->rs_datalen)
return false;
/*
@@ -834,6 +857,11 @@ static bool ath9k_rx_accept(struct ath_common *common,
if (rx_stats->rs_more)
return true;
+ mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
+ !ieee80211_has_morefrags(fc) &&
+ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+ (rx_stats->rs_status & ATH9K_RXERR_MIC);
+
/*
* The rx_stats->rs_status will not be set until the end of the
* chained descriptors so it can be ignored if rs_more is set. The
@@ -841,47 +869,47 @@ static bool ath9k_rx_accept(struct ath_common *common,
* descriptors.
*/
if (rx_stats->rs_status != 0) {
- if (rx_stats->rs_status & ATH9K_RXERR_CRC)
+ u8 status_mask;
+
+ if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+ mic_error = false;
+ }
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
return false;
- if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
+ if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
+ (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
*decrypt_error = true;
- } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
- bool is_mc;
- /*
- * The MIC error bit is only valid if the frame
- * is not a control frame or fragment, and it was
- * decrypted using a valid TKIP key.
- */
- is_mc = !!is_multicast_ether_addr(hdr->addr1);
-
- if (!ieee80211_is_ctl(fc) &&
- !ieee80211_has_morefrags(fc) &&
- !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
- is_mc_or_valid_tkip_keyix)
- rxs->flag |= RX_FLAG_MMIC_ERROR;
- else
- rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+ mic_error = false;
}
+
/*
* Reject error frames with the exception of
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
- if (ah->is_monitoring) {
- if (rx_stats->rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
- ATH9K_RXERR_CRC))
- return false;
- } else {
- if (rx_stats->rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
- return false;
- }
- }
+ status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_KEYMISS;
+
+ if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
+ status_mask |= ATH9K_RXERR_CRC;
+
+ if (rx_stats->rs_status & ~status_mask)
+ return false;
}
+
+ /*
+ * For unicast frames the MIC error bit can have false positives,
+ * so all MIC error reports need to be validated in software.
+ * False negatives are not common, so skip software verification
+ * if the hardware considers the MIC valid.
+ */
+ if (strip_mic)
+ rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+ else if (is_mc && mic_error)
+ rxs->flag |= RX_FLAG_MMIC_ERROR;
+
return true;
}
@@ -924,7 +952,7 @@ static int ath9k_process_rate(struct ath_common *common,
* No valid hardware bitrate found -- we should not get here
* because hardware has already validated this frame as OK.
*/
- ath_dbg(common, ATH_DBG_XMIT,
+ ath_dbg(common, ATH_DBG_ANY,
"unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate);
@@ -939,23 +967,12 @@ static void ath9k_process_rssi(struct ath_common *common,
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = common->ah;
int last_rssi;
- __le16 fc;
- if ((ah->opmode != NL80211_IFTYPE_STATION) &&
- (ah->opmode != NL80211_IFTYPE_ADHOC))
+ if (!rx_stats->is_mybeacon ||
+ ((ah->opmode != NL80211_IFTYPE_STATION) &&
+ (ah->opmode != NL80211_IFTYPE_ADHOC)))
return;
- fc = hdr->frame_control;
- if (!ieee80211_is_beacon(fc) ||
- compare_ether_addr(hdr->addr3, common->curbssid)) {
- /* TODO: This doesn't work well if you have stations
- * associated to two different APs because curbssid
- * is just the last AP that any of the stations associated
- * with.
- */
- return;
- }
-
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
@@ -982,6 +999,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error)
{
+ struct ath_hw *ah = common->ah;
+
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
/*
@@ -1002,7 +1021,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
rx_status->band = hw->conf.channel->band;
rx_status->freq = hw->conf.channel->center_freq;
- rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
+ rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
@@ -1072,39 +1091,39 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
antcomb->rssi_lna1 = main_rssi_avg;
switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
@@ -1321,65 +1340,148 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
/* Adjust the fast_div_bias based on main and alt lna conf */
switch ((ant_conf->main_lna_conf << 4) |
ant_conf->alt_lna_conf) {
- case (0x01): /* A-B LNA2 */
+ case 0x01: /* A-B LNA2 */
ant_conf->fast_div_bias = 0x3b;
break;
- case (0x02): /* A-B LNA1 */
+ case 0x02: /* A-B LNA1 */
ant_conf->fast_div_bias = 0x3d;
break;
- case (0x03): /* A-B A+B */
+ case 0x03: /* A-B A+B */
ant_conf->fast_div_bias = 0x1;
break;
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
ant_conf->fast_div_bias = 0x7;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
ant_conf->fast_div_bias = 0x2;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
ant_conf->fast_div_bias = 0x7;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
ant_conf->fast_div_bias = 0x6;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
ant_conf->fast_div_bias = 0x0;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
ant_conf->fast_div_bias = 0x6;
break;
- case (0x30): /* A+B A-B */
+ case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
break;
- case (0x31): /* A+B LNA2 */
+ case 0x31: /* A+B LNA2 */
ant_conf->fast_div_bias = 0x3b;
break;
- case (0x32): /* A+B LNA1 */
+ case 0x32: /* A+B LNA1 */
ant_conf->fast_div_bias = 0x3d;
break;
default:
break;
}
+ } else if (ant_conf->div_group == 1) {
+ /* Adjust the fast_div_bias based on main and alt_lna_conf */
+ switch ((ant_conf->main_lna_conf << 4) |
+ ant_conf->alt_lna_conf) {
+ case 0x01: /* A-B LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x02: /* A-B LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x03: /* A-B A+B */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x10: /* LNA2 A-B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x12: /* LNA2 LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x13: /* LNA2 A+B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x20: /* LNA1 A-B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x21: /* LNA1 LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x23: /* LNA1 A+B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x30: /* A+B A-B */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x31: /* A+B LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x32: /* A+B LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ default:
+ break;
+ }
} else if (ant_conf->div_group == 2) {
/* Adjust the fast_div_bias based on main and alt_lna_conf */
switch ((ant_conf->main_lna_conf << 4) |
ant_conf->alt_lna_conf) {
- case (0x01): /* A-B LNA2 */
+ case 0x01: /* A-B LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x02): /* A-B LNA1 */
+ case 0x02: /* A-B LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x03): /* A-B A+B */
+ case 0x03: /* A-B A+B */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1388,12 +1490,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1402,7 +1504,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1411,12 +1513,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1425,17 +1527,17 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x30): /* A+B A-B */
+ case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x31): /* A+B LNA2 */
+ case 0x31: /* A+B LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x32): /* A+B LNA1 */
+ case 0x32: /* A+B LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
@@ -1443,9 +1545,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
default:
break;
}
-
}
-
}
/* Antenna diversity and combining */
@@ -1689,11 +1789,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
struct ieee80211_rx_status *rxs;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- /*
- * The hw can technically differ from common->hw when using ath9k
- * virtual wiphy so to account for that we iterate over the active
- * wiphys and find the appropriate wiphy and therefore hw.
- */
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_hdr *hdr;
int retval;
@@ -1747,6 +1842,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
rxs = IEEE80211_SKB_RXCB(hdr_skb);
+ if (ieee80211_is_beacon(hdr->frame_control) &&
+ !compare_ether_addr(hdr->addr3, common->curbssid))
+ rs.is_mybeacon = true;
+ else
+ rs.is_mybeacon = false;
ath_debug_stat_rx(sc, &rs);
@@ -1754,7 +1854,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
* If we're asked to flush receive queue, directly
* chain it back at the queue without processing it.
*/
- if (flush)
+ if (sc->sc_flags & SC_OP_RXFLUSH)
goto requeue_drop_frag;
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
@@ -1853,16 +1953,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.rxotherant = 0;
}
+ if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
+ skb_trim(skb, skb->len - 8);
+
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA)) ||
- ath9k_check_auto_sleep(sc))
- ath_rx_ps(sc, skb);
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA)) ||
+ ath9k_check_auto_sleep(sc))
+ ath_rx_ps(sc, skb, rs.is_mybeacon);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
- if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
ath_ant_comb_scan(sc, &rs);
ieee80211_rx(hw, skb);
@@ -1873,17 +1976,24 @@ requeue_drop_frag:
sc->rx.frag = NULL;
}
requeue:
+ list_add_tail(&bf->list, &sc->rx.rxbuf);
+ if (flush)
+ continue;
+
if (edma) {
- list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
} else {
- list_move_tail(&bf->list, &sc->rx.rxbuf);
- ath_rx_buf_link(sc, bf);
+ ath_rx_buf_relink(sc, bf);
ath9k_hw_rxena(ah);
}
} while (1);
spin_unlock_bh(&sc->rx.rxbuflock);
+ if (!(ah->imask & ATH9K_INT_RXEOL)) {
+ ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+ ath9k_hw_set_interrupts(ah);
+ }
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index c18ee99..8fcb7e9 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -600,7 +600,6 @@
#define AR_D_GBL_IFS_SIFS 0x1030
#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
-#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
#define AR_D_TXBLK_BASE 0x1038
@@ -616,12 +615,11 @@
#define AR_D_GBL_IFS_SLOT 0x1070
#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
-#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420
#define AR_D_GBL_IFS_EIFS 0x10b0
#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
-#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB
+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363
#define AR_D_GBL_IFS_MISC 0x10f0
#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
@@ -788,18 +786,23 @@
#define AR_SREV_REVISION_9271_11 1
#define AR_SREV_VERSION_9300 0x1c0
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9330 0x200
+#define AR_SREV_REVISION_9330_10 0
+#define AR_SREV_REVISION_9330_11 1
+#define AR_SREV_REVISION_9330_12 2
#define AR_SREV_VERSION_9485 0x240
#define AR_SREV_REVISION_9485_10 0
#define AR_SREV_REVISION_9485_11 1
#define AR_SREV_VERSION_9340 0x300
+#define AR_SREV_VERSION_9580 0x1C0
+#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
+#define AR_SREV_VERSION_9462 0x280
+#define AR_SREV_REVISION_9462_10 0
+#define AR_SREV_REVISION_9462_20 2
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
-#define AR_SREV_5416_20_OR_LATER(_ah) \
- (((AR_SREV_5416(_ah)) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
- ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
#define AR_SREV_5416_22_OR_LATER(_ah) \
(((AR_SREV_5416(_ah)) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
@@ -862,6 +865,18 @@
#define AR_SREV_9300_20_OR_LATER(_ah) \
((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
+#define AR_SREV_9330(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
+#define AR_SREV_9330_10(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
+#define AR_SREV_9330_11(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
+#define AR_SREV_9330_12(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
#define AR_SREV_9485(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
#define AR_SREV_9485_10(_ah) \
@@ -880,6 +895,33 @@
(AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
+#define AR_SREV_9462(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
+
+#define AR_SREV_9462_10(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_10))
+
+#define AR_SREV_9462_20(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
+
+#define AR_SREV_9462_20_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
+
+#define AR_SREV_9580(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
+
+#define AR_SREV_9580_10(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10))
+
+/* NOTE: When adding chips newer than Peacock, add chip check here */
+#define AR_SREV_9580_10_OR_LATER(_ah) \
+ (AR_SREV_9580(_ah))
+
enum ath_usb_dev {
AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
@@ -1104,7 +1146,7 @@ enum {
#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
#define AR_ENT_OTP 0x40d8
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
-#define AR_ENT_OTP_MPSD 0x00800000
+#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000
#define AR_CH0_BB_DPLL1 0x16180
#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000
@@ -1461,7 +1503,6 @@ enum {
#define AR_TIME_OUT_ACK_S 0
#define AR_TIME_OUT_CTS 0x3FFF0000
#define AR_TIME_OUT_CTS_S 16
-#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56
#define AR_RSSI_THR 0x8018
#define AR_RSSI_THR_MASK 0x000000FF
@@ -1477,7 +1518,7 @@ enum {
#define AR_USEC_TX_LAT_S 14
#define AR_USEC_RX_LAT 0x1F800000
#define AR_USEC_RX_LAT_S 23
-#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074
+#define AR_USEC_ASYNC_FIFO 0x12E00074
#define AR_RESET_TSF 0x8020
#define AR_RESET_TSF_ONCE 0x01000000
@@ -1752,6 +1793,7 @@ enum {
#define AR_TXOP_12_15 0x81fc
#define AR_NEXT_NDP2_TIMER 0x8180
+#define AR_GEN_TIMER_BANK_1_LEN 8
#define AR_FIRST_NDP_TIMER 7
#define AR_NDP2_PERIOD 0x81a0
#define AR_NDP2_TIMER_MODE 0x81c0
@@ -1840,9 +1882,10 @@ enum {
#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
-#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
-#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
-#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+#define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8
#define AR_AES_MUTE_MASK0 0x805c
@@ -1862,29 +1905,6 @@ enum {
#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2))
-#define AR_KEYTABLE_0 0x8800
-#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
-#define AR_KEY_CACHE_SIZE 128
-#define AR_RSVD_KEYTABLE_ENTRIES 4
-#define AR_KEY_TYPE 0x00000007
-#define AR_KEYTABLE_TYPE_40 0x00000000
-#define AR_KEYTABLE_TYPE_104 0x00000001
-#define AR_KEYTABLE_TYPE_128 0x00000003
-#define AR_KEYTABLE_TYPE_TKIP 0x00000004
-#define AR_KEYTABLE_TYPE_AES 0x00000005
-#define AR_KEYTABLE_TYPE_CCM 0x00000006
-#define AR_KEYTABLE_TYPE_CLR 0x00000007
-#define AR_KEYTABLE_ANT 0x00000008
-#define AR_KEYTABLE_VALID 0x00008000
-#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
-#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
-#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
-#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
-#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
-#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
-#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
-#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
-
#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */
@@ -1913,7 +1933,42 @@ enum {
#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */
#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */
#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */
+#define AR_PHY_AGC_CONTROL_PKDET_CAL 0x00100000
#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0
#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6
+/* MCI Registers */
+#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6
+#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
+#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12
+#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \
+ AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
+
+
#endif
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index e1f1971..a0ba5ac 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#include "ar9003_mac.h"
@@ -47,19 +48,24 @@ static u16 bits_per_symbol[][2] = {
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head);
+ struct ath_atx_tid *tid, struct sk_buff *skb);
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+ int tx_flags, struct ath_txq *txq);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head);
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
+ struct list_head *head, bool internal);
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad,
- int txok, bool update_rc);
+ int txok);
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
int seqno);
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct sk_buff *skb,
+ bool dequeue);
enum {
MCS_HT20,
@@ -128,7 +134,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
spin_lock_bh(&txq->axq_lock);
tid->paused = false;
- if (list_empty(&tid->buf_q))
+ if (skb_queue_empty(&tid->buf_q))
goto unlock;
ath_tx_queue_tid(txq, tid);
@@ -148,6 +154,7 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
+ struct sk_buff *skb;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
@@ -158,17 +165,17 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
memset(&ts, 0, sizeof(ts));
spin_lock_bh(&txq->axq_lock);
- while (!list_empty(&tid->buf_q)) {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- list_move_tail(&bf->list, &bf_head);
+ while ((skb = __skb_dequeue(&tid->buf_q))) {
+ fi = get_frame_info(skb);
+ bf = fi->bf;
spin_unlock_bh(&txq->axq_lock);
- fi = get_frame_info(bf->bf_mpdu);
- if (fi->retries) {
- ath_tx_update_baw(sc, tid, fi->seqno);
+ if (bf && fi->retries) {
+ list_add_tail(&bf->list, &bf_head);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
} else {
- ath_tx_send_normal(sc, txq, NULL, &bf_head);
+ ath_tx_send_normal(sc, txq, NULL, skb);
}
spin_lock_bh(&txq->axq_lock);
}
@@ -218,6 +225,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid)
{
+ struct sk_buff *skb;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
@@ -226,16 +234,21 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
- for (;;) {
- if (list_empty(&tid->buf_q))
- break;
+ while ((skb = __skb_dequeue(&tid->buf_q))) {
+ fi = get_frame_info(skb);
+ bf = fi->bf;
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- list_move_tail(&bf->list, &bf_head);
+ if (!bf) {
+ spin_unlock(&txq->axq_lock);
+ ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
+ spin_lock(&txq->axq_lock);
+ continue;
+ }
+
+ list_add_tail(&bf->list, &bf_head);
- fi = get_frame_info(bf->bf_mpdu);
if (fi->retries)
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
@@ -250,6 +263,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
{
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ath_buf *bf = fi->bf;
struct ieee80211_hdr *hdr;
TX_STAT_INC(txq->axq_qnum, a_retries);
@@ -258,6 +272,8 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
hdr = (struct ieee80211_hdr *)skb->data;
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+ sizeof(*hdr), DMA_TO_DEVICE);
}
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
@@ -326,7 +342,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
while (bf) {
fi = get_frame_info(bf->bf_mpdu);
- ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
+ ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
(*nframes)++;
if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
@@ -349,16 +365,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ieee80211_tx_info *tx_info;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
- struct list_head bf_head, bf_pending;
+ struct list_head bf_head;
+ struct sk_buff_head bf_pending;
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
- bool rc_update = true;
+ bool rc_update = true, isba;
struct ieee80211_tx_rate rates[4];
struct ath_frame_info *fi;
int nframes;
u8 tidno;
- bool clear_filter;
+ bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -377,12 +394,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
while (bf) {
bf_next = bf->bf_next;
- bf->bf_state.bf_type |= BUF_XRETRY;
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
- !bf->bf_stale || bf_next != NULL)
+ if (!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
- ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0);
@@ -394,13 +408,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
an = (struct ath_node *)sta->drv_priv;
tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
tid = ATH_AN_2_TID(an, tidno);
+ isba = ts->ts_flags & ATH9K_TX_BA;
/*
* The hardware occasionally sends a tx status for the wrong TID.
* In this case, the BA status cannot be considered valid and all
* subframes need to be retransmitted
+ *
+ * Only BlockAcks have a TID and therefore normal Acks cannot be
+ * checked
*/
- if (tidno != ts->tid)
+ if (isba && tidno != ts->tid)
txok = false;
isaggr = bf_isaggr(bf);
@@ -423,11 +441,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
}
- INIT_LIST_HEAD(&bf_pending);
- INIT_LIST_HEAD(&bf_head);
+ __skb_queue_head_init(&bf_pending);
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
+ u16 seqno = bf->bf_state.seqno;
+
txfail = txpending = sendbar = 0;
bf_next = bf->bf_next;
@@ -435,7 +454,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
fi = get_frame_info(skb);
- if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
+ if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
/* transmit completion, subframe is
* acked by block ack */
acked_cnt++;
@@ -449,35 +468,28 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* the un-acked sub-frames
*/
txfail = 1;
+ } else if (flush) {
+ txpending = 1;
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
- if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
- !an->sleeping)
+ if (txok || !an->sleeping)
ath_tx_set_retry(sc, txq, bf->bf_mpdu);
- clear_filter = true;
txpending = 1;
} else {
- bf->bf_state.bf_type |= BUF_XRETRY;
txfail = 1;
sendbar = 1;
txfail_cnt++;
}
}
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
- bf_next == NULL) {
- /*
- * Make sure the last desc is reclaimed if it
- * not a holding desc.
- */
- if (!bf_last->bf_stale)
- list_move_tail(&bf->list, &bf_head);
- else
- INIT_LIST_HEAD(&bf_head);
- } else {
- BUG_ON(list_empty(bf_q));
+ /*
+ * Make sure the last desc is reclaimed if it
+ * not a holding desc.
+ */
+ INIT_LIST_HEAD(&bf_head);
+ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
+ bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
- }
if (!txpending || (tid->state & AGGR_CLEANUP)) {
/*
@@ -485,22 +497,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* block-ack window
*/
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
+ ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
rc_update = false;
- } else {
- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
}
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
!txfail, sendbar);
} else {
/* retry the un-acked ones */
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
@@ -513,29 +522,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
- bf->bf_state.bf_type |=
- BUF_XRETRY;
- ath_tx_rc_status(sc, bf, ts, nframes,
- nbad, 0, false);
ath_tx_complete_buf(sc, bf, txq,
&bf_head,
- ts, 0, 0);
+ ts, 0,
+ !flush);
break;
}
- ath9k_hw_cleartxdesc(sc->sc_ah,
- tbf->bf_desc);
- list_add_tail(&tbf->list, &bf_head);
- } else {
- /*
- * Clear descriptor status words for
- * software retry
- */
- ath9k_hw_cleartxdesc(sc->sc_ah,
- bf->bf_desc);
+ fi->bf = tbf;
}
}
@@ -543,22 +540,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* Put this buffer to the temporary pending
* queue to retain ordering
*/
- list_splice_tail_init(&bf_head, &bf_pending);
+ __skb_queue_tail(&bf_pending, skb);
}
bf = bf_next;
}
/* prepend un-acked frames to the beginning of the pending frame queue */
- if (!list_empty(&bf_pending)) {
+ if (!skb_queue_empty(&bf_pending)) {
if (an->sleeping)
- ieee80211_sta_set_tim(sta);
+ ieee80211_sta_set_buffered(sta, tid->tidno, true);
spin_lock_bh(&txq->axq_lock);
- if (clear_filter)
- tid->ac->clear_ps_filter = true;
- list_splice(&bf_pending, &tid->buf_q);
- ath_tx_queue_tid(txq, tid);
+ skb_queue_splice(&bf_pending, &tid->buf_q);
+ if (!an->sleeping) {
+ ath_tx_queue_tid(txq, tid);
+
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ tid->ac->clear_ps_filter = true;
+ }
spin_unlock_bh(&txq->axq_lock);
}
@@ -574,10 +574,31 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_unlock();
if (needreset) {
- spin_unlock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, false);
- spin_lock_bh(&sc->sc_pcu_lock);
+ RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
+}
+
+static bool ath_lookup_legacy(struct ath_buf *bf)
+{
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *rates;
+ int i;
+
+ skb = bf->bf_mpdu;
+ tx_info = IEEE80211_SKB_CB(skb);
+ rates = tx_info->control.rates;
+
+ for (i = 0; i < 4; i++) {
+ if (!rates[i].count || rates[i].idx < 0)
+ break;
+
+ if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
+ return true;
}
+
+ return false;
}
static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -653,8 +674,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
* meet the minimum required mpdudensity.
*/
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf, u16 frmlen)
+ struct ath_buf *bf, u16 frmlen,
+ bool first_subfrm)
{
+#define FIRST_DESC_NDELIMS 60
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
@@ -677,6 +700,14 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
ndelim += ATH_AGGR_ENCRYPTDELIM;
/*
+ * Add delimiter when using RTS/CTS with aggregation
+ * and non enterprise AR9003 card
+ */
+ if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
+ (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
+ ndelim = max(ndelim, FIRST_DESC_NDELIMS);
+
+ /*
* Convert desired mpdu density from microeconds to bytes based
* on highest rate in rate series (i.e. first rate) to determine
* required minimum length for subframe. Take into account
@@ -721,22 +752,33 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
int *aggr_len)
{
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
- struct ath_buf *bf, *bf_first, *bf_prev = NULL;
+ struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
int rl = 0, nframes = 0, ndelim, prev_al = 0;
u16 aggr_limit = 0, al = 0, bpad = 0,
al_delta, h_baw = tid->baw_size / 2;
enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi;
-
- bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
+ struct sk_buff *skb;
+ u16 seqno;
do {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- fi = get_frame_info(bf->bf_mpdu);
+ skb = skb_peek(&tid->buf_q);
+ fi = get_frame_info(skb);
+ bf = fi->bf;
+ if (!fi->bf)
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
+
+ if (!bf)
+ continue;
+
+ bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
+ seqno = bf->bf_state.seqno;
+ if (!bf_first)
+ bf_first = bf;
/* do not step over block-ack window */
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
status = ATH_AGGR_BAW_CLOSED;
break;
}
@@ -750,14 +792,14 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
if (nframes &&
- (aggr_limit < (al + bpad + al_delta + prev_al))) {
+ ((aggr_limit < (al + bpad + al_delta + prev_al)) ||
+ ath_lookup_legacy(bf))) {
status = ATH_AGGR_LIMITED;
break;
}
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
- if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
- !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
+ if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
break;
/* do not exceed subframe limit */
@@ -765,7 +807,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
status = ATH_AGGR_LIMITED;
break;
}
- nframes++;
/* add padding for previous frame to aggregation length */
al += bpad + al_delta;
@@ -774,25 +815,26 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* Get the delimiters needed to meet the MPDU
* density for this node.
*/
- ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
+ ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
+ !nframes);
bpad = PADBYTES(al_delta) + (ndelim << 2);
+ nframes++;
bf->bf_next = NULL;
- ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
/* link buffers of this frame to the aggregate */
if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
- ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
- list_move_tail(&bf->list, bf_q);
- if (bf_prev) {
+ ath_tx_addto_baw(sc, tid, seqno);
+ bf->bf_state.ndelim = ndelim;
+
+ __skb_unlink(skb, &tid->buf_q);
+ list_add_tail(&bf->list, bf_q);
+ if (bf_prev)
bf_prev->bf_next = bf;
- ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
- bf->bf_daddr);
- }
+
bf_prev = bf;
- } while (!list_empty(&tid->buf_q));
+ } while (!skb_queue_empty(&tid->buf_q));
*aggr_len = al;
@@ -800,17 +842,236 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
#undef PADBYTES
}
+/*
+ * rix - rate index
+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+ * width - 0 for 20 MHz, 1 for 40 MHz
+ * half_gi - to use 4us v/s 3.6 us for symbol time
+ */
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+ int width, int half_gi, bool shortPreamble)
+{
+ u32 nbits, nsymbits, duration, nsymbols;
+ int streams;
+
+ /* find number of symbols: PLCP + data */
+ streams = HT_RC_2_STREAMS(rix);
+ nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+ nsymbits = bits_per_symbol[rix % 8][width] * streams;
+ nsymbols = (nbits + nsymbits - 1) / nsymbits;
+
+ if (!half_gi)
+ duration = SYMBOL_TIME(nsymbols);
+ else
+ duration = SYMBOL_TIME_HALFGI(nsymbols);
+
+ /* addup duration for legacy/ht training and signal fields */
+ duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
+ return duration;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_info *info, int len)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *rates;
+ const struct ieee80211_rate *rate;
+ struct ieee80211_hdr *hdr;
+ int i;
+ u8 rix = 0;
+
+ skb = bf->bf_mpdu;
+ tx_info = IEEE80211_SKB_CB(skb);
+ rates = tx_info->control.rates;
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ /* set dur_update_en for l-sig computation except for PS-Poll frames */
+ info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
+
+ /*
+ * We check if Short Preamble is needed for the CTS rate by
+ * checking the BSS's global flag.
+ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+ */
+ rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
+ info->rtscts_rate = rate->hw_value;
+ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+ info->rtscts_rate |= rate->hw_value_short;
+
+ for (i = 0; i < 4; i++) {
+ bool is_40, is_sgi, is_sp;
+ int phy;
+
+ if (!rates[i].count || (rates[i].idx < 0))
+ continue;
+
+ rix = rates[i].idx;
+ info->rates[i].Tries = rates[i].count;
+
+ if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+ info->flags |= ATH9K_TXDESC_RTSENA;
+ } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+ info->flags |= ATH9K_TXDESC_CTSENA;
+ }
+
+ if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
+ if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+
+ is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
+ is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
+ is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+
+ if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+ /* MCS rates */
+ info->rates[i].Rate = rix | 0x80;
+ info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+ ah->txchainmask, info->rates[i].Rate);
+ info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
+ is_40, is_sgi, is_sp);
+ if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+ continue;
+ }
+
+ /* legacy rates */
+ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
+ if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
+ !(rate->flags & IEEE80211_RATE_ERP_G))
+ phy = WLAN_RC_PHY_CCK;
+ else
+ phy = WLAN_RC_PHY_OFDM;
+
+ info->rates[i].Rate = rate->hw_value;
+ if (rate->hw_value_short) {
+ if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ info->rates[i].Rate |= rate->hw_value_short;
+ } else {
+ is_sp = false;
+ }
+
+ if (bf->bf_state.bfs_paprd)
+ info->rates[i].ChSel = ah->txchainmask;
+ else
+ info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+ ah->txchainmask, info->rates[i].Rate);
+
+ info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+ phy, rate->bitrate * 100, len, rix, is_sp);
+ }
+
+ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+ if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
+ info->flags &= ~ATH9K_TXDESC_RTSENA;
+
+ /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+ if (info->flags & ATH9K_TXDESC_RTSENA)
+ info->flags &= ~ATH9K_TXDESC_CTSENA;
+}
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr;
+ enum ath9k_pkt_type htype;
+ __le16 fc;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = hdr->frame_control;
+
+ if (ieee80211_is_beacon(fc))
+ htype = ATH9K_PKT_TYPE_BEACON;
+ else if (ieee80211_is_probe_resp(fc))
+ htype = ATH9K_PKT_TYPE_PROBE_RESP;
+ else if (ieee80211_is_atim(fc))
+ htype = ATH9K_PKT_TYPE_ATIM;
+ else if (ieee80211_is_pspoll(fc))
+ htype = ATH9K_PKT_TYPE_PSPOLL;
+ else
+ htype = ATH9K_PKT_TYPE_NORMAL;
+
+ return htype;
+}
+
+static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq, int len)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+ struct ath_buf *bf_first = bf;
+ struct ath_tx_info info;
+ bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
+
+ memset(&info, 0, sizeof(info));
+ info.is_first = true;
+ info.is_last = true;
+ info.txpower = MAX_RATE_POWER;
+ info.qcu = txq->axq_qnum;
+
+ info.flags = ATH9K_TXDESC_INTREQ;
+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+ info.flags |= ATH9K_TXDESC_NOACK;
+ if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
+ info.flags |= ATH9K_TXDESC_LDPC;
+
+ ath_buf_set_rate(sc, bf, &info, len);
+
+ if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+ info.flags |= ATH9K_TXDESC_CLRDMASK;
+
+ if (bf->bf_state.bfs_paprd)
+ info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
+
+
+ while (bf) {
+ struct sk_buff *skb = bf->bf_mpdu;
+ struct ath_frame_info *fi = get_frame_info(skb);
+
+ info.type = get_hw_packet_type(skb);
+ if (bf->bf_next)
+ info.link = bf->bf_next->bf_daddr;
+ else
+ info.link = 0;
+
+ info.buf_addr[0] = bf->bf_buf_addr;
+ info.buf_len[0] = skb->len;
+ info.pkt_len = fi->framelen;
+ info.keyix = fi->keyix;
+ info.keytype = fi->keytype;
+
+ if (aggr) {
+ if (bf == bf_first)
+ info.aggr = AGGR_BUF_FIRST;
+ else if (!bf->bf_next)
+ info.aggr = AGGR_BUF_LAST;
+ else
+ info.aggr = AGGR_BUF_MIDDLE;
+
+ info.ndelim = bf->bf_state.ndelim;
+ info.aggr_len = len;
+ }
+
+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+ bf = bf->bf_next;
+ }
+}
+
static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid)
{
struct ath_buf *bf;
enum ATH_AGGR_STATUS status;
- struct ath_frame_info *fi;
+ struct ieee80211_tx_info *tx_info;
struct list_head bf_q;
int aggr_len;
do {
- if (list_empty(&tid->buf_q))
+ if (skb_queue_empty(&tid->buf_q))
return;
INIT_LIST_HEAD(&bf_q);
@@ -826,34 +1087,25 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf = list_first_entry(&bf_q, struct ath_buf, list);
bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
+ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
if (tid->ac->clear_ps_filter) {
tid->ac->clear_ps_filter = false;
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+ } else {
+ tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
}
/* if only one frame, send as non-aggregate */
if (bf == bf->bf_lastbf) {
- fi = get_frame_info(bf->bf_mpdu);
-
- bf->bf_state.bf_type &= ~BUF_AGGR;
- ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
- ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, &bf_q);
- continue;
+ aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
+ bf->bf_state.bf_type = BUF_AMPDU;
+ } else {
+ TX_STAT_INC(txq->axq_qnum, a_aggr);
}
- /* setup first desc of aggregate */
- bf->bf_state.bf_type |= BUF_AGGR;
- ath_buf_set_rate(sc, bf, aggr_len);
- ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
-
- /* anchor last desc of aggregate */
- ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
-
- ath_tx_txqaddbuf(sc, txq, &bf_q);
- TX_STAT_INC(txq->axq_qnum, a_aggr);
-
+ ath_tx_fill_desc(sc, bf, txq, aggr_len);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, false);
} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED);
}
@@ -912,27 +1164,29 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
ath_tx_flush_tid(sc, txtid);
}
-bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
+void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+ struct ath_node *an)
{
struct ath_atx_tid *tid;
struct ath_atx_ac *ac;
struct ath_txq *txq;
- bool buffered = false;
+ bool buffered;
int tidno;
for (tidno = 0, tid = &an->tid[tidno];
tidno < WME_NUM_TID; tidno++, tid++) {
- if (!tid->sched)
- continue;
-
ac = tid->ac;
txq = ac->txq;
spin_lock_bh(&txq->axq_lock);
- if (!list_empty(&tid->buf_q))
- buffered = true;
+ if (!tid->sched) {
+ spin_unlock_bh(&txq->axq_lock);
+ continue;
+ }
+
+ buffered = !skb_queue_empty(&tid->buf_q);
tid->sched = false;
list_del(&tid->list);
@@ -943,9 +1197,9 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
}
spin_unlock_bh(&txq->axq_lock);
- }
- return buffered;
+ ieee80211_sta_set_buffered(sta, tidno, buffered);
+ }
}
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
@@ -964,7 +1218,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
spin_lock_bh(&txq->axq_lock);
ac->clear_ps_filter = true;
- if (!list_empty(&tid->buf_q) && !tid->paused) {
+ if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
ath_tx_queue_tid(txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1014,7 +1268,6 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
{
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_tx_queue_info qi;
static const int subtype_txq_to_hwq[] = {
[WME_AC_BE] = ATH_TXQ_AC_BE,
@@ -1064,12 +1317,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
*/
return NULL;
}
- if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
- ath_err(common, "qnum %u out of range, max %zu!\n",
- axq_qnum, ARRAY_SIZE(sc->tx.txq));
- ath9k_hw_releasetxqueue(ah, axq_qnum);
- return NULL;
- }
if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
struct ath_txq *txq = &sc->tx.txq[axq_qnum];
@@ -1087,7 +1334,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
txq->txq_headidx = txq->txq_tailidx = 0;
for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
INIT_LIST_HEAD(&txq->txq_fifo[i]);
- INIT_LIST_HEAD(&txq->txq_fifo_pending);
}
return &sc->tx.txq[axq_qnum];
}
@@ -1144,7 +1390,7 @@ int ath_cabq_update(struct ath_softc *sc)
else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
- qi.tqi_readyTime = (cur_conf->beacon_interval *
+ qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) *
sc->config.cabqReadytime) / 100;
ath_txq_update(sc, qnum, &qi);
@@ -1157,108 +1403,76 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
}
-/*
- * Drain a given TX queue (could be Beacon or Data)
- *
- * This assumes output has been stopped and
- * we do not need to block ath_tx_tasklet.
- */
-void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
+ struct list_head *list, bool retry_tx)
+ __releases(txq->axq_lock)
+ __acquires(txq->axq_lock)
{
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
struct ath_tx_status ts;
memset(&ts, 0, sizeof(ts));
+ ts.ts_status = ATH9K_TX_FLUSH;
INIT_LIST_HEAD(&bf_head);
- for (;;) {
- spin_lock_bh(&txq->axq_lock);
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
- txq->txq_headidx = txq->txq_tailidx = 0;
- spin_unlock_bh(&txq->axq_lock);
- break;
- } else {
- bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
- struct ath_buf, list);
- }
- } else {
- if (list_empty(&txq->axq_q)) {
- txq->axq_link = NULL;
- spin_unlock_bh(&txq->axq_lock);
- break;
- }
- bf = list_first_entry(&txq->axq_q, struct ath_buf,
- list);
+ while (!list_empty(list)) {
+ bf = list_first_entry(list, struct ath_buf, list);
- if (bf->bf_stale) {
- list_del(&bf->list);
- spin_unlock_bh(&txq->axq_lock);
+ if (bf->bf_stale) {
+ list_del(&bf->list);
- ath_tx_return_buffer(sc, bf);
- continue;
- }
+ ath_tx_return_buffer(sc, bf);
+ continue;
}
lastbf = bf->bf_lastbf;
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- list_cut_position(&bf_head,
- &txq->txq_fifo[txq->txq_tailidx],
- &lastbf->list);
- INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- } else {
- /* remove ath_buf's of the same mpdu from txq */
- list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
- }
+ list_cut_position(&bf_head, list, &lastbf->list);
txq->axq_depth--;
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
- spin_unlock_bh(&txq->axq_lock);
+ spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
retry_tx);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+ spin_lock_bh(&txq->axq_lock);
}
+}
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+{
spin_lock_bh(&txq->axq_lock);
- txq->axq_tx_inprogress = false;
- spin_unlock_bh(&txq->axq_lock);
-
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- spin_lock_bh(&txq->axq_lock);
- while (!list_empty(&txq->txq_fifo_pending)) {
- bf = list_first_entry(&txq->txq_fifo_pending,
- struct ath_buf, list);
- list_cut_position(&bf_head,
- &txq->txq_fifo_pending,
- &bf->bf_lastbf->list);
- spin_unlock_bh(&txq->axq_lock);
+ int idx = txq->txq_tailidx;
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head,
- &ts, 0, retry_tx);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &ts, 0, 0);
- spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(&txq->txq_fifo[idx])) {
+ ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
+ retry_tx);
+
+ INCR(idx, ATH_TXFIFO_DEPTH);
}
- spin_unlock_bh(&txq->axq_lock);
+ txq->txq_tailidx = idx;
}
+ txq->axq_link = NULL;
+ txq->axq_tx_inprogress = false;
+ ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
+
/* flush any pending frames if aggregation is enabled */
- if (sc->sc_flags & SC_OP_TXAGGR) {
- if (!retry_tx) {
- spin_lock_bh(&txq->axq_lock);
- ath_txq_drain_pending_buffers(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
- }
- }
+ if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
+ ath_txq_drain_pending_buffers(sc, txq);
+
+ spin_unlock_bh(&txq->axq_lock);
}
bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1266,7 +1480,8 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_txq *txq;
- int i, npend = 0;
+ int i;
+ u32 npend = 0;
if (sc->sc_flags & SC_OP_INVALID)
return true;
@@ -1278,11 +1493,12 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
if (!ATH_TXQ_SETUP(sc, i))
continue;
- npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
+ if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
+ npend |= BIT(i);
}
if (npend)
- ath_err(common, "Failed to stop TX DMA!\n");
+ ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (!ATH_TXQ_SETUP(sc, i))
@@ -1315,7 +1531,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
struct ath_atx_ac *ac, *ac_tmp, *last_ac;
struct ath_atx_tid *tid, *last_tid;
- if (list_empty(&txq->axq_acq) ||
+ if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return;
@@ -1342,7 +1558,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
* add tid to round-robin queue if more frames
* are pending for the tid
*/
- if (!list_empty(&tid->buf_q))
+ if (!skb_queue_empty(&tid->buf_q))
ath_tx_queue_tid(txq, tid);
if (tid == last_tid ||
@@ -1372,11 +1588,13 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
* assume the descriptors are already chained together by caller.
*/
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head)
+ struct list_head *head, bool internal)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_buf *bf;
+ struct ath_buf *bf, *bf_last;
+ bool puttxbuf = false;
+ bool edma;
/*
* Insert the frame on the outbound list and
@@ -1386,60 +1604,57 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
if (list_empty(head))
return;
+ edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
bf = list_first_entry(head, struct ath_buf, list);
+ bf_last = list_entry(head->prev, struct ath_buf, list);
ath_dbg(common, ATH_DBG_QUEUE,
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
- list_splice_tail_init(head, &txq->txq_fifo_pending);
- return;
- }
- if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
- ath_dbg(common, ATH_DBG_XMIT,
- "Initializing tx fifo %d which is non-empty\n",
- txq->txq_headidx);
- INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
- list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
+ if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
+ list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
- TX_STAT_INC(txq->axq_qnum, puttxbuf);
- ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
- ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
- txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+ puttxbuf = true;
} else {
list_splice_tail_init(head, &txq->axq_q);
- if (txq->axq_link == NULL) {
- TX_STAT_INC(txq->axq_qnum, puttxbuf);
- ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
- ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
- txq->axq_qnum, ito64(bf->bf_daddr),
- bf->bf_desc);
- } else {
- *txq->axq_link = bf->bf_daddr;
+ if (txq->axq_link) {
+ ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
ath_dbg(common, ATH_DBG_XMIT,
"link[%u] (%p)=%llx (%p)\n",
txq->axq_qnum, txq->axq_link,
ito64(bf->bf_daddr), bf->bf_desc);
- }
- ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
- &txq->axq_link);
+ } else if (!edma)
+ puttxbuf = true;
+
+ txq->axq_link = bf_last->bf_desc;
+ }
+
+ if (puttxbuf) {
+ TX_STAT_INC(txq->axq_qnum, puttxbuf);
+ ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+ ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+ txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+ }
+
+ if (!edma) {
TX_STAT_INC(txq->axq_qnum, txstart);
ath9k_hw_txstart(ah, txq->axq_qnum);
}
- txq->axq_depth++;
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth++;
+
+ if (!internal) {
+ txq->axq_depth++;
+ if (bf_is_ampdu_not_probing(bf))
+ txq->axq_ampdu_depth++;
+ }
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf, struct ath_tx_control *txctl)
+ struct sk_buff *skb, struct ath_tx_control *txctl)
{
- struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+ struct ath_frame_info *fi = get_frame_info(skb);
struct list_head bf_head;
-
- bf->bf_state.bf_type |= BUF_AMPDU;
+ struct ath_buf *bf;
/*
* Do not queue to h/w when any of the following conditions is true:
@@ -1448,42 +1663,55 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
* - seqno is not within block-ack window
* - h/w queue depth exceeds low water mark
*/
- if (!list_empty(&tid->buf_q) || tid->paused ||
- !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
+ if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+ !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
* for aggregation.
*/
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
- list_add_tail(&bf->list, &tid->buf_q);
- ath_tx_queue_tid(txctl->txq, tid);
+ __skb_queue_tail(&tid->buf_q, skb);
+ if (!txctl->an || !txctl->an->sleeping)
+ ath_tx_queue_tid(txctl->txq, tid);
return;
}
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+ if (!bf)
+ return;
+
+ bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
/* Add sub-frame to BAW */
- if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
+ ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
/* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf;
- ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
+ ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
+ ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head)
+ struct ath_atx_tid *tid, struct sk_buff *skb)
{
- struct ath_frame_info *fi;
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct list_head bf_head;
struct ath_buf *bf;
- bf = list_first_entry(bf_head, struct ath_buf, list);
- bf->bf_state.bf_type &= ~BUF_AMPDU;
+ bf = fi->bf;
+ if (!bf)
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
+
+ if (!bf)
+ return;
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
+ bf->bf_state.bf_type = 0;
/* update starting sequence number for subsequent ADDBA request */
if (tid)
@@ -1491,71 +1719,27 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_next = NULL;
bf->bf_lastbf = bf;
- fi = get_frame_info(bf->bf_mpdu);
- ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, bf_head);
+ ath_tx_fill_desc(sc, bf, txq, fi->framelen);
+ ath_tx_txqaddbuf(sc, txq, &bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued);
}
-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr;
- enum ath9k_pkt_type htype;
- __le16 fc;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
-
- if (ieee80211_is_beacon(fc))
- htype = ATH9K_PKT_TYPE_BEACON;
- else if (ieee80211_is_probe_resp(fc))
- htype = ATH9K_PKT_TYPE_PROBE_RESP;
- else if (ieee80211_is_atim(fc))
- htype = ATH9K_PKT_TYPE_ATIM;
- else if (ieee80211_is_pspoll(fc))
- htype = ATH9K_PKT_TYPE_PSPOLL;
- else
- htype = ATH9K_PKT_TYPE_NORMAL;
-
- return htype;
-}
-
static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
int framelen)
{
- struct ath_softc *sc = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = tx_info->control.sta;
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_node *an = NULL;
- struct ath_atx_tid *tid;
enum ath9k_key_type keytype;
- u16 seqno = 0;
- u8 tidno;
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (sta)
an = (struct ath_node *) sta->drv_priv;
- hdr = (struct ieee80211_hdr *)skb->data;
- if (an && ieee80211_is_data_qos(hdr->frame_control) &&
- conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
-
- tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
-
- /*
- * Override seqno set by upper layer with the one
- * in tx aggregation state.
- */
- tid = ATH_AN_2_TID(an, tidno);
- seqno = tid->seq_next;
- hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
- }
-
memset(fi, 0, sizeof(*fi));
if (hw_key)
fi->keyix = hw_key->hw_key_idx;
@@ -1565,199 +1749,51 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype;
fi->framelen = framelen;
- fi->seqno = seqno;
-}
-
-static int setup_tx_flags(struct sk_buff *skb)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- int flags = 0;
-
- flags |= ATH9K_TXDESC_INTREQ;
-
- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
- flags |= ATH9K_TXDESC_NOACK;
-
- if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
- flags |= ATH9K_TXDESC_LDPC;
-
- return flags;
-}
-
-/*
- * rix - rate index
- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
- * width - 0 for 20 MHz, 1 for 40 MHz
- * half_gi - to use 4us v/s 3.6 us for symbol time
- */
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
- int width, int half_gi, bool shortPreamble)
-{
- u32 nbits, nsymbits, duration, nsymbols;
- int streams;
-
- /* find number of symbols: PLCP + data */
- streams = HT_RC_2_STREAMS(rix);
- nbits = (pktlen << 3) + OFDM_PLCP_BITS;
- nsymbits = bits_per_symbol[rix % 8][width] * streams;
- nsymbols = (nbits + nsymbits - 1) / nsymbits;
-
- if (!half_gi)
- duration = SYMBOL_TIME(nsymbols);
- else
- duration = SYMBOL_TIME_HALFGI(nsymbols);
-
- /* addup duration for legacy/ht training and signal fields */
- duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
-
- return duration;
}
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_channel *curchan = ah->curchan;
- if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
- (curchan->channelFlags & CHANNEL_5GHZ) &&
- (chainmask == 0x7) && (rate < 0x90))
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
+ (curchan->channelFlags & CHANNEL_5GHZ) &&
+ (chainmask == 0x7) && (rate < 0x90))
return 0x3;
else
return chainmask;
}
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath9k_11n_rate_series series[4];
- struct sk_buff *skb;
- struct ieee80211_tx_info *tx_info;
- struct ieee80211_tx_rate *rates;
- const struct ieee80211_rate *rate;
- struct ieee80211_hdr *hdr;
- int i, flags = 0;
- u8 rix = 0, ctsrate = 0;
- bool is_pspoll;
-
- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-
- skb = bf->bf_mpdu;
- tx_info = IEEE80211_SKB_CB(skb);
- rates = tx_info->control.rates;
- hdr = (struct ieee80211_hdr *)skb->data;
- is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
-
- /*
- * We check if Short Preamble is needed for the CTS rate by
- * checking the BSS's global flag.
- * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
- */
- rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
- ctsrate = rate->hw_value;
- if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
- ctsrate |= rate->hw_value_short;
-
- for (i = 0; i < 4; i++) {
- bool is_40, is_sgi, is_sp;
- int phy;
-
- if (!rates[i].count || (rates[i].idx < 0))
- continue;
-
- rix = rates[i].idx;
- series[i].Tries = rates[i].count;
-
- if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- flags |= ATH9K_TXDESC_RTSENA;
- } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- flags |= ATH9K_TXDESC_CTSENA;
- }
-
- if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- series[i].RateFlags |= ATH9K_RATESERIES_2040;
- if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
- series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
-
- is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
- is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
- is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
-
- if (rates[i].flags & IEEE80211_TX_RC_MCS) {
- /* MCS rates */
- series[i].Rate = rix | 0x80;
- series[i].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[i].Rate);
- series[i].PktDuration = ath_pkt_duration(sc, rix, len,
- is_40, is_sgi, is_sp);
- if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
- series[i].RateFlags |= ATH9K_RATESERIES_STBC;
- continue;
- }
-
- /* legacy rates */
- if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
- !(rate->flags & IEEE80211_RATE_ERP_G))
- phy = WLAN_RC_PHY_CCK;
- else
- phy = WLAN_RC_PHY_OFDM;
-
- rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
- series[i].Rate = rate->hw_value;
- if (rate->hw_value_short) {
- if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
- series[i].Rate |= rate->hw_value_short;
- } else {
- is_sp = false;
- }
-
- if (bf->bf_state.bfs_paprd)
- series[i].ChSel = common->tx_chainmask;
- else
- series[i].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[i].Rate);
-
- series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
- phy, rate->bitrate * 100, len, rix, is_sp);
- }
-
- /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
- if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
- flags &= ~ATH9K_TXDESC_RTSENA;
-
- /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
- if (flags & ATH9K_TXDESC_RTSENA)
- flags &= ~ATH9K_TXDESC_CTSENA;
-
- /* set dur_update_en for l-sig computation except for PS-Poll frames */
- ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
- bf->bf_lastbf->bf_desc,
- !is_pspoll, ctsrate,
- 0, series, 4, flags);
-
-}
-
-static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
+/*
+ * Assign a descriptor (and sequence number if necessary,
+ * and map buffer for DMA. Frees skb on error
+ */
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
- struct sk_buff *skb)
+ struct ath_atx_tid *tid,
+ struct sk_buff *skb,
+ bool dequeue)
{
- struct ath_softc *sc = hw->priv;
- struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_buf *bf;
- struct ath_desc *ds;
- int frm_type;
+ u16 seqno;
bf = ath_tx_get_buffer(sc);
if (!bf) {
ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
- return NULL;
+ goto error;
}
ATH_TXBUF_RESET(bf);
- bf->bf_flags = setup_tx_flags(skb);
+ if (tid) {
+ seqno = tid->seq_next;
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+ bf->bf_state.seqno = seqno;
+ }
+
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
@@ -1768,38 +1804,28 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
ath_err(ath9k_hw_common(sc->sc_ah),
"dma_mapping_error() on TX\n");
ath_tx_return_buffer(sc, bf);
- return NULL;
+ goto error;
}
- frm_type = get_hw_packet_type(skb);
-
- ds = bf->bf_desc;
- ath9k_hw_set_desc_link(ah, ds, 0);
-
- ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
- fi->keyix, fi->keytype, bf->bf_flags);
-
- ath9k_hw_filltxdesc(ah, ds,
- skb->len, /* segment length */
- true, /* first segment */
- true, /* last segment */
- ds, /* first descriptor */
- bf->bf_buf_addr,
- txq->axq_qnum);
-
+ fi->bf = bf;
return bf;
+
+error:
+ if (dequeue)
+ __skb_unlink(skb, &tid->buf_q);
+ dev_kfree_skb_any(skb);
+ return NULL;
}
/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
- struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct list_head bf_head;
struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
@@ -1817,27 +1843,21 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
* Try aggregation if it's a unicast data frame
* and the destination is HT capable.
*/
- ath_tx_send_ampdu(sc, tid, bf, txctl);
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
} else {
- INIT_LIST_HEAD(&bf_head);
- list_add_tail(&bf->list, &bf_head);
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+ if (!bf)
+ goto out;
- bf->bf_state.bfs_ftype = txctl->frame_type;
bf->bf_state.bfs_paprd = txctl->paprd;
- if (bf->bf_state.bfs_paprd)
- ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
- bf->bf_state.bfs_paprd);
-
if (txctl->paprd)
bf->bf_state.bfs_paprd_timestamp = jiffies;
- if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
-
- ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
+ ath_tx_send_normal(sc, txctl->txq, tid, skb);
}
+out:
spin_unlock_bh(&txctl->txq->axq_lock);
}
@@ -1851,7 +1871,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
- struct ath_buf *bf;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
int q;
@@ -1884,6 +1903,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
skb_push(skb, padsize);
memmove(skb->data, skb->data + padsize, padpos);
+ hdr = (struct ieee80211_hdr *) skb->data;
}
if ((vif && vif->type != NL80211_IFTYPE_AP &&
@@ -1898,10 +1918,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
* info are no longer valid (overwritten by the ath_frame_info data.
*/
- bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
- if (unlikely(!bf))
- return -ENOMEM;
-
q = skb_get_queue_mapping(skb);
spin_lock_bh(&txq->axq_lock);
if (txq == sc->tx.txq_map[q] &&
@@ -1911,8 +1927,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
}
spin_unlock_bh(&txq->axq_lock);
- ath_tx_start_dma(sc, bf, txctl);
-
+ ath_tx_start_dma(sc, skb, txctl);
return 0;
}
@@ -1921,7 +1936,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
/*****************/
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- int tx_flags, int ftype, struct ath_txq *txq)
+ int tx_flags, struct ath_txq *txq)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1934,10 +1949,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
if (tx_flags & ATH_TX_BAR)
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
- if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
+ if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
- }
padpos = ath9k_cmn_padpos(hdr->frame_control);
padsize = padpos & 3;
@@ -1981,18 +1995,18 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int txok, int sendbar)
{
struct sk_buff *skb = bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
unsigned long flags;
int tx_flags = 0;
if (sendbar)
tx_flags = ATH_TX_BAR;
- if (!txok) {
+ if (!txok)
tx_flags |= ATH_TX_ERROR;
- if (bf_isxretried(bf))
- tx_flags |= ATH_TX_XRETRY;
- }
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = 0;
@@ -2005,9 +2019,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
else
complete(&sc->paprd_complete);
} else {
- ath_debug_stat_tx(sc, bf, ts, txq);
- ath_tx_complete(sc, skb, tx_flags,
- bf->bf_state.bfs_ftype, txq);
+ ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
+ ath_tx_complete(sc, skb, tx_flags, txq);
}
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
* accidentally reference it later.
@@ -2024,7 +2037,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad,
- int txok, bool update_rc)
+ int txok)
{
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -2039,19 +2052,16 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
tx_rateindex = ts->ts_rateindex;
WARN_ON(tx_rateindex >= hw->max_rates);
- if (ts->ts_status & ATH9K_TXERR_FILT)
- tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
BUG_ON(nbad > nframes);
-
- tx_info->status.ampdu_len = nframes;
- tx_info->status.ampdu_ack_len = nframes - nbad;
}
+ tx_info->status.ampdu_len = nframes;
+ tx_info->status.ampdu_ack_len = nframes - nbad;
if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
- (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+ (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
/*
* If an underrun error is seen assume it as an excessive
* retry only if max frame trigger level has been reached
@@ -2064,9 +2074,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
* successfully by eventually preferring slower rates.
* This itself should also alleviate congestion on the bus.
*/
- if (ieee80211_is_data(hdr->frame_control) &&
- (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
- ATH9K_TX_DELIM_UNDERRUN)) &&
+ if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+ ATH9K_TX_DELIM_UNDERRUN)) &&
+ ieee80211_is_data(hdr->frame_control) &&
ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
tx_info->status.rates[tx_rateindex].count =
hw->max_rate_tries;
@@ -2080,6 +2090,34 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}
+static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_tx_status *ts, struct ath_buf *bf,
+ struct list_head *bf_head)
+ __releases(txq->axq_lock)
+ __acquires(txq->axq_lock)
+{
+ int txok;
+
+ txq->axq_depth--;
+ txok = !(ts->ts_status & ATH9K_TXERR_MASK);
+ txq->axq_tx_inprogress = false;
+ if (bf_is_ampdu_not_probing(bf))
+ txq->axq_ampdu_depth--;
+
+ spin_unlock_bh(&txq->axq_lock);
+
+ if (!bf_isampdu(bf)) {
+ ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+ ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+ } else
+ ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+
+ spin_lock_bh(&txq->axq_lock);
+
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_txq_schedule(sc, txq);
+}
+
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hw *ah = sc->sc_ah;
@@ -2088,20 +2126,21 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
struct list_head bf_head;
struct ath_desc *ds;
struct ath_tx_status ts;
- int txok;
int status;
ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
txq->axq_link);
+ spin_lock_bh(&txq->axq_lock);
for (;;) {
- spin_lock_bh(&txq->axq_lock);
+ if (work_pending(&sc->hw_reset_work))
+ break;
+
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
break;
}
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
@@ -2117,13 +2156,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
bf_held = NULL;
if (bf->bf_stale) {
bf_held = bf;
- if (list_is_last(&bf_held->list, &txq->axq_q)) {
- spin_unlock_bh(&txq->axq_lock);
+ if (list_is_last(&bf_held->list, &txq->axq_q))
break;
- } else {
- bf = list_entry(bf_held->list.next,
- struct ath_buf, list);
- }
+
+ bf = list_entry(bf_held->list.next, struct ath_buf,
+ list);
}
lastbf = bf->bf_lastbf;
@@ -2131,10 +2168,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
memset(&ts, 0, sizeof(ts));
status = ath9k_hw_txprocdesc(ah, ds, &ts);
- if (status == -EINPROGRESS) {
- spin_unlock_bh(&txq->axq_lock);
+ if (status == -EINPROGRESS)
break;
- }
+
TX_STAT_INC(txq->axq_qnum, txprocdesc);
/*
@@ -2148,42 +2184,14 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
list_cut_position(&bf_head,
&txq->axq_q, lastbf->list.prev);
- txq->axq_depth--;
- txok = !(ts.ts_status & ATH9K_TXERR_MASK);
- txq->axq_tx_inprogress = false;
- if (bf_held)
+ if (bf_held) {
list_del(&bf_held->list);
-
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth--;
-
- spin_unlock_bh(&txq->axq_lock);
-
- if (bf_held)
ath_tx_return_buffer(sc, bf_held);
-
- if (!bf_isampdu(bf)) {
- /*
- * This frame is sent out as a single frame.
- * Use hardware retry status for this frame.
- */
- if (ts.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
}
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
- true);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
-
- spin_lock_bh(&txq->axq_lock);
-
- if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
}
+ spin_unlock_bh(&txq->axq_lock);
}
static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2216,7 +2224,8 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
- ath_reset(sc, true);
+ RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2240,17 +2249,19 @@ void ath_tx_tasklet(struct ath_softc *sc)
void ath_tx_edma_tasklet(struct ath_softc *sc)
{
- struct ath_tx_status txs;
+ struct ath_tx_status ts;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
int status;
- int txok;
for (;;) {
- status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
+ if (work_pending(&sc->hw_reset_work))
+ break;
+
+ status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS)
break;
if (status == -EIO) {
@@ -2260,12 +2271,13 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
}
/* Skip beacon completions */
- if (txs.qid == sc->beacon.beaconq)
+ if (ts.qid == sc->beacon.beaconq)
continue;
- txq = &sc->tx.txq[txs.qid];
+ txq = &sc->tx.txq[ts.qid];
spin_lock_bh(&txq->axq_lock);
+
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
spin_unlock_bh(&txq->axq_lock);
return;
@@ -2278,41 +2290,21 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
INIT_LIST_HEAD(&bf_head);
list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
&lastbf->list);
- INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- txq->axq_depth--;
- txq->axq_tx_inprogress = false;
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth--;
- spin_unlock_bh(&txq->axq_lock);
- txok = !(txs.ts_status & ATH9K_TXERR_MASK);
-
- if (!bf_isampdu(bf)) {
- if (txs.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
- }
-
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
- txok, true);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &txs, txok, 0);
+ if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- spin_lock_bh(&txq->axq_lock);
+ if (!list_empty(&txq->axq_q)) {
+ struct list_head bf_q;
- if (!list_empty(&txq->txq_fifo_pending)) {
- INIT_LIST_HEAD(&bf_head);
- bf = list_first_entry(&txq->txq_fifo_pending,
- struct ath_buf, list);
- list_cut_position(&bf_head,
- &txq->txq_fifo_pending,
- &bf->bf_lastbf->list);
- ath_tx_txqaddbuf(sc, txq, &bf_head);
- } else if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq);
+ INIT_LIST_HEAD(&bf_q);
+ txq->axq_link = NULL;
+ list_splice_tail_init(&txq->axq_q, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+ }
+ }
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
spin_unlock_bh(&txq->axq_lock);
}
}
@@ -2423,7 +2415,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->sched = false;
tid->paused = false;
tid->state &= ~AGGR_CLEANUP;
- INIT_LIST_HEAD(&tid->buf_q);
+ __skb_queue_head_init(&tid->buf_q);
acno = TID_TO_WME_AC(tidno);
tid->ac = &an->ac[acno];
tid->state &= ~AGGR_ADDBA_COMPLETE;
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 2d1b821..267d5dc 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -39,3 +39,17 @@ config CARL9170_WPC
bool
depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
default y
+
+config CARL9170_HWRNG
+ bool "Random number generator"
+ depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170)
+ default n
+ help
+ Provides a hardware random number generator to the kernel.
+
+ SECURITY WARNING: It's relatively easy to eavesdrop all
+ generated random numbers from the transport stream with
+ usbmon [software] or special usb sniffer hardware.
+
+ Say N, unless your setup[i.e.: embedded system] has no
+ other rng source and you can afford to take the risk.
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 4da01a9..8bcf6b9 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -43,6 +43,7 @@
#include <linux/firmware.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
+#include <linux/hw_random.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <linux/usb.h>
@@ -67,6 +68,8 @@
#define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1)
+static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
+
enum carl9170_rf_init_mode {
CARL9170_RFI_NONE,
CARL9170_RFI_WARM,
@@ -149,6 +152,7 @@ struct carl9170_sta_tid {
#define CARL9170_TX_TIMEOUT 2500
#define CARL9170_JANITOR_DELAY 128
#define CARL9170_QUEUE_STUCK_TIMEOUT 5500
+#define CARL9170_STAT_WORK 30000
#define CARL9170_NUM_TX_AGG_MAX 30
@@ -175,7 +179,7 @@ struct carl9170_tx_queue_stats {
struct carl9170_vif {
unsigned int id;
- struct ieee80211_vif *vif;
+ struct ieee80211_vif __rcu *vif;
};
struct carl9170_vif_info {
@@ -261,6 +265,7 @@ struct ar9170 {
atomic_t rx_work_urbs;
atomic_t rx_pool_urbs;
kernel_ulong_t features;
+ bool usb_ep_cmd_is_bulk;
/* firmware settings */
struct completion fw_load_wait;
@@ -280,6 +285,7 @@ struct ar9170 {
bool rx_stream;
bool tx_stream;
bool rx_filter;
+ bool hw_counters;
unsigned int mem_blocks;
unsigned int mem_block_size;
unsigned int rx_size;
@@ -309,7 +315,7 @@ struct ar9170 {
spinlock_t beacon_lock;
unsigned int global_pretbtt;
unsigned int global_beacon_int;
- struct carl9170_vif_info *beacon_iter;
+ struct carl9170_vif_info __rcu *beacon_iter;
unsigned int beacon_enabled;
/* cryptographic engine */
@@ -329,11 +335,21 @@ struct ar9170 {
/* PHY */
struct ieee80211_channel *channel;
+ unsigned int num_channels;
int noise[4];
unsigned int chan_fail;
unsigned int total_chan_fail;
u8 heavy_clip;
u8 ht_settings;
+ struct {
+ u64 active; /* usec */
+ u64 cca; /* usec */
+ u64 tx_time; /* usec */
+ u64 rx_total;
+ u64 rx_overrun;
+ } tally;
+ struct delayed_work stat_work;
+ struct survey_info *survey;
/* power calibration data */
u8 power_5G_leg[4];
@@ -387,7 +403,7 @@ struct ar9170 {
/* tx ampdu */
struct work_struct ampdu_work;
spinlock_t tx_ampdu_list_lock;
- struct carl9170_sta_tid *tx_ampdu_iter;
+ struct carl9170_sta_tid __rcu *tx_ampdu_iter;
struct list_head tx_ampdu_list;
atomic_t tx_ampdu_upload;
atomic_t tx_ampdu_scheduler;
@@ -435,12 +451,22 @@ struct ar9170 {
unsigned int off_override;
bool state;
} ps;
+
+#ifdef CONFIG_CARL9170_HWRNG
+# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN
+ struct {
+ struct hwrng rng;
+ bool initialized;
+ char name[30 + 1];
+ u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)];
+ unsigned int cache_idx;
+ } rng;
+#endif /* CONFIG_CARL9170_HWRNG */
};
enum carl9170_ps_off_override_reasons {
PS_OFF_VIF = BIT(0),
PS_OFF_BCN = BIT(1),
- PS_OFF_5GHZ = BIT(2),
};
struct carl9170_ba_stats {
@@ -455,7 +481,7 @@ struct carl9170_sta_info {
bool sleeping;
atomic_t pending_frames;
unsigned int ampdu_max_len;
- struct carl9170_sta_tid *agg[CARL9170_NUM_TID];
+ struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID];
struct carl9170_ba_stats stats[CARL9170_NUM_TID];
};
@@ -531,7 +557,6 @@ int carl9170_set_ampdu_settings(struct ar9170 *ar);
int carl9170_set_slot_time(struct ar9170 *ar);
int carl9170_set_mac_rates(struct ar9170 *ar);
int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
int carl9170_disable_key(struct ar9170 *ar, const u8 id);
@@ -552,6 +577,7 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb);
void carl9170_tx_scheduler(struct ar9170 *ar);
void carl9170_tx_get_skb(struct sk_buff *skb);
int carl9170_tx_put_skb(struct sk_buff *skb);
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
/* LEDs */
#ifdef CONFIG_CARL9170_LEDS
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
index cdfc94c..195dc65 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.c
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -36,6 +36,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/div64.h>
#include "carl9170.h"
#include "cmd.h"
@@ -165,6 +166,39 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
return __carl9170_exec_cmd(ar, cmd, true);
}
+int carl9170_collect_tally(struct ar9170 *ar)
+{
+ struct carl9170_tally_rsp tally;
+ struct survey_info *info;
+ unsigned int tick;
+ int err;
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL,
+ sizeof(tally), (u8 *)&tally);
+ if (err)
+ return err;
+
+ tick = le32_to_cpu(tally.tick);
+ if (tick) {
+ ar->tally.active += le32_to_cpu(tally.active) / tick;
+ ar->tally.cca += le32_to_cpu(tally.cca) / tick;
+ ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick;
+ ar->tally.rx_total += le32_to_cpu(tally.rx_total);
+ ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun);
+
+ if (ar->channel) {
+ info = &ar->survey[ar->channel->hw_value];
+ info->channel_time = ar->tally.active;
+ info->channel_time_busy = ar->tally.cca;
+ info->channel_time_tx = ar->tally.tx_time;
+ do_div(info->channel_time, 1000);
+ do_div(info->channel_time_busy, 1000);
+ do_div(info->channel_time_tx, 1000);
+ }
+ }
+ return 0;
+}
+
int carl9170_powersave(struct ar9170 *ar, const bool ps)
{
struct carl9170_cmd *cmd;
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index 568174c..885c427 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -50,6 +50,7 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v);
int carl9170_reboot(struct ar9170 *ar);
int carl9170_mac_reset(struct ar9170 *ar);
int carl9170_powersave(struct ar9170 *ar, const bool power_on);
+int carl9170_collect_tally(struct ar9170 *ar);
int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
const u32 mode, const u32 addr, const u32 len);
@@ -87,7 +88,7 @@ do { \
__ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \
__ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \
__nreg++; \
- if ((__nreg >= PAYLOAD_MAX/2)) { \
+ if ((__nreg >= PAYLOAD_MAX / 2)) { \
if (IS_ACCEPTING_CMD(__ar)) \
__err = carl9170_exec_cmd(__ar, \
CARL9170_CMD_WREG, 8 * __nreg, \
@@ -160,7 +161,7 @@ do { \
} while (0)
#define carl9170_async_regwrite_finish() do { \
-__async_regwrite_out : \
+__async_regwrite_out: \
if (__cmd != NULL && __err == 0) \
carl9170_async_regwrite_flush(); \
kfree(__cmd); \
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 0ac1124..de57f90 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -695,7 +695,7 @@ static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
}
__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
-static const char *erp_modes[] = {
+static const char *const erp_modes[] = {
[CARL9170_ERP_INVALID] = "INVALID",
[CARL9170_ERP_AUTO] = "Automatic",
[CARL9170_ERP_MAC80211] = "Set by MAC80211",
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 221957c..cba9d04 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
+#include <linux/module.h>
#include "carl9170.h"
#include "fwcmd.h"
#include "version.h"
@@ -237,7 +238,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
ar->disable_offload = true;
}
- if (SUPP(CARL9170FW_PSM))
+ if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;
if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
@@ -266,6 +267,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
FIF_PROMISC_IN_BSS;
}
+ if (SUPP(CARL9170FW_HW_COUNTERS))
+ ar->fw.hw_counters = true;
+
if (SUPP(CARL9170FW_WOL))
device_set_wakeup_enable(&ar->udev->dev, true);
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index 30449d2..9443c80 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -4,7 +4,7 @@
* Firmware command interface definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,6 +54,8 @@ enum carl9170_cmd_oids {
CARL9170_CMD_BCN_CTRL = 0x05,
CARL9170_CMD_READ_TSF = 0x06,
CARL9170_CMD_RX_FILTER = 0x07,
+ CARL9170_CMD_WOL = 0x08,
+ CARL9170_CMD_TALLY = 0x09,
/* CAM */
CARL9170_CMD_EKEY = 0x10,
@@ -180,6 +182,21 @@ struct carl9170_bcn_ctrl_cmd {
#define CARL9170_BCN_CTRL_DRAIN 0
#define CARL9170_BCN_CTRL_CAB_TRIGGER 1
+struct carl9170_wol_cmd {
+ __le32 flags;
+ u8 mac[6];
+ u8 bssid[6];
+ __le32 null_interval;
+ __le32 free_for_use2;
+ __le32 mask;
+ u8 pattern[32];
+} __packed;
+
+#define CARL9170_WOL_CMD_SIZE 60
+
+#define CARL9170_WOL_DISCONNECT 1
+#define CARL9170_WOL_MAGIC_PKT 2
+
struct carl9170_cmd_head {
union {
struct {
@@ -203,6 +220,7 @@ struct carl9170_cmd {
struct carl9170_write_reg wreg;
struct carl9170_rf_init rf_init;
struct carl9170_psm psm;
+ struct carl9170_wol_cmd wol;
struct carl9170_bcn_ctrl_cmd bcn_ctrl;
struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
@@ -269,6 +287,15 @@ struct carl9170_tsf_rsp {
} __packed;
#define CARL9170_TSF_RSP_SIZE 8
+struct carl9170_tally_rsp {
+ __le32 active;
+ __le32 cca;
+ __le32 tx_time;
+ __le32 rx_total;
+ __le32 rx_overrun;
+ __le32 tick;
+} __packed;
+
struct carl9170_rsp {
struct carl9170_cmd_head hdr;
@@ -283,6 +310,7 @@ struct carl9170_rsp {
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
+ struct carl9170_tally_rsp tally;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
} __packed __aligned(4);
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 9210668..6d9c089 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -3,7 +3,7 @@
*
* Firmware descriptor format
*
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -72,6 +72,12 @@ enum carl9170fw_feature_list {
/* Wake up on WLAN */
CARL9170FW_WOL,
+ /* Firmware supports PSM in the 5GHZ Band */
+ CARL9170FW_FIXED_5GHZ_PSM,
+
+ /* HW (ANI, CCA, MIB) tally counters */
+ CARL9170FW_HW_COUNTERS,
+
/* KEEP LAST */
__CARL9170FW_FEATURE_NUM
};
@@ -82,6 +88,7 @@ enum carl9170fw_feature_list {
#define DBG_MAGIC "DBG\0"
#define CHK_MAGIC "CHK\0"
#define TXSQ_MAGIC "TXSQ"
+#define WOL_MAGIC "WOL\0"
#define LAST_MAGIC "LAST"
#define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
@@ -104,7 +111,7 @@ struct carl9170fw_desc_head {
(sizeof(struct carl9170fw_desc_head))
#define CARL9170FW_OTUS_DESC_MIN_VER 6
-#define CARL9170FW_OTUS_DESC_CUR_VER 6
+#define CARL9170FW_OTUS_DESC_CUR_VER 7
struct carl9170fw_otus_desc {
struct carl9170fw_desc_head head;
__le32 feature_set;
@@ -186,6 +193,16 @@ struct carl9170fw_txsq_desc {
#define CARL9170FW_TXSQ_DESC_SIZE \
(sizeof(struct carl9170fw_txsq_desc))
+#define CARL9170FW_WOL_DESC_MIN_VER 1
+#define CARL9170FW_WOL_DESC_CUR_VER 1
+struct carl9170fw_wol_desc {
+ struct carl9170fw_desc_head head;
+
+ __le32 supported_triggers; /* CARL9170_WOL_ */
+} __packed;
+#define CARL9170FW_WOL_DESC_SIZE \
+ (sizeof(struct carl9170fw_wol_desc))
+
#define CARL9170FW_LAST_DESC_MIN_VER 1
#define CARL9170FW_LAST_DESC_CUR_VER 2
struct carl9170fw_last_desc {
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index 4e30762..fa834c1 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -4,7 +4,7 @@
* Register map, hardware-specific definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -174,6 +174,7 @@
#define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0)
#define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000
#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678)
+#define AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE BIT(2)
#define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3)
#define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70
@@ -222,6 +223,12 @@
#define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0)
#define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4)
#define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8)
+#define AR9170_MAC_BACKOFF_CCA BIT(24)
+#define AR9170_MAC_BACKOFF_TX_PEX BIT(25)
+#define AR9170_MAC_BACKOFF_RX_PE BIT(26)
+#define AR9170_MAC_BACKOFF_MD_READY BIT(27)
+#define AR9170_MAC_BACKOFF_TX_PE BIT(28)
+
#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc)
#define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4)
@@ -357,7 +364,18 @@
#define AR9170_MAC_REG_DMA_WLAN_STATUS (AR9170_MAC_REG_BASE + 0xd38)
#define AR9170_MAC_REG_DMA_STATUS (AR9170_MAC_REG_BASE + 0xd3c)
-
+#define AR9170_MAC_REG_DMA_TXQ_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd40)
+#define AR9170_MAC_REG_DMA_TXQ0_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd40)
+#define AR9170_MAC_REG_DMA_TXQ1_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd44)
+#define AR9170_MAC_REG_DMA_TXQ2_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd48)
+#define AR9170_MAC_REG_DMA_TXQ3_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd4c)
+#define AR9170_MAC_REG_DMA_TXQ4_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd50)
+#define AR9170_MAC_REG_DMA_TXQ0Q1_LEN (AR9170_MAC_REG_BASE + 0xd54)
+#define AR9170_MAC_REG_DMA_TXQ2Q3_LEN (AR9170_MAC_REG_BASE + 0xd58)
+#define AR9170_MAC_REG_DMA_TXQ4_LEN (AR9170_MAC_REG_BASE + 0xd5c)
+
+#define AR9170_MAC_REG_DMA_TXQX_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd74)
+#define AR9170_MAC_REG_DMA_TXQX_FAIL_ADDR (AR9170_MAC_REG_BASE + 0xd78)
#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xd7c)
#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f
#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0
@@ -377,10 +395,40 @@
#define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98)
#define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c)
-
-
#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0)
+#define AR9170_MAC_BCN_HT1_HT_EN BIT(0)
+#define AR9170_MAC_BCN_HT1_GF_PMB BIT(1)
+#define AR9170_MAC_BCN_HT1_SP_EXP BIT(2)
+#define AR9170_MAC_BCN_HT1_TX_BF BIT(3)
+#define AR9170_MAC_BCN_HT1_PWR_CTRL_S 4
+#define AR9170_MAC_BCN_HT1_PWR_CTRL 0x70
+#define AR9170_MAC_BCN_HT1_TX_ANT1 BIT(7)
+#define AR9170_MAC_BCN_HT1_TX_ANT0 BIT(8)
+#define AR9170_MAC_BCN_HT1_NUM_LFT_S 9
+#define AR9170_MAC_BCN_HT1_NUM_LFT 0x600
+#define AR9170_MAC_BCN_HT1_BWC_20M_EXT BIT(16)
+#define AR9170_MAC_BCN_HT1_BWC_40M_SHARED BIT(17)
+#define AR9170_MAC_BCN_HT1_BWC_40M_DUP (BIT(16) | BIT(17))
+#define AR9170_MAC_BCN_HT1_BF_MCS_S 18
+#define AR9170_MAC_BCN_HT1_BF_MCS 0x1c0000
+#define AR9170_MAC_BCN_HT1_TPC_S 21
+#define AR9170_MAC_BCN_HT1_TPC 0x7e00000
+#define AR9170_MAC_BCN_HT1_CHAIN_MASK_S 27
+#define AR9170_MAC_BCN_HT1_CHAIN_MASK 0x38000000
+
#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4)
+#define AR9170_MAC_BCN_HT2_MCS_S 0
+#define AR9170_MAC_BCN_HT2_MCS 0x7f
+#define AR9170_MAC_BCN_HT2_BW40 BIT(8)
+#define AR9170_MAC_BCN_HT2_SMOOTHING BIT(9)
+#define AR9170_MAC_BCN_HT2_SS BIT(10)
+#define AR9170_MAC_BCN_HT2_NSS BIT(11)
+#define AR9170_MAC_BCN_HT2_STBC_S 12
+#define AR9170_MAC_BCN_HT2_STBC 0x3000
+#define AR9170_MAC_BCN_HT2_ADV_COD BIT(14)
+#define AR9170_MAC_BCN_HT2_SGI BIT(15)
+#define AR9170_MAC_BCN_HT2_LEN_S 16
+#define AR9170_MAC_BCN_HT2_LEN 0xffff0000
#define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0)
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c
index 4bb2cbd..78dadc7 100644
--- a/drivers/net/wireless/ath/carl9170/led.c
+++ b/drivers/net/wireless/ath/carl9170/led.c
@@ -118,7 +118,7 @@ static void carl9170_led_set_brightness(struct led_classdev *led,
}
if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
- ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
+ ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10);
}
static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 385cf50..dfda919 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -455,135 +455,6 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
return carl9170_regwrite_result();
}
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
-{
- struct sk_buff *skb = NULL;
- struct carl9170_vif_info *cvif;
- struct ieee80211_tx_info *txinfo;
- __le32 *data, *old = NULL;
- u32 word, off, addr, len;
- int i = 0, err = 0;
-
- rcu_read_lock();
- cvif = rcu_dereference(ar->beacon_iter);
-retry:
- if (ar->vifs == 0 || !cvif)
- goto out_unlock;
-
- list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
- if (cvif->active && cvif->enable_beacon)
- goto found;
- }
-
- if (!ar->beacon_enabled || i++)
- goto out_unlock;
-
- goto retry;
-
-found:
- rcu_assign_pointer(ar->beacon_iter, cvif);
-
- skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
- NULL, NULL);
-
- if (!skb) {
- err = -ENOMEM;
- goto err_free;
- }
-
- txinfo = IEEE80211_SKB_CB(skb);
- if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
- err = -EINVAL;
- goto err_free;
- }
-
- spin_lock_bh(&ar->beacon_lock);
- data = (__le32 *)skb->data;
- if (cvif->beacon)
- old = (__le32 *)cvif->beacon->data;
-
- off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
- addr = ar->fw.beacon_addr + off;
- len = roundup(skb->len + FCS_LEN, 4);
-
- if ((off + len) > ar->fw.beacon_max_len) {
- if (net_ratelimit()) {
- wiphy_err(ar->hw->wiphy, "beacon does not "
- "fit into device memory!\n");
- }
- err = -EINVAL;
- goto err_unlock;
- }
-
- if (len > AR9170_MAC_BCN_LENGTH_MAX) {
- if (net_ratelimit()) {
- wiphy_err(ar->hw->wiphy, "no support for beacons "
- "bigger than %d (yours:%d).\n",
- AR9170_MAC_BCN_LENGTH_MAX, len);
- }
-
- err = -EMSGSIZE;
- goto err_unlock;
- }
-
- i = txinfo->control.rates[0].idx;
- if (txinfo->band != IEEE80211_BAND_2GHZ)
- i += 4;
-
- word = __carl9170_ratetable[i].hw_value & 0xf;
- if (i < 4)
- word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
- else
- word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
-
- carl9170_async_regwrite_begin(ar);
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
-
- for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
- /*
- * XXX: This accesses beyond skb data for up
- * to the last 3 bytes!!
- */
-
- if (old && (data[i] == old[i]))
- continue;
-
- word = le32_to_cpu(data[i]);
- carl9170_async_regwrite(addr + 4 * i, word);
- }
- carl9170_async_regwrite_finish();
-
- dev_kfree_skb_any(cvif->beacon);
- cvif->beacon = NULL;
-
- err = carl9170_async_regwrite_result();
- if (!err)
- cvif->beacon = skb;
- spin_unlock_bh(&ar->beacon_lock);
- if (err)
- goto err_free;
-
- if (submit) {
- err = carl9170_bcn_ctrl(ar, cvif->id,
- CARL9170_BCN_CTRL_CAB_TRIGGER,
- addr, skb->len + FCS_LEN);
-
- if (err)
- goto err_free;
- }
-out_unlock:
- rcu_read_unlock();
- return 0;
-
-err_unlock:
- spin_unlock_bh(&ar->beacon_lock);
-
-err_free:
- rcu_read_unlock();
- dev_kfree_skb_any(skb);
- return err;
-}
-
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata,
const int keylen)
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index b54966c..f06e069 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -345,11 +345,11 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
carl9170_zap_queues(ar);
/* reset QoS defaults */
- CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT */
- CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7, 15, 94); /* VIDEO */
- CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3, 7, 47); /* VOICE */
- CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023, 0); /* BACKGROUND */
- CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VO], 2, 3, 7, 47);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VI], 2, 7, 15, 94);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BE], 3, 15, 1023, 0);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BK], 7, 15, 1023, 0);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_SPECIAL], 2, 3, 7, 0);
ar->current_factor = ar->current_density = -1;
/* "The first key is unique." */
@@ -413,6 +413,9 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
+ ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
+ round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
+
ieee80211_wake_queues(ar->hw);
err = 0;
@@ -423,6 +426,7 @@ out:
static void carl9170_cancel_worker(struct ar9170 *ar)
{
+ cancel_delayed_work_sync(&ar->stat_work);
cancel_delayed_work_sync(&ar->tx_janitor);
#ifdef CONFIG_CARL9170_LEDS
cancel_delayed_work_sync(&ar->led_work);
@@ -794,6 +798,43 @@ static void carl9170_ps_work(struct work_struct *work)
mutex_unlock(&ar->mutex);
}
+static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise)
+{
+ int err;
+
+ if (noise) {
+ err = carl9170_get_noisefloor(ar);
+ if (err)
+ return err;
+ }
+
+ if (ar->fw.hw_counters) {
+ err = carl9170_collect_tally(ar);
+ if (err)
+ return err;
+ }
+
+ if (flush)
+ memset(&ar->tally, 0, sizeof(ar->tally));
+
+ return 0;
+}
+
+static void carl9170_stat_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work);
+ int err;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_update_survey(ar, false, true);
+ mutex_unlock(&ar->mutex);
+
+ if (err)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
+ round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
+}
static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
{
@@ -828,11 +869,19 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (err)
goto out;
+ err = carl9170_update_survey(ar, true, false);
+ if (err)
+ goto out;
+
err = carl9170_set_channel(ar, hw->conf.channel,
hw->conf.channel_type, CARL9170_RFI_NONE);
if (err)
goto out;
+ err = carl9170_update_survey(ar, false, true);
+ if (err)
+ goto out;
+
err = carl9170_set_dyn_sifs_ack(ar);
if (err)
goto out;
@@ -1029,7 +1078,8 @@ out:
mutex_unlock(&ar->mutex);
}
-static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw)
+static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ar9170 *ar = hw->priv;
struct carl9170_tsf_rsp tsf;
@@ -1255,7 +1305,8 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
return 0;
}
-static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
struct ar9170 *ar = hw->priv;
@@ -1421,24 +1472,159 @@ static int carl9170_register_wps_button(struct ar9170 *ar)
}
#endif /* CONFIG_CARL9170_WPC */
-static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
- struct survey_info *survey)
+#ifdef CONFIG_CARL9170_HWRNG
+static int carl9170_rng_get(struct ar9170 *ar)
{
- struct ar9170 *ar = hw->priv;
+
+#define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32))
+#define RB (CARL9170_MAX_CMD_PAYLOAD_LEN)
+
+ static const __le32 rng_load[RW] = {
+ [0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)};
+
+ u32 buf[RW];
+
+ unsigned int i, off = 0, transfer, count;
int err;
- if (idx != 0)
- return -ENOENT;
+ BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN);
+
+ if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized)
+ return -EAGAIN;
+
+ count = ARRAY_SIZE(ar->rng.cache);
+ while (count) {
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
+ RB, (u8 *) rng_load,
+ RB, (u8 *) buf);
+ if (err)
+ return err;
+
+ transfer = min_t(unsigned int, count, RW);
+ for (i = 0; i < transfer; i++)
+ ar->rng.cache[off + i] = buf[i];
+
+ off += transfer;
+ count -= transfer;
+ }
+
+ ar->rng.cache_idx = 0;
+
+#undef RW
+#undef RB
+ return 0;
+}
+
+static int carl9170_rng_read(struct hwrng *rng, u32 *data)
+{
+ struct ar9170 *ar = (struct ar9170 *)rng->priv;
+ int ret = -EIO;
mutex_lock(&ar->mutex);
- err = carl9170_get_noisefloor(ar);
+ if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) {
+ ret = carl9170_rng_get(ar);
+ if (ret) {
+ mutex_unlock(&ar->mutex);
+ return ret;
+ }
+ }
+
+ *data = ar->rng.cache[ar->rng.cache_idx++];
mutex_unlock(&ar->mutex);
- if (err)
+
+ return sizeof(u16);
+}
+
+static void carl9170_unregister_hwrng(struct ar9170 *ar)
+{
+ if (ar->rng.initialized) {
+ hwrng_unregister(&ar->rng.rng);
+ ar->rng.initialized = false;
+ }
+}
+
+static int carl9170_register_hwrng(struct ar9170 *ar)
+{
+ int err;
+
+ snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name),
+ "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy));
+ ar->rng.rng.name = ar->rng.name;
+ ar->rng.rng.data_read = carl9170_rng_read;
+ ar->rng.rng.priv = (unsigned long)ar;
+
+ if (WARN_ON(ar->rng.initialized))
+ return -EALREADY;
+
+ err = hwrng_register(&ar->rng.rng);
+ if (err) {
+ dev_err(&ar->udev->dev, "Failed to register the random "
+ "number generator (%d)\n", err);
+ return err;
+ }
+
+ ar->rng.initialized = true;
+
+ err = carl9170_rng_get(ar);
+ if (err) {
+ carl9170_unregister_hwrng(ar);
return err;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_CARL9170_HWRNG */
- survey->channel = ar->channel;
+static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct ar9170 *ar = hw->priv;
+ struct ieee80211_channel *chan;
+ struct ieee80211_supported_band *band;
+ int err, b, i;
+
+ chan = ar->channel;
+ if (!chan)
+ return -ENODEV;
+
+ if (idx == chan->hw_value) {
+ mutex_lock(&ar->mutex);
+ err = carl9170_update_survey(ar, false, true);
+ mutex_unlock(&ar->mutex);
+ if (err)
+ return err;
+ }
+
+ for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
+ band = ar->hw->wiphy->bands[b];
+
+ if (!band)
+ continue;
+
+ for (i = 0; i < band->n_channels; i++) {
+ if (band->channels[i].hw_value == idx) {
+ chan = &band->channels[i];
+ goto found;
+ }
+ }
+ }
+ return -ENOENT;
+
+found:
+ memcpy(survey, &ar->survey[idx], sizeof(*survey));
+
+ survey->channel = chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = ar->noise[0];
+
+ if (ar->channel == chan)
+ survey->filled |= SURVEY_INFO_IN_USE;
+
+ if (ar->fw.hw_counters) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ }
+
return 0;
}
@@ -1486,6 +1672,13 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
}
}
+static bool carl9170_tx_frames_pending(struct ieee80211_hw *hw)
+{
+ struct ar9170 *ar = hw->priv;
+
+ return !!atomic_read(&ar->tx_total_queued);
+}
+
static const struct ieee80211_ops carl9170_ops = {
.start = carl9170_op_start,
.stop = carl9170_op_stop,
@@ -1506,6 +1699,7 @@ static const struct ieee80211_ops carl9170_ops = {
.get_survey = carl9170_op_get_survey,
.get_stats = carl9170_op_get_stats,
.ampdu_action = carl9170_op_ampdu_action,
+ .tx_frames_pending = carl9170_tx_frames_pending,
};
void *carl9170_alloc(size_t priv_size)
@@ -1563,6 +1757,7 @@ void *carl9170_alloc(size_t priv_size)
INIT_WORK(&ar->ping_work, carl9170_ping_work);
INIT_WORK(&ar->restart_work, carl9170_restart_work);
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
+ INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work);
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
INIT_LIST_HEAD(&ar->tx_ampdu_list);
rcu_assign_pointer(ar->tx_ampdu_iter,
@@ -1579,6 +1774,7 @@ void *carl9170_alloc(size_t priv_size)
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_NEED_DTIM_PERIOD |
IEEE80211_HW_SIGNAL_DBM;
if (!modparam_noht) {
@@ -1623,7 +1819,7 @@ static int carl9170_read_eeprom(struct ar9170 *ar)
BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
#endif
- for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
+ for (i = 0; i < sizeof(ar->eeprom) / RB; i++) {
for (j = 0; j < RW; j++)
offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
RB * i + 4 * j);
@@ -1645,6 +1841,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
struct ath_regulatory *regulatory = &ar->common.regulatory;
unsigned int rx_streams, tx_streams, tx_params = 0;
int bands = 0;
+ int chans = 0;
if (ar->eeprom.length == cpu_to_le16(0xffff))
return -ENODATA;
@@ -1668,14 +1865,24 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&carl9170_band_2GHz;
+ chans += carl9170_band_2GHz.n_channels;
bands++;
}
if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&carl9170_band_5GHz;
+ chans += carl9170_band_5GHz.n_channels;
bands++;
}
+ if (!bands)
+ return -EINVAL;
+
+ ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL);
+ if (!ar->survey)
+ return -ENOMEM;
+ ar->num_channels = chans;
+
/*
* I measured this, a bandswitch takes roughly
* 135 ms and a frequency switch about 80.
@@ -1689,12 +1896,11 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
ar->hw->channel_change_time = 80 * 1000;
regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
- regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
/* second part of wiphy init */
SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
- return bands ? 0 : -EINVAL;
+ return 0;
}
static int carl9170_reg_notifier(struct wiphy *wiphy,
@@ -1778,6 +1984,12 @@ int carl9170_register(struct ar9170 *ar)
goto err_unreg;
#endif /* CONFIG_CARL9170_WPC */
+#ifdef CONFIG_CARL9170_HWRNG
+ err = carl9170_register_hwrng(ar);
+ if (err)
+ goto err_unreg;
+#endif /* CONFIG_CARL9170_HWRNG */
+
dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
wiphy_name(ar->hw->wiphy));
@@ -1810,6 +2022,10 @@ void carl9170_unregister(struct ar9170 *ar)
}
#endif /* CONFIG_CARL9170_WPC */
+#ifdef CONFIG_CARL9170_HWRNG
+ carl9170_unregister_hwrng(ar);
+#endif /* CONFIG_CARL9170_HWRNG */
+
carl9170_cancel_worker(ar);
cancel_work_sync(&ar->restart_work);
@@ -1827,6 +2043,9 @@ void carl9170_free(struct ar9170 *ar)
kfree(ar->mem_bitmap);
ar->mem_bitmap = NULL;
+ kfree(ar->survey);
+ ar->survey = NULL;
+
mutex_destroy(&ar->mutex);
ieee80211_free_hw(ar->hw);
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index b6ae0e1..472efc7 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -578,11 +578,10 @@ static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
if (err)
return err;
- /* XXX: remove magic! */
- if (is_2ghz)
- err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163);
- else
- err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143);
+ if (!ar->fw.hw_counters) {
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC,
+ is_2ghz ? 0x5163 : 0x5143);
+ }
return err;
}
@@ -1098,7 +1097,7 @@ static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
* Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
* Can we rely on the compiler to optimise away the div?
*/
- return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
+ return (y >> SHIFT) + ((y & (1 << (SHIFT - 1))) >> (SHIFT - 1));
#undef SHIFT
}
@@ -1379,7 +1378,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
modes[i].max_power =
carl9170_get_max_edge_power(ar,
- freq+f_off, EDGES(ctl_idx, 1));
+ freq + f_off, EDGES(ctl_idx, 1));
/*
* TODO: check if the regulatory max. power is
@@ -1441,7 +1440,7 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
if (freq < 3000)
f = freq - 2300;
else
- f = (freq - 4800)/5;
+ f = (freq - 4800) / 5;
/*
* cycle through the various modes
@@ -1574,6 +1573,9 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
}
+ if (ar->channel)
+ ar->survey[ar->channel->hw_value].noise = ar->noise[0];
+
return 0;
}
@@ -1766,10 +1768,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
ar->chan_fail = 0;
}
- err = carl9170_get_noisefloor(ar);
- if (err)
- return err;
-
if (ar->heavy_clip) {
err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
0x200 | ar->heavy_clip);
@@ -1783,12 +1781,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
}
}
- /* FIXME: PSM does not work in 5GHz Band */
- if (channel->band == IEEE80211_BAND_5GHZ)
- ar->ps.off_override |= PS_OFF_5GHZ;
- else
- ar->ps.off_override &= ~PS_OFF_5GHZ;
-
ar->channel = channel;
ar->ht_settings = new_ht;
return 0;
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index ec21ea9..dc99030 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -472,7 +472,7 @@ static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)
u8 *qc = ieee80211_get_qos_ctl(hdr);
reserved += NET_IP_ALIGN;
- if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
reserved += NET_IP_ALIGN;
}
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index f190f32..f6384af 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -296,7 +296,8 @@ static void carl9170_tx_release(struct kref *ref)
super = (void *)skb->data;
txinfo->status.ampdu_len = super->s.rix;
txinfo->status.ampdu_ack_len = super->s.cnt;
- } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
+ } else if ((txinfo->flags & IEEE80211_TX_STAT_ACK) &&
+ !(txinfo->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
/*
* drop redundant tx_status reports:
*
@@ -308,15 +309,17 @@ static void carl9170_tx_release(struct kref *ref)
*
* 3. minstrel_ht is picky, it only accepts
* reports of frames with the TX_STATUS_AMPDU flag.
+ *
+ * 4. mac80211 is not particularly interested in
+ * feedback either [CTL_REQ_TX_STATUS not set]
*/
dev_kfree_skb_any(skb);
return;
} else {
/*
- * Frame has failed, but we want to keep it in
- * case it was lost due to a power-state
- * transition.
+ * Either the frame transmission has failed or
+ * mac80211 requested tx status.
*/
}
}
@@ -661,11 +664,67 @@ void carl9170_tx_process_status(struct ar9170 *ar,
}
}
+static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar,
+ struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate,
+ unsigned int *phyrate, unsigned int *tpc, unsigned int *chains)
+{
+ struct ieee80211_rate *rate = NULL;
+ u8 *txpower;
+ unsigned int idx;
+
+ idx = txrate->idx;
+ *tpc = 0;
+ *phyrate = 0;
+
+ if (txrate->flags & IEEE80211_TX_RC_MCS) {
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ /* +1 dBm for HT40 */
+ *tpc += 2;
+
+ if (info->band == IEEE80211_BAND_2GHZ)
+ txpower = ar->power_2G_ht40;
+ else
+ txpower = ar->power_5G_ht40;
+ } else {
+ if (info->band == IEEE80211_BAND_2GHZ)
+ txpower = ar->power_2G_ht20;
+ else
+ txpower = ar->power_5G_ht20;
+ }
+
+ *phyrate = txrate->idx;
+ *tpc += txpower[idx & 7];
+ } else {
+ if (info->band == IEEE80211_BAND_2GHZ) {
+ if (idx < 4)
+ txpower = ar->power_2G_cck;
+ else
+ txpower = ar->power_2G_ofdm;
+ } else {
+ txpower = ar->power_5G_leg;
+ idx += 4;
+ }
+
+ rate = &__carl9170_ratetable[idx];
+ *tpc += txpower[(rate->hw_value & 0x30) >> 4];
+ *phyrate = rate->hw_value & 0xf;
+ }
+
+ if (ar->eeprom.tx_mask == 1) {
+ *chains = AR9170_TX_PHY_TXCHAIN_1;
+ } else {
+ if (!(txrate->flags & IEEE80211_TX_RC_MCS) &&
+ rate && rate->bitrate >= 360)
+ *chains = AR9170_TX_PHY_TXCHAIN_1;
+ else
+ *chains = AR9170_TX_PHY_TXCHAIN_2;
+ }
+}
+
static __le32 carl9170_tx_physet(struct ar9170 *ar,
struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate)
{
- struct ieee80211_rate *rate = NULL;
- u32 power, chains;
+ unsigned int power = 0, chains = 0, phyrate = 0;
__le32 tmp;
tmp = cpu_to_le32(0);
@@ -682,35 +741,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
if (txrate->flags & IEEE80211_TX_RC_MCS) {
- u32 r = txrate->idx;
- u8 *txpower;
+ SET_VAL(AR9170_TX_PHY_MCS, phyrate, txrate->idx);
/* heavy clip control */
- tmp |= cpu_to_le32((r & 0x7) <<
+ tmp |= cpu_to_le32((txrate->idx & 0x7) <<
AR9170_TX_PHY_TX_HEAVY_CLIP_S);
- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
- if (info->band == IEEE80211_BAND_5GHZ)
- txpower = ar->power_5G_ht40;
- else
- txpower = ar->power_2G_ht40;
- } else {
- if (info->band == IEEE80211_BAND_5GHZ)
- txpower = ar->power_5G_ht20;
- else
- txpower = ar->power_2G_ht20;
- }
-
- power = txpower[r & 7];
-
- /* +1 dBm for HT40 */
- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- power += 2;
-
- r <<= AR9170_TX_PHY_MCS_S;
- BUG_ON(r & ~AR9170_TX_PHY_MCS);
-
- tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS);
tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
/*
@@ -720,34 +756,15 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
* tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
*/
} else {
- u8 *txpower;
- u32 mod;
- u32 phyrate;
- u8 idx = txrate->idx;
-
- if (info->band != IEEE80211_BAND_2GHZ) {
- idx += 4;
- txpower = ar->power_5G_leg;
- mod = AR9170_TX_PHY_MOD_OFDM;
+ if (info->band == IEEE80211_BAND_2GHZ) {
+ if (txrate->idx <= AR9170_TX_PHY_RATE_CCK_11M)
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_CCK);
+ else
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
} else {
- if (idx < 4) {
- txpower = ar->power_2G_cck;
- mod = AR9170_TX_PHY_MOD_CCK;
- } else {
- mod = AR9170_TX_PHY_MOD_OFDM;
- txpower = ar->power_2G_ofdm;
- }
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
}
- rate = &__carl9170_ratetable[idx];
-
- phyrate = rate->hw_value & 0xF;
- power = txpower[(rate->hw_value & 0x30) >> 4];
- phyrate <<= AR9170_TX_PHY_MCS_S;
-
- tmp |= cpu_to_le32(mod);
- tmp |= cpu_to_le32(phyrate);
-
/*
* short preamble seems to be broken too.
*
@@ -755,23 +772,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
* tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
*/
}
- power <<= AR9170_TX_PHY_TX_PWR_S;
- power &= AR9170_TX_PHY_TX_PWR;
- tmp |= cpu_to_le32(power);
-
- /* set TX chains */
- if (ar->eeprom.tx_mask == 1) {
- chains = AR9170_TX_PHY_TXCHAIN_1;
- } else {
- chains = AR9170_TX_PHY_TXCHAIN_2;
-
- /* >= 36M legacy OFDM - use only one chain */
- if (rate && rate->bitrate >= 360 &&
- !(txrate->flags & IEEE80211_TX_RC_MCS))
- chains = AR9170_TX_PHY_TXCHAIN_1;
- }
- tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S);
+ carl9170_tx_rate_tpc_chains(ar, info, txrate,
+ &phyrate, &power, &chains);
+ tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_MCS, phyrate));
+ tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TX_PWR, power));
+ tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TXCHAIN, chains));
return tmp;
}
@@ -1228,6 +1234,7 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
{
struct ieee80211_sta *sta;
struct carl9170_sta_info *sta_info;
+ struct ieee80211_tx_info *tx_info;
rcu_read_lock();
sta = __carl9170_get_tx_sta(ar, skb);
@@ -1235,12 +1242,13 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
goto out_rcu;
sta_info = (void *) sta->drv_priv;
- if (unlikely(sta_info->sleeping)) {
- struct ieee80211_tx_info *tx_info;
+ tx_info = IEEE80211_SKB_CB(skb);
+ if (unlikely(sta_info->sleeping) &&
+ !(tx_info->flags & (IEEE80211_TX_CTL_POLL_RESPONSE |
+ IEEE80211_TX_CTL_CLEAR_PS_FILT))) {
rcu_read_unlock();
- tx_info = IEEE80211_SKB_CB(skb);
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
atomic_dec(&ar->tx_ampdu_upload);
@@ -1439,3 +1447,154 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
if (ar->tx_schedule)
carl9170_tx(ar);
}
+
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+{
+ struct sk_buff *skb = NULL;
+ struct carl9170_vif_info *cvif;
+ struct ieee80211_tx_info *txinfo;
+ struct ieee80211_tx_rate *rate;
+ __le32 *data, *old = NULL;
+ unsigned int plcp, power, chains;
+ u32 word, ht1, off, addr, len;
+ int i = 0, err = 0;
+
+ rcu_read_lock();
+ cvif = rcu_dereference(ar->beacon_iter);
+retry:
+ if (ar->vifs == 0 || !cvif)
+ goto out_unlock;
+
+ list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
+ if (cvif->active && cvif->enable_beacon)
+ goto found;
+ }
+
+ if (!ar->beacon_enabled || i++)
+ goto out_unlock;
+
+ goto retry;
+
+found:
+ rcu_assign_pointer(ar->beacon_iter, cvif);
+
+ skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
+ NULL, NULL);
+
+ if (!skb) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ spin_lock_bh(&ar->beacon_lock);
+ data = (__le32 *)skb->data;
+ if (cvif->beacon)
+ old = (__le32 *)cvif->beacon->data;
+
+ off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
+ addr = ar->fw.beacon_addr + off;
+ len = roundup(skb->len + FCS_LEN, 4);
+
+ if ((off + len) > ar->fw.beacon_max_len) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "beacon does not "
+ "fit into device memory!\n");
+ }
+ err = -EINVAL;
+ goto err_unlock;
+ }
+
+ if (len > AR9170_MAC_BCN_LENGTH_MAX) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "no support for beacons "
+ "bigger than %d (yours:%d).\n",
+ AR9170_MAC_BCN_LENGTH_MAX, len);
+ }
+
+ err = -EMSGSIZE;
+ goto err_unlock;
+ }
+
+ ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
+ rate = &txinfo->control.rates[0];
+ carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
+ if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
+ if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
+ plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+ else
+ plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+ } else {
+ ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ plcp |= AR9170_MAC_BCN_HT2_SGI;
+
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
+ plcp |= AR9170_MAC_BCN_HT2_BW40;
+ }
+ if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
+ ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
+ plcp |= AR9170_MAC_BCN_HT2_BW40;
+ }
+
+ SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
+ }
+
+ SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
+ SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
+ SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
+ if (chains == AR9170_TX_PHY_TXCHAIN_2)
+ ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
+
+ carl9170_async_regwrite_begin(ar);
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
+ if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
+ else
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
+
+ for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
+ /*
+ * XXX: This accesses beyond skb data for up
+ * to the last 3 bytes!!
+ */
+
+ if (old && (data[i] == old[i]))
+ continue;
+
+ word = le32_to_cpu(data[i]);
+ carl9170_async_regwrite(addr + 4 * i, word);
+ }
+ carl9170_async_regwrite_finish();
+
+ dev_kfree_skb_any(cvif->beacon);
+ cvif->beacon = NULL;
+
+ err = carl9170_async_regwrite_result();
+ if (!err)
+ cvif->beacon = skb;
+ spin_unlock_bh(&ar->beacon_lock);
+ if (err)
+ goto err_free;
+
+ if (submit) {
+ err = carl9170_bcn_ctrl(ar, cvif->id,
+ CARL9170_BCN_CTRL_CAB_TRIGGER,
+ addr, skb->len + FCS_LEN);
+
+ if (err)
+ goto err_free;
+ }
+out_unlock:
+ rcu_read_unlock();
+ return 0;
+
+err_unlock:
+ spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+ rcu_read_unlock();
+ dev_kfree_skb_any(skb);
+ return err;
+}
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 333b69e..5538596 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -614,9 +614,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
goto err_free;
}
- usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
- AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
- carl9170_usb_cmd_complete, ar, 1);
+ if (ar->usb_ep_cmd_is_bulk)
+ usb_fill_bulk_urb(urb, ar->udev,
+ usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD),
+ cmd, cmd->hdr.len + 4,
+ carl9170_usb_cmd_complete, ar);
+ else
+ usb_fill_int_urb(urb, ar->udev,
+ usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD),
+ cmd, cmd->hdr.len + 4,
+ carl9170_usb_cmd_complete, ar, 1);
if (free_buf)
urb->transfer_flags |= URB_FREE_BUFFER;
@@ -1025,9 +1032,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw,
static int carl9170_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct usb_endpoint_descriptor *ep;
struct ar9170 *ar;
struct usb_device *udev;
- int err;
+ int i, err;
err = usb_reset_device(interface_to_usbdev(intf));
if (err)
@@ -1043,6 +1051,21 @@ static int carl9170_usb_probe(struct usb_interface *intf,
ar->intf = intf;
ar->features = id->driver_info;
+ /* We need to remember the type of endpoint 4 because it differs
+ * between high- and full-speed configuration. The high-speed
+ * configuration specifies it as interrupt and the full-speed
+ * configuration as bulk endpoint. This information is required
+ * later when sending urbs to that endpoint.
+ */
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) {
+ ep = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD &&
+ usb_endpoint_dir_out(ep) &&
+ usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK)
+ ar->usb_ep_cmd_is_bulk = true;
+ }
+
usb_set_intfdata(intf, ar);
SET_IEEE80211_DEV(ar->hw, &intf->dev);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index 15095c0..e651db8 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 11
-#define CARL9170FW_VERSION_MONTH 1
-#define CARL9170FW_VERSION_DAY 22
-#define CARL9170FW_VERSION_GIT "1.9.2"
+#define CARL9170FW_VERSION_MONTH 8
+#define CARL9170FW_VERSION_DAY 15
+#define CARL9170FW_VERSION_GIT "1.9.4"
#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h
index 9e1324b..ea17995 100644
--- a/drivers/net/wireless/ath/carl9170/wlan.h
+++ b/drivers/net/wireless/ath/carl9170/wlan.h
@@ -4,7 +4,7 @@
* RX/TX meta descriptor format
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -278,7 +278,7 @@ struct ar9170_tx_frame {
struct carl9170_tx_superframe {
struct carl9170_tx_superdesc s;
struct ar9170_tx_frame f;
-} __packed;
+} __packed __aligned(4);
#endif /* __CARL9170FW__ */
@@ -328,7 +328,7 @@ struct _carl9170_tx_superframe {
struct _carl9170_tx_superdesc s;
struct _ar9170_tx_hwdesc f;
u8 frame_data[0];
-} __packed;
+} __packed __aligned(4);
#define CARL9170_TX_SUPERDESC_LEN 24
#define AR9170_TX_HWDESC_LEN 8
@@ -404,16 +404,6 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
(t->DAidx & 0xc0) >> 6;
}
-enum ar9170_txq {
- AR9170_TXQ_BE,
-
- AR9170_TXQ_VI,
- AR9170_TXQ_VO,
- AR9170_TXQ_BK,
-
- __AR9170_NUM_TXQ,
-};
-
/*
* This is an workaround for several undocumented bugs.
* Don't mess with the QoS/AC <-> HW Queue map, if you don't
@@ -431,7 +421,14 @@ enum ar9170_txq {
* result, this makes the device pretty much useless
* for any serious 802.11n setup.
*/
-static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
+enum ar9170_txq {
+ AR9170_TXQ_BK = 0, /* TXQ0 */
+ AR9170_TXQ_BE, /* TXQ1 */
+ AR9170_TXQ_VI, /* TXQ2 */
+ AR9170_TXQ_VO, /* TXQ3 */
+
+ __AR9170_NUM_TXQ,
+};
#define AR9170_TXQ_DEPTH 32
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 480595f..36a7ce3 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -26,6 +26,16 @@ config B43
This driver can be built as a module (recommended) that will be called "b43".
If unsure, say M.
+config B43_BCMA
+ bool "Support for BCMA bus"
+ depends on B43 && (BCMA = y || BCMA = B43)
+ default y
+
+config B43_SSB
+ bool
+ depends on B43 && (SSB = y || SSB = B43)
+ default y
+
# Auto-select SSB PCI-HOST support, if possible
config B43_PCI_AUTOSELECT
bool
@@ -80,6 +90,12 @@ config B43_SDIO
#Data transfers to the device via PIO. We want it as a fallback even
# if we can do DMA.
+config B43_BCMA_PIO
+ bool
+ depends on B43_BCMA
+ select BCMA_BLOCKIO
+ default y
+
config B43_PIO
bool
depends on B43
@@ -98,15 +114,31 @@ config B43_PHY_N
affect other devices support and may provide support for basic needs.
config B43_PHY_LP
- bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
- depends on B43 && EXPERIMENTAL
+ bool "Support for low-power (LP-PHY) devices"
+ depends on B43
default y
---help---
Support for the LP-PHY.
The LP-PHY is a low-power PHY built into some notebooks
- and embedded devices. It supports 802.11a/g
+ and embedded devices. It supports 802.11a/b/g
(802.11a support is optional, and currently disabled).
+config B43_PHY_HT
+ bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)"
+ depends on B43 && EXPERIMENTAL
+ ---help---
+ Support for the HT-PHY.
+
+ Enables support for BCM4331 and possibly other chipsets with that PHY.
+
+config B43_PHY_LCN
+ bool "Support for LCN-PHY devices (BROKEN)"
+ depends on B43 && BROKEN
+ ---help---
+ Support for the LCN-PHY.
+
+ Say N, this is BROKEN and crashes driver.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
@@ -137,13 +169,3 @@ config B43_DEBUG
Say N, if you are a distributor or user building a release kernel
for production use.
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
-
-config B43_FORCE_PIO
- bool "Force usage of PIO instead of DMA"
- depends on B43 && B43_DEBUG
- ---help---
- This will disable DMA and always enable PIO instead.
-
- Say N!
- This is only for debugging the PIO engine code. You do
- _NOT_ want to enable this.
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index cef334a..4648bbf 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,4 +1,5 @@
b43-y += main.o
+b43-y += bus.o
b43-y += tables.o
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
@@ -9,6 +10,10 @@ b43-y += phy_a.o
b43-$(CONFIG_B43_PHY_N) += phy_n.o
b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o
+b43-$(CONFIG_B43_PHY_HT) += phy_ht.o
+b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o
+b43-$(CONFIG_B43_PHY_HT) += radio_2059.o
+b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 25a78cf..37110df 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -5,21 +5,18 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/hw_random.h>
+#include <linux/bcma/bcma.h>
#include <linux/ssb/ssb.h>
#include <net/mac80211.h>
#include "debugfs.h"
#include "leds.h"
#include "rfkill.h"
+#include "bus.h"
#include "lo.h"
#include "phy_common.h"
-/* The unique identifier of the firmware that's officially supported by
- * this driver version. */
-#define B43_SUPPORTED_FIRMWARE_ID "FW13"
-
-
#ifdef CONFIG_B43_DEBUG
# define B43_DEBUG 1
#else
@@ -90,6 +87,8 @@
#define B43_MMIO_PIO11_BASE4 0x300
#define B43_MMIO_PIO11_BASE5 0x340
+#define B43_MMIO_RADIO24_CONTROL 0x3D8 /* core rev >= 24 only */
+#define B43_MMIO_RADIO24_DATA 0x3DA /* core rev >= 24 only */
#define B43_MMIO_PHY_VER 0x3E0
#define B43_MMIO_PHY_RADIO 0x3E2
#define B43_MMIO_PHY0 0x3E6
@@ -108,21 +107,61 @@
#define B43_MMIO_RADIO_HWENABLED_LO 0x49A
#define B43_MMIO_GPIO_CONTROL 0x49C
#define B43_MMIO_GPIO_MASK 0x49E
+#define B43_MMIO_TXE0_CTL 0x500
+#define B43_MMIO_TXE0_AUX 0x502
+#define B43_MMIO_TXE0_TS_LOC 0x504
+#define B43_MMIO_TXE0_TIME_OUT 0x506
+#define B43_MMIO_TXE0_WM_0 0x508
+#define B43_MMIO_TXE0_WM_1 0x50A
+#define B43_MMIO_TXE0_PHYCTL 0x50C
+#define B43_MMIO_TXE0_STATUS 0x50E
+#define B43_MMIO_TXE0_MMPLCP0 0x510
+#define B43_MMIO_TXE0_MMPLCP1 0x512
+#define B43_MMIO_TXE0_PHYCTL1 0x514
+#define B43_MMIO_XMTFIFODEF 0x520
+#define B43_MMIO_XMTFIFO_FRAME_CNT 0x522 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_BYTE_CNT 0x524 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_HEAD 0x526 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_RD_PTR 0x528 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_WR_PTR 0x52A /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFODEF1 0x52C /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFOCMD 0x540
+#define B43_MMIO_XMTFIFOFLUSH 0x542
+#define B43_MMIO_XMTFIFOTHRESH 0x544
+#define B43_MMIO_XMTFIFORDY 0x546
+#define B43_MMIO_XMTFIFOPRIRDY 0x548
+#define B43_MMIO_XMTFIFORQPRI 0x54A
+#define B43_MMIO_XMTTPLATETXPTR 0x54C
+#define B43_MMIO_XMTTPLATEPTR 0x550
+#define B43_MMIO_SMPL_CLCT_STRPTR 0x552 /* core rev>= 22 only */
+#define B43_MMIO_SMPL_CLCT_STPPTR 0x554 /* core rev>= 22 only */
+#define B43_MMIO_SMPL_CLCT_CURPTR 0x556 /* core rev>= 22 only */
+#define B43_MMIO_XMTTPLATEDATALO 0x560
+#define B43_MMIO_XMTTPLATEDATAHI 0x562
+#define B43_MMIO_XMTSEL 0x568
+#define B43_MMIO_XMTTXCNT 0x56A
+#define B43_MMIO_XMTTXSHMADDR 0x56C
#define B43_MMIO_TSF_CFP_START_LOW 0x604
#define B43_MMIO_TSF_CFP_START_HIGH 0x606
#define B43_MMIO_TSF_CFP_PRETBTT 0x612
+#define B43_MMIO_TSF_CLK_FRAC_LOW 0x62E
+#define B43_MMIO_TSF_CLK_FRAC_HIGH 0x630
#define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
#define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
#define B43_MMIO_RNG 0x65A
#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */
-#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
+#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
+#define B43_MMIO_IFSSTAT 0x690
+#define B43_MMIO_IFSMEDBUSYCTL 0x692
+#define B43_MMIO_IFTXDUR 0x694
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
#define B43_MMIO_POWERUP_DELAY 0x6A8
#define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */
#define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */
#define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */
+#define B43_MMIO_WEPCTL 0x7C0
/* SPROM boardflags_lo values */
#define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
@@ -361,6 +400,10 @@ enum {
#define B43_PHYTYPE_G 0x02
#define B43_PHYTYPE_N 0x04
#define B43_PHYTYPE_LP 0x05
+#define B43_PHYTYPE_SSLPN 0x06
+#define B43_PHYTYPE_HT 0x07
+#define B43_PHYTYPE_LCN 0x08
+#define B43_PHYTYPE_LCNXN 0x09
/* PHYRegisters */
#define B43_PHY_ILT_A_CTRL 0x0072
@@ -414,6 +457,23 @@ enum {
#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
+/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */
+#define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */
+#define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */
+#define B43_BCMA_IOCTL_MACPHYCLKEN 0x00000010 /* MAC PHY Clock Control Enable */
+#define B43_BCMA_IOCTL_PLLREFSEL 0x00000020 /* PLL Frequency Reference Select */
+#define B43_BCMA_IOCTL_PHY_BW 0x000000C0 /* PHY band width and clock speed mask (N-PHY+ only?) */
+#define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */
+#define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */
+#define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */
+#define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */
+
+/* BCMA 802.11 core specific IO status (BCMA_IOST) flags */
+#define B43_BCMA_IOST_2G_PHY 0x00000001 /* 2.4G capable phy */
+#define B43_BCMA_IOST_5G_PHY 0x00000002 /* 5G capable phy */
+#define B43_BCMA_IOST_FASTCLKA 0x00000004 /* Fast Clock Available */
+#define B43_BCMA_IOST_DUALB_PHY 0x00000008 /* Dualband phy */
+
/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
#define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */
@@ -569,6 +629,8 @@ struct b43_dma {
struct b43_dmaring *rx_ring;
u32 translation; /* Routing bits */
+ bool translation_in_low; /* Should translation bit go into low addr? */
+ bool parity; /* Check for parity */
};
struct b43_pio_txqueue;
@@ -668,6 +730,12 @@ struct b43_firmware_file {
enum b43_firmware_file_type type;
};
+enum b43_firmware_hdr_format {
+ B43_FW_HDR_598,
+ B43_FW_HDR_410,
+ B43_FW_HDR_351,
+};
+
/* Pointers to the firmware data and meta information about it. */
struct b43_firmware {
/* Microcode */
@@ -684,6 +752,9 @@ struct b43_firmware {
/* Firmware patchlevel */
u16 patch;
+ /* Format of header used by firmware */
+ enum b43_firmware_hdr_format hdr_format;
+
/* Set to true, if we are using an opensource firmware.
* Use this to check for proprietary vs opensource. */
bool opensource;
@@ -707,7 +778,7 @@ enum {
/* Data structure for one wireless device (802.11 core) */
struct b43_wldev {
- struct ssb_device *sdev;
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
/* The device initialization status.
@@ -849,7 +920,7 @@ struct b43_wl {
struct b43_leds leds;
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
- u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
+ u8 pio_scratchspace[118] __attribute__((__aligned__(8)));
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
};
@@ -879,36 +950,59 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
return wl->hw->conf.channel->band;
}
+static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
+{
+ return wldev->dev->bus_may_powerdown(wldev->dev);
+}
+static inline int b43_bus_powerup(struct b43_wldev *wldev, bool dynamic_pctl)
+{
+ return wldev->dev->bus_powerup(wldev->dev, dynamic_pctl);
+}
+static inline int b43_device_is_enabled(struct b43_wldev *wldev)
+{
+ return wldev->dev->device_is_enabled(wldev->dev);
+}
+static inline void b43_device_enable(struct b43_wldev *wldev,
+ u32 core_specific_flags)
+{
+ wldev->dev->device_enable(wldev->dev, core_specific_flags);
+}
+static inline void b43_device_disable(struct b43_wldev *wldev,
+ u32 core_specific_flags)
+{
+ wldev->dev->device_disable(wldev->dev, core_specific_flags);
+}
+
static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
{
- return ssb_read16(dev->sdev, offset);
+ return dev->dev->read16(dev->dev, offset);
}
static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
{
- ssb_write16(dev->sdev, offset, value);
+ dev->dev->write16(dev->dev, offset, value);
}
static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
{
- return ssb_read32(dev->sdev, offset);
+ return dev->dev->read32(dev->dev, offset);
}
static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
{
- ssb_write32(dev->sdev, offset, value);
+ dev->dev->write32(dev->dev, offset, value);
}
static inline void b43_block_read(struct b43_wldev *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
- ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+ dev->dev->block_read(dev->dev, buffer, count, offset, reg_width);
}
static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
- ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+ dev->dev->block_write(dev->dev, buffer, count, offset, reg_width);
}
static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
@@ -916,21 +1010,11 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
return dev->__using_pio_transfers;
}
-#ifdef CONFIG_B43_FORCE_PIO
-# define B43_PIO_DEFAULT 1
-#else
-# define B43_PIO_DEFAULT 0
-#endif
-
/* Message printing */
-void b43info(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43err(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43warn(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43dbg(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
+__printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43warn(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43dbg(struct b43_wl *wl, const char *fmt, ...);
/* A WARN_ON variant that vanishes when b43 debugging is disabled.
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 59f59fa..e751fde 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -4,7 +4,7 @@
debugfs driver debugging code
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
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
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 5deeb14..ca70267 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -4,7 +4,7 @@
DMA ringbuffer and descriptor allocation/management
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Some code in this file is derived from the b44.c driver
Copyright (C) 2002 David S. Miller
@@ -47,6 +47,38 @@
* into separate slots. */
#define TX_SLOTS_PER_FRAME 2
+static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr,
+ enum b43_addrtype addrtype)
+{
+ u32 uninitialized_var(addr);
+
+ switch (addrtype) {
+ case B43_DMA_ADDR_LOW:
+ addr = lower_32_bits(dmaaddr);
+ if (dma->translation_in_low) {
+ addr &= ~SSB_DMA_TRANSLATION_MASK;
+ addr |= dma->translation;
+ }
+ break;
+ case B43_DMA_ADDR_HIGH:
+ addr = upper_32_bits(dmaaddr);
+ if (!dma->translation_in_low) {
+ addr &= ~SSB_DMA_TRANSLATION_MASK;
+ addr |= dma->translation;
+ }
+ break;
+ case B43_DMA_ADDR_EXT:
+ if (dma->translation_in_low)
+ addr = lower_32_bits(dmaaddr);
+ else
+ addr = upper_32_bits(dmaaddr);
+ addr &= SSB_DMA_TRANSLATION_MASK;
+ addr >>= SSB_DMA_TRANSLATION_SHIFT;
+ break;
+ }
+
+ return addr;
+}
/* 32bit DMA ops. */
static
@@ -77,10 +109,9 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma32) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addr |= ring->dev->dma.translation;
+ addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
+ addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
+
ctl = bufsize & B43_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
ctl |= B43_DMA32_DCTL_DTABLEEND;
@@ -170,11 +201,10 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma64) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- addrlo = (u32) (dmaaddr & 0xFFFFFFFF);
- addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= (ring->dev->dma.translation << 1);
+ addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
+ addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH);
+ addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
+
if (slot == ring->nr_slots - 1)
ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
if (start)
@@ -333,10 +363,10 @@ static inline
dma_addr_t dmaaddr;
if (tx) {
- dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
buf, len, DMA_TO_DEVICE);
} else {
- dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
buf, len, DMA_FROM_DEVICE);
}
@@ -348,10 +378,10 @@ static inline
dma_addr_t addr, size_t len, int tx)
{
if (tx) {
- dma_unmap_single(ring->dev->sdev->dma_dev,
+ dma_unmap_single(ring->dev->dev->dma_dev,
addr, len, DMA_TO_DEVICE);
} else {
- dma_unmap_single(ring->dev->sdev->dma_dev,
+ dma_unmap_single(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
}
@@ -361,7 +391,7 @@ static inline
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_cpu(ring->dev->sdev->dma_dev,
+ dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -370,7 +400,7 @@ static inline
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_device(ring->dev->sdev->dma_dev,
+ dma_sync_single_for_device(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -389,33 +419,34 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
gfp_t flags = GFP_KERNEL;
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
- * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
- * has shown that 4K is sufficient for the latter as long as the buffer
- * does not cross an 8K boundary.
- *
- * For unknown reasons - possibly a hardware error - the BCM4311 rev
- * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
- * which accounts for the GFP_DMA flag below.
- *
- * The flags here must match the flags in free_ringmemory below!
+ * alignment and 8K buffers for 64-bit DMA with 8K alignment.
+ * In practice we could use smaller buffers for the latter, but the
+ * alignment is really important because of the hardware bug. If bit
+ * 0x00001000 is used in DMA address, some hardware (like BCM4331)
+ * copies that bit into B43_DMA64_RXSTATUS and we get false values from
+ * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use
+ * more than 256 slots for ring.
*/
- if (ring->type == B43_DMA_64BIT)
- flags |= GFP_DMA;
- ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev,
- B43_DMA_RINGMEMSIZE,
- &(ring->dmabase), flags);
+ u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+ B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+
+ ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+ ring_mem_size, &(ring->dmabase),
+ flags);
if (!ring->descbase) {
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
return -ENOMEM;
}
- memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
+ memset(ring->descbase, 0, ring_mem_size);
return 0;
}
static void free_ringmemory(struct b43_dmaring *ring)
{
- dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE,
+ u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+ B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+ dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size,
ring->descbase, ring->dmabase);
}
@@ -523,7 +554,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
dma_addr_t addr,
size_t buffersize, bool dma_to_device)
{
- if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr)))
+ if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
return 1;
switch (ring->type) {
@@ -658,36 +689,37 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
- u32 trans = ring->dev->dma.translation;
+ bool parity = ring->dev->dma.parity;
+ u32 addrlo;
+ u32 addrhi;
if (ring->tx) {
if (ring->type == B43_DMA_64BIT) {
u64 ringbase = (u64) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+ addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA64_TXENABLE;
value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
& B43_DMA64_TXADDREXT_MASK;
+ if (!parity)
+ value |= B43_DMA64_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_TXCTL, value);
- b43_dma_write(ring, B43_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_TXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
- | (trans << 1));
+ b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo);
+ b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi);
} else {
u32 ringbase = (u32) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA32_TXENABLE;
value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
& B43_DMA32_TXADDREXT_MASK;
+ if (!parity)
+ value |= B43_DMA32_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_TXCTL, value);
- b43_dma_write(ring, B43_DMA32_TXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA32_TXRING, addrlo);
}
} else {
err = alloc_initial_descbuffers(ring);
@@ -695,35 +727,34 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
goto out;
if (ring->type == B43_DMA_64BIT) {
u64 ringbase = (u64) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+ addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
value |= B43_DMA64_RXENABLE;
value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
& B43_DMA64_RXADDREXT_MASK;
+ if (!parity)
+ value |= B43_DMA64_RXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_RXCTL, value);
- b43_dma_write(ring, B43_DMA64_RXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
- | (trans << 1));
+ b43_dma_write(ring, B43_DMA64_RXRINGLO, addrlo);
+ b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi);
b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc64));
} else {
u32 ringbase = (u32) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT);
value |= B43_DMA32_RXENABLE;
value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
& B43_DMA32_RXADDREXT_MASK;
+ if (!parity)
+ value |= B43_DMA32_RXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_RXCTL, value);
- b43_dma_write(ring, B43_DMA32_RXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA32_RXRING, addrlo);
b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc32));
}
@@ -757,14 +788,14 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring)
static void free_all_descbuffers(struct b43_dmaring *ring)
{
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ /* get meta - ignore returned value */
+ ring->ops->idx2desc(ring, i, &meta);
if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) {
B43_WARN_ON(!ring->tx);
@@ -786,9 +817,23 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
u32 tmp;
u16 mmio_base;
- tmp = b43_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
- return DMA_BIT_MASK(64);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+ if (tmp & BCMA_IOST_DMA64)
+ return DMA_BIT_MASK(64);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+ if (tmp & SSB_TMSHIGH_DMA64)
+ return DMA_BIT_MASK(64);
+ break;
+#endif
+ }
+
mmio_base = b43_dmacontroller_base(0, 0);
b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
@@ -849,8 +894,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
ring->current_slot = -1;
} else {
if (ring->index == 0) {
- ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE;
- ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET;
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE;
+ ring->frameoffset = B43_DMA0_RX_FW598_FO;
+ break;
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE;
+ ring->frameoffset = B43_DMA0_RX_FW351_FO;
+ break;
+ }
} else
B43_WARN_ON(1);
}
@@ -869,7 +923,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
goto err_kfree_meta;
/* test for ability to dma to txhdr_cache */
- dma_test = dma_map_single(dev->sdev->dma_dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
b43_txhdr_size(dev),
DMA_TO_DEVICE);
@@ -884,7 +938,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
if (!ring->txhdr_cache)
goto err_kfree_meta;
- dma_test = dma_map_single(dev->sdev->dma_dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
b43_txhdr_size(dev),
DMA_TO_DEVICE);
@@ -898,7 +952,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
}
}
- dma_unmap_single(dev->sdev->dma_dev,
+ dma_unmap_single(dev->dev->dma_dev,
dma_test, b43_txhdr_size(dev),
DMA_TO_DEVICE);
}
@@ -1013,9 +1067,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
/* Try to set the DMA mask. If it fails, try falling back to a
* lower mask, as we can always also support a lower one. */
while (1) {
- err = dma_set_mask(dev->sdev->dma_dev, mask);
+ err = dma_set_mask(dev->dev->dma_dev, mask);
if (!err) {
- err = dma_set_coherent_mask(dev->sdev->dma_dev, mask);
+ err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
if (!err)
break;
}
@@ -1043,6 +1097,25 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
return 0;
}
+/* Some hardware with 64-bit DMA seems to be bugged and looks for translation
+ * bit in low address word instead of high one.
+ */
+static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
+ enum b43_dmatype type)
+{
+ if (type != B43_DMA_64BIT)
+ return 1;
+
+#ifdef CONFIG_B43_SSB
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ !(dev->dev->sdev->bus->host_pci->is_pcie &&
+ ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
+ return 1;
+#endif
+ return 0;
+}
+
int b43_dma_init(struct b43_wldev *dev)
{
struct b43_dma *dma = &dev->dma;
@@ -1055,7 +1128,27 @@ int b43_dma_init(struct b43_wldev *dev)
err = b43_dma_set_mask(dev, dmamask);
if (err)
return err;
- dma->translation = ssb_dma_translation(dev->sdev);
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ dma->translation = bcma_core_dma_translation(dev->dev->bdev);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ dma->translation = ssb_dma_translation(dev->dev->sdev);
+ break;
+#endif
+ }
+ dma->translation_in_low = b43_dma_translation_in_low_word(dev, type);
+
+ dma->parity = true;
+#ifdef CONFIG_B43_BCMA
+ /* TODO: find out which SSB devices need disabling parity */
+ if (dev->dev->bus_type == B43_BUS_BCMA)
+ dma->parity = false;
+#endif
err = -ENOMEM;
/* setup TX DMA channels. */
@@ -1085,7 +1178,7 @@ int b43_dma_init(struct b43_wldev *dev)
goto err_destroy_mcast;
/* No support for the TX status DMA ring. */
- B43_WARN_ON(dev->sdev->id.revision < 5);
+ B43_WARN_ON(dev->dev->core_rev < 5);
b43dbg(dev->wl, "%u-bit DMA initialized\n",
(unsigned int)type);
@@ -1388,7 +1481,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
{
const struct b43_dma_ops *ops;
struct b43_dmaring *ring;
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
static const struct b43_txstatus fake; /* filled with 0 */
const struct b43_txstatus *txstat;
@@ -1443,7 +1535,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
ops = ring->ops;
while (1) {
B43_WARN_ON(slot < 0 || slot >= ring->nr_slots);
- desc = ops->idx2desc(ring, slot, &meta);
+ /* get meta - ignore returned value */
+ ops->idx2desc(ring, slot, &meta);
if (b43_dma_ptr_is_poisoned(meta->skb)) {
b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) "
@@ -1626,6 +1719,25 @@ drop_recycle_buffer:
sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
}
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
+{
+ int current_slot, previous_slot;
+
+ B43_WARN_ON(ring->tx);
+
+ /* Device has filled all buffers, drop all packets and let TCP
+ * decrease speed.
+ * Decrement RX index by one will let the device to see all slots
+ * as free again
+ */
+ /*
+ *TODO: How to increase rx_drop in mac80211?
+ */
+ current_slot = ring->ops->get_current_rxslot(ring);
+ previous_slot = prev_slot(ring, current_slot);
+ ring->ops->set_current_rxslot(ring, previous_slot);
+}
+
void b43_dma_rx(struct b43_dmaring *ring)
{
const struct b43_dma_ops *ops = ring->ops;
@@ -1641,6 +1753,7 @@ void b43_dma_rx(struct b43_dmaring *ring)
dma_rx(ring, &slot);
update_max_used_slots(ring, ++used_slots);
}
+ wmb();
ops->set_current_rxslot(ring, slot);
ring->current_slot = slot;
}
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index e8a80a1..df8c8cd 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -9,7 +9,7 @@
/* DMA-Interrupt reasons. */
#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
| (1 << 14) | (1 << 15))
-#define B43_DMAIRQ_NONFATALMASK (1 << 13)
+#define B43_DMAIRQ_RDESC_UFLOW (1 << 13)
#define B43_DMAIRQ_RX_DONE (1 << 16)
/*** 32-bit DMA Engine. ***/
@@ -20,6 +20,7 @@
#define B43_DMA32_TXSUSPEND 0x00000002
#define B43_DMA32_TXLOOPBACK 0x00000004
#define B43_DMA32_TXFLUSH 0x00000010
+#define B43_DMA32_TXPARITYDISABLE 0x00000800
#define B43_DMA32_TXADDREXT_MASK 0x00030000
#define B43_DMA32_TXADDREXT_SHIFT 16
#define B43_DMA32_TXRING 0x04
@@ -44,6 +45,7 @@
#define B43_DMA32_RXFROFF_MASK 0x000000FE
#define B43_DMA32_RXFROFF_SHIFT 1
#define B43_DMA32_RXDIRECTFIFO 0x00000100
+#define B43_DMA32_RXPARITYDISABLE 0x00000800
#define B43_DMA32_RXADDREXT_MASK 0x00030000
#define B43_DMA32_RXADDREXT_SHIFT 16
#define B43_DMA32_RXRING 0x14
@@ -84,6 +86,7 @@ struct b43_dmadesc32 {
#define B43_DMA64_TXSUSPEND 0x00000002
#define B43_DMA64_TXLOOPBACK 0x00000004
#define B43_DMA64_TXFLUSH 0x00000010
+#define B43_DMA64_TXPARITYDISABLE 0x00000800
#define B43_DMA64_TXADDREXT_MASK 0x00030000
#define B43_DMA64_TXADDREXT_SHIFT 16
#define B43_DMA64_TXINDEX 0x04
@@ -111,6 +114,7 @@ struct b43_dmadesc32 {
#define B43_DMA64_RXFROFF_MASK 0x000000FE
#define B43_DMA64_RXFROFF_SHIFT 1
#define B43_DMA64_RXDIRECTFIFO 0x00000100
+#define B43_DMA64_RXPARITYDISABLE 0x00000800
#define B43_DMA64_RXADDREXT_MASK 0x00030000
#define B43_DMA64_RXADDREXT_SHIFT 16
#define B43_DMA64_RXINDEX 0x24
@@ -157,13 +161,17 @@ struct b43_dmadesc_generic {
} __packed;
/* Misc DMA constants */
-#define B43_DMA_RINGMEMSIZE PAGE_SIZE
-#define B43_DMA0_RX_FRAMEOFFSET 30
+#define B43_DMA32_RINGMEMSIZE 4096
+#define B43_DMA64_RINGMEMSIZE 8192
+/* Offset of frame with actual data */
+#define B43_DMA0_RX_FW598_FO 38
+#define B43_DMA0_RX_FW351_FO 30
/* DMA engine tuning knobs */
#define B43_TXRING_SLOTS 256
-#define B43_RXRING_SLOTS 64
-#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
+#define B43_RXRING_SLOTS 256
+#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
/* Pointer poison */
#define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM))
@@ -208,6 +216,12 @@ enum b43_dmatype {
B43_DMA_64BIT = 64,
};
+enum b43_addrtype {
+ B43_DMA_ADDR_LOW,
+ B43_DMA_ADDR_HIGH,
+ B43_DMA_ADDR_EXT,
+};
+
struct b43_dmaring {
/* Lowlevel DMA ops. */
const struct b43_dma_ops *ops;
@@ -281,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev,
void b43_dma_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
+
void b43_dma_rx(struct b43_dmaring *ring);
void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 0cafafe..a38c1c6 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
led->led_dev.default_trigger = default_trigger;
led->led_dev.brightness_set = b43_led_brightness_set;
- err = led_classdev_register(dev->sdev->dev, &led->led_dev);
+ err = led_classdev_register(dev->dev->dev, &led->led_dev);
if (err) {
b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
led->wl = NULL;
@@ -215,13 +215,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
enum b43_led_behaviour *behaviour,
bool *activelow)
{
- struct ssb_bus *bus = dev->sdev->bus;
u8 sprom[4];
- sprom[0] = bus->sprom.gpio0;
- sprom[1] = bus->sprom.gpio1;
- sprom[2] = bus->sprom.gpio2;
- sprom[3] = bus->sprom.gpio3;
+ sprom[0] = dev->dev->bus_sprom->gpio0;
+ sprom[1] = dev->dev->bus_sprom->gpio1;
+ sprom[2] = dev->dev->bus_sprom->gpio2;
+ sprom[3] = dev->dev->bus_sprom->gpio3;
if (sprom[led_index] == 0xFF) {
/* There is no LED information in the SPROM
@@ -231,12 +230,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
case 0:
*behaviour = B43_LED_ACTIVITY;
*activelow = 1;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)
*behaviour = B43_LED_RADIO_ALL;
break;
case 1:
*behaviour = B43_LED_RADIO_B;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
*behaviour = B43_LED_ASSOC;
break;
case 2:
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 2ef7d4b..4c82d58 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -6,7 +6,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005, 2006 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
rfover |= pga;
rfover |= lna;
rfover |= trsw_rx;
- if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+ if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)
&& phy->rev > 6)
rfover |= B43_PHY_RFOVERVAL_EXTLNA;
@@ -301,14 +301,12 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
max_rx_gain = 0;
if (has_loopback_gain(phy)) {
- int trsw_rx = 0;
int trsw_rx_gain;
if (use_trsw_rx) {
trsw_rx_gain = gphy->trsw_rx_gain / 2;
if (max_rx_gain >= trsw_rx_gain) {
trsw_rx_gain = max_rx_gain - trsw_rx_gain;
- trsw_rx = 0x20;
}
} else
trsw_rx_gain = max_rx_gain;
@@ -387,7 +385,7 @@ struct lo_g_saved_values {
static void lo_measure_setup(struct b43_wldev *dev,
struct lo_g_saved_values *sav)
{
- struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_txpower_lo_control *lo = gphy->lo_control;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 4db716b..b0c2801 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4,9 +4,10 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2009 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2009 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+ Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
SDIO support
Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
@@ -33,11 +34,10 @@
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include <linux/io.h>
@@ -65,9 +65,9 @@ MODULE_AUTHOR("Martin Langer");
MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_AUTHOR("Gábor Stefanik");
+MODULE_AUTHOR("Rafał Miłecki");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43/ucode11.fw");
MODULE_FIRMWARE("b43/ucode13.fw");
MODULE_FIRMWARE("b43/ucode14.fw");
@@ -109,10 +109,22 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
module_param_named(verbose, b43_modparam_verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
-static int b43_modparam_pio = B43_PIO_DEFAULT;
+static int b43_modparam_pio = 0;
module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
+#ifdef CONFIG_B43_BCMA
+static const struct bcma_device_id b43_bcma_tbl[] = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
+#endif
+
+#ifdef CONFIG_B43_SSB
static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
@@ -126,8 +138,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
SSB_DEVTABLE_END
};
-
MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+#endif
/* Channel and ratetables are shared for all devices.
* They can't be const, because ieee80211 puts some precalculated
@@ -309,6 +321,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
static int b43_wireless_core_start(struct b43_wldev *dev);
+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf,
+ u32 changed);
static int b43_ratelimit(struct b43_wl *wl)
{
@@ -548,7 +564,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
{
u32 low, high;
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
/* The hardware guarantees us an atomic read, if we
* read the low register first. */
@@ -586,7 +602,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
{
u32 low, high;
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
low = tsf;
high = (tsf >> 32);
@@ -713,52 +729,59 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
for (i = 0; i < 5; i++)
b43_ram_write(dev, i * 4, buffer[i]);
- b43_write16(dev, 0x0568, 0x0000);
- if (dev->sdev->id.revision < 11)
- b43_write16(dev, 0x07C0, 0x0000);
+ b43_write16(dev, B43_MMIO_XMTSEL, 0x0000);
+
+ if (dev->dev->core_rev < 11)
+ b43_write16(dev, B43_MMIO_WEPCTL, 0x0000);
else
- b43_write16(dev, 0x07C0, 0x0100);
+ b43_write16(dev, B43_MMIO_WEPCTL, 0x0100);
+
value = (ofdm ? 0x41 : 0x40);
- b43_write16(dev, 0x050C, value);
- if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP))
- b43_write16(dev, 0x0514, 0x1A02);
- b43_write16(dev, 0x0508, 0x0000);
- b43_write16(dev, 0x050A, 0x0000);
- b43_write16(dev, 0x054C, 0x0000);
- b43_write16(dev, 0x056A, 0x0014);
- b43_write16(dev, 0x0568, 0x0826);
- b43_write16(dev, 0x0500, 0x0000);
- if (!pa_on && (phy->type == B43_PHYTYPE_N)) {
- //SPEC TODO
- }
+ b43_write16(dev, B43_MMIO_TXE0_PHYCTL, value);
+ if (phy->type == B43_PHYTYPE_N || phy->type == B43_PHYTYPE_LP ||
+ phy->type == B43_PHYTYPE_LCN)
+ b43_write16(dev, B43_MMIO_TXE0_PHYCTL1, 0x1A02);
+
+ b43_write16(dev, B43_MMIO_TXE0_WM_0, 0x0000);
+ b43_write16(dev, B43_MMIO_TXE0_WM_1, 0x0000);
+
+ b43_write16(dev, B43_MMIO_XMTTPLATETXPTR, 0x0000);
+ b43_write16(dev, B43_MMIO_XMTTXCNT, 0x0014);
+ b43_write16(dev, B43_MMIO_XMTSEL, 0x0826);
+ b43_write16(dev, B43_MMIO_TXE0_CTL, 0x0000);
+
+ if (!pa_on && phy->type == B43_PHYTYPE_N)
+ ; /*b43_nphy_pa_override(dev, false) */
switch (phy->type) {
case B43_PHYTYPE_N:
- b43_write16(dev, 0x0502, 0x00D0);
+ case B43_PHYTYPE_LCN:
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0);
break;
case B43_PHYTYPE_LP:
- b43_write16(dev, 0x0502, 0x0050);
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050);
break;
default:
- b43_write16(dev, 0x0502, 0x0030);
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0030);
}
+ b43_read16(dev, B43_MMIO_TXE0_AUX);
if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
b43_radio_write16(dev, 0x0051, 0x0017);
for (i = 0x00; i < max_loop; i++) {
- value = b43_read16(dev, 0x050E);
+ value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
if (value & 0x0080)
break;
udelay(10);
}
for (i = 0x00; i < 0x0A; i++) {
- value = b43_read16(dev, 0x050E);
+ value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
if (value & 0x0400)
break;
udelay(10);
}
for (i = 0x00; i < 0x19; i++) {
- value = b43_read16(dev, 0x0690);
+ value = b43_read16(dev, B43_MMIO_IFSSTAT);
if (!(value & 0x0100))
break;
udelay(10);
@@ -1132,7 +1155,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit write */
b43_read32(dev, B43_MMIO_MACCTL);
- if (awake && dev->sdev->id.revision >= 5) {
+ if (awake && dev->dev->core_rev >= 5) {
/* Wait for the microcode to wake up. */
for (i = 0; i < 100; i++) {
ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
@@ -1144,35 +1167,85 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
}
}
-static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+#ifdef CONFIG_B43_BCMA
+static void b43_bcma_phy_reset(struct b43_wldev *dev)
{
+ u32 flags;
+
+ /* Put PHY into reset */
+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ flags |= B43_BCMA_IOCTL_PHY_RESET;
+ flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+ udelay(2);
+
+ /* Take PHY out of reset */
+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ flags &= ~B43_BCMA_IOCTL_PHY_RESET;
+ flags |= BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+ udelay(1);
+
+ /* Do not force clock anymore */
+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ flags &= ~BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+ udelay(1);
+}
+
+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+ b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
+ bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
+ b43_bcma_phy_reset(dev);
+ bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true);
+}
+#endif
+
+static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+ struct ssb_device *sdev = dev->dev->sdev;
u32 tmslow;
+ u32 flags = 0;
+ if (gmode)
+ flags |= B43_TMSLOW_GMODE;
flags |= B43_TMSLOW_PHYCLKEN;
flags |= B43_TMSLOW_PHYRESET;
if (dev->phy.type == B43_PHYTYPE_N)
flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
- ssb_device_enable(dev->sdev, flags);
+ b43_device_enable(dev, flags);
msleep(2); /* Wait for the PLL to turn on. */
/* Now take the PHY out of Reset again */
- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
+ tmslow = ssb_read32(sdev, SSB_TMSLOW);
tmslow |= SSB_TMSLOW_FGC;
tmslow &= ~B43_TMSLOW_PHYRESET;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */
+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */
+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
}
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
u32 macctl;
- b43_ssb_wireless_core_reset(dev, flags);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ b43_bcma_wireless_core_reset(dev, gmode);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_ssb_wireless_core_reset(dev, gmode);
+ break;
+#endif
+ }
/* Turn Analog ON, but only if we already know the PHY-type.
* This protects against very early setup where we don't know the
@@ -1183,7 +1256,7 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE;
- if (flags & B43_TMSLOW_GMODE)
+ if (gmode)
macctl |= B43_MACCTL_GMODE;
macctl |= B43_MACCTL_IHR_ENABLED;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
@@ -1221,7 +1294,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev)
{
u32 dummy;
- if (dev->sdev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
return;
/* Read all entries from the microcode TXstatus FIFO
* and throw them away.
@@ -1427,9 +1500,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
/* Get the mask of available antennas. */
if (dev->phy.gmode)
- antenna_mask = dev->sdev->bus->sprom.ant_available_bg;
+ antenna_mask = dev->dev->bus_sprom->ant_available_bg;
else
- antenna_mask = dev->sdev->bus->sprom.ant_available_a;
+ antenna_mask = dev->dev->bus_sprom->ant_available_a;
if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
/* This antenna is not available. Fall back to default. */
@@ -1645,7 +1718,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is enough. */
b43_do_beacon_update_trigger_work(dev);
mmiowb();
@@ -1690,7 +1763,7 @@ static void b43_update_templates(struct b43_wl *wl)
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{
b43_time_lock(dev);
- if (dev->sdev->id.revision >= 3) {
+ if (dev->dev->core_rev >= 3) {
b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
} else {
@@ -1828,30 +1901,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
}
}
- if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
- B43_DMAIRQ_NONFATALMASK))) {
- if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {
- b43err(dev->wl, "Fatal DMA error: "
- "0x%08X, 0x%08X, 0x%08X, "
- "0x%08X, 0x%08X, 0x%08X\n",
- dma_reason[0], dma_reason[1],
- dma_reason[2], dma_reason[3],
- dma_reason[4], dma_reason[5]);
- b43err(dev->wl, "This device does not support DMA "
+ if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) {
+ b43err(dev->wl,
+ "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3],
+ dma_reason[4], dma_reason[5]);
+ b43err(dev->wl, "This device does not support DMA "
"on your system. It will now be switched to PIO.\n");
- /* Fall back to PIO transfers if we get fatal DMA errors! */
- dev->use_pio = 1;
- b43_controller_restart(dev, "DMA error");
- return;
- }
- if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
- b43err(dev->wl, "DMA error: "
- "0x%08X, 0x%08X, 0x%08X, "
- "0x%08X, 0x%08X, 0x%08X\n",
- dma_reason[0], dma_reason[1],
- dma_reason[2], dma_reason[3],
- dma_reason[4], dma_reason[5]);
- }
+ /* Fall back to PIO transfers if we get fatal DMA errors! */
+ dev->use_pio = true;
+ b43_controller_restart(dev, "DMA error");
+ return;
}
if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
@@ -1870,6 +1931,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
handle_irq_noise(dev);
/* Check the DMA reason registers for received data. */
+ if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
+ if (B43_DEBUG)
+ b43warn(dev->wl, "RX descriptor underrun\n");
+ b43_dma_handle_rx_overflow(dev->dma.rx_ring);
+ }
if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
if (b43_using_pio_transfers(dev))
b43_pio_rx(dev->pio.rx_queue);
@@ -1924,10 +1990,10 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
return IRQ_NONE;
reason &= dev->irq_mask;
if (!reason)
- return IRQ_HANDLED;
+ return IRQ_NONE;
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
- & 0x0001DC00;
+ & 0x0001FC00;
dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
& 0x0000DC00;
dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
@@ -2064,7 +2130,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
B43_WARN_ON(1);
return -ENOSYS;
}
- err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev);
+ err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
if (err == -ENOENT) {
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
@@ -2114,26 +2180,48 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
{
struct b43_wldev *dev = ctx->dev;
struct b43_firmware *fw = &ctx->dev->fw;
- const u8 rev = ctx->dev->sdev->id.revision;
+ const u8 rev = ctx->dev->dev->core_rev;
const char *filename;
u32 tmshigh;
int err;
+ /* Files for HT and LCN were found by trying one by one */
+
/* Get microcode */
- if ((rev >= 5) && (rev <= 10))
+ if ((rev >= 5) && (rev <= 10)) {
filename = "ucode5";
- else if ((rev >= 11) && (rev <= 12))
+ } else if ((rev >= 11) && (rev <= 12)) {
filename = "ucode11";
- else if (rev == 13)
+ } else if (rev == 13) {
filename = "ucode13";
- else if (rev == 14)
+ } else if (rev == 14) {
filename = "ucode14";
- else if (rev == 15)
+ } else if (rev == 15) {
filename = "ucode15";
- else if ((rev >= 16) && (rev <= 20))
- filename = "ucode16_mimo";
- else
- goto err_no_ucode;
+ } else {
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_N:
+ if (rev >= 16)
+ filename = "ucode16_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ucode29_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "ucode24_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ default:
+ goto err_no_ucode;
+ }
+ }
err = b43_do_request_fw(ctx, filename, &fw->ucode);
if (err)
goto err_load;
@@ -2158,7 +2246,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1initvals5";
else
@@ -2192,6 +2280,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0initvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0initvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
@@ -2203,7 +2303,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1bsinitvals5";
else
@@ -2239,6 +2339,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0bsinitvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0bsinitvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
@@ -2401,16 +2513,15 @@ static int b43_upload_microcode(struct b43_wldev *dev)
b43_print_fw_helptext(dev->wl, 1);
err = -EOPNOTSUPP;
goto error;
- } else if (fwrev >= 598) {
- b43err(dev->wl, "YOUR FIRMWARE IS TOO NEW. Support for "
- "firmware 598 and up requires kernel 3.2 or newer. You "
- "have to install older firmware or upgrade kernel.\n");
- b43_print_fw_helptext(dev->wl, 1);
- err = -EOPNOTSUPP;
- goto error;
}
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
+ if (dev->fw.rev >= 598)
+ dev->fw.hdr_format = B43_FW_HDR_598;
+ else if (dev->fw.rev >= 410)
+ dev->fw.hdr_format = B43_FW_HDR_410;
+ else
+ dev->fw.hdr_format = B43_FW_HDR_351;
dev->fw.opensource = (fwdate == 0xFFFF);
/* Default to use-all-queues. */
@@ -2456,9 +2567,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
dev->fw.rev, dev->fw.patch);
- wiphy->hw_version = dev->sdev->id.coreid;
+ wiphy->hw_version = dev->dev->core_id;
- if (b43_is_old_txhdr_format(dev)) {
+ if (dev->fw.hdr_format == B43_FW_HDR_351) {
/* We're over the deadline, but we keep support for old fw
* until it turns out to be in major conflict with something new. */
b43warn(dev->wl, "You are using an old firmware image. "
@@ -2574,7 +2685,7 @@ out:
*/
static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
#ifdef CONFIG_SSB_DRIVER_PCICORE
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
@@ -2596,7 +2707,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask = 0x0000001F;
set = 0x0000000F;
- if (dev->sdev->bus->chip_id == 0x4301) {
+ if (dev->dev->chip_id == 0x4301) {
mask |= 0x0060;
set |= 0x0060;
}
@@ -2607,21 +2718,34 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask |= 0x0180;
set |= 0x0180;
}
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) {
b43_write16(dev, B43_MMIO_GPIO_MASK,
b43_read16(dev, B43_MMIO_GPIO_MASK)
| 0x0200);
mask |= 0x0200;
set |= 0x0200;
}
- if (dev->sdev->id.revision >= 2)
+ if (dev->dev->core_rev >= 2)
mask |= 0x0010; /* FIXME: This is redundant. */
- gpiodev = b43_ssb_gpio_dev(dev);
- if (gpiodev)
- ssb_write32(gpiodev, B43_GPIO_CONTROL,
- (ssb_read32(gpiodev, B43_GPIO_CONTROL)
- & mask) | set);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+ (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_GPIOCTL) & mask) | set);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ gpiodev = b43_ssb_gpio_dev(dev);
+ if (gpiodev)
+ ssb_write32(gpiodev, B43_GPIO_CONTROL,
+ (ssb_read32(gpiodev, B43_GPIO_CONTROL)
+ & mask) | set);
+ break;
+#endif
+ }
return 0;
}
@@ -2631,9 +2755,21 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
{
struct ssb_device *gpiodev;
- gpiodev = b43_ssb_gpio_dev(dev);
- if (gpiodev)
- ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+ 0);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ gpiodev = b43_ssb_gpio_dev(dev);
+ if (gpiodev)
+ ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+ break;
+#endif
+ }
}
/* http://bcm-specs.sipsolutions.net/EnableMac */
@@ -2705,12 +2841,30 @@ out:
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
{
- u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
- if (on)
- tmslow |= B43_TMSLOW_MACPHYCLKEN;
- else
- tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+ u32 tmp;
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ if (on)
+ tmp |= B43_BCMA_IOCTL_MACPHYCLKEN;
+ else
+ tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ if (on)
+ tmp |= B43_TMSLOW_MACPHYCLKEN;
+ else
+ tmp &= ~B43_TMSLOW_MACPHYCLKEN;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
+ }
}
static void b43_adjust_opmode(struct b43_wldev *dev)
@@ -2749,15 +2903,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
/* Workaround: On old hardware the HW-MAC-address-filter
* doesn't work properly, so always run promisc in filter
* it in software. */
- if (dev->sdev->id.revision <= 4)
+ if (dev->dev->core_rev <= 4)
ctl |= B43_MACCTL_PROMISC;
b43_write32(dev, B43_MMIO_MACCTL, ctl);
cfp_pretbtt = 2;
if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
- if (dev->sdev->bus->chip_id == 0x4306 &&
- dev->sdev->bus->chip_rev == 3)
+ if (dev->dev->chip_id == 0x4306 &&
+ dev->dev->chip_rev == 3)
cfp_pretbtt = 100;
else
cfp_pretbtt = 50;
@@ -2801,6 +2955,8 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
+ case B43_PHYTYPE_LCN:
b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
@@ -2915,7 +3071,7 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write16(dev, 0x005E, value16);
}
b43_write32(dev, 0x0100, 0x01000000);
- if (dev->sdev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
b43_write32(dev, 0x010C, 0x01000000);
b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
@@ -2930,7 +3086,7 @@ static int b43_chip_init(struct b43_wldev *dev)
/* Initially set the wireless operation mode. */
b43_adjust_opmode(dev);
- if (dev->sdev->id.revision < 3) {
+ if (dev->dev->core_rev < 3) {
b43_write16(dev, 0x060E, 0x0000);
b43_write16(dev, 0x0610, 0x8000);
b43_write16(dev, 0x0604, 0x0000);
@@ -2940,7 +3096,7 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write32(dev, 0x018C, 0x02000000);
}
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
- b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+ b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00);
b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
@@ -2949,8 +3105,20 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_mac_phy_clock_set(dev, true);
- b43_write16(dev, B43_MMIO_POWERUP_DELAY,
- dev->sdev->bus->chipco.fast_pwrup_delay);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ /* FIXME: 0xE74 is quite common, but should be read from CC */
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY,
+ dev->dev->sdev->bus->chipco.fast_pwrup_delay);
+ break;
+#endif
+ }
err = 0;
b43dbg(dev->wl, "Chip initialized\n");
@@ -3113,7 +3281,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
- if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) {
+ if ((dev->dev->core_rev >= 3) && (dev->dev->core_rev <= 10)) {
/* The 32bit register shadows the two 16bit registers
* with update sideeffects. Validate this. */
b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
@@ -3384,7 +3552,8 @@ static void b43_qos_init(struct b43_wldev *dev)
b43dbg(dev->wl, "QoS enabled\n");
}
-static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
+static int b43_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 _queue,
const struct ieee80211_tx_queue_params *params)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -3431,7 +3600,7 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
+static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -3450,7 +3619,8 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void b43_op_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u64 tsf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -3466,21 +3636,33 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
static void b43_put_phy_into_reset(struct b43_wldev *dev)
{
- struct ssb_device *sdev = dev->sdev;
- u32 tmslow;
+ u32 tmp;
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~B43_TMSLOW_GMODE;
- tmslow |= B43_TMSLOW_PHYRESET;
- tmslow |= SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ b43err(dev->wl,
+ "Putting PHY into reset not supported on BCMA\n");
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~B43_TMSLOW_GMODE;
+ tmp |= B43_TMSLOW_PHYRESET;
+ tmp |= SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ msleep(1);
+
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~SSB_TMSLOW_FGC;
+ tmp |= B43_TMSLOW_PHYRESET;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ msleep(1);
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~SSB_TMSLOW_FGC;
- tmslow |= B43_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
+ break;
+#endif
+ }
}
static const char *band_to_string(enum ieee80211_band band)
@@ -3612,14 +3794,24 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int antenna;
int err = 0;
+ bool reload_bss = false;
mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+
/* Switch the band (if necessary). This might change the active core. */
err = b43_switch_band(wl, conf->channel);
if (err)
goto out_unlock_mutex;
- dev = wl->current_dev;
+
+ /* Need to reload all settings if the core changed */
+ if (dev != wl->current_dev) {
+ dev = wl->current_dev;
+ changed = ~0;
+ reload_bss = true;
+ }
+
phy = &dev->phy;
if (conf_is_ht(conf))
@@ -3680,6 +3872,9 @@ out_mac_enable:
out_unlock_mutex:
mutex_unlock(&wl->mutex);
+ if (wl->vif && reload_bss)
+ b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
+
return err;
}
@@ -3768,7 +3963,8 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON_INT &&
(b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
- b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+ b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
+ conf->beacon_int)
b43_set_beacon_int(dev, conf->beacon_int);
if (changed & BSS_CHANGED_BASIC_RATES)
@@ -3941,10 +4137,13 @@ out_unlock:
* because the core might be gone away while we unlocked the mutex. */
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
{
- struct b43_wl *wl = dev->wl;
+ struct b43_wl *wl;
struct b43_wldev *orig_dev;
u32 mask;
+ if (!dev)
+ return NULL;
+ wl = dev->wl;
redo:
if (!dev || b43_status(dev) < B43_STAT_STARTED)
return dev;
@@ -3962,7 +4161,7 @@ redo:
/* Disable interrupts on the device. */
b43_set_status(dev, B43_STAT_INITIALIZED);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is locked. That is enough. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
@@ -3975,11 +4174,11 @@ redo:
/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
orig_dev = dev;
mutex_unlock(&wl->mutex);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
b43_sdio_free_irq(dev);
} else {
- synchronize_irq(dev->sdev->irq);
- free_irq(dev->sdev->irq, dev);
+ synchronize_irq(dev->dev->irq);
+ free_irq(dev->dev->irq, dev);
}
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -4012,19 +4211,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
drain_txstatus_queue(dev);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
if (err) {
b43err(dev->wl, "Cannot request SDIO IRQ\n");
goto out;
}
} else {
- err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler,
+ err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
b43_interrupt_thread_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) {
b43err(dev->wl, "Cannot request IRQ-%d\n",
- dev->sdev->irq);
+ dev->dev->irq);
goto out;
}
}
@@ -4091,9 +4290,21 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
#endif
+#ifdef CONFIG_B43_PHY_HT
+ case B43_PHYTYPE_HT:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
+#ifdef CONFIG_B43_PHY_LCN
+ case B43_PHYTYPE_LCN:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43err(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
@@ -4104,22 +4315,42 @@ static int b43_phy_versioning(struct b43_wldev *dev)
analog_type, phy_type, phy_rev);
/* Get RADIO versioning */
- if (dev->sdev->bus->chip_id == 0x4317) {
- if (dev->sdev->bus->chip_rev == 0)
- tmp = 0x3205017F;
- else if (dev->sdev->bus->chip_rev == 1)
- tmp = 0x4205017F;
- else
- tmp = 0x5205017F;
+ if (dev->dev->core_rev >= 24) {
+ u16 radio24[3];
+
+ for (tmp = 0; tmp < 3; tmp++) {
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+ radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ }
+
+ /* Broadcom uses "id" for our "ver" and has separated "ver" */
+ /* radio_ver = (radio24[0] & 0xF0) >> 4; */
+
+ radio_manuf = 0x17F;
+ radio_ver = (radio24[2] << 8) | radio24[1];
+ radio_rev = (radio24[0] & 0xF);
} else {
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
- }
- radio_manuf = (tmp & 0x00000FFF);
- radio_ver = (tmp & 0x0FFFF000) >> 12;
- radio_rev = (tmp & 0xF0000000) >> 28;
+ if (dev->dev->chip_id == 0x4317) {
+ if (dev->dev->chip_rev == 0)
+ tmp = 0x3205017F;
+ else if (dev->dev->chip_rev == 1)
+ tmp = 0x4205017F;
+ else
+ tmp = 0x5205017F;
+ } else {
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+ << 16;
+ }
+ radio_manuf = (tmp & 0x00000FFF);
+ radio_ver = (tmp & 0x0FFFF000) >> 12;
+ radio_rev = (tmp & 0xF0000000) >> 28;
+ }
+
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
@@ -4147,6 +4378,14 @@ static int b43_phy_versioning(struct b43_wldev *dev)
if (radio_ver != 0x2062 && radio_ver != 0x2063)
unsupported = 1;
break;
+ case B43_PHYTYPE_HT:
+ if (radio_ver != 0x2059)
+ unsupported = 1;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (radio_ver != 0x2064)
+ unsupported = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -4212,7 +4451,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
{
- struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u64 hf;
if (!modparam_btcoex)
@@ -4239,16 +4478,21 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus;
u32 tmp;
+ if (dev->dev->bus_type != B43_BUS_SSB)
+ return;
+
+ bus = dev->dev->sdev->bus;
+
if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||
(bus->chip_id == 0x4312)) {
- tmp = ssb_read32(dev->sdev, SSB_IMCFGLO);
+ tmp = ssb_read32(dev->dev->sdev, SSB_IMCFGLO);
tmp &= ~SSB_IMCFGLO_REQTO;
tmp &= ~SSB_IMCFGLO_SERTO;
tmp |= 0x3;
- ssb_write32(dev->sdev, SSB_IMCFGLO, tmp);
+ ssb_write32(dev->dev->sdev, SSB_IMCFGLO, tmp);
ssb_commit_settings(bus);
}
}
@@ -4318,36 +4562,45 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
dev->wl->current_beacon = NULL;
}
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(dev->sdev->bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
/* Initialize a wireless core */
static int b43_wireless_core_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
- struct ssb_sprom *sprom = &bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
int err;
u64 hf;
- u32 tmp;
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
- err = ssb_bus_powerup(bus, 0);
+ err = b43_bus_powerup(dev, 0);
if (err)
goto out;
- if (!ssb_device_is_enabled(dev->sdev)) {
- tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
- }
+ if (!b43_device_is_enabled(dev))
+ b43_wireless_core_reset(dev, phy->gmode);
/* Reset all data structures. */
setup_struct_wldev_for_init(dev);
phy->ops->prepare_structs(dev);
/* Enable IRQ routing to this device. */
- ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+ dev->dev->bdev, true);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore,
+ dev->dev->sdev);
+ break;
+#endif
+ }
b43_imcfglo_timeouts_workaround(dev);
b43_bluetooth_coext_disable(dev);
@@ -4360,7 +4613,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if (err)
goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_WLCOREREV, dev->sdev->id.revision);
+ B43_SHM_SH_WLCOREREV, dev->dev->core_rev);
hf = b43_hf_read(dev);
if (phy->type == B43_PHYTYPE_G) {
hf |= B43_HF_SYMW;
@@ -4378,8 +4631,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
#ifdef CONFIG_SSB_DRIVER_PCICORE
- if ((bus->bustype == SSB_BUSTYPE_PCI) &&
- (bus->pcicore.dev->id.revision <= 10))
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
#endif
hf &= ~B43_HF_SKCFPUP;
@@ -4407,9 +4661,14 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
/* Maximum Contention Window */
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
- if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
- (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) ||
- dev->use_pio) {
+ if (b43_bus_host_is_pcmcia(dev->dev) ||
+ b43_bus_host_is_sdio(dev->dev)) {
+ dev->__using_pio_transfers = 1;
+ err = b43_pio_init(dev);
+ } else if (dev->use_pio) {
+ b43warn(dev->wl, "Forced PIO by use_pio module parameter. "
+ "This should not be needed and will result in lower "
+ "performance.\n");
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
} else {
@@ -4422,7 +4681,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_set_synth_pu_delay(dev, 1);
b43_bluetooth_coext_enable(dev);
- ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
+ b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
b43_upload_card_macaddress(dev);
b43_security_init(dev);
@@ -4439,7 +4698,7 @@ out:
err_chip_exit:
b43_chip_exit(dev);
err_busdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
return err;
}
@@ -4481,6 +4740,9 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
out_mutex_unlock:
mutex_unlock(&wl->mutex);
+ if (err == 0)
+ b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
+
return err;
}
@@ -4551,6 +4813,15 @@ static int b43_op_start(struct ieee80211_hw *hw)
out_mutex_unlock:
mutex_unlock(&wl->mutex);
+ /*
+ * Configuration may have been overwritten during initialization.
+ * Reload the configuration, but only if initialization was
+ * successful. Reloading the configuration after a failed init
+ * may hang the system.
+ */
+ if (!err)
+ b43_op_config(hw, ~0);
+
return err;
}
@@ -4707,10 +4978,18 @@ out:
if (err)
wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
- if (err)
+
+ if (err) {
b43err(wl, "Controller restart FAILED\n");
- else
- b43info(wl, "Controller restarted\n");
+ return;
+ }
+
+ /* reload configuration */
+ b43_op_config(wl->hw, ~0);
+ if (wl->vif)
+ b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);
+
+ b43info(wl, "Controller restarted\n");
}
static int b43_setup_bands(struct b43_wldev *dev,
@@ -4745,11 +5024,10 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
static int b43_wireless_core_attach(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
- struct ssb_bus *bus = dev->sdev->bus;
- struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+ struct pci_dev *pdev = NULL;
int err;
- bool have_2ghz_phy = 0, have_5ghz_phy = 0;
u32 tmp;
+ bool have_2ghz_phy = 0, have_5ghz_phy = 0;
/* Do NOT do any device initialization here.
* Do it in wireless_core_init() instead.
@@ -4758,25 +5036,42 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
* that in core_init(), too.
*/
- err = ssb_bus_powerup(bus, 0);
+#ifdef CONFIG_B43_SSB
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+ pdev = dev->dev->sdev->bus->host_pci;
+#endif
+
+ err = b43_bus_powerup(dev, 0);
if (err) {
b43err(wl, "Bus powerup failed\n");
goto out;
}
- /* Get the PHY type. */
- if (dev->sdev->id.revision >= 5) {
- u32 tmshigh;
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
- have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
- have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
- } else
- B43_WARN_ON(1);
+ /* Get the PHY type. */
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+ have_2ghz_phy = !!(tmp & B43_BCMA_IOST_2G_PHY);
+ have_5ghz_phy = !!(tmp & B43_BCMA_IOST_5G_PHY);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ if (dev->dev->core_rev >= 5) {
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+ have_2ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_2GHZ_PHY);
+ have_5ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_5GHZ_PHY);
+ } else
+ B43_WARN_ON(1);
+ break;
+#endif
+ }
dev->phy.gmode = have_2ghz_phy;
dev->phy.radio_on = 1;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_phy_versioning(dev);
if (err)
@@ -4798,6 +5093,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
#endif
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
+ case B43_PHYTYPE_HT:
+ case B43_PHYTYPE_LCN:
have_2ghz_phy = 1;
break;
default:
@@ -4824,8 +5121,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
goto err_powerdown;
dev->phy.gmode = have_2ghz_phy;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_validate_chipaccess(dev);
if (err)
@@ -4840,8 +5136,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
INIT_WORK(&dev->restart_work, b43_chip_reset);
dev->phy.ops->switch_analog(dev, 0);
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
out:
return err;
@@ -4849,11 +5145,11 @@ out:
err_phy_free:
b43_phy_free(dev);
err_powerdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
return err;
}
-static void b43_one_core_detach(struct ssb_device *dev)
+static void b43_one_core_detach(struct b43_bus_dev *dev)
{
struct b43_wldev *wldev;
struct b43_wl *wl;
@@ -4861,17 +5157,17 @@ static void b43_one_core_detach(struct ssb_device *dev)
/* Do not cancel ieee80211-workqueue based work here.
* See comment in b43_remove(). */
- wldev = ssb_get_drvdata(dev);
+ wldev = b43_bus_get_wldev(dev);
wl = wldev->wl;
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
wl->nr_devs--;
- ssb_set_drvdata(dev, NULL);
+ b43_bus_set_wldev(dev, NULL);
kfree(wldev);
}
-static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct b43_wldev *wldev;
int err = -ENOMEM;
@@ -4881,7 +5177,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
goto out;
wldev->use_pio = b43_modparam_pio;
- wldev->sdev = dev;
+ wldev->dev = dev;
wldev->wl = wl;
b43_set_status(wldev, B43_STAT_UNINIT);
wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4893,7 +5189,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
list_add(&wldev->list, &wl->devlist);
wl->nr_devs++;
- ssb_set_drvdata(dev, wldev);
+ b43_bus_set_wldev(dev, wldev);
b43_debugfs_add_device(wldev);
out:
@@ -4934,19 +5230,20 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
}
}
-static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct ieee80211_hw *hw = wl->hw;
- ssb_set_devtypedata(dev, NULL);
+ ssb_set_devtypedata(dev->sdev, NULL);
ieee80211_free_hw(hw);
}
-static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{
- struct ssb_sprom *sprom = &dev->bus->sprom;
+ struct ssb_sprom *sprom = dev->bus_sprom;
struct ieee80211_hw *hw;
struct b43_wl *wl;
+ char chip_name[6];
hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
if (!hw) {
@@ -4985,29 +5282,105 @@ static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
INIT_WORK(&wl->tx_work, b43_tx_work);
skb_queue_head_init(&wl->tx_queue);
- b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
- dev->bus->chip_id, dev->id.revision);
+ snprintf(chip_name, ARRAY_SIZE(chip_name),
+ (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);
+ b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name,
+ dev->core_rev);
return wl;
}
-static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
+#ifdef CONFIG_B43_BCMA
+static int b43_bcma_probe(struct bcma_device *core)
{
+ struct b43_bus_dev *dev;
+ struct b43_wl *wl;
+ int err;
+
+ dev = b43_bus_dev_bcma_init(core);
+ if (!dev)
+ return -ENODEV;
+
+ wl = b43_wireless_init(dev);
+ if (IS_ERR(wl)) {
+ err = PTR_ERR(wl);
+ goto bcma_out;
+ }
+
+ err = b43_one_core_attach(dev, wl);
+ if (err)
+ goto bcma_err_wireless_exit;
+
+ err = ieee80211_register_hw(wl->hw);
+ if (err)
+ goto bcma_err_one_core_detach;
+ b43_leds_register(wl->current_dev);
+
+bcma_out:
+ return err;
+
+bcma_err_one_core_detach:
+ b43_one_core_detach(dev);
+bcma_err_wireless_exit:
+ ieee80211_free_hw(wl->hw);
+ return err;
+}
+
+static void b43_bcma_remove(struct bcma_device *core)
+{
+ struct b43_wldev *wldev = bcma_get_drvdata(core);
+ struct b43_wl *wl = wldev->wl;
+
+ /* We must cancel any work here before unregistering from ieee80211,
+ * as the ieee80211 unreg will destroy the workqueue. */
+ cancel_work_sync(&wldev->restart_work);
+
+ /* Restore the queues count before unregistering, because firmware detect
+ * might have modified it. Restoring is important, so the networking
+ * stack can properly free resources. */
+ wl->hw->queues = wl->mac80211_initially_registered_queues;
+ b43_leds_stop(wldev);
+ ieee80211_unregister_hw(wl->hw);
+
+ b43_one_core_detach(wldev->dev);
+
+ b43_leds_unregister(wl);
+
+ ieee80211_free_hw(wl->hw);
+}
+
+static struct bcma_driver b43_bcma_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = b43_bcma_tbl,
+ .probe = b43_bcma_probe,
+ .remove = b43_bcma_remove,
+};
+#endif
+
+#ifdef CONFIG_B43_SSB
+static
+int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+{
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
int err;
int first = 0;
- wl = ssb_get_devtypedata(dev);
+ dev = b43_bus_dev_ssb_init(sdev);
+ if (!dev)
+ return -ENOMEM;
+
+ wl = ssb_get_devtypedata(sdev);
if (!wl) {
/* Probing the first core. Must setup common struct b43_wl */
first = 1;
- b43_sprom_fixup(dev->bus);
+ b43_sprom_fixup(sdev->bus);
wl = b43_wireless_init(dev);
if (IS_ERR(wl)) {
err = PTR_ERR(wl);
goto out;
}
- ssb_set_devtypedata(dev, wl);
- B43_WARN_ON(ssb_get_devtypedata(dev) != wl);
+ ssb_set_devtypedata(sdev, wl);
+ B43_WARN_ON(ssb_get_devtypedata(sdev) != wl);
}
err = b43_one_core_attach(dev, wl);
if (err)
@@ -5031,10 +5404,11 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
return err;
}
-static void b43_ssb_remove(struct ssb_device *dev)
+static void b43_ssb_remove(struct ssb_device *sdev)
{
- struct b43_wl *wl = ssb_get_devtypedata(dev);
- struct b43_wldev *wldev = ssb_get_drvdata(dev);
+ struct b43_wl *wl = ssb_get_devtypedata(sdev);
+ struct b43_wldev *wldev = ssb_get_drvdata(sdev);
+ struct b43_bus_dev *dev = wldev->dev;
/* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */
@@ -5061,6 +5435,14 @@ static void b43_ssb_remove(struct ssb_device *dev)
}
}
+static struct ssb_driver b43_ssb_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = b43_ssb_tbl,
+ .probe = b43_ssb_probe,
+ .remove = b43_ssb_remove,
+};
+#endif /* CONFIG_B43_SSB */
+
/* Perform a hardware reset. This can be called from any context. */
void b43_controller_restart(struct b43_wldev *dev, const char *reason)
{
@@ -5071,13 +5453,6 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
-static struct ssb_driver b43_ssb_driver = {
- .name = KBUILD_MODNAME,
- .id_table = b43_ssb_tbl,
- .probe = b43_ssb_probe,
- .remove = b43_ssb_remove,
-};
-
static void b43_print_driverinfo(void)
{
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@ -5099,8 +5474,7 @@ static void b43_print_driverinfo(void)
feat_sdio = "S";
#endif
printk(KERN_INFO "Broadcom 43xx driver loaded "
- "[ Features: %s%s%s%s%s, Firmware-ID: "
- B43_SUPPORTED_FIRMWARE_ID " ]\n",
+ "[ Features: %s%s%s%s%s ]\n",
feat_pci, feat_pcmcia, feat_nphy,
feat_leds, feat_sdio);
}
@@ -5116,14 +5490,27 @@ static int __init b43_init(void)
err = b43_sdio_init();
if (err)
goto err_pcmcia_exit;
- err = ssb_driver_register(&b43_ssb_driver);
+#ifdef CONFIG_B43_BCMA
+ err = bcma_driver_register(&b43_bcma_driver);
if (err)
goto err_sdio_exit;
+#endif
+#ifdef CONFIG_B43_SSB
+ err = ssb_driver_register(&b43_ssb_driver);
+ if (err)
+ goto err_bcma_driver_exit;
+#endif
b43_print_driverinfo();
return err;
+#ifdef CONFIG_B43_SSB
+err_bcma_driver_exit:
+#endif
+#ifdef CONFIG_B43_BCMA
+ bcma_driver_unregister(&b43_bcma_driver);
err_sdio_exit:
+#endif
b43_sdio_exit();
err_pcmcia_exit:
b43_pcmcia_exit();
@@ -5134,7 +5521,12 @@ err_dfs_exit:
static void __exit b43_exit(void)
{
+#ifdef CONFIG_B43_SSB
ssb_driver_unregister(&b43_ssb_driver);
+#endif
+#ifdef CONFIG_B43_BCMA
+ bcma_driver_unregister(&b43_bcma_driver);
+#endif
b43_sdio_exit();
b43_pcmcia_exit();
b43_debugfs_exit();
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index a0d327f..8c684cd 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mb@bu3sch.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -121,7 +121,7 @@ void b43_hf_write(struct b43_wldev *dev, u64 value);
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
void b43_controller_restart(struct b43_wldev *dev, const char *reason);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 2c8461d..714cad6 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -2,7 +2,7 @@
Broadcom B43 wireless driver
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
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
@@ -25,6 +25,7 @@
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index b01c8ce..a6c3810 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -265,7 +265,6 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev)
void b43_phy_inita(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
/* This lowlevel A-PHY init is also called from G-PHY init.
@@ -296,9 +295,9 @@ void b43_phy_inita(struct b43_wldev *dev)
b43_radio_init2060(dev);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
- (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ ((dev->dev->board_type == SSB_BOARD_BU4306) ||
+ (dev->dev->board_type == SSB_BOARD_BU4309))) {
; //TODO: A PHY LO
}
@@ -311,7 +310,7 @@ void b43_phy_inita(struct b43_wldev *dev)
}
if ((phy->type == B43_PHYTYPE_G) &&
- (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+ (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
}
}
@@ -323,17 +322,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
struct b43_phy_a *aphy = phy->a;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->sdev->bus->sprom.pa1b0);
- pab1 = (s16) (dev->sdev->bus->sprom.pa1b1);
- pab2 = (s16) (dev->sdev->bus->sprom.pa1b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->sdev->bus->sprom.itssi_a != 0 &&
- (s8) dev->sdev->bus->sprom.itssi_a != -1)
+ if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_a != -1)
aphy->tgt_idle_tssi =
- (s8) (dev->sdev->bus->sprom.itssi_a);
+ (s8) (dev->dev->bus_sprom->itssi_a);
else
aphy->tgt_idle_tssi = 62;
aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index e46b2f4..3ea44bb 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -31,6 +31,8 @@
#include "phy_a.h"
#include "phy_n.h"
#include "phy_lp.h"
+#include "phy_ht.h"
+#include "phy_lcn.h"
#include "b43.h"
#include "main.h"
@@ -59,6 +61,16 @@ int b43_phy_allocate(struct b43_wldev *dev)
phy->ops = &b43_phyops_lp;
#endif
break;
+ case B43_PHYTYPE_HT:
+#ifdef CONFIG_B43_PHY_HT
+ phy->ops = &b43_phyops_ht;
+#endif
+ break;
+ case B43_PHYTYPE_LCN:
+#ifdef CONFIG_B43_PHY_LCN
+ phy->ops = &b43_phyops_lcn;
+#endif
+ break;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
@@ -168,7 +180,7 @@ void b43_phy_lock(struct b43_wldev *dev)
B43_WARN_ON(dev->phy.phy_locked);
dev->phy.phy_locked = 1;
#endif
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
@@ -180,7 +192,7 @@ void b43_phy_unlock(struct b43_wldev *dev)
B43_WARN_ON(!dev->phy.phy_locked);
dev->phy.phy_locked = 0;
#endif
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
@@ -368,8 +380,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
/* The next check will be needed in two seconds, or later. */
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
- if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return; /* No software txpower adjustment needed */
result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
@@ -436,6 +448,38 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
channel_type == NL80211_CHAN_HT40PLUS);
}
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
+void b43_phy_force_clock(struct b43_wldev *dev, bool force)
+{
+ u32 tmp;
+
+ WARN_ON(dev->phy.type != B43_PHYTYPE_N &&
+ dev->phy.type != B43_PHYTYPE_HT);
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ if (force)
+ tmp |= BCMA_IOCTL_FGC;
+ else
+ tmp &= ~BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ if (force)
+ tmp |= SSB_TMSLOW_FGC;
+ else
+ tmp &= ~SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
+ }
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */
struct b43_c32 b43_cordic(int theta)
{
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 2401bee..9233b13 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -194,6 +194,8 @@ struct b43_phy_a;
struct b43_phy_g;
struct b43_phy_n;
struct b43_phy_lp;
+struct b43_phy_ht;
+struct b43_phy_lcn;
struct b43_phy {
/* Hardware operation callbacks. */
@@ -216,6 +218,10 @@ struct b43_phy {
struct b43_phy_n *n;
/* LP-PHY specific information */
struct b43_phy_lp *lp;
+ /* HT-PHY specific information */
+ struct b43_phy_ht *ht;
+ /* LCN-PHY specific information */
+ struct b43_phy_lcn *lcn;
};
/* Band support flags. */
@@ -438,6 +444,8 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
+void b43_phy_force_clock(struct b43_wldev *dev, bool force);
+
struct b43_c32 b43_cordic(int theta);
#endif /* LINUX_B43_PHY_COMMON_H_ */
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 1758a28..8e157bc 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
if (!phy->gmode ||
- !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
tmp16 = b43_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
tmp16 -= 0x40;
@@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
if (!phy->gmode)
return 0;
@@ -1491,7 +1491,6 @@ static u16 b43_radio_init2050(struct b43_wldev *dev)
static void b43_phy_initb5(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
u16 offset, value;
@@ -1500,8 +1499,8 @@ static void b43_phy_initb5(struct b43_wldev *dev)
if (phy->analog == 1) {
b43_radio_set(dev, 0x007A, 0x0050);
}
- if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type != SSB_BOARD_BU4306)) {
+ if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type != SSB_BOARD_BU4306)) {
value = 0x2120;
for (offset = 0x00A8; offset < 0x00C7; offset++) {
b43_phy_write(dev, offset, value);
@@ -1620,7 +1619,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
b43_radio_write16(dev, 0x5A, 0x88);
b43_radio_write16(dev, 0x5B, 0x6B);
b43_radio_write16(dev, 0x5C, 0x0F);
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {
b43_radio_write16(dev, 0x5D, 0xFA);
b43_radio_write16(dev, 0x5E, 0xD8);
} else {
@@ -1787,7 +1786,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);
b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {
if (phy->rev >= 7) {
b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);
b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);
@@ -1922,7 +1921,6 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
/* Initialize B/G PHY power control */
static void b43_phy_init_pctl(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_rfatt old_rfatt;
@@ -1931,8 +1929,8 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return;
b43_phy_write(dev, 0x0028, 0x8018);
@@ -2053,7 +2051,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
if (phy->rev >= 6) {
b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));
}
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
else
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
@@ -2066,7 +2064,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
- if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
/* The specs state to update the NRSSI LT with
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
@@ -2088,8 +2086,8 @@ static void b43_phy_initg(struct b43_wldev *dev)
/* FIXME: The spec says in the following if, the 0 should be replaced
'if OFDM may not be used in the current locale'
but OFDM is legal everywhere */
- if ((dev->sdev->bus->chip_id == 0x4306
- && dev->sdev->bus->chip_package == 2) || 0) {
+ if ((dev->dev->chip_id == 0x4306
+ && dev->dev->chip_pkg == 2) || 0) {
b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);
b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);
}
@@ -2105,7 +2103,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev,
b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
if (channel == 14) {
- if (dev->sdev->bus->sprom.country_code ==
+ if (dev->dev->bus_sprom->country_code ==
SSB_SPROM1CCODE_JAPAN)
b43_hf_write(dev,
b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -2136,17 +2134,17 @@ static void default_baseband_attenuation(struct b43_wldev *dev,
static void default_radio_attenuation(struct b43_wldev *dev,
struct b43_rfatt *rf)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct b43_bus_dev *bdev = dev->dev;
struct b43_phy *phy = &dev->phy;
rf->with_padmix = 0;
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BCM4309G) {
- if (bus->boardinfo.rev < 0x43) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BCM4309G) {
+ if (dev->dev->board_rev < 0x43) {
rf->att = 2;
return;
- } else if (bus->boardinfo.rev < 0x51) {
+ } else if (dev->dev->board_rev < 0x51) {
rf->att = 3;
return;
}
@@ -2172,21 +2170,21 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 1:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 3;
else
rf->att = 1;
} else {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 7;
else
rf->att = 6;
@@ -2194,16 +2192,16 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 2:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 5;
- else if (bus->chip_id == 0x4320)
+ else if (bdev->chip_id == 0x4320)
rf->att = 4;
else
rf->att = 3;
@@ -2384,11 +2382,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
struct b43_phy_g *gphy = phy->g;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->sdev->bus->sprom.pa0b0);
- pab1 = (s16) (dev->sdev->bus->sprom.pa0b1);
- pab2 = (s16) (dev->sdev->bus->sprom.pa0b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa0b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa0b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa0b2);
- B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) &&
+ B43_WARN_ON((dev->dev->chip_id == 0x4301) &&
(phy->radio_ver != 0x2050)); /* Not supported anymore */
gphy->dyn_tssi_tbl = 0;
@@ -2396,10 +2394,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 &&
- (s8) dev->sdev->bus->sprom.itssi_bg != -1) {
+ if ((s8) dev->dev->bus_sprom->itssi_bg != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_bg != -1) {
gphy->tgt_idle_tssi =
- (s8) (dev->sdev->bus->sprom.itssi_bg);
+ (s8) (dev->dev->bus_sprom->itssi_bg);
} else
gphy->tgt_idle_tssi = 62;
gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
@@ -2537,7 +2535,7 @@ static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
b43_wireless_core_reset(dev, 0);
b43_phy_initg(dev);
phy->gmode = 1;
- b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+ b43_wireless_core_reset(dev, 1);
}
return 0;
@@ -2840,7 +2838,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
B43_TXCTL_TXMIX;
rfatt += 2;
bbatt += 2;
- } else if (dev->sdev->bus->sprom.
+ } else if (dev->dev->bus_sprom->
boardflags_lo &
B43_BFL_PACTRL) {
bbatt += 4 * (rfatt - 2);
@@ -2914,14 +2912,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- max_pwr = dev->sdev->bus->sprom.maxpwr_bg;
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ max_pwr = dev->dev->bus_sprom->maxpwr_bg;
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
max_pwr -= 3; /* minus 0.75 */
if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
b43warn(dev->wl,
"Invalid max-TX-power value in SPROM.\n");
max_pwr = INT_TO_Q52(20); /* fake it */
- dev->sdev->bus->sprom.maxpwr_bg = max_pwr;
+ dev->dev->bus_sprom->maxpwr_bg = max_pwr;
}
/* Get desired power (in Q5.2) */
@@ -3014,7 +3012,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))
return;
b43_mac_suspend(dev);
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 012c8da..f93d66b 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11a/g LP-PHY driver
- Copyright (c) 2008-2009 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008-2009 Michael Buesch <m@bues.ch>
Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
This program is free software; you can redistribute it and/or modify
@@ -85,39 +85,39 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
static void lpphy_read_band_sprom(struct b43_wldev *dev)
{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
u16 cckpo, maxpwr;
u32 ofdmpo;
int i;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- lpphy->tx_isolation_med_band = bus->sprom.tri2g;
- lpphy->bx_arch = bus->sprom.bxa2g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
- lpphy->rssi_vf = bus->sprom.rssismf2g;
- lpphy->rssi_vc = bus->sprom.rssismc2g;
- lpphy->rssi_gs = bus->sprom.rssisav2g;
- lpphy->txpa[0] = bus->sprom.pa0b0;
- lpphy->txpa[1] = bus->sprom.pa0b1;
- lpphy->txpa[2] = bus->sprom.pa0b2;
- maxpwr = bus->sprom.maxpwr_bg;
+ lpphy->tx_isolation_med_band = sprom->tri2g;
+ lpphy->bx_arch = sprom->bxa2g;
+ lpphy->rx_pwr_offset = sprom->rxpo2g;
+ lpphy->rssi_vf = sprom->rssismf2g;
+ lpphy->rssi_vc = sprom->rssismc2g;
+ lpphy->rssi_gs = sprom->rssisav2g;
+ lpphy->txpa[0] = sprom->pa0b0;
+ lpphy->txpa[1] = sprom->pa0b1;
+ lpphy->txpa[2] = sprom->pa0b2;
+ maxpwr = sprom->maxpwr_bg;
lpphy->max_tx_pwr_med_band = maxpwr;
- cckpo = bus->sprom.cck2gpo;
+ cckpo = sprom->cck2gpo;
/*
* We don't read SPROM's opo as specs say. On rev8 SPROMs
* opo == ofdm2gpo and we don't know any SSB with LP-PHY
* and SPROM rev below 8.
*/
- B43_WARN_ON(bus->sprom.revision < 8);
- ofdmpo = bus->sprom.ofdm2gpo;
+ B43_WARN_ON(sprom->revision < 8);
+ ofdmpo = sprom->ofdm2gpo;
if (cckpo) {
for (i = 0; i < 4; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- ofdmpo = bus->sprom.ofdm2gpo;
+ ofdmpo = sprom->ofdm2gpo;
for (i = 4; i < 15; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
@@ -131,39 +131,39 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
}
} else { /* 5GHz */
- lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
- lpphy->tx_isolation_med_band = bus->sprom.tri5g;
- lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
- lpphy->bx_arch = bus->sprom.bxa5g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
- lpphy->rssi_vf = bus->sprom.rssismf5g;
- lpphy->rssi_vc = bus->sprom.rssismc5g;
- lpphy->rssi_gs = bus->sprom.rssisav5g;
- lpphy->txpa[0] = bus->sprom.pa1b0;
- lpphy->txpa[1] = bus->sprom.pa1b1;
- lpphy->txpa[2] = bus->sprom.pa1b2;
- lpphy->txpal[0] = bus->sprom.pa1lob0;
- lpphy->txpal[1] = bus->sprom.pa1lob1;
- lpphy->txpal[2] = bus->sprom.pa1lob2;
- lpphy->txpah[0] = bus->sprom.pa1hib0;
- lpphy->txpah[1] = bus->sprom.pa1hib1;
- lpphy->txpah[2] = bus->sprom.pa1hib2;
- maxpwr = bus->sprom.maxpwr_al;
- ofdmpo = bus->sprom.ofdm5glpo;
+ lpphy->tx_isolation_low_band = sprom->tri5gl;
+ lpphy->tx_isolation_med_band = sprom->tri5g;
+ lpphy->tx_isolation_hi_band = sprom->tri5gh;
+ lpphy->bx_arch = sprom->bxa5g;
+ lpphy->rx_pwr_offset = sprom->rxpo5g;
+ lpphy->rssi_vf = sprom->rssismf5g;
+ lpphy->rssi_vc = sprom->rssismc5g;
+ lpphy->rssi_gs = sprom->rssisav5g;
+ lpphy->txpa[0] = sprom->pa1b0;
+ lpphy->txpa[1] = sprom->pa1b1;
+ lpphy->txpa[2] = sprom->pa1b2;
+ lpphy->txpal[0] = sprom->pa1lob0;
+ lpphy->txpal[1] = sprom->pa1lob1;
+ lpphy->txpal[2] = sprom->pa1lob2;
+ lpphy->txpah[0] = sprom->pa1hib0;
+ lpphy->txpah[1] = sprom->pa1hib1;
+ lpphy->txpah[2] = sprom->pa1hib2;
+ maxpwr = sprom->maxpwr_al;
+ ofdmpo = sprom->ofdm5glpo;
lpphy->max_tx_pwr_low_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- maxpwr = bus->sprom.maxpwr_a;
- ofdmpo = bus->sprom.ofdm5gpo;
+ maxpwr = sprom->maxpwr_a;
+ ofdmpo = sprom->ofdm5gpo;
lpphy->max_tx_pwr_med_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- maxpwr = bus->sprom.maxpwr_ah;
- ofdmpo = bus->sprom.ofdm5ghpo;
+ maxpwr = sprom->maxpwr_ah;
+ ofdmpo = sprom->ofdm5ghpo;
lpphy->max_tx_pwr_hi_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
@@ -214,7 +214,8 @@ static void lpphy_table_init(struct b43_wldev *dev)
static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 tmp, tmp2;
@@ -242,9 +243,9 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
0xFF00, lpphy->rx_pwr_offset);
- if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
+ if ((sprom->boardflags_lo & B43_BFL_FEM) &&
((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
+ (sprom->boardflags_hi & B43_BFH_PAREF))) {
ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
ssb_pmu_set_ldo_paref(&bus->chipco, true);
if (dev->phy.rev == 0) {
@@ -260,7 +261,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
}
tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
- if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV)
+ if (sprom->boardflags_hi & B43_BFH_RSSIINV)
b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
else
b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
@@ -268,7 +269,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
0xFFF9, (lpphy->bx_arch << 1));
if (dev->phy.rev == 1 &&
- (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
+ (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
@@ -286,8 +287,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
- (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
- (bus->sprom.boardflags_lo & B43_BFL_FEM))) {
+ (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
+ (sprom->boardflags_lo & B43_BFL_FEM))) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
@@ -297,7 +298,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
} else if (dev->phy.rev == 1 ||
- (bus->sprom.boardflags_lo & B43_BFL_FEM)) {
+ (sprom->boardflags_lo & B43_BFL_FEM)) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
@@ -316,15 +317,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
}
- if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) {
+ if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
}
- if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
- (bus->chip_id == 0x5354) &&
- (bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
+ if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
+ (dev->dev->chip_id == 0x5354) &&
+ (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
@@ -412,7 +413,6 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy_lp *lpphy = dev->phy.lp;
b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
@@ -432,7 +432,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
- if (bus->boardinfo.rev >= 0x18) {
+ if (dev->dev->board_rev >= 0x18) {
b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
} else {
@@ -449,7 +449,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
} else {
@@ -467,7 +467,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
}
@@ -492,7 +492,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
0x2000 | ((u16)lpphy->rssi_gs << 10) |
((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
@@ -519,7 +519,7 @@ struct b2062_freqdata {
static void lpphy_2062_init(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystalfreq, tmp, ref;
unsigned int i;
const struct b2062_freqdata *fd = NULL;
@@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev)
lpphy_sync_stx(dev);
b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
- if (dev->sdev->bus->chip_id == 0x4325) {
+ if (dev->dev->chip_id == 0x4325) {
// TODO SSB PMU recalibration
}
}
@@ -1289,7 +1289,7 @@ finish:
static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
int i;
@@ -1840,7 +1840,6 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
struct lpphy_tx_gains gains, oldgains;
int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
@@ -1854,7 +1853,7 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
- if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+ if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)
lpphy_papd_cal(dev, gains, 0, 1, 30);
else
lpphy_papd_cal(dev, gains, 0, 1, 65);
@@ -1870,7 +1869,6 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
bool rx, bool pa, struct lpphy_tx_gains *gains)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
const struct lpphy_rx_iq_comp *iqcomp = NULL;
struct lpphy_tx_gains nogains, oldgains;
u16 tmp;
@@ -1879,7 +1877,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
memset(&nogains, 0, sizeof(nogains));
memset(&oldgains, 0, sizeof(oldgains));
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
iqcomp = &lpphy_5354_iq_table[i];
@@ -2408,11 +2406,9 @@ static const struct b206x_channel b2063_chantbl[] = {
static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
-
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
udelay(20);
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
b43_radio_write(dev, B2062_N_COMM1, 4);
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
} else {
@@ -2432,7 +2428,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
unsigned int channel)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
@@ -2522,7 +2518,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
static int lpphy_b2063_tune(struct b43_wldev *dev,
unsigned int channel)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
static const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
@@ -2670,6 +2666,11 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
{
int err;
+ if (dev->dev->bus_type != B43_BUS_SSB) {
+ b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
+ return -EOPNOTSUPP;
+ }
+
lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
lpphy_baseband_init(dev);
lpphy_radio_init(dev);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 05960dd..0490c7c 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -3,7 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY support
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008 Michael Buesch <m@bues.ch>
+ Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -77,6 +78,7 @@ enum b43_nphy_rssi_type {
B43_NPHY_RSSI_TBD,
};
+/* TODO: reorder functions */
static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
bool enable);
static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
@@ -87,6 +89,14 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
u16 value, u8 core, bool off);
static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
u16 value, u8 core);
+static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev);
+
+static inline bool b43_nphy_ipa(struct b43_wldev *dev)
+{
+ enum ieee80211_band band = b43_current_band(dev->wl);
+ return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
+ (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
+}
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
@@ -248,15 +258,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
{
struct b43_phy_n *nphy = dev->phy.n;
u8 i;
- u16 tmp;
+ u16 bmask, val, tmp;
+ enum ieee80211_band band = b43_current_band(dev->wl);
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 1);
nphy->txpwrctrl = enable;
if (!enable) {
- if (dev->phy.rev >= 3)
- ; /* TODO */
+ if (dev->phy.rev >= 3 &&
+ (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
+ (B43_NPHY_TXPCTL_CMD_COEFF |
+ B43_NPHY_TXPCTL_CMD_HWPCTLEN |
+ B43_NPHY_TXPCTL_CMD_PCTLEN))) {
+ /* We disable enabled TX pwr ctl, save it's state */
+ nphy->tx_pwr_idx[0] = b43_phy_read(dev,
+ B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
+ nphy->tx_pwr_idx[1] = b43_phy_read(dev,
+ B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
+ }
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
for (i = 0; i < 84; i++)
@@ -285,10 +305,67 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
- if (dev->phy.rev < 2 && 0)
- ; /* TODO */
+ if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
} else {
- b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n");
+ b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
+ nphy->adj_pwr_tbl);
+ b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
+ nphy->adj_pwr_tbl);
+
+ bmask = B43_NPHY_TXPCTL_CMD_COEFF |
+ B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+ /* wl does useless check for "enable" param here */
+ val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+ if (dev->phy.rev >= 3) {
+ bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+ if (val)
+ val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+ }
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
+
+ if (band == IEEE80211_BAND_5GHZ) {
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
+ if (dev->phy.rev > 1)
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+ ~B43_NPHY_TXPCTL_INIT_PIDXI1,
+ 0x64);
+ }
+
+ if (dev->phy.rev >= 3) {
+ if (nphy->tx_pwr_idx[0] != 128 &&
+ nphy->tx_pwr_idx[1] != 128) {
+ /* Recover TX pwr ctl state */
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT,
+ nphy->tx_pwr_idx[0]);
+ if (dev->phy.rev > 1)
+ b43_phy_maskset(dev,
+ B43_NPHY_TXPCTL_INIT,
+ ~0xff, nphy->tx_pwr_idx[1]);
+ }
+ }
+
+ if (dev->phy.rev >= 3) {
+ b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
+ b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
+ } else {
+ b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
+ }
+
+ if (dev->phy.rev == 2)
+ b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
+ else if (dev->phy.rev < 2)
+ b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
+
+ if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
+
+ if (b43_nphy_ipa(dev)) {
+ b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
+ b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
+ }
}
if (nphy->hang_avoid)
@@ -299,7 +376,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u8 txpi[2], bbmult, i;
u16 tmp, radio_gain, dac_gain;
@@ -369,22 +446,23 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
else
b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
- tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
+ tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
if (i == 0)
tmp = (tmp & 0x00FF) | (bbmult << 8);
else
tmp = (tmp & 0xFF00) | bbmult;
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp);
-
- if (0)
- ; /* TODO */
+ b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
+
+ if (b43_nphy_ipa(dev)) {
+ u32 tmp32;
+ u16 reg = (i == 0) ?
+ B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
+ tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i]));
+ b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
+ b43_phy_set(dev, reg, 0x4);
+ }
}
b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
@@ -393,6 +471,57 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, 0);
}
+static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ const u32 *table = NULL;
+#if 0
+ TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
+ u32 rfpwr_offset;
+ u8 pga_gain;
+ int i;
+#endif
+
+ if (phy->rev >= 3) {
+ if (b43_nphy_ipa(dev)) {
+ table = b43_nphy_get_ipa_gain_table(dev);
+ } else {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ if (phy->rev == 3)
+ table = b43_ntab_tx_gain_rev3_5ghz;
+ if (phy->rev == 4)
+ table = b43_ntab_tx_gain_rev4_5ghz;
+ else
+ table = b43_ntab_tx_gain_rev5plus_5ghz;
+ } else {
+ table = b43_ntab_tx_gain_rev3plus_2ghz;
+ }
+ }
+ } else {
+ table = b43_ntab_tx_gain_rev0_1_2;
+ }
+ b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
+ b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
+
+ if (phy->rev >= 3) {
+#if 0
+ nphy->gmval = (table[0] >> 16) & 0x7000;
+
+ for (i = 0; i < 128; i++) {
+ pga_gain = (table[i] >> 24) & 0xF;
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+ else
+ rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
+ b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
+ rfpwr_offset);
+ b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
+ rfpwr_offset);
+ }
+#endif
+ }
+}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
static void b43_radio_2055_setup(struct b43_wldev *dev,
@@ -423,16 +552,15 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev)
static void b43_radio_init2055_post(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
- struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
int i;
u16 val;
bool workaround = false;
if (sprom->revision < 4)
- workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM &&
- binfo->type == 0x46D &&
- binfo->rev >= 0x41);
+ workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
+ && dev->dev->board_type == 0x46D
+ && dev->dev->board_rev >= 0x41);
else
workaround =
!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
@@ -582,14 +710,10 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
{
- struct b43_phy_n *nphy = dev->phy.n;
u16 tmp;
- enum ieee80211_band band = b43_current_band(dev->wl);
- bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
if (dev->phy.rev >= 3) {
- if (ipa) {
+ if (b43_nphy_ipa(dev)) {
tmp = 4;
b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
(((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
@@ -601,33 +725,17 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
}
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
-static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
-{
- u32 tmslow;
-
- if (dev->phy.type != B43_PHYTYPE_N)
- return;
-
- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
- if (force)
- tmslow |= SSB_TMSLOW_FGC;
- else
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
static void b43_nphy_reset_cca(struct b43_wldev *dev)
{
u16 bbcfg;
- b43_nphy_bmac_clock_fgc(dev, 1);
+ b43_phy_force_clock(dev, 1);
bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
udelay(1);
b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
- b43_nphy_bmac_clock_fgc(dev, 0);
+ b43_phy_force_clock(dev, 0);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
}
@@ -916,11 +1024,7 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
{
u16 array[4];
- int i;
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
- for (i = 0; i < 4; i++)
- array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
@@ -959,8 +1063,21 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
- ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
- 0xFC00);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
+ 0xFC00, 0xFC00);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
+ 0xFC00, 0xFC00);
+ break;
+#endif
+ }
+
b43_write32(dev, B43_MMIO_MACCTL,
b43_read32(dev, B43_MMIO_MACCTL) &
~B43_MACCTL_GPOUTSMSK);
@@ -983,7 +1100,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
{
u16 tmp;
- if (dev->sdev->id.revision == 16)
+ if (dev->dev->core_rev == 16)
b43_mac_suspend(dev);
tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
@@ -993,7 +1110,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
tmp |= (val & mask);
b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
- if (dev->sdev->id.revision == 16)
+ if (dev->dev->core_rev == 16)
b43_mac_enable(dev);
return tmp;
@@ -1168,7 +1285,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
/* PHY rev 0, 1, 2 */
u8 i, j;
@@ -1370,181 +1487,221 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
}
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
-static void b43_nphy_workarounds(struct b43_wldev *dev)
+static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_n *nphy = phy->n;
-
- u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
- u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
-
- u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
- u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
+ struct b43_phy_n *nphy = dev->phy.n;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+ /* TX to RX */
+ u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
+ u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+ /* RX to TX */
+ u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
+ 0x1F };
+ u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+ u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
+ u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
u16 tmp16;
u32 tmp32;
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
- b43_nphy_classifier(dev, 1, 0);
- else
- b43_nphy_classifier(dev, 1, 1);
+ tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+ tmp32 &= 0xffffff;
+ b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+ b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
+ b43_phy_write(dev, 0x2AE, 0x000C);
+
+ /* TX to RX */
+ b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9);
+
+ /* RX to TX */
+ if (b43_nphy_ipa(dev))
+ b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa,
+ rx2tx_delays_ipa, 9);
+ if (nphy->hw_phyrxchain != 3 &&
+ nphy->hw_phyrxchain != nphy->hw_phytxchain) {
+ if (b43_nphy_ipa(dev)) {
+ rx2tx_delays[5] = 59;
+ rx2tx_delays[6] = 1;
+ rx2tx_events[7] = 0x1F;
+ }
+ b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9);
+ }
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
+ tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
+ 0x2 : 0x9C40;
+ b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
- b43_phy_set(dev, B43_NPHY_IQFLIP,
- B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+ b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
- if (dev->phy.rev >= 3) {
- tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
- tmp32 &= 0xffffff;
- b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
-
- b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
- b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
- b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
- b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
- b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
- b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+ b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
+ b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
- b43_phy_write(dev, 0x2AE, 0x000C);
+ b43_nphy_gain_ctrl_workarounds(dev);
- /* TODO */
+ b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
+ b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
- tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
- 0x2 : 0x9C40;
- b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+ /* TODO */
- b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+
+ /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
+
+ if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+ b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
+ (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+ b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
+ tmp32 = 0x00088888;
+ else
+ tmp32 = 0x88888888;
+ b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
+ b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
+ b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
+
+ if (dev->phy.rev == 4 &&
+ b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
+ 0x70);
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
+ 0x70);
+ }
- b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
- b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
+ b43_phy_write(dev, 0x224, 0x039C);
+ b43_phy_write(dev, 0x225, 0x0357);
+ b43_phy_write(dev, 0x226, 0x0317);
+ b43_phy_write(dev, 0x227, 0x02D7);
+ b43_phy_write(dev, 0x228, 0x039C);
+ b43_phy_write(dev, 0x229, 0x0357);
+ b43_phy_write(dev, 0x22A, 0x0317);
+ b43_phy_write(dev, 0x22B, 0x02D7);
+ b43_phy_write(dev, 0x22C, 0x039C);
+ b43_phy_write(dev, 0x22D, 0x0357);
+ b43_phy_write(dev, 0x22E, 0x0317);
+ b43_phy_write(dev, 0x22F, 0x02D7);
+}
- b43_nphy_gain_ctrl_workarounds(dev);
+static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
- b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
- b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
+ u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
+ u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
- /* TODO */
+ u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
+ u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
-
- /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
-
- if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR &&
- b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR &&
- b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
- tmp32 = 0x00088888;
- else
- tmp32 = 0x88888888;
- b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
- b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
- b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
-
- if (dev->phy.rev == 4 &&
- b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
- 0x70);
- b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
- 0x70);
- }
-
- b43_phy_write(dev, 0x224, 0x039C);
- b43_phy_write(dev, 0x225, 0x0357);
- b43_phy_write(dev, 0x226, 0x0317);
- b43_phy_write(dev, 0x227, 0x02D7);
- b43_phy_write(dev, 0x228, 0x039C);
- b43_phy_write(dev, 0x229, 0x0357);
- b43_phy_write(dev, 0x22A, 0x0317);
- b43_phy_write(dev, 0x22B, 0x02D7);
- b43_phy_write(dev, 0x22C, 0x039C);
- b43_phy_write(dev, 0x22D, 0x0357);
- b43_phy_write(dev, 0x22E, 0x0317);
- b43_phy_write(dev, 0x22F, 0x02D7);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
+ nphy->band5g_pwrgain) {
+ b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
+ b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
} else {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
- nphy->band5g_pwrgain) {
- b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
- b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
- } else {
- b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
- b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
- }
-
- b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
- b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
- b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
- b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
+ b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
+ b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
+ }
- if (dev->phy.rev < 2) {
- b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
- b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
- b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
- b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
- b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
- b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
- }
+ b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+ if (dev->phy.rev < 2) {
+ b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
+ }
- if (bus->sprom.boardflags2_lo & 0x100 &&
- bus->boardinfo.type == 0x8B) {
- delays1[0] = 0x1;
- delays1[5] = 0x14;
- }
- b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
- b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
- b43_nphy_gain_ctrl_workarounds(dev);
+ if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
+ dev->dev->board_type == 0x8B) {
+ delays1[0] = 0x1;
+ delays1[5] = 0x14;
+ }
+ b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
+ b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
- if (dev->phy.rev < 2) {
- if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
- b43_hf_write(dev, b43_hf_read(dev) |
- B43_HF_MLADVW);
- } else if (dev->phy.rev == 2) {
- b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
- b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
- }
-
- if (dev->phy.rev < 2)
- b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
- ~B43_NPHY_SCRAM_SIGCTL_SCM);
-
- /* Set phase track alpha and beta */
- b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
- b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
- b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
- b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
- b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
- b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
-
- b43_phy_mask(dev, B43_NPHY_PIL_DW1,
- ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+ b43_nphy_gain_ctrl_workarounds(dev);
- if (dev->phy.rev == 2)
- b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
- B43_NPHY_FINERX2_CGC_DECGC);
+ if (dev->phy.rev < 2) {
+ if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
+ b43_hf_write(dev, b43_hf_read(dev) |
+ B43_HF_MLADVW);
+ } else if (dev->phy.rev == 2) {
+ b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
+ b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
}
+ if (dev->phy.rev < 2)
+ b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
+ ~B43_NPHY_SCRAM_SIGCTL_SCM);
+
+ /* Set phase track alpha and beta */
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+
+ b43_phy_mask(dev, B43_NPHY_PIL_DW1,
+ ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
+ b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
+ b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
+ b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+
+ if (dev->phy.rev == 2)
+ b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
+ B43_NPHY_FINERX2_CGC_DECGC);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
+static void b43_nphy_workarounds(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ b43_nphy_classifier(dev, 1, 0);
+ else
+ b43_nphy_classifier(dev, 1, 1);
+
+ if (nphy->hang_avoid)
+ b43_nphy_stay_in_carrier_search(dev, 1);
+
+ b43_phy_set(dev, B43_NPHY_IQFLIP,
+ B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+
+ if (dev->phy.rev >= 3)
+ b43_nphy_workarounds_rev3plus(dev);
+ else
+ b43_nphy_workarounds_rev1_2(dev);
+
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 0);
}
@@ -2139,7 +2296,6 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
{
- struct b43_phy_n *nphy = dev->phy.n;
u8 i;
u16 reg, val;
@@ -2203,10 +2359,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
enum ieee80211_band band =
b43_current_band(dev->wl);
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ))
+ if (b43_nphy_ipa(dev))
val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
else
val = 0x11;
@@ -2581,8 +2734,8 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if (dev->phy.rev >= 6) {
- /* TODO If the chip is 47162
- return txpwrctrl_tx_gain_ipa_rev5 */
+ if (dev->dev->chip_id == 47162)
+ return txpwrctrl_tx_gain_ipa_rev5;
return txpwrctrl_tx_gain_ipa_rev6;
} else if (dev->phy.rev >= 5) {
return txpwrctrl_tx_gain_ipa_rev5;
@@ -2832,10 +2985,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
enum ieee80211_band band =
b43_current_band(dev->wl);
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ)) {
+ if (b43_nphy_ipa(dev)) {
table = b43_nphy_get_ipa_gain_table(dev);
} else {
if (band == IEEE80211_BAND_5GHZ) {
@@ -3586,7 +3736,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
*/
int b43_phy_initn(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
u8 tx_pwr_state;
@@ -3599,9 +3749,22 @@ int b43_phy_initn(struct b43_wldev *dev)
bool do_cal = false;
if ((dev->phy.rev >= 3) &&
- (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
- chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_CHIPCTL, 0x40);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ chipco_set32(&dev->dev->sdev->bus->chipco,
+ SSB_CHIPCO_CHIPCTL, 0x40);
+ break;
+#endif
+ }
}
nphy->deaf_count = 0;
b43_nphy_tables_init(dev);
@@ -3639,9 +3802,9 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
- if (bus->sprom.boardflags2_lo & 0x100 ||
- (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
- bus->boardinfo.type == 0x8B))
+ if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
+ (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+ dev->dev->board_type == 0x8B))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
else
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
@@ -3658,8 +3821,7 @@ int b43_phy_initn(struct b43_wldev *dev)
}
tmp2 = b43_current_band(dev->wl);
- if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
+ if (b43_nphy_ipa(dev)) {
b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
nphy->papd_epsilon_offset[0] << 7);
@@ -3674,11 +3836,11 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_workarounds(dev);
/* Reset CCA, in init code it differs a little from standard way */
- b43_nphy_bmac_clock_fgc(dev, 1);
+ b43_phy_force_clock(dev, 1);
tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
- b43_nphy_bmac_clock_fgc(dev, 0);
+ b43_phy_force_clock(dev, 0);
b43_mac_phy_clock_set(dev, true);
@@ -3697,15 +3859,7 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_tx_power_fix(dev);
/* TODO N PHY TX Power Control Idle TSSI */
/* TODO N PHY TX Power Control Setup */
-
- if (phy->rev >= 3) {
- /* TODO */
- } else {
- b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- }
+ b43_nphy_tx_gain_table_upload(dev);
if (nphy->phyrxchain != 3)
b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
@@ -3783,22 +3937,22 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
struct b43_phy_n *nphy = dev->phy.n;
u16 old_band_5ghz;
- u32 tmp32;
+ u16 tmp16;
old_band_5ghz =
b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
- tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
+ tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
- tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
+ tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
}
b43_chantab_phy_upload(dev, e);
@@ -3909,6 +4063,10 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
+ /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
+ * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
+ nphy->tx_pwr_idx[0] = 128;
+ nphy->tx_pwr_idx[1] = 128;
}
static void b43_nphy_op_free(struct b43_wldev *dev)
@@ -4026,11 +4184,24 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
{
- u16 val = on ? 0 : 0x7FFF;
+ u16 override = on ? 0x0 : 0x7FFF;
+ u16 core = on ? 0xD : 0x00FD;
- if (dev->phy.rev >= 3)
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
+ if (dev->phy.rev >= 3) {
+ if (on) {
+ b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ } else {
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+ }
+ } else {
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ }
}
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index e789a89..fbf5202 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -764,6 +764,8 @@ struct b43_phy_n {
u8 cal_orig_pwr_idx[2];
u8 measure_hold;
u8 phyrxchain;
+ u8 hw_phyrxchain;
+ u8 hw_phytxchain;
u8 perical;
u32 deaf_count;
u32 rxcalparams;
@@ -783,6 +785,8 @@ struct b43_phy_n {
u16 mphase_txcal_bestcoeffs[11];
bool txpwrctrl;
+ u8 tx_pwr_idx[2];
+ u16 adj_pwr_tbl[84];
u16 txcal_bbmult;
u16 txiqlocal_bestc[11];
bool txiqlocal_coeffsvalid;
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 72ab94d..279a53e 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -4,7 +4,7 @@
PIO data transfer
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
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
@@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
B43_MMIO_PIO11_BASE5,
};
- if (dev->sdev->id.revision >= 11) {
+ if (dev->dev->core_rev >= 11) {
B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
return bases_rev11[index];
}
@@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
static u16 pio_txqueue_offset(struct b43_wldev *dev)
{
- if (dev->sdev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x18;
return 0;
}
static u16 pio_rxqueue_offset(struct b43_wldev *dev)
{
- if (dev->sdev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x38;
return 8;
}
@@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->sdev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_txqueue_offset(dev);
q->index = index;
@@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->sdev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_rxqueue_offset(dev);
@@ -611,15 +611,25 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
u16 len;
- u32 macstat;
+ u32 macstat = 0;
unsigned int i, padding;
struct sk_buff *skb;
const char *err_msg = NULL;
struct b43_rxhdr_fw4 *rxhdr =
(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
+ size_t rxhdr_size = sizeof(*rxhdr);
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
- memset(rxhdr, 0, sizeof(*rxhdr));
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ rxhdr_size -= sizeof(rxhdr->format_598) -
+ sizeof(rxhdr->format_351);
+ break;
+ case B43_FW_HDR_598:
+ break;
+ }
+ memset(rxhdr, 0, rxhdr_size);
/* Check if we have data and wait for it to get ready. */
if (q->rev >= 8) {
@@ -657,11 +667,11 @@ data_ready:
/* Get the preamble (RX header) */
if (q->rev >= 8) {
- b43_block_read(dev, rxhdr, sizeof(*rxhdr),
+ b43_block_read(dev, rxhdr, rxhdr_size,
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
} else {
- b43_block_read(dev, rxhdr, sizeof(*rxhdr),
+ b43_block_read(dev, rxhdr, rxhdr_size,
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
}
@@ -676,7 +686,15 @@ data_ready:
goto rx_error;
}
- macstat = le32_to_cpu(rxhdr->mac_status);
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ macstat = le32_to_cpu(rxhdr->format_598.mac_status);
+ break;
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ macstat = le32_to_cpu(rxhdr->format_351.mac_status);
+ break;
+ }
if (macstat & B43_RX_MAC_FCSERR) {
if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
/* Drop frames with failed FCS. */
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
index 44c6dea..5289a18 100644
--- a/drivers/net/wireless/b43/radio_2055.c
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -3,7 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY and radio device data tables
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008 Michael Buesch <m@bues.ch>
+ Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h
index d9bfa0f..67f9612 100644
--- a/drivers/net/wireless/b43/radio_2055.h
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -251,4 +251,9 @@ struct b43_nphy_channeltab_entry_rev2 {
void b2055_upload_inittab(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+
#endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index 8890df0..a01f776 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n 2056 radio device data tables
+ Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index d601f6e..a7159d8 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1,29 +1,3 @@
-/*
-
- Broadcom B43 wireless driver
-
- Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
-
- Some parts of the code in this file are derived from the brcm80211
- driver Copyright (c) 2010 Broadcom Corporation
-
- 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; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
-*/
-
#ifndef B43_RADIO_2056_H_
#define B43_RADIO_2056_H_
@@ -1117,4 +1091,9 @@ struct b43_nphy_channeltab_entry_rev3 {
void b2056_upload_inittabs(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+
#endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index a617efe..70c2fce 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
RFKILL support
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
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
@@ -37,17 +37,16 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
- struct ssb_bus *bus = dev->sdev->bus;
bool enabled;
bool brought_up = false;
mutex_lock(&wl->mutex);
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
- if (ssb_bus_powerup(bus, 0)) {
+ if (b43_bus_powerup(dev, 0)) {
mutex_unlock(&wl->mutex);
return;
}
- ssb_device_enable(dev->sdev, 0);
+ b43_device_enable(dev, 0);
brought_up = true;
}
@@ -63,8 +62,8 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
}
if (brought_up) {
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index 808e25b..80b0755 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -4,7 +4,7 @@
* SDIO over Sonics Silicon Backplane bus glue for b43.
*
* Copyright (C) 2009 Albert Herranz
- * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2009 Michael Buesch <m@bues.ch>
*
* 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
@@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
int err;
@@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev,
void b43_sdio_free_irq(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
@@ -93,8 +93,8 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
sdio->irq_handler = NULL;
}
-static int b43_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
+static int __devinit b43_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
struct sdio_func_tuple *tuple;
@@ -171,7 +171,7 @@ out:
return error;
}
-static void b43_sdio_remove(struct sdio_func *func)
+static void __devexit b43_sdio_remove(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 57af619..8e8431d 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -4,7 +4,7 @@
SYSFS support routines
- Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006 Michael Buesch <m@bues.ch>
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
@@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644,
int b43_sysfs_register(struct b43_wldev *wldev)
{
- struct device *dev = wldev->sdev->dev;
+ struct device *dev = wldev->dev->dev;
B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
@@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev)
void b43_sysfs_unregister(struct b43_wldev *wldev)
{
- struct device *dev = wldev->sdev->dev;
+ struct device *dev = wldev->dev->dev;
device_remove_file(dev, &dev_attr_interference);
}
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 1ef9a64..ea288df 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2006, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006, 2006 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 59df3c6..cff187c 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11a/g LP-PHY and radio device data tables
- Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2009 Michael Buesch <m@bues.ch>
Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
This program is free software; you can redistribute it and/or modify
@@ -2304,7 +2304,6 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
void lpphy_rev2plus_table_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
int i;
B43_WARN_ON(dev->phy.rev < 2);
@@ -2341,7 +2340,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
@@ -2416,12 +2415,12 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
void lpphy_init_tx_gain_table(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
switch (dev->phy.rev) {
case 0:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+ (sprom->boardflags_lo & B43_BFL_HGPA))
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev0_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2432,8 +2431,8 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
lpphy_rev0_5ghz_tx_gain_table);
break;
case 1:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+ (sprom->boardflags_lo & B43_BFL_HGPA))
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev1_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2444,7 +2443,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
lpphy_rev1_5ghz_tx_gain_table);
break;
default:
- if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
+ if (sprom->boardflags_hi & B43_BFH_NOPA)
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev2_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 2de483b..7b326f2 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -3,7 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY data tables
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008 Michael Buesch <m@bues.ch>
+ Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 1856936..a81696b 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -60,16 +60,8 @@ struct nphy_gain_ctl_workaround_entry {
struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
struct b43_wldev *dev, bool ghz5, bool ext_lna);
-/* Get the NPHY Channel Switch Table entry for a channel.
- * Returns NULL on failure to find an entry. */
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
-const struct b43_nphy_channeltab_entry_rev3 *
-b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
-
/* The N-PHY tables. */
-
#define B43_NTAB_TYPEMASK 0xF0000000
#define B43_NTAB_8BIT 0x10000000
#define B43_NTAB_16BIT 0x20000000
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
index 8f4db44..9b1a038 100644
--- a/drivers/net/wireless/b43/wa.c
+++ b/drivers/net/wireless/b43/wa.c
@@ -5,7 +5,7 @@
PHY workarounds.
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
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
@@ -458,17 +458,15 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev)
static void b43_wa_boards_a(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
-
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BU4306 &&
- bus->boardinfo.rev < 0x30) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BU4306 &&
+ dev->dev->board_rev < 0x30) {
b43_phy_write(dev, 0x0010, 0xE000);
b43_phy_write(dev, 0x0013, 0x0140);
b43_phy_write(dev, 0x0014, 0x0280);
} else {
- if (bus->boardinfo.type == SSB_BOARD_MP4318 &&
- bus->boardinfo.rev < 0x20) {
+ if (dev->dev->board_type == SSB_BOARD_MP4318 &&
+ dev->dev->board_rev < 0x20) {
b43_phy_write(dev, 0x0013, 0x0210);
b43_phy_write(dev, 0x0014, 0x0840);
} else {
@@ -486,19 +484,19 @@ static void b43_wa_boards_a(struct b43_wldev *dev)
static void b43_wa_boards_g(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
- if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
- bus->boardinfo.type != SSB_BOARD_BU4306 ||
- bus->boardinfo.rev != 0x17) {
+ if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
+ dev->dev->board_type != SSB_BOARD_BU4306 ||
+ dev->dev->board_rev != 0x17) {
if (phy->rev < 2) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
- if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(phy->rev >= 7)) {
b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
@@ -510,7 +508,7 @@ static void b43_wa_boards_g(struct b43_wldev *dev)
}
}
}
- if (bus->sprom.boardflags_lo & B43_BFL_FEM) {
+ if (sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
}
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index c8f99ae..e8afd35 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -6,7 +6,7 @@
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -175,6 +175,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
}
}
+/* TODO: verify if needed for SSLPN or LCN */
static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
{
const struct b43_phy *phy = &dev->phy;
@@ -256,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
unsigned int plcp_fragment_len;
u32 mac_ctl = 0;
u16 phy_ctl = 0;
+ bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
+ phy->type == B43_PHYTYPE_N ||
+ phy->type == B43_PHYTYPE_HT);
u8 extra_ft = 0;
struct ieee80211_rate *txrate;
struct ieee80211_tx_rate *rates;
@@ -323,8 +327,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
/* we give the phase1key and iv16 here, the key is stored in
* shm. With that the hardware can do phase 2 and encryption.
*/
- ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
- IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
+ ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
for (i = 0; i < 5; i++) {
txhdr->iv[i * 2 + 0] = phase1key[i];
@@ -338,12 +341,19 @@ int b43_generate_txhdr(struct b43_wldev *dev,
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
}
- if (b43_is_old_txhdr_format(dev)) {
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
plcp_fragment_len, rate);
- } else {
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
+ break;
+ case B43_FW_HDR_351:
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
plcp_fragment_len, rate);
+ break;
+ case B43_FW_HDR_410:
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
+ plcp_fragment_len, rate);
+ break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
plcp_fragment_len, rate_fb);
@@ -416,10 +426,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr *uninitialized_var(hdr);
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
- struct b43_plcp_hdr6 *plcp;
+ struct b43_plcp_hdr6 *uninitialized_var(plcp);
struct ieee80211_rate *rts_cts_rate;
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
@@ -430,14 +440,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- struct ieee80211_cts *cts;
+ struct ieee80211_cts *uninitialized_var(cts);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
cts = (struct ieee80211_cts *)
- (txhdr->old_format.rts_frame);
- } else {
+ (txhdr->format_598.rts_frame);
+ break;
+ case B43_FW_HDR_351:
+ cts = (struct ieee80211_cts *)
+ (txhdr->format_351.rts_frame);
+ break;
+ case B43_FW_HDR_410:
cts = (struct ieee80211_cts *)
- (txhdr->new_format.rts_frame);
+ (txhdr->format_410.rts_frame);
+ break;
}
ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
@@ -445,14 +462,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
- struct ieee80211_rts *rts;
+ struct ieee80211_rts *uninitialized_var(rts);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
rts = (struct ieee80211_rts *)
- (txhdr->old_format.rts_frame);
- } else {
+ (txhdr->format_598.rts_frame);
+ break;
+ case B43_FW_HDR_351:
+ rts = (struct ieee80211_rts *)
+ (txhdr->format_351.rts_frame);
+ break;
+ case B43_FW_HDR_410:
rts = (struct ieee80211_rts *)
- (txhdr->new_format.rts_frame);
+ (txhdr->format_410.rts_frame);
+ break;
}
ieee80211_rts_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
@@ -463,22 +487,36 @@ int b43_generate_txhdr(struct b43_wldev *dev,
len += FCS_LEN;
/* Generate the PLCP headers for the RTS/CTS frame */
- if (b43_is_old_txhdr_format(dev))
- plcp = &txhdr->old_format.rts_plcp;
- else
- plcp = &txhdr->new_format.rts_plcp;
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ plcp = &txhdr->format_598.rts_plcp;
+ break;
+ case B43_FW_HDR_351:
+ plcp = &txhdr->format_351.rts_plcp;
+ break;
+ case B43_FW_HDR_410:
+ plcp = &txhdr->format_410.rts_plcp;
+ break;
+ }
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate);
plcp = &txhdr->rts_plcp_fb;
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate_fb);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
hdr = (struct ieee80211_hdr *)
- (&txhdr->old_format.rts_frame);
- } else {
+ (&txhdr->format_598.rts_frame);
+ break;
+ case B43_FW_HDR_351:
+ hdr = (struct ieee80211_hdr *)
+ (&txhdr->format_351.rts_frame);
+ break;
+ case B43_FW_HDR_410:
hdr = (struct ieee80211_hdr *)
- (&txhdr->new_format.rts_frame);
+ (&txhdr->format_410.rts_frame);
+ break;
}
txhdr->rts_dur_fb = hdr->duration_id;
@@ -497,7 +535,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
extra_ft |= B43_TXH_EFT_RTSFB_CCK;
if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
- phy->type == B43_PHYTYPE_N) {
+ fill_phy_ctl1) {
txhdr->phy_ctl1_rts = cpu_to_le16(
b43_generate_tx_phy_ctl1(dev, rts_rate));
txhdr->phy_ctl1_rts_fb = cpu_to_le16(
@@ -506,12 +544,19 @@ int b43_generate_txhdr(struct b43_wldev *dev,
}
/* Magic cookie */
- if (b43_is_old_txhdr_format(dev))
- txhdr->old_format.cookie = cpu_to_le16(cookie);
- else
- txhdr->new_format.cookie = cpu_to_le16(cookie);
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ txhdr->format_598.cookie = cpu_to_le16(cookie);
+ break;
+ case B43_FW_HDR_351:
+ txhdr->format_351.cookie = cpu_to_le16(cookie);
+ break;
+ case B43_FW_HDR_410:
+ txhdr->format_410.cookie = cpu_to_le16(cookie);
+ break;
+ }
- if (phy->type == B43_PHYTYPE_N) {
+ if (fill_phy_ctl1) {
txhdr->phy_ctl1 =
cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
txhdr->phy_ctl1_fb =
@@ -547,7 +592,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
else
tmp -= 3;
} else {
- if (dev->sdev->bus->sprom.
+ if (dev->dev->bus_sprom->
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
@@ -612,8 +657,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
struct ieee80211_hdr *wlhdr;
const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
__le16 fctl;
- u16 phystat0, phystat3, chanstat, mactime;
- u32 macstat;
+ u16 phystat0, phystat3;
+ u16 uninitialized_var(chanstat), uninitialized_var(mactime);
+ u32 uninitialized_var(macstat);
u16 chanid;
u16 phytype;
int padding;
@@ -623,9 +669,19 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
/* Get metadata about the frame from the header. */
phystat0 = le16_to_cpu(rxhdr->phy_status0);
phystat3 = le16_to_cpu(rxhdr->phy_status3);
- macstat = le32_to_cpu(rxhdr->mac_status);
- mactime = le16_to_cpu(rxhdr->mac_time);
- chanstat = le16_to_cpu(rxhdr->channel);
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ macstat = le32_to_cpu(rxhdr->format_598.mac_status);
+ mactime = le16_to_cpu(rxhdr->format_598.mac_time);
+ chanstat = le16_to_cpu(rxhdr->format_598.channel);
+ break;
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ macstat = le32_to_cpu(rxhdr->format_351.mac_status);
+ mactime = le16_to_cpu(rxhdr->format_351.mac_time);
+ chanstat = le16_to_cpu(rxhdr->format_351.channel);
+ break;
+ }
phytype = chanstat & B43_RX_CHAN_PHYTYPE;
if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
@@ -683,16 +739,29 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
}
/* Link quality statistics */
- if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
-// s8 rssi = max(rxhdr->power0, rxhdr->power1);
- //TODO: Find out what the rssi value is (dBm or percentage?)
- // and also find out what the maximum possible value is.
- // Fill status.ssi and status.signal fields.
- } else {
+ switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+ case B43_PHYTYPE_HT:
+ /* TODO: is max the right choice? */
+ status.signal = max_t(__s8,
+ max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
+ rxhdr->phy_ht_power2);
+ break;
+ case B43_PHYTYPE_N:
+ /* Broadcom has code for min and avg, but always uses max */
+ if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
+ status.signal = max(rxhdr->power1, rxhdr->power2);
+ else
+ status.signal = max(rxhdr->power0, rxhdr->power1);
+ break;
+ case B43_PHYTYPE_A:
+ case B43_PHYTYPE_B:
+ case B43_PHYTYPE_G:
+ case B43_PHYTYPE_LP:
status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
(phystat0 & B43_RX_PHYST0_OFDM),
(phystat0 & B43_RX_PHYST0_GAINCTL),
(phystat3 & B43_RX_PHYST3_TRSTATE));
+ break;
}
if (phystat0 & B43_RX_PHYST0_OFDM)
@@ -739,20 +808,25 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
break;
case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ;
- /* chanid is the radio channel cookie value as used
- * to tune the radio. */
- status.freq = chanid + 2400;
+ /* Somewhere between 478.104 and 508.1084 firmware for G-PHY
+ * has been modified to be compatible with N-PHY and others.
+ */
+ if (dev->fw.rev >= 508)
+ status.freq = ieee80211_channel_to_frequency(chanid, status.band);
+ else
+ status.freq = chanid + 2400;
break;
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
/* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */
if (chanstat & B43_RX_CHAN_5GHZ) {
status.band = IEEE80211_BAND_5GHZ;
- status.freq = b43_freq_to_channel_5ghz(chanid);
+ status.freq = b43_channel_to_freq_5ghz(chanid);
} else {
status.band = IEEE80211_BAND_2GHZ;
- status.freq = b43_freq_to_channel_2ghz(chanid);
+ status.freq = b43_channel_to_freq_2ghz(chanid);
}
break;
default:
@@ -768,7 +842,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
#endif
return;
drop:
- b43dbg(dev->wl, "RX: Packet dropped\n");
dev_kfree_skb_any(skb);
}
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 42debb5..98d9074 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -46,7 +46,24 @@ struct b43_txhdr {
__le32 timeout; /* Timeout */
union {
- /* The new r410 format. */
+ /* Tested with 598.314, 644.1001 and 666.2 */
+ struct {
+ __le16 mimo_antenna; /* MIMO antenna select */
+ __le16 preload_size; /* Preload size */
+ PAD_BYTES(2);
+ __le16 cookie; /* TX frame cookie */
+ __le16 tx_status; /* TX status */
+ __le16 max_n_mpdus;
+ __le16 max_a_bytes_mrt;
+ __le16 max_a_bytes_fbr;
+ __le16 min_m_bytes;
+ struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
+ __u8 rts_frame[16]; /* The RTS frame (if used) */
+ PAD_BYTES(2);
+ struct b43_plcp_hdr6 plcp; /* Main PLCP header */
+ } format_598 __packed;
+
+ /* Tested with 410.2160, 478.104 and 508.* */
struct {
__le16 mimo_antenna; /* MIMO antenna select */
__le16 preload_size; /* Preload size */
@@ -57,9 +74,9 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
- } new_format __packed;
+ } format_410 __packed;
- /* The old r351 format. */
+ /* Tested with 351.126 */
struct {
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
@@ -68,7 +85,7 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
- } old_format __packed;
+ } format_351 __packed;
} __packed;
} __packed;
@@ -166,19 +183,18 @@ struct b43_tx_legacy_rate_phy_ctl_entry {
#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */
-/* r351 firmware compatibility stuff. */
-static inline
-bool b43_is_old_txhdr_format(struct b43_wldev *dev)
-{
- return (dev->fw.rev <= 351);
-}
-
static inline
size_t b43_txhdr_size(struct b43_wldev *dev)
{
- if (b43_is_old_txhdr_format(dev))
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ return 112 + sizeof(struct b43_plcp_hdr6);
+ case B43_FW_HDR_410:
+ return 104 + sizeof(struct b43_plcp_hdr6);
+ case B43_FW_HDR_351:
return 100 + sizeof(struct b43_plcp_hdr6);
- return 104 + sizeof(struct b43_plcp_hdr6);
+ }
+ return 0;
}
@@ -232,11 +248,47 @@ struct b43_rxhdr_fw4 {
__s8 power1; /* PHY RX Status 1: Power 1 */
} __packed;
} __packed;
- __le16 phy_status2; /* PHY RX Status 2 */
- __le16 phy_status3; /* PHY RX Status 3 */
- __le32 mac_status; /* MAC RX status */
- __le16 mac_time;
- __le16 channel;
+ union {
+ /* HT-PHY */
+ struct {
+ PAD_BYTES(1);
+ __s8 phy_ht_power0;
+ } __packed;
+
+ /* RSSI for N-PHYs */
+ struct {
+ __s8 power2;
+ PAD_BYTES(1);
+ } __packed;
+
+ __le16 phy_status2; /* PHY RX Status 2 */
+ } __packed;
+ union {
+ /* HT-PHY */
+ struct {
+ __s8 phy_ht_power1;
+ __s8 phy_ht_power2;
+ } __packed;
+
+ __le16 phy_status3; /* PHY RX Status 3 */
+ } __packed;
+ union {
+ /* Tested with 598.314, 644.1001 and 666.2 */
+ struct {
+ __le16 phy_status4; /* PHY RX Status 4 */
+ __le16 phy_status5; /* PHY RX Status 5 */
+ __le32 mac_status; /* MAC RX status */
+ __le16 mac_time;
+ __le16 channel;
+ } format_598 __packed;
+
+ /* Tested with 351.126, 410.2160, 478.104 and 508.* */
+ struct {
+ __le32 mac_status; /* MAC RX status */
+ __le16 mac_time;
+ __le16 channel;
+ } format_351 __packed;
+ } __packed;
} __packed;
/* PHY RX Status 0 */
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 23583be..1d4fc9d 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -8,13 +8,12 @@
#include <linux/stringify.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/io.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include "debugfs.h"
@@ -23,10 +22,6 @@
#include "phy.h"
-/* The unique identifier of the firmware that's officially supported by this
- * driver version. */
-#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10"
-
#define B43legacy_IRQWAIT_MAX_RETRIES 20
/* MMIO offsets */
@@ -532,6 +527,8 @@ struct b43legacy_dma {
struct b43legacy_dmaring *rx_ring0;
struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */
+
+ u32 translation; /* Routing bits */
};
/* Data structures for PIO transmission, per 80211 core. */
@@ -813,15 +810,15 @@ struct b43legacy_lopair *b43legacy_get_lopair(struct b43legacy_phy *phy,
/* Message printing */
-void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+__printf(2, 3)
+void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...);
#if B43legacy_DEBUG
-void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+__printf(2, 3)
+void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...);
#else /* DEBUG */
# define b43legacydbg(wl, fmt...) do { /* nothing */ } while (0)
#endif /* DEBUG */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index f232618..5e28ad0 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -4,7 +4,7 @@
debugfs driver debugging code
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
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
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index e03e01d..c5535ad 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -4,7 +4,7 @@
DMA ringbuffer and descriptor allocation/management
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Some code in this file is derived from the b44.c driver
Copyright (C) 2002 David S. Miller
@@ -42,10 +42,9 @@
/* 32bit DMA ops. */
static
-struct b43legacy_dmadesc_generic *op32_idx2desc(
- struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta **meta)
+struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
+ int slot,
+ struct b43legacy_dmadesc_meta **meta)
{
struct b43legacy_dmadesc32 *desc;
@@ -53,11 +52,11 @@ struct b43legacy_dmadesc_generic *op32_idx2desc(
desc = ring->descbase;
desc = &(desc[slot]);
- return (struct b43legacy_dmadesc_generic *)desc;
+ return (struct b43legacy_dmadesc32 *)desc;
}
static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
+ struct b43legacy_dmadesc32 *desc,
dma_addr_t dmaaddr, u16 bufsize,
int start, int end, int irq)
{
@@ -67,13 +66,13 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
u32 addr;
u32 addrext;
- slot = (int)(&(desc->dma32) - descbase);
+ slot = (int)(desc - descbase);
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
- addr |= ssb_dma_translation(ring->dev->dev);
+ addr |= ring->dev->dma.translation;
ctl = (bufsize - ring->frameoffset)
& B43legacy_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
@@ -87,8 +86,8 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT)
& B43legacy_DMA32_DCTL_ADDREXT_MASK;
- desc->dma32.control = cpu_to_le32(ctl);
- desc->dma32.address = cpu_to_le32(addr);
+ desc->control = cpu_to_le32(ctl);
+ desc->address = cpu_to_le32(addr);
}
static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot)
@@ -128,121 +127,6 @@ static void op32_set_current_rxslot(struct b43legacy_dmaring *ring,
(u32)(slot * sizeof(struct b43legacy_dmadesc32)));
}
-static const struct b43legacy_dma_ops dma32_ops = {
- .idx2desc = op32_idx2desc,
- .fill_descriptor = op32_fill_descriptor,
- .poke_tx = op32_poke_tx,
- .tx_suspend = op32_tx_suspend,
- .tx_resume = op32_tx_resume,
- .get_current_rxslot = op32_get_current_rxslot,
- .set_current_rxslot = op32_set_current_rxslot,
-};
-
-/* 64bit DMA ops. */
-static
-struct b43legacy_dmadesc_generic *op64_idx2desc(
- struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta
- **meta)
-{
- struct b43legacy_dmadesc64 *desc;
-
- *meta = &(ring->meta[slot]);
- desc = ring->descbase;
- desc = &(desc[slot]);
-
- return (struct b43legacy_dmadesc_generic *)desc;
-}
-
-static void op64_fill_descriptor(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
- dma_addr_t dmaaddr, u16 bufsize,
- int start, int end, int irq)
-{
- struct b43legacy_dmadesc64 *descbase = ring->descbase;
- int slot;
- u32 ctl0 = 0;
- u32 ctl1 = 0;
- u32 addrlo;
- u32 addrhi;
- u32 addrext;
-
- slot = (int)(&(desc->dma64) - descbase);
- B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
-
- addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
- addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= ssb_dma_translation(ring->dev->dev);
- if (slot == ring->nr_slots - 1)
- ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND;
- if (start)
- ctl0 |= B43legacy_DMA64_DCTL0_FRAMESTART;
- if (end)
- ctl0 |= B43legacy_DMA64_DCTL0_FRAMEEND;
- if (irq)
- ctl0 |= B43legacy_DMA64_DCTL0_IRQ;
- ctl1 |= (bufsize - ring->frameoffset)
- & B43legacy_DMA64_DCTL1_BYTECNT;
- ctl1 |= (addrext << B43legacy_DMA64_DCTL1_ADDREXT_SHIFT)
- & B43legacy_DMA64_DCTL1_ADDREXT_MASK;
-
- desc->dma64.control0 = cpu_to_le32(ctl0);
- desc->dma64.control1 = cpu_to_le32(ctl1);
- desc->dma64.address_low = cpu_to_le32(addrlo);
- desc->dma64.address_high = cpu_to_le32(addrhi);
-}
-
-static void op64_poke_tx(struct b43legacy_dmaring *ring, int slot)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXINDEX,
- (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
-}
-
-static void op64_tx_suspend(struct b43legacy_dmaring *ring)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
- | B43legacy_DMA64_TXSUSPEND);
-}
-
-static void op64_tx_resume(struct b43legacy_dmaring *ring)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
- & ~B43legacy_DMA64_TXSUSPEND);
-}
-
-static int op64_get_current_rxslot(struct b43legacy_dmaring *ring)
-{
- u32 val;
-
- val = b43legacy_dma_read(ring, B43legacy_DMA64_RXSTATUS);
- val &= B43legacy_DMA64_RXSTATDPTR;
-
- return (val / sizeof(struct b43legacy_dmadesc64));
-}
-
-static void op64_set_current_rxslot(struct b43legacy_dmaring *ring,
- int slot)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
- (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
-}
-
-static const struct b43legacy_dma_ops dma64_ops = {
- .idx2desc = op64_idx2desc,
- .fill_descriptor = op64_fill_descriptor,
- .poke_tx = op64_poke_tx,
- .tx_suspend = op64_tx_suspend,
- .tx_resume = op64_tx_resume,
- .get_current_rxslot = op64_get_current_rxslot,
- .set_current_rxslot = op64_set_current_rxslot,
-};
-
-
static inline int free_slots(struct b43legacy_dmaring *ring)
{
return (ring->nr_slots - ring->used_slots);
@@ -358,14 +242,6 @@ return 0;
static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
int controller_idx)
{
- static const u16 map64[] = {
- B43legacy_MMIO_DMA64_BASE0,
- B43legacy_MMIO_DMA64_BASE1,
- B43legacy_MMIO_DMA64_BASE2,
- B43legacy_MMIO_DMA64_BASE3,
- B43legacy_MMIO_DMA64_BASE4,
- B43legacy_MMIO_DMA64_BASE5,
- };
static const u16 map32[] = {
B43legacy_MMIO_DMA32_BASE0,
B43legacy_MMIO_DMA32_BASE1,
@@ -375,11 +251,6 @@ static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
B43legacy_MMIO_DMA32_BASE5,
};
- if (type == B43legacy_DMA_64BIT) {
- B43legacy_WARN_ON(!(controller_idx >= 0 &&
- controller_idx < ARRAY_SIZE(map64)));
- return map64[controller_idx];
- }
B43legacy_WARN_ON(!(controller_idx >= 0 &&
controller_idx < ARRAY_SIZE(map32)));
return map32[controller_idx];
@@ -491,25 +362,15 @@ static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev,
might_sleep();
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL;
+ offset = B43legacy_DMA32_RXCTL;
b43legacy_write32(dev, mmio_base + offset, 0);
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS;
+ offset = B43legacy_DMA32_RXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_RXSTAT;
- if (value == B43legacy_DMA64_RXSTAT_DISABLED) {
- i = -1;
- break;
- }
- } else {
- value &= B43legacy_DMA32_RXSTATE;
- if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
- i = -1;
- break;
- }
+ value &= B43legacy_DMA32_RXSTATE;
+ if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
+ i = -1;
+ break;
}
msleep(1);
}
@@ -533,43 +394,24 @@ static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
might_sleep();
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
+ offset = B43legacy_DMA32_TXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_TXSTAT;
- if (value == B43legacy_DMA64_TXSTAT_DISABLED ||
- value == B43legacy_DMA64_TXSTAT_IDLEWAIT ||
- value == B43legacy_DMA64_TXSTAT_STOPPED)
- break;
- } else {
- value &= B43legacy_DMA32_TXSTATE;
- if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
- value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
- value == B43legacy_DMA32_TXSTAT_STOPPED)
- break;
- }
+ value &= B43legacy_DMA32_TXSTATE;
+ if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
+ value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
+ value == B43legacy_DMA32_TXSTAT_STOPPED)
+ break;
msleep(1);
}
- offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL :
- B43legacy_DMA32_TXCTL;
+ offset = B43legacy_DMA32_TXCTL;
b43legacy_write32(dev, mmio_base + offset, 0);
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
+ offset = B43legacy_DMA32_TXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_TXSTAT;
- if (value == B43legacy_DMA64_TXSTAT_DISABLED) {
- i = -1;
- break;
- }
- } else {
- value &= B43legacy_DMA32_TXSTATE;
- if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
- i = -1;
- break;
- }
+ value &= B43legacy_DMA32_TXSTATE;
+ if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
+ i = -1;
+ break;
}
msleep(1);
}
@@ -601,9 +443,6 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
if ((u64)addr + buffersize > (1ULL << 32))
goto address_error;
break;
- case B43legacy_DMA_64BIT:
- /* Currently we can't have addresses beyond 64 bits in the kernel. */
- break;
}
/* The address is OK. */
@@ -617,7 +456,7 @@ address_error:
}
static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
+ struct b43legacy_dmadesc32 *desc,
struct b43legacy_dmadesc_meta *meta,
gfp_t gfp_flags)
{
@@ -653,8 +492,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
meta->skb = skb;
meta->dmaaddr = dmaaddr;
- ring->ops->fill_descriptor(ring, desc, dmaaddr,
- ring->rx_buffersize, 0, 0, 0);
+ op32_fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0);
rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data);
rxhdr->frame_len = 0;
@@ -671,11 +509,11 @@ static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring)
{
int i;
int err = -ENOMEM;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ desc = op32_idx2desc(ring, i, &meta);
err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
if (err) {
@@ -692,7 +530,7 @@ out:
err_unwind:
for (i--; i >= 0; i--) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ desc = op32_idx2desc(ring, i, &meta);
unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
dev_kfree_skb(meta->skb);
@@ -709,84 +547,36 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
- u32 trans = ssb_dma_translation(ring->dev->dev);
+ u32 trans = ring->dev->dma.translation;
+ u32 ringbase = (u32)(ring->dmabase);
if (ring->tx) {
- if (ring->type == B43legacy_DMA_64BIT) {
- u64 ringbase = (u64)(ring->dmabase);
-
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = B43legacy_DMA64_TXENABLE;
- value |= (addrext << B43legacy_DMA64_TXADDREXT_SHIFT)
- & B43legacy_DMA64_TXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI,
- ((ringbase >> 32)
- & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- } else {
- u32 ringbase = (u32)(ring->dmabase);
-
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = B43legacy_DMA32_TXENABLE;
- value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
- & B43legacy_DMA32_TXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
- (ringbase &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- }
+ addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+ >> SSB_DMA_TRANSLATION_SHIFT;
+ value = B43legacy_DMA32_TXENABLE;
+ value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
+ & B43legacy_DMA32_TXADDREXT_MASK;
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, value);
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
+ (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+ | trans);
} else {
err = alloc_initial_descbuffers(ring);
if (err)
goto out;
- if (ring->type == B43legacy_DMA_64BIT) {
- u64 ringbase = (u64)(ring->dmabase);
-
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = (ring->frameoffset <<
- B43legacy_DMA64_RXFROFF_SHIFT);
- value |= B43legacy_DMA64_RXENABLE;
- value |= (addrext << B43legacy_DMA64_RXADDREXT_SHIFT)
- & B43legacy_DMA64_RXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA64_RXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK) |
- trans);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
- 200);
- } else {
- u32 ringbase = (u32)(ring->dmabase);
-
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = (ring->frameoffset <<
- B43legacy_DMA32_RXFROFF_SHIFT);
- value |= B43legacy_DMA32_RXENABLE;
- value |= (addrext <<
- B43legacy_DMA32_RXADDREXT_SHIFT)
- & B43legacy_DMA32_RXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
- (ringbase &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX,
- 200);
- }
+
+ addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+ >> SSB_DMA_TRANSLATION_SHIFT;
+ value = (ring->frameoffset <<
+ B43legacy_DMA32_RXFROFF_SHIFT);
+ value |= B43legacy_DMA32_RXENABLE;
+ value |= (addrext << B43legacy_DMA32_RXADDREXT_SHIFT)
+ & B43legacy_DMA32_RXADDREXT_MASK;
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, value);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
+ (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+ | trans);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, 200);
}
out:
@@ -799,32 +589,23 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
if (ring->tx) {
b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
ring->type);
- if (ring->type == B43legacy_DMA_64BIT) {
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0);
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0);
- } else
- b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
} else {
b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
ring->type);
- if (ring->type == B43legacy_DMA_64BIT) {
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0);
- } else
- b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
}
}
static void free_all_descbuffers(struct b43legacy_dmaring *ring)
{
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ op32_idx2desc(ring, i, &meta);
if (!meta->skb) {
B43legacy_WARN_ON(!ring->tx);
@@ -845,9 +626,6 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
u32 tmp;
u16 mmio_base;
- tmp = b43legacy_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
- return DMA_BIT_MASK(64);
mmio_base = b43legacy_dmacontroller_base(0, 0);
b43legacy_write32(dev,
mmio_base + B43legacy_DMA32_TXCTL,
@@ -866,8 +644,6 @@ static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
return B43legacy_DMA_30BIT;
if (dmamask == DMA_BIT_MASK(32))
return B43legacy_DMA_32BIT;
- if (dmamask == DMA_BIT_MASK(64))
- return B43legacy_DMA_64BIT;
B43legacy_WARN_ON(1);
return B43legacy_DMA_30BIT;
}
@@ -938,10 +714,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
ring->nr_slots = nr_slots;
ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
ring->index = controller_index;
- if (type == B43legacy_DMA_64BIT)
- ring->ops = &dma64_ops;
- else
- ring->ops = &dma32_ops;
if (for_tx) {
ring->tx = 1;
ring->current_slot = -1;
@@ -1094,6 +866,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
return -EOPNOTSUPP;
#endif
}
+ dma->translation = ssb_dma_translation(dev->dev);
err = -ENOMEM;
/* setup TX DMA channels. */
@@ -1247,12 +1020,11 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
struct sk_buff **in_skb)
{
struct sk_buff *skb = *in_skb;
- const struct b43legacy_dma_ops *ops = ring->ops;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
int slot, old_top_slot, old_used_slots;
int err;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
struct b43legacy_dmadesc_meta *meta_hdr;
struct sk_buff *bounce_skb;
@@ -1265,7 +1037,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
/* Get a slot for the header. */
slot = request_slot(ring);
- desc = ops->idx2desc(ring, slot, &meta_hdr);
+ desc = op32_idx2desc(ring, slot, &meta_hdr);
memset(meta_hdr, 0, sizeof(*meta_hdr));
header = &(ring->txhdr_cache[slot * sizeof(
@@ -1287,12 +1059,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
ring->used_slots = old_used_slots;
return -EIO;
}
- ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
+ op32_fill_descriptor(ring, desc, meta_hdr->dmaaddr,
sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0);
/* Get a slot for the payload. */
slot = request_slot(ring);
- desc = ops->idx2desc(ring, slot, &meta);
+ desc = op32_idx2desc(ring, slot, &meta);
memset(meta, 0, sizeof(*meta));
meta->skb = skb;
@@ -1328,12 +1100,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
}
}
- ops->fill_descriptor(ring, desc, meta->dmaaddr,
+ op32_fill_descriptor(ring, desc, meta->dmaaddr,
skb->len, 0, 1, 1);
wmb(); /* previous stuff MUST be done */
/* Now transfer the whole frame. */
- ops->poke_tx(ring, next_slot(ring, slot));
+ op32_poke_tx(ring, next_slot(ring, slot));
return 0;
out_free_bounce:
@@ -1371,10 +1143,8 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
struct sk_buff *skb)
{
struct b43legacy_dmaring *ring;
- struct ieee80211_hdr *hdr;
int err = 0;
unsigned long flags;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
spin_lock_irqsave(&ring->lock, flags);
@@ -1401,8 +1171,6 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
/* 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
@@ -1433,9 +1201,7 @@ out_unlock:
void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
const struct b43legacy_txstatus *status)
{
- const struct b43legacy_dma_ops *ops;
struct b43legacy_dmaring *ring;
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int retry_limit;
int slot;
@@ -1447,10 +1213,9 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
spin_lock(&ring->lock);
B43legacy_WARN_ON(!ring->tx);
- ops = ring->ops;
while (1) {
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- desc = ops->idx2desc(ring, slot, &meta);
+ op32_idx2desc(ring, slot, &meta);
if (meta->skb)
unmap_descbuffer(ring, meta->dmaaddr,
@@ -1533,8 +1298,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
static void dma_rx(struct b43legacy_dmaring *ring,
int *slot)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
struct b43legacy_rxhdr_fw3 *rxhdr;
struct sk_buff *skb;
@@ -1542,7 +1306,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
int err;
dma_addr_t dmaaddr;
- desc = ops->idx2desc(ring, *slot, &meta);
+ desc = op32_idx2desc(ring, *slot, &meta);
sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
skb = meta->skb;
@@ -1594,7 +1358,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
s32 tmp = len;
while (1) {
- desc = ops->idx2desc(ring, *slot, &meta);
+ desc = op32_idx2desc(ring, *slot, &meta);
/* recycle the descriptor buffer. */
sync_descbuffer_for_device(ring, meta->dmaaddr,
ring->rx_buffersize);
@@ -1631,13 +1395,12 @@ drop:
void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
int slot;
int current_slot;
int used_slots = 0;
B43legacy_WARN_ON(ring->tx);
- current_slot = ops->get_current_rxslot(ring);
+ current_slot = op32_get_current_rxslot(ring);
B43legacy_WARN_ON(!(current_slot >= 0 && current_slot <
ring->nr_slots));
@@ -1646,7 +1409,7 @@ void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
dma_rx(ring, &slot);
update_max_used_slots(ring, ++used_slots);
}
- ops->set_current_rxslot(ring, slot);
+ op32_set_current_rxslot(ring, slot);
ring->current_slot = slot;
}
@@ -1656,7 +1419,7 @@ static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring)
spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- ring->ops->tx_suspend(ring);
+ op32_tx_suspend(ring);
spin_unlock_irqrestore(&ring->lock, flags);
}
@@ -1666,7 +1429,7 @@ static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring)
spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- ring->ops->tx_resume(ring);
+ op32_tx_resume(ring);
spin_unlock_irqrestore(&ring->lock, flags);
}
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h
index f89c342..504a587 100644
--- a/drivers/net/wireless/b43legacy/dma.h
+++ b/drivers/net/wireless/b43legacy/dma.h
@@ -5,7 +5,7 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "b43legacy.h"
@@ -82,90 +82,6 @@ struct b43legacy_dmadesc32 {
#define B43legacy_DMA32_DCTL_FRAMESTART 0x80000000
-
-/*** 64-bit DMA Engine. ***/
-
-/* 64-bit DMA controller registers. */
-#define B43legacy_DMA64_TXCTL 0x00
-#define B43legacy_DMA64_TXENABLE 0x00000001
-#define B43legacy_DMA64_TXSUSPEND 0x00000002
-#define B43legacy_DMA64_TXLOOPBACK 0x00000004
-#define B43legacy_DMA64_TXFLUSH 0x00000010
-#define B43legacy_DMA64_TXADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_TXADDREXT_SHIFT 16
-#define B43legacy_DMA64_TXINDEX 0x04
-#define B43legacy_DMA64_TXRINGLO 0x08
-#define B43legacy_DMA64_TXRINGHI 0x0C
-#define B43legacy_DMA64_TXSTATUS 0x10
-#define B43legacy_DMA64_TXSTATDPTR 0x00001FFF
-#define B43legacy_DMA64_TXSTAT 0xF0000000
-#define B43legacy_DMA64_TXSTAT_DISABLED 0x00000000
-#define B43legacy_DMA64_TXSTAT_ACTIVE 0x10000000
-#define B43legacy_DMA64_TXSTAT_IDLEWAIT 0x20000000
-#define B43legacy_DMA64_TXSTAT_STOPPED 0x30000000
-#define B43legacy_DMA64_TXSTAT_SUSP 0x40000000
-#define B43legacy_DMA64_TXERROR 0x14
-#define B43legacy_DMA64_TXERRDPTR 0x0001FFFF
-#define B43legacy_DMA64_TXERR 0xF0000000
-#define B43legacy_DMA64_TXERR_NOERR 0x00000000
-#define B43legacy_DMA64_TXERR_PROT 0x10000000
-#define B43legacy_DMA64_TXERR_UNDERRUN 0x20000000
-#define B43legacy_DMA64_TXERR_TRANSFER 0x30000000
-#define B43legacy_DMA64_TXERR_DESCREAD 0x40000000
-#define B43legacy_DMA64_TXERR_CORE 0x50000000
-#define B43legacy_DMA64_RXCTL 0x20
-#define B43legacy_DMA64_RXENABLE 0x00000001
-#define B43legacy_DMA64_RXFROFF_MASK 0x000000FE
-#define B43legacy_DMA64_RXFROFF_SHIFT 1
-#define B43legacy_DMA64_RXDIRECTFIFO 0x00000100
-#define B43legacy_DMA64_RXADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_RXADDREXT_SHIFT 16
-#define B43legacy_DMA64_RXINDEX 0x24
-#define B43legacy_DMA64_RXRINGLO 0x28
-#define B43legacy_DMA64_RXRINGHI 0x2C
-#define B43legacy_DMA64_RXSTATUS 0x30
-#define B43legacy_DMA64_RXSTATDPTR 0x00001FFF
-#define B43legacy_DMA64_RXSTAT 0xF0000000
-#define B43legacy_DMA64_RXSTAT_DISABLED 0x00000000
-#define B43legacy_DMA64_RXSTAT_ACTIVE 0x10000000
-#define B43legacy_DMA64_RXSTAT_IDLEWAIT 0x20000000
-#define B43legacy_DMA64_RXSTAT_STOPPED 0x30000000
-#define B43legacy_DMA64_RXSTAT_SUSP 0x40000000
-#define B43legacy_DMA64_RXERROR 0x34
-#define B43legacy_DMA64_RXERRDPTR 0x0001FFFF
-#define B43legacy_DMA64_RXERR 0xF0000000
-#define B43legacy_DMA64_RXERR_NOERR 0x00000000
-#define B43legacy_DMA64_RXERR_PROT 0x10000000
-#define B43legacy_DMA64_RXERR_UNDERRUN 0x20000000
-#define B43legacy_DMA64_RXERR_TRANSFER 0x30000000
-#define B43legacy_DMA64_RXERR_DESCREAD 0x40000000
-#define B43legacy_DMA64_RXERR_CORE 0x50000000
-
-/* 64-bit DMA descriptor. */
-struct b43legacy_dmadesc64 {
- __le32 control0;
- __le32 control1;
- __le32 address_low;
- __le32 address_high;
-} __packed;
-#define B43legacy_DMA64_DCTL0_DTABLEEND 0x10000000
-#define B43legacy_DMA64_DCTL0_IRQ 0x20000000
-#define B43legacy_DMA64_DCTL0_FRAMEEND 0x40000000
-#define B43legacy_DMA64_DCTL0_FRAMESTART 0x80000000
-#define B43legacy_DMA64_DCTL1_BYTECNT 0x00001FFF
-#define B43legacy_DMA64_DCTL1_ADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_DCTL1_ADDREXT_SHIFT 16
-
-
-
-struct b43legacy_dmadesc_generic {
- union {
- struct b43legacy_dmadesc32 dma32;
- struct b43legacy_dmadesc64 dma64;
- } __packed;
-} __packed;
-
-
/* Misc DMA constants */
#define B43legacy_DMA_RINGMEMSIZE PAGE_SIZE
#define B43legacy_DMA0_RX_FRAMEOFFSET 30
@@ -197,35 +113,12 @@ struct b43legacy_dmadesc_meta {
bool is_last_fragment;
};
-struct b43legacy_dmaring;
-
-/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
-struct b43legacy_dma_ops {
- struct b43legacy_dmadesc_generic * (*idx2desc)
- (struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta
- **meta);
- void (*fill_descriptor)(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
- dma_addr_t dmaaddr, u16 bufsize,
- int start, int end, int irq);
- void (*poke_tx)(struct b43legacy_dmaring *ring, int slot);
- void (*tx_suspend)(struct b43legacy_dmaring *ring);
- void (*tx_resume)(struct b43legacy_dmaring *ring);
- int (*get_current_rxslot)(struct b43legacy_dmaring *ring);
- void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot);
-};
-
enum b43legacy_dmatype {
B43legacy_DMA_30BIT = 30,
B43legacy_DMA_32BIT = 32,
- B43legacy_DMA_64BIT = 64,
};
struct b43legacy_dmaring {
- /* Lowlevel DMA ops. */
- const struct b43legacy_dma_ops *ops;
/* Kernel virtual base address of the ring memory. */
void *descbase;
/* Meta data about all descriptors. */
diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c
index a849078..ee5682e 100644
--- a/drivers/net/wireless/b43legacy/ilt.c
+++ b/drivers/net/wireless/b43legacy/ilt.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index 37e9be8..2f1bfdc 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 4e8b481..71195cb 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
- * Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
* Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -31,11 +31,10 @@
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
@@ -61,7 +60,6 @@ MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43legacy/ucode2.fw");
MODULE_FIRMWARE("b43legacy/ucode4.fw");
@@ -1564,10 +1562,8 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
int err;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
if (!fw->ucode) {
if (rev == 2)
filename = "ucode2";
@@ -2468,7 +2464,8 @@ out:
}
}
-static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
return 0;
@@ -2634,11 +2631,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna_tx;
- int antenna_rx;
int err = 0;
antenna_tx = B43legacy_ANTENNA_DEFAULT;
- antenna_rx = B43legacy_ANTENNA_DEFAULT;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -2775,14 +2770,12 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
- struct b43legacy_phy *phy;
unsigned long flags;
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(wl->vif != vif);
dev = wl->current_dev;
- phy = &dev->phy;
/* Disable IRQs while reconfiguring the device.
* This makes it possible to drop the spinlock throughout
@@ -2974,7 +2967,7 @@ static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)
break;
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
@@ -3789,7 +3782,8 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
ssb_set_devtypedata(dev, wl);
- b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+ b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n",
+ dev->bus->chip_id, dev->id.revision);
err = 0;
out:
return err;
@@ -3953,8 +3947,7 @@ static void b43legacy_print_driverinfo(void)
feat_dma = "D";
#endif
printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
- "[ Features: %s%s%s%s, Firmware-ID: "
- B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
+ "[ Features: %s%s%s%s ]\n",
feat_pci, feat_leds, feat_pio, feat_dma);
}
diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h
index 1f0e2e37..b74a058 100644
--- a/drivers/net/wireless/b43legacy/main.h
+++ b/drivers/net/wireless/b43legacy/main.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 28e477d..96faaef 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h
index ecbe409..831a7a4 100644
--- a/drivers/net/wireless/b43legacy/phy.h
+++ b/drivers/net/wireless/b43legacy/phy.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index b033b0e..192251a 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -4,7 +4,7 @@
PIO Transmission
- Copyright (c) 2005 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005 Michael Buesch <m@bues.ch>
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
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 2df545c..475eb14 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h
index ec4de28..bccb3d7 100644
--- a/drivers/net/wireless/b43legacy/radio.h
+++ b/drivers/net/wireless/b43legacy/radio.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index b90f223..c4559bc 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
RFKILL support
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
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
diff --git a/drivers/net/wireless/b43legacy/sysfs.c b/drivers/net/wireless/b43legacy/sysfs.c
index 56c384f..57f8b08 100644
--- a/drivers/net/wireless/b43legacy/sysfs.c
+++ b/drivers/net/wireless/b43legacy/sysfs.c
@@ -4,7 +4,7 @@
SYSFS support routines
- Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006 Michael Buesch <m@bues.ch>
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
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 3a95541..5188fab 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -6,7 +6,7 @@
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (C) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -321,11 +321,9 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
struct ieee80211_hdr *hdr;
int rts_rate;
int rts_rate_fb;
- int rts_rate_ofdm;
int rts_rate_fb_ofdm;
rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
- rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
if (rts_rate_fb_ofdm)
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index e0b3e8d..df7050a 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1,5 +1,6 @@
#include <linux/etherdevice.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <net/lib80211.h>
#include <linux/if_arp.h>
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index c34a3b7..344a981 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,4 +1,5 @@
#include <linux/slab.h>
+#include <linux/export.h>
#include "hostap_80211.h"
#include "hostap_common.h"
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 3d05dc1..e1f4102 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -21,6 +21,8 @@
#include <linux/random.h>
#include <linux/if_arp.h>
#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/moduleparam.h>
#include "hostap_wlan.h"
#include "hostap.h"
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index c052a0d..5441ad1 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -648,6 +648,8 @@ static const struct pcmcia_device_id hostap_cs_ids[] = {
0x74c5e40d),
PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil",
0x4b801a17),
+ PCMCIA_DEVICE_MANF_CARD_PROD_ID3(0x0156, 0x0002, "Version 01.02",
+ 0x4b74baa0),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
0x7a954bd9, 0x74be00c6),
PCMCIA_DEVICE_PROD_ID123(
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index d737091..47932b2 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -3,6 +3,7 @@
#include <linux/if_arp.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "hostap_wlan.h"
#include "hostap.h"
#include "hostap_ap.h"
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 10ce1bc..271e818 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -5,6 +5,7 @@
#include <linux/sched.h>
#include <linux/ethtool.h>
#include <linux/if_arp.h>
+#include <linux/module.h>
#include <net/lib80211.h>
#include "hostap_wlan.h"
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 89a116f..bfa0d54 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -816,7 +816,7 @@ static const struct net_device_ops hostap_netdev_ops = {
.ndo_stop = prism2_close,
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
- .ndo_set_multicast_list = hostap_set_multicast_list,
+ .ndo_set_rx_mode = hostap_set_multicast_list,
.ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -829,7 +829,7 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = {
.ndo_stop = prism2_close,
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
- .ndo_set_multicast_list = hostap_set_multicast_list,
+ .ndo_set_rx_mode = hostap_set_multicast_list,
.ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -842,7 +842,7 @@ static const struct net_device_ops hostap_master_ops = {
.ndo_stop = prism2_close,
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
- .ndo_set_multicast_list = hostap_set_multicast_list,
+ .ndo_set_rx_mode = hostap_set_multicast_list,
.ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index 005ff25..75ef8f0 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -2,6 +2,7 @@
#include <linux/types.h>
#include <linux/proc_fs.h>
+#include <linux/export.h>
#include <net/lib80211.h>
#include "hostap_wlan.h"
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 88dc6a5..7bb0b4b 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,7 @@
#ifndef HOSTAP_WLAN_H
#define HOSTAP_WLAN_H
+#include <linux/interrupt.h>
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <linux/mutex.h>
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 4430775..10862d4 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -161,11 +161,12 @@ that only one external action is invoked at a time.
#include <linux/firmware.h>
#include <linux/acpi.h>
#include <linux/ctype.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <net/lib80211.h>
#include "ipw2100.h"
+#include "ipw.h"
#define IPW2100_VERSION "git-1.2.2"
@@ -174,7 +175,7 @@ that only one external action is invoked at a time.
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
-static struct pm_qos_request_list ipw2100_pm_qos_req;
+static struct pm_qos_request ipw2100_pm_qos_req;
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
@@ -287,7 +288,7 @@ static const char *command_types[] = {
"unused", /* HOST_INTERRUPT_COALESCING */
"undefined",
"CARD_DISABLE_PHY_OFF",
- "MSDU_TX_RATES" "undefined",
+ "MSDU_TX_RATES",
"undefined",
"SET_STATION_STAT_BITS",
"CLEAR_STATIONS_STAT_BITS",
@@ -1903,15 +1904,17 @@ static void ipw2100_down(struct ipw2100_priv *priv)
static int ipw2100_net_init(struct net_device *dev)
{
struct ipw2100_priv *priv = libipw_priv(dev);
+
+ return ipw2100_up(priv, 1);
+}
+
+static int ipw2100_wdev_init(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = libipw_priv(dev);
const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
struct wireless_dev *wdev = &priv->ieee->wdev;
- int ret;
int i;
- ret = ipw2100_up(priv, 1);
- if (ret)
- return ret;
-
memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
/* fill-out priv->ieee->bg_band */
@@ -1953,6 +1956,9 @@ static int ipw2100_net_init(struct net_device *dev)
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
}
+ wdev->wiphy->cipher_suites = ipw_cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites);
+
set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
if (wiphy_register(wdev->wiphy)) {
ipw2100_down(priv);
@@ -6350,9 +6356,13 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
"Error calling register_netdev.\n");
goto fail;
}
+ registered = 1;
+
+ err = ipw2100_wdev_init(dev);
+ if (err)
+ goto fail;
mutex_lock(&priv->action_mutex);
- registered = 1;
IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev));
@@ -6389,7 +6399,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
fail_unlock:
mutex_unlock(&priv->action_mutex);
-
+ wiphy_unregister(priv->ieee->wdev.wiphy);
+ kfree(priv->ieee->bg_band.channels);
fail:
if (dev) {
if (registered)
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index b2707d73..da567f0 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -32,7 +32,9 @@
#include <linux/sched.h>
#include <linux/slab.h>
+#include <net/cfg80211-wext.h>
#include "ipw2200.h"
+#include "ipw.h"
#ifndef KBUILD_EXTMOD
@@ -10461,7 +10463,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
} else
len = src->len;
- dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+ dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
if (!dst)
continue;
@@ -11436,16 +11438,23 @@ static void ipw_bg_down(struct work_struct *work)
/* Called by register_netdev() */
static int ipw_net_init(struct net_device *dev)
{
+ int rc = 0;
+ struct ipw_priv *priv = libipw_priv(dev);
+
+ mutex_lock(&priv->mutex);
+ if (ipw_up(priv))
+ rc = -EIO;
+ mutex_unlock(&priv->mutex);
+
+ return rc;
+}
+
+static int ipw_wdev_init(struct net_device *dev)
+{
int i, rc = 0;
struct ipw_priv *priv = libipw_priv(dev);
const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
struct wireless_dev *wdev = &priv->ieee->wdev;
- mutex_lock(&priv->mutex);
-
- if (ipw_up(priv)) {
- rc = -EIO;
- goto out;
- }
memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
@@ -11527,16 +11536,15 @@ static int ipw_net_init(struct net_device *dev)
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band;
}
+ wdev->wiphy->cipher_suites = ipw_cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites);
+
set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
/* With that information in place, we can now register the wiphy... */
- if (wiphy_register(wdev->wiphy)) {
+ if (wiphy_register(wdev->wiphy))
rc = -EIO;
- goto out;
- }
-
out:
- mutex_unlock(&priv->mutex);
return rc;
}
@@ -11712,7 +11720,7 @@ static const struct net_device_ops ipw_netdev_ops = {
.ndo_init = ipw_net_init,
.ndo_open = ipw_net_open,
.ndo_stop = ipw_net_stop,
- .ndo_set_multicast_list = ipw_net_set_multicast_list,
+ .ndo_set_rx_mode = ipw_net_set_multicast_list,
.ndo_set_mac_address = ipw_net_set_mac_address,
.ndo_start_xmit = libipw_xmit,
.ndo_change_mtu = libipw_change_mtu,
@@ -11843,14 +11851,22 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
goto out_remove_sysfs;
}
+ err = ipw_wdev_init(net_dev);
+ if (err) {
+ IPW_ERROR("failed to register wireless device\n");
+ goto out_unregister_netdev;
+ }
+
#ifdef CONFIG_IPW2200_PROMISCUOUS
if (rtap_iface) {
err = ipw_prom_alloc(priv);
if (err) {
IPW_ERROR("Failed to register promiscuous network "
"device (error %d).\n", err);
- unregister_netdev(priv->net_dev);
- goto out_remove_sysfs;
+ wiphy_unregister(priv->ieee->wdev.wiphy);
+ kfree(priv->ieee->a_band.channels);
+ kfree(priv->ieee->bg_band.channels);
+ goto out_unregister_netdev;
}
}
#endif
@@ -11862,6 +11878,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
return 0;
+ out_unregister_netdev:
+ unregister_netdev(priv->net_dev);
out_remove_sysfs:
sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
out_release_irq:
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index 91795b5..ecb561d 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/pci.h>
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index e5ad76c..32a9966 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -442,7 +442,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
* 802.11, but makes it easier to use different keys with
* stations that do not support WEP key mapping). */
- if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ if (is_unicast_ether_addr(hdr->addr1) || local->bcrx_sta_key)
(void)hostap_handle_sta_crypto(local, hdr, &crypt,
&sta);
#endif
@@ -772,7 +772,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
#ifdef NOT_YET
if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
- if (dst[0] & 0x01) {
+ if (is_multicast_ether_addr(dst)) {
/* copy multicast frame both to the higher layers and
* to the wireless media */
ieee->ap->bridged_multicast++;
diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c
index 01c88a7..e8c0398 100644
--- a/drivers/net/wireless/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_tx.c
@@ -395,7 +395,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
(CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
bytes_per_frag -= LIBIPW_FCS_LEN;
- /* Each fragment may need to have room for encryptiong
+ /* Each fragment may need to have room for encryption
* pre/postfix */
if (host_encrypt)
bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index d7bd6cf0..6623e50 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -30,6 +30,7 @@
******************************************************************************/
+#include <linux/hardirq.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/module.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.c b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
index abd9235..7a7f0f3 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
@@ -32,7 +32,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
index 164bcae..8faeaf2 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
@@ -28,7 +28,6 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index effeabb..7d1aa7c 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -34,7 +34,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -408,7 +407,6 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
#endif
- iwl_legacy_recover_from_statistics(priv, pkt);
memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
}
@@ -2645,7 +2643,6 @@ static struct iwl_lib_ops iwl3945_lib = {
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
.txq_init = iwl3945_hw_tx_queue_init,
.load_ucode = iwl3945_load_bsm,
- .dump_nic_event_log = iwl3945_dump_nic_event_log,
.dump_nic_error_log = iwl3945_dump_nic_error_log,
.apm_ops = {
.init = iwl3945_apm_init,
@@ -2703,9 +2700,7 @@ static struct iwl_base_params iwl3945_base_params = {
.set_l0s = false,
.use_bsm = true,
.led_compensation = 64,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
.wd_timeout = IWL_DEF_WD_TIMEOUT,
- .max_event_log_size = 512,
};
static struct iwl_cfg iwl3945_bg_cfg = {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.c b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
index 26d324e..6862fdc 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
@@ -32,7 +32,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
index a7a4739..2be6d9e 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
@@ -694,47 +694,6 @@ void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
sizeof(struct iwl_rx_phy_res));
}
-static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u16 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
- channel = iwl_legacy_get_single_channel_number(priv, band);
- if (channel) {
- scan_ch->channel = cpu_to_le16(channel);
- scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set txpower levels to defaults */
- scan_ch->dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
struct ieee80211_vif *vif,
enum ieee80211_band band,
@@ -858,16 +817,13 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_legacy_is_any_associated(priv)) {
- u16 interval = 0;
+ u16 interval;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- if (priv->is_internal_short_scan)
- interval = 0;
- else
- interval = vif->bss_conf.beacon_int;
+ interval = vif->bss_conf.beacon_int;
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -882,9 +838,7 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -981,38 +935,21 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
scan->rx_chain = cpu_to_le16(rx_chain);
- if (!priv->is_internal_short_scan) {
- cmd_len = iwl_legacy_fill_probe_req(priv,
+
+ cmd_len = iwl_legacy_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
vif->addr,
priv->scan_request->ie,
priv->scan_request->ie_len,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
- } else {
- /* use bcast addr, will not be transmitted but must be valid */
- cmd_len = iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwlegacy_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
- }
scan->tx_cmd.len = cpu_to_le16(cmd_len);
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
RXON_FILTER_BCON_AWARE_MSK);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl4965_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl4965_get_channels_for_scan(priv, vif, band,
- is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- }
+ scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band,
+ is_active, n_probes,
+ (void *)&scan->data[cmd_len]);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
return -EIO;
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
index 24d1499..57ebe21 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -27,7 +27,6 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
@@ -2275,6 +2274,9 @@ iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
if (rate_control_send_low(sta, priv_sta, txrc))
return;
+ if (!lq_sta)
+ return;
+
rate_idx = lq_sta->last_txrate_idx;
if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
index b9fa2f6..2b144bb 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
@@ -151,81 +151,6 @@ static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
#define REG_RECALIB_PERIOD (60)
-/**
- * iwl4965_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl4965_good_plcp_health(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt)
-{
- bool rc = true;
- int combined_plcp_delta;
- unsigned int plcp_msec;
- unsigned long plcp_received_jiffies;
-
- if (priv->cfg->base_params->plcp_delta_threshold ==
- IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
- IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
- return rc;
- }
-
- /*
- * check for plcp_err and trigger radio reset if it exceeds
- * the plcp error threshold plcp_delta.
- */
- plcp_received_jiffies = jiffies;
- plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
- (long) priv->plcp_jiffies);
- priv->plcp_jiffies = plcp_received_jiffies;
- /*
- * check to make sure plcp_msec is not 0 to prevent division
- * by zero.
- */
- if (plcp_msec) {
- struct statistics_rx_phy *ofdm;
- struct statistics_rx_ht_phy *ofdm_ht;
-
- ofdm = &pkt->u.stats.rx.ofdm;
- ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
- combined_plcp_delta =
- (le32_to_cpu(ofdm->plcp_err) -
- le32_to_cpu(priv->_4965.statistics.
- rx.ofdm.plcp_err)) +
- (le32_to_cpu(ofdm_ht->plcp_err) -
- le32_to_cpu(priv->_4965.statistics.
- rx.ofdm_ht.plcp_err));
-
- if ((combined_plcp_delta > 0) &&
- ((combined_plcp_delta * 100) / plcp_msec) >
- priv->cfg->base_params->plcp_delta_threshold) {
- /*
- * if plcp_err exceed the threshold,
- * the following data is printed in csv format:
- * Text: plcp_err exceeded %d,
- * Received ofdm.plcp_err,
- * Current ofdm.plcp_err,
- * Received ofdm_ht.plcp_err,
- * Current ofdm_ht.plcp_err,
- * combined_plcp_delta,
- * plcp_msec
- */
- IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
- "%u, %u, %u, %u, %d, %u mSecs\n",
- priv->cfg->base_params->plcp_delta_threshold,
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- combined_plcp_delta, plcp_msec);
-
- rc = false;
- }
- }
- return rc;
-}
-
void iwl4965_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -248,8 +173,7 @@ void iwl4965_rx_statistics(struct iwl_priv *priv,
iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
- iwl_legacy_recover_from_statistics(priv, pkt);
-
+ /* TODO: reading some of statistics is unneeded */
memcpy(&priv->_4965.statistics, &pkt->u.stats,
sizeof(priv->_4965.statistics));
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-sta.c b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
index a262c23..0116ca8 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
@@ -466,7 +466,7 @@ int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
return 0;
}
- if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+ if (priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) {
IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
keyconf->keyidx, key_flags);
spin_unlock_irqrestore(&priv->sta_lock, flags);
@@ -483,7 +483,7 @@ int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
sizeof(struct iwl4965_keyinfo));
priv->stations[sta_id].sta.key.key_flags =
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
- priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+ priv->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
index 79ac081..7f12e36 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
@@ -240,8 +240,7 @@ static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
- ieee80211_get_tkip_key(keyconf, skb_frag,
- IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
break;
@@ -336,7 +335,7 @@ int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
sta_priv = (void *)sta->drv_priv;
if (sta_priv && sta_priv->asleep &&
- (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+ (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
/*
* This sends an asynchronous command to the device,
* but we can rely on it being processed before the
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
index 0a1babb..86f4fce 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -33,7 +33,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -496,7 +495,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
return CALIB_CH_GROUP_4;
- return -1;
+ return -EINVAL;
}
static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
@@ -915,7 +914,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
if (txatten_grp < 0) {
IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
channel);
- return -EINVAL;
+ return txatten_grp;
}
IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
@@ -1185,8 +1184,6 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
sizeof(rxon_assoc), &rxon_assoc, NULL);
- if (ret)
- return ret;
return ret;
}
@@ -2075,7 +2072,6 @@ static struct iwl_lib_ops iwl4965_lib = {
.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
.init_alive_start = iwl4965_init_alive_start,
.load_ucode = iwl4965_load_bsm,
- .dump_nic_event_log = iwl4965_dump_nic_event_log,
.dump_nic_error_log = iwl4965_dump_nic_error_log,
.dump_fh = iwl4965_dump_fh,
.set_channel_switch = iwl4965_hw_channel_switch,
@@ -2106,7 +2102,6 @@ static struct iwl_lib_ops iwl4965_lib = {
.tx_stats_read = iwl4965_ucode_tx_stats_read,
.general_stats_read = iwl4965_ucode_general_stats_read,
},
- .check_plcp_health = iwl4965_good_plcp_health,
};
static const struct iwl_legacy_ops iwl4965_legacy_ops = {
@@ -2156,10 +2151,8 @@ static struct iwl_base_params iwl4965_base_params = {
.use_bsm = true,
.led_compensation = 61,
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
.wd_timeout = IWL_DEF_WD_TIMEOUT,
.temperature_kelvin = true,
- .max_event_log_size = 512,
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlegacy/iwl-commands.h b/drivers/net/wireless/iwlegacy/iwl-commands.h
index 17a1d50..8990405 100644
--- a/drivers/net/wireless/iwlegacy/iwl-commands.h
+++ b/drivers/net/wireless/iwlegacy/iwl-commands.h
@@ -2297,14 +2297,7 @@ struct iwl_spectrum_notification {
#define IWL_POWER_VEC_SIZE 5
#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_SAVE_ENA_MSK cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK cpu_to_le16(BIT(1))
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2))
#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3))
-#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4))
-#define IWL_POWER_BEACON_FILTERING cpu_to_le16(BIT(5))
-#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6))
-#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7))
struct iwl3945_powertable_cmd {
__le16 flags;
@@ -2624,8 +2617,8 @@ struct iwl_scanstart_notification {
__le32 status;
} __packed;
-#define SCAN_OWNER_STATUS 0x1;
-#define MEASURE_OWNER_STATUS 0x2;
+#define SCAN_OWNER_STATUS 0x1
+#define MEASURE_OWNER_STATUS 0x2
#define IWL_PROBE_STATUS_OK 0
#define IWL_PROBE_STATUS_TX_FAILED BIT(0)
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index d273d50..09891e5 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -931,7 +931,6 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
priv->cfg->ops->lib->dump_nic_error_log(priv);
if (priv->cfg->ops->lib->dump_fh)
priv->cfg->ops->lib->dump_fh(priv, NULL, false);
- priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
iwl_legacy_print_rx_config_cmd(priv,
@@ -1251,7 +1250,8 @@ void iwl_legacy_clear_isr_stats(struct iwl_priv *priv)
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
}
-int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = hw->priv;
@@ -1707,41 +1707,14 @@ iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
EXPORT_SYMBOL(iwl_legacy_update_stats);
#endif
-static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (!iwl_legacy_is_any_associated(priv)) {
- IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
- return;
- }
- /*
- * There is no easy and better way to force reset the radio,
- * the only known method is switching channel which will force to
- * reset and tune the radio.
- * Use internal short scan (single channel) operation to should
- * achieve this objective.
- * Driver should reset the radio when number of consecutive missed
- * beacon, or any other uCode error condition detected.
- */
- IWL_DEBUG_INFO(priv, "perform radio reset.\n");
- iwl_legacy_internal_short_hw_scan(priv);
-}
-
-
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
{
struct iwl_force_reset *force_reset;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EINVAL;
- if (mode >= IWL_MAX_FORCE_RESET) {
- IWL_DEBUG_INFO(priv, "invalid reset request.\n");
- return -EINVAL;
- }
- force_reset = &priv->force_reset[mode];
+ force_reset = &priv->force_reset;
force_reset->reset_request_count++;
if (!external) {
if (force_reset->last_force_reset_jiffies &&
@@ -1754,39 +1727,37 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
}
force_reset->reset_success_count++;
force_reset->last_force_reset_jiffies = jiffies;
- IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
- switch (mode) {
- case IWL_RF_RESET:
- _iwl_legacy_force_rf_reset(priv);
- break;
- case IWL_FW_RESET:
- /*
- * if the request is from external(ex: debugfs),
- * then always perform the request in regardless the module
- * parameter setting
- * if the request is from internal (uCode error or driver
- * detect failure), then fw_restart module parameter
- * need to be check before performing firmware reload
- */
- if (!external && !priv->cfg->mod_params->restart_fw) {
- IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
- "module parameter setting\n");
- break;
- }
- IWL_ERR(priv, "On demand firmware reload\n");
- /* Set the FW error flag -- cleared on iwl_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
- wake_up(&priv->wait_command_queue);
- /*
- * Keep the restart process from trying to send host
- * commands by clearing the INIT status bit
- */
- clear_bit(STATUS_READY, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- break;
+
+ /*
+ * if the request is from external(ex: debugfs),
+ * then always perform the request in regardless the module
+ * parameter setting
+ * if the request is from internal (uCode error or driver
+ * detect failure), then fw_restart module parameter
+ * need to be check before performing firmware reload
+ */
+
+ if (!external && !priv->cfg->mod_params->restart_fw) {
+ IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+ "module parameter setting\n");
+ return 0;
}
+
+ IWL_ERR(priv, "On demand firmware reload\n");
+
+ /* Set the FW error flag -- cleared on iwl_down */
+ set_bit(STATUS_FW_ERROR, &priv->status);
+ wake_up(&priv->wait_command_queue);
+ /*
+ * Keep the restart process from trying to send host
+ * commands by clearing the INIT status bit
+ */
+ clear_bit(STATUS_READY, &priv->status);
+ queue_work(priv->workqueue, &priv->restart);
+
return 0;
}
+EXPORT_SYMBOL(iwl_legacy_force_reset);
int
iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
@@ -1879,7 +1850,7 @@ static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
if (time_after(jiffies, timeout)) {
IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
q->id, priv->cfg->base_params->wd_timeout);
- ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+ ret = iwl_legacy_force_reset(priv, false);
return (ret == -EAGAIN) ? 0 : 1;
}
@@ -1914,14 +1885,12 @@ void iwl_legacy_bg_watchdog(unsigned long data)
return;
/* monitor and check for other stuck queues */
- if (iwl_legacy_is_any_associated(priv)) {
- for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
- /* skip as we already checked the command queue */
- if (cnt == priv->cmd_queue)
- continue;
- if (iwl_legacy_check_stuck_queue(priv, cnt))
- return;
- }
+ for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+ /* skip as we already checked the command queue */
+ if (cnt == priv->cmd_queue)
+ continue;
+ if (iwl_legacy_check_stuck_queue(priv, cnt))
+ return;
}
mod_timer(&priv->watchdog, jiffies +
@@ -2251,7 +2220,8 @@ out:
}
EXPORT_SYMBOL(iwl_legacy_mac_config);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
index c5fbda0..d1271fe 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.h
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -143,8 +143,7 @@ struct iwl_lib_ops {
int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv);
- int (*dump_nic_event_log)(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
+
void (*dump_nic_error_log)(struct iwl_priv *priv);
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
int (*set_channel_switch)(struct iwl_priv *priv,
@@ -161,9 +160,6 @@ struct iwl_lib_ops {
/* temperature */
struct iwl_temp_ops temp_ops;
- /* check for plcp health */
- bool (*check_plcp_health)(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt);
struct iwl_debugfs_ops debugfs_ops;
@@ -207,11 +203,8 @@ struct iwl_mod_params {
* to the deviation to achieve the desired led frequency.
* The detail algorithm is described in iwl-led.c
* @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- * radio tuning when there is a high receiving plcp error rate
* @wd_timeout: TX queues watchdog timeout
* @temperature_kelvin: temperature report by uCode in kelvin
- * @max_event_log_size: size of event log buffer size for ucode event logging
* @ucode_tracing: support ucode continuous tracing
* @sensitivity_calib_by_driver: driver has the capability to perform
* sensitivity calibration operation
@@ -229,10 +222,8 @@ struct iwl_base_params {
u16 led_compensation;
int chain_noise_num_beacons;
- u8 plcp_delta_threshold;
unsigned int wd_timeout;
bool temperature_kelvin;
- u32 max_event_log_size;
const bool ucode_tracing;
const bool sensitivity_calib_by_driver;
const bool chain_noise_calib_by_driver;
@@ -295,7 +286,8 @@ struct iwl_cfg {
***************************/
struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg);
-int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
@@ -441,7 +433,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);
u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
struct ieee80211_mgmt *frame,
const u8 *ta, const u8 *ie, int ie_len, int left);
@@ -493,7 +485,7 @@ static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)
{
int pos;
u16 pci_lnk_ctl;
- pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(priv->pci_dev);
pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
return pci_lnk_ctl;
}
@@ -521,8 +513,6 @@ extern const struct dev_pm_ops iwl_legacy_pm_ops;
* Error Handling Debugging
******************************************************/
void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
@@ -631,7 +621,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
/* mac80211 handlers */
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
index 2d32438..1407dca 100644
--- a/drivers/net/wireless/iwlegacy/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
@@ -26,6 +26,7 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include <linux/ieee80211.h>
+#include <linux/export.h>
#include <net/mac80211.h>
@@ -391,48 +392,6 @@ static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
return ret;
}
-static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char *buf;
- int pos = 0;
- ssize_t ret = -ENOMEM;
-
- ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
- priv, true, &buf, true);
- if (buf) {
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- }
- return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- u32 event_log_flag;
- char buf[8];
- int buf_size;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &event_log_flag) != 1)
- return -EFAULT;
- if (event_log_flag == 1)
- priv->cfg->ops->lib->dump_nic_event_log(priv, true,
- NULL, false);
-
- return count;
-}
-
-
-
static ssize_t
iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -706,7 +665,6 @@ static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels);
@@ -1098,56 +1056,6 @@ static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
return count;
}
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[128];
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
- priv->event_log.ucode_trace ? "On" : "Off");
- pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
- priv->event_log.non_wraps_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
- priv->event_log.wraps_once_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
- priv->event_log.wraps_more_count);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int trace;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &trace) != 1)
- return -EFAULT;
-
- if (trace) {
- priv->event_log.ucode_trace = true;
- /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- } else {
- priv->event_log.ucode_trace = false;
- del_timer_sync(&priv->ucode_trace);
- }
-
- return count;
-}
-
static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
@@ -1236,72 +1144,31 @@ static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
return count;
}
-static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[12];
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
- priv->cfg->base_params->plcp_delta_threshold);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int plcp;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &plcp) != 1)
- return -EINVAL;
- if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
- (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
- priv->cfg->base_params->plcp_delta_threshold =
- IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
- else
- priv->cfg->base_params->plcp_delta_threshold = plcp;
- return count;
-}
-
static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
- int i, pos = 0;
+ int pos = 0;
char buf[300];
const size_t bufsz = sizeof(buf);
struct iwl_force_reset *force_reset;
- for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
- force_reset = &priv->force_reset[i];
- pos += scnprintf(buf + pos, bufsz - pos,
- "Force reset method %d\n", i);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request: %d\n",
- force_reset->reset_request_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request success: %d\n",
- force_reset->reset_success_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request reject: %d\n",
- force_reset->reset_reject_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\treset duration: %lu\n",
- force_reset->reset_duration);
- }
+ force_reset = &priv->force_reset;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request: %d\n",
+ force_reset->reset_request_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request success: %d\n",
+ force_reset->reset_success_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request reject: %d\n",
+ force_reset->reset_reject_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\treset duration: %lu\n",
+ force_reset->reset_duration);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1309,25 +1176,11 @@ static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos) {
+ int ret;
struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int reset, ret;
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &reset) != 1)
- return -EINVAL;
- switch (reset) {
- case IWL_RF_RESET:
- case IWL_FW_RESET:
- ret = iwl_legacy_force_reset(priv, reset, true);
- break;
- default:
- return -EINVAL;
- }
+ ret = iwl_legacy_force_reset(priv, true);
+
return ret ? ret : count;
}
@@ -1367,10 +1220,8 @@ DEBUGFS_READ_FILE_OPS(chain_noise);
DEBUGFS_READ_FILE_OPS(power_save_status);
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
DEBUGFS_READ_FILE_OPS(rxon_flags);
DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
@@ -1403,7 +1254,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
@@ -1420,7 +1270,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
@@ -1430,8 +1279,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
if (priv->cfg->base_params->chain_noise_calib_by_driver)
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
- if (priv->cfg->base_params->ucode_tracing)
- DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
index ea30122..9c786ed 100644
--- a/drivers/net/wireless/iwlegacy/iwl-dev.h
+++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
@@ -32,6 +32,7 @@
#ifndef __iwl_legacy_dev_h__
#define __iwl_legacy_dev_h__
+#include <linux/interrupt.h>
#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h>
#include <linux/leds.h>
@@ -855,32 +856,6 @@ struct traffic_stats {
};
/*
- * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
- * to perform continuous uCode event logging operation if enabled
- */
-#define UCODE_TRACE_PERIOD (100)
-
-/*
- * iwl_event_log: current uCode event log position
- *
- * @ucode_trace: enable/disable ucode continuous trace timer
- * @num_wraps: how many times the event buffer wraps
- * @next_entry: the entry just before the next one that uCode would fill
- * @non_wraps_count: counter for no wrap detected when dump ucode events
- * @wraps_once_count: counter for wrap once detected when dump ucode events
- * @wraps_more_count: counter for wrap more than once detected
- * when dump ucode events
- */
-struct iwl_event_log {
- bool ucode_trace;
- u32 num_wraps;
- u32 next_entry;
- int non_wraps_count;
- int wraps_once_count;
- int wraps_more_count;
-};
-
-/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
@@ -895,18 +870,6 @@ struct iwl_event_log {
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
-/*
- * This is the threshold value of plcp error rate per 100mSecs. It is
- * used to set and check for the validity of plcp_delta.
- */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (1)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
-#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
-#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0)
-
-#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
/* TX queue watchdog timeouts in mSecs */
@@ -914,12 +877,6 @@ struct iwl_event_log {
#define IWL_LONG_WD_TIMEOUT (10000)
#define IWL_MAX_WD_TIMEOUT (120000)
-enum iwl_reset {
- IWL_RF_RESET = 0,
- IWL_FW_RESET,
- IWL_MAX_FORCE_RESET,
-};
-
struct iwl_force_reset {
int reset_request_count;
int reset_success_count;
@@ -1032,11 +989,8 @@ struct iwl_priv {
/* track IBSS manager (last beacon) status */
u32 ibss_manager;
- /* storing the jiffies when the plcp error rate is received */
- unsigned long plcp_jiffies;
-
/* force reset */
- struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+ struct iwl_force_reset force_reset;
/* we allocate array of iwl_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
@@ -1057,7 +1011,6 @@ struct iwl_priv {
enum ieee80211_band scan_band;
struct cfg80211_scan_request *scan_request;
struct ieee80211_vif *scan_vif;
- bool is_internal_short_scan;
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant;
@@ -1212,12 +1165,6 @@ struct iwl_priv {
#endif
#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
struct {
- /*
- * reporting the number of tids has AGG on. 0 means
- * no AGGREGATION
- */
- u8 agg_tids_count;
-
struct iwl_rx_phy_res last_phy_res;
bool last_phy_res_valid;
@@ -1256,7 +1203,6 @@ struct iwl_priv {
struct iwl_rxon_context *beacon_ctx;
struct sk_buff *beacon_skb;
- struct work_struct start_internal_scan;
struct work_struct tx_flush;
struct tasklet_struct irq_tasklet;
@@ -1293,12 +1239,9 @@ struct iwl_priv {
u32 disable_tx_power_cal;
struct work_struct run_time_calib_work;
struct timer_list statistics_periodic;
- struct timer_list ucode_trace;
struct timer_list watchdog;
bool hw_ready;
- struct iwl_event_log event_log;
-
struct led_classdev led;
unsigned long blink_on, blink_off;
bool led_registered;
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
index 080b852..acec991 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.c
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
@@ -38,8 +38,5 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
index 9612aa0..a443725 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
@@ -96,47 +96,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_legacy_ucode
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
- TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
- TP_ARGS(priv, wraps, n_entry, p_entry),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, wraps)
- __field(u32, n_entry)
- __field(u32, p_entry)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->wraps = wraps;
- __entry->n_entry = n_entry;
- __entry->p_entry = p_entry;
- ),
- TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
- __entry->priv, __entry->wraps, __entry->n_entry,
- __entry->p_entry)
-);
-
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi
@@ -242,25 +201,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
__entry->blink2, __entry->ilink1, __entry->ilink2)
);
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
#endif /* __IWLWIFI_DEVICE_TRACE */
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
index cb346d1..5bf3f49 100644
--- a/drivers/net/wireless/iwlegacy/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
@@ -316,7 +316,6 @@ static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
break;
default:
BUG();
- return;
}
}
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
index a6effda..5cf23ea 100644
--- a/drivers/net/wireless/iwlegacy/iwl-helpers.h
+++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h
@@ -132,7 +132,16 @@ static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
ieee80211_stop_queue(priv->hw, ac);
}
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.c b/drivers/net/wireless/iwlegacy/iwl-led.c
index bda0d61..dc568a4 100644
--- a/drivers/net/wireless/iwlegacy/iwl-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-led.c
@@ -33,7 +33,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c
index 654cf23..f4d21ec 100644
--- a/drivers/net/wireless/iwlegacy/iwl-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-rx.c
@@ -29,6 +29,7 @@
#include <linux/etherdevice.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <net/mac80211.h>
#include <asm/unaligned.h>
#include "iwl-eeprom.h"
@@ -227,27 +228,6 @@ void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
-void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
- if (iwl_legacy_is_any_associated(priv)) {
- if (priv->cfg->ops->lib->check_plcp_health) {
- if (!priv->cfg->ops->lib->check_plcp_health(
- priv, pkt)) {
- /*
- * high plcp error detected
- * reset Radio
- */
- iwl_legacy_force_reset(priv,
- IWL_RF_RESET, false);
- }
- }
- }
-}
-EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
-
/*
* returns non-zero if packet should be dropped
*/
diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c
index 353234a..521b73b 100644
--- a/drivers/net/wireless/iwlegacy/iwl-scan.c
+++ b/drivers/net/wireless/iwlegacy/iwl-scan.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/etherdevice.h>
+#include <linux/export.h>
#include <net/mac80211.h>
#include "iwl-eeprom.h"
@@ -101,7 +102,6 @@ static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
ieee80211_scan_completed(priv->hw, aborted);
}
- priv->is_internal_short_scan = false;
priv->scan_vif = NULL;
priv->scan_request = NULL;
}
@@ -329,10 +329,8 @@ void iwl_legacy_init_scan_params(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_legacy_init_scan_params);
-static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- bool internal,
- enum ieee80211_band band)
+static int iwl_legacy_scan_initiate(struct iwl_priv *priv,
+ struct ieee80211_vif *vif)
{
int ret;
@@ -359,18 +357,14 @@ static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
return -EBUSY;
}
- IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
- internal ? "internal short " : "");
+ IWL_DEBUG_SCAN(priv, "Starting scan...\n");
set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = internal;
priv->scan_start = jiffies;
- priv->scan_band = band;
ret = priv->cfg->ops->utils->request_scan(priv, vif);
if (ret) {
clear_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = false;
return ret;
}
@@ -394,8 +388,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCANNING, &priv->status) &&
- !priv->is_internal_short_scan) {
+ if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
ret = -EAGAIN;
goto out_unlock;
@@ -404,17 +397,9 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
/* mac80211 will only ask for one band at a time */
priv->scan_request = req;
priv->scan_vif = vif;
+ priv->scan_band = req->channels[0]->band;
- /*
- * If an internal scan is in progress, just set
- * up the scan_request as per above.
- */
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
- ret = 0;
- } else
- ret = iwl_legacy_scan_initiate(priv, vif, false,
- req->channels[0]->band);
+ ret = iwl_legacy_scan_initiate(priv, vif);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -425,40 +410,6 @@ out_unlock:
}
EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
-/*
- * internal short scan, this function should only been called while associated.
- * It will reset and tune the radio to prevent possible RF related problem
- */
-void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
-{
- queue_work(priv->workqueue, &priv->start_internal_scan);
-}
-
-static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
-{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, start_internal_scan);
-
- IWL_DEBUG_SCAN(priv, "Start internal scan\n");
-
- mutex_lock(&priv->mutex);
-
- if (priv->is_internal_short_scan == true) {
- IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
- goto unlock;
- }
-
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
- goto unlock;
- }
-
- if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
- IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
- unlock:
- mutex_unlock(&priv->mutex);
-}
-
static void iwl_legacy_bg_scan_check(struct work_struct *data)
{
struct iwl_priv *priv =
@@ -542,8 +493,7 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
container_of(work, struct iwl_priv, scan_completed);
bool aborted;
- IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
- priv->is_internal_short_scan ? "internal short " : "");
+ IWL_DEBUG_SCAN(priv, "Completed scan.\n");
cancel_delayed_work(&priv->scan_check);
@@ -558,27 +508,6 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
goto out_settings;
}
- if (priv->is_internal_short_scan && !aborted) {
- int err;
-
- /* Check if mac80211 requested scan during our internal scan */
- if (priv->scan_request == NULL)
- goto out_complete;
-
- /* If so request a new scan */
- err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false,
- priv->scan_request->channels[0]->band);
- if (err) {
- IWL_DEBUG_SCAN(priv,
- "failed to initiate pending scan: %d\n", err);
- aborted = true;
- goto out_complete;
- }
-
- goto out;
- }
-
-out_complete:
iwl_legacy_complete_scan(priv, aborted);
out_settings:
@@ -590,8 +519,7 @@ out_settings:
* We do not commit power settings while scan is pending,
* do it now if the settings changed.
*/
- iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
- false);
+ iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
priv->cfg->ops->utils->post_scan(priv);
@@ -604,15 +532,12 @@ void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
{
INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
- INIT_WORK(&priv->start_internal_scan,
- iwl_legacy_bg_start_internal_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
}
EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
{
- cancel_work_sync(&priv->start_internal_scan);
cancel_work_sync(&priv->abort_scan);
cancel_work_sync(&priv->scan_completed);
diff --git a/drivers/net/wireless/iwlegacy/iwl-sta.c b/drivers/net/wireless/iwlegacy/iwl-sta.c
index 66f0fb2..f10df3e 100644
--- a/drivers/net/wireless/iwlegacy/iwl-sta.c
+++ b/drivers/net/wireless/iwlegacy/iwl-sta.c
@@ -31,6 +31,7 @@
#include <linux/etherdevice.h>
#include <linux/sched.h>
#include <linux/lockdep.h>
+#include <linux/export.h>
#include "iwl-dev.h"
#include "iwl-core.h"
diff --git a/drivers/net/wireless/iwlegacy/iwl-tx.c b/drivers/net/wireless/iwlegacy/iwl-tx.c
index ef9e268..c0dfb1a 100644
--- a/drivers/net/wireless/iwlegacy/iwl-tx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-tx.c
@@ -30,6 +30,7 @@
#include <linux/etherdevice.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <net/mac80211.h>
#include "iwl-eeprom.h"
#include "iwl-dev.h"
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 101a2c2..b3d9f3f 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -40,7 +40,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
@@ -1409,212 +1408,6 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
}
}
-#define EVENT_START_OFFSET (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (num_events == 0)
- return pos;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- iwl_grab_nic_access(priv);
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- /* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "0x%08x:%04u\n",
- time, ev);
- } else {
- IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
- time, ev);
- }
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
- time, data, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, time,
- data, ev);
- }
- }
- }
-
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
- u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- /*
- * display the newest DEFAULT_LOG_ENTRIES entries
- * i.e the entries just before the next ont that uCode would fill.
- */
- if (num_wraps) {
- if (next_entry < size) {
- pos = iwl3945_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
- } else {
- if (next_entry < size)
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
- }
- return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
- int pos = 0;
- size_t bufsz = 0;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl3945_hw_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_legacy_read_targ_mem(priv, base);
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- if (capacity > priv->cfg->base_params->max_event_log_size) {
- IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
- capacity, priv->cfg->base_params->max_event_log_size);
- capacity = priv->cfg->base_params->max_event_log_size;
- }
-
- if (next_entry > priv->cfg->base_params->max_event_log_size) {
- IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
- next_entry, priv->cfg->base_params->max_event_log_size);
- next_entry = priv->cfg->base_params->max_event_log_size;
- }
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
- }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
- size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
- size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
- size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
- /* if uCode has wrapped back to top of log,
- * start at the oldest entry,
- * i.e the next one that uCode would fill.
- */
- if (num_wraps)
- pos = iwl3945_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
-
- /* (then/else) start at top of log */
- pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
{
u32 inta, handled = 0;
@@ -1762,49 +1555,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
#endif
}
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl3945_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u8 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
-
- channel = iwl_legacy_get_single_channel_number(priv, band);
-
- if (channel) {
- scan_ch->channel = channel;
- scan_ch->type = 0; /* passive */
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set txpower levels to defaults */
- scan_ch->tpc.dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
@@ -2816,6 +2566,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
enum ieee80211_band band;
bool is_active = false;
int ret;
+ u16 len;
lockdep_assert_held(&priv->mutex);
@@ -2834,17 +2585,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
- u16 interval = 0;
+ u16 interval;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- if (priv->is_internal_short_scan)
- interval = 0;
- else
- interval = vif->bss_conf.beacon_int;
+ interval = vif->bss_conf.beacon_int;
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -2866,9 +2614,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -2918,36 +2664,17 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
IWL_GOOD_CRC_TH_NEVER;
- if (!priv->is_internal_short_scan) {
- scan->tx_cmd.len = cpu_to_le16(
- iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- vif->addr,
- priv->scan_request->ie,
- priv->scan_request->ie_len,
- IWL_MAX_SCAN_SIZE - sizeof(*scan)));
- } else {
- /* use bcast addr, will not be transmitted but must be valid */
- scan->tx_cmd.len = cpu_to_le16(
- iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwlegacy_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan)));
- }
+ len = iwl_legacy_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+ vif->addr, priv->scan_request->ie,
+ priv->scan_request->ie_len,
+ IWL_MAX_SCAN_SIZE - sizeof(*scan));
+ scan->tx_cmd.len = cpu_to_le16(len);
+
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl3945_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
- }
-
+ scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+ (void *)&scan->data[len], vif);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
return -EIO;
@@ -3823,10 +3550,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
/* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+ priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index 0c37c02..6e25c7b 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -40,7 +40,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
@@ -488,134 +487,6 @@ static void iwl4965_bg_statistics_periodic(unsigned long data)
iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
}
-
-static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
- u32 start_idx, u32 num_events,
- u32 mode)
-{
- u32 i;
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (mode == 0)
- ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
- else
- ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- if (iwl_grab_nic_access(priv)) {
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return;
- }
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /*
- * "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing.
- */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
- 0, time, ev);
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
- time, data, ev);
- }
- }
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
-{
- u32 capacity; /* event log capacity in # entries */
- u32 base; /* SRAM byte address of event log header */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- capacity = iwl_legacy_read_targ_mem(priv, base);
- num_wraps = iwl_legacy_read_targ_mem(priv,
- base + (2 * sizeof(u32)));
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv,
- base + (3 * sizeof(u32)));
- } else
- return;
-
- if (num_wraps == priv->event_log.num_wraps) {
- iwl4965_print_cont_event_trace(priv,
- base, priv->event_log.next_entry,
- next_entry - priv->event_log.next_entry,
- mode);
- priv->event_log.non_wraps_count++;
- } else {
- if ((num_wraps - priv->event_log.num_wraps) > 1)
- priv->event_log.wraps_more_count++;
- else
- priv->event_log.wraps_once_count++;
- trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
- num_wraps - priv->event_log.num_wraps,
- next_entry, priv->event_log.next_entry);
- if (next_entry < priv->event_log.next_entry) {
- iwl4965_print_cont_event_trace(priv, base,
- priv->event_log.next_entry,
- capacity - priv->event_log.next_entry,
- mode);
-
- iwl4965_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- } else {
- iwl4965_print_cont_event_trace(priv, base,
- next_entry, capacity - next_entry,
- mode);
-
- iwl4965_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- }
- }
- priv->event_log.num_wraps = num_wraps;
- priv->event_log.next_entry = next_entry;
-}
-
-/**
- * iwl4965_bg_ucode_trace - Timer callback to log ucode event
- *
- * The timer is continually set to execute every
- * UCODE_TRACE_PERIOD milliseconds after the last timer expired
- * this function is to perform continuous uCode event logging operation
- * if enabled
- */
-static void iwl4965_bg_ucode_trace(unsigned long data)
-{
- struct iwl_priv *priv = (struct iwl_priv *)data;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (priv->event_log.ucode_trace) {
- iwl4965_continuous_event_trace(priv);
- /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- }
-}
-
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -997,13 +868,13 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
* is killed. Hence update the killswitch state here. The
* rfkill handler will care about restarting if needed.
*/
- if (!test_bit(STATUS_ALIVE, &priv->status)) {
- if (hw_rf_kill)
- set_bit(STATUS_RF_KILL_HW, &priv->status);
- else
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
+ if (hw_rf_kill) {
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
+ } else {
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ iwl_legacy_force_reset(priv, true);
}
+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
handled |= CSR_INT_BIT_RF_KILL;
}
@@ -1612,7 +1483,7 @@ static const char * const desc_lookup_text[] = {
"NMI_INTERRUPT_DATA_ACTION_PT",
"NMI_TRM_HW_ER",
"NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
+ "NMI_INTERRUPT_BREAK_POINT",
"DEBUG_0",
"DEBUG_1",
"DEBUG_2",
@@ -1711,209 +1582,6 @@ void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
pc, blink1, blink2, ilink1, ilink2, hcmd);
}
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (num_events == 0)
- return pos;
-
- if (priv->ucode_type == UCODE_INIT) {
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- } else {
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- }
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- iwl_grab_nic_access(priv);
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- /* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- } else {
- trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
- time, ev);
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- }
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, time,
- data, ev);
- }
- }
- }
-
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
-}
-
-/**
- * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
- u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- /*
- * display the newest DEFAULT_LOG_ENTRIES entries
- * i.e the entries just before the next ont that uCode would fill.
- */
- if (num_wraps) {
- if (next_entry < size) {
- pos = iwl4965_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl4965_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl4965_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- } else {
- if (next_entry < size) {
- pos = iwl4965_print_event_log(priv, 0, next_entry,
- mode, pos, buf, bufsz);
- } else {
- pos = iwl4965_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- }
- }
- return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
- int pos = 0;
- size_t bufsz = 0;
-
- if (priv->ucode_type == UCODE_INIT) {
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- } else {
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- }
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv,
- "Invalid event log pointer 0x%08X for %s uCode\n",
- base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_legacy_read_targ_mem(priv, base);
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
- }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
- size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#else
- size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
- IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
- size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
- /*
- * if uCode has wrapped back to top of log,
- * start at the oldest entry,
- * i.e the next one that uCode would fill.
- */
- if (num_wraps)
- pos = iwl4965_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
- /* (then/else) start at top of log */
- pos = iwl4965_print_event_log(priv, 0,
- next_entry, mode, pos, buf, bufsz);
- } else
- pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
@@ -2096,6 +1764,9 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
priv->active_rate = IWL_RATES_MASK;
+ iwl_legacy_power_update_mode(priv, true);
+ IWL_DEBUG_INFO(priv, "Updated power mode\n");
+
if (iwl_legacy_is_associated_ctx(ctx)) {
struct iwl_legacy_rxon_cmd *active_rxon =
(struct iwl_legacy_rxon_cmd *)&ctx->active;
@@ -2128,9 +1799,6 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
wake_up(&priv->wait_command_queue);
- iwl_legacy_power_update_mode(priv, true);
- IWL_DEBUG_INFO(priv, "Updated power mode\n");
-
return;
restart:
@@ -2773,20 +2441,10 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
- if (ret == 0) {
- priv->_4965.agg_tids_count++;
- IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
- priv->_4965.agg_tids_count);
- }
break;
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
- if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
- priv->_4965.agg_tids_count--;
- IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
- priv->_4965.agg_tids_count);
- }
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
ret = 0;
break;
@@ -2851,7 +2509,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u16 ch;
- unsigned long flags = 0;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2868,64 +2525,64 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
if (!iwl_legacy_is_associated_ctx(ctx))
goto out;
- if (priv->cfg->ops->lib->set_channel_switch) {
+ if (!priv->cfg->ops->lib->set_channel_switch)
+ goto out;
- ch = channel->hw_value;
- if (le16_to_cpu(ctx->active.channel) != ch) {
- ch_info = iwl_legacy_get_channel_info(priv,
- channel->band,
- ch);
- if (!iwl_legacy_is_channel_valid(ch_info)) {
- IWL_DEBUG_MAC80211(priv, "invalid channel\n");
- goto out;
- }
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->current_ht_config.smps = conf->smps_mode;
-
- /* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
- } else
- ctx->ht.is_40mhz = false;
-
- if ((le16_to_cpu(ctx->staging.channel) != ch))
- ctx->staging.flags = 0;
-
- iwl_legacy_set_rxon_channel(priv, channel, ctx);
- iwl_legacy_set_rxon_ht(priv, ht_conf);
- iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
- ctx->vif);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- iwl_legacy_set_rate(priv);
- /*
- * at this point, staging_rxon has the
- * configuration for channel switch
- */
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
- priv->switch_channel = cpu_to_le16(ch);
- if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
- &priv->status);
- priv->switch_channel = 0;
- ieee80211_chswitch_done(ctx->vif, false);
- }
+ ch = channel->hw_value;
+ if (le16_to_cpu(ctx->active.channel) == ch)
+ goto out;
+
+ ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+ if (!iwl_legacy_is_channel_valid(ch_info)) {
+ IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+ goto out;
+ }
+
+ spin_lock_irq(&priv->lock);
+
+ priv->current_ht_config.smps = conf->smps_mode;
+
+ /* Configure HT40 channels */
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
}
+ } else
+ ctx->ht.is_40mhz = false;
+
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
+
+ iwl_legacy_set_rxon_channel(priv, channel, ctx);
+ iwl_legacy_set_rxon_ht(priv, ht_conf);
+ iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+ spin_unlock_irq(&priv->lock);
+
+ iwl_legacy_set_rate(priv);
+ /*
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = cpu_to_le16(ch);
+ if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+ clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = 0;
+ ieee80211_chswitch_done(ctx->vif, false);
}
+
out:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3034,10 +2691,6 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
- init_timer(&priv->ucode_trace);
- priv->ucode_trace.data = (unsigned long)priv;
- priv->ucode_trace.function = iwl4965_bg_ucode_trace;
-
init_timer(&priv->watchdog);
priv->watchdog.data = (unsigned long)priv;
priv->watchdog.function = iwl_legacy_bg_watchdog;
@@ -3056,7 +2709,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
iwl_legacy_cancel_scan_deferred_work(priv);
del_timer_sync(&priv->statistics_periodic);
- del_timer_sync(&priv->ucode_trace);
}
static void iwl4965_init_hw_rates(struct iwl_priv *priv,
@@ -3132,13 +2784,9 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
- priv->_4965.agg_tids_count = 0;
/* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+ priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index ed57e44..c42be81 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -187,13 +187,17 @@ static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
struct key_params*))
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
- struct iwm_key *key = &iwm->keys[key_index];
+ struct iwm_key *key;
struct key_params params;
IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
+ if (key_index >= IWM_NUM_KEYS)
+ return -ENOENT;
+
memset(&params, 0, sizeof(params));
+ key = &iwm->keys[key_index];
params.cipher = key->cipher;
params.key_len = key->key_len;
params.seq_len = key->seq_len;
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
index 50dee6a..bd75078 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ b/drivers/net/wireless/iwmc3200wifi/commands.c
@@ -42,6 +42,7 @@
#include <linux/ieee80211.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/moduleparam.h>
#include "iwm.h"
#include "bus.h"
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 0a0cc96..87eef57 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/debugfs.h>
+#include <linux/export.h>
#include "iwm.h"
#include "bus.h"
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index 4906709..6f1afe6 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -187,7 +187,7 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
if (ret < 0)
goto err_release_fw;
opcode_idx++;
- };
+ }
/* Read firmware version */
fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
index 3620027..98a179f 100644
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -42,6 +42,7 @@
#include <linux/ieee80211.h>
#include <linux/wireless.h>
#include <linux/slab.h>
+#include <linux/moduleparam.h>
#include "iwm.h"
#include "debug.h"
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index 56383e7..764b40d 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -63,6 +63,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/debugfs.h>
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index 1453eec..91f2ca9 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -238,28 +238,3 @@ hostsleep
echo "1" > hostsleep : enable host sleep.
echo "0" > hostsleep : disable host sleep
-========================
-IWCONFIG COMMANDS
-========================
-power period
-
- This command is used to configure the station in deep sleep mode /
- auto deep sleep mode.
-
- The timer is implemented to monitor the activities (command, event,
- etc.). When an activity is detected station will exit from deep
- sleep mode automatically and restart the timer. At timer expiry
- (no activity for defined time period) the deep sleep mode is entered
- automatically.
-
- Note: this command is for SDIO interface only.
-
- Usage:
- To enable deep sleep mode do:
- iwconfig wlan0 power period 0
- To enable auto deep sleep mode with idle time period 5 seconds do:
- iwconfig wlan0 power period 5
- To disable deep sleep/auto deep sleep mode do:
- iwconfig wlan0 power period -1
-
-==============================================================================
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 5d637af..db64ef1 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/slab.h>
@@ -18,6 +19,7 @@
#include "decl.h"
#include "cfg.h"
#include "cmd.h"
+#include "mesh.h"
#define CHAN2G(_channel, _freq, _flags) { \
@@ -441,13 +443,16 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;
- lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
- channel->center_freq, channel_type);
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d",
+ netdev_name(netdev), channel->center_freq, channel_type);
if (channel_type != NL80211_CHAN_NO_HT)
goto out;
- ret = lbs_set_channel(priv, channel->hw_value);
+ if (netdev == priv->mesh_dev)
+ ret = lbs_mesh_set_channel(priv, channel->hw_value);
+ else
+ ret = lbs_set_channel(priv, channel->hw_value);
out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -629,7 +634,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
if (channel &&
!(channel->flags & IEEE80211_CHAN_DISABLED))
cfg80211_inform_bss(wiphy, channel,
- bssid, le64_to_cpu(*(__le64 *)tsfdesc),
+ bssid, get_unaligned_le64(tsfdesc),
capa, intvl, ie, ielen,
LBS_SCAN_RSSI_TO_MBM(rssi),
GFP_KERNEL);
@@ -690,7 +695,7 @@ static void lbs_scan_worker(struct work_struct *work)
tlv = scan_cmd->tlvbuffer;
/* add SSID TLV */
- if (priv->scan_req->n_ssids)
+ if (priv->scan_req->n_ssids && priv->scan_req->ssids[0].ssid_len > 0)
tlv += lbs_add_ssid_tlv(tlv,
priv->scan_req->ssids[0].ssid,
priv->scan_req->ssids[0].ssid_len);
@@ -707,7 +712,7 @@ static void lbs_scan_worker(struct work_struct *work)
if (priv->scan_channel < priv->scan_req->n_channels) {
cancel_delayed_work(&priv->scan_work);
- if (!priv->stopping)
+ if (netif_running(priv->dev))
queue_delayed_work(priv->work_thread, &priv->scan_work,
msecs_to_jiffies(300));
}
@@ -725,13 +730,8 @@ static void lbs_scan_worker(struct work_struct *work)
if (priv->scan_channel >= priv->scan_req->n_channels) {
/* Mark scan done */
- if (priv->internal_scan)
- kfree(priv->scan_req);
- else
- cfg80211_scan_done(priv->scan_req, false);
-
- priv->scan_req = NULL;
- priv->last_scan = jiffies;
+ cancel_delayed_work(&priv->scan_work);
+ lbs_scan_done(priv);
}
/* Restart network */
@@ -761,15 +761,30 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal,
request->n_ssids, request->n_channels, request->ie_len);
priv->scan_channel = 0;
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(50));
-
priv->scan_req = request;
priv->internal_scan = internal;
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(50));
+
lbs_deb_leave(LBS_DEB_CFG80211);
}
+/*
+ * Clean up priv->scan_req. Should be used to handle the allocation details.
+ */
+void lbs_scan_done(struct lbs_private *priv)
+{
+ WARN_ON(!priv->scan_req);
+
+ if (priv->internal_scan)
+ kfree(priv->scan_req);
+ else
+ cfg80211_scan_done(priv->scan_req, false);
+
+ priv->scan_req = NULL;
+}
+
static int lbs_cfg_scan(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_scan_request *request)
@@ -1291,27 +1306,32 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
int ret = 0;
u8 preamble = RADIO_PREAMBLE_SHORT;
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
if (!sme->bssid) {
- /* Run a scan if one isn't in-progress already and if the last
- * scan was done more than 2 seconds ago.
- */
- if (priv->scan_req == NULL &&
- time_after(jiffies, priv->last_scan + (2 * HZ))) {
- struct cfg80211_scan_request *creq;
+ struct cfg80211_scan_request *creq;
- creq = _new_connect_scan_req(wiphy, sme);
- if (!creq) {
- ret = -EINVAL;
- goto done;
- }
+ /*
+ * Scan for the requested network after waiting for existing
+ * scans to finish.
+ */
+ lbs_deb_assoc("assoc: waiting for existing scans\n");
+ wait_event_interruptible_timeout(priv->scan_q,
+ (priv->scan_req == NULL),
+ (15 * HZ));
- lbs_deb_assoc("assoc: scanning for compatible AP\n");
- _internal_start_scan(priv, true, creq);
+ creq = _new_connect_scan_req(wiphy, sme);
+ if (!creq) {
+ ret = -EINVAL;
+ goto done;
}
- /* Wait for any in-progress scan to complete */
+ lbs_deb_assoc("assoc: scanning for compatible AP\n");
+ _internal_start_scan(priv, true, creq);
+
lbs_deb_assoc("assoc: waiting for scan to complete\n");
wait_event_interruptible_timeout(priv->scan_q,
(priv->scan_req == NULL),
@@ -1401,28 +1421,23 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
-static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
- u16 reason_code)
+int lbs_disconnect(struct lbs_private *priv, u16 reason)
{
- struct lbs_private *priv = wiphy_priv(wiphy);
struct cmd_ds_802_11_deauthenticate cmd;
-
- lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
-
- /* store for lbs_cfg_ret_disconnect() */
- priv->disassoc_reason = reason_code;
+ int ret;
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
/* Mildly ugly to use a locally store my own BSSID ... */
memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
- cmd.reasoncode = cpu_to_le16(reason_code);
+ cmd.reasoncode = cpu_to_le16(reason);
- if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd))
- return -EFAULT;
+ ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
+ if (ret)
+ return ret;
cfg80211_disconnected(priv->dev,
- priv->disassoc_reason,
+ reason,
NULL, 0,
GFP_KERNEL);
priv->connect_status = LBS_DISCONNECTED;
@@ -1430,6 +1445,21 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
+static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
+
+ /* store for lbs_cfg_ret_disconnect() */
+ priv->disassoc_reason = reason_code;
+
+ return lbs_disconnect(priv, reason_code);
+}
static int lbs_cfg_set_default_key(struct wiphy *wiphy,
struct net_device *netdev,
@@ -1438,6 +1468,9 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
{
struct lbs_private *priv = wiphy_priv(wiphy);
+ if (netdev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
if (key_index != priv->wep_tx_key) {
@@ -1459,6 +1492,9 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
u16 key_type;
int ret = 0;
+ if (netdev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
@@ -1602,6 +1638,9 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
s8 signal, noise;
int ret;
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
if (idx != 0)
ret = -ENOENT;
@@ -1635,28 +1674,23 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = 0;
- lbs_deb_enter(LBS_DEB_CFG80211);
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
switch (type) {
case NL80211_IFTYPE_MONITOR:
- ret = lbs_set_monitor_mode(priv, 1);
- break;
case NL80211_IFTYPE_STATION:
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- ret = lbs_set_monitor_mode(priv, 0);
- if (!ret)
- ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
- break;
case NL80211_IFTYPE_ADHOC:
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- ret = lbs_set_monitor_mode(priv, 0);
- if (!ret)
- ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
break;
default:
- ret = -ENOTSUPP;
+ return -EOPNOTSUPP;
}
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ if (priv->iface_running)
+ ret = lbs_set_iface_type(priv, type);
+
if (!ret)
priv->wdev->iftype = type;
@@ -1958,6 +1992,9 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_bss *bss;
DECLARE_SSID_BUF(ssid_buf);
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
if (!params->channel) {
@@ -1994,6 +2031,9 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
struct cmd_ds_802_11_ad_hoc_stop cmd;
int ret = 0;
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
memset(&cmd, 0, sizeof(cmd));
@@ -2116,6 +2156,8 @@ int lbs_cfg_register(struct lbs_private *priv)
BIT(NL80211_IFTYPE_ADHOC);
if (lbs_rtap_supported(priv))
wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+ if (lbs_mesh_activated(priv))
+ wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index 4f46bb7..558168c 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -16,6 +16,8 @@ int lbs_reg_notifier(struct wiphy *wiphy,
void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
+void lbs_scan_done(struct lbs_private *priv);
void lbs_scan_deinit(struct lbs_private *priv);
+int lbs_disconnect(struct lbs_private *priv, u16 reason);
#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 71c8f3f..d798bcc 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,10 +3,12 @@
* It prepares command and sends it to firmware when it is ready.
*/
+#include <linux/hardirq.h>
#include <linux/kfifo.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/if_arp.h>
+#include <linux/export.h>
#include "decl.h"
#include "cfg.h"
@@ -873,6 +875,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_GET);
+ cmd.offset = cpu_to_le16(offset);
if (reg != CMD_MAC_REG_ACCESS &&
reg != CMD_BBP_REG_ACCESS &&
@@ -882,7 +885,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
}
ret = lbs_cmd_with_response(priv, reg, &cmd);
- if (ret) {
+ if (!ret) {
if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
*value = cmd.value.bbp_rf;
else if (reg == CMD_MAC_REG_ACCESS)
@@ -915,6 +918,7 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.offset = cpu_to_le16(offset);
if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
cmd.value.bbp_rf = (u8) (value & 0xFF);
@@ -1067,16 +1071,34 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
spin_unlock_irqrestore(&priv->driver_lock, flags);
}
-void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
- int result)
+void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result)
{
+ /*
+ * Normally, commands are removed from cmdpendingq before being
+ * submitted. However, we can arrive here on alternative codepaths
+ * where the command is still pending. Make sure the command really
+ * isn't part of a list at this point.
+ */
+ list_del_init(&cmd->list);
+
cmd->result = result;
cmd->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmd->cmdwait_q);
+ wake_up(&cmd->cmdwait_q);
if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
__lbs_cleanup_and_insert_cmd(priv, cmd);
priv->cur_cmd = NULL;
+ wake_up(&priv->waitq);
+}
+
+void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ __lbs_complete_command(priv, cmd, result);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
}
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
@@ -1248,7 +1270,7 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
if (!list_empty(&priv->cmdfreeq)) {
tempnode = list_first_entry(&priv->cmdfreeq,
struct cmd_ctrl_node, list);
- list_del(&tempnode->list);
+ list_del_init(&tempnode->list);
} else {
lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
tempnode = NULL;
@@ -1356,10 +1378,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
- spin_lock_irqsave(&priv->driver_lock, flags);
- list_del(&cmdnode->list);
lbs_complete_command(priv, cmdnode, 0);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
goto done;
@@ -1369,10 +1388,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
(priv->psstate == PS_STATE_PRE_SLEEP)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
- spin_lock_irqsave(&priv->driver_lock, flags);
- list_del(&cmdnode->list);
lbs_complete_command(priv, cmdnode, 0);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
priv->needtowakeup = 1;
ret = 0;
@@ -1384,7 +1400,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
- list_del(&cmdnode->list);
+ list_del_init(&cmdnode->list);
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
le16_to_cpu(cmd->command));
@@ -1612,7 +1628,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
/* Wake up main thread to execute next command */
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
cmdnode = ERR_PTR(-ENOBUFS);
goto done;
}
@@ -1632,7 +1648,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
cmdnode->cmdwaitqwoken = 0;
lbs_queue_cmd(priv, cmdnode);
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
done:
lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
@@ -1667,7 +1683,13 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
}
might_sleep();
- wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
+
+ /*
+ * Be careful with signals here. A signal may be received as the system
+ * goes into suspend or resume. We do not want this to interrupt the
+ * command, so we perform an uninterruptible sleep.
+ */
+ wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
spin_lock_irqsave(&priv->driver_lock, flags);
ret = cmdnode->result;
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 7109d6b..b280ef7 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -59,6 +59,8 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv);
int lbs_free_cmd_buffer(struct lbs_private *priv);
int lbs_execute_next_command(struct lbs_private *priv);
+void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result);
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
int result);
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 207fc36..178b222 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -3,6 +3,7 @@
* responses as well as events generated by firmware.
*/
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
@@ -165,7 +166,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
}
- lbs_complete_command(priv, priv->cur_cmd, result);
+ __lbs_complete_command(priv, priv->cur_cmd, result);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
@@ -186,7 +187,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
break;
}
- lbs_complete_command(priv, priv->cur_cmd, result);
+ __lbs_complete_command(priv, priv->cur_cmd, result);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
@@ -204,7 +205,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
if (priv->cur_cmd) {
/* Clean up and Put current command back to cmdfreeq */
- lbs_complete_command(priv, priv->cur_cmd, result);
+ __lbs_complete_command(priv, priv->cur_cmd, result);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 23250f6..35d86fa 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,9 +1,11 @@
#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
+#include <linux/hardirq.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "decl.h"
#include "cmd.h"
@@ -917,7 +919,10 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
char *p2;
struct debug_data *d = f->private_data;
- pdata = kmalloc(cnt, GFP_KERNEL);
+ if (cnt == 0)
+ return 0;
+
+ pdata = kmalloc(cnt + 1, GFP_KERNEL);
if (pdata == NULL)
return 0;
@@ -926,6 +931,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
kfree(pdata);
return 0;
}
+ pdata[cnt] = '\0';
p0 = pdata;
for (i = 0; i < num_of_items; i++) {
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index da0b05b..bc951ab 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -9,6 +9,7 @@
#include <linux/netdevice.h>
#include <linux/firmware.h>
+#include <linux/nl80211.h>
/* Should be terminated by a NULL entry */
struct lbs_fw_table {
@@ -43,10 +44,15 @@ int lbs_start_card(struct lbs_private *priv);
void lbs_stop_card(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);
+int lbs_start_iface(struct lbs_private *priv);
+int lbs_stop_iface(struct lbs_private *priv);
+int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type);
+
int lbs_rtap_supported(struct lbs_private *priv);
int lbs_set_mac_address(struct net_device *dev, void *addr);
void lbs_set_multicast_list(struct net_device *dev);
+void lbs_update_mcast(struct lbs_private *priv);
int lbs_suspend(struct lbs_private *priv);
int lbs_resume(struct lbs_private *priv);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 76d018b..f3fd447 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -6,7 +6,6 @@
#ifndef _LBS_DEV_H_
#define _LBS_DEV_H_
-#include "mesh.h"
#include "defs.h"
#include "host.h"
@@ -22,6 +21,17 @@ struct sleep_params {
uint16_t sp_reserved;
};
+/* Mesh statistics */
+struct lbs_mesh_stats {
+ u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
+ u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
+ u32 fwd_drop_ttl; /* Fwd: TTL zero */
+ u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
+ u32 fwd_drop_noroute; /* Fwd: No route to Destination */
+ u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
+ u32 drop_blind; /* Rx: Dropped by blinding table */
+ u32 tx_failed_cnt; /* Tx: Failed transmissions */
+};
/* Private structure for the MV device */
struct lbs_private {
@@ -36,7 +46,6 @@ struct lbs_private {
/* CFG80211 */
struct wireless_dev *wdev;
bool wiphy_registered;
- bool stopping;
struct cfg80211_scan_request *scan_req;
u8 assoc_bss[ETH_ALEN];
u8 disassoc_reason;
@@ -44,9 +53,7 @@ struct lbs_private {
/* Mesh */
struct net_device *mesh_dev; /* Virtual device */
#ifdef CONFIG_LIBERTAS_MESH
- u32 mesh_connect_status;
struct lbs_mesh_stats mstats;
- int mesh_open;
uint16_t mesh_tlv;
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 mesh_ssid_len;
@@ -88,11 +95,14 @@ struct lbs_private {
/* Hardware access */
void *card;
+ bool iface_running;
u8 fw_ready;
u8 surpriseremoved;
u8 setup_fw_on_resume;
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
void (*reset_card) (struct lbs_private *priv);
+ int (*power_save) (struct lbs_private *priv);
+ int (*power_restore) (struct lbs_private *priv);
int (*enter_deep_sleep) (struct lbs_private *priv);
int (*exit_deep_sleep) (struct lbs_private *priv);
int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
@@ -148,6 +158,7 @@ struct lbs_private {
/* protected by hard_start_xmit serialization */
u8 txretrycount;
struct sk_buff *currenttxskb;
+ struct timer_list tx_lockup_timer;
/* Locks */
struct mutex lock;
@@ -169,9 +180,20 @@ struct lbs_private {
wait_queue_head_t scan_q;
/* Whether the scan was initiated internally and not by cfg80211 */
bool internal_scan;
- unsigned long last_scan;
};
extern struct cmd_confirm_sleep confirm_sleep;
+/* Check if there is an interface active. */
+static inline int lbs_iface_active(struct lbs_private *priv)
+{
+ int r;
+
+ r = netif_running(priv->dev);
+ if (priv->mesh_dev)
+ r |= netif_running(priv->mesh_dev);
+
+ return r;
+}
+
#endif
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 29dbce4..885ddc1 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,9 +1,11 @@
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include "decl.h"
#include "cmd.h"
+#include "mesh.h"
static void lbs_ethtool_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 224e985..9804ebc 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -29,7 +29,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
@@ -39,6 +39,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
#include "host.h"
#include "decl.h"
@@ -47,6 +48,8 @@
#include "cmd.h"
#include "if_sdio.h"
+static void if_sdio_interrupt(struct sdio_func *func);
+
/* The if_sdio_remove() callback function is called when
* user removes this module from kernel space or ejects
* the card from the slot. The driver handles these 2 cases
@@ -757,6 +760,136 @@ out:
return ret;
}
+/********************************************************************/
+/* Power management */
+/********************************************************************/
+
+static int if_sdio_power_on(struct if_sdio_card *card)
+{
+ struct sdio_func *func = card->func;
+ struct lbs_private *priv = card->priv;
+ struct mmc_host *host = func->card->host;
+ int ret;
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ /* For 1-bit transfers to the 8686 model, we need to enable the
+ * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
+ * bit to allow access to non-vendor registers. */
+ if ((card->model == MODEL_8686) &&
+ (host->caps & MMC_CAP_SDIO_IRQ) &&
+ (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
+ u8 reg;
+
+ func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+ reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
+ if (ret)
+ goto disable;
+
+ reg |= SDIO_BUS_ECSI;
+ sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
+ if (ret)
+ goto disable;
+ }
+
+ card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
+ if (ret)
+ goto disable;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
+ if (ret)
+ goto disable;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
+ if (ret)
+ goto disable;
+
+ sdio_release_host(func);
+ ret = if_sdio_prog_firmware(card);
+ sdio_claim_host(func);
+ if (ret)
+ goto disable;
+
+ /*
+ * Get rx_unit if the chip is SD8688 or newer.
+ * SD8385 & SD8686 do not have rx_unit.
+ */
+ if ((card->model != MODEL_8385)
+ && (card->model != MODEL_8686))
+ card->rx_unit = if_sdio_read_rx_unit(card);
+ else
+ card->rx_unit = 0;
+
+ /*
+ * Set up the interrupt handler late.
+ *
+ * If we set it up earlier, the (buggy) hardware generates a spurious
+ * interrupt, even before the interrupt has been enabled, with
+ * CCCR_INTx = 0.
+ *
+ * We register the interrupt handler late so that we can handle any
+ * spurious interrupts, and also to avoid generation of that known
+ * spurious interrupt in the first place.
+ */
+ ret = sdio_claim_irq(func, if_sdio_interrupt);
+ if (ret)
+ goto disable;
+
+ /*
+ * Enable interrupts now that everything is set up
+ */
+ sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
+ if (ret)
+ goto release_irq;
+
+ sdio_release_host(func);
+
+ /*
+ * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
+ */
+ if (card->model == MODEL_8688) {
+ struct cmd_header cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ lbs_deb_sdio("send function INIT command\n");
+ if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
+ lbs_cmd_copyback, (unsigned long) &cmd))
+ netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
+ }
+
+ priv->fw_ready = 1;
+
+ return 0;
+
+release_irq:
+ sdio_release_irq(func);
+disable:
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+ return ret;
+}
+
+static int if_sdio_power_off(struct if_sdio_card *card)
+{
+ struct sdio_func *func = card->func;
+ struct lbs_private *priv = card->priv;
+
+ priv->fw_ready = 0;
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ return 0;
+}
+
+
/*******************************************************************/
/* Libertas callbacks */
/*******************************************************************/
@@ -892,6 +1025,63 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
}
+static struct mmc_host *reset_host;
+
+static void if_sdio_reset_card_worker(struct work_struct *work)
+{
+ /*
+ * The actual reset operation must be run outside of lbs_thread. This
+ * is because mmc_remove_host() will cause the device to be instantly
+ * destroyed, and the libertas driver then needs to end lbs_thread,
+ * leading to a deadlock.
+ *
+ * We run it in a workqueue totally independent from the if_sdio_card
+ * instance for that reason.
+ */
+
+ pr_info("Resetting card...");
+ mmc_remove_host(reset_host);
+ mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker);
+
+static void if_sdio_reset_card(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+
+ if (work_pending(&card_reset_work))
+ return;
+
+ reset_host = card->func->card->host;
+ schedule_work(&card_reset_work);
+}
+
+static int if_sdio_power_save(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+ int ret;
+
+ flush_workqueue(card->workqueue);
+
+ ret = if_sdio_power_off(card);
+
+ /* Let runtime PM know the card is powered off */
+ pm_runtime_put_sync(&card->func->dev);
+
+ return ret;
+}
+
+static int if_sdio_power_restore(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+
+ /* Make sure the card will not be powered off by runtime PM */
+ pm_runtime_get_sync(&card->func->dev);
+
+ return if_sdio_power_on(card);
+}
+
+
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@@ -945,7 +1135,6 @@ static int if_sdio_probe(struct sdio_func *func,
int ret, i;
unsigned int model;
struct if_sdio_packet *packet;
- struct mmc_host *host = func->card->host;
lbs_deb_enter(LBS_DEB_SDIO);
@@ -1002,45 +1191,6 @@ static int if_sdio_probe(struct sdio_func *func,
goto free;
}
- sdio_claim_host(func);
-
- ret = sdio_enable_func(func);
- if (ret)
- goto release;
-
- /* For 1-bit transfers to the 8686 model, we need to enable the
- * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
- * bit to allow access to non-vendor registers. */
- if ((card->model == MODEL_8686) &&
- (host->caps & MMC_CAP_SDIO_IRQ) &&
- (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
- u8 reg;
-
- func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
- if (ret)
- goto release_int;
-
- reg |= SDIO_BUS_ECSI;
- sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
- if (ret)
- goto release_int;
- }
-
- card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
- if (ret)
- goto release_int;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
- if (ret)
- goto release_int;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
- if (ret)
- goto release_int;
-
- sdio_release_host(func);
-
sdio_set_drvdata(func, card);
lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
@@ -1048,14 +1198,11 @@ static int if_sdio_probe(struct sdio_func *func,
func->class, func->vendor, func->device,
model, (unsigned)card->ioport);
- ret = if_sdio_prog_firmware(card);
- if (ret)
- goto reclaim;
priv = lbs_add_card(card, &func->dev);
if (!priv) {
ret = -ENOMEM;
- goto reclaim;
+ goto free;
}
card->priv = priv;
@@ -1065,62 +1212,22 @@ static int if_sdio_probe(struct sdio_func *func,
priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
+ priv->reset_card = if_sdio_reset_card;
+ priv->power_save = if_sdio_power_save;
+ priv->power_restore = if_sdio_power_restore;
- sdio_claim_host(func);
-
- /*
- * Get rx_unit if the chip is SD8688 or newer.
- * SD8385 & SD8686 do not have rx_unit.
- */
- if ((card->model != MODEL_8385)
- && (card->model != MODEL_8686))
- card->rx_unit = if_sdio_read_rx_unit(card);
- else
- card->rx_unit = 0;
-
- /*
- * Set up the interrupt handler late.
- *
- * If we set it up earlier, the (buggy) hardware generates a spurious
- * interrupt, even before the interrupt has been enabled, with
- * CCCR_INTx = 0.
- *
- * We register the interrupt handler late so that we can handle any
- * spurious interrupts, and also to avoid generation of that known
- * spurious interrupt in the first place.
- */
- ret = sdio_claim_irq(func, if_sdio_interrupt);
- if (ret)
- goto disable;
-
- /*
- * Enable interrupts now that everything is set up
- */
- sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
- sdio_release_host(func);
+ ret = if_sdio_power_on(card);
if (ret)
- goto reclaim;
-
- priv->fw_ready = 1;
-
- /*
- * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
- */
- if (card->model == MODEL_8688) {
- struct cmd_header cmd;
-
- memset(&cmd, 0, sizeof(cmd));
-
- lbs_deb_sdio("send function INIT command\n");
- if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
- lbs_cmd_copyback, (unsigned long) &cmd))
- netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
- }
+ goto err_activate_card;
ret = lbs_start_card(priv);
+ if_sdio_power_off(card);
if (ret)
goto err_activate_card;
+ /* Tell PM core that we don't need the card to be powered now */
+ pm_runtime_put_noidle(&func->dev);
+
out:
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
@@ -1129,14 +1236,6 @@ out:
err_activate_card:
flush_workqueue(card->workqueue);
lbs_remove_card(priv);
-reclaim:
- sdio_claim_host(func);
-release_int:
- sdio_release_irq(func);
-disable:
- sdio_disable_func(func);
-release:
- sdio_release_host(func);
free:
destroy_workqueue(card->workqueue);
while (card->packets) {
@@ -1163,6 +1262,9 @@ static void if_sdio_remove(struct sdio_func *func)
card = sdio_get_drvdata(func);
+ /* Undo decrement done above in if_sdio_probe */
+ pm_runtime_get_noresume(&func->dev);
+
if (user_rmmod && (card->model == MODEL_8688)) {
/*
* FUNC_SHUTDOWN is required for SD8688 WLAN/BT
@@ -1187,11 +1289,6 @@ static void if_sdio_remove(struct sdio_func *func)
flush_workqueue(card->workqueue);
destroy_workqueue(card->workqueue);
- sdio_claim_host(func);
- sdio_release_irq(func);
- sdio_disable_func(func);
- sdio_release_host(func);
-
while (card->packets) {
packet = card->packets;
card->packets = card->packets->next;
@@ -1301,6 +1398,8 @@ static void __exit if_sdio_exit_module(void)
/* Set the flag as user is removing this module. */
user_rmmod = 1;
+ cancel_work_sync(&card_reset_work);
+
sdio_unregister_driver(&if_sdio_driver);
lbs_deb_leave(LBS_DEB_SDIO);
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index db39742..728baa4 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -19,7 +19,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/moduleparam.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <linux/list.h>
@@ -529,10 +531,6 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
goto out;
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
- goto out;
-
- lbs_deb_spi("waiting for helper to boot...\n");
-
out:
if (err)
pr_err("failed to load helper firmware (err=%d)\n", err);
@@ -1033,7 +1031,6 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
static int if_spi_init_card(struct if_spi_card *card)
{
struct lbs_private *priv = card->priv;
- struct spi_device *spi = card->spi;
int err, i;
u32 scratch;
const struct firmware *helper = NULL;
@@ -1081,8 +1078,9 @@ static int if_spi_init_card(struct if_spi_card *card)
"attached to SPI bus_num %d, chip_select %d. "
"spi->max_speed_hz=%d\n",
card->card_id, card->card_rev,
- spi->master->bus_num, spi->chip_select,
- spi->max_speed_hz);
+ card->spi->master->bus_num,
+ card->spi->chip_select,
+ card->spi->max_speed_hz);
err = if_spi_prog_helper_firmware(card, helper);
if (err)
goto out;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index b5acc39..db879c3 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -5,7 +5,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/delay.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
@@ -324,7 +324,7 @@ static int if_usb_probe(struct usb_interface *intf,
}
kparam_unblock_sysfs_write(fw_name);
- if (!(priv = lbs_add_card(cardp, &udev->dev)))
+ if (!(priv = lbs_add_card(cardp, &intf->dev)))
goto err_prog_firmware;
cardp->priv = priv;
@@ -956,7 +956,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp,
priv->dnld_sent = DNLD_RES_RECEIVED;
spin_unlock_irqrestore(&priv->driver_lock, flags);
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
return ret;
}
@@ -973,6 +973,23 @@ static const struct {
{ MODEL_8682, "libertas/usb8682.bin" }
};
+#ifdef CONFIG_OLPC
+
+static int try_olpc_fw(struct if_usb_card *cardp)
+{
+ int retval = -ENOENT;
+
+ /* try the OLPC firmware first; fall back to fw_table list */
+ if (machine_is_olpc() && cardp->model == MODEL_8388)
+ retval = request_firmware(&cardp->fw,
+ "libertas/usb8388_olpc.bin", &cardp->udev->dev);
+ return retval;
+}
+
+#else
+static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; }
+#endif /* !CONFIG_OLPC */
+
static int get_fw(struct if_usb_card *cardp, const char *fwname)
{
int i;
@@ -981,6 +998,10 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname)
if (fwname)
return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
+ /* Handle OLPC firmware */
+ if (try_olpc_fw(cardp) == 0)
+ return 0;
+
/* Otherwise search for firmware to use */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (fw_table[i].model != cardp->model)
@@ -1112,6 +1133,15 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
if (priv->psstate != PS_STATE_FULL_POWER)
return -1;
+#ifdef CONFIG_OLPC
+ if (machine_is_olpc()) {
+ if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
+ olpc_ec_wakeup_clear(EC_SCI_SRC_WLAN);
+ else
+ olpc_ec_wakeup_set(EC_SCI_SRC_WLAN);
+ }
+#endif
+
ret = lbs_suspend(priv);
if (ret)
goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 8c40949..957681d 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -6,9 +6,10 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/kthread.h>
@@ -22,6 +23,7 @@
#include "cfg.h"
#include "debugfs.h"
#include "cmd.h"
+#include "mesh.h"
#define DRIVER_RELEASE_VERSION "323.p0"
const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
@@ -97,6 +99,69 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
return 0;
}
+int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type)
+{
+ int ret = 0;
+
+ switch (type) {
+ case NL80211_IFTYPE_MONITOR:
+ ret = lbs_set_monitor_mode(priv, 1);
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
+ ret = lbs_set_monitor_mode(priv, 0);
+ if (!ret)
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
+ ret = lbs_set_monitor_mode(priv, 0);
+ if (!ret)
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
+ break;
+ default:
+ ret = -ENOTSUPP;
+ }
+ return ret;
+}
+
+int lbs_start_iface(struct lbs_private *priv)
+{
+ struct cmd_ds_802_11_mac_address cmd;
+ int ret;
+
+ if (priv->power_restore) {
+ ret = priv->power_restore(priv);
+ if (ret)
+ return ret;
+ }
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ memcpy(cmd.macadd, priv->current_addr, ETH_ALEN);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
+ if (ret) {
+ lbs_deb_net("set MAC address failed\n");
+ goto err;
+ }
+
+ ret = lbs_set_iface_type(priv, priv->wdev->iftype);
+ if (ret) {
+ lbs_deb_net("set iface type failed\n");
+ goto err;
+ }
+
+ lbs_update_channel(priv);
+
+ priv->iface_running = true;
+ return 0;
+
+err:
+ if (priv->power_save)
+ priv->power_save(priv);
+ return ret;
+}
/**
* lbs_dev_open - open the ethX interface
@@ -110,23 +175,65 @@ static int lbs_dev_open(struct net_device *dev)
int ret = 0;
lbs_deb_enter(LBS_DEB_NET);
+ if (!priv->iface_running) {
+ ret = lbs_start_iface(priv);
+ if (ret)
+ goto out;
+ }
spin_lock_irq(&priv->driver_lock);
- priv->stopping = false;
- if (priv->connect_status == LBS_CONNECTED)
- netif_carrier_on(dev);
- else
- netif_carrier_off(dev);
+ netif_carrier_off(dev);
if (!priv->tx_pending_len)
netif_wake_queue(dev);
spin_unlock_irq(&priv->driver_lock);
+
+out:
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
+static bool lbs_command_queue_empty(struct lbs_private *priv)
+{
+ unsigned long flags;
+ bool ret;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ ret = priv->cur_cmd == NULL && list_empty(&priv->cmdpendingq);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ return ret;
+}
+
+int lbs_stop_iface(struct lbs_private *priv)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->iface_running = false;
+ kfree_skb(priv->currenttxskb);
+ priv->currenttxskb = NULL;
+ priv->tx_pending_len = 0;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ cancel_work_sync(&priv->mcast_work);
+ del_timer_sync(&priv->tx_lockup_timer);
+
+ /* Disable command processing, and wait for all commands to complete */
+ lbs_deb_main("waiting for commands to complete\n");
+ wait_event(priv->waitq, lbs_command_queue_empty(priv));
+ lbs_deb_main("all commands completed\n");
+
+ if (priv->power_save)
+ ret = priv->power_save(priv);
+
+ lbs_deb_leave(LBS_DEB_MAIN);
+ return ret;
+}
+
/**
* lbs_eth_stop - close the ethX interface
*
@@ -139,17 +246,22 @@ static int lbs_eth_stop(struct net_device *dev)
lbs_deb_enter(LBS_DEB_NET);
+ if (priv->connect_status == LBS_CONNECTED)
+ lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING);
+
spin_lock_irq(&priv->driver_lock);
- priv->stopping = true;
netif_stop_queue(dev);
spin_unlock_irq(&priv->driver_lock);
- schedule_work(&priv->mcast_work);
+ lbs_update_mcast(priv);
cancel_delayed_work_sync(&priv->scan_work);
- if (priv->scan_req) {
- cfg80211_scan_done(priv->scan_req, false);
- priv->scan_req = NULL;
- }
+ if (priv->scan_req)
+ lbs_scan_done(priv);
+
+ netif_carrier_off(priv->dev);
+
+ if (!lbs_iface_active(priv))
+ lbs_stop_iface(priv);
lbs_deb_leave(LBS_DEB_NET);
return 0;
@@ -162,13 +274,14 @@ void lbs_host_to_card_done(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_THREAD);
spin_lock_irqsave(&priv->driver_lock, flags);
+ del_timer(&priv->tx_lockup_timer);
priv->dnld_sent = DNLD_RES_RECEIVED;
/* Wake main thread if commands are pending */
if (!priv->cur_cmd || priv->tx_pending_len > 0) {
if (!priv->wakeup_dev_required)
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -181,29 +294,24 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
int ret = 0;
struct lbs_private *priv = dev->ml_priv;
struct sockaddr *phwaddr = addr;
- struct cmd_ds_802_11_mac_address cmd;
lbs_deb_enter(LBS_DEB_NET);
+ /*
+ * Can only set MAC address when all interfaces are down, to be written
+ * to the hardware when one of them is brought up.
+ */
+ if (lbs_iface_active(priv))
+ return -EBUSY;
+
/* In case it was called from the mesh device */
dev = priv->dev;
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_SET);
- memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
- if (ret) {
- lbs_deb_net("set MAC address failed\n");
- goto done;
- }
-
memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
-done:
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -257,18 +365,18 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
return i;
}
-static void lbs_set_mcast_worker(struct work_struct *work)
+void lbs_update_mcast(struct lbs_private *priv)
{
- struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
struct cmd_ds_mac_multicast_adr mcast_cmd;
- int dev_flags;
+ int dev_flags = 0;
int nr_addrs;
int old_mac_control = priv->mac_control;
lbs_deb_enter(LBS_DEB_NET);
- dev_flags = priv->dev->flags;
- if (priv->mesh_dev)
+ if (netif_running(priv->dev))
+ dev_flags |= priv->dev->flags;
+ if (priv->mesh_dev && netif_running(priv->mesh_dev))
dev_flags |= priv->mesh_dev->flags;
if (dev_flags & IFF_PROMISC) {
@@ -314,6 +422,12 @@ static void lbs_set_mcast_worker(struct work_struct *work)
lbs_deb_leave(LBS_DEB_NET);
}
+static void lbs_set_mcast_worker(struct work_struct *work)
+{
+ struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
+ lbs_update_mcast(priv);
+}
+
void lbs_set_multicast_list(struct net_device *dev)
{
struct lbs_private *priv = dev->ml_priv;
@@ -503,6 +617,9 @@ static int lbs_thread(void *data)
if (ret) {
lbs_deb_tx("host_to_card failed %d\n", ret);
priv->dnld_sent = DNLD_RES_RECEIVED;
+ } else {
+ mod_timer(&priv->tx_lockup_timer,
+ jiffies + (HZ * 5));
}
priv->tx_pending_len = 0;
if (!priv->currenttxskb) {
@@ -511,7 +628,7 @@ static int lbs_thread(void *data)
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
if (priv->mesh_dev &&
- lbs_mesh_connected(priv))
+ netif_running(priv->mesh_dev))
netif_wake_queue(priv->mesh_dev);
}
}
@@ -519,6 +636,7 @@ static int lbs_thread(void *data)
}
del_timer(&priv->command_timer);
+ del_timer(&priv->tx_lockup_timer);
del_timer(&priv->auto_deepsleep_timer);
lbs_deb_leave(LBS_DEB_THREAD);
@@ -638,13 +756,47 @@ static void lbs_cmd_timeout_handler(unsigned long data)
le16_to_cpu(priv->cur_cmd->cmdbuf->command));
priv->cmd_timed_out = 1;
- wake_up_interruptible(&priv->waitq);
+
+ /*
+ * If the device didn't even acknowledge the command, reset the state
+ * so that we don't block all future commands due to this one timeout.
+ */
+ if (priv->dnld_sent == DNLD_CMD_SENT)
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+
+ wake_up(&priv->waitq);
out:
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_leave(LBS_DEB_CMD);
}
/**
+ * lbs_tx_lockup_handler - handles the timeout of the passing of TX frames
+ * to the hardware. This is known to frequently happen with SD8686 when
+ * waking up after a Wake-on-WLAN-triggered resume.
+ *
+ * @data: &struct lbs_private pointer
+ */
+static void lbs_tx_lockup_handler(unsigned long data)
+{
+ struct lbs_private *priv = (struct lbs_private *)data;
+ unsigned long flags;
+
+ lbs_deb_enter(LBS_DEB_TX);
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ netdev_info(priv->dev, "TX lockup detected\n");
+ if (priv->reset_card)
+ priv->reset_card(priv);
+
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+ wake_up_interruptible(&priv->waitq);
+
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ lbs_deb_leave(LBS_DEB_TX);
+}
+
+/**
* auto_deepsleep_timer_fn - put the device back to deep sleep mode when
* timer expires and no activity (command, event, data etc.) is detected.
* @data: &struct lbs_private pointer
@@ -730,6 +882,8 @@ static int lbs_init_adapter(struct lbs_private *priv)
setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
(unsigned long)priv);
+ setup_timer(&priv->tx_lockup_timer, lbs_tx_lockup_handler,
+ (unsigned long)priv);
setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
(unsigned long)priv);
@@ -767,6 +921,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
lbs_free_cmd_buffer(priv);
kfifo_free(&priv->event_fifo);
del_timer(&priv->command_timer);
+ del_timer(&priv->tx_lockup_timer);
del_timer(&priv->auto_deepsleep_timer);
lbs_deb_leave(LBS_DEB_MAIN);
@@ -777,7 +932,7 @@ static const struct net_device_ops lbs_netdev_ops = {
.ndo_stop = lbs_eth_stop,
.ndo_start_xmit = lbs_hard_start_xmit,
.ndo_set_mac_address = lbs_set_mac_address,
- .ndo_set_multicast_list = lbs_set_multicast_list,
+ .ndo_set_rx_mode = lbs_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -880,10 +1035,6 @@ void lbs_remove_card(struct lbs_private *priv)
lbs_remove_mesh(priv);
lbs_scan_deinit(priv);
- dev = priv->dev;
-
- cancel_work_sync(&priv->mcast_work);
-
/* worker thread destruction blocks on the in-flight command which
* should have been cleared already in lbs_stop_card().
*/
@@ -941,17 +1092,18 @@ int lbs_start_card(struct lbs_private *priv)
if (ret)
goto done;
+ if (!lbs_disablemesh)
+ lbs_init_mesh(priv);
+ else
+ pr_info("%s: mesh disabled\n", dev->name);
+
if (lbs_cfg_register(priv)) {
pr_err("cannot register device\n");
goto done;
}
- lbs_update_channel(priv);
-
- if (!lbs_disablemesh)
- lbs_init_mesh(priv);
- else
- pr_info("%s: mesh disabled\n", dev->name);
+ if (lbs_mesh_activated(priv))
+ lbs_start_mesh(priv);
lbs_debugfs_init_one(priv, dev);
@@ -969,8 +1121,6 @@ EXPORT_SYMBOL_GPL(lbs_start_card);
void lbs_stop_card(struct lbs_private *priv)
{
struct net_device *dev;
- struct cmd_ctrl_node *cmdnode;
- unsigned long flags;
lbs_deb_enter(LBS_DEB_MAIN);
@@ -983,30 +1133,6 @@ void lbs_stop_card(struct lbs_private *priv)
lbs_debugfs_remove_one(priv);
lbs_deinit_mesh(priv);
-
- /* Delete the timeout of the currently processing command */
- del_timer_sync(&priv->command_timer);
- del_timer_sync(&priv->auto_deepsleep_timer);
-
- /* Flush pending command nodes */
- spin_lock_irqsave(&priv->driver_lock, flags);
- lbs_deb_main("clearing pending commands\n");
- list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
- cmdnode->result = -ENOENT;
- cmdnode->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmdnode->cmdwait_q);
- }
-
- /* Flush the command the card is currently processing */
- if (priv->cur_cmd) {
- lbs_deb_main("clearing current command\n");
- priv->cur_cmd->result = -ENOENT;
- priv->cur_cmd->cmdwaitqwoken = 1;
- wake_up_interruptible(&priv->cur_cmd->cmdwait_q);
- }
- lbs_deb_main("done clearing commands\n");
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
unregister_netdev(dev);
out:
@@ -1027,7 +1153,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32));
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_leave(LBS_DEB_THREAD);
@@ -1045,7 +1171,7 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
BUG_ON(resp_idx > 1);
priv->resp_idx = resp_idx;
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
lbs_deb_leave(LBS_DEB_THREAD);
}
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 24cf066..e87c031 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -2,6 +2,7 @@
#include <linux/delay.h>
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
@@ -14,6 +15,134 @@
#include "cmd.h"
+static int lbs_add_mesh(struct lbs_private *priv);
+
+/***************************************************************************
+ * Mesh command handling
+ */
+
+static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+ struct cmd_ds_mesh_access *cmd)
+{
+ int ret;
+
+ lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+ cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
+ cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
+ cmd->hdr.result = 0;
+
+ cmd->action = cpu_to_le16(cmd_action);
+
+ ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
+
+ lbs_deb_leave(LBS_DEB_CMD);
+ return ret;
+}
+
+static int __lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type)
+{
+ int ret;
+ u16 command = CMD_MESH_CONFIG_OLD;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ /*
+ * Command id is 0xac for v10 FW along with mesh interface
+ * id in bits 14-13-12.
+ */
+ if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+ command = CMD_MESH_CONFIG |
+ (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
+
+ cmd->hdr.command = cpu_to_le16(command);
+ cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
+ cmd->hdr.result = 0;
+
+ cmd->type = cpu_to_le16(type);
+ cmd->action = cpu_to_le16(action);
+
+ ret = lbs_cmd_with_response(priv, command, cmd);
+
+ lbs_deb_leave(LBS_DEB_CMD);
+ return ret;
+}
+
+static int lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type)
+{
+ int ret;
+
+ if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
+ return -EOPNOTSUPP;
+
+ ret = __lbs_mesh_config_send(priv, cmd, action, type);
+ return ret;
+}
+
+/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
+ * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
+ * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
+ * lbs_mesh_config_send.
+ */
+static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
+ uint16_t chan)
+{
+ struct cmd_ds_mesh_config cmd;
+ struct mrvl_meshie *ie;
+ DECLARE_SSID_BUF(ssid);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.channel = cpu_to_le16(chan);
+ ie = (struct mrvl_meshie *)cmd.data;
+
+ switch (action) {
+ case CMD_ACT_MESH_CONFIG_START:
+ ie->id = WLAN_EID_GENERIC;
+ ie->val.oui[0] = 0x00;
+ ie->val.oui[1] = 0x50;
+ ie->val.oui[2] = 0x43;
+ ie->val.type = MARVELL_MESH_IE_TYPE;
+ ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
+ ie->val.version = MARVELL_MESH_IE_VERSION;
+ ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
+ ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
+ ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
+ ie->val.mesh_id_len = priv->mesh_ssid_len;
+ memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
+ ie->len = sizeof(struct mrvl_meshie_val) -
+ IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
+ cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
+ break;
+ case CMD_ACT_MESH_CONFIG_STOP:
+ break;
+ default:
+ return -1;
+ }
+ lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
+ action, priv->mesh_tlv, chan,
+ print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+
+ return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
+}
+
+int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
+{
+ return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
+}
+
+static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
+{
+ struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr;
+ if (mesh_wdev->channel)
+ return mesh_wdev->channel->hw_value;
+ else
+ return 1;
+}
+
/***************************************************************************
* Mesh sysfs support
*/
@@ -154,17 +283,11 @@ static ssize_t lbs_mesh_set(struct device *dev,
{
struct lbs_private *priv = to_net_dev(dev)->ml_priv;
int enable;
- int ret, action = CMD_ACT_MESH_CONFIG_STOP;
sscanf(buf, "%x", &enable);
enable = !!enable;
if (enable == !!priv->mesh_dev)
return count;
- if (enable)
- action = CMD_ACT_MESH_CONFIG_START;
- ret = lbs_mesh_config(priv, action, priv->channel);
- if (ret)
- return ret;
if (enable)
lbs_add_mesh(priv);
@@ -199,582 +322,11 @@ static struct attribute *lbs_mesh_sysfs_entries[] = {
NULL,
};
-static struct attribute_group lbs_mesh_attr_group = {
+static const struct attribute_group lbs_mesh_attr_group = {
.attrs = lbs_mesh_sysfs_entries,
};
-
-/***************************************************************************
- * Initializing and starting, stopping mesh
- */
-
-/*
- * Check mesh FW version and appropriately send the mesh start
- * command
- */
-int lbs_init_mesh(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- priv->mesh_connect_status = LBS_DISCONNECTED;
-
- /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
- /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
- /* 5.110.22 have mesh command with 0xa3 command id */
- /* 10.0.0.p0 FW brings in mesh config command with different id */
- /* Check FW version MSB and initialize mesh_fw_ver */
- if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
- /* Enable mesh, if supported, and work out which TLV it uses.
- 0x100 + 291 is an unofficial value used in 5.110.20.pXX
- 0x100 + 37 is the official value used in 5.110.21.pXX
- but we check them in that order because 20.pXX doesn't
- give an error -- it just silently fails. */
-
- /* 5.110.20.pXX firmware will fail the command if the channel
- doesn't match the existing channel. But only if the TLV
- is correct. If the channel is wrong, _BOTH_ versions will
- give an error to 0x100+291, and allow 0x100+37 to succeed.
- It's just that 5.110.20.pXX will not have done anything
- useful */
-
- priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel)) {
- priv->mesh_tlv = TLV_TYPE_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel))
- priv->mesh_tlv = 0;
- }
- } else
- if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
- (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
- /* 10.0.0.pXX new firmwares should succeed with TLV
- * 0x100+37; Do not invoke command with old TLV.
- */
- priv->mesh_tlv = TLV_TYPE_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel))
- priv->mesh_tlv = 0;
- }
-
-
- if (priv->mesh_tlv) {
- sprintf(priv->mesh_ssid, "mesh");
- priv->mesh_ssid_len = 4;
-
- lbs_add_mesh(priv);
-
- if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
- netdev_err(dev, "cannot register lbs_mesh attribute\n");
-
- ret = 1;
- }
-
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-
-int lbs_deinit_mesh(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- if (priv->mesh_tlv) {
- device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
- ret = 1;
- }
-
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-
-/**
- * lbs_mesh_stop - close the mshX interface
- *
- * @dev: A pointer to &net_device structure
- * returns: 0
- */
-static int lbs_mesh_stop(struct net_device *dev)
-{
- struct lbs_private *priv = dev->ml_priv;
-
- lbs_deb_enter(LBS_DEB_MESH);
- spin_lock_irq(&priv->driver_lock);
-
- priv->mesh_open = 0;
- priv->mesh_connect_status = LBS_DISCONNECTED;
-
- netif_stop_queue(dev);
- netif_carrier_off(dev);
-
- spin_unlock_irq(&priv->driver_lock);
-
- schedule_work(&priv->mcast_work);
-
- lbs_deb_leave(LBS_DEB_MESH);
- return 0;
-}
-
-/**
- * lbs_mesh_dev_open - open the mshX interface
- *
- * @dev: A pointer to &net_device structure
- * returns: 0 or -EBUSY if monitor mode active
- */
-static int lbs_mesh_dev_open(struct net_device *dev)
-{
- struct lbs_private *priv = dev->ml_priv;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- spin_lock_irq(&priv->driver_lock);
-
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
- ret = -EBUSY;
- goto out;
- }
-
- priv->mesh_open = 1;
- priv->mesh_connect_status = LBS_CONNECTED;
- netif_carrier_on(dev);
-
- if (!priv->tx_pending_len)
- netif_wake_queue(dev);
- out:
-
- spin_unlock_irq(&priv->driver_lock);
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
- return ret;
-}
-
-static const struct net_device_ops mesh_netdev_ops = {
- .ndo_open = lbs_mesh_dev_open,
- .ndo_stop = lbs_mesh_stop,
- .ndo_start_xmit = lbs_hard_start_xmit,
- .ndo_set_mac_address = lbs_set_mac_address,
- .ndo_set_multicast_list = lbs_set_multicast_list,
-};
-
-/**
- * lbs_add_mesh - add mshX interface
- *
- * @priv: A pointer to the &struct lbs_private structure
- * returns: 0 if successful, -X otherwise
- */
-int lbs_add_mesh(struct lbs_private *priv)
-{
- struct net_device *mesh_dev = NULL;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- /* Allocate a virtual mesh device */
- mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
- if (!mesh_dev) {
- lbs_deb_mesh("init mshX device failed\n");
- ret = -ENOMEM;
- goto done;
- }
- mesh_dev->ml_priv = priv;
- priv->mesh_dev = mesh_dev;
-
- mesh_dev->netdev_ops = &mesh_netdev_ops;
- mesh_dev->ethtool_ops = &lbs_ethtool_ops;
- memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
-
- SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
- mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- /* Register virtual mesh interface */
- ret = register_netdev(mesh_dev);
- if (ret) {
- pr_err("cannot register mshX virtual interface\n");
- goto err_free;
- }
-
- ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
- if (ret)
- goto err_unregister;
-
- lbs_persist_config_init(mesh_dev);
-
- /* Everything successful */
- ret = 0;
- goto done;
-
-err_unregister:
- unregister_netdev(mesh_dev);
-
-err_free:
- free_netdev(mesh_dev);
-
-done:
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-void lbs_remove_mesh(struct lbs_private *priv)
-{
- struct net_device *mesh_dev;
-
- mesh_dev = priv->mesh_dev;
- if (!mesh_dev)
- return;
-
- lbs_deb_enter(LBS_DEB_MESH);
- netif_stop_queue(mesh_dev);
- netif_carrier_off(mesh_dev);
- sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
- lbs_persist_config_remove(mesh_dev);
- unregister_netdev(mesh_dev);
- priv->mesh_dev = NULL;
- free_netdev(mesh_dev);
- lbs_deb_leave(LBS_DEB_MESH);
-}
-
-
-
-/***************************************************************************
- * Sending and receiving
- */
-struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
- struct net_device *dev, struct rxpd *rxpd)
-{
- if (priv->mesh_dev) {
- if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
- if (rxpd->rx_control & RxPD_MESH_FRAME)
- dev = priv->mesh_dev;
- } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
- if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
- dev = priv->mesh_dev;
- }
- }
- return dev;
-}
-
-
-void lbs_mesh_set_txpd(struct lbs_private *priv,
- struct net_device *dev, struct txpd *txpd)
-{
- if (dev == priv->mesh_dev) {
- if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
- txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
- else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
- txpd->u.bss.bss_num = MESH_IFACE_ID;
- }
-}
-
-
-/***************************************************************************
- * Mesh command handling
- */
-
-/**
- * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries
- *
- * @priv: A pointer to &struct lbs_private structure
- * @add: TRUE to add the entry, FALSE to delete it
- * @addr1: Destination address to blind or unblind
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- BUG_ON(addr1 == NULL);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- memcpy(cmd.addr1, addr1, ETH_ALEN);
- if (add) {
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
- lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
- addr1, ETH_ALEN);
- } else {
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
- lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
- addr1, ETH_ALEN);
- }
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_reset - Reset/clear the mesh blinding table
- *
- * @priv: A pointer to &struct lbs_private structure
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_reset(struct lbs_private *priv)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh
- * blinding table
- *
- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
- * table, but an inverted table allows *only* traffic from nodes listed in
- * the table.
- *
- * @priv: A pointer to &struct lbs_private structure
- * @inverted: On success, TRUE if the blinding table is inverted,
- * FALSE if it is not inverted
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- BUG_ON(inverted == NULL);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
- if (ret == 0)
- *inverted = !!cmd.id;
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh
- * blinding table
- *
- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
- * table, but an inverted table allows *only* traffic from nodes listed in
- * the table.
- *
- * @priv: A pointer to &struct lbs_private structure
- * @inverted: TRUE to invert the blinding table (only traffic from
- * listed nodes allowed), FALSE to return it
- * to normal state (listed nodes ignored)
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
- cmd.id = cpu_to_le32(!!inverted);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table
- *
- * @priv: A pointer to &struct lbs_private structure
- * @id: The ID of the entry to list
- * @addr1: MAC address associated with the table entry
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- BUG_ON(addr1 == NULL);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
- cmd.id = cpu_to_le32(id);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
- if (ret == 0)
- memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_cmd_fwt_access - Access the mesh forwarding table
- *
- * @priv: A pointer to &struct lbs_private structure
- * @cmd_action: The forwarding table action to perform
- * @cmd: The pre-filled FWT_ACCESS command
- *
- * returns: 0 on success and 'cmd' will be filled with the
- * firmware's response
- */
-int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
- struct cmd_ds_fwt_access *cmd)
-{
- int ret;
-
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
- cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
- cmd->hdr.result = 0;
- cmd->action = cpu_to_le16(cmd_action);
-
- ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return 0;
-}
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd)
-{
- int ret;
-
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
- cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
- cmd->hdr.result = 0;
-
- cmd->action = cpu_to_le16(cmd_action);
-
- ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-static int __lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type)
-{
- int ret;
- u16 command = CMD_MESH_CONFIG_OLD;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- /*
- * Command id is 0xac for v10 FW along with mesh interface
- * id in bits 14-13-12.
- */
- if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
- command = CMD_MESH_CONFIG |
- (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
-
- cmd->hdr.command = cpu_to_le16(command);
- cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
- cmd->hdr.result = 0;
-
- cmd->type = cpu_to_le16(type);
- cmd->action = cpu_to_le16(action);
-
- ret = lbs_cmd_with_response(priv, command, cmd);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-int lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type)
-{
- int ret;
-
- if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
- return -EOPNOTSUPP;
-
- ret = __lbs_mesh_config_send(priv, cmd, action, type);
- return ret;
-}
-
-/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
- * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
- * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
- * lbs_mesh_config_send.
- */
-int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
-{
- struct cmd_ds_mesh_config cmd;
- struct mrvl_meshie *ie;
- DECLARE_SSID_BUF(ssid);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.channel = cpu_to_le16(chan);
- ie = (struct mrvl_meshie *)cmd.data;
-
- switch (action) {
- case CMD_ACT_MESH_CONFIG_START:
- ie->id = WLAN_EID_GENERIC;
- ie->val.oui[0] = 0x00;
- ie->val.oui[1] = 0x50;
- ie->val.oui[2] = 0x43;
- ie->val.type = MARVELL_MESH_IE_TYPE;
- ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
- ie->val.version = MARVELL_MESH_IE_VERSION;
- ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
- ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
- ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
- ie->val.mesh_id_len = priv->mesh_ssid_len;
- memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
- ie->len = sizeof(struct mrvl_meshie_val) -
- IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
- cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
- break;
- case CMD_ACT_MESH_CONFIG_STOP:
- break;
- default:
- return -1;
- }
- lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
- action, priv->mesh_tlv, chan,
- print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
-
- return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
-}
-
-
-
/***************************************************************************
* Persistent configuration support
*/
@@ -1231,7 +783,7 @@ static struct attribute *boot_opts_attrs[] = {
NULL
};
-static struct attribute_group boot_opts_group = {
+static const struct attribute_group boot_opts_group = {
.name = "boot_options",
.attrs = boot_opts_attrs,
};
@@ -1244,31 +796,323 @@ static struct attribute *mesh_ie_attrs[] = {
NULL
};
-static struct attribute_group mesh_ie_group = {
+static const struct attribute_group mesh_ie_group = {
.name = "mesh_ie",
.attrs = mesh_ie_attrs,
};
-void lbs_persist_config_init(struct net_device *dev)
+static void lbs_persist_config_init(struct net_device *dev)
{
int ret;
ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
}
-void lbs_persist_config_remove(struct net_device *dev)
+static void lbs_persist_config_remove(struct net_device *dev)
{
sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
}
+/***************************************************************************
+ * Initializing and starting, stopping mesh
+ */
+
+/*
+ * Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+int lbs_init_mesh(struct lbs_private *priv)
+{
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
+ /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
+ /* 5.110.22 have mesh command with 0xa3 command id */
+ /* 10.0.0.p0 FW brings in mesh config command with different id */
+ /* Check FW version MSB and initialize mesh_fw_ver */
+ if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
+ /* Enable mesh, if supported, and work out which TLV it uses.
+ 0x100 + 291 is an unofficial value used in 5.110.20.pXX
+ 0x100 + 37 is the official value used in 5.110.21.pXX
+ but we check them in that order because 20.pXX doesn't
+ give an error -- it just silently fails. */
+
+ /* 5.110.20.pXX firmware will fail the command if the channel
+ doesn't match the existing channel. But only if the TLV
+ is correct. If the channel is wrong, _BOTH_ versions will
+ give an error to 0x100+291, and allow 0x100+37 to succeed.
+ It's just that 5.110.20.pXX will not have done anything
+ useful */
+
+ priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) {
+ priv->mesh_tlv = TLV_TYPE_MESH_ID;
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
+ priv->mesh_tlv = 0;
+ }
+ } else
+ if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+ (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
+ /* 10.0.0.pXX new firmwares should succeed with TLV
+ * 0x100+37; Do not invoke command with old TLV.
+ */
+ priv->mesh_tlv = TLV_TYPE_MESH_ID;
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
+ priv->mesh_tlv = 0;
+ }
+
+ /* Stop meshing until interface is brought up */
+ lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1);
+
+ if (priv->mesh_tlv) {
+ sprintf(priv->mesh_ssid, "mesh");
+ priv->mesh_ssid_len = 4;
+ ret = 1;
+ }
+
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
+}
+
+void lbs_start_mesh(struct lbs_private *priv)
+{
+ lbs_add_mesh(priv);
+
+ if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh))
+ netdev_err(priv->dev, "cannot register lbs_mesh attribute\n");
+}
+
+int lbs_deinit_mesh(struct lbs_private *priv)
+{
+ struct net_device *dev = priv->dev;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ if (priv->mesh_tlv) {
+ device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+ ret = 1;
+ }
+
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
+}
+
+
+/**
+ * lbs_mesh_stop - close the mshX interface
+ *
+ * @dev: A pointer to &net_device structure
+ * returns: 0
+ */
+static int lbs_mesh_stop(struct net_device *dev)
+{
+ struct lbs_private *priv = dev->ml_priv;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+ lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
+ lbs_mesh_get_channel(priv));
+
+ spin_lock_irq(&priv->driver_lock);
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ spin_unlock_irq(&priv->driver_lock);
+
+ lbs_update_mcast(priv);
+ if (!lbs_iface_active(priv))
+ lbs_stop_iface(priv);
+
+ lbs_deb_leave(LBS_DEB_MESH);
+ return 0;
+}
+
+/**
+ * lbs_mesh_dev_open - open the mshX interface
+ *
+ * @dev: A pointer to &net_device structure
+ * returns: 0 or -EBUSY if monitor mode active
+ */
+static int lbs_mesh_dev_open(struct net_device *dev)
+{
+ struct lbs_private *priv = dev->ml_priv;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_NET);
+ if (!priv->iface_running) {
+ ret = lbs_start_iface(priv);
+ if (ret)
+ goto out;
+ }
+
+ spin_lock_irq(&priv->driver_lock);
+
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+ ret = -EBUSY;
+ spin_unlock_irq(&priv->driver_lock);
+ goto out;
+ }
+
+ netif_carrier_on(dev);
+
+ if (!priv->tx_pending_len)
+ netif_wake_queue(dev);
+
+ spin_unlock_irq(&priv->driver_lock);
+
+ ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+ lbs_mesh_get_channel(priv));
+
+out:
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+ return ret;
+}
+
+static const struct net_device_ops mesh_netdev_ops = {
+ .ndo_open = lbs_mesh_dev_open,
+ .ndo_stop = lbs_mesh_stop,
+ .ndo_start_xmit = lbs_hard_start_xmit,
+ .ndo_set_mac_address = lbs_set_mac_address,
+ .ndo_set_rx_mode = lbs_set_multicast_list,
+};
+
+/**
+ * lbs_add_mesh - add mshX interface
+ *
+ * @priv: A pointer to the &struct lbs_private structure
+ * returns: 0 if successful, -X otherwise
+ */
+static int lbs_add_mesh(struct lbs_private *priv)
+{
+ struct net_device *mesh_dev = NULL;
+ struct wireless_dev *mesh_wdev;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ /* Allocate a virtual mesh device */
+ mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+ if (!mesh_wdev) {
+ lbs_deb_mesh("init mshX wireless device failed\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+ if (!mesh_dev) {
+ lbs_deb_mesh("init mshX device failed\n");
+ ret = -ENOMEM;
+ goto err_free_wdev;
+ }
+
+ mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
+ mesh_wdev->wiphy = priv->wdev->wiphy;
+ mesh_wdev->netdev = mesh_dev;
+
+ mesh_dev->ml_priv = priv;
+ mesh_dev->ieee80211_ptr = mesh_wdev;
+ priv->mesh_dev = mesh_dev;
+
+ mesh_dev->netdev_ops = &mesh_netdev_ops;
+ mesh_dev->ethtool_ops = &lbs_ethtool_ops;
+ memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
+
+ SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
+
+ mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+ /* Register virtual mesh interface */
+ ret = register_netdev(mesh_dev);
+ if (ret) {
+ pr_err("cannot register mshX virtual interface\n");
+ goto err_free_netdev;
+ }
+
+ ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+ if (ret)
+ goto err_unregister;
+
+ lbs_persist_config_init(mesh_dev);
+
+ /* Everything successful */
+ ret = 0;
+ goto done;
+
+err_unregister:
+ unregister_netdev(mesh_dev);
+
+err_free_netdev:
+ free_netdev(mesh_dev);
+
+err_free_wdev:
+ kfree(mesh_wdev);
+
+done:
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
+}
+
+void lbs_remove_mesh(struct lbs_private *priv)
+{
+ struct net_device *mesh_dev;
+
+ mesh_dev = priv->mesh_dev;
+ if (!mesh_dev)
+ return;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+ netif_stop_queue(mesh_dev);
+ netif_carrier_off(mesh_dev);
+ sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+ lbs_persist_config_remove(mesh_dev);
+ unregister_netdev(mesh_dev);
+ priv->mesh_dev = NULL;
+ kfree(mesh_dev->ieee80211_ptr);
+ free_netdev(mesh_dev);
+ lbs_deb_leave(LBS_DEB_MESH);
+}
+
+
+/***************************************************************************
+ * Sending and receiving
+ */
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+ struct net_device *dev, struct rxpd *rxpd)
+{
+ if (priv->mesh_dev) {
+ if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
+ if (rxpd->rx_control & RxPD_MESH_FRAME)
+ dev = priv->mesh_dev;
+ } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
+ if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
+ dev = priv->mesh_dev;
+ }
+ }
+ return dev;
+}
+
+
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+ struct net_device *dev, struct txpd *txpd)
+{
+ if (dev == priv->mesh_dev) {
+ if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
+ txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+ else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+ txpd->u.bss.bss_num = MESH_IFACE_ID;
+ }
+}
+
/***************************************************************************
* Ethtool related
*/
-static const char *mesh_stat_strings[] = {
+static const char * const mesh_stat_strings[] = {
"drop_duplicate_bcast",
"drop_ttl_zero",
"drop_no_fwd_route",
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index ee95c73..6603f34 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -9,31 +9,25 @@
#include <net/lib80211.h>
#include "host.h"
+#include "dev.h"
#ifdef CONFIG_LIBERTAS_MESH
-/* Mesh statistics */
-struct lbs_mesh_stats {
- u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
- u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
- u32 fwd_drop_ttl; /* Fwd: TTL zero */
- u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
- u32 fwd_drop_noroute; /* Fwd: No route to Destination */
- u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
- u32 drop_blind; /* Rx: Dropped by blinding table */
- u32 tx_failed_cnt; /* Tx: Failed transmissions */
-};
-
-
struct net_device;
-struct lbs_private;
int lbs_init_mesh(struct lbs_private *priv);
+void lbs_start_mesh(struct lbs_private *priv);
int lbs_deinit_mesh(struct lbs_private *priv);
-int lbs_add_mesh(struct lbs_private *priv);
void lbs_remove_mesh(struct lbs_private *priv);
+static inline bool lbs_mesh_activated(struct lbs_private *priv)
+{
+ /* Mesh SSID is only programmed after successful init */
+ return priv->mesh_ssid_len != 0;
+}
+
+int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel);
/* Sending / Receiving */
@@ -52,29 +46,6 @@ struct cmd_ds_command;
struct cmd_ds_mesh_access;
struct cmd_ds_mesh_config;
-int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
-int lbs_mesh_bt_reset(struct lbs_private *priv);
-int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
-int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
-int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
-
-int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
- struct cmd_ds_fwt_access *cmd);
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd);
-int lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type);
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
-
-
-
-/* Persistent configuration */
-
-void lbs_persist_config_init(struct net_device *net);
-void lbs_persist_config_remove(struct net_device *net);
-
/* Ethtool statistics */
@@ -87,22 +58,17 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *s);
-/* Accessors */
-
-#define lbs_mesh_open(priv) (priv->mesh_open)
-#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED)
-
#else
#define lbs_init_mesh(priv)
#define lbs_deinit_mesh(priv)
+#define lbs_start_mesh(priv)
#define lbs_add_mesh(priv)
#define lbs_remove_mesh(priv)
#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
#define lbs_mesh_set_txpd(priv, dev, txpd)
-#define lbs_mesh_config(priv, enable, chan)
-#define lbs_mesh_open(priv) (0)
-#define lbs_mesh_connected(priv) (0)
+#define lbs_mesh_set_channel(priv, channel) (0)
+#define lbs_mesh_activated(priv) (false)
#endif
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index fdb0448..c7366b0 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -5,8 +5,10 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/export.h>
#include <net/cfg80211.h>
#include "defs.h"
@@ -14,6 +16,7 @@
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
+#include "mesh.h"
struct eth803hdr {
u8 dest_addr[6];
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index bbb95f8..c025f9c 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -1,9 +1,11 @@
/*
* This file contains the handling of TX in wlan driver.
*/
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
+#include <linux/export.h>
#include <net/cfg80211.h>
#include "host.h"
@@ -11,6 +13,7 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
+#include "mesh.h"
/**
* convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
@@ -198,7 +201,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
- if (priv->mesh_dev && lbs_mesh_connected(priv))
+ if (priv->mesh_dev && netif_running(priv->mesh_dev))
netif_wake_queue(priv->mesh_dev);
}
EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
index 8945afd..909ac36 100644
--- a/drivers/net/wireless/libertas_tf/cmd.c
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -9,7 +9,9 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "libertas_tf.h"
diff --git a/drivers/net/wireless/libertas_tf/deb_defs.h b/drivers/net/wireless/libertas_tf/deb_defs.h
index ae75396..4bd3dc5 100644
--- a/drivers/net/wireless/libertas_tf/deb_defs.h
+++ b/drivers/net/wireless/libertas_tf/deb_defs.h
@@ -3,7 +3,7 @@
* global variable declaration.
*/
#ifndef _LBS_DEB_DEFS_H_
-#define _LBS_DEB_EFS_H_
+#define _LBS_DEB_DEFS_H_
#ifndef DRV_NAME
#define DRV_NAME "libertas_tf"
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index ba7d965..68202e6 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -15,7 +15,7 @@
#include "if_usb.h"
#include <linux/delay.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index d400508..ceb51b6 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -9,9 +9,11 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
+#include <linux/module.h>
#include "libertas_tf.h"
#define DRIVER_RELEASE_VERSION "004.p0"
@@ -585,7 +587,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
need_padding ^= ieee80211_has_a4(hdr->frame_control);
need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
(*ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
+ IEEE80211_QOS_CTL_A_MSDU_PRESENT);
if (need_padding) {
memmove(skb->data + 2, skb->data, skb->len);
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 916183d..6543f4f 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -185,13 +185,12 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
*
* Handling includes changing the header fields into CPU format.
*/
-int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
+ struct mwifiex_ds_11n_tx_cfg *tx_cfg)
{
- struct mwifiex_ds_11n_tx_cfg *tx_cfg;
struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
- if (data_buf) {
- tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf;
+ if (tx_cfg) {
tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);
tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);
}
@@ -208,11 +207,10 @@ int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
*/
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd, int cmd_action,
- void *data_buf)
+ u16 *buf_size)
{
struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
u16 action = (u16) cmd_action;
- u16 buf_size = *((u16 *) data_buf);
cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
cmd->size =
@@ -220,8 +218,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
tx_buf->action = cpu_to_le16(action);
switch (action) {
case HostCmd_ACT_GEN_SET:
- dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size);
- tx_buf->buff_size = cpu_to_le16(buf_size);
+ dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+ tx_buf->buff_size = cpu_to_le16(*buf_size);
break;
case HostCmd_ACT_GEN_GET:
default:
@@ -240,13 +238,12 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
* - Ensuring correct endian-ness
*/
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf)
+ int cmd_action,
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
{
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&cmd->params.amsdu_aggr_ctrl;
u16 action = (u16) cmd_action;
- struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
- (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
@@ -272,15 +269,13 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
* Handling includes changing the header fields into CPU format.
*/
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl
+ *amsdu_aggr_ctrl)
{
- struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl;
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&resp->params.amsdu_aggr_ctrl;
- if (data_buf) {
- amsdu_aggr_ctrl =
- (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
+ if (amsdu_aggr_ctrl) {
amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);
amsdu_aggr_ctrl->curr_buf_size =
le16_to_cpu(amsdu_ctrl->curr_buf_size);
@@ -296,12 +291,10 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
* - Setting HT Tx capability and HT Tx information fields
* - Ensuring correct endian-ness
*/
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+ struct mwifiex_ds_11n_tx_cfg *txcfg)
{
struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
- struct mwifiex_ds_11n_tx_cfg *txcfg =
- (struct mwifiex_ds_11n_tx_cfg *) data_buf;
cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
@@ -350,8 +343,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
ht_cap->header.len =
cpu_to_le16(sizeof(struct ieee80211_ht_cap));
memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header),
- (u8 *) bss_desc->bcn_ht_cap +
- sizeof(struct ieee_types_header),
+ (u8 *)bss_desc->bcn_ht_cap,
le16_to_cpu(ht_cap->header.len));
mwifiex_fill_cap_info(priv, radio_type, ht_cap);
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index a4390a1..90b421e 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -29,9 +29,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
- void *data_buf);
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf);
+ struct mwifiex_ds_11n_tx_cfg *tx_cfg);
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+ struct mwifiex_ds_11n_tx_cfg *txcfg);
int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc,
@@ -62,12 +62,14 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
struct mwifiex_ds_tx_ba_stream_tbl *buf);
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
- void *data_buf);
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl
+ *amsdu_aggr_ctrl);
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf);
+ int cmd_action, u16 *buf_size);
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf);
+ int cmd_action,
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
/*
* This function checks whether AMPDU is allowed or not for a particular TID.
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index f807447..079e553 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -164,12 +164,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
struct mwifiex_tx_param tx_param;
struct txpd *ptx_pd = NULL;
- if (skb_queue_empty(&pra_list->skb_head)) {
+ skb_src = skb_peek(&pra_list->skb_head);
+ if (!skb_src) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
return 0;
}
- skb_src = skb_peek(&pra_list->skb_head);
+
tx_info_src = MWIFIEX_SKB_TXCB(skb_src);
skb_aggr = dev_alloc_skb(adapter->tx_buf_size);
if (!skb_aggr) {
@@ -184,17 +185,14 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
tx_info_aggr->bss_index = tx_info_src->bss_index;
skb_aggr->priority = skb_src->priority;
- while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len
- + LLC_SNAP_LEN)
- <= adapter->tx_buf_size)) {
+ do {
+ /* Check if AMSDU can accommodate this MSDU */
+ if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
+ break;
- if (!skb_queue_empty(&pra_list->skb_head))
- skb_src = skb_dequeue(&pra_list->skb_head);
- else
- skb_src = NULL;
+ skb_src = skb_dequeue(&pra_list->skb_head);
- if (skb_src)
- pra_list->total_pkts_size -= skb_src->len;
+ pra_list->total_pkts_size -= skb_src->len;
atomic_dec(&priv->wmm.tx_pkts_queued);
@@ -212,11 +210,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
return -1;
}
- if (!skb_queue_empty(&pra_list->skb_head))
- skb_src = skb_peek(&pra_list->skb_head);
- else
- skb_src = NULL;
- }
+ if (skb_tailroom(skb_aggr) < pad) {
+ pad = 0;
+ break;
+ }
+ skb_put(skb_aggr, pad);
+
+ skb_src = skb_peek(&pra_list->skb_head);
+
+ } while (skb_src);
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
@@ -230,14 +232,21 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_push(skb_aggr, headroom);
- tx_param.next_pkt_len = ((pra_list->total_pkts_size) ?
- (((pra_list->total_pkts_size) >
- adapter->tx_buf_size) ? adapter->
- tx_buf_size : pra_list->total_pkts_size +
- LLC_SNAP_LEN + sizeof(struct txpd)) : 0);
+ /*
+ * Padding per MSDU will affect the length of next
+ * packet and hence the exact length of next packet
+ * is uncertain here.
+ *
+ * Also, aggregation of transmission buffer, while
+ * downloading the data to the card, wont gain much
+ * on the AMSDU packets as the AMSDU packets utilizes
+ * the transmission buffer space to the maximum
+ * (adapter->tx_buf_size).
+ */
+ tx_param.next_pkt_len = 0;
+
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb_aggr->data,
- skb_aggr->len, &tx_param);
+ skb_aggr, &tx_param);
switch (ret) {
case -EBUSY:
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h
index 9c6dca7..900e1c6 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.h
+++ b/drivers/net/wireless/mwifiex/11n_aggr.h
@@ -21,6 +21,7 @@
#define _MWIFIEX_11N_AGGR_H_
#define PKT_TYPE_AMSDU 0xE6
+#define MIN_NUM_AMSDU 2
int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
struct sk_buff *skb);
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index d2358cf..39fd4d5 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -329,13 +329,12 @@ int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
*/
int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ struct host_cmd_ds_11n_addba_req
+ *cmd_addba_req)
{
struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =
(struct host_cmd_ds_11n_addba_rsp *)
&cmd->params.add_ba_rsp;
- struct host_cmd_ds_11n_addba_req *cmd_addba_req =
- (struct host_cmd_ds_11n_addba_req *) data_buf;
u8 tid;
int win_size;
uint16_t block_ack_param_set;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 7576c2a..7128baa 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -59,8 +59,9 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
void *data_buf);
int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
- struct host_cmd_ds_command
- *cmd, void *data_buf);
+ struct host_cmd_ds_command *cmd,
+ struct host_cmd_ds_11n_addba_req
+ *cmd_addba_req);
int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
void *data_buf);
void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 8696292..8f2797a 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -19,3 +19,14 @@ config MWIFIEX_SDIO
If you choose to build it as a module, it will be called
mwifiex_sdio.
+
+config MWIFIEX_PCIE
+ tristate "Marvell WiFi-Ex Driver for PCIE 8766"
+ depends on MWIFIEX && PCI
+ select FW_LOADER
+ ---help---
+ This adds support for wireless adapters based on Marvell
+ 8766 chipset with PCIe interface.
+
+ If you choose to build it as a module, it will be called
+ mwifiex_pcie.
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 42cb733..b0257ad 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -39,3 +39,6 @@ obj-$(CONFIG_MWIFIEX) += mwifiex.o
mwifiex_sdio-y += sdio.o
obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
+
+mwifiex_pcie-y += pcie.o
+obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 687c1f2..45ac407 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -543,12 +543,28 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
ret = -EFAULT;
}
+ /*
+ * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid
+ * MCS index values for us are 0 to 15.
+ */
+ if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
+ sinfo->txrate.mcs = priv->tx_rate;
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ /* 40MHz rate */
+ if (priv->tx_htinfo & BIT(1))
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ /* SGI enabled */
+ if (priv->tx_htinfo & BIT(2))
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ }
+
sinfo->rx_bytes = priv->stats.rx_bytes;
sinfo->tx_bytes = priv->stats.tx_bytes;
sinfo->rx_packets = priv->stats.rx_packets;
sinfo->tx_packets = priv->stats.tx_packets;
- sinfo->signal = priv->w_stats.qual.level;
- sinfo->txrate.legacy = rate.rate;
+ sinfo->signal = priv->qual_level;
+ /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
+ sinfo->txrate.legacy = rate.rate * 5;
return ret;
}
@@ -565,8 +581,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- mwifiex_dump_station_info(priv, sinfo);
-
if (!priv->media_connected)
return -ENOENT;
if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
@@ -672,6 +686,59 @@ static const u32 mwifiex_cipher_suites[] = {
};
/*
+ * CFG802.11 operation handler for setting bit rates.
+ *
+ * Function selects legacy bang B/G/BG from corresponding bitrates selection.
+ * Currently only 2.4GHz band is supported.
+ */
+static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct mwifiex_ds_band_cfg band_cfg;
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ int index = 0, mode = 0, i;
+
+ /* Currently only 2.4GHz is supported */
+ for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
+ /*
+ * Rates below 6 Mbps in the table are CCK rates; 802.11b
+ * and from 6 they are OFDM; 802.11G
+ */
+ if (mwifiex_rates[i].bitrate == 60) {
+ index = 1 << i;
+ break;
+ }
+ }
+
+ if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {
+ mode = BAND_B;
+ } else {
+ mode = BAND_G;
+ if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)
+ mode |= BAND_B;
+ }
+
+ memset(&band_cfg, 0, sizeof(band_cfg));
+ band_cfg.config_bands = mode;
+
+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
+ band_cfg.adhoc_start_band = mode;
+
+ band_cfg.sec_chan_offset = NO_SEC_CHANNEL;
+
+ if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
+ return -EFAULT;
+
+ wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
+ (mode & BAND_B) ? "b" : "",
+ (mode & BAND_G) ? "g" : "");
+
+ return 0;
+}
+
+/*
* CFG802.11 operation handler for disconnection request.
*
* This function does not work when there is already a disconnection
@@ -715,6 +782,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
struct mwifiex_bss_info bss_info;
int ie_len;
u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
+ enum ieee80211_band band;
if (mwifiex_get_bss_info(priv, &bss_info))
return -1;
@@ -727,9 +795,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
bss_info.ssid.ssid_len);
ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
+ band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
chan = __ieee80211_get_channel(priv->wdev->wiphy,
ieee80211_channel_to_frequency(bss_info.bss_chan,
- priv->curr_bss_params.band));
+ band));
cfg80211_inform_bss(priv->wdev->wiphy, chan,
bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
@@ -740,139 +809,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
}
/*
- * This function informs the CFG802.11 subsystem of a new BSS connection.
- *
- * The following information are sent to the CFG802.11 subsystem
- * to register the new BSS connection. If we do not register the new BSS,
- * a kernel panic will result.
- * - MAC address
- * - Capabilities
- * - Beacon period
- * - RSSI value
- * - Channel
- * - Supported rates IE
- * - Extended capabilities IE
- * - DS parameter set IE
- * - HT Capability IE
- * - Vendor Specific IE (221)
- * - WPA IE
- * - RSN IE
- */
-static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *ssid)
-{
- struct mwifiex_bssdescriptor *scan_table;
- int i, j;
- struct ieee80211_channel *chan;
- u8 *ie, *ie_buf;
- u32 ie_len;
- u8 *beacon;
- int beacon_size;
- u8 element_id, element_len;
-
-#define MAX_IE_BUF 2048
- ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL);
- if (!ie_buf) {
- dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n",
- __func__);
- return -ENOMEM;
- }
-
- scan_table = priv->adapter->scan_table;
- for (i = 0; i < priv->adapter->num_in_scan_table; i++) {
- if (ssid) {
- /* Inform specific BSS only */
- if (memcmp(ssid->ssid, scan_table[i].ssid.ssid,
- ssid->ssid_len))
- continue;
- }
- memset(ie_buf, 0, MAX_IE_BUF);
- ie_buf[0] = WLAN_EID_SSID;
- ie_buf[1] = scan_table[i].ssid.ssid_len;
- memcpy(&ie_buf[sizeof(struct ieee_types_header)],
- scan_table[i].ssid.ssid, ie_buf[1]);
-
- ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header);
- ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
-
- ie[0] = WLAN_EID_SUPP_RATES;
-
- for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
- if (!scan_table[i].supported_rates[j])
- break;
- else
- ie[j + sizeof(struct ieee_types_header)] =
- scan_table[i].supported_rates[j];
- }
-
- ie[1] = j;
- ie_len += ie[1] + sizeof(struct ieee_types_header);
-
- beacon = scan_table[i].beacon_buf;
- beacon_size = scan_table[i].beacon_buf_size;
-
- /* Skip time stamp, beacon interval and capability */
-
- if (beacon) {
- beacon += sizeof(scan_table[i].beacon_period)
- + sizeof(scan_table[i].time_stamp) +
- +sizeof(scan_table[i].cap_info_bitmap);
-
- beacon_size -= sizeof(scan_table[i].beacon_period)
- + sizeof(scan_table[i].time_stamp)
- + sizeof(scan_table[i].cap_info_bitmap);
- }
-
- while (beacon_size >= sizeof(struct ieee_types_header)) {
- ie = ie_buf + ie_len;
- element_id = *beacon;
- element_len = *(beacon + 1);
- if (beacon_size < (int) element_len +
- sizeof(struct ieee_types_header)) {
- dev_err(priv->adapter->dev, "%s: in processing"
- " IE, bytes left < IE length\n",
- __func__);
- break;
- }
- switch (element_id) {
- case WLAN_EID_EXT_CAPABILITY:
- case WLAN_EID_DS_PARAMS:
- case WLAN_EID_HT_CAPABILITY:
- case WLAN_EID_VENDOR_SPECIFIC:
- case WLAN_EID_RSN:
- case WLAN_EID_BSS_AC_ACCESS_DELAY:
- ie[0] = element_id;
- ie[1] = element_len;
- memcpy(&ie[sizeof(struct ieee_types_header)],
- (u8 *) beacon
- + sizeof(struct ieee_types_header),
- element_len);
- ie_len += ie[1] +
- sizeof(struct ieee_types_header);
- break;
- default:
- break;
- }
- beacon += element_len +
- sizeof(struct ieee_types_header);
- beacon_size -= element_len +
- sizeof(struct ieee_types_header);
- }
- chan = ieee80211_get_channel(priv->wdev->wiphy,
- scan_table[i].freq);
- cfg80211_inform_bss(priv->wdev->wiphy, chan,
- scan_table[i].mac_address,
- 0, scan_table[i].cap_info_bitmap,
- scan_table[i].beacon_period,
- ie_buf, ie_len,
- scan_table[i].rssi, GFP_KERNEL);
- }
-
- kfree(ie_buf);
- return 0;
-}
-
-/*
* This function connects with a BSS.
*
* This function handles both Infra and Ad-Hoc modes. It also performs
@@ -884,8 +820,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
* For Infra mode, the function returns failure if the specified SSID
* is not found in scan table. However, for Ad-Hoc mode, it can create
* the IBSS if it does not exist. On successful completion in either case,
- * the function notifies the CFG802.11 subsystem of the new BSS connection,
- * otherwise the kernel will panic.
+ * the function notifies the CFG802.11 subsystem of the new BSS connection.
*/
static int
mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
@@ -893,11 +828,11 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
struct cfg80211_connect_params *sme, bool privacy)
{
struct mwifiex_802_11_ssid req_ssid;
- struct mwifiex_ssid_bssid ssid_bssid;
int ret, auth_type = 0;
+ struct cfg80211_bss *bss = NULL;
+ u8 is_scanning_required = 0;
memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
- memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
req_ssid.ssid_len = ssid_len;
if (ssid_len > IEEE80211_MAX_SSID_LEN) {
@@ -960,7 +895,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
if (sme->key) {
- if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) {
+ if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
dev_dbg(priv->adapter->dev,
"info: setting wep encryption"
" with key len %d\n", sme->key_len);
@@ -975,30 +910,48 @@ done:
return -EFAULT;
}
+ /*
+ * Scan entries are valid for some time (15 sec). So we can save one
+ * active scan time if we just try cfg80211_get_bss first. If it fails
+ * then request scan and cfg80211_get_bss() again for final output.
+ */
+ while (1) {
+ if (is_scanning_required) {
+ /* Do specific SSID scanning */
+ if (mwifiex_request_scan(priv, &req_ssid)) {
+ dev_err(priv->adapter->dev, "scan error\n");
+ return -EFAULT;
+ }
+ }
- memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid));
-
- if (mode != NL80211_IFTYPE_ADHOC) {
- if (mwifiex_find_best_bss(priv, &ssid_bssid))
- return -EFAULT;
- /* Inform the BSS information to kernel, otherwise
- * kernel will give a panic after successful assoc */
- if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid))
- return -EFAULT;
+ /* Find the BSS we want using available scan results */
+ if (mode == NL80211_IFTYPE_ADHOC)
+ bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
+ bssid, ssid, ssid_len,
+ WLAN_CAPABILITY_IBSS,
+ WLAN_CAPABILITY_IBSS);
+ else
+ bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
+ bssid, ssid, ssid_len,
+ WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+
+ if (!bss) {
+ if (is_scanning_required) {
+ dev_warn(priv->adapter->dev, "assoc: requested "
+ "bss not found in scan results\n");
+ break;
+ }
+ is_scanning_required = 1;
+ } else {
+ dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
+ (char *) req_ssid.ssid, bss->bssid);
+ memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
+ break;
+ }
}
- dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
- (char *) req_ssid.ssid, ssid_bssid.bssid);
-
- memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6);
-
- /* Connect to BSS by ESSID */
- memset(&ssid_bssid.bssid, 0, ETH_ALEN);
-
- if (!netif_queue_stopped(priv->netdev))
- netif_stop_queue(priv->netdev);
-
- if (mwifiex_bss_start(priv, &ssid_bssid))
+ if (mwifiex_bss_start(priv, bss, &req_ssid))
return -EFAULT;
if (mode == NL80211_IFTYPE_ADHOC) {
@@ -1209,8 +1162,144 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
}
+/*
+ * create a new virtual interface with the given name
+ */
+struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params)
+{
+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
+ struct mwifiex_adapter *adapter;
+ struct net_device *dev;
+ void *mdev_priv;
+
+ if (!priv)
+ return ERR_PTR(-EFAULT);
+
+ adapter = priv->adapter;
+ if (!adapter)
+ return ERR_PTR(-EFAULT);
+
+ switch (type) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ if (priv->bss_mode) {
+ wiphy_err(wiphy, "cannot create multiple"
+ " station/adhoc interfaces\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (type == NL80211_IFTYPE_UNSPECIFIED)
+ priv->bss_mode = NL80211_IFTYPE_STATION;
+ else
+ priv->bss_mode = type;
+
+ priv->bss_type = MWIFIEX_BSS_TYPE_STA;
+ priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
+ priv->bss_priority = 0;
+ priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_index = 0;
+ priv->bss_num = 0;
+
+ break;
+ default:
+ wiphy_err(wiphy, "type not supported\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
+ ether_setup, 1);
+ if (!dev) {
+ wiphy_err(wiphy, "no memory available for netdevice\n");
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+ return ERR_PTR(-ENOMEM);
+ }
+
+ dev_net_set(dev, wiphy_net(wiphy));
+ dev->ieee80211_ptr = priv->wdev;
+ dev->ieee80211_ptr->iftype = priv->bss_mode;
+ memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
+ memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN);
+ SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
+
+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+ dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
+ dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
+
+ mdev_priv = netdev_priv(dev);
+ *((unsigned long *) mdev_priv) = (unsigned long) priv;
+
+ priv->netdev = dev;
+ mwifiex_init_priv_params(priv, dev);
+
+ SET_NETDEV_DEV(dev, adapter->dev);
+
+ /* Register network device */
+ if (register_netdevice(dev)) {
+ wiphy_err(wiphy, "cannot register virtual network device\n");
+ free_netdev(dev);
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+ return ERR_PTR(-EFAULT);
+ }
+
+ sema_init(&priv->async_sem, 1);
+ priv->scan_pending_on_block = false;
+
+ dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
+
+#ifdef CONFIG_DEBUG_FS
+ mwifiex_dev_debugfs_init(priv);
+#endif
+ return dev;
+}
+EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
+
+/*
+ * del_virtual_intf: remove the virtual interface determined by dev
+ */
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
+
+ if (!priv || !dev)
+ return 0;
+
+#ifdef CONFIG_DEBUG_FS
+ mwifiex_dev_debugfs_remove(priv);
+#endif
+
+ if (!netif_queue_stopped(priv->netdev))
+ netif_stop_queue(priv->netdev);
+
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
+
+ if (dev->reg_state == NETREG_REGISTERED)
+ unregister_netdevice(dev);
+
+ /* Clear the priv in adapter */
+ priv->netdev = NULL;
+
+ priv->media_connected = false;
+
+ cancel_work_sync(&priv->cfg_workqueue);
+ flush_workqueue(priv->workqueue);
+ destroy_workqueue(priv->workqueue);
+
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
+
/* station cfg80211 operations */
static struct cfg80211_ops mwifiex_cfg80211_ops = {
+ .add_virtual_intf = mwifiex_add_virtual_intf,
+ .del_virtual_intf = mwifiex_del_virtual_intf,
.change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
.scan = mwifiex_cfg80211_scan,
.connect = mwifiex_cfg80211_connect,
@@ -1225,6 +1314,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.set_default_key = mwifiex_cfg80211_set_default_key,
.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
.set_tx_power = mwifiex_cfg80211_set_tx_power,
+ .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
};
/*
@@ -1234,8 +1324,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
* default parameters and handler function pointers, and finally
* registers the device.
*/
-int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
- struct mwifiex_private *priv)
+int mwifiex_register_cfg80211(struct mwifiex_private *priv)
{
int ret;
void *wdev_priv;
@@ -1275,12 +1364,15 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
wdev->wiphy->cipher_suites = mwifiex_cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
- memcpy(wdev->wiphy->perm_addr, mac, 6);
+ memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
/* We are using custom domains */
wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+ /* Reserve space for bss band information */
+ wdev->wiphy->bss_priv_size = sizeof(u8);
+
wdev->wiphy->reg_notifier = mwifiex_reg_notifier;
/* Set struct mwifiex_private pointer in wiphy_priv */
@@ -1302,17 +1394,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
"info: successfully registered wiphy device\n");
}
- dev_net_set(dev, wiphy_net(wdev->wiphy));
- dev->ieee80211_ptr = wdev;
- memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6);
- memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6);
- SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
priv->wdev = wdev;
- dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
- dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
-
return ret;
}
@@ -1362,13 +1445,8 @@ mwifiex_cfg80211_results(struct work_struct *work)
MWIFIEX_SCAN_TYPE_ACTIVE;
scan_req->chan_list[i].scan_time = 0;
}
- if (mwifiex_set_user_scan_ioctl(priv, scan_req)) {
- ret = -EFAULT;
- goto done;
- }
- if (mwifiex_inform_bss_from_scan_result(priv, NULL))
+ if (mwifiex_set_user_scan_ioctl(priv, scan_req))
ret = -EFAULT;
-done:
priv->scan_result_status = ret;
dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
__func__);
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h
index c4db8f3..8d010f2 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.h
+++ b/drivers/net/wireless/mwifiex/cfg80211.h
@@ -24,8 +24,7 @@
#include "main.h"
-int mwifiex_register_cfg80211(struct net_device *, u8 *,
- struct mwifiex_private *);
+int mwifiex_register_cfg80211(struct mwifiex_private *);
void mwifiex_cfg80211_results(struct work_struct *work);
#endif
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index d0cada5..f2e6de0 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -48,7 +48,7 @@ static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,
static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
0xb0, 0x48, 0x60, 0x6c, 0 };
-u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
+static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
0xb0, 0x48, 0x60, 0x6c, 0 };
static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,
@@ -57,19 +57,19 @@ static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,
0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };
-u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
+static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
-u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
+static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
0x30, 0x48, 0x60, 0x6c, 0 };
-u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
+static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
0x60, 0x6c, 0 };
u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
0x32, 0x40, 0x41, 0xff };
-u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
/*
* This function maps an index in supported rates table into
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 677e60b..90ffc76 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -40,8 +40,12 @@ mwifiex_init_cmd_node(struct mwifiex_private *priv,
{
cmd_node->priv = priv;
cmd_node->cmd_oid = cmd_oid;
- cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required;
- priv->adapter->cmd_wait_q_required = false;
+ if (priv->adapter->cmd_wait_q_required) {
+ cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required;
+ priv->adapter->cmd_wait_q_required = false;
+ cmd_node->cmd_wait_q_woken = false;
+ cmd_node->condition = &cmd_node->cmd_wait_q_woken;
+ }
cmd_node->data_buf = data_buf;
cmd_node->cmd_skb = cmd_node->skb;
}
@@ -90,8 +94,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
cmd_node->data_buf = NULL;
cmd_node->wait_q_enabled = false;
+ if (cmd_node->cmd_skb)
+ skb_trim(cmd_node->cmd_skb, 0);
+
if (cmd_node->resp_skb) {
- dev_kfree_skb_any(cmd_node->resp_skb);
+ adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb);
cmd_node->resp_skb = NULL;
}
}
@@ -104,13 +111,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
* main thread.
*/
static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_ds_misc_cmd *pcmd_ptr)
{
- struct mwifiex_ds_misc_cmd *pcmd_ptr =
- (struct mwifiex_ds_misc_cmd *) data_buf;
-
/* Copy the HOST command to command buffer */
- memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len);
+ memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);
return 0;
}
@@ -175,8 +180,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
- cmd_node->cmd_skb->data,
- cmd_node->cmd_skb->len, NULL);
+ cmd_node->cmd_skb, NULL);
skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
@@ -237,8 +241,7 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
- adapter->sleep_cfm->data,
- adapter->sleep_cfm->len, NULL);
+ adapter->sleep_cfm, NULL);
skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
if (ret == -1) {
@@ -401,8 +404,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
adapter->event_cause = 0;
adapter->event_skb = NULL;
-
- dev_kfree_skb_any(skb);
+ adapter->if_ops.event_complete(adapter, skb);
return ret;
}
@@ -420,7 +422,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
struct mwifiex_adapter *adapter = priv->adapter;
adapter->cmd_wait_q_required = true;
- adapter->cmd_wait_q.condition = false;
ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
data_buf);
@@ -513,10 +514,12 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
}
/* Send command */
- if (cmd_no == HostCmd_CMD_802_11_SCAN)
+ if (cmd_no == HostCmd_CMD_802_11_SCAN) {
mwifiex_queue_scan_cmd(priv, cmd_node);
- else
+ } else {
+ adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+ }
return ret;
}
@@ -537,7 +540,7 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
return;
if (cmd_node->wait_q_enabled)
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, cmd_node);
/* Clean the node */
mwifiex_clean_cmd_node(adapter, cmd_node);
@@ -707,15 +710,14 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
/* Copy original response back to response buffer */
- struct mwifiex_ds_misc_cmd *hostcmd = NULL;
+ struct mwifiex_ds_misc_cmd *hostcmd;
uint16_t size = le16_to_cpu(resp->size);
dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);
size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
if (adapter->curr_cmd->data_buf) {
- hostcmd = (struct mwifiex_ds_misc_cmd *)
- adapter->curr_cmd->data_buf;
+ hostcmd = adapter->curr_cmd->data_buf;
hostcmd->len = size;
- memcpy(hostcmd->cmd, (void *) resp, size);
+ memcpy(hostcmd->cmd, resp, size);
}
}
orig_cmdresp_no = le16_to_cpu(resp->command);
@@ -814,9 +816,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
return;
}
cmd_node = adapter->curr_cmd;
- if (cmd_node->wait_q_enabled)
- adapter->cmd_wait_q.status = -ETIMEDOUT;
-
if (cmd_node) {
adapter->dbg.timeout_cmd_id =
adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
@@ -861,6 +860,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
adapter->ps_mode, adapter->ps_state);
+
+ if (cmd_node->wait_q_enabled) {
+ adapter->cmd_wait_q.status = -ETIMEDOUT;
+ wake_up_interruptible(&adapter->cmd_wait_q.wait);
+ mwifiex_cancel_pending_ioctl(adapter);
+ /* reset cmd_sent flag to unblock new commands */
+ adapter->cmd_sent = false;
+ }
}
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
mwifiex_init_fw_complete(adapter);
@@ -885,7 +892,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
adapter->curr_cmd->wait_q_enabled = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
adapter->cmd_wait_q.status = -1;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
}
/* Cancel all pending command */
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
@@ -896,7 +903,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
if (cmd_node->wait_q_enabled) {
adapter->cmd_wait_q.status = -1;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, cmd_node);
cmd_node->wait_q_enabled = false;
}
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
@@ -937,7 +944,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
{
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
unsigned long cmd_flags;
- unsigned long cmd_pending_q_flags;
unsigned long scan_pending_q_flags;
uint16_t cancel_scan_cmd = false;
@@ -947,12 +953,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
cmd_node = adapter->curr_cmd;
cmd_node->wait_q_enabled = false;
cmd_node->cmd_flag |= CMD_F_CANCELED;
- spin_lock_irqsave(&adapter->cmd_pending_q_lock,
- cmd_pending_q_flags);
- list_del(&cmd_node->list);
- spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
- cmd_pending_q_flags);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+ adapter->curr_cmd = NULL;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
}
@@ -979,7 +982,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
}
adapter->cmd_wait_q.status = -1;
- mwifiex_complete_cmd(adapter);
}
/*
@@ -1156,7 +1158,7 @@ EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, uint16_t ps_bitmap,
- void *data_buf)
+ struct mwifiex_ds_auto_ds *auto_ds)
{
struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
&cmd->params.psmode_enh;
@@ -1219,9 +1221,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
sizeof(struct mwifiex_ie_types_header));
cmd_size += sizeof(*auto_ds_tlv);
tlv += sizeof(*auto_ds_tlv);
- if (data_buf)
- idletime = ((struct mwifiex_ds_auto_ds *)
- data_buf)->idle_time;
+ if (auto_ds)
+ idletime = auto_ds->idle_time;
dev_dbg(priv->adapter->dev,
"cmd: PS Command: Enter Auto Deep Sleep\n");
auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
@@ -1240,7 +1241,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
*/
int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_pm_cfg *pm_cfg)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
@@ -1283,10 +1284,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap);
- if (data_buf) {
+ if (pm_cfg) {
/* This section is for get power save mode */
- struct mwifiex_ds_pm_cfg *pm_cfg =
- (struct mwifiex_ds_pm_cfg *)data_buf;
if (ps_bitmap & BITMAP_STA_PS)
pm_cfg->param.ps_mode = 1;
else
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 46d65e0..d26a78b 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -27,8 +27,8 @@ static struct dentry *mwifiex_dfs_dir;
static char *bss_modes[] = {
"Unknown",
- "Managed",
"Ad-hoc",
+ "Managed",
"Auto"
};
@@ -216,28 +216,19 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
p += sprintf(p, "media_state=\"%s\"\n",
(!priv->media_connected ? "Disconnected" : "Connected"));
- p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
- netdev->dev_addr[0], netdev->dev_addr[1],
- netdev->dev_addr[2], netdev->dev_addr[3],
- netdev->dev_addr[4], netdev->dev_addr[5]);
+ p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
p += sprintf(p, "multicast_count=\"%d\"\n",
netdev_mc_count(netdev));
p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
- p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
- info.bssid[0], info.bssid[1],
- info.bssid[2], info.bssid[3],
- info.bssid[4], info.bssid[5]);
+ p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
p += sprintf(p, "region_code = \"%02x\"\n", info.region_code);
netdev_for_each_mc_addr(ha, netdev)
- p += sprintf(p, "multicast_address[%d]="
- "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++,
- ha->addr[0], ha->addr[1],
- ha->addr[2], ha->addr[3],
- ha->addr[4], ha->addr[5]);
+ p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
+ i++, ha->addr);
}
p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
@@ -451,26 +442,18 @@ mwifiex_debug_read(struct file *file, char __user *ubuf,
if (info.tx_tbl_num) {
p += sprintf(p, "Tx BA stream table:\n");
for (i = 0; i < info.tx_tbl_num; i++)
- p += sprintf(p, "tid = %d, "
- "ra = %02x:%02x:%02x:%02x:%02x:%02x\n",
- info.tx_tbl[i].tid, info.tx_tbl[i].ra[0],
- info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2],
- info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4],
- info.tx_tbl[i].ra[5]);
+ p += sprintf(p, "tid = %d, ra = %pM\n",
+ info.tx_tbl[i].tid, info.tx_tbl[i].ra);
}
if (info.rx_tbl_num) {
p += sprintf(p, "Rx reorder table:\n");
for (i = 0; i < info.rx_tbl_num; i++) {
-
- p += sprintf(p, "tid = %d, "
- "ta = %02x:%02x:%02x:%02x:%02x:%02x, "
+ p += sprintf(p, "tid = %d, ta = %pM, "
"start_win = %d, "
"win_size = %d, buffer: ",
info.rx_tbl[i].tid,
- info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1],
- info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3],
- info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5],
+ info.rx_tbl[i].ta,
info.rx_tbl[i].start_win,
info.rx_tbl[i].win_size);
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 0e90b09..ae17ce0 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -30,7 +30,9 @@
#define MWIFIEX_MAX_BSS_NUM (1)
-#define MWIFIEX_MIN_DATA_HEADER_LEN 32 /* (sizeof(mwifiex_txpd)) */
+#define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd)
+ * + 4 byte alignment
+ */
#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2
#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16
@@ -96,7 +98,6 @@ struct mwifiex_802_11_ssid {
struct mwifiex_wait_queue {
wait_queue_head_t wait;
- u16 condition;
int status;
};
@@ -112,14 +113,6 @@ struct mwifiex_txinfo {
u8 bss_index;
};
-struct mwifiex_bss_attr {
- u8 bss_type;
- u8 frame_type;
- u8 active;
- u8 bss_priority;
- u8 bss_num;
-};
-
enum mwifiex_wmm_ac_e {
WMM_AC_BK,
WMM_AC_BE,
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index afdd145..0cc5d73 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -57,12 +57,6 @@ struct tx_packet_hdr {
#define GET_FW_DEFAULT_BANDS(adapter) \
((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS)
-extern u8 supported_rates_b[B_SUPPORTED_RATES];
-extern u8 supported_rates_g[G_SUPPORTED_RATES];
-extern u8 supported_rates_bg[BG_SUPPORTED_RATES];
-extern u8 supported_rates_a[A_SUPPORTED_RATES];
-extern u8 supported_rates_n[N_SUPPORTED_RATES];
-
#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff
#define KEY_INFO_ENABLED 0x01
@@ -84,7 +78,8 @@ enum KEY_TYPE_ID {
#define MAX_FIRMWARE_POLL_TRIES 100
-#define FIRMWARE_READY 0xfedc
+#define FIRMWARE_READY_SDIO 0xfedc
+#define FIRMWARE_READY_PCIE 0xfedcba00
enum MWIFIEX_802_11_PRIVACY_FILTER {
MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL,
@@ -157,6 +152,17 @@ enum MWIFIEX_802_11_WEP_STATUS {
#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))
#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
+/* httxcfg bitmap
+ * 0 reserved
+ * 1 20/40 Mhz enable(1)/disable(0)
+ * 2-3 reserved
+ * 4 green field enable(1)/disable(0)
+ * 5 short GI in 20 Mhz enable(1)/disable(0)
+ * 6 short GI in 40 Mhz enable(1)/disable(0)
+ * 7-15 reserved
+ */
+#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6))
+
#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
#define SETHT_MCS32(x) (x[4] |= 1)
@@ -210,7 +216,7 @@ enum MWIFIEX_802_11_WEP_STATUS {
#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5
#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed
#define HostCmd_CMD_SET_BSS_MODE 0x00f7
-
+#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
enum ENH_PS_MODES {
EN_PS = 1,
@@ -810,6 +816,14 @@ struct host_cmd_ds_txpwr_cfg {
__le32 mode;
} __packed;
+struct mwifiex_bcn_param {
+ u8 bssid[ETH_ALEN];
+ u8 rssi;
+ __le32 timestamp[2];
+ __le16 beacon_period;
+ __le16 cap_info_bitmap;
+} __packed;
+
#define MWIFIEX_USER_SCAN_CHAN_MAX 50
#define MWIFIEX_MAX_SSID_LIST_LENGTH 10
@@ -851,13 +865,6 @@ struct mwifiex_user_scan_ssid {
struct mwifiex_user_scan_cfg {
/*
- * Flag set to keep the previous scan table intact
- *
- * If set, the scan results will accumulate, replacing any previous
- * matched entries for a BSS with the new scan data
- */
- u8 keep_previous_scan;
- /*
* BSS mode to be sent in the firmware command
*/
u8 bss_mode;
@@ -1125,6 +1132,30 @@ struct host_cmd_ds_set_bss_mode {
u8 con_type;
} __packed;
+struct host_cmd_ds_pcie_details {
+ /* TX buffer descriptor ring address */
+ u32 txbd_addr_lo;
+ u32 txbd_addr_hi;
+ /* TX buffer descriptor ring count */
+ u32 txbd_count;
+
+ /* RX buffer descriptor ring address */
+ u32 rxbd_addr_lo;
+ u32 rxbd_addr_hi;
+ /* RX buffer descriptor ring count */
+ u32 rxbd_count;
+
+ /* Event buffer descriptor ring address */
+ u32 evtbd_addr_lo;
+ u32 evtbd_addr_hi;
+ /* Event buffer descriptor ring count */
+ u32 evtbd_count;
+
+ /* Sleep cookie buffer physical address */
+ u32 sleep_cookie_addr_lo;
+ u32 sleep_cookie_addr_hi;
+} __packed;
+
struct host_cmd_ds_command {
__le16 command;
__le16 size;
@@ -1172,6 +1203,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_rf_reg_access rf_reg;
struct host_cmd_ds_pmic_reg_access pmic_reg;
struct host_cmd_ds_set_bss_mode bss_mode;
+ struct host_cmd_ds_pcie_details pcie_host_spec;
struct host_cmd_ds_802_11_eeprom_access eeprom;
} params;
} __packed;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 3f1559e..d792b3f 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -76,7 +76,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
memset(priv->curr_addr, 0xff, ETH_ALEN);
priv->pkt_tx_ctrl = 0;
- priv->bss_mode = NL80211_IFTYPE_STATION;
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
priv->data_rate = 0; /* Initially indicate the rate as auto */
priv->is_data_rate_auto = true;
priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
@@ -152,19 +152,6 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
{
int ret;
- u32 buf_size;
- struct mwifiex_bssdescriptor *temp_scan_table;
-
- /* Allocate buffer to store the BSSID list */
- buf_size = sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP;
- temp_scan_table = kzalloc(buf_size, GFP_KERNEL);
- if (!temp_scan_table) {
- dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n",
- __func__);
- return -ENOMEM;
- }
-
- adapter->scan_table = temp_scan_table;
/* Allocate command buffer */
ret = mwifiex_alloc_cmd_buffer(adapter);
@@ -204,7 +191,12 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
(adapter->sleep_cfm->data);
adapter->cmd_sent = false;
- adapter->data_sent = true;
+
+ if (adapter->iface_type == MWIFIEX_PCIE)
+ adapter->data_sent = false;
+ else
+ adapter->data_sent = true;
+
adapter->cmd_resp_received = false;
adapter->event_received = false;
adapter->data_received = false;
@@ -222,14 +214,8 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
- adapter->num_in_scan_table = 0;
- memset(adapter->scan_table, 0,
- (sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP));
adapter->scan_probes = 1;
- memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf));
- adapter->bcn_buf_end = adapter->bcn_buf;
-
adapter->multiple_dtim = 1;
adapter->local_listen_interval = 0; /* default value in firmware
@@ -297,6 +283,34 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
}
/*
+ * This function releases the lock variables and frees the locks and
+ * associated locks.
+ */
+static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
+{
+ struct mwifiex_private *priv;
+ s32 i, j;
+
+ /* Free lists */
+ list_del(&adapter->cmd_free_q);
+ list_del(&adapter->cmd_pending_q);
+ list_del(&adapter->scan_pending_q);
+
+ for (i = 0; i < adapter->priv_num; i++)
+ list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
+
+ for (i = 0; i < adapter->priv_num; i++) {
+ if (adapter->priv[i]) {
+ priv = adapter->priv[i];
+ for (j = 0; j < MAX_NUM_TID; ++j)
+ list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
+ list_del(&priv->tx_ba_stream_tbl_ptr);
+ list_del(&priv->rx_reorder_tbl_ptr);
+ }
+ }
+}
+
+/*
* This function frees the adapter structure.
*
* The freeing operation is done recursively, by canceling all
@@ -326,8 +340,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
del_timer(&adapter->cmd_timer);
dev_dbg(adapter->dev, "info: free scan table\n");
- kfree(adapter->scan_table);
- adapter->scan_table = NULL;
adapter->if_ops.cleanup_if(adapter);
@@ -392,34 +404,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
}
/*
- * This function releases the lock variables and frees the locks and
- * associated locks.
- */
-void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
-{
- struct mwifiex_private *priv;
- s32 i, j;
-
- /* Free lists */
- list_del(&adapter->cmd_free_q);
- list_del(&adapter->cmd_pending_q);
- list_del(&adapter->scan_pending_q);
-
- for (i = 0; i < adapter->priv_num; i++)
- list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
-
- for (i = 0; i < adapter->priv_num; i++) {
- if (adapter->priv[i]) {
- priv = adapter->priv[i];
- for (j = 0; j < MAX_NUM_TID; ++j)
- list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
- list_del(&priv->tx_ba_stream_tbl_ptr);
- list_del(&priv->rx_reorder_tbl_ptr);
- }
- }
-}
-
-/*
* This function initializes the firmware.
*
* The following operations are performed sequentially -
@@ -602,11 +586,13 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
struct mwifiex_fw_image *pmfw)
{
- int ret, winner;
+ int ret;
u32 poll_num = 1;
+ adapter->winner = 0;
+
/* Check if firmware is already running */
- ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner);
+ ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (!ret) {
dev_notice(adapter->dev,
"WLAN FW already running! Skip FW download\n");
@@ -615,7 +601,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
poll_num = MAX_FIRMWARE_POLL_TRIES;
/* Check if we are the winner for downloading FW */
- if (!winner) {
+ if (!adapter->winner) {
dev_notice(adapter->dev,
"Other interface already running!"
" Skip FW download\n");
@@ -633,7 +619,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
poll_fw:
/* Check if the firmware is downloaded successfully or not */
- ret = adapter->if_ops.check_fw_status(adapter, poll_num, NULL);
+ ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (ret) {
dev_err(adapter->dev, "FW failed to be active in time\n");
return -1;
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 7c1c5ee..e0b68e7 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -134,7 +134,6 @@ struct mwifiex_ver_ext {
struct mwifiex_bss_info {
u32 bss_mode;
struct mwifiex_802_11_ssid ssid;
- u32 scan_table_idx;
u32 bss_chan;
u32 region_code;
u32 media_connected;
@@ -249,6 +248,7 @@ struct mwifiex_ds_hs_cfg {
};
#define DEEP_SLEEP_ON 1
+#define DEEP_SLEEP_OFF 0
#define DEEP_SLEEP_IDLE_TIME 100
#define PS_MODE_AUTO 1
@@ -306,10 +306,12 @@ struct mwifiex_ds_read_eeprom {
u8 value[MAX_EEPROM_DATA];
};
+#define IEEE_MAX_IE_SIZE 256
+
struct mwifiex_ds_misc_gen_ie {
u32 type;
u32 len;
- u8 ie_data[IW_CUSTOM_MAX];
+ u8 ie_data[IEEE_MAX_IE_SIZE];
};
struct mwifiex_ds_misc_cmd {
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 890841a..d48dfb7 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -147,13 +147,12 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
u8 *ptr = rate1, *tmp;
u32 i, j;
- tmp = kmalloc(rate1_size, GFP_KERNEL);
+ tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
if (!tmp) {
dev_err(priv->adapter->dev, "failed to alloc tmp buf\n");
return -ENOMEM;
}
- memcpy(tmp, rate1, rate1_size);
memset(rate1, 0, rate1_size);
for (i = 0; rate2[i] && i < rate2_size; i++) {
@@ -224,32 +223,6 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
}
/*
- * This function updates the scan entry TSF timestamps to reflect
- * a new association.
- */
-static void
-mwifiex_update_tsf_timestamps(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *new_bss_desc)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 table_idx;
- long long new_tsf_base;
- signed long long tsf_delta;
-
- memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base));
-
- tsf_delta = new_tsf_base - new_bss_desc->network_tsf;
-
- dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, "
- "0x%016llx -> 0x%016llx\n",
- new_bss_desc->network_tsf, new_tsf_base);
-
- for (table_idx = 0; table_idx < adapter->num_in_scan_table;
- table_idx++)
- adapter->scan_table[table_idx].network_tsf += tsf_delta;
-}
-
-/*
* This function appends a WAPI IE.
*
* This function is called from the network join command preparation routine.
@@ -364,10 +337,9 @@ static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
*/
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ struct mwifiex_bssdescriptor *bss_desc)
{
struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
- struct mwifiex_bssdescriptor *bss_desc;
struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
struct mwifiex_ie_types_phy_param_set *phy_tlv;
struct mwifiex_ie_types_ss_param_set *ss_tlv;
@@ -380,7 +352,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
u8 *pos;
int rsn_ie_len = 0;
- bss_desc = (struct mwifiex_bssdescriptor *) data_buf;
pos = (u8 *) assoc;
mwifiex_cfg_tx_buf(priv, bss_desc);
@@ -641,12 +612,6 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
priv->curr_bss_params.band = (u8) bss_desc->bss_band;
- /*
- * Adjust the timestamps in the scan table to be relative to the newly
- * associated AP's TSF
- */
- mwifiex_update_tsf_timestamps(priv, bss_desc);
-
if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
priv->curr_bss_params.wmm_enabled = true;
else
@@ -748,7 +713,8 @@ done:
*/
int
mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_802_11_ssid *req_ssid)
{
int rsn_ie_len = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -786,20 +752,15 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(adhoc_start->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+ memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
adhoc_start->ssid);
memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(bss_desc->ssid.ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+ memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
- bss_desc->ssid.ssid_len =
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len;
+ bss_desc->ssid.ssid_len = req_ssid->ssid_len;
/* Set the BSS mode */
adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
@@ -1036,13 +997,12 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
*/
int
mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_bssdescriptor *bss_desc)
{
int rsn_ie_len = 0;
struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
&cmd->params.adhoc_join;
- struct mwifiex_bssdescriptor *bss_desc =
- (struct mwifiex_bssdescriptor *) data_buf;
struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
u32 cmd_append_size = 0;
u16 tmp_cap;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index f058225..018276f 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -26,26 +26,6 @@
const char driver_version[] = "mwifiex " VERSION " (%s) ";
-struct mwifiex_adapter *g_adapter;
-EXPORT_SYMBOL_GPL(g_adapter);
-
-static struct mwifiex_bss_attr mwifiex_bss_sta[] = {
- {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0},
-};
-
-static int drv_mode = DRV_MODE_STA;
-
-static char fw_name[32] = DEFAULT_FW_NAME;
-
-/* Supported drv_mode table */
-static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
- {
- .drv_mode = DRV_MODE_STA,
- .intf_num = ARRAY_SIZE(mwifiex_bss_sta),
- .bss_attr = mwifiex_bss_sta,
- },
-};
-
/*
* This function registers the device and performs all the necessary
* initializations.
@@ -62,7 +42,7 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
* proper cleanup before exiting.
*/
static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
- struct mwifiex_drv_mode *drv_mode_ptr)
+ void **padapter)
{
struct mwifiex_adapter *adapter;
int i;
@@ -71,7 +51,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
if (!adapter)
return -ENOMEM;
- g_adapter = adapter;
+ *padapter = adapter;
adapter->card = card;
/* Save interface specific operations in adapter */
@@ -82,44 +62,20 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
goto error;
adapter->priv_num = 0;
- for (i = 0; i < drv_mode_ptr->intf_num; i++) {
- adapter->priv[i] = NULL;
- if (!drv_mode_ptr->bss_attr[i].active)
- continue;
-
- /* Allocate memory for private structure */
- adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private),
- GFP_KERNEL);
- if (!adapter->priv[i]) {
- dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n",
- __func__, i);
- goto error;
- }
-
- adapter->priv_num++;
- adapter->priv[i]->adapter = adapter;
- /* Save bss_type, frame_type & bss_priority */
- adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type;
- adapter->priv[i]->frame_type =
- drv_mode_ptr->bss_attr[i].frame_type;
- adapter->priv[i]->bss_priority =
- drv_mode_ptr->bss_attr[i].bss_priority;
-
- if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA)
- adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA;
- else if (drv_mode_ptr->bss_attr[i].bss_type ==
- MWIFIEX_BSS_TYPE_UAP)
- adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP;
-
- /* Save bss_index & bss_num */
- adapter->priv[i]->bss_index = i;
- adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num;
+ /* Allocate memory for private structure */
+ adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private),
+ GFP_KERNEL);
+ if (!adapter->priv[0]) {
+ dev_err(adapter->dev, "%s: failed to alloc priv[0]\n",
+ __func__);
+ goto error;
}
- adapter->drv_mode = drv_mode_ptr;
- if (mwifiex_init_lock_list(adapter))
- goto error;
+ adapter->priv_num++;
+
+ adapter->priv[0]->adapter = adapter;
+ mwifiex_init_lock_list(adapter);
init_timer(&adapter->cmd_timer);
adapter->cmd_timer.function = mwifiex_cmd_timeout_func;
@@ -130,9 +86,9 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
error:
dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
- mwifiex_free_lock_list(adapter);
- for (i = 0; i < drv_mode_ptr->intf_num; i++)
+ for (i = 0; i < adapter->priv_num; i++)
kfree(adapter->priv[i]);
+
kfree(adapter);
return -1;
@@ -320,38 +276,6 @@ exit_main_proc:
}
/*
- * This function initializes the software.
- *
- * The main work includes allocating and initializing the adapter structure
- * and initializing the private structures.
- */
-static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
-{
- int i;
- struct mwifiex_drv_mode *drv_mode_ptr;
-
- /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */
- drv_mode_ptr = NULL;
- for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) {
- if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) {
- drv_mode_ptr = &mwifiex_drv_mode_tbl[i];
- break;
- }
- }
-
- if (!drv_mode_ptr) {
- pr_err("invalid drv_mode=%d\n", drv_mode);
- return -1;
- }
-
- if (mwifiex_register(card, if_ops, drv_mode_ptr))
- return -1;
-
- return 0;
-}
-
-/*
* This function frees the adapter structure.
*
* Additionally, this closes the netlink socket, frees the timers
@@ -384,20 +308,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
memset(&fw, 0, sizeof(struct mwifiex_fw_image));
- switch (adapter->revision_id) {
- case SD8787_W0:
- case SD8787_W1:
- strcpy(fw_name, SD8787_W1_FW_NAME);
- break;
- case SD8787_A0:
- case SD8787_A1:
- strcpy(fw_name, SD8787_AX_FW_NAME);
- break;
- default:
- break;
- }
-
- err = request_firmware(&adapter->firmware, fw_name, adapter->dev);
+ err = request_firmware(&adapter->firmware, adapter->fw_name,
+ adapter->dev);
if (err < 0) {
dev_err(adapter->dev, "request_firmware() returned"
" error code %#x\n", err);
@@ -546,6 +458,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
tx_info = MWIFIEX_SKB_TXCB(skb);
+ memset(tx_info, 0, sizeof(*tx_info));
tx_info->bss_index = priv->bss_index;
mwifiex_fill_buffer(skb);
@@ -569,7 +482,7 @@ static int
mwifiex_set_mac_address(struct net_device *dev, void *addr)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- struct sockaddr *hw_addr = (struct sockaddr *) addr;
+ struct sockaddr *hw_addr = addr;
int ret;
memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
@@ -643,7 +556,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
.ndo_set_mac_address = mwifiex_set_mac_address,
.ndo_tx_timeout = mwifiex_tx_timeout,
.ndo_get_stats = mwifiex_get_stats,
- .ndo_set_multicast_list = mwifiex_set_multicast_list,
+ .ndo_set_rx_mode = mwifiex_set_multicast_list,
};
/*
@@ -665,10 +578,11 @@ static const struct net_device_ops mwifiex_netdev_ops = {
*
* In addition, the CFG80211 work queue is also created.
*/
-static void
-mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev)
+void mwifiex_init_priv_params(struct mwifiex_private *priv,
+ struct net_device *dev)
{
dev->netdev_ops = &mwifiex_netdev_ops;
+ dev->destructor = free_netdev;
/* Initialize private structure */
priv->current_key_index = 0;
priv->media_connected = false;
@@ -680,118 +594,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev)
}
/*
- * This function adds a new logical interface.
- *
- * It allocates, initializes and registers the interface by performing
- * the following opearations -
- * - Allocate a new net device structure
- * - Assign device name
- * - Register the new device with CFG80211 subsystem
- * - Initialize semaphore and private structure
- * - Register the new device with kernel
- * - Create the complete debug FS structure if configured
- */
-static struct mwifiex_private *mwifiex_add_interface(
- struct mwifiex_adapter *adapter,
- u8 bss_index, u8 bss_type)
-{
- struct net_device *dev;
- struct mwifiex_private *priv;
- void *mdev_priv;
-
- dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d",
- ether_setup, 1);
- if (!dev) {
- dev_err(adapter->dev, "no memory available for netdevice\n");
- goto error;
- }
-
- if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr,
- adapter->priv[bss_index]) != 0) {
- dev_err(adapter->dev, "cannot register netdevice with cfg80211\n");
- goto error;
- }
- /* Save the priv pointer in netdev */
- priv = adapter->priv[bss_index];
- mdev_priv = netdev_priv(dev);
- *((unsigned long *) mdev_priv) = (unsigned long) priv;
-
- priv->netdev = dev;
-
- sema_init(&priv->async_sem, 1);
- priv->scan_pending_on_block = false;
-
- mwifiex_init_priv_params(priv, dev);
-
- SET_NETDEV_DEV(dev, adapter->dev);
-
- /* Register network device */
- if (register_netdev(dev)) {
- dev_err(adapter->dev, "cannot register virtual network device\n");
- goto error;
- }
-
- dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
-#ifdef CONFIG_DEBUG_FS
- mwifiex_dev_debugfs_init(priv);
-#endif
- return priv;
-error:
- if (dev)
- free_netdev(dev);
- return NULL;
-}
-
-/*
- * This function removes a logical interface.
- *
- * It deregisters, resets and frees the interface by performing
- * the following operations -
- * - Disconnect the device if connected, send wireless event to
- * notify applications.
- * - Remove the debug FS structure if configured
- * - Unregister the device from kernel
- * - Free the net device structure
- * - Cancel all works and destroy work queue
- * - Unregister and free the wireless device from CFG80211 subsystem
- */
-static void
-mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index)
-{
- struct net_device *dev;
- struct mwifiex_private *priv = adapter->priv[bss_index];
-
- if (!priv)
- return;
- dev = priv->netdev;
-
- if (priv->media_connected)
- priv->media_connected = false;
-
-#ifdef CONFIG_DEBUG_FS
- mwifiex_dev_debugfs_remove(priv);
-#endif
- /* Last reference is our one */
- dev_dbg(adapter->dev, "info: %s: refcnt = %d\n",
- dev->name, netdev_refcnt_read(dev));
-
- if (dev->reg_state == NETREG_REGISTERED)
- unregister_netdev(dev);
-
- /* Clear the priv in adapter */
- priv->netdev = NULL;
- if (dev)
- free_netdev(dev);
-
- cancel_work_sync(&priv->cfg_workqueue);
- flush_workqueue(priv->workqueue);
- destroy_workqueue(priv->workqueue);
- wiphy_unregister(priv->wdev->wiphy);
- wiphy_free(priv->wdev->wiphy);
- kfree(priv->wdev);
-}
-
-/*
* This function check if command is pending.
*/
int is_command_pending(struct mwifiex_adapter *adapter)
@@ -861,20 +663,21 @@ mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
*/
int
mwifiex_add_card(void *card, struct semaphore *sem,
- struct mwifiex_if_ops *if_ops)
+ struct mwifiex_if_ops *if_ops, u8 iface_type)
{
- int i;
struct mwifiex_adapter *adapter;
+ char fmt[64];
+ struct mwifiex_private *priv;
if (down_interruptible(sem))
goto exit_sem_err;
- if (mwifiex_init_sw(card, if_ops)) {
+ if (mwifiex_register(card, if_ops, (void **)&adapter)) {
pr_err("%s: software init failed\n", __func__);
goto err_init_sw;
}
- adapter = g_adapter;
+ adapter->iface_type = iface_type;
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
adapter->surprise_removed = false;
@@ -884,8 +687,8 @@ mwifiex_add_card(void *card, struct semaphore *sem,
init_waitqueue_head(&adapter->hs_activate_wait_q);
adapter->cmd_wait_q_required = false;
init_waitqueue_head(&adapter->cmd_wait_q.wait);
- adapter->cmd_wait_q.condition = false;
adapter->cmd_wait_q.status = 0;
+ adapter->scan_wait_q_woken = false;
adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
if (!adapter->workqueue)
@@ -905,21 +708,37 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_init_fw;
}
- /* Add interfaces */
- for (i = 0; i < adapter->drv_mode->intf_num; i++) {
- if (!mwifiex_add_interface(adapter, i,
- adapter->drv_mode->bss_attr[i].bss_type)) {
- goto err_add_intf;
- }
+ priv = adapter->priv[0];
+
+ if (mwifiex_register_cfg80211(priv) != 0) {
+ dev_err(adapter->dev, "cannot register netdevice"
+ " with cfg80211\n");
+ goto err_init_fw;
}
+ rtnl_lock();
+ /* Create station interface by default */
+ if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
+ NL80211_IFTYPE_STATION, NULL, NULL)) {
+ rtnl_unlock();
+ dev_err(adapter->dev, "cannot create default station"
+ " interface\n");
+ goto err_add_intf;
+ }
+
+ rtnl_unlock();
+
up(sem);
+ mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
+ dev_notice(adapter->dev, "driver_version = %s\n", fmt);
+
return 0;
err_add_intf:
- for (i = 0; i < adapter->priv_num; i++)
- mwifiex_remove_interface(adapter, i);
+ rtnl_lock();
+ mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ rtnl_unlock();
err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter);
@@ -974,7 +793,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
/* Stop data */
for (i = 0; i < adapter->priv_num; i++) {
priv = adapter->priv[i];
- if (priv) {
+ if (priv && priv->netdev) {
if (!netif_queue_stopped(priv->netdev))
netif_stop_queue(priv->netdev);
if (netif_carrier_ok(priv->netdev))
@@ -999,9 +818,24 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
atomic_read(&adapter->cmd_pending));
}
- /* Remove interface */
- for (i = 0; i < adapter->priv_num; i++)
- mwifiex_remove_interface(adapter, i);
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+
+ if (!priv)
+ continue;
+
+ rtnl_lock();
+ mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ rtnl_unlock();
+ }
+
+ priv = adapter->priv[0];
+ if (!priv)
+ goto exit_remove;
+
+ wiphy_unregister(priv->wdev->wiphy);
+ wiphy_free(priv->wdev->wiphy);
+ kfree(priv->wdev);
mwifiex_terminate_workqueue(adapter);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 8316b3c..30f138b 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -37,32 +37,16 @@
#include "ioctl.h"
#include "util.h"
#include "fw.h"
+#include "pcie.h"
extern const char driver_version[];
-extern struct mwifiex_adapter *g_adapter;
enum {
MWIFIEX_ASYNC_CMD,
MWIFIEX_SYNC_CMD
};
-#define DRV_MODE_STA 0x1
-
-#define SD8787_W0 0x30
-#define SD8787_W1 0x31
-#define SD8787_A0 0x40
-#define SD8787_A1 0x41
-
-#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
-#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
-#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
-
-struct mwifiex_drv_mode {
- u16 drv_mode;
- u16 intf_num;
- struct mwifiex_bss_attr *bss_attr;
-};
-
+#define MWIFIEX_MAX_AP 64
#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ)
@@ -124,6 +108,8 @@ struct mwifiex_drv_mode {
#define MAX_FREQUENCY_BAND_BG 2484
+#define MWIFIEX_EVENT_HEADER_LEN 4
+
struct mwifiex_dbg {
u32 num_cmd_host_to_card_failure;
u32 num_cmd_sleep_cfm_host_to_card_failure;
@@ -173,6 +159,11 @@ enum MWIFIEX_PS_STATE {
PS_STATE_SLEEP
};
+enum mwifiex_iface_type {
+ MWIFIEX_SDIO,
+ MWIFIEX_PCIE,
+};
+
struct mwifiex_add_ba_param {
u32 tx_win_size;
u32 rx_win_size;
@@ -236,27 +227,10 @@ struct ieee_types_header {
u8 len;
} __packed;
-struct ieee_obss_scan_param {
- u16 obss_scan_passive_dwell;
- u16 obss_scan_active_dwell;
- u16 bss_chan_width_trigger_scan_int;
- u16 obss_scan_passive_total;
- u16 obss_scan_active_total;
- u16 bss_width_chan_trans_delay;
- u16 obss_scan_active_threshold;
-} __packed;
-
-struct ieee_types_obss_scan_param {
- struct ieee_types_header ieee_hdr;
- struct ieee_obss_scan_param obss_scan;
-} __packed;
-
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
-#define IEEE_MAX_IE_SIZE 256
-
struct ieee_types_vendor_specific {
struct ieee_types_vendor_header vend_hdr;
u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
@@ -300,8 +274,6 @@ struct mwifiex_bssdescriptor {
u16 bss_co_2040_offset;
u8 *bcn_ext_cap;
u16 ext_cap_offset;
- struct ieee_types_obss_scan_param *bcn_obss_scan;
- u16 overlap_bss_offset;
struct ieee_types_vendor_specific *bcn_wpa_ie;
u16 wpa_offset;
struct ieee_types_generic *bcn_rsn_ie;
@@ -310,8 +282,6 @@ struct mwifiex_bssdescriptor {
u16 wapi_offset;
u8 *beacon_buf;
u32 beacon_buf_size;
- u32 beacon_buf_size_max;
-
};
struct mwifiex_current_bss_params {
@@ -477,7 +447,7 @@ struct mwifiex_private {
struct dentry *dfs_dev_dir;
#endif
u8 nick_name[16];
- struct iw_statistics w_stats;
+ u8 qual_level, qual_noise;
u16 current_key_index;
struct semaphore async_sem;
u8 scan_pending_on_block;
@@ -550,36 +520,41 @@ struct cmd_ctrl_node {
void *data_buf;
u32 wait_q_enabled;
struct sk_buff *skb;
+ u8 *condition;
+ u8 cmd_wait_q_woken;
};
struct mwifiex_if_ops {
int (*init_if) (struct mwifiex_adapter *);
void (*cleanup_if) (struct mwifiex_adapter *);
- int (*check_fw_status) (struct mwifiex_adapter *, u32, int *);
+ int (*check_fw_status) (struct mwifiex_adapter *, u32);
int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
int (*register_dev) (struct mwifiex_adapter *);
void (*unregister_dev) (struct mwifiex_adapter *);
int (*enable_int) (struct mwifiex_adapter *);
int (*process_int_status) (struct mwifiex_adapter *);
- int (*host_to_card) (struct mwifiex_adapter *, u8,
- u8 *payload, u32 pkt_len,
+ int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
struct mwifiex_tx_param *);
int (*wakeup) (struct mwifiex_adapter *);
int (*wakeup_complete) (struct mwifiex_adapter *);
+ /* Interface specific functions */
void (*update_mp_end_port) (struct mwifiex_adapter *, u16);
void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
+ int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
+ int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
};
struct mwifiex_adapter {
+ u8 iface_type;
struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM];
u8 priv_num;
- struct mwifiex_drv_mode *drv_mode;
const struct firmware *firmware;
+ char fw_name[32];
+ int winner;
struct device *dev;
bool surprise_removed;
u32 fw_release_number;
- u32 revision_id;
u16 init_wait_q_woken;
wait_queue_head_t init_wait_q;
void *card;
@@ -633,15 +608,11 @@ struct mwifiex_adapter {
u32 scan_processing;
u16 region_code;
struct mwifiex_802_11d_domain_reg domain_reg;
- struct mwifiex_bssdescriptor *scan_table;
- u32 num_in_scan_table;
u16 scan_probes;
u32 scan_mode;
u16 specific_scan_time;
u16 active_scan_time;
u16 passive_scan_time;
- u8 bcn_buf[MAX_SCAN_BEACON_BUFFER];
- u8 *bcn_buf_end;
u8 fw_bands;
u8 adhoc_start_band;
u8 config_bands;
@@ -682,10 +653,11 @@ struct mwifiex_adapter {
u32 arp_filter_size;
u16 cmd_wait_q_required;
struct mwifiex_wait_queue cmd_wait_q;
+ u8 scan_wait_q_woken;
+ struct cmd_ctrl_node *cmd_queued;
};
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
-void mwifiex_free_lock_list(struct mwifiex_adapter *adapter);
int mwifiex_init_fw(struct mwifiex_adapter *adapter);
@@ -701,7 +673,8 @@ int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
int mwifiex_process_event(struct mwifiex_adapter *adapter);
-int mwifiex_complete_cmd(struct mwifiex_adapter *adapter);
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
+ struct cmd_ctrl_node *cmd_node);
int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid, void *data_buf);
@@ -735,8 +708,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags);
int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
struct sk_buff *skb, int status);
-int mwifiex_recv_packet_complete(struct mwifiex_adapter *,
- struct sk_buff *skb, int status);
void mwifiex_clean_txrx(struct mwifiex_private *priv);
u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv);
void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter);
@@ -745,10 +716,10 @@ void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,
int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, uint16_t ps_bitmap,
- void *data_buf);
+ struct mwifiex_ds_auto_ds *auto_ds);
int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf);
+ struct mwifiex_ds_pm_cfg *pm_cfg);
void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
void mwifiex_hs_activated_event(struct mwifiex_private *priv,
u8 activated);
@@ -760,38 +731,28 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid,
void *data_buf, void *cmd_buf);
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
- void *cmd_buf);
+ struct host_cmd_ds_command *resp);
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
struct sk_buff *skb);
int mwifiex_process_sta_event(struct mwifiex_private *);
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
-int mwifiex_scan_networks(struct mwifiex_private *priv,
- const struct mwifiex_user_scan_cfg *user_scan_in);
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_scan_cmd_config *scan_cfg);
void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
struct cmd_ctrl_node *cmd_node);
int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
-s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *ssid, u8 *bssid,
- u32 mode);
-s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
- u32 mode);
-int mwifiex_find_best_network(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *req_ssid_bssid);
s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
struct mwifiex_802_11_ssid *ssid2);
int mwifiex_associate(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
- struct host_cmd_ds_command
- *cmd, void *data_buf);
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
void mwifiex_reset_connect_state(struct mwifiex_private *priv);
-void mwifiex_2040_coex_event(struct mwifiex_private *priv);
u8 mwifiex_band_to_radio_type(u8 band);
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
int mwifiex_adhoc_start(struct mwifiex_private *priv,
@@ -800,10 +761,10 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
@@ -832,6 +793,8 @@ int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int is_command_pending(struct mwifiex_adapter *adapter);
+void mwifiex_init_priv_params(struct mwifiex_private *priv,
+ struct net_device *dev);
/*
* This function checks if the queuing is RA based or not.
@@ -921,7 +884,7 @@ struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter
*adapter, u8 bss_index);
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *);
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
@@ -931,19 +894,15 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
struct net_device *dev);
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
-int mwifiex_bss_start(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid);
-int mwifiex_set_hs_params(struct mwifiex_private *priv,
- u16 action, int cmd_type,
- struct mwifiex_ds_hs_cfg *hscfg);
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+ struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
int mwifiex_get_signal_info(struct mwifiex_private *priv,
struct mwifiex_ds_get_signal *signal);
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
-int mwifiex_find_best_bss(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid);
int mwifiex_request_scan(struct mwifiex_private *priv,
struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
@@ -992,12 +951,26 @@ int mwifiex_main_process(struct mwifiex_adapter *);
int mwifiex_bss_set_channel(struct mwifiex_private *,
struct mwifiex_chan_freq_power *cfp);
-int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *,
- struct mwifiex_ssid_bssid *);
int mwifiex_set_radio_band_cfg(struct mwifiex_private *,
struct mwifiex_ds_band_cfg *);
int mwifiex_get_bss_info(struct mwifiex_private *,
struct mwifiex_bss_info *);
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+ u8 *bssid, s32 rssi, u8 *ie_buf,
+ size_t ie_len, u16 beacon_period,
+ u16 cap_info_bitmap, u8 band,
+ struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
+ struct mwifiex_bssdescriptor *bss_entry,
+ u8 *ie_buf, u32 ie_len);
+int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
+ struct mwifiex_bssdescriptor *bss_desc);
+
+struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+ char *name, enum nl80211_iftype type,
+ u32 *flags, struct vif_params *params);
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
+
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 5c22860..6618dd6 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -172,59 +172,6 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
}
/*
- * Sends IOCTL request to get the best BSS.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_find_best_bss(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid)
-{
- struct mwifiex_ssid_bssid tmp_ssid_bssid;
- u8 *mac;
-
- if (!ssid_bssid)
- return -1;
-
- memcpy(&tmp_ssid_bssid, ssid_bssid,
- sizeof(struct mwifiex_ssid_bssid));
-
- if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) {
- memcpy(ssid_bssid, &tmp_ssid_bssid,
- sizeof(struct mwifiex_ssid_bssid));
- mac = (u8 *) &ssid_bssid->bssid;
- dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"
- " %pM\n", ssid_bssid->ssid.ssid, mac);
- return 0;
- }
-
- return -1;
-}
-
-/*
- * Sends IOCTL request to start a scan with user configurations.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- *
- * Upon completion, it also generates a wireless event to notify
- * applications.
- */
-int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
- struct mwifiex_user_scan_cfg *scan_req)
-{
- int status;
-
- priv->adapter->cmd_wait_q.condition = false;
-
- status = mwifiex_scan_networks(priv, scan_req);
- if (!status)
- status = mwifiex_wait_queue_complete(priv->adapter);
-
- return status;
-}
-
-/*
* This function checks if wapi is enabled in driver and scanned network is
* compatible with it.
*/
@@ -286,8 +233,7 @@ mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv,
*/
static bool
mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *bss_desc,
- int index)
+ struct mwifiex_bssdescriptor *bss_desc)
{
if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
&& priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -298,9 +244,9 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
* LinkSys WRT54G && bss_desc->privacy
*/
) {
- dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d"
+ dev_dbg(priv->adapter->dev, "info: %s: WPA:"
" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "EncMode=%#x privacy=%#x\n", __func__, index,
+ "EncMode=%#x privacy=%#x\n", __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).
vend_hdr.element_id : 0,
@@ -324,8 +270,7 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
*/
static bool
mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *bss_desc,
- int index)
+ struct mwifiex_bssdescriptor *bss_desc)
{
if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
&& !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled
@@ -336,9 +281,9 @@ mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
* LinkSys WRT54G && bss_desc->privacy
*/
) {
- dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d"
+ dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "EncMode=%#x privacy=%#x\n", __func__, index,
+ "EncMode=%#x privacy=%#x\n", __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).
vend_hdr.element_id : 0,
@@ -383,8 +328,7 @@ mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv,
*/
static bool
mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *bss_desc,
- int index)
+ struct mwifiex_bssdescriptor *bss_desc)
{
if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
&& !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -395,9 +339,9 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
&& priv->sec_info.encryption_mode
&& bss_desc->privacy) {
dev_dbg(priv->adapter->dev, "info: %s: dynamic "
- "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x "
+ "WEP: wpa_ie=%#x wpa2_ie=%#x "
"EncMode=%#x privacy=%#x\n",
- __func__, index,
+ __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).
vend_hdr.element_id : 0,
@@ -430,42 +374,41 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
* Compatibility is not matched while roaming, except for mode.
*/
static s32
-mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
+mwifiex_is_network_compatible(struct mwifiex_private *priv,
+ struct mwifiex_bssdescriptor *bss_desc, u32 mode)
{
struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *bss_desc;
- bss_desc = &adapter->scan_table[index];
bss_desc->disable_11n = false;
/* Don't check for compatibility if roaming */
if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION)
&& (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
- return index;
+ return 0;
if (priv->wps.session_enable) {
dev_dbg(adapter->dev,
"info: return success directly in WPS period\n");
- return index;
+ return 0;
}
if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) {
dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
- return index;
+ return 0;
}
if (bss_desc->bss_mode == mode) {
if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) {
/* No security */
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_static_wep(priv,
bss_desc)) {
/* Static WEP enabled */
dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
bss_desc->disable_11n = true;
- return index;
- } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc,
- index)) {
+ return 0;
+ } else if (mwifiex_is_network_compatible_for_wpa(priv,
+ bss_desc)) {
/* WPA enabled */
if (((priv->adapter->config_bands & BAND_GN
|| priv->adapter->config_bands & BAND_AN)
@@ -483,9 +426,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
return -1;
}
}
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_wpa2(priv,
- bss_desc, index)) {
+ bss_desc)) {
/* WPA2 enabled */
if (((priv->adapter->config_bands & BAND_GN
|| priv->adapter->config_bands & BAND_AN)
@@ -503,22 +446,22 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
return -1;
}
}
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_adhoc_aes(priv,
bss_desc)) {
/* Ad-hoc AES enabled */
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_dynamic_wep(priv,
- bss_desc, index)) {
+ bss_desc)) {
/* Dynamic WEP enabled */
- return index;
+ return 0;
}
/* Security doesn't match */
- dev_dbg(adapter->dev, "info: %s: failed: index=%d "
+ dev_dbg(adapter->dev, "info: %s: failed: "
"wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode"
"=%#x privacy=%#x\n",
- __func__, index,
+ __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).vend_hdr.
element_id : 0,
@@ -538,52 +481,6 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
}
/*
- * This function finds the best SSID in the scan list.
- *
- * It searches the scan table for the best SSID that also matches the current
- * adapter network preference (mode, security etc.).
- */
-static s32
-mwifiex_find_best_network_in_list(struct mwifiex_private *priv)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 mode = priv->bss_mode;
- s32 best_net = -1;
- s32 best_rssi = 0;
- u32 i;
-
- dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n",
- adapter->num_in_scan_table);
-
- for (i = 0; i < adapter->num_in_scan_table; i++) {
- switch (mode) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- if (mwifiex_is_network_compatible(priv, i, mode) >= 0) {
- if (SCAN_RSSI(adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->
- scan_table[i].rssi);
- best_net = i;
- }
- }
- break;
- case NL80211_IFTYPE_UNSPECIFIED:
- default:
- if (SCAN_RSSI(adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->scan_table[i].
- rssi);
- best_net = i;
- }
- break;
- }
- }
-
- return best_net;
-}
-
-/*
* This function creates a channel list for the driver to scan, based
* on region/band information.
*
@@ -612,7 +509,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
sband = priv->wdev->wiphy->bands[band];
- for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) {
+ for (i = 0; (i < sband->n_channels) ; i++) {
ch = &sband->channels[i];
if (ch->flags & IEEE80211_CHAN_DISABLED)
continue;
@@ -643,6 +540,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|= MWIFIEX_DISABLE_CHAN_FILT;
}
+ chan_idx++;
}
}
@@ -921,8 +819,10 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
wildcard_ssid_tlv->header.len = cpu_to_le16(
(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
max_ssid_length)));
- wildcard_ssid_tlv->max_ssid_length =
- user_scan_in->ssid_list[ssid_idx].max_len;
+
+ /* max_ssid_length = 0 tells firmware to perform
+ specific scan for the SSID filled */
+ wildcard_ssid_tlv->max_ssid_length = 0;
memcpy(wildcard_ssid_tlv->ssid,
user_scan_in->ssid_list[ssid_idx].ssid,
@@ -1161,34 +1061,13 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
}
/*
- * This function interprets a BSS scan response returned from the firmware.
- *
- * The various fixed fields and IEs are parsed and passed back for a BSS
- * probe response or beacon from scan command. Information is recorded as
- * needed in the scan table for that entry.
- *
- * The following IE types are recognized and parsed -
- * - SSID
- * - Supported rates
- * - FH parameters set
- * - DS parameters set
- * - CF parameters set
- * - IBSS parameters set
- * - ERP information
- * - Extended supported rates
- * - Vendor specific (221)
- * - RSN IE
- * - WAPI IE
- * - HT capability
- * - HT operation
- * - BSS Coexistence 20/40
- * - Extended capability
- * - Overlapping BSS scan parameters
+ * This function parses provided beacon buffer and updates
+ * respective fields in bss descriptor structure.
*/
-static int
-mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
- struct mwifiex_bssdescriptor *bss_entry,
- u8 **beacon_info, u32 *bytes_left)
+int
+mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
+ struct mwifiex_bssdescriptor *bss_entry,
+ u8 *ie_buf, u32 ie_len)
{
int ret = 0;
u8 element_id;
@@ -1196,135 +1075,43 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
struct ieee_types_ds_param_set *ds_param_set;
struct ieee_types_cf_param_set *cf_param_set;
struct ieee_types_ibss_param_set *ibss_param_set;
- __le16 beacon_interval;
- __le16 capabilities;
u8 *current_ptr;
u8 *rate;
u8 element_len;
u16 total_ie_len;
u8 bytes_to_copy;
u8 rate_size;
- u16 beacon_size;
u8 found_data_rate_ie;
- u32 bytes_left_for_current_beacon;
+ u32 bytes_left;
struct ieee_types_vendor_specific *vendor_ie;
const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
found_data_rate_ie = false;
rate_size = 0;
- beacon_size = 0;
-
- if (*bytes_left >= sizeof(beacon_size)) {
- /* Extract & convert beacon size from the command buffer */
- memcpy(&beacon_size, *beacon_info, sizeof(beacon_size));
- *bytes_left -= sizeof(beacon_size);
- *beacon_info += sizeof(beacon_size);
- }
-
- if (!beacon_size || beacon_size > *bytes_left) {
- *beacon_info += *bytes_left;
- *bytes_left = 0;
- return -1;
- }
-
- /* Initialize the current working beacon pointer for this BSS
- iteration */
- current_ptr = *beacon_info;
-
- /* Advance the return beacon pointer past the current beacon */
- *beacon_info += beacon_size;
- *bytes_left -= beacon_size;
-
- bytes_left_for_current_beacon = beacon_size;
-
- memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN);
- dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n",
- bss_entry->mac_address);
-
- current_ptr += ETH_ALEN;
- bytes_left_for_current_beacon -= ETH_ALEN;
-
- if (bytes_left_for_current_beacon < 12) {
- dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
- return -1;
- }
-
- /*
- * Next 4 fields are RSSI, time stamp, beacon interval,
- * and capability information
- */
-
- /* RSSI is 1 byte long */
- bss_entry->rssi = (s32) (*current_ptr);
- dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr);
- current_ptr += 1;
- bytes_left_for_current_beacon -= 1;
-
- /*
- * The RSSI is not part of the beacon/probe response. After we have
- * advanced current_ptr past the RSSI field, save the remaining
- * data for use at the application layer
- */
- bss_entry->beacon_buf = current_ptr;
- bss_entry->beacon_buf_size = bytes_left_for_current_beacon;
-
- /* Time stamp is 8 bytes long */
- memcpy(bss_entry->time_stamp, current_ptr, 8);
- current_ptr += 8;
- bytes_left_for_current_beacon -= 8;
-
- /* Beacon interval is 2 bytes long */
- memcpy(&beacon_interval, current_ptr, 2);
- bss_entry->beacon_period = le16_to_cpu(beacon_interval);
- current_ptr += 2;
- bytes_left_for_current_beacon -= 2;
-
- /* Capability information is 2 bytes long */
- memcpy(&capabilities, current_ptr, 2);
- dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
- capabilities);
- bss_entry->cap_info_bitmap = le16_to_cpu(capabilities);
- current_ptr += 2;
- bytes_left_for_current_beacon -= 2;
-
- /* Rest of the current buffer are IE's */
- dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
- bytes_left_for_current_beacon);
-
- if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
- dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n");
- bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
- } else {
- bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
- }
-
- if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
- bss_entry->bss_mode = NL80211_IFTYPE_ADHOC;
- else
- bss_entry->bss_mode = NL80211_IFTYPE_STATION;
-
+ current_ptr = ie_buf;
+ bytes_left = ie_len;
+ bss_entry->beacon_buf = ie_buf;
+ bss_entry->beacon_buf_size = ie_len;
/* Process variable IE */
- while (bytes_left_for_current_beacon >= 2) {
+ while (bytes_left >= 2) {
element_id = *current_ptr;
element_len = *(current_ptr + 1);
total_ie_len = element_len + sizeof(struct ieee_types_header);
- if (bytes_left_for_current_beacon < total_ie_len) {
+ if (bytes_left < total_ie_len) {
dev_err(adapter->dev, "err: InterpretIE: in processing"
" IE, bytes left < IE length\n");
- bytes_left_for_current_beacon = 0;
- ret = -1;
- continue;
+ return -1;
}
switch (element_id) {
case WLAN_EID_SSID:
bss_entry->ssid.ssid_len = element_len;
memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
element_len);
- dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n",
- bss_entry->ssid.ssid);
+ dev_dbg(adapter->dev, "info: InterpretIE: ssid: "
+ "%-32s\n", bss_entry->ssid.ssid);
break;
case WLAN_EID_SUPP_RATES:
@@ -1471,13 +1258,6 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
sizeof(struct ieee_types_header) -
bss_entry->beacon_buf);
break;
- case WLAN_EID_OVERLAP_BSS_SCAN_PARAM:
- bss_entry->bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- current_ptr;
- bss_entry->overlap_bss_offset = (u16) (current_ptr -
- bss_entry->beacon_buf);
- break;
default:
break;
}
@@ -1485,577 +1265,13 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
current_ptr += element_len + 2;
/* Need to account for IE ID and IE Len */
- bytes_left_for_current_beacon -= (element_len + 2);
+ bytes_left -= (element_len + 2);
- } /* while (bytes_left_for_current_beacon > 2) */
+ } /* while (bytes_left > 2) */
return ret;
}
/*
- * This function adjusts the pointers used in beacon buffers to reflect
- * shifts.
- *
- * The memory allocated for beacon buffers is of fixed sizes where all the
- * saved beacons must be stored. New beacons are added in the free portion
- * of this memory, space permitting; while duplicate beacon buffers are
- * placed at the same start location. However, since duplicate beacon
- * buffers may not match the size of the old one, all the following buffers
- * in the memory must be shifted to either make space, or to fill up freed
- * up space.
- *
- * This function is used to update the beacon buffer pointers that are past
- * an existing beacon buffer that is updated with a new one of different
- * size. The pointers are shifted by a fixed amount, either forward or
- * backward.
- *
- * the following pointers in every affected beacon buffers are changed, if
- * present -
- * - WPA IE pointer
- * - RSN IE pointer
- * - WAPI IE pointer
- * - HT capability IE pointer
- * - HT information IE pointer
- * - BSS coexistence 20/40 IE pointer
- * - Extended capability IE pointer
- * - Overlapping BSS scan parameter IE pointer
- */
-static void
-mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance,
- u8 *bcn_store, u32 rem_bcn_size,
- u32 num_of_ent)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 adj_idx;
- for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
- if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) {
-
- if (advance)
- adapter->scan_table[adj_idx].beacon_buf +=
- rem_bcn_size;
- else
- adapter->scan_table[adj_idx].beacon_buf -=
- rem_bcn_size;
-
- if (adapter->scan_table[adj_idx].bcn_wpa_ie)
- adapter->scan_table[adj_idx].bcn_wpa_ie =
- (struct ieee_types_vendor_specific *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].wpa_offset);
- if (adapter->scan_table[adj_idx].bcn_rsn_ie)
- adapter->scan_table[adj_idx].bcn_rsn_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].rsn_offset);
- if (adapter->scan_table[adj_idx].bcn_wapi_ie)
- adapter->scan_table[adj_idx].bcn_wapi_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].wapi_offset);
- if (adapter->scan_table[adj_idx].bcn_ht_cap)
- adapter->scan_table[adj_idx].bcn_ht_cap =
- (struct ieee80211_ht_cap *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].ht_cap_offset);
-
- if (adapter->scan_table[adj_idx].bcn_ht_info)
- adapter->scan_table[adj_idx].bcn_ht_info =
- (struct ieee80211_ht_info *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].ht_info_offset);
- if (adapter->scan_table[adj_idx].bcn_bss_co_2040)
- adapter->scan_table[adj_idx].bcn_bss_co_2040 =
- (u8 *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].bss_co_2040_offset);
- if (adapter->scan_table[adj_idx].bcn_ext_cap)
- adapter->scan_table[adj_idx].bcn_ext_cap =
- (u8 *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].ext_cap_offset);
- if (adapter->scan_table[adj_idx].bcn_obss_scan)
- adapter->scan_table[adj_idx].bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].overlap_bss_offset);
- }
- }
-}
-
-/*
- * This function updates the pointers used in beacon buffer for given bss
- * descriptor to reflect shifts
- *
- * Following pointers are updated
- * - WPA IE pointer
- * - RSN IE pointer
- * - WAPI IE pointer
- * - HT capability IE pointer
- * - HT information IE pointer
- * - BSS coexistence 20/40 IE pointer
- * - Extended capability IE pointer
- * - Overlapping BSS scan parameter IE pointer
- */
-static void
-mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon)
-{
- if (beacon->bcn_wpa_ie)
- beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *)
- (beacon->beacon_buf + beacon->wpa_offset);
- if (beacon->bcn_rsn_ie)
- beacon->bcn_rsn_ie = (struct ieee_types_generic *)
- (beacon->beacon_buf + beacon->rsn_offset);
- if (beacon->bcn_wapi_ie)
- beacon->bcn_wapi_ie = (struct ieee_types_generic *)
- (beacon->beacon_buf + beacon->wapi_offset);
- if (beacon->bcn_ht_cap)
- beacon->bcn_ht_cap = (struct ieee80211_ht_cap *)
- (beacon->beacon_buf + beacon->ht_cap_offset);
- if (beacon->bcn_ht_info)
- beacon->bcn_ht_info = (struct ieee80211_ht_info *)
- (beacon->beacon_buf + beacon->ht_info_offset);
- if (beacon->bcn_bss_co_2040)
- beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf +
- beacon->bss_co_2040_offset);
- if (beacon->bcn_ext_cap)
- beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf +
- beacon->ext_cap_offset);
- if (beacon->bcn_obss_scan)
- beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *)
- (beacon->beacon_buf + beacon->overlap_bss_offset);
-}
-
-/*
- * This function stores a beacon or probe response for a BSS returned
- * in the scan.
- *
- * This stores a new scan response or an update for a previous scan response.
- * New entries need to verify that they do not exceed the total amount of
- * memory allocated for the table.
- *
- * Replacement entries need to take into consideration the amount of space
- * currently allocated for the beacon/probe response and adjust the entry
- * as needed.
- *
- * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
- * for an entry in case it is a beacon since a probe response for the
- * network will by larger per the standard. This helps to reduce the
- * amount of memory copying to fit a new probe response into an entry
- * already occupied by a network's previously stored beacon.
- */
-static void
-mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv,
- u32 beacon_idx, u32 num_of_ent,
- struct mwifiex_bssdescriptor *new_beacon)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u8 *bcn_store;
- u32 new_bcn_size;
- u32 old_bcn_size;
- u32 bcn_space;
-
- if (adapter->scan_table[beacon_idx].beacon_buf) {
-
- new_bcn_size = new_beacon->beacon_buf_size;
- old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size;
- bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max;
- bcn_store = adapter->scan_table[beacon_idx].beacon_buf;
-
- /* Set the max to be the same as current entry unless changed
- below */
- new_beacon->beacon_buf_size_max = bcn_space;
- if (new_bcn_size == old_bcn_size) {
- /*
- * Beacon is the same size as the previous entry.
- * Replace the previous contents with the scan result
- */
- memcpy(bcn_store, new_beacon->beacon_buf,
- new_beacon->beacon_buf_size);
-
- } else if (new_bcn_size <= bcn_space) {
- /*
- * New beacon size will fit in the amount of space
- * we have previously allocated for it
- */
-
- /* Copy the new beacon buffer entry over the old one */
- memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
-
- /*
- * If the old beacon size was less than the maximum
- * we had alloted for the entry, and the new entry
- * is even smaller, reset the max size to the old
- * beacon entry and compress the storage space
- * (leaving a new pad space of (old_bcn_size -
- * new_bcn_size).
- */
- if (old_bcn_size < bcn_space
- && new_bcn_size <= old_bcn_size) {
- /*
- * Old Beacon size is smaller than the alloted
- * storage size. Shrink the alloted storage
- * space.
- */
- dev_dbg(adapter->dev, "info: AppControl:"
- " smaller duplicate beacon "
- "(%d), old = %d, new = %d, space = %d,"
- "left = %d\n",
- beacon_idx, old_bcn_size, new_bcn_size,
- bcn_space,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
-
- /*
- * memmove (since the memory overlaps) the
- * data after the beacon we just stored to the
- * end of the current beacon. This cleans up
- * any unused space the old larger beacon was
- * using in the buffer
- */
- memmove(bcn_store + old_bcn_size,
- bcn_store + bcn_space,
- adapter->bcn_buf_end - (bcn_store +
- bcn_space));
-
- /*
- * Decrement the end pointer by the difference
- * between the old larger size and the new
- * smaller size since we are using less space
- * due to the new beacon being smaller
- */
- adapter->bcn_buf_end -=
- (bcn_space - old_bcn_size);
-
- /* Set the maximum storage size to the old
- beacon size */
- new_beacon->beacon_buf_size_max = old_bcn_size;
-
- /* Adjust beacon buffer pointers that are past
- the current */
- mwifiex_adjust_beacon_buffer_ptrs(priv, 0,
- bcn_store, (bcn_space - old_bcn_size),
- num_of_ent);
- }
- } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space)
- < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) {
- /*
- * Beacon is larger than space previously allocated
- * (bcn_space) and there is enough space left in the
- * beaconBuffer to store the additional data
- */
- dev_dbg(adapter->dev, "info: AppControl:"
- " larger duplicate beacon (%d), "
- "old = %d, new = %d, space = %d, left = %d\n",
- beacon_idx, old_bcn_size, new_bcn_size,
- bcn_space,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
-
- /*
- * memmove (since the memory overlaps) the data
- * after the beacon we just stored to the end of
- * the current beacon. This moves the data for
- * the beacons after this further in memory to
- * make space for the new larger beacon we are
- * about to copy in.
- */
- memmove(bcn_store + new_bcn_size,
- bcn_store + bcn_space,
- adapter->bcn_buf_end - (bcn_store + bcn_space));
-
- /* Copy the new beacon buffer entry over the old one */
- memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
-
- /* Move the beacon end pointer by the amount of new
- beacon data we are adding */
- adapter->bcn_buf_end += (new_bcn_size - bcn_space);
-
- /*
- * This entry is bigger than the alloted max space
- * previously reserved. Increase the max space to
- * be equal to the new beacon size
- */
- new_beacon->beacon_buf_size_max = new_bcn_size;
-
- /* Adjust beacon buffer pointers that are past the
- current */
- mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store,
- (new_bcn_size - bcn_space),
- num_of_ent);
- } else {
- /*
- * Beacon is larger than the previously allocated space,
- * but there is not enough free space to store the
- * additional data.
- */
- dev_err(adapter->dev, "AppControl: larger duplicate "
- " beacon (%d), old = %d new = %d, space = %d,"
- " left = %d\n", beacon_idx, old_bcn_size,
- new_bcn_size, bcn_space,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end - adapter->bcn_buf)));
-
- /* Storage failure, keep old beacon intact */
- new_beacon->beacon_buf_size = old_bcn_size;
- if (new_beacon->bcn_wpa_ie)
- new_beacon->wpa_offset =
- adapter->scan_table[beacon_idx].
- wpa_offset;
- if (new_beacon->bcn_rsn_ie)
- new_beacon->rsn_offset =
- adapter->scan_table[beacon_idx].
- rsn_offset;
- if (new_beacon->bcn_wapi_ie)
- new_beacon->wapi_offset =
- adapter->scan_table[beacon_idx].
- wapi_offset;
- if (new_beacon->bcn_ht_cap)
- new_beacon->ht_cap_offset =
- adapter->scan_table[beacon_idx].
- ht_cap_offset;
- if (new_beacon->bcn_ht_info)
- new_beacon->ht_info_offset =
- adapter->scan_table[beacon_idx].
- ht_info_offset;
- if (new_beacon->bcn_bss_co_2040)
- new_beacon->bss_co_2040_offset =
- adapter->scan_table[beacon_idx].
- bss_co_2040_offset;
- if (new_beacon->bcn_ext_cap)
- new_beacon->ext_cap_offset =
- adapter->scan_table[beacon_idx].
- ext_cap_offset;
- if (new_beacon->bcn_obss_scan)
- new_beacon->overlap_bss_offset =
- adapter->scan_table[beacon_idx].
- overlap_bss_offset;
- }
- /* Point the new entry to its permanent storage space */
- new_beacon->beacon_buf = bcn_store;
- mwifiex_update_beacon_buffer_ptrs(new_beacon);
- } else {
- /*
- * No existing beacon data exists for this entry, check to see
- * if we can fit it in the remaining space
- */
- if (adapter->bcn_buf_end + new_beacon->beacon_buf_size +
- SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf +
- sizeof(adapter->bcn_buf))) {
-
- /*
- * Copy the beacon buffer data from the local entry to
- * the adapter dev struct buffer space used to store
- * the raw beacon data for each entry in the scan table
- */
- memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf,
- new_beacon->beacon_buf_size);
-
- /* Update the beacon ptr to point to the table save
- area */
- new_beacon->beacon_buf = adapter->bcn_buf_end;
- new_beacon->beacon_buf_size_max =
- (new_beacon->beacon_buf_size +
- SCAN_BEACON_ENTRY_PAD);
-
- mwifiex_update_beacon_buffer_ptrs(new_beacon);
-
- /* Increment the end pointer by the size reserved */
- adapter->bcn_buf_end += new_beacon->beacon_buf_size_max;
-
- dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]"
- " sz=%03d, used = %04d, left = %04d\n",
- beacon_idx,
- new_beacon->beacon_buf_size,
- (int)(adapter->bcn_buf_end - adapter->bcn_buf),
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
- } else {
- /* No space for new beacon */
- dev_dbg(adapter->dev, "info: AppControl: no space for"
- " beacon (%d): %pM sz=%03d, left=%03d\n",
- beacon_idx, new_beacon->mac_address,
- new_beacon->beacon_buf_size,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
-
- /* Storage failure; clear storage records for this
- bcn */
- new_beacon->beacon_buf = NULL;
- new_beacon->beacon_buf_size = 0;
- new_beacon->beacon_buf_size_max = 0;
- new_beacon->bcn_wpa_ie = NULL;
- new_beacon->wpa_offset = 0;
- new_beacon->bcn_rsn_ie = NULL;
- new_beacon->rsn_offset = 0;
- new_beacon->bcn_wapi_ie = NULL;
- new_beacon->wapi_offset = 0;
- new_beacon->bcn_ht_cap = NULL;
- new_beacon->ht_cap_offset = 0;
- new_beacon->bcn_ht_info = NULL;
- new_beacon->ht_info_offset = 0;
- new_beacon->bcn_bss_co_2040 = NULL;
- new_beacon->bss_co_2040_offset = 0;
- new_beacon->bcn_ext_cap = NULL;
- new_beacon->ext_cap_offset = 0;
- new_beacon->bcn_obss_scan = NULL;
- new_beacon->overlap_bss_offset = 0;
- }
- }
-}
-
-/*
- * This function restores a beacon buffer of the current BSS descriptor.
- */
-static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *curr_bss =
- &priv->curr_bss_params.bss_descriptor;
- unsigned long flags;
-
- if (priv->curr_bcn_buf &&
- ((adapter->bcn_buf_end + priv->curr_bcn_size) <
- (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) {
- spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
-
- /* restore the current beacon buffer */
- memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf,
- priv->curr_bcn_size);
- curr_bss->beacon_buf = adapter->bcn_buf_end;
- curr_bss->beacon_buf_size = priv->curr_bcn_size;
- adapter->bcn_buf_end += priv->curr_bcn_size;
-
- /* adjust the pointers in the current BSS descriptor */
- if (curr_bss->bcn_wpa_ie)
- curr_bss->bcn_wpa_ie =
- (struct ieee_types_vendor_specific *)
- (curr_bss->beacon_buf +
- curr_bss->wpa_offset);
-
- if (curr_bss->bcn_rsn_ie)
- curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
- (curr_bss->beacon_buf +
- curr_bss->rsn_offset);
-
- if (curr_bss->bcn_ht_cap)
- curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
- (curr_bss->beacon_buf +
- curr_bss->ht_cap_offset);
-
- if (curr_bss->bcn_ht_info)
- curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
- (curr_bss->beacon_buf +
- curr_bss->ht_info_offset);
-
- if (curr_bss->bcn_bss_co_2040)
- curr_bss->bcn_bss_co_2040 =
- (u8 *) (curr_bss->beacon_buf +
- curr_bss->bss_co_2040_offset);
-
- if (curr_bss->bcn_ext_cap)
- curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
- curr_bss->ext_cap_offset);
-
- if (curr_bss->bcn_obss_scan)
- curr_bss->bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- (curr_bss->beacon_buf +
- curr_bss->overlap_bss_offset);
-
- spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
-
- dev_dbg(adapter->dev, "info: current beacon restored %d\n",
- priv->curr_bcn_size);
- } else {
- dev_warn(adapter->dev,
- "curr_bcn_buf not saved or bcn_buf has no space\n");
- }
-}
-
-/*
- * This function post processes the scan table after a new scan command has
- * completed.
- *
- * It inspects each entry of the scan table and tries to find an entry that
- * matches with our current associated/joined network from the scan. If
- * one is found, the stored copy of the BSS descriptor of our current network
- * is updated.
- *
- * It also debug dumps the current scan table contents after processing is over.
- */
-static void
-mwifiex_process_scan_results(struct mwifiex_private *priv)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- s32 j;
- u32 i;
- unsigned long flags;
-
- if (priv->media_connected) {
-
- j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params.
- bss_descriptor.ssid,
- priv->curr_bss_params.
- bss_descriptor.mac_address,
- priv->bss_mode);
-
- if (j >= 0) {
- spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
- priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
- priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ht_cap_offset =
- 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
- priv->curr_bss_params.bss_descriptor.ht_info_offset =
- 0;
- priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
- NULL;
- priv->curr_bss_params.bss_descriptor.
- bss_co_2040_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.
- bcn_obss_scan = NULL;
- priv->curr_bss_params.bss_descriptor.
- overlap_bss_offset = 0;
- priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
- priv->curr_bss_params.bss_descriptor.beacon_buf_size =
- 0;
- priv->curr_bss_params.bss_descriptor.
- beacon_buf_size_max = 0;
-
- dev_dbg(adapter->dev, "info: Found current ssid/bssid"
- " in list @ index #%d\n", j);
- /* Make a copy of current BSSID descriptor */
- memcpy(&priv->curr_bss_params.bss_descriptor,
- &adapter->scan_table[j],
- sizeof(priv->curr_bss_params.bss_descriptor));
-
- mwifiex_save_curr_bcn(priv);
- spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
-
- } else {
- mwifiex_restore_curr_bcn(priv);
- }
- }
-
- for (i = 0; i < adapter->num_in_scan_table; i++)
- dev_dbg(adapter->dev, "info: scan:(%02d) %pM "
- "RSSI[%03d], SSID[%s]\n",
- i, adapter->scan_table[i].mac_address,
- (s32) adapter->scan_table[i].rssi,
- adapter->scan_table[i].ssid.ssid);
-}
-
-/*
* This function converts radio type scan parameter to a band configuration
* to be used in join command.
*/
@@ -2072,175 +1288,6 @@ mwifiex_radio_type_to_band(u8 radio_type)
}
/*
- * This function deletes a specific indexed entry from the scan table.
- *
- * This also compacts the remaining entries and adjusts any buffering
- * of beacon/probe response data if needed.
- */
-static void
-mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 del_idx;
- u32 beacon_buf_adj;
- u8 *beacon_buf;
-
- /*
- * Shift the saved beacon buffer data for the scan table back over the
- * entry being removed. Update the end of buffer pointer. Save the
- * deleted buffer allocation size for pointer adjustments for entries
- * compacted after the deleted index.
- */
- beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max;
-
- dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer "
- "removal = %d bytes\n", table_idx, beacon_buf_adj);
-
- /* Check if the table entry had storage allocated for its beacon */
- if (beacon_buf_adj) {
- beacon_buf = adapter->scan_table[table_idx].beacon_buf;
-
- /*
- * Remove the entry's buffer space, decrement the table end
- * pointer by the amount we are removing
- */
- adapter->bcn_buf_end -= beacon_buf_adj;
-
- dev_dbg(adapter->dev, "info: scan: delete entry %d,"
- " compact data: %p <- %p (sz = %d)\n",
- table_idx, beacon_buf,
- beacon_buf + beacon_buf_adj,
- (int)(adapter->bcn_buf_end - beacon_buf));
-
- /*
- * Compact data storage. Copy all data after the deleted
- * entry's end address (beacon_buf + beacon_buf_adj) back
- * to the original start address (beacon_buf).
- *
- * Scan table entries affected by the move will have their
- * entry pointer adjusted below.
- *
- * Use memmove since the dest/src memory regions overlap.
- */
- memmove(beacon_buf, beacon_buf + beacon_buf_adj,
- adapter->bcn_buf_end - beacon_buf);
- }
-
- dev_dbg(adapter->dev,
- "info: Scan: Delete Entry %d, num_in_scan_table = %d\n",
- table_idx, adapter->num_in_scan_table);
-
- /* Shift all of the entries after the table_idx back by one, compacting
- the table and removing the requested entry */
- for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table;
- del_idx++) {
- /* Copy the next entry over this one */
- memcpy(adapter->scan_table + del_idx,
- adapter->scan_table + del_idx + 1,
- sizeof(struct mwifiex_bssdescriptor));
-
- /*
- * Adjust this entry's pointer to its beacon buffer based on
- * the removed/compacted entry from the deleted index. Don't
- * decrement if the buffer pointer is NULL (no data stored for
- * this entry).
- */
- if (adapter->scan_table[del_idx].beacon_buf) {
- adapter->scan_table[del_idx].beacon_buf -=
- beacon_buf_adj;
- if (adapter->scan_table[del_idx].bcn_wpa_ie)
- adapter->scan_table[del_idx].bcn_wpa_ie =
- (struct ieee_types_vendor_specific *)
- (adapter->scan_table[del_idx].
- beacon_buf +
- adapter->scan_table[del_idx].
- wpa_offset);
- if (adapter->scan_table[del_idx].bcn_rsn_ie)
- adapter->scan_table[del_idx].bcn_rsn_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[del_idx].
- beacon_buf +
- adapter->scan_table[del_idx].
- rsn_offset);
- if (adapter->scan_table[del_idx].bcn_wapi_ie)
- adapter->scan_table[del_idx].bcn_wapi_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- wapi_offset);
- if (adapter->scan_table[del_idx].bcn_ht_cap)
- adapter->scan_table[del_idx].bcn_ht_cap =
- (struct ieee80211_ht_cap *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- ht_cap_offset);
-
- if (adapter->scan_table[del_idx].bcn_ht_info)
- adapter->scan_table[del_idx].bcn_ht_info =
- (struct ieee80211_ht_info *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- ht_info_offset);
- if (adapter->scan_table[del_idx].bcn_bss_co_2040)
- adapter->scan_table[del_idx].bcn_bss_co_2040 =
- (u8 *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- bss_co_2040_offset);
- if (adapter->scan_table[del_idx].bcn_ext_cap)
- adapter->scan_table[del_idx].bcn_ext_cap =
- (u8 *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- ext_cap_offset);
- if (adapter->scan_table[del_idx].bcn_obss_scan)
- adapter->scan_table[del_idx].
- bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- overlap_bss_offset);
- }
- }
-
- /* The last entry is invalid now that it has been deleted or moved
- back */
- memset(adapter->scan_table + adapter->num_in_scan_table - 1,
- 0x00, sizeof(struct mwifiex_bssdescriptor));
-
- adapter->num_in_scan_table--;
-}
-
-/*
- * This function deletes all occurrences of a given SSID from the scan table.
- *
- * This iterates through the scan table and deletes all entries that match
- * the given SSID. It also compacts the remaining scan table entries.
- */
-static int
-mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *del_ssid)
-{
- s32 table_idx = -1;
-
- dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",
- del_ssid->ssid);
-
- /* If the requested SSID is found in the table, delete it. Then keep
- searching the table for multiple entires for the SSID until no
- more are found */
- while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL,
- NL80211_IFTYPE_UNSPECIFIED)) >= 0) {
- dev_dbg(priv->adapter->dev,
- "info: Scan: Delete SSID Entry: Found Idx = %d\n",
- table_idx);
- mwifiex_scan_delete_table_entry(priv, table_idx);
- }
-
- return table_idx == -1 ? -1 : 0;
-}
-
-/*
* This is an internal function used to start a scan based on an input
* configuration.
*
@@ -2248,8 +1295,8 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
* order to send the appropriate scan commands to firmware to populate or
* update the internal driver scan table.
*/
-int mwifiex_scan_networks(struct mwifiex_private *priv,
- const struct mwifiex_user_scan_cfg *user_scan_in)
+static int mwifiex_scan_networks(struct mwifiex_private *priv,
+ const struct mwifiex_user_scan_cfg *user_scan_in)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -2258,7 +1305,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
u32 buf_size;
struct mwifiex_chan_scan_param_set *scan_chan_list;
- u8 keep_previous_scan;
u8 filtered_scan;
u8 scan_current_chan_only;
u8 max_chan_per_scan;
@@ -2295,24 +1341,11 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
return -ENOMEM;
}
- keep_previous_scan = false;
-
mwifiex_scan_setup_scan_config(priv, user_scan_in,
&scan_cfg_out->config, &chan_list_out,
scan_chan_list, &max_chan_per_scan,
&filtered_scan, &scan_current_chan_only);
- if (user_scan_in)
- keep_previous_scan = user_scan_in->keep_previous_scan;
-
-
- if (!keep_previous_scan) {
- memset(adapter->scan_table, 0x00,
- sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
- adapter->num_in_scan_table = 0;
- adapter->bcn_buf_end = adapter->bcn_buf;
- }
-
ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
&scan_cfg_out->config, chan_list_out,
scan_chan_list);
@@ -2326,6 +1359,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
+ adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
} else {
@@ -2344,6 +1378,29 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
}
/*
+ * Sends IOCTL request to start a scan with user configurations.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ *
+ * Upon completion, it also generates a wireless event to notify
+ * applications.
+ */
+int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
+ struct mwifiex_user_scan_cfg *scan_req)
+{
+ int status;
+
+ priv->adapter->scan_wait_q_woken = false;
+
+ status = mwifiex_scan_networks(priv, scan_req);
+ if (!status)
+ status = mwifiex_wait_queue_complete(priv->adapter);
+
+ return status;
+}
+
+/*
* This function prepares a scan command to be sent to the firmware.
*
* This uses the scan command configuration sent to the command processing
@@ -2357,12 +1414,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
* - Setting command ID, and proper size
* - Ensuring correct endian-ness
*/
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+ struct mwifiex_scan_cmd_config *scan_cfg)
{
struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
- struct mwifiex_scan_cmd_config *scan_cfg;
-
- scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
/* Set fixed field variables in scan command */
scan_cmd->bss_mode = scan_cfg->bss_mode;
@@ -2381,6 +1436,113 @@ int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
}
/*
+ * This function checks compatibility of requested network with current
+ * driver settings.
+ */
+int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
+ struct mwifiex_bssdescriptor *bss_desc)
+{
+ int ret = -1;
+
+ if (!bss_desc)
+ return -1;
+
+ if ((mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
+ (u8) bss_desc->bss_band, (u16) bss_desc->channel))) {
+ switch (priv->bss_mode) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ ret = mwifiex_is_network_compatible(priv, bss_desc,
+ priv->bss_mode);
+ if (ret)
+ dev_err(priv->adapter->dev, "cannot find ssid "
+ "%s\n", bss_desc->ssid.ssid);
+ break;
+ default:
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+static int
+mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
+ s32 rssi, const u8 *ie_buf, size_t ie_len,
+ u16 beacon_period, u16 cap_info_bitmap, u8 band)
+{
+ struct mwifiex_bssdescriptor *bss_desc;
+ int ret;
+ unsigned long flags;
+ u8 *beacon_ie;
+
+ /* Allocate and fill new bss descriptor */
+ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
+ GFP_KERNEL);
+ if (!bss_desc) {
+ dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
+ return -ENOMEM;
+ }
+
+ beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
+ if (!beacon_ie) {
+ kfree(bss_desc);
+ dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
+ return -ENOMEM;
+ }
+
+ ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
+ ie_len, beacon_period,
+ cap_info_bitmap, band, bss_desc);
+ if (ret)
+ goto done;
+
+ ret = mwifiex_check_network_compatibility(priv, bss_desc);
+ if (ret)
+ goto done;
+
+ /* Update current bss descriptor parameters */
+ spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
+ priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
+ priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
+ priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
+ priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
+ priv->curr_bss_params.bss_descriptor.ht_cap_offset =
+ 0;
+ priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
+ priv->curr_bss_params.bss_descriptor.ht_info_offset =
+ 0;
+ priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
+ NULL;
+ priv->curr_bss_params.bss_descriptor.
+ bss_co_2040_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
+ priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
+ priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
+ priv->curr_bss_params.bss_descriptor.beacon_buf_size =
+ 0;
+
+ /* Make a copy of current BSSID descriptor */
+ memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
+ sizeof(priv->curr_bss_params.bss_descriptor));
+ mwifiex_save_curr_bcn(priv);
+ spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
+
+done:
+ kfree(bss_desc);
+ kfree(beacon_ie);
+ return 0;
+}
+
+static void mwifiex_free_bss_priv(struct cfg80211_bss *bss)
+{
+ kfree(bss->priv);
+}
+
+/*
* This function handles the command response of scan.
*
* The response buffer for the scan command has the following
@@ -2406,23 +1568,19 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmd_node;
struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
- struct mwifiex_bssdescriptor *bss_new_entry = NULL;
struct mwifiex_ie_types_data *tlv_data;
struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
u8 *bss_info;
u32 scan_resp_size;
u32 bytes_left;
- u32 num_in_table;
- u32 bss_idx;
u32 idx;
u32 tlv_buf_size;
- long long tsf_val;
struct mwifiex_chan_freq_power *cfp;
struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
struct chan_band_param_set *chan_band;
- u8 band;
u8 is_bgscan_resp;
unsigned long flags;
+ struct cfg80211_bss *bss;
is_bgscan_resp = (le16_to_cpu(resp->command)
== HostCmd_CMD_802_11_BG_SCAN_QUERY);
@@ -2432,11 +1590,11 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
scan_rsp = &resp->params.scan_resp;
- if (scan_rsp->number_of_sets > IW_MAX_AP) {
+ if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
scan_rsp->number_of_sets);
ret = -1;
- goto done;
+ goto check_next_scan;
}
bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
@@ -2449,7 +1607,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
"info: SCAN_RESP: returned %d APs before parsing\n",
scan_rsp->number_of_sets);
- num_in_table = adapter->num_in_scan_table;
bss_info = scan_rsp->bss_desc_and_tlv_buffer;
/*
@@ -2481,143 +1638,163 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
(struct mwifiex_ie_types_data **)
&chan_band_tlv);
- /*
- * Process each scan response returned (scan_rsp->number_of_sets).
- * Save the information in the bss_new_entry and then insert into the
- * driver scan table either as an update to an existing entry
- * or as an addition at the end of the table
- */
- bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor),
- GFP_KERNEL);
- if (!bss_new_entry) {
- dev_err(adapter->dev, " failed to alloc bss_new_entry\n");
- return -ENOMEM;
- }
-
for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
- /* Zero out the bss_new_entry we are about to store info in */
- memset(bss_new_entry, 0x00,
- sizeof(struct mwifiex_bssdescriptor));
-
- if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry,
- &bss_info,
- &bytes_left)) {
- /* Error parsing/interpreting scan response, skipped */
- dev_err(adapter->dev, "SCAN_RESP: "
- "mwifiex_interpret_bss_desc_with_ie "
- "returned ERROR\n");
- continue;
+ u8 bssid[ETH_ALEN];
+ s32 rssi;
+ const u8 *ie_buf;
+ size_t ie_len;
+ int channel = -1;
+ u64 network_tsf = 0;
+ u16 beacon_size = 0;
+ u32 curr_bcn_bytes;
+ u32 freq;
+ u16 beacon_period;
+ u16 cap_info_bitmap;
+ u8 *current_ptr;
+ struct mwifiex_bcn_param *bcn_param;
+
+ if (bytes_left >= sizeof(beacon_size)) {
+ /* Extract & convert beacon size from command buffer */
+ memcpy(&beacon_size, bss_info, sizeof(beacon_size));
+ bytes_left -= sizeof(beacon_size);
+ bss_info += sizeof(beacon_size);
+ }
+
+ if (!beacon_size || beacon_size > bytes_left) {
+ bss_info += bytes_left;
+ bytes_left = 0;
+ ret = -1;
+ goto check_next_scan;
}
- /* Process the data fields and IEs returned for this BSS */
- dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n",
- bss_new_entry->mac_address);
+ /* Initialize the current working beacon pointer for this BSS
+ * iteration */
+ current_ptr = bss_info;
- /* Search the scan table for the same bssid */
- for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
- if (memcmp(bss_new_entry->mac_address,
- adapter->scan_table[bss_idx].mac_address,
- sizeof(bss_new_entry->mac_address))) {
- continue;
+ /* Advance the return beacon pointer past the current beacon */
+ bss_info += beacon_size;
+ bytes_left -= beacon_size;
+
+ curr_bcn_bytes = beacon_size;
+
+ /*
+ * First 5 fields are bssid, RSSI, time stamp, beacon interval,
+ * and capability information
+ */
+ if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
+ dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
+ continue;
+ }
+ bcn_param = (struct mwifiex_bcn_param *)current_ptr;
+ current_ptr += sizeof(*bcn_param);
+ curr_bcn_bytes -= sizeof(*bcn_param);
+
+ memcpy(bssid, bcn_param->bssid, ETH_ALEN);
+
+ rssi = (s32) (bcn_param->rssi);
+ dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n",
+ rssi);
+
+ beacon_period = le16_to_cpu(bcn_param->beacon_period);
+
+ cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
+ dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
+ cap_info_bitmap);
+
+ /* Rest of the current buffer are IE's */
+ ie_buf = current_ptr;
+ ie_len = curr_bcn_bytes;
+ dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP"
+ " = %d\n", curr_bcn_bytes);
+
+ while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
+ u8 element_id, element_len;
+
+ element_id = *current_ptr;
+ element_len = *(current_ptr + 1);
+ if (curr_bcn_bytes < element_len +
+ sizeof(struct ieee_types_header)) {
+ dev_err(priv->adapter->dev, "%s: in processing"
+ " IE, bytes left < IE length\n",
+ __func__);
+ goto check_next_scan;
}
- /*
- * If the SSID matches as well, it is a
- * duplicate of this entry. Keep the bss_idx
- * set to this entry so we replace the old
- * contents in the table
- */
- if ((bss_new_entry->ssid.ssid_len
- == adapter->scan_table[bss_idx]. ssid.ssid_len)
- && (!memcmp(bss_new_entry->ssid.ssid,
- adapter->scan_table[bss_idx].ssid.ssid,
- bss_new_entry->ssid.ssid_len))) {
- dev_dbg(adapter->dev, "info: SCAN_RESP:"
- " duplicate of index: %d\n", bss_idx);
+ if (element_id == WLAN_EID_DS_PARAMS) {
+ channel = *(u8 *) (current_ptr +
+ sizeof(struct ieee_types_header));
break;
}
- }
- /*
- * If the bss_idx is equal to the number of entries in
- * the table, the new entry was not a duplicate; append
- * it to the scan table
- */
- if (bss_idx == num_in_table) {
- /* Range check the bss_idx, keep it limited to
- the last entry */
- if (bss_idx == IW_MAX_AP)
- bss_idx--;
- else
- num_in_table++;
+
+ current_ptr += element_len +
+ sizeof(struct ieee_types_header);
+ curr_bcn_bytes -= element_len +
+ sizeof(struct ieee_types_header);
}
/*
- * Save the beacon/probe response returned for later application
- * retrieval. Duplicate beacon/probe responses are updated if
- * possible
- */
- mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx,
- num_in_table, bss_new_entry);
- /*
* If the TSF TLV was appended to the scan results, save this
* entry's TSF value in the networkTSF field.The networkTSF is
* the firmware's TSF value at the time the beacon or probe
* response was received.
*/
- if (tsf_tlv) {
- memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE]
- , sizeof(tsf_val));
- memcpy(&bss_new_entry->network_tsf, &tsf_val,
- sizeof(bss_new_entry->network_tsf));
- }
- band = BAND_G;
- if (chan_band_tlv) {
- chan_band = &chan_band_tlv->chan_band_param[idx];
- band = mwifiex_radio_type_to_band(chan_band->radio_type
- & (BIT(0) | BIT(1)));
- }
+ if (tsf_tlv)
+ memcpy(&network_tsf,
+ &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+ sizeof(network_tsf));
+
+ if (channel != -1) {
+ struct ieee80211_channel *chan;
+ u8 band;
+
+ band = BAND_G;
+ if (chan_band_tlv) {
+ chan_band =
+ &chan_band_tlv->chan_band_param[idx];
+ band = mwifiex_radio_type_to_band(
+ chan_band->radio_type
+ & (BIT(0) | BIT(1)));
+ }
- /* Save the band designation for this entry for use in join */
- bss_new_entry->bss_band = band;
- cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
- (u8) bss_new_entry->bss_band,
- (u16)bss_new_entry->channel);
+ cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
+ priv, (u8)band, (u16)channel);
- if (cfp)
- bss_new_entry->freq = cfp->freq;
- else
- bss_new_entry->freq = 0;
+ freq = cfp ? cfp->freq : 0;
- /* Copy the locally created bss_new_entry to the scan table */
- memcpy(&adapter->scan_table[bss_idx], bss_new_entry,
- sizeof(adapter->scan_table[bss_idx]));
+ chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
- }
+ if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
+ bss = cfg80211_inform_bss(priv->wdev->wiphy,
+ chan, bssid, network_tsf,
+ cap_info_bitmap, beacon_period,
+ ie_buf, ie_len, rssi, GFP_KERNEL);
+ *(u8 *)bss->priv = band;
+ bss->free_priv = mwifiex_free_bss_priv;
- dev_dbg(adapter->dev,
- "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
- scan_rsp->number_of_sets,
- num_in_table - adapter->num_in_scan_table, num_in_table);
-
- /* Update the total number of BSSIDs in the scan table */
- adapter->num_in_scan_table = num_in_table;
+ if (priv->media_connected && !memcmp(bssid,
+ priv->curr_bss_params.bss_descriptor
+ .mac_address, ETH_ALEN))
+ mwifiex_update_curr_bss_params(priv,
+ bssid, rssi, ie_buf,
+ ie_len, beacon_period,
+ cap_info_bitmap, band);
+ }
+ } else {
+ dev_dbg(adapter->dev, "missing BSS channel IE\n");
+ }
+ }
+check_next_scan:
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
if (list_empty(&adapter->scan_pending_q)) {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
- /*
- * Process the resulting scan table:
- * - Remove any bad ssids
- * - Update our current BSS information from scan data
- */
- mwifiex_process_scan_results(priv);
/* Need to indicate IOCTL complete */
if (adapter->curr_cmd->wait_q_enabled) {
adapter->cmd_wait_q.status = 0;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
}
if (priv->report_scan_result)
priv->report_scan_result = false;
@@ -2637,8 +1814,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
}
-done:
- kfree((u8 *) bss_new_entry);
return ret;
}
@@ -2665,141 +1840,6 @@ int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
}
/*
- * This function finds a SSID in the scan table.
- *
- * A BSSID may optionally be provided to qualify the SSID.
- * For non-Auto mode, further check is made to make sure the
- * BSS found in the scan table is compatible with the current
- * settings of the driver.
- */
-s32
-mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *ssid, u8 *bssid,
- u32 mode)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- s32 net = -1, j;
- u8 best_rssi = 0;
- u32 i;
-
- dev_dbg(adapter->dev, "info: num of entries in table = %d\n",
- adapter->num_in_scan_table);
-
- /*
- * Loop through the table until the maximum is reached or until a match
- * is found based on the bssid field comparison
- */
- for (i = 0;
- i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0));
- i++) {
- if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) &&
- (!bssid
- || !memcmp(adapter->scan_table[i].mac_address, bssid,
- ETH_ALEN))
- &&
- (mwifiex_get_cfp_by_band_and_channel_from_cfg80211
- (priv, (u8) adapter->scan_table[i].bss_band,
- (u16) adapter->scan_table[i].channel))) {
- switch (mode) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- j = mwifiex_is_network_compatible(priv, i,
- mode);
-
- if (j >= 0) {
- if (SCAN_RSSI
- (adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->
- scan_table
- [i].rssi);
- net = i;
- }
- } else {
- if (net == -1)
- net = j;
- }
- break;
- case NL80211_IFTYPE_UNSPECIFIED:
- default:
- /*
- * Do not check compatibility if the mode
- * requested is Auto/Unknown. Allows generic
- * find to work without verifying against the
- * Adapter security settings
- */
- if (SCAN_RSSI(adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->
- scan_table[i].rssi);
- net = i;
- }
- break;
- }
- }
- }
-
- return net;
-}
-
-/*
- * This function finds a specific compatible BSSID in the scan list.
- *
- * This function loops through the scan table looking for a compatible
- * match. If a BSSID matches, but the BSS is found to be not compatible
- * the function ignores it and continues to search through the rest of
- * the entries in case there is an AP with multiple SSIDs assigned to
- * the same BSSID.
- */
-s32
-mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
- u32 mode)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- s32 net = -1;
- u32 i;
-
- if (!bssid)
- return -1;
-
- dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n",
- adapter->num_in_scan_table);
-
- /*
- * Look through the scan table for a compatible match. The ret return
- * variable will be equal to the index in the scan table (greater
- * than zero) if the network is compatible. The loop will continue
- * past a matched bssid that is not compatible in case there is an
- * AP with multiple SSIDs assigned to the same BSSID
- */
- for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) {
- if (!memcmp
- (adapter->scan_table[i].mac_address, bssid, ETH_ALEN)
- && mwifiex_get_cfp_by_band_and_channel_from_cfg80211
- (priv,
- (u8) adapter->
- scan_table[i].
- bss_band,
- (u16) adapter->
- scan_table[i].
- channel)) {
- switch (mode) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- net = mwifiex_is_network_compatible(priv, i,
- mode);
- break;
- default:
- net = i;
- break;
- }
- }
- }
-
- return net;
-}
-
-/*
* This function inserts scan command node to the scan pending queue.
*/
void
@@ -2810,48 +1850,13 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
unsigned long flags;
cmd_node->wait_q_enabled = true;
+ cmd_node->condition = &adapter->scan_wait_q_woken;
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
}
/*
- * This function finds an AP with specific ssid in the scan list.
- */
-int mwifiex_find_best_network(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *req_ssid_bssid)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *req_bss;
- s32 i;
-
- memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
-
- i = mwifiex_find_best_network_in_list(priv);
-
- if (i >= 0) {
- req_bss = &adapter->scan_table[i];
- memcpy(&req_ssid_bssid->ssid, &req_bss->ssid,
- sizeof(struct mwifiex_802_11_ssid));
- memcpy((u8 *) &req_ssid_bssid->bssid,
- (u8 *) &req_bss->mac_address, ETH_ALEN);
-
- /* Make sure we are in the right mode */
- if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
- priv->bss_mode = req_bss->bss_mode;
- }
-
- if (!req_ssid_bssid->ssid.ssid_len)
- return -1;
-
- dev_dbg(adapter->dev, "info: Best network found = [%s], "
- "[%pM]\n", req_ssid_bssid->ssid.ssid,
- req_ssid_bssid->bssid);
-
- return 0;
-}
-
-/*
* This function sends a scan command for all available channels to the
* firmware, filtered on a specific SSID.
*/
@@ -2876,8 +1881,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
return ret;
}
- mwifiex_scan_delete_ssid_table_entry(priv, req_ssid);
-
scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
if (!scan_cfg) {
dev_err(adapter->dev, "failed to alloc scan_cfg\n");
@@ -2886,7 +1889,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
req_ssid->ssid_len);
- scan_cfg->keep_previous_scan = true;
ret = mwifiex_scan_networks(priv, scan_cfg);
@@ -2915,7 +1917,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
}
priv->scan_pending_on_block = true;
- priv->adapter->cmd_wait_q.condition = false;
+ priv->adapter->scan_wait_q_woken = false;
if (req_ssid && req_ssid->ssid_len != 0)
/* Specific SSID scan */
@@ -2999,7 +2001,7 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
priv->curr_bcn_size = curr_bss->beacon_buf_size;
kfree(priv->curr_bcn_buf);
- priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size,
+ priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
GFP_KERNEL);
if (!priv->curr_bcn_buf) {
dev_err(priv->adapter->dev,
@@ -3012,6 +2014,39 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
curr_bss->beacon_buf_size);
dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
priv->curr_bcn_size);
+
+ curr_bss->beacon_buf = priv->curr_bcn_buf;
+
+ /* adjust the pointers in the current BSS descriptor */
+ if (curr_bss->bcn_wpa_ie)
+ curr_bss->bcn_wpa_ie =
+ (struct ieee_types_vendor_specific *)
+ (curr_bss->beacon_buf +
+ curr_bss->wpa_offset);
+
+ if (curr_bss->bcn_rsn_ie)
+ curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
+ (curr_bss->beacon_buf +
+ curr_bss->rsn_offset);
+
+ if (curr_bss->bcn_ht_cap)
+ curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
+ (curr_bss->beacon_buf +
+ curr_bss->ht_cap_offset);
+
+ if (curr_bss->bcn_ht_info)
+ curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
+ (curr_bss->beacon_buf +
+ curr_bss->ht_info_offset);
+
+ if (curr_bss->bcn_bss_co_2040)
+ curr_bss->bcn_bss_co_2040 =
+ (u8 *) (curr_bss->beacon_buf +
+ curr_bss->bss_co_2040_offset);
+
+ if (curr_bss->bcn_ext_cap)
+ curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
+ curr_bss->ext_cap_offset);
}
/*
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 61e152d..72b253d2 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -31,10 +31,27 @@
#define SDIO_VERSION "1.0"
+/* The mwifiex_sdio_remove() callback function is called when
+ * user removes this module from kernel space or ejects
+ * the card from the slot. The driver handles these 2 cases
+ * differently.
+ * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
+ * HS_CANCEL etc.) are sent to the firmware.
+ * If the card is removed, there is no need to send these command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
static struct mwifiex_if_ops sdio_ops;
static struct semaphore add_remove_card_sem;
+static int mwifiex_sdio_resume(struct device *dev);
+
/*
* SDIO probe.
*
@@ -72,7 +89,8 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
return -EIO;
}
- if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops)) {
+ if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
+ MWIFIEX_SDIO)) {
pr_err("%s: add card failed\n", __func__);
kfree(card);
sdio_claim_host(func);
@@ -93,17 +111,39 @@ static void
mwifiex_sdio_remove(struct sdio_func *func)
{
struct sdio_mmc_card *card;
+ struct mwifiex_adapter *adapter;
+ int i;
pr_debug("info: SDIO func num=%d\n", func->num);
- if (func) {
- card = sdio_get_drvdata(func);
- if (card) {
- mwifiex_remove_card(card->adapter,
- &add_remove_card_sem);
- kfree(card);
- }
+ card = sdio_get_drvdata(func);
+ if (!card)
+ return;
+
+ adapter = card->adapter;
+ if (!adapter || !adapter->priv_num)
+ return;
+
+ if (user_rmmod) {
+ if (adapter->is_suspended)
+ mwifiex_sdio_resume(adapter->dev);
+
+ for (i = 0; i < adapter->priv_num; i++)
+ if ((GET_BSS_ROLE(adapter->priv[i]) ==
+ MWIFIEX_BSS_ROLE_STA) &&
+ adapter->priv[i]->media_connected)
+ mwifiex_deauthenticate(adapter->priv[i], NULL);
+
+ mwifiex_disable_auto_ds(mwifiex_get_priv(adapter,
+ MWIFIEX_BSS_ROLE_ANY));
+
+ mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+ MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_FUNC_SHUTDOWN);
}
+
+ mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+ kfree(card);
}
/*
@@ -792,7 +832,7 @@ done:
* The winner interface is also determined by this function.
*/
static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
- u32 poll_num, int *winner)
+ u32 poll_num)
{
int ret = 0;
u16 firmware_stat;
@@ -804,7 +844,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat);
if (ret)
continue;
- if (firmware_stat == FIRMWARE_READY) {
+ if (firmware_stat == FIRMWARE_READY_SDIO) {
ret = 0;
break;
} else {
@@ -813,15 +853,15 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
}
}
- if (winner && ret) {
+ if (ret) {
if (mwifiex_read_reg
(adapter, CARD_FW_STATUS0_REG, &winner_status))
winner_status = 0;
if (winner_status)
- *winner = 0;
+ adapter->winner = 0;
else
- *winner = 1;
+ adapter->winner = 1;
}
return ret;
}
@@ -896,7 +936,10 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
struct sk_buff *skb, u32 upld_typ)
{
u8 *cmd_buf;
+ __le16 *curr_ptr = (__le16 *)skb->data;
+ u16 pkt_len = le16_to_cpu(*curr_ptr);
+ skb_trim(skb, pkt_len);
skb_pull(skb, INTF_HEADER_LEN);
switch (upld_typ) {
@@ -1284,7 +1327,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
if (!(card->mp_wr_bitmap &
(1 << card->curr_wr_port))
|| !MP_TX_AGGR_BUF_HAS_ROOM(
- card, next_pkt_len))
+ card, pkt_len + next_pkt_len))
f_send_aggr_buf = 1;
} else {
/* No room in Aggr buf, send it */
@@ -1375,7 +1418,7 @@ tx_curr_single:
* the type. The firmware handles the packets based upon this set type.
*/
static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
- u8 type, u8 *payload, u32 pkt_len,
+ u8 type, struct sk_buff *skb,
struct mwifiex_tx_param *tx_param)
{
struct sdio_mmc_card *card = adapter->card;
@@ -1383,6 +1426,8 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
u32 buf_block_len;
u32 blk_size;
u8 port = CTRL_PORT;
+ u8 *payload = (u8 *)skb->data;
+ u32 pkt_len = skb->len;
/* Allocate buffer and copy payload */
blk_size = MWIFIEX_SDIO_BLOCK_SIZE;
@@ -1532,6 +1577,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
sdio_set_drvdata(func, card);
adapter->dev = &func->dev;
+ strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
return 0;
@@ -1553,7 +1599,6 @@ disable_func:
* the first interrupt got from bootloader
* - Disable host interrupt mask register
* - Get SDIO port
- * - Get revision ID
* - Initialize SDIO variables in card
* - Allocate MP registers
* - Allocate MPA Tx and Rx buffers
@@ -1577,10 +1622,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
/* Get SDIO ioport */
mwifiex_init_sdio_ioport(adapter);
- /* Get revision ID */
-#define REV_ID_REG 0x5c
- mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id);
-
/* Initialize SDIO variables in card */
card->mp_rd_bitmap = 0;
card->mp_wr_bitmap = 0;
@@ -1688,6 +1729,8 @@ static struct mwifiex_if_ops sdio_ops = {
/* SDIO specific */
.update_mp_end_port = mwifiex_update_mp_end_port,
.cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
+ .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
+ .event_complete = mwifiex_sdio_event_complete,
};
/*
@@ -1701,6 +1744,9 @@ mwifiex_sdio_init_module(void)
{
sema_init(&add_remove_card_sem, 1);
+ /* Clear the flag in case user removes the card. */
+ user_rmmod = 0;
+
return sdio_register_driver(&mwifiex_sdio);
}
@@ -1716,32 +1762,12 @@ mwifiex_sdio_init_module(void)
static void
mwifiex_sdio_cleanup_module(void)
{
- struct mwifiex_adapter *adapter = g_adapter;
- int i;
-
- if (down_interruptible(&add_remove_card_sem))
- goto exit_sem_err;
-
- if (!adapter || !adapter->priv_num)
- goto exit;
-
- if (adapter->is_suspended)
- mwifiex_sdio_resume(adapter->dev);
-
- for (i = 0; i < adapter->priv_num; i++)
- if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) &&
- adapter->priv[i]->media_connected)
- mwifiex_deauthenticate(adapter->priv[i], NULL);
-
- if (!adapter->surprise_removed)
- mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
- MWIFIEX_BSS_ROLE_ANY),
- MWIFIEX_FUNC_SHUTDOWN);
+ if (!down_interruptible(&add_remove_card_sem))
+ up(&add_remove_card_sem);
-exit:
- up(&add_remove_card_sem);
+ /* Set the flag as user is removing this module. */
+ user_rmmod = 1;
-exit_sem_err:
sdio_unregister_driver(&mwifiex_sdio);
}
@@ -1752,4 +1778,4 @@ MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
MODULE_VERSION(SDIO_VERSION);
MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("sd8787.bin");
+MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 4e97e90..3f71180 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -28,6 +28,8 @@
#include "main.h"
+#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
+
#define BLOCK_MODE 1
#define BYTE_MODE 0
@@ -52,10 +54,10 @@
#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8
-#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (4096) /* 4K */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (8192) /* 8K */
/* Multi port RX aggregation buffer size */
-#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (4096) /* 4K */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (16384) /* 16K */
/* Misc. Config Register : Auto Re-enable interrupts */
#define AUTO_RE_ENABLE_INT BIT(4)
@@ -167,9 +169,6 @@
/* Rx unit register */
#define CARD_RX_UNIT_REG 0x63
-/* Event header len w/o 4 bytes of interface header */
-#define MWIFIEX_EVENT_HEADER_LEN 4
-
/* Max retry number of CMD53 write */
#define MAX_WRITE_IOMEM_RETRY 2
@@ -302,4 +301,25 @@ struct sdio_mmc_card {
struct mwifiex_sdio_mpa_tx mpa_tx;
struct mwifiex_sdio_mpa_rx mpa_rx;
};
+
+/*
+ * .cmdrsp_complete handler
+ */
+static inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter,
+ struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+ return 0;
+}
+
+/*
+ * .event_complete handler
+ */
+static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter,
+ struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+ return 0;
+}
+
#endif /* _MWIFIEX_SDIO_H */
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 8af3a78..ea6518d 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -67,10 +67,9 @@ mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,
*/
static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *action)
{
struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
- u16 action = *((u16 *) data_buf);
if (cmd_action != HostCmd_ACT_GEN_SET) {
dev_err(priv->adapter->dev,
@@ -81,7 +80,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
cmd->size =
cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
- mac_ctrl->action = cpu_to_le16(action);
+ mac_ctrl->action = cpu_to_le16(*action);
return 0;
}
@@ -104,10 +103,9 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, u32 cmd_oid,
- void *data_buf)
+ u32 *ul_temp)
{
struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
- u32 ul_temp;
dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
@@ -127,9 +125,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *((u32 *) data_buf);
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -139,9 +136,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *((u32 *) data_buf);
*(__le16 *) (snmp_mib->value) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -152,9 +148,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = (*(u32 *) data_buf);
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -164,9 +159,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *(u32 *) data_buf;
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -209,13 +203,11 @@ mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
*/
static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *pbitmap_rates)
{
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
struct mwifiex_rate_drop_pattern *rate_drop;
- u16 *pbitmap_rates = (u16 *) data_buf;
-
u32 i;
cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
@@ -272,10 +264,10 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action,
+ struct host_cmd_ds_txpwr_cfg *txp)
{
struct mwifiex_types_power_group *pg_tlv;
- struct host_cmd_ds_txpwr_cfg *txp;
struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
@@ -283,12 +275,11 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
- txp = (struct host_cmd_ds_txpwr_cfg *) data_buf;
if (txp->mode) {
pg_tlv = (struct mwifiex_types_power_group
- *) ((unsigned long) data_buf +
+ *) ((unsigned long) txp +
sizeof(struct host_cmd_ds_txpwr_cfg));
- memmove(cmd_txp_cfg, data_buf,
+ memmove(cmd_txp_cfg, txp,
sizeof(struct host_cmd_ds_txpwr_cfg) +
sizeof(struct mwifiex_types_power_group) +
pg_tlv->length);
@@ -300,8 +291,7 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
sizeof(struct mwifiex_types_power_group) +
pg_tlv->length);
} else {
- memmove(cmd_txp_cfg, data_buf,
- sizeof(struct host_cmd_ds_txpwr_cfg));
+ memmove(cmd_txp_cfg, txp, sizeof(*txp));
}
cmd_txp_cfg->action = cpu_to_le16(cmd_action);
break;
@@ -322,22 +312,23 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
* (as required)
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd,
- u16 cmd_action,
- struct mwifiex_hs_config_param *data_buf)
+static int
+mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_hs_config_param *hscfg_param)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
u16 hs_activate = false;
- if (data_buf == NULL)
+ if (!hscfg_param)
/* New Activate command */
hs_activate = true;
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
if (!hs_activate &&
- (data_buf->conditions
+ (hscfg_param->conditions
!= cpu_to_le32(HOST_SLEEP_CFG_CANCEL))
&& ((adapter->arp_filter_size > 0)
&& (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
@@ -359,9 +350,9 @@ static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
} else {
hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
- hs_cfg->params.hs_config.conditions = data_buf->conditions;
- hs_cfg->params.hs_config.gpio = data_buf->gpio;
- hs_cfg->params.hs_config.gap = data_buf->gap;
+ hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
+ hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
+ hs_cfg->params.hs_config.gap = hscfg_param->gap;
dev_dbg(adapter->dev,
"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
hs_cfg->params.hs_config.conditions,
@@ -405,11 +396,11 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
* - Setting MAC multicast address
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+static int
+mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_multicast_list *mcast_list)
{
- struct mwifiex_multicast_list *mcast_list =
- (struct mwifiex_multicast_list *) data_buf;
struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
@@ -435,7 +426,7 @@ static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
*/
static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ u8 *mac)
{
struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
@@ -444,7 +435,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
+ S_DS_GEN);
/* Set AP MAC address */
- memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN);
+ memcpy(deauth->mac_addr, mac, ETH_ALEN);
dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr);
@@ -543,15 +534,14 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
* encryption (TKIP, AES) (as required)
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd,
- u16 cmd_action,
- u32 cmd_oid, void *data_buf)
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action, u32 cmd_oid,
+ struct mwifiex_ds_encrypt_key *enc_key)
{
struct host_cmd_ds_802_11_key_material *key_material =
&cmd->params.key_material;
- struct mwifiex_ds_encrypt_key *enc_key =
- (struct mwifiex_ds_encrypt_key *) data_buf;
u16 key_param_len = 0;
int ret = 0;
const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -741,7 +731,7 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
*/
static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *channel)
{
struct host_cmd_ds_802_11_rf_channel *rf_chan =
&cmd->params.rf_channel;
@@ -759,7 +749,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
rf_type = le16_to_cpu(rf_chan->rf_type);
SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset);
- rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf));
+ rf_chan->current_channel = cpu_to_le16(*channel);
}
rf_chan->action = cpu_to_le16(cmd_action);
return 0;
@@ -774,11 +764,10 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *enable)
{
struct host_cmd_ds_802_11_ibss_status *ibss_coal =
&(cmd->params.ibss_coalescing);
- u16 enable = 0;
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
@@ -788,9 +777,10 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
- if (data_buf != NULL)
- enable = *(u16 *) data_buf;
- ibss_coal->enable = cpu_to_le16(enable);
+ if (enable)
+ ibss_coal->enable = cpu_to_le16(*enable);
+ else
+ ibss_coal->enable = 0;
break;
/* In other case.. Nothing to do */
@@ -822,9 +812,8 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
u16 cmd_action, void *data_buf)
{
- struct mwifiex_ds_reg_rw *reg_rw;
+ struct mwifiex_ds_reg_rw *reg_rw = data_buf;
- reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
switch (le16_to_cpu(cmd->command)) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
@@ -893,8 +882,7 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
}
case HostCmd_CMD_802_11_EEPROM_ACCESS:
{
- struct mwifiex_ds_read_eeprom *rd_eeprom =
- (struct mwifiex_ds_read_eeprom *) data_buf;
+ struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
(struct host_cmd_ds_802_11_eeprom_access *)
&cmd->params.eeprom;
@@ -914,6 +902,59 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
}
/*
+ * This function prepares command to set PCI-Express
+ * host buffer configuration
+ *
+ * Preparation includes -
+ * - Setting command ID, action and proper size
+ * - Setting host buffer configuration
+ * - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd, u16 action)
+{
+ struct host_cmd_ds_pcie_details *host_spec =
+ &cmd->params.pcie_host_spec;
+ struct pcie_service_card *card = priv->adapter->card;
+ phys_addr_t *buf_pa;
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS);
+ cmd->size = cpu_to_le16(sizeof(struct
+ host_cmd_ds_pcie_details) + S_DS_GEN);
+ cmd->result = 0;
+
+ memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details));
+
+ if (action == HostCmd_ACT_GEN_SET) {
+ /* Send the ring base addresses and count to firmware */
+ host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase);
+ host_spec->txbd_addr_hi =
+ (u32)(((u64)card->txbd_ring_pbase)>>32);
+ host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD;
+ host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase);
+ host_spec->rxbd_addr_hi =
+ (u32)(((u64)card->rxbd_ring_pbase)>>32);
+ host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD;
+ host_spec->evtbd_addr_lo =
+ (u32)(card->evtbd_ring_pbase);
+ host_spec->evtbd_addr_hi =
+ (u32)(((u64)card->evtbd_ring_pbase)>>32);
+ host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD;
+ if (card->sleep_cookie) {
+ buf_pa = MWIFIEX_SKB_PACB(card->sleep_cookie);
+ host_spec->sleep_cookie_addr_lo = (u32) *buf_pa;
+ host_spec->sleep_cookie_addr_hi =
+ (u32) (((u64)*buf_pa) >> 32);
+ dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: "
+ "0x%x\n", host_spec->sleep_cookie_addr_lo);
+ }
+ }
+
+ return 0;
+}
+
+/*
* This function prepares the commands before sending them to the firmware.
*
* This is a generic function which calls specific command preparation
@@ -923,8 +964,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid,
void *data_buf, void *cmd_buf)
{
- struct host_cmd_ds_command *cmd_ptr =
- (struct host_cmd_ds_command *) cmd_buf;
+ struct host_cmd_ds_command *cmd_ptr = cmd_buf;
int ret = 0;
/* Prepare command */
@@ -1092,6 +1132,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
host_cmd_ds_set_bss_mode) + S_DS_GEN);
ret = 0;
break;
+ case HostCmd_CMD_PCIE_DESC_DETAILS:
+ ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action);
+ break;
default:
dev_err(priv->adapter->dev,
"PREP_CMD: unknown cmd- %#x\n", cmd_no);
@@ -1108,6 +1151,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
* working state.
*
* The following commands are issued sequentially -
+ * - Set PCI-Express host buffer configuration (PCIE only)
* - Function init (for first interface only)
* - Read MAC address (for first interface only)
* - Reconfigure Tx buffer size (for first interface only)
@@ -1126,8 +1170,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
struct mwifiex_ds_auto_ds auto_ds;
enum state_11d_t state_11d;
+ struct mwifiex_ds_11n_tx_cfg tx_cfg;
if (first_sta) {
+ if (priv->adapter->iface_type == MWIFIEX_PCIE) {
+ ret = mwifiex_send_cmd_async(priv,
+ HostCmd_CMD_PCIE_DESC_DETAILS,
+ HostCmd_ACT_GEN_SET, 0, NULL);
+ if (ret)
+ return -1;
+ }
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT,
HostCmd_ACT_GEN_SET, 0, NULL);
@@ -1181,7 +1233,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
/* Send request to firmware */
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
HostCmd_ACT_GEN_SET, 0,
- (void *) &amsdu_aggr_ctrl);
+ &amsdu_aggr_ctrl);
if (ret)
return -1;
/* MAC Control must be the last command in init_fw */
@@ -1211,8 +1263,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
if (ret)
dev_err(priv->adapter->dev, "11D: failed to enable 11D\n");
+ /* Send cmd to FW to configure 11n specific configuration
+ * (Short GI, Channel BW, Green field support etc.) for transmit
+ */
+ tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG;
+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_CFG,
+ HostCmd_ACT_GEN_SET, 0, &tx_cfg);
+
/* set last_init_cmd */
- priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB;
+ priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG;
ret = -EINPROGRESS;
return ret;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index d08f764..7a16b0c 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -120,11 +120,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
*/
static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_get_signal *signal)
{
struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
&resp->params.rssi_info_rsp;
- struct mwifiex_ds_get_signal *signal;
priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@@ -139,9 +138,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
/* Need to indicate IOCTL complete */
- if (data_buf) {
- signal = (struct mwifiex_ds_get_signal *) data_buf;
- memset(signal, 0, sizeof(struct mwifiex_ds_get_signal));
+ if (signal) {
+ memset(signal, 0, sizeof(*signal));
signal->selector = ALL_RSSI_INFO_MASK;
@@ -185,7 +183,7 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
*/
static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ u32 *data_buf)
{
struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
u16 oid = le16_to_cpu(smib->oid);
@@ -198,7 +196,7 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
if (query_type == HostCmd_ACT_GEN_GET) {
ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
if (data_buf)
- *(u32 *)data_buf = ul_temp;
+ *data_buf = ul_temp;
switch (oid) {
case FRAG_THRESH_I:
dev_dbg(priv->adapter->dev,
@@ -228,14 +226,12 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
*/
static int mwifiex_ret_get_log(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_get_stats *stats)
{
struct host_cmd_ds_802_11_get_log *get_log =
(struct host_cmd_ds_802_11_get_log *) &resp->params.get_log;
- struct mwifiex_ds_get_stats *stats;
- if (data_buf) {
- stats = (struct mwifiex_ds_get_stats *) data_buf;
+ if (stats) {
stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
stats->failed = le32_to_cpu(get_log->failed);
stats->retry = le32_to_cpu(get_log->retry);
@@ -278,9 +274,8 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv,
*/
static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_rate_cfg *ds_rate)
{
- struct mwifiex_rate_cfg *ds_rate;
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
struct mwifiex_ie_types_header *head;
@@ -329,8 +324,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
- if (data_buf) {
- ds_rate = (struct mwifiex_rate_cfg *) data_buf;
+ if (ds_rate) {
if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
if (priv->is_data_rate_auto) {
ds_rate->is_rate_auto = 1;
@@ -413,8 +407,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
* and saving the current Tx power level in driver.
*/
static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
- struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct host_cmd_ds_command *resp)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
@@ -631,7 +624,7 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
*/
static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ u16 *data_buf)
{
struct host_cmd_ds_802_11_rf_channel *rf_channel =
&resp->params.rf_channel;
@@ -644,8 +637,9 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
/* Update the channel again */
priv->curr_bss_params.bss_descriptor.channel = new_channel;
}
+
if (data_buf)
- *((u16 *)data_buf) = new_channel;
+ *data_buf = new_channel;
return 0;
}
@@ -658,13 +652,11 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
*/
static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct host_cmd_ds_version_ext *version_ext)
{
struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
- struct host_cmd_ds_version_ext *version_ext;
- if (data_buf) {
- version_ext = (struct host_cmd_ds_version_ext *)data_buf;
+ if (version_ext) {
version_ext->version_str_sel = ver_ext->version_str_sel;
memcpy(version_ext->version_str, ver_ext->version_str,
sizeof(char) * 128);
@@ -686,8 +678,8 @@ static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
struct mwifiex_ds_read_eeprom *eeprom;
if (data_buf) {
- reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
- eeprom = (struct mwifiex_ds_read_eeprom *) data_buf;
+ reg_rw = data_buf;
+ eeprom = data_buf;
switch (type) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
@@ -825,13 +817,11 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
* This is a generic function, which calls command specific
* response handlers based on the command ID.
*/
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
- u16 cmdresp_no, void *cmd_buf)
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
+ struct host_cmd_ds_command *resp)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
- struct host_cmd_ds_command *resp =
- (struct host_cmd_ds_command *) cmd_buf;
void *data_buf = adapter->curr_cmd->data_buf;
/* If the command is not successful, cleanup and return failure */
@@ -865,7 +855,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
"info: CMD_RESP: BG_SCAN result is ready!\n");
break;
case HostCmd_CMD_TXPWR_CFG:
- ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf);
+ ret = mwifiex_ret_tx_power_cfg(priv, resp);
break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
@@ -962,6 +952,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
case HostCmd_CMD_11N_CFG:
ret = mwifiex_ret_11n_cfg(resp, data_buf);
break;
+ case HostCmd_CMD_PCIE_DESC_DETAILS:
+ break;
default:
dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
resp->command);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index fc265ca..f204810 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -130,8 +130,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
/* Reset wireless stats signal info */
- priv->w_stats.qual.level = 0;
- priv->w_stats.qual.noise = 0;
+ priv->qual_level = 0;
+ priv->qual_noise = 0;
}
/*
@@ -299,11 +299,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
case EVENT_BG_SCAN_REPORT:
dev_dbg(adapter->dev, "event: BGS_REPORT\n");
- /* Clear the previous scan result */
- memset(adapter->scan_table, 0x00,
- sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
- adapter->num_in_scan_table = 0;
- adapter->bcn_buf_end = adapter->bcn_buf;
ret = mwifiex_send_cmd_async(priv,
HostCmd_CMD_802_11_BG_SCAN_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index a677e7b..5c3c62d 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -53,8 +53,14 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
*/
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
{
- bool cancel_flag = false;
- int status = adapter->cmd_wait_q.status;
+ int status;
+ struct cmd_ctrl_node *cmd_queued;
+
+ if (!adapter->cmd_queued)
+ return 0;
+
+ cmd_queued = adapter->cmd_queued;
+ adapter->cmd_queued = NULL;
dev_dbg(adapter->dev, "cmd pending\n");
atomic_inc(&adapter->cmd_pending);
@@ -63,15 +69,14 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
queue_work(adapter->workqueue, &adapter->main_work);
/* Wait for completion */
- wait_event_interruptible(adapter->cmd_wait_q.wait,
- adapter->cmd_wait_q.condition);
- if (!adapter->cmd_wait_q.condition)
- cancel_flag = true;
-
- if (cancel_flag) {
- mwifiex_cancel_pending_ioctl(adapter);
- dev_dbg(adapter->dev, "cmd cancel\n");
+ status = wait_event_interruptible(adapter->cmd_wait_q.wait,
+ *(cmd_queued->condition));
+ if (status) {
+ dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
+ return status;
}
+
+ status = adapter->cmd_wait_q.status;
adapter->cmd_wait_q.status = 0;
return status;
@@ -133,90 +138,150 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
}
/*
+ * This function fills bss descriptor structure using provided
+ * information.
+ */
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+ u8 *bssid, s32 rssi, u8 *ie_buf,
+ size_t ie_len, u16 beacon_period,
+ u16 cap_info_bitmap, u8 band,
+ struct mwifiex_bssdescriptor *bss_desc)
+{
+ int ret;
+
+ memcpy(bss_desc->mac_address, bssid, ETH_ALEN);
+ bss_desc->rssi = rssi;
+ bss_desc->beacon_buf = ie_buf;
+ bss_desc->beacon_buf_size = ie_len;
+ bss_desc->beacon_period = beacon_period;
+ bss_desc->cap_info_bitmap = cap_info_bitmap;
+ bss_desc->bss_band = band;
+ if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
+ dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
+ bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
+ } else {
+ bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
+ }
+ if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
+ bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
+ else
+ bss_desc->bss_mode = NL80211_IFTYPE_STATION;
+
+ ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc,
+ ie_buf, ie_len);
+
+ return ret;
+}
+
+/*
* In Ad-Hoc mode, the IBSS is created if not found in scan list.
* In both Ad-Hoc and infra mode, an deauthentication is performed
* first.
*/
-int mwifiex_bss_start(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid)
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+ struct mwifiex_802_11_ssid *req_ssid)
{
int ret;
struct mwifiex_adapter *adapter = priv->adapter;
- s32 i = -1;
+ struct mwifiex_bssdescriptor *bss_desc = NULL;
+ u8 *beacon_ie = NULL;
priv->scan_block = false;
- if (!ssid_bssid)
- return -1;
+
+ if (bss) {
+ /* Allocate and fill new bss descriptor */
+ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
+ GFP_KERNEL);
+ if (!bss_desc) {
+ dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
+ return -ENOMEM;
+ }
+
+ beacon_ie = kmemdup(bss->information_elements,
+ bss->len_beacon_ies, GFP_KERNEL);
+ if (!beacon_ie) {
+ kfree(bss_desc);
+ dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
+ return -ENOMEM;
+ }
+
+ ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
+ beacon_ie, bss->len_beacon_ies,
+ bss->beacon_interval,
+ bss->capability,
+ *(u8 *)bss->priv, bss_desc);
+ if (ret)
+ goto done;
+ }
if (priv->bss_mode == NL80211_IFTYPE_STATION) {
/* Infra mode */
ret = mwifiex_deauthenticate(priv, NULL);
if (ret)
- return ret;
+ goto done;
- /* Search for the requested SSID in the scan table */
- if (ssid_bssid->ssid.ssid_len)
- i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid,
- NULL, NL80211_IFTYPE_STATION);
- else
- i = mwifiex_find_bssid_in_list(priv,
- (u8 *) &ssid_bssid->bssid,
- NL80211_IFTYPE_STATION);
- if (i < 0)
- return -1;
+ ret = mwifiex_check_network_compatibility(priv, bss_desc);
+ if (ret)
+ goto done;
+
+ dev_dbg(adapter->dev, "info: SSID found in scan list ... "
+ "associating...\n");
- dev_dbg(adapter->dev,
- "info: SSID found in scan list ... associating...\n");
+ if (!netif_queue_stopped(priv->netdev))
+ netif_stop_queue(priv->netdev);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
/* Clear any past association response stored for
* application retrieval */
priv->assoc_rsp_size = 0;
- ret = mwifiex_associate(priv, &adapter->scan_table[i]);
- if (ret)
- return ret;
+ ret = mwifiex_associate(priv, bss_desc);
+ if (bss)
+ cfg80211_put_bss(bss);
} else {
/* Adhoc mode */
/* If the requested SSID matches current SSID, return */
- if (ssid_bssid->ssid.ssid_len &&
+ if (bss_desc && bss_desc->ssid.ssid_len &&
(!mwifiex_ssid_cmp
(&priv->curr_bss_params.bss_descriptor.ssid,
- &ssid_bssid->ssid)))
+ &bss_desc->ssid))) {
+ kfree(bss_desc);
+ kfree(beacon_ie);
return 0;
+ }
/* Exit Adhoc mode first */
dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
ret = mwifiex_deauthenticate(priv, NULL);
if (ret)
- return ret;
+ goto done;
priv->adhoc_is_link_sensed = false;
- /* Search for the requested network in the scan table */
- if (ssid_bssid->ssid.ssid_len)
- i = mwifiex_find_ssid_in_list(priv,
- &ssid_bssid->ssid, NULL,
- NL80211_IFTYPE_ADHOC);
- else
- i = mwifiex_find_bssid_in_list(priv,
- (u8 *)&ssid_bssid->bssid,
- NL80211_IFTYPE_ADHOC);
+ ret = mwifiex_check_network_compatibility(priv, bss_desc);
+
+ if (!netif_queue_stopped(priv->netdev))
+ netif_stop_queue(priv->netdev);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
- if (i >= 0) {
+ if (!ret) {
dev_dbg(adapter->dev, "info: network found in scan"
" list. Joining...\n");
- ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]);
- if (ret)
- return ret;
+ ret = mwifiex_adhoc_join(priv, bss_desc);
+ if (bss)
+ cfg80211_put_bss(bss);
} else {
dev_dbg(adapter->dev, "info: Network not found in "
"the list, creating adhoc with ssid = %s\n",
- ssid_bssid->ssid.ssid);
- ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid);
- if (ret)
- return ret;
+ req_ssid->ssid);
+ ret = mwifiex_adhoc_start(priv, req_ssid);
}
}
+done:
+ kfree(bss_desc);
+ kfree(beacon_ie);
return ret;
}
@@ -226,8 +291,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv,
* This function prepares the correct firmware command and
* issues it.
*/
-int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
- int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+ int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
{
struct mwifiex_adapter *adapter = priv->adapter;
@@ -349,8 +414,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
return false;
}
- wait_event_interruptible(adapter->hs_activate_wait_q,
- adapter->hs_activate_wait_q_woken);
+ if (wait_event_interruptible(adapter->hs_activate_wait_q,
+ adapter->hs_activate_wait_q_woken)) {
+ dev_err(adapter->dev, "hs_activate_wait_q terminated\n");
+ return false;
+ }
return true;
}
@@ -367,7 +435,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
{
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_bssdescriptor *bss_desc;
- s32 tbl_idx;
if (!info)
return -1;
@@ -385,17 +452,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
info->region_code = adapter->region_code;
- /* Scan table index if connected */
- info->scan_table_idx = 0;
- if (priv->media_connected) {
- tbl_idx =
- mwifiex_find_ssid_in_list(priv, &bss_desc->ssid,
- bss_desc->mac_address,
- priv->bss_mode);
- if (tbl_idx >= 0)
- info->scan_table_idx = tbl_idx;
- }
-
info->media_connected = priv->media_connected;
info->max_power_level = priv->max_tx_power_level;
@@ -478,6 +534,20 @@ int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv,
}
/*
+ * The function disables auto deep sleep mode.
+ */
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
+{
+ struct mwifiex_ds_auto_ds auto_ds;
+
+ auto_ds.auto_ds = DEEP_SLEEP_OFF;
+
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds);
+}
+EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);
+
+/*
* IOCTL request handler to set/get active channel.
*
* This function performs validity checking on channel/frequency
@@ -563,50 +633,6 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
}
/*
- * IOCTL request handler to find a particular BSS.
- *
- * The BSS can be searched with either a BSSID or a SSID. If none of
- * these are provided, just the best BSS (best RSSI) is returned.
- */
-int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *bss_desc;
- u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
- u8 mac[ETH_ALEN];
- int i = 0;
-
- if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) {
- i = mwifiex_find_bssid_in_list(priv,
- (u8 *) ssid_bssid->bssid,
- priv->bss_mode);
- if (i < 0) {
- memcpy(mac, ssid_bssid->bssid, sizeof(mac));
- dev_err(adapter->dev, "cannot find bssid %pM\n", mac);
- return -1;
- }
- bss_desc = &adapter->scan_table[i];
- memcpy(&ssid_bssid->ssid, &bss_desc->ssid,
- sizeof(struct mwifiex_802_11_ssid));
- } else if (ssid_bssid->ssid.ssid_len) {
- i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL,
- priv->bss_mode);
- if (i < 0) {
- dev_err(adapter->dev, "cannot find ssid %s\n",
- ssid_bssid->ssid.ssid);
- return -1;
- }
- bss_desc = &adapter->scan_table[i];
- memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);
- } else {
- return mwifiex_find_best_network(priv, ssid_bssid);
- }
-
- return 0;
-}
-
-/*
* IOCTL request handler to change Ad-Hoc channel.
*
* This function allocates the IOCTL request buffer, fills it
@@ -630,6 +656,9 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
struct mwifiex_bss_info bss_info;
struct mwifiex_ssid_bssid ssid_bssid;
u16 curr_chan = 0;
+ struct cfg80211_bss *bss = NULL;
+ struct ieee80211_channel *chan;
+ enum ieee80211_band band;
memset(&bss_info, 0, sizeof(bss_info));
@@ -665,12 +694,20 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
ret = -1;
goto done;
}
- /* Start/Join Adhoc network */
- memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
- memcpy(&ssid_bssid.ssid, &bss_info.ssid,
- sizeof(struct mwifiex_802_11_ssid));
- ret = mwifiex_bss_start(priv, &ssid_bssid);
+ band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+ chan = __ieee80211_get_channel(priv->wdev->wiphy,
+ ieee80211_channel_to_frequency(channel, band));
+
+ /* Find the BSS we want using available scan results */
+ bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
+ bss_info.ssid.ssid, bss_info.ssid.ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+ if (!bss)
+ wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
+ bss_info.bssid);
+
+ ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
done:
return ret;
}
@@ -686,51 +723,9 @@ done:
static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate_cfg)
{
- struct mwifiex_adapter *adapter = priv->adapter;
-
rate_cfg->is_rate_auto = priv->is_data_rate_auto;
- if (!priv->media_connected) {
- switch (adapter->config_bands) {
- case BAND_B:
- /* Return the lowest supported rate for B band */
- rate_cfg->rate = supported_rates_b[0] & 0x7f;
- break;
- case BAND_G:
- case BAND_G | BAND_GN:
- /* Return the lowest supported rate for G band */
- rate_cfg->rate = supported_rates_g[0] & 0x7f;
- break;
- case BAND_B | BAND_G:
- case BAND_A | BAND_B | BAND_G:
- case BAND_A | BAND_B:
- case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN:
- case BAND_B | BAND_G | BAND_GN:
- /* Return the lowest supported rate for BG band */
- rate_cfg->rate = supported_rates_bg[0] & 0x7f;
- break;
- case BAND_A:
- case BAND_A | BAND_G:
- case BAND_A | BAND_G | BAND_AN | BAND_GN:
- case BAND_A | BAND_AN:
- /* Return the lowest supported rate for A band */
- rate_cfg->rate = supported_rates_a[0] & 0x7f;
- break;
- case BAND_GN:
- /* Return the lowest supported rate for N band */
- rate_cfg->rate = supported_rates_n[0] & 0x7f;
- break;
- default:
- dev_warn(adapter->dev, "invalid band %#x\n",
- adapter->config_bands);
- break;
- }
- } else {
- return mwifiex_send_cmd_sync(priv,
- HostCmd_CMD_802_11_TX_RATE_QUERY,
- HostCmd_ACT_GEN_GET, 0, NULL);
- }
-
- return 0;
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+ HostCmd_ACT_GEN_GET, 0, NULL);
}
/*
@@ -771,7 +766,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f))
break;
}
- if (!rate[i] || (i == MWIFIEX_SUPPORTED_RATES)) {
+ if ((i == MWIFIEX_SUPPORTED_RATES) || !rate[i]) {
dev_err(adapter->dev, "fixed data rate %#x is out "
"of range\n", rate_cfg->rate);
return -1;
@@ -837,10 +832,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
ret = mwifiex_rate_ioctl_cfg(priv, rate);
if (!ret) {
- if (rate && rate->is_rate_auto)
+ if (rate->is_rate_auto)
rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
priv->tx_htinfo);
- else if (rate)
+ else
rate->rate = priv->data_rate;
} else {
ret = -1;
@@ -1257,9 +1252,9 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
if (!status) {
if (signal->selector & BCN_RSSI_AVG_MASK)
- priv->w_stats.qual.level = signal->bcn_rssi_avg;
+ priv->qual_level = signal->bcn_rssi_avg;
if (signal->selector & BCN_NF_AVG_MASK)
- priv->w_stats.qual.noise = signal->bcn_nf_avg;
+ priv->qual_noise = signal->bcn_nf_avg;
}
return status;
@@ -1318,18 +1313,8 @@ int
mwifiex_get_stats_info(struct mwifiex_private *priv,
struct mwifiex_ds_get_stats *log)
{
- int ret;
-
- ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
HostCmd_ACT_GEN_GET, 0, log);
-
- if (!ret) {
- priv->w_stats.discard.fragment = log->fcs_error;
- priv->w_stats.discard.retries = log->retry;
- priv->w_stats.discard.misc = log->ack_failure;
- }
-
- return ret;
}
/*
@@ -1571,7 +1556,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
{
struct mwifiex_ds_misc_gen_ie gen_ie;
- if (ie_len > IW_CUSTOM_MAX)
+ if (ie_len > IEEE_MAX_IE_SIZE)
return -EFAULT;
gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 1fdddec..2743051 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -187,7 +187,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
local_rx_pd->priority, ta,
(u8) local_rx_pd->rx_pkt_type,
- (void *) skb);
+ skb);
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
if (priv && (ret == -1))
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index fa6221b..d97facd 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -47,6 +47,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter;
struct txpd *local_tx_pd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+ u8 pad;
if (!skb->len) {
dev_err(adapter->dev, "Tx: bad packet length: %d\n",
@@ -55,15 +56,19 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
return skb->data;
}
- BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN));
- skb_push(skb, sizeof(*local_tx_pd));
+ /* If skb->data is not aligned; add padding */
+ pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
+
+ BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN
+ + pad));
+ skb_push(skb, sizeof(*local_tx_pd) + pad);
local_tx_pd = (struct txpd *) skb->data;
memset(local_tx_pd, 0, sizeof(struct txpd));
local_tx_pd->bss_num = priv->bss_num;
local_tx_pd->bss_type = priv->bss_type;
local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len -
- sizeof(struct txpd)));
+ (sizeof(struct txpd) + pad)));
local_tx_pd->priority = (u8) skb->priority;
local_tx_pd->pkt_delay_2ms =
@@ -88,7 +93,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
}
/* Offset of actual data */
- local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
+ local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + pad);
/* make space for INTF_HEADER_LEN */
skb_push(skb, INTF_HEADER_LEN);
@@ -146,7 +151,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
skb_push(skb, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb->data, skb->len, NULL);
+ skb, NULL);
switch (ret) {
case -EBUSY:
adapter->data_sent = true;
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index aaa50c0..a206f41 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -71,14 +71,14 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
u8 *head_ptr;
struct txpd *local_tx_pd = NULL;
- head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb);
+ head_ptr = mwifiex_process_sta_txpd(priv, skb);
if (head_ptr) {
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
local_tx_pd =
(struct txpd *) (head_ptr + INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb->data, skb->len, tx_param);
+ skb, tx_param);
}
switch (ret) {
@@ -87,7 +87,8 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
(adapter->pps_uapsd_mode) &&
(adapter->tx_lock_flag)) {
priv->adapter->tx_lock_flag = false;
- local_tx_pd->flags = 0;
+ if (local_tx_pd)
+ local_tx_pd->flags = 0;
}
dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
break;
@@ -160,43 +161,3 @@ done:
return 0;
}
-/*
- * Packet receive completion callback handler.
- *
- * This function calls another completion callback handler which
- * updates the statistics, and optionally updates the parent buffer
- * use count before freeing the received packet.
- */
-int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter,
- struct sk_buff *skb, int status)
-{
- struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
- struct mwifiex_rxinfo *rx_info_parent;
- struct mwifiex_private *priv;
- struct sk_buff *skb_parent;
- unsigned long flags;
-
- priv = adapter->priv[rx_info->bss_index];
-
- if (priv && (status == -1))
- priv->stats.rx_dropped++;
-
- if (rx_info->parent) {
- skb_parent = rx_info->parent;
- rx_info_parent = MWIFIEX_SKB_RXCB(skb_parent);
-
- spin_lock_irqsave(&priv->rx_pkt_lock, flags);
- --rx_info_parent->use_count;
-
- if (!rx_info_parent->use_count) {
- spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
- dev_kfree_skb_any(skb_parent);
- } else {
- spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
- }
- } else {
- dev_kfree_skb_any(skb);
- }
-
- return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index d412915..06976f5 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -185,13 +185,14 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
* corresponding waiting function. Otherwise, it processes the
* IOCTL response and frees the response buffer.
*/
-int mwifiex_complete_cmd(struct mwifiex_adapter *adapter)
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
+ struct cmd_ctrl_node *cmd_node)
{
atomic_dec(&adapter->cmd_pending);
dev_dbg(adapter->dev, "cmd completed: status=%d\n",
adapter->cmd_wait_q.status);
- adapter->cmd_wait_q.condition = true;
+ *(cmd_node->condition) = true;
if (adapter->cmd_wait_q.status == -ETIMEDOUT)
dev_err(adapter->dev, "cmd timeout\n");
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h
index 9506afc..f6d36b9 100644
--- a/drivers/net/wireless/mwifiex/util.h
+++ b/drivers/net/wireless/mwifiex/util.h
@@ -22,11 +22,16 @@
static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
{
- return (struct mwifiex_rxinfo *)skb->cb;
+ return (struct mwifiex_rxinfo *)(skb->cb + sizeof(phys_addr_t));
}
static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
{
- return (struct mwifiex_txinfo *)skb->cb;
+ return (struct mwifiex_txinfo *)(skb->cb + sizeof(phys_addr_t));
+}
+
+static inline phys_addr_t *MWIFIEX_SKB_PACB(struct sk_buff *skb)
+{
+ return (phys_addr_t *)skb->cb;
}
#endif /* !_MWIFIEX_UTIL_H_ */
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 2cdb41a..06fcf1e 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -635,6 +635,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,
ra_list = NULL;
} else {
memcpy(ra, skb->data, ETH_ALEN);
+ if (ra[0] & 0x01)
+ memset(ra, 0xff, ETH_ALEN);
ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra);
}
@@ -973,25 +975,25 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
}
/*
- * This function gets the number of packets in the Tx queue of a
- * particular RA list.
+ * This function checks if 11n aggregation is possible.
*/
static int
-mwifiex_num_pkts_in_txq(struct mwifiex_private *priv,
- struct mwifiex_ra_list_tbl *ptr, int max_buf_size)
+mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
+ struct mwifiex_ra_list_tbl *ptr,
+ int max_buf_size)
{
int count = 0, total_size = 0;
struct sk_buff *skb, *tmp;
skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
total_size += skb->len;
- if (total_size < max_buf_size)
- ++count;
- else
+ if (total_size >= max_buf_size)
break;
+ if (++count >= MIN_NUM_AMSDU)
+ return true;
}
- return count;
+ return false;
}
/*
@@ -1125,8 +1127,8 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
tx_param.next_pkt_len =
((skb_next) ? skb_next->len +
sizeof(struct txpd) : 0);
- ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb->data, skb->len, &tx_param);
+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, skb,
+ &tx_param);
switch (ret) {
case -EBUSY:
dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
@@ -1209,10 +1211,12 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
return 0;
}
- if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid)
- || ((priv->sec_info.wpa_enabled
- || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set)
- ) {
+ if (!ptr->is_11n_enabled ||
+ mwifiex_is_ba_stream_setup(priv, ptr, tid) ||
+ priv->wps.session_enable ||
+ ((priv->sec_info.wpa_enabled ||
+ priv->sec_info.wpa2_enabled) &&
+ !priv->wpa_is_gtk_set)) {
mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
/* ra_list_spinlock has been freed in
mwifiex_send_single_packet() */
@@ -1231,11 +1235,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
mwifiex_send_delba(priv, tid_del, ra, 1);
}
}
-/* Minimum number of AMSDU */
-#define MIN_NUM_AMSDU 2
if (mwifiex_is_amsdu_allowed(priv, tid) &&
- (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >=
- MIN_NUM_AMSDU))
+ mwifiex_is_11n_aggragation_possible(priv, ptr,
+ adapter->tx_buf_size))
mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
ptr_index, flags);
/* ra_list_spinlock has been freed in
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
index 4a0a0e5..0ca8b14 100644
--- a/drivers/net/wireless/orinoco/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -150,7 +150,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
struct orinoco_private *priv;
struct airport *card;
unsigned long phys_addr;
- hermes_t *hw;
+ struct hermes *hw;
if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
@@ -228,10 +228,9 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
MODULE_LICENSE("Dual MPL/GPL");
-static struct of_device_id airport_match[] =
-{
+static struct of_device_id airport_match[] = {
{
- .name = "radio",
+ .name = "radio",
},
{},
};
@@ -240,7 +239,7 @@ MODULE_DEVICE_TABLE(of, airport_match);
static struct macio_driver airport_driver = {
.driver = {
- .name = DRIVER_NAME,
+ .name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = airport_match,
},
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 736bbb9..f7b15b8 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -59,7 +59,7 @@ int orinoco_wiphy_register(struct wiphy *wiphy)
for (i = 0; i < NUM_CHANNELS; i++) {
if (priv->channel_mask & (1 << i)) {
priv->channels[i].center_freq =
- ieee80211_dsss_chan_to_freq(i+1);
+ ieee80211_dsss_chan_to_freq(i + 1);
channels++;
}
}
@@ -182,7 +182,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
if ((channel < 1) || (channel > NUM_CHANNELS) ||
- !(priv->channel_mask & (1 << (channel-1))))
+ !(priv->channel_mask & (1 << (channel - 1))))
return -EINVAL;
if (orinoco_lock(priv, &flags) != 0)
@@ -191,7 +191,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
priv->channel = channel;
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
/* Fast channel change - no commit if successful */
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
HERMES_TEST_SET_CHANNEL,
channel, NULL);
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c
index 259d758..4df8cf6 100644
--- a/drivers/net/wireless/orinoco/fw.c
+++ b/drivers/net/wireless/orinoco/fw.c
@@ -6,6 +6,7 @@
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/device.h>
+#include <linux/module.h>
#include "hermes.h"
#include "hermes_dld.h"
@@ -100,7 +101,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
/* Plug Data Area (PDA) */
__le16 *pda;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
const struct firmware *fw_entry;
const struct orinoco_fw_header *hdr;
const unsigned char *first_block;
@@ -205,7 +206,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
const unsigned char *image, const void *end,
int secondary)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret = 0;
const unsigned char *ptr;
const unsigned char *first_block;
@@ -322,9 +323,8 @@ symbol_dl_firmware(struct orinoco_private *priv,
fw_entry->data + fw_entry->size, 1);
if (!orinoco_cached_fw_get(priv, false))
release_firmware(fw_entry);
- if (ret) {
+ if (ret)
dev_err(dev, "Secondary firmware download failed\n");
- }
return ret;
}
diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h
index 89fc26d..aca63e3 100644
--- a/drivers/net/wireless/orinoco/fw.h
+++ b/drivers/net/wireless/orinoco/fw.h
@@ -14,7 +14,7 @@ int orinoco_download(struct orinoco_private *priv);
void orinoco_cache_fw(struct orinoco_private *priv, int ap);
void orinoco_uncache_fw(struct orinoco_private *priv);
#else
-#define orinoco_cache_fw(priv, ap) do { } while(0)
+#define orinoco_cache_fw(priv, ap) do { } while (0)
#define orinoco_uncache_fw(priv) do { } while (0)
#endif
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c
index 6c6a23e..75c15bc 100644
--- a/drivers/net/wireless/orinoco/hermes.c
+++ b/drivers/net/wireless/orinoco/hermes.c
@@ -103,7 +103,7 @@ static const struct hermes_ops hermes_ops_local;
Callable from any context.
*/
-static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
+static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0,
u16 param1, u16 param2)
{
int k = CMD_BUSY_TIMEOUT;
@@ -132,7 +132,7 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
*/
/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
-static int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
+static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
u16 parm0, u16 parm1, u16 parm2,
struct hermes_response *resp)
{
@@ -185,7 +185,8 @@ out:
return err;
}
-void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
+void hermes_struct_init(struct hermes *hw, void __iomem *address,
+ int reg_spacing)
{
hw->iobase = address;
hw->reg_spacing = reg_spacing;
@@ -195,7 +196,7 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
}
EXPORT_SYMBOL(hermes_struct_init);
-static int hermes_init(hermes_t *hw)
+static int hermes_init(struct hermes *hw)
{
u16 reg;
int err = 0;
@@ -249,7 +250,7 @@ static int hermes_init(hermes_t *hw)
* > 0 on error returned by the firmware
*
* Callable from any context, but locking is your problem. */
-static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
struct hermes_response *resp)
{
int err;
@@ -313,7 +314,7 @@ static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
return err;
}
-static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
+static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid)
{
int err = 0;
int k;
@@ -363,7 +364,7 @@ static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
* from firmware
*
* Callable from any context */
-static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
+static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
{
int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
@@ -422,7 +423,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
* 0 on success
* > 0 on error from firmware
*/
-static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
+static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len,
u16 id, u16 offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -436,7 +437,7 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
goto out;
/* Actually do the transfer */
- hermes_read_words(hw, dreg, buf, len/2);
+ hermes_read_words(hw, dreg, buf, len / 2);
out:
return err;
@@ -450,8 +451,8 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
* 0 on success
* > 0 on error from firmware
*/
-static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
- u16 id, u16 offset)
+static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf,
+ int len, u16 id, u16 offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
int err = 0;
@@ -478,8 +479,8 @@ static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
* practice.
*
* Callable from user or bh context. */
-static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
- u16 *length, void *buf)
+static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid,
+ unsigned bufsize, u16 *length, void *buf)
{
int err = 0;
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -523,7 +524,7 @@ static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
return 0;
}
-static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
+static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid,
u16 length, const void *value)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -553,14 +554,14 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
/*** Hermes AUX control ***/
static inline void
-hermes_aux_setaddr(hermes_t *hw, u32 addr)
+hermes_aux_setaddr(struct hermes *hw, u32 addr)
{
hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
}
static inline int
-hermes_aux_control(hermes_t *hw, int enabled)
+hermes_aux_control(struct hermes *hw, int enabled)
{
int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
@@ -594,7 +595,7 @@ hermes_aux_control(hermes_t *hw, int enabled)
* wl_lkm Agere fw does
* Don't know about intersil
*/
-static int hermesi_program_init(hermes_t *hw, u32 offset)
+static int hermesi_program_init(struct hermes *hw, u32 offset)
{
int err;
@@ -643,7 +644,7 @@ static int hermesi_program_init(hermes_t *hw, u32 offset)
* wl_lkm Agere fw does
* Don't know about intersil
*/
-static int hermesi_program_end(hermes_t *hw)
+static int hermesi_program_end(struct hermes *hw)
{
struct hermes_response resp;
int rc = 0;
@@ -684,7 +685,8 @@ static int hermes_program_bytes(struct hermes *hw, const char *data,
}
/* Read PDA from the adapter */
-static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
+static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr,
+ u16 pda_len)
{
int ret;
u16 pda_size;
diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h
index d9f18c1..28a4244 100644
--- a/drivers/net/wireless/orinoco/hermes.h
+++ b/drivers/net/wireless/orinoco/hermes.h
@@ -28,7 +28,7 @@
*
* As a module of low level hardware access routines, there is no
* locking. Users of this module should ensure that they serialize
- * access to the hermes_t structure, and to the hardware
+ * access to the hermes structure, and to the hardware
*/
#include <linux/if_ether.h>
@@ -43,7 +43,7 @@
#define HERMES_BAP_DATALEN_MAX (4096)
#define HERMES_BAP_OFFSET_MAX (4096)
#define HERMES_PORTID_MAX (7)
-#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX+1)
+#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX + 1)
#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */
#define HERMES_PDA_RECS_MAX (200) /* a guess */
#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */
@@ -148,7 +148,7 @@
#define HERMES_CMD_WRITEMIF (0x0031)
/*--- Debugging Commands -----------------------------*/
-#define HERMES_CMD_TEST (0x0038)
+#define HERMES_CMD_TEST (0x0038)
/* Test command arguments */
@@ -178,8 +178,8 @@
#define HERMES_DESCRIPTOR_OFFSET 0
#define HERMES_802_11_OFFSET (14)
-#define HERMES_802_3_OFFSET (14+32)
-#define HERMES_802_2_OFFSET (14+32+14)
+#define HERMES_802_3_OFFSET (14 + 32)
+#define HERMES_802_2_OFFSET (14 + 32 + 14)
#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
#define HERMES_RXSTAT_ERR (0x0003)
@@ -406,7 +406,7 @@ struct hermes_ops {
};
/* Basic control structure */
-typedef struct hermes {
+struct hermes {
void __iomem *iobase;
int reg_spacing;
#define HERMES_16BIT_REGSPACING 0
@@ -415,7 +415,7 @@ typedef struct hermes {
bool eeprom_pda;
const struct hermes_ops *ops;
void *priv;
-} hermes_t;
+};
/* Register access convenience macros */
#define hermes_read_reg(hw, off) \
@@ -427,28 +427,29 @@ typedef struct hermes {
hermes_write_reg((hw), HERMES_##name, (val))
/* Function prototypes */
-void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
+void hermes_struct_init(struct hermes *hw, void __iomem *address,
+ int reg_spacing);
/* Inline functions */
-static inline int hermes_present(hermes_t *hw)
+static inline int hermes_present(struct hermes *hw)
{
return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
}
-static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
+static inline void hermes_set_irqmask(struct hermes *hw, u16 events)
{
hw->inten = events;
hermes_write_regn(hw, INTEN, events);
}
-static inline int hermes_enable_port(hermes_t *hw, int port)
+static inline int hermes_enable_port(struct hermes *hw, int port)
{
return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
0, NULL);
}
-static inline int hermes_disable_port(hermes_t *hw, int port)
+static inline int hermes_disable_port(struct hermes *hw, int port)
{
return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
0, NULL);
@@ -456,13 +457,13 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
/* Initiate an INQUIRE command (tallies or scan). The result will come as an
* information frame in __orinoco_ev_info() */
-static inline int hermes_inquire(hermes_t *hw, u16 rid)
+static inline int hermes_inquire(struct hermes *hw, u16 rid)
{
return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
}
-#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
-#define HERMES_RECLEN_TO_BYTES(n) (((n)-1) * 2)
+#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1)
+#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2)
/* Note that for the next two, the count is in 16-bit words, not bytes */
static inline void hermes_read_words(struct hermes *hw, int off,
@@ -498,7 +499,8 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
(hw->ops->write_ltv((hw), (bap), (rid), \
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
-static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
+static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid,
+ u16 *word)
{
__le16 rec;
int err;
@@ -508,7 +510,8 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
return err;
}
-static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
+static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid,
+ u16 word)
{
__le16 rec = cpu_to_le16(word);
return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
index 2b2b9a1..4a10b7a 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.c
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
@@ -193,7 +193,7 @@ hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end)
/* Process one Plug Data Item - find corresponding PDR and plug it */
static int
-hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
+hermes_plug_pdi(struct hermes *hw, const struct pdr *first_pdr,
const struct pdi *pdi, const void *pdr_end)
{
const struct pdr *pdr;
@@ -220,7 +220,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
* Attempt to write every records that is in the specified pda
* which also has a valid production data record for the firmware.
*/
-int hermes_apply_pda(hermes_t *hw,
+int hermes_apply_pda(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
@@ -274,7 +274,7 @@ hermes_blocks_length(const char *first_block, const void *end)
/*** Hermes programming ***/
/* Program the data blocks */
-int hermes_program(hermes_t *hw, const char *first_block, const void *end)
+int hermes_program(struct hermes *hw, const char *first_block, const void *end)
{
const struct dblock *blk;
u32 blkaddr;
@@ -387,7 +387,7 @@ DEFINE_DEFAULT_PDR(0x0161, 256,
*
* For certain records, use defaults if they are not found in pda.
*/
-int hermes_apply_pda_with_defaults(hermes_t *hw,
+int hermes_apply_pda_with_defaults(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
diff --git a/drivers/net/wireless/orinoco/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h
index 583a5bc..b5377e2 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.h
+++ b/drivers/net/wireless/orinoco/hermes_dld.h
@@ -27,21 +27,21 @@
#include "hermes.h"
-int hermesi_program_init(hermes_t *hw, u32 offset);
-int hermesi_program_end(hermes_t *hw);
-int hermes_program(hermes_t *hw, const char *first_block, const void *end);
+int hermesi_program_init(struct hermes *hw, u32 offset);
+int hermesi_program_end(struct hermes *hw);
+int hermes_program(struct hermes *hw, const char *first_block, const void *end);
-int hermes_read_pda(hermes_t *hw,
+int hermes_read_pda(struct hermes *hw,
__le16 *pda,
u32 pda_addr,
u16 pda_len,
int use_eeprom);
-int hermes_apply_pda(hermes_t *hw,
+int hermes_apply_pda(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
const void *pda_end);
-int hermes_apply_pda_with_defaults(hermes_t *hw,
+int hermes_apply_pda_with_defaults(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 3c7877a..c09c843 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -47,7 +47,7 @@ struct comp_id {
u16 id, variant, major, minor;
} __packed;
-static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
+static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
{
if (nic_id->id < 0x8000)
return FIRMWARE_TYPE_AGERE;
@@ -71,11 +71,11 @@ int determine_fw_capabilities(struct orinoco_private *priv,
u32 *hw_ver)
{
struct device *dev = priv->dev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
struct comp_id nic_id, sta_id;
unsigned int firmver;
- char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
+ char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
/* Get the hardware version */
err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
@@ -280,7 +280,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
{
struct device *dev = priv->dev;
struct hermes_idstring nickbuf;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int len;
int err;
u16 reclen;
@@ -458,7 +458,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
{
struct net_device *dev = priv->ndev;
struct wireless_dev *wdev = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
struct hermes_idstring idbuf;
@@ -529,7 +529,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
- HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+ HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
&idbuf);
if (err) {
printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
@@ -537,7 +537,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
return err;
}
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
- HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+ HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
&idbuf);
if (err) {
printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
@@ -549,7 +549,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
idbuf.len = cpu_to_le16(strlen(priv->nick));
memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
- HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+ HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
&idbuf);
if (err) {
printk(KERN_ERR "%s: Error %d setting nickname\n",
@@ -689,7 +689,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
/* Get tsc from the firmware */
int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u8 tsc_arr[4][ORINOCO_SEQ_LEN];
@@ -706,7 +706,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ratemode = priv->bitratemode;
int err = 0;
@@ -737,7 +737,7 @@ int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int i;
int err = 0;
u16 val;
@@ -786,7 +786,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv)
{
int roaming_flag;
int err = 0;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
switch (priv->firmware_type) {
case FIRMWARE_TYPE_AGERE:
@@ -818,7 +818,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv)
* which is needed for 802.1x implementations. */
int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
int i;
@@ -902,7 +902,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
int __orinoco_hw_setup_enc(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
int master_wep_flag;
int auth_flag;
@@ -999,7 +999,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
u8 rx_mic[MIC_KEYLEN];
u8 tsc[ORINOCO_SEQ_LEN];
} __packed buf;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret;
int err;
int k;
@@ -1052,7 +1052,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
err = hermes_write_wordrec(hw, USER_BAP,
@@ -1068,7 +1068,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
struct net_device *dev,
int mc_count, int promisc)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
if (promisc != priv->promiscuous) {
@@ -1111,9 +1111,9 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
/* Return : < 0 -> error code ; >= 0 -> length */
int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
- char buf[IW_ESSID_MAX_SIZE+1])
+ char buf[IW_ESSID_MAX_SIZE + 1])
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
struct hermes_idstring essidbuf;
char *p = (char *)(&essidbuf.val);
@@ -1166,7 +1166,7 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
int orinoco_hw_get_freq(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u16 channel;
int freq = 0;
@@ -1206,7 +1206,7 @@ int orinoco_hw_get_freq(struct orinoco_private *priv)
int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int *numrates, s32 *rates, int max)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct hermes_idstring list;
unsigned char *p = (unsigned char *)&list.val;
int err = 0;
@@ -1238,7 +1238,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
const struct cfg80211_ssid *ssid)
{
struct net_device *dev = priv->ndev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
unsigned long flags;
int err = 0;
@@ -1323,7 +1323,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
int orinoco_hw_disassociate(struct orinoco_private *priv,
u8 *addr, u16 reason_code)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
struct {
@@ -1346,7 +1346,7 @@ int orinoco_hw_disassociate(struct orinoco_private *priv,
int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
u8 *addr)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 97af71e..8f6831f 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -45,7 +45,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
struct net_device *dev,
int mc_count, int promisc);
int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
- char buf[IW_ESSID_MAX_SIZE+1]);
+ char buf[IW_ESSID_MAX_SIZE + 1]);
int orinoco_hw_get_freq(struct orinoco_private *priv);
int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int *numrates, s32 *rates, int max);
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 62c6b2b..b52acc4 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -4,7 +4,7 @@
* adaptors, with Lucent/Agere, Intersil or Symbol firmware.
*
* Current maintainers (as of 29 September 2003) are:
- * Pavel Roskin <proski AT gnu.org>
+ * Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* (C) Copyright David Gibson, IBM Corporation 2001-2003.
@@ -146,10 +146,10 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
#define MAX_IRQLOOPS_PER_IRQ 10
-#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
- * how many events the
- * device could
- * legitimately generate */
+#define MAX_IRQLOOPS_PER_JIFFY (20000 / HZ) /* Based on a guestimate of
+ * how many events the
+ * device could
+ * legitimately generate */
#define DUMMY_FID 0xFFFF
@@ -157,7 +157,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
HERMES_MAX_MULTICAST : 0)*/
#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
-#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
+#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
| HERMES_EV_TX | HERMES_EV_TXEXC \
| HERMES_EV_WTERR | HERMES_EV_INFO \
| HERMES_EV_INFDROP)
@@ -437,12 +437,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u16 txfid = priv->txfid;
int tx_control;
unsigned long flags;
- u8 mic_buf[MICHAEL_MIC_LEN+1];
+ u8 mic_buf[MICHAEL_MIC_LEN + 1];
if (!netif_running(dev)) {
printk(KERN_ERR "%s: Tx on stopped device!\n",
@@ -579,7 +579,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_alloc(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
u16 fid = hermes_read_regn(hw, ALLOCFID);
@@ -594,7 +594,7 @@ static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
}
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_tx(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
@@ -606,7 +606,7 @@ static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
}
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_txexc(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
@@ -753,7 +753,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
struct sk_buff *skb;
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
len = le16_to_cpu(desc->data_len);
@@ -840,7 +840,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
stats->rx_dropped++;
}
-void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
@@ -918,7 +918,7 @@ void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
32bit boundary, plus 1 byte so we can read in odd length
packets from the card, which has an IO granularity of 16
bits */
- skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+ skb = dev_alloc_skb(length + ETH_HLEN + 2 + 1);
if (!skb) {
printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
dev->name);
@@ -1402,7 +1402,7 @@ static void orinoco_process_scan_results(struct work_struct *work)
spin_unlock_irqrestore(&priv->scan_lock, flags);
}
-void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_info(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
u16 infofid;
@@ -1620,7 +1620,7 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
}
EXPORT_SYMBOL(__orinoco_ev_info);
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_infdrop(struct net_device *dev, struct hermes *hw)
{
if (net_ratelimit())
printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
@@ -1831,7 +1831,7 @@ static int __orinoco_commit(struct orinoco_private *priv)
int orinoco_commit(struct orinoco_private *priv)
{
struct net_device *dev = priv->ndev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
if (priv->broken_disableport) {
@@ -1874,12 +1874,12 @@ int orinoco_commit(struct orinoco_private *priv)
/* Interrupt handler */
/********************************************************************/
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_tick(struct net_device *dev, struct hermes *hw)
{
printk(KERN_DEBUG "%s: TICK\n", dev->name);
}
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_wterr(struct net_device *dev, struct hermes *hw)
{
/* This seems to happen a fair bit under load, but ignoring it
seems to work fine...*/
@@ -1891,7 +1891,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
{
struct orinoco_private *priv = dev_id;
struct net_device *dev = priv->ndev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int count = MAX_IRQLOOPS_PER_IRQ;
u16 evstat, events;
/* These are used to detect a runaway interrupt situation.
@@ -1958,7 +1958,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
evstat = hermes_read_regn(hw, EVSTAT);
events = evstat & hw->inten;
- };
+ }
orinoco_unlock(priv, &flags);
return IRQ_HANDLED;
@@ -2017,8 +2017,8 @@ static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
unregister_pm_notifier(&priv->pm_notifier);
}
#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
-#define orinoco_register_pm_notifier(priv) do { } while(0)
-#define orinoco_unregister_pm_notifier(priv) do { } while(0)
+#define orinoco_register_pm_notifier(priv) do { } while (0)
+#define orinoco_unregister_pm_notifier(priv) do { } while (0)
#endif
/********************************************************************/
@@ -2029,7 +2029,7 @@ int orinoco_init(struct orinoco_private *priv)
{
struct device *dev = priv->dev;
struct wiphy *wiphy = priv_to_wiphy(priv);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
/* No need to lock, the hw_unavailable flag is already set in
@@ -2135,7 +2135,7 @@ static const struct net_device_ops orinoco_netdev_ops = {
.ndo_open = orinoco_open,
.ndo_stop = orinoco_stop,
.ndo_start_xmit = orinoco_xmit,
- .ndo_set_multicast_list = orinoco_set_multicast_list,
+ .ndo_set_rx_mode = orinoco_set_multicast_list,
.ndo_change_mtu = orinoco_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/orinoco/mic.c b/drivers/net/wireless/orinoco/mic.c
index c03e7f5..fce4a84 100644
--- a/drivers/net/wireless/orinoco/mic.c
+++ b/drivers/net/wireless/orinoco/mic.c
@@ -59,10 +59,10 @@ int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key,
/* Copy header into buffer. We need the padding on the end zeroed */
memcpy(&hdr[0], da, ETH_ALEN);
memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
- hdr[ETH_ALEN*2] = priority;
- hdr[ETH_ALEN*2+1] = 0;
- hdr[ETH_ALEN*2+2] = 0;
- hdr[ETH_ALEN*2+3] = 0;
+ hdr[ETH_ALEN * 2] = priority;
+ hdr[ETH_ALEN * 2 + 1] = 0;
+ hdr[ETH_ALEN * 2 + 2] = 0;
+ hdr[ETH_ALEN * 2 + 3] = 0;
/* Use scatter gather to MIC header and data in one go */
sg_init_table(sg, 2);
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 255710e..3bb936b 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -49,11 +49,11 @@ enum orinoco_alg {
ORINOCO_ALG_TKIP
};
-typedef enum {
+enum fwtype {
FIRMWARE_TYPE_AGERE,
FIRMWARE_TYPE_INTERSIL,
FIRMWARE_TYPE_SYMBOL
-} fwtype_t;
+};
struct firmware;
@@ -88,11 +88,11 @@ struct orinoco_private {
struct iw_statistics wstats;
/* Hardware control variables */
- hermes_t hw;
+ struct hermes hw;
u16 txfid;
/* Capabilities of the hardware/firmware */
- fwtype_t firmware_type;
+ enum fwtype firmware_type;
int ibss_port;
int nicbuf_size;
u16 channel_mask;
@@ -122,8 +122,8 @@ struct orinoco_private {
struct key_params keys[ORINOCO_MAX_KEYS];
int bitratemode;
- char nick[IW_ESSID_MAX_SIZE+1];
- char desired_essid[IW_ESSID_MAX_SIZE+1];
+ char nick[IW_ESSID_MAX_SIZE + 1];
+ char desired_essid[IW_ESSID_MAX_SIZE + 1];
char desired_bssid[ETH_ALEN];
int bssid_fixed;
u16 frag_thresh, mwo_robust;
@@ -197,8 +197,8 @@ extern int orinoco_up(struct orinoco_private *priv);
extern void orinoco_down(struct orinoco_private *priv);
extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
-extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
-extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
+extern void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
+extern void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
int orinoco_process_xmit_skb(struct sk_buff *skb,
struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 88e3c0e..d7dbc00 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -65,7 +65,7 @@ static void orinoco_cs_release(struct pcmcia_device *link);
static void orinoco_cs_detach(struct pcmcia_device *p_dev);
/********************************************************************/
-/* Device methods */
+/* Device methods */
/********************************************************************/
static int
@@ -89,7 +89,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
}
/********************************************************************/
-/* PCMCIA stuff */
+/* PCMCIA stuff */
/********************************************************************/
static int
@@ -134,7 +134,7 @@ static int
orinoco_cs_config(struct pcmcia_device *link)
{
struct orinoco_private *priv = link->priv;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret;
void __iomem *mem;
@@ -239,7 +239,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
static const struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
- PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
@@ -272,6 +271,7 @@ static const struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+ PCMCIA_DEVICE_MANF_CARD_PROD_ID3(0x0156, 0x0002, "Version 01.01", 0xd27deb1a), /* Lucent Orinoco */
#ifdef CONFIG_HERMES_PRISM
/* Only entries that certainly identify Prism chipset */
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
@@ -321,6 +321,9 @@ static const struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
+
+ /* This may be Agere or Intersil Firmware */
+ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
#endif
PCMCIA_DEVICE_NULL,
};
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index bc3ea0b..326396b 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -296,8 +296,7 @@ static struct pci_driver orinoco_nortel_driver = {
static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
" (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
-MODULE_DESCRIPTION
- ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge");
MODULE_LICENSE("Dual MPL/GPL");
static int __init orinoco_nortel_init(void)
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 468197f..6058c66 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -6,7 +6,7 @@
* hermes registers, as well as the COR register.
*
* Current maintainers are:
- * Pavel Roskin <proski AT gnu.org>
+ * Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* Some of this code is borrowed from orinoco_plx.c
@@ -81,7 +81,7 @@
*/
static int orinoco_pci_cor_reset(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
unsigned long timeout;
u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index 9358f4d..2bac824 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -4,7 +4,7 @@
* but are connected to the PCI bus by a PLX9052.
*
* Current maintainers are:
- * Pavel Roskin <proski AT gnu.org>
+ * Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* (C) Copyright David Gibson, IBM Corp. 2001-2003.
@@ -102,14 +102,14 @@
#define PLX_RESET_TIME (500) /* milliseconds */
#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
-#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
+#define PLX_INTCSR_INTEN (1 << 6) /* Interrupt Enable bit */
/*
* Do a soft reset of the card using the Configuration Option Register
*/
static int orinoco_plx_cor_reset(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct orinoco_pci_card *card = priv->card;
unsigned long timeout;
u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index 784605f..93159d6 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -59,7 +59,7 @@
*/
static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct orinoco_pci_card *card = priv->card;
unsigned long timeout;
u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index b9aedf1..0793e42 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -199,7 +199,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
#define EZUSB_FRAME_DATA 1
#define EZUSB_FRAME_CONTROL 2
-#define DEF_TIMEOUT (3*HZ)
+#define DEF_TIMEOUT (3 * HZ)
#define BULK_BUF_SIZE 2048
@@ -959,7 +959,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
return retval;
}
-static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
+static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
u16 length, const void *data)
{
struct ezusb_priv *upriv = hw->priv;
@@ -989,7 +989,7 @@ static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
NULL, 0, NULL);
}
-static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
+static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
unsigned bufsize, u16 *length, void *buf)
{
struct ezusb_priv *upriv = hw->priv;
@@ -1006,7 +1006,7 @@ static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
buf, bufsize, length);
}
-static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
+static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
u16 parm2, struct hermes_response *resp)
{
struct ezusb_priv *upriv = hw->priv;
@@ -1028,7 +1028,7 @@ static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
EZUSB_FRAME_CONTROL, NULL, 0, NULL);
}
-static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
struct hermes_response *resp)
{
struct ezusb_priv *upriv = hw->priv;
@@ -1196,7 +1196,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct ezusb_priv *upriv = priv->card;
- u8 mic[MICHAEL_MIC_LEN+1];
+ u8 mic[MICHAEL_MIC_LEN + 1];
int err = 0;
int tx_control;
unsigned long flags;
@@ -1356,7 +1356,7 @@ static int ezusb_hard_reset(struct orinoco_private *priv)
}
-static int ezusb_init(hermes_t *hw)
+static int ezusb_init(struct hermes *hw)
{
struct ezusb_priv *upriv = hw->priv;
int retval;
@@ -1438,7 +1438,7 @@ static void ezusb_bulk_in_callback(struct urb *urb)
} else if (upriv->dev) {
struct net_device *dev = upriv->dev;
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
if (hermes_rid == EZUSB_RID_RX) {
__orinoco_ev_rx(dev, hw);
@@ -1562,7 +1562,7 @@ static const struct net_device_ops ezusb_netdev_ops = {
.ndo_open = orinoco_open,
.ndo_stop = orinoco_stop,
.ndo_start_xmit = ezusb_xmit,
- .ndo_set_multicast_list = orinoco_set_multicast_list,
+ .ndo_set_rx_mode = orinoco_set_multicast_list,
.ndo_change_mtu = orinoco_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -1575,7 +1575,7 @@ static int ezusb_probe(struct usb_interface *interface,
{
struct usb_device *udev = interface_to_usbdev(interface);
struct orinoco_private *priv;
- hermes_t *hw;
+ struct hermes *hw;
struct ezusb_priv *upriv = NULL;
struct usb_interface_descriptor *iface_desc;
struct usb_endpoint_descriptor *ep;
@@ -1757,7 +1757,7 @@ static struct usb_driver orinoco_driver = {
/* Can't be declared "const" or the whole __initdata section will
* become const */
static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
- " (Manuel Estrada Sainz)";
+ " (Manuel Estrada Sainz)";
static int __init ezusb_module_init(void)
{
@@ -1787,6 +1787,5 @@ module_init(ezusb_module_init);
module_exit(ezusb_module_exit);
MODULE_AUTHOR("Manuel Estrada Sainz");
-MODULE_DESCRIPTION
- ("Driver for Orinoco wireless LAN cards using EZUSB bridge");
+MODULE_DESCRIPTION("Driver for Orinoco wireless LAN cards using EZUSB bridge");
MODULE_LICENSE("Dual MPL/GPL");
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 81f3673..6e28ee4 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -11,9 +11,9 @@
*
* Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
* Portions based on orinoco_cs.c:
- * Copyright (C) David Gibson, Linuxcare Australia
+ * Copyright (C) David Gibson, Linuxcare Australia
* Portions based on Spectrum24tDnld.c from original spectrum24 driver:
- * Copyright (C) Symbol Technologies.
+ * Copyright (C) Symbol Technologies.
*
* See copyright notice in file main.c.
*/
@@ -125,7 +125,7 @@ failed:
}
/********************************************************************/
-/* Device methods */
+/* Device methods */
/********************************************************************/
static int
@@ -150,7 +150,7 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
}
/********************************************************************/
-/* PCMCIA stuff */
+/* PCMCIA stuff */
/********************************************************************/
static int
@@ -197,7 +197,7 @@ static int
spectrum_cs_config(struct pcmcia_device *link)
{
struct orinoco_private *priv = link->priv;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret;
void __iomem *mem;
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index e793679..33747e1 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -9,6 +9,7 @@
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
+#include <net/cfg80211-wext.h>
#include "hermes.h"
#include "hermes_rid.h"
@@ -87,7 +88,7 @@ nomem:
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
int err;
unsigned long flags;
@@ -448,7 +449,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
}
if ((chan < 1) || (chan > NUM_CHANNELS) ||
- !(priv->channel_mask & (1 << (chan-1))))
+ !(priv->channel_mask & (1 << (chan - 1))))
return -EINVAL;
if (orinoco_lock(priv, &flags) != 0)
@@ -457,7 +458,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
priv->channel = chan;
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
/* Fast channel change - no commit if successful */
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
HERMES_TEST_SET_CHANNEL,
chan, NULL);
@@ -492,7 +493,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
u16 val;
int err;
unsigned long flags;
@@ -668,7 +669,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u16 enable, period, timeout, mcast;
unsigned long flags;
@@ -873,7 +874,7 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct iw_param *param = &wrqu->param;
unsigned long flags;
int ret = -EINPROGRESS;
@@ -1269,7 +1270,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int rid = data->flags;
u16 length;
int err;
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 54cc0bb..fa8ce51 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -24,6 +24,7 @@
#include <net/mac80211.h>
#include <linux/crc-ccitt.h>
+#include <linux/export.h>
#include "p54.h"
#include "eeprom.h"
@@ -145,6 +146,7 @@ static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
static int p54_generate_band(struct ieee80211_hw *dev,
struct p54_channel_list *list,
+ unsigned int *chan_num,
enum ieee80211_band band)
{
struct p54_common *priv = dev->priv;
@@ -190,7 +192,14 @@ static int p54_generate_band(struct ieee80211_hw *dev,
tmp->channels[j].band = chan->band;
tmp->channels[j].center_freq = chan->freq;
+ priv->survey[*chan_num].channel = &tmp->channels[j];
+ priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
+ SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ tmp->channels[j].hw_value = (*chan_num);
j++;
+ (*chan_num)++;
}
if (j == 0) {
@@ -263,7 +272,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
struct p54_channel_list *list;
- unsigned int i, j, max_channel_num;
+ unsigned int i, j, k, max_channel_num;
int ret = 0;
u16 freq;
@@ -283,6 +292,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
ret = -ENOMEM;
goto free;
}
+ priv->chan_num = max_channel_num;
+ priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num,
+ GFP_KERNEL);
+ if (!priv->survey) {
+ ret = -ENOMEM;
+ goto free;
+ }
list->max_entries = max_channel_num;
list->channels = kzalloc(sizeof(struct p54_channel_entry) *
@@ -321,8 +337,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
p54_compare_channels, NULL);
+ k = 0;
for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
- if (p54_generate_band(dev, list, i) == 0)
+ if (p54_generate_band(dev, list, &k, i) == 0)
j++;
}
if (j == 0) {
@@ -335,6 +352,10 @@ free:
kfree(list->channels);
kfree(list);
}
+ if (ret) {
+ kfree(priv->survey);
+ priv->survey = NULL;
+ }
return ret;
}
@@ -853,10 +874,12 @@ err:
kfree(priv->output_limit);
kfree(priv->curve_data);
kfree(priv->rssi_db);
+ kfree(priv->survey);
priv->iq_autocal = NULL;
priv->output_limit = NULL;
priv->curve_data = NULL;
priv->rssi_db = NULL;
+ priv->survey = NULL;
wiphy_err(dev->wiphy, "eeprom parse failed!\n");
return err;
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index b6a061c..18e82b3 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
+#include <linux/export.h>
#include <net/mac80211.h>
@@ -385,6 +386,7 @@ int p54_setup_mac(struct p54_common *priv)
setup->v2.osc_start_delay = cpu_to_le16(65535);
}
p54_tx(priv, skb);
+ priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE;
return 0;
}
@@ -626,6 +628,7 @@ int p54_set_ps(struct p54_common *priv)
psm->exclude[0] = WLAN_EID_TIM;
p54_tx(priv, skb);
+ priv->phy_ps = mode != P54_PSM_CAM;
return 0;
}
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index a5a6d9e..db4d9a0 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
+#include <linux/module.h>
#include <net/mac80211.h>
@@ -204,13 +205,11 @@ static void p54_stop(struct ieee80211_hw *dev)
struct p54_common *priv = dev->priv;
int i;
- mutex_lock(&priv->conf_mutex);
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
priv->softled_state = 0;
- p54_set_leds(priv);
-
cancel_delayed_work_sync(&priv->work);
-
+ mutex_lock(&priv->conf_mutex);
+ p54_set_leds(priv);
priv->stop(dev);
skb_queue_purge(&priv->tx_pending);
skb_queue_purge(&priv->tx_queue);
@@ -278,6 +277,42 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
mutex_unlock(&priv->conf_mutex);
}
+static int p54_wait_for_stats(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ int ret;
+
+ priv->update_stats = true;
+ ret = p54_fetch_statistics(priv);
+ if (ret)
+ return ret;
+
+ ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ);
+ if (ret == 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static void p54_reset_stats(struct p54_common *priv)
+{
+ struct ieee80211_channel *chan = priv->curchan;
+
+ if (chan) {
+ struct survey_info *info = &priv->survey[chan->hw_value];
+
+ /* only reset channel statistics, don't touch .filled, etc. */
+ info->channel_time = 0;
+ info->channel_time_busy = 0;
+ info->channel_time_tx = 0;
+ }
+
+ priv->update_stats = true;
+ priv->survey_raw.active = 0;
+ priv->survey_raw.cca = 0;
+ priv->survey_raw.tx = 0;
+}
+
static int p54_config(struct ieee80211_hw *dev, u32 changed)
{
int ret = 0;
@@ -288,19 +323,36 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_POWER)
priv->output_power = conf->power_level << 2;
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ struct ieee80211_channel *oldchan;
+ WARN_ON(p54_wait_for_stats(dev));
+ oldchan = priv->curchan;
+ priv->curchan = NULL;
ret = p54_scan(priv, P54_SCAN_EXIT, 0);
- if (ret)
+ if (ret) {
+ priv->curchan = oldchan;
goto out;
+ }
+ /*
+ * TODO: Use the LM_SCAN_TRAP to determine the current
+ * operating channel.
+ */
+ priv->curchan = priv->hw->conf.channel;
+ p54_reset_stats(priv);
+ WARN_ON(p54_fetch_statistics(priv));
}
if (changed & IEEE80211_CONF_CHANGE_PS) {
+ WARN_ON(p54_wait_for_stats(dev));
ret = p54_set_ps(priv);
if (ret)
goto out;
+ WARN_ON(p54_wait_for_stats(dev));
}
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+ WARN_ON(p54_wait_for_stats(dev));
ret = p54_setup_mac(priv);
if (ret)
goto out;
+ WARN_ON(p54_wait_for_stats(dev));
}
out:
@@ -353,7 +405,8 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
p54_set_groupfilter(priv);
}
-static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
+static int p54_conf_tx(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct p54_common *priv = dev->priv;
@@ -384,7 +437,9 @@ static void p54_work(struct work_struct *work)
* 2. cancel stuck frames / reset the device if necessary.
*/
- p54_fetch_statistics(priv);
+ mutex_lock(&priv->conf_mutex);
+ WARN_ON_ONCE(p54_fetch_statistics(priv));
+ mutex_unlock(&priv->conf_mutex);
}
static int p54_get_stats(struct ieee80211_hw *dev,
@@ -541,16 +596,47 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,
struct survey_info *survey)
{
struct p54_common *priv = dev->priv;
- struct ieee80211_conf *conf = &dev->conf;
+ struct ieee80211_channel *chan;
+ int err, tries;
+ bool in_use = false;
- if (idx != 0)
+ if (idx >= priv->chan_num)
return -ENOENT;
- survey->channel = conf->channel;
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = clamp_t(s8, priv->noise, -128, 127);
+#define MAX_TRIES 1
+ for (tries = 0; tries < MAX_TRIES; tries++) {
+ chan = priv->curchan;
+ if (chan && chan->hw_value == idx) {
+ mutex_lock(&priv->conf_mutex);
+ err = p54_wait_for_stats(dev);
+ mutex_unlock(&priv->conf_mutex);
+ if (err)
+ return err;
+
+ in_use = true;
+ }
- return 0;
+ memcpy(survey, &priv->survey[idx], sizeof(*survey));
+
+ if (in_use) {
+ /* test if the reported statistics are valid. */
+ if (survey->channel_time != 0) {
+ survey->filled |= SURVEY_INFO_IN_USE;
+ } else {
+ /*
+ * hw/fw has not accumulated enough sample sets.
+ * Wait for 100ms, this ought to be enough to
+ * to get at least one non-null set of channel
+ * usage statistics.
+ */
+ msleep(100);
+ continue;
+ }
+ }
+ return 0;
+ }
+ return -ETIMEDOUT;
+#undef MAX_TRIES
}
static unsigned int p54_flush_count(struct p54_common *priv)
@@ -686,11 +772,14 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
mutex_init(&priv->conf_mutex);
mutex_init(&priv->eeprom_mutex);
+ init_completion(&priv->stat_comp);
init_completion(&priv->eeprom_comp);
init_completion(&priv->beacon_comp);
INIT_DELAYED_WORK(&priv->work, p54_work);
memset(&priv->mc_maclist[0], ~0, ETH_ALEN);
+ priv->curchan = NULL;
+ p54_reset_stats(priv);
return dev;
}
EXPORT_SYMBOL_GPL(p54_init_common);
@@ -730,11 +819,13 @@ void p54_free_common(struct ieee80211_hw *dev)
kfree(priv->curve_data);
kfree(priv->rssi_db);
kfree(priv->used_rxkeys);
+ kfree(priv->survey);
priv->iq_autocal = NULL;
priv->output_limit = NULL;
priv->curve_data = NULL;
priv->rssi_db = NULL;
priv->used_rxkeys = NULL;
+ priv->survey = NULL;
ieee80211_free_hw(dev);
}
EXPORT_SYMBOL_GPL(p54_free_common);
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 799d05e..452fa3a 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -199,6 +199,22 @@ struct p54_common {
u8 tx_diversity_mask;
unsigned int output_power;
struct p54_rssi_db_entry *cur_rssi;
+ struct ieee80211_channel *curchan;
+ struct survey_info *survey;
+ unsigned int chan_num;
+ struct completion stat_comp;
+ bool update_stats;
+ struct {
+ unsigned int timestamp;
+ unsigned int cached_cca;
+ unsigned int cached_tx;
+ unsigned int cached_rssi;
+ u64 active;
+ u64 cca;
+ u64 tx;
+ u64 rssi;
+ } survey_raw;
+
int noise;
/* calibration, output power limit and rssi<->dBm conversation data */
struct pda_iq_autocal_entry *iq_autocal;
@@ -220,6 +236,8 @@ struct p54_common {
u32 basic_rate_mask;
u16 aid;
u8 coverage_class;
+ bool phy_idle;
+ bool phy_ps;
bool powersave_override;
__le32 beacon_req_id;
struct completion beacon_comp;
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 1b75317..b1f51a2 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -20,6 +20,7 @@
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/completion.h>
+#include <linux/module.h>
#include <net/mac80211.h>
#include "p54.h"
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index ee9bc62..7aa509f 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -1,5 +1,6 @@
#ifndef P54PCI_H
#define P54PCI_H
+#include <linux/interrupt.h>
/*
* Defines for PCI based mac80211 Prism54 driver
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index d895ff9..428401b 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -41,7 +41,6 @@
#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
MODULE_FIRMWARE("3826.arm");
-MODULE_ALIAS("stlc45xx");
/*
* gpios should be handled in board files and provided via platform data,
@@ -745,3 +744,4 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
MODULE_ALIAS("spi:cx3110x");
MODULE_ALIAS("spi:p54spi");
+MODULE_ALIAS("spi:stlc45xx");
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 0de0837..0784493 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -20,6 +20,7 @@
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/crc32.h>
+#include <linux/module.h>
#include <net/mac80211.h>
#include "p54.h"
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 042842e..6ed9c32 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -16,9 +16,11 @@
* published by the Free Software Foundation.
*/
+#include <linux/export.h>
#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
+#include <asm/div64.h>
#include <net/mac80211.h>
@@ -507,6 +509,8 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
struct sk_buff *tmp;
+ struct ieee80211_channel *chan;
+ unsigned int i, rssi, tx, cca, dtime, dtotal, dcca, dtx, drssi, unit;
u32 tsf32;
if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
@@ -523,8 +527,75 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise));
+ /*
+ * STSW450X LMAC API page 26 - 3.8 Statistics
+ * "The exact measurement period can be derived from the
+ * timestamp member".
+ */
+ dtime = tsf32 - priv->survey_raw.timestamp;
+
+ /*
+ * STSW450X LMAC API page 26 - 3.8.1 Noise histogram
+ * The LMAC samples RSSI, CCA and transmit state at regular
+ * periods (typically 8 times per 1k [as in 1024] usec).
+ */
+ cca = le32_to_cpu(stats->sample_cca);
+ tx = le32_to_cpu(stats->sample_tx);
+ rssi = 0;
+ for (i = 0; i < ARRAY_SIZE(stats->sample_noise); i++)
+ rssi += le32_to_cpu(stats->sample_noise[i]);
+
+ dcca = cca - priv->survey_raw.cached_cca;
+ drssi = rssi - priv->survey_raw.cached_rssi;
+ dtx = tx - priv->survey_raw.cached_tx;
+ dtotal = dcca + drssi + dtx;
+
+ /*
+ * update statistics when more than a second is over since the
+ * last call, or when a update is badly needed.
+ */
+ if (dtotal && (priv->update_stats || dtime >= USEC_PER_SEC) &&
+ dtime >= dtotal) {
+ priv->survey_raw.timestamp = tsf32;
+ priv->update_stats = false;
+ unit = dtime / dtotal;
+
+ if (dcca) {
+ priv->survey_raw.cca += dcca * unit;
+ priv->survey_raw.cached_cca = cca;
+ }
+ if (dtx) {
+ priv->survey_raw.tx += dtx * unit;
+ priv->survey_raw.cached_tx = tx;
+ }
+ if (drssi) {
+ priv->survey_raw.rssi += drssi * unit;
+ priv->survey_raw.cached_rssi = rssi;
+ }
+
+ /* 1024 usec / 8 times = 128 usec / time */
+ if (!(priv->phy_ps || priv->phy_idle))
+ priv->survey_raw.active += dtotal * unit;
+ else
+ priv->survey_raw.active += (dcca + dtx) * unit;
+ }
+
+ chan = priv->curchan;
+ if (chan) {
+ struct survey_info *survey = &priv->survey[chan->hw_value];
+ survey->noise = clamp_t(s8, priv->noise, -128, 127);
+ survey->channel_time = priv->survey_raw.active;
+ survey->channel_time_tx = priv->survey_raw.tx;
+ survey->channel_time_busy = priv->survey_raw.tx +
+ priv->survey_raw.cca;
+ do_div(survey->channel_time, 1024);
+ do_div(survey->channel_time_tx, 1024);
+ do_div(survey->channel_time_busy, 1024);
+ }
+
tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
dev_kfree_skb_any(tmp);
+ complete(&priv->stat_comp);
}
static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
@@ -619,7 +690,7 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb,
if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
*flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
- if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)
+ if (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)
*flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index d97a2ca..bc2ba80 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -778,7 +778,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
dwrq->flags = 0;
dwrq->length = 0;
}
- essid->octets[essid->length] = '\0';
+ essid->octets[dwrq->length] = '\0';
memcpy(extra, essid->octets, dwrq->length);
kfree(essid);
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index ec2c75d..e2fa538 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -18,6 +18,7 @@
*
*/
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -811,6 +812,10 @@ static const struct net_device_ops islpci_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
+static struct device_type wlan_type = {
+ .name = "wlan",
+};
+
struct net_device *
islpci_setup(struct pci_dev *pdev)
{
@@ -821,9 +826,8 @@ islpci_setup(struct pci_dev *pdev)
return ndev;
pci_set_drvdata(pdev, ndev);
-#if defined(SET_NETDEV_DEV)
SET_NETDEV_DEV(ndev, &pdev->dev);
-#endif
+ SET_NETDEV_DEVTYPE(ndev, &wlan_type);
/* setup the structure members */
ndev->base_addr = pci_resource_start(pdev, 0);
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index c4d0f19..c404038 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -22,6 +22,7 @@
#ifndef _ISLPCI_DEV_H
#define _ISLPCI_DEV_H
+#include <linux/irqreturn.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index b5e64d7..9e68e0c 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index b2f8b8f..a0a7854 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -83,14 +83,12 @@ config RT2800PCI_RT33XX
config RT2800PCI_RT35XX
bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt35xx wireless chipset family to the
rt2800pci driver.
Supported chips: RT3060, RT3062, RT3562, RT3592
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
config RT2800PCI_RT53XX
bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
@@ -154,15 +152,12 @@ config RT2800USB_RT33XX
config RT2800USB_RT35XX
bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt35xx wireless chipset family to the
rt2800usb driver.
Supported chips: RT3572
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
config RT2800USB_RT53XX
bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 1493171..131b22b 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -645,11 +645,6 @@ static void rt2400pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- /*
- * Allow the tbtt tasklet to be scheduled.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -715,7 +710,7 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
/*
* Wait for possibly running tbtt tasklets.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
@@ -982,12 +977,6 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
- /*
- * Enable tasklets.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
}
/*
@@ -1011,8 +1000,9 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* Ensure that all tasklets are finished before
* disabling the interrupts.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
}
}
@@ -1249,7 +1239,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
* call, we must decrease the higher 32bits with 1 to get
* to correct value.
*/
- tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw);
+ tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);
rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
rx_high = upper_32_bits(tsf);
@@ -1263,7 +1253,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
*/
rxdesc->timestamp = ((u64)rx_high << 32) | rx_low;
rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
- rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) -
+ rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) -
entry->queue->rt2x00dev->rssi_offset;
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
@@ -1347,22 +1337,25 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
/*
* Enable all TXDONE interrupts again.
*/
- spin_lock_irq(&rt2x00dev->irqmask_lock);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+ spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
- rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR8, reg);
- spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ }
}
static void rt2400pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
}
static void rt2400pci_rxdone_tasklet(unsigned long data)
@@ -1370,7 +1363,7 @@ static void rt2400pci_rxdone_tasklet(unsigned long data)
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
}
@@ -1664,7 +1657,8 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1677,7 +1671,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
if (queue != 0)
return -EINVAL;
- if (rt2x00mac_conf_tx(hw, queue, params))
+ if (rt2x00mac_conf_tx(hw, vif, queue, params))
return -EINVAL;
/*
@@ -1689,7 +1683,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
-static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
+static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
@@ -1732,6 +1727,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index cdd480f..aa10c48 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -735,11 +735,6 @@ static void rt2500pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- /*
- * Allow the tbtt tasklet to be scheduled.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -805,7 +800,7 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
/*
* Wait for possibly running tbtt tasklets.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
@@ -1137,12 +1132,6 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
- /*
- * Enable tasklets.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
}
/*
@@ -1165,8 +1154,9 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
/*
* Ensure that all tasklets are finished.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
}
}
@@ -1479,22 +1469,25 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
/*
* Enable all TXDONE interrupts again.
*/
- spin_lock_irq(&rt2x00dev->irqmask_lock);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+ spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
- rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR8, reg);
- spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ }
}
static void rt2500pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
}
static void rt2500pci_rxdone_tasklet(unsigned long data)
@@ -1502,7 +1495,7 @@ static void rt2500pci_rxdone_tasklet(unsigned long data)
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
}
@@ -1982,7 +1975,8 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
+static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
@@ -2025,6 +2019,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index f124a1b..2be9880 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1836,6 +1836,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1920,7 +1921,7 @@ static struct usb_device_id rt2500usb_device_table[] = {
{ USB_DEVICE(0x0b05, 0x1706) },
{ USB_DEVICE(0x0b05, 0x1707) },
/* Belkin */
- { USB_DEVICE(0x050d, 0x7050) },
+ { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050A ver. 2.x */
{ USB_DEVICE(0x050d, 0x7051) },
/* Cisco Systems */
{ USB_DEVICE(0x13b1, 0x000d) },
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index f67bc9b..5396e3b 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -664,6 +664,9 @@
/*
* LED_CFG: LED control
+ * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1)
+ * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1)
+ * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)
* color LED's:
* 0: off
* 1: blinking upon TX2
@@ -1734,12 +1737,13 @@ struct mac_iveiv_entry {
* 2 - drop tx power by 12dBm,
* 3 - increase tx power by 6dBm
*/
-#define BBP1_TX_POWER_CTRL FIELD8(0x07)
+#define BBP1_TX_POWER_CTRL FIELD8(0x03)
#define BBP1_TX_ANTENNA FIELD8(0x18)
/*
* BBP 3: RX Antenna
*/
+#define BBP3_RX_ADC FIELD8(0x03)
#define BBP3_RX_ANTENNA FIELD8(0x18)
#define BBP3_HT40_MINUS FIELD8(0x20)
@@ -1783,6 +1787,8 @@ struct mac_iveiv_entry {
#define RFCSR1_TX0_PD FIELD8(0x08)
#define RFCSR1_RX1_PD FIELD8(0x10)
#define RFCSR1_TX1_PD FIELD8(0x20)
+#define RFCSR1_RX2_PD FIELD8(0x40)
+#define RFCSR1_TX2_PD FIELD8(0x80)
/*
* RFCSR 2:
@@ -1790,15 +1796,25 @@ struct mac_iveiv_entry {
#define RFCSR2_RESCAL_EN FIELD8(0x80)
/*
+ * FRCSR 5:
+ */
+#define RFCSR5_R1 FIELD8(0x0c)
+
+/*
* RFCSR 6:
*/
#define RFCSR6_R1 FIELD8(0x03)
#define RFCSR6_R2 FIELD8(0x40)
+#define RFCSR6_TXDIV FIELD8(0x0c)
/*
* RFCSR 7:
*/
#define RFCSR7_RF_TUNING FIELD8(0x01)
+#define RFCSR7_R02 FIELD8(0x07)
+#define RFCSR7_R3 FIELD8(0x08)
+#define RFCSR7_R45 FIELD8(0x30)
+#define RFCSR7_R67 FIELD8(0xc0)
/*
* RFCSR 11:
@@ -1809,11 +1825,13 @@ struct mac_iveiv_entry {
* RFCSR 12:
*/
#define RFCSR12_TX_POWER FIELD8(0x1f)
+#define RFCSR12_DR0 FIELD8(0xe0)
/*
* RFCSR 13:
*/
#define RFCSR13_TX_POWER FIELD8(0x1f)
+#define RFCSR13_DR0 FIELD8(0xe0)
/*
* RFCSR 15:
@@ -2256,6 +2274,7 @@ struct mac_iveiv_entry {
#define MCU_ANT_SELECT 0X73
#define MCU_BBP_SIGNAL 0x80
#define MCU_POWER_SAVE 0x83
+#define MCU_BAND_SELECT 0x91
/*
* MCU mailbox tokens
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 62b92c4..8fb8c9e 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -38,7 +38,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/sched.h>
#include "rt2x00.h"
#include "rt2800lib.h"
@@ -402,7 +401,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
return -EBUSY;
if (rt2x00_is_pci(rt2x00dev)) {
- if (rt2x00_rt(rt2x00dev, RT5390)) {
+ if (rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -493,7 +493,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- txdesc->key_idx : 0xff);
+ txdesc->key_idx : txdesc->u.ht.wcid);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length);
rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
@@ -601,59 +601,7 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
-static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
-{
- __le32 *txwi;
- u32 word;
- int wcid, ack, pid;
- int tx_wcid, tx_ack, tx_pid;
-
- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
- WARNING(entry->queue->rt2x00dev,
- "Data pending for entry %u in queue %u\n",
- entry->entry_idx, entry->queue->qid);
- cond_resched();
- return false;
- }
-
- wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
- pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-
- /*
- * This frames has returned with an IO error,
- * so the status report is not intended for this
- * frame.
- */
- if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
- return false;
- }
-
- /*
- * Validate if this TX status report is intended for
- * this entry by comparing the WCID/ACK/PID fields.
- */
- txwi = rt2800_drv_get_txwi(entry);
-
- rt2x00_desc_read(txwi, 1, &word);
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
- tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
- tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
- if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
- WARNING(entry->queue->rt2x00dev,
- "TX status report missed for queue %d entry %d\n",
- entry->queue->qid, entry->entry_idx);
- rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
- return false;
- }
-
- return true;
-}
-
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@@ -661,13 +609,11 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
u32 word;
u16 mcs, real_mcs;
int aggr, ampdu;
- __le32 *txwi;
/*
* Obtain the status about this packet.
*/
txdesc.flags = 0;
- txwi = rt2800_drv_get_txwi(entry);
rt2x00_desc_read(txwi, 0, &word);
mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
@@ -735,44 +681,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
}
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue;
- struct queue_entry *entry;
- u32 reg;
- u8 qid;
-
- while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-
- /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
- * qid is guaranteed to be one of the TX QIDs
- */
- qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
- queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
- if (unlikely(!queue)) {
- WARNING(rt2x00dev, "Got TX status for an unavailable "
- "queue %u, dropping\n", qid);
- continue;
- }
-
- /*
- * Inside each queue, we process each entry in a chronological
- * order. We first check that the queue is not empty.
- */
- entry = NULL;
- while (!rt2x00queue_empty(queue)) {
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- if (rt2800_txdone_entry_check(entry, reg))
- break;
- entry = NULL;
- }
-
- if (entry)
- rt2800_txdone_entry(entry, reg);
- }
-}
-EXPORT_SYMBOL_GPL(rt2800_txdone);
-
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -989,28 +897,12 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
}
}
-static int rt2800_blink_set(struct led_classdev *led_cdev,
- unsigned long *delay_on, unsigned long *delay_off)
-{
- struct rt2x00_led *led =
- container_of(led_cdev, struct rt2x00_led, led_dev);
- u32 reg;
-
- rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
- rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
- rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
- rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
-
- return 0;
-}
-
static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led, enum led_type type)
{
led->rt2x00dev = rt2x00dev;
led->type = type;
led->led_dev.brightness_set = rt2800_brightness_set;
- led->led_dev.blink_set = rt2800_blink_set;
led->flags = LED_INITIALIZED;
}
#endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -1018,11 +910,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
/*
* Configuration handlers.
*/
-static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
+static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
+ const u8 *address,
+ int wcid)
{
struct mac_wcid_entry wcid_entry;
+ u32 offset;
+
+ offset = MAC_WCID_ENTRY(wcid);
+
+ memset(&wcid_entry, 0xff, sizeof(wcid_entry));
+ if (address)
+ memcpy(wcid_entry.mac, address, ETH_ALEN);
+
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &wcid_entry, sizeof(wcid_entry));
+}
+
+static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+ u32 offset;
+ offset = MAC_WCID_ATTR_ENTRY(wcid);
+ rt2800_register_write(rt2x00dev, offset, 0);
+}
+
+static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
+ int wcid, u32 bssidx)
+{
+ u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
+ u32 reg;
+
+ /*
+ * The BSS Idx numbers is split in a main value of 3 bits,
+ * and a extended field for adding one additional bit to the value.
+ */
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
+ (bssidx & 0x8) >> 3);
+ rt2800_register_write(rt2x00dev, offset, reg);
+}
+
+static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
struct mac_iveiv_entry iveiv_entry;
u32 offset;
u32 reg;
@@ -1042,14 +974,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
(crypto->cipher & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
(crypto->cipher & 0x8) >> 3);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
- (crypto->bssidx & 0x7));
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
- (crypto->bssidx & 0x8) >> 3);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
rt2800_register_write(rt2x00dev, offset, reg);
} else {
- rt2800_register_write(rt2x00dev, offset, 0);
+ /* Delete the cipher without touching the bssidx */
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
+ rt2800_register_write(rt2x00dev, offset, reg);
}
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
@@ -1062,14 +996,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
iveiv_entry.iv[3] |= key->keyidx << 6;
rt2800_register_multiwrite(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry));
-
- offset = MAC_WCID_ENTRY(key->hw_key_idx);
-
- memset(&wcid_entry, 0, sizeof(wcid_entry));
- if (crypto->cmd == SET_KEY)
- memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
- rt2800_register_multiwrite(rt2x00dev, offset,
- &wcid_entry, sizeof(wcid_entry));
}
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -1116,20 +1042,24 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
/*
* Update WCID information
*/
- rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+ rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
+ rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
+ crypto->bssidx);
+ rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
-static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
+static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
{
+ struct mac_wcid_entry wcid_entry;
int idx;
- u32 offset, reg;
+ u32 offset;
/*
- * Search for the first free pairwise key entry and return the
- * corresponding index.
+ * Search for the first free WCID entry and return the corresponding
+ * index.
*
* Make sure the WCID starts _after_ the last possible shared key
* entry (>32).
@@ -1139,11 +1069,17 @@ static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
* first 222 entries.
*/
for (idx = 33; idx <= 222; idx++) {
- offset = MAC_WCID_ATTR_ENTRY(idx);
- rt2800_register_read(rt2x00dev, offset, &reg);
- if (!reg)
+ offset = MAC_WCID_ENTRY(idx);
+ rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
+ sizeof(wcid_entry));
+ if (is_broadcast_ether_addr(wcid_entry.mac))
return idx;
}
+
+ /*
+ * Use -1 to indicate that we don't have any more space in the WCID
+ * table.
+ */
return -1;
}
@@ -1153,13 +1089,15 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
{
struct hw_key_entry key_entry;
u32 offset;
- int idx;
if (crypto->cmd == SET_KEY) {
- idx = rt2800_find_pairwise_keyslot(rt2x00dev);
- if (idx < 0)
+ /*
+ * Allow key configuration only for STAs that are
+ * known by the hw.
+ */
+ if (crypto->wcid < 0)
return -ENOSPC;
- key->hw_key_idx = idx;
+ key->hw_key_idx = crypto->wcid;
memcpy(key_entry.key, crypto->key,
sizeof(key_entry.key));
@@ -1176,12 +1114,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
/*
* Update WCID information
*/
- rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+ rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ int wcid;
+ struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+ /*
+ * Find next free WCID.
+ */
+ wcid = rt2800_find_wcid(rt2x00dev);
+
+ /*
+ * Store selected wcid even if it is invalid so that we can
+ * later decide if the STA is uploaded into the hw.
+ */
+ sta_priv->wcid = wcid;
+
+ /*
+ * No space left in the device, however, we can still communicate
+ * with the STA -> No error.
+ */
+ if (wcid < 0)
+ return 0;
+
+ /*
+ * Clean up WCID attributes and write STA address to the device.
+ */
+ rt2800_delete_wcid_attr(rt2x00dev, wcid);
+ rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
+ rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
+ rt2x00lib_get_bssidx(rt2x00dev, vif));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_add);
+
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+ /*
+ * Remove WCID entry, no need to clean the attributes as they will
+ * get renewed when the WCID is reused.
+ */
+ rt2800_config_wcid(rt2x00dev, NULL, wcid);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_remove);
+
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
@@ -1363,7 +1348,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
gf20_rate = gf40_rate = 0x0003;
}
break;
- };
+ }
/* check for STAs not supporting greenfield mode */
if (any_sta_nongf)
@@ -1441,6 +1426,40 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
}
EXPORT_SYMBOL_GPL(rt2800_config_erp);
+static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+ u16 eeprom;
+ u8 led_ctrl, led_g_mode, led_r_mode;
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
+ } else {
+ rt2x00_set_field32(&reg, GPIO_SWITCH_0, 0);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_1, 0);
+ }
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+ rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+ led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
+ led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
+ if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
+ led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
+ if (led_ctrl == 0 || led_ctrl > 0x40) {
+ rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
+ rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, led_r_mode);
+ rt2800_register_write(rt2x00dev, LED_CFG, reg);
+ } else {
+ rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,
+ (led_g_mode << 2) | led_r_mode, 1);
+ }
+ }
+}
+
static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
enum antenna ant)
{
@@ -1471,6 +1490,10 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2800_bbp_read(rt2x00dev, 1, &r1);
rt2800_bbp_read(rt2x00dev, 3, &r3);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2800_config_3572bt_ant(rt2x00dev);
+
/*
* Configure the TX antenna.
*/
@@ -1479,7 +1502,11 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
break;
case 2:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);
+ else
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
break;
case 3:
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
@@ -1504,7 +1531,15 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
break;
case 2:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+ rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,
+ rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+ rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);
+ } else {
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ }
break;
case 3:
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
@@ -1638,6 +1673,161 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}
+static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+ u32 reg;
+
+ if (rf->channel <= 14) {
+ rt2800_bbp_write(rt2x00dev, 25, 0x15);
+ rt2800_bbp_write(rt2x00dev, 26, 0x85);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 25, 0x09);
+ rt2800_bbp_write(rt2x00dev, 26, 0xff);
+ }
+
+ rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
+ rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ (info->default_power1 & 0x3) |
+ ((info->default_power1 & 0xC) << 1));
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ (info->default_power1 & 0x3) |
+ ((info->default_power1 & 0xC) << 1));
+ }
+ rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+ (info->default_power2 & 0x3) |
+ ((info->default_power2 & 0xC) << 1));
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+ (info->default_power2 & 0x3) |
+ ((info->default_power2 & 0xC) << 1));
+ }
+ rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+ }
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ } else {
+ switch (rt2x00dev->default_ant.tx_chain_num) {
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ break;
+ }
+
+ switch (rt2x00dev->default_ant.rx_chain_num) {
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ break;
+ }
+ }
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+ rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+ rt2800_rfcsr_write(rt2x00dev, 24,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+ rt2800_rfcsr_write(rt2x00dev, 31,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+
+ if (rf->channel <= 14) {
+ rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+ } else {
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x14);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x43);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x7a);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ if (rf->channel <= 64) {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+ } else if (rf->channel <= 128) {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x74);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ } else {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x72);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ }
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x87);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
+ }
+
+ rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT7, 0);
+ if (rf->channel <= 14)
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 1);
+ else
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 0);
+ rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+ rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+}
#define RT5390_POWER_BOUND 0x27
#define RT5390_FREQ_OFFSET_BOUND 0x5f
@@ -1756,9 +1946,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_rf(rt2x00dev, RF3020) ||
rt2x00_rf(rt2x00dev, RF3021) ||
rt2x00_rf(rt2x00dev, RF3022) ||
- rt2x00_rf(rt2x00dev, RF3052) ||
rt2x00_rf(rt2x00dev, RF3320))
rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+ else if (rt2x00_rf(rt2x00dev, RF3052))
+ rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
else if (rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5390))
rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
@@ -1785,7 +1976,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
}
}
} else {
- rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_bbp_write(rt2x00dev, 82, 0x94);
+ else
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
rt2800_bbp_write(rt2x00dev, 75, 0x46);
@@ -1799,12 +1993,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0);
+
tx_pin = 0;
/* Turn on unused PA or LNA when not using 1T or 1R */
if (rt2x00dev->default_ant.tx_chain_num == 2) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
+ rf->channel > 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
+ rf->channel <= 14);
}
/* Turn on unused PA or LNA when not using 1T or 1R */
@@ -1817,11 +2016,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+ else
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,
+ rf->channel <= 14);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
+
rt2800_bbp_read(rt2x00dev, 4, &bbp);
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
rt2800_bbp_write(rt2x00dev, 4, bbp);
@@ -2428,6 +2634,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
} else if (rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -2644,11 +2853,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
SHARED_KEY_MODE_ENTRY(i), 0);
for (i = 0; i < 256; i++) {
- static const u32 wcid[2] = { 0xffffffff, 0x00ffffff };
- rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
- wcid, sizeof(wcid));
-
- rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0);
+ rt2800_config_wcid(rt2x00dev, NULL, i);
+ rt2800_delete_wcid_attr(rt2x00dev, i);
rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
}
@@ -2814,6 +3020,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
}
if (rt2800_is_305x_soc(rt2x00dev) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 31, 0x08);
@@ -2843,6 +3050,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_bbp_write(rt2x00dev, 79, 0x13);
rt2800_bbp_write(rt2x00dev, 80, 0x05);
@@ -2883,6 +3091,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2800_is_305x_soc(rt2x00dev))
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
@@ -2910,6 +3119,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_bbp_read(rt2x00dev, 138, &value);
@@ -3046,6 +3256,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
!rt2x00_rt(rt2x00dev, RT3071) &&
!rt2x00_rt(rt2x00dev, RT3090) &&
!rt2x00_rt(rt2x00dev, RT3390) &&
+ !rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) &&
!rt2800_is_305x_soc(rt2x00dev))
return 0;
@@ -3124,6 +3335,38 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x05);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x65);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0xac);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
} else if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
@@ -3273,6 +3516,19 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ msleep(1);
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
}
/*
@@ -3285,7 +3541,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
} else if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572)) {
rt2x00dev->calibration[0] =
rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
rt2x00dev->calibration[1] =
@@ -3958,7 +4215,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
- IEEE80211_HW_AMPDU_AGGREGATION;
+ IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL;
/*
* Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
* unless we are capable of sending the buffered frames out after the
@@ -4082,8 +4340,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
for (i = 14; i < spec->num_channels; i++) {
- info[i].default_power1 = default_power1[i - 14];
- info[i].default_power2 = default_power2[i - 14];
+ info[i].default_power1 = default_power1[i];
+ info[i].default_power2 = default_power2[i];
}
}
@@ -4148,7 +4406,8 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
}
EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold);
-int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+int rt2800_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -4164,7 +4423,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
* we are free to update the registers based on the value
* in the queue parameter.
*/
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
if (retval)
return retval;
@@ -4216,7 +4475,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
}
EXPORT_SYMBOL_GPL(rt2800_conf_tx);
-u64 rt2800_get_tsf(struct ieee80211_hw *hw)
+u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
@@ -4236,8 +4495,19 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size)
{
+ struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
int ret = 0;
+ /*
+ * Don't allow aggregation for stations the hardware isn't aware
+ * of because tx status reports for frames to an unknown station
+ * always contain wcid=255 and thus we can't distinguish between
+ * multiple stations which leads to unwanted situations when the
+ * hw reorders frames due to aggregation.
+ */
+ if (sta_priv->wcid < 0)
+ return 1;
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index f2d1594..8c3c281 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -152,8 +152,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry);
@@ -167,6 +166,9 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
@@ -195,9 +197,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev);
void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
u16 *iv16);
int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+int rt2800_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params);
-u64 rt2800_get_tsf(struct ieee80211_hw *hw);
+u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index e947d3a..518157d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -200,13 +200,6 @@ static void rt2800pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- /*
- * Allow beacon tasklets to be scheduled for periodic
- * beacon updates.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
- tasklet_enable(&rt2x00dev->pretbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
@@ -219,7 +212,7 @@ static void rt2800pci_start_queue(struct data_queue *queue)
break;
default:
break;
- };
+ }
}
static void rt2800pci_kick_queue(struct data_queue *queue)
@@ -269,10 +262,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
/*
- * Wait for tbtt tasklets to finish.
+ * Wait for current invocation to finish. The tasklet
+ * won't be scheduled anymore afterwards since we disabled
+ * the TBTT and PRE TBTT timer.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
- tasklet_disable(&rt2x00dev->pretbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+
break;
default:
break;
@@ -436,14 +432,6 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
- /*
- * Enable tasklets. The beacon related tasklets are
- * enabled when the beacon queue is started.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
- tasklet_enable(&rt2x00dev->autowake_tasklet);
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
@@ -460,12 +448,13 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_OFF) {
/*
- * Ensure that all tasklets are finished before
- * disabling the interrupts.
+ * Wait for possibly running tasklets to finish.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
- tasklet_disable(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->pretbtt_tasklet);
}
}
@@ -489,7 +478,9 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
- if (rt2x00_rt(rt2x00dev, RT5390)) {
+ if (rt2x00_is_pcie(rt2x00dev) &&
+ (rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390))) {
rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -616,11 +607,11 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
/*
* Initialize TX descriptor
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
rt2x00_desc_write(txd, 0, word);
- rt2x00_desc_read(txd, 1, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
@@ -631,12 +622,12 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
skbdesc->skb_dma + TXWI_DESC_SIZE);
rt2x00_desc_write(txd, 2, word);
- rt2x00_desc_read(txd, 3, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W3_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
@@ -757,7 +748,7 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
}
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- rt2800_txdone_entry(entry, status);
+ rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));
if (--max_tx_done == 0)
break;
@@ -799,14 +790,16 @@ static void rt2800pci_pretbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_pretbtt(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
}
static void rt2800pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
}
static void rt2800pci_rxdone_tasklet(unsigned long data)
@@ -814,7 +807,7 @@ static void rt2800pci_rxdone_tasklet(unsigned long data)
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
}
@@ -822,7 +815,8 @@ static void rt2800pci_autowake_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2800pci_wakeup(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
}
static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
@@ -1018,6 +1012,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
+ .sta_add = rt2x00mac_sta_add,
+ .sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
@@ -1026,6 +1022,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -1078,6 +1075,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+ .sta_add = rt2800_sta_add,
+ .sta_remove = rt2800_sta_remove,
};
static const struct data_queue_desc rt2800pci_queue_rx = {
@@ -1155,6 +1154,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
#endif
#ifdef CONFIG_RT2800PCI_RT53XX
{ PCI_DEVICE(0x1814, 0x5390) },
+ { PCI_DEVICE(0x1814, 0x539a) },
{ PCI_DEVICE(0x1814, 0x539f) },
#endif
{ 0, }
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 9366ef0..ee7efd2 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -457,6 +457,96 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/*
* TX control handlers
*/
+static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+ __le32 *txwi;
+ u32 word;
+ int wcid, ack, pid;
+ int tx_wcid, tx_ack, tx_pid;
+
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+ !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
+ WARNING(entry->queue->rt2x00dev,
+ "Data pending for entry %u in queue %u\n",
+ entry->entry_idx, entry->queue->qid);
+ cond_resched();
+ return false;
+ }
+
+ wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+ ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+ pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+
+ /*
+ * This frames has returned with an IO error,
+ * so the status report is not intended for this
+ * frame.
+ */
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ return false;
+ }
+
+ /*
+ * Validate if this TX status report is intended for
+ * this entry by comparing the WCID/ACK/PID fields.
+ */
+ txwi = rt2800usb_get_txwi(entry);
+
+ rt2x00_desc_read(txwi, 1, &word);
+ tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+ tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
+ tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+ if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+ WARNING(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+ return false;
+ }
+
+ return true;
+}
+
+static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+ struct queue_entry *entry;
+ u32 reg;
+ u8 qid;
+
+ while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
+
+ /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+ * qid is guaranteed to be one of the TX QIDs
+ */
+ qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+ queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+ if (unlikely(!queue)) {
+ WARNING(rt2x00dev, "Got TX status for an unavailable "
+ "queue %u, dropping\n", qid);
+ continue;
+ }
+
+ /*
+ * Inside each queue, we process each entry in a chronological
+ * order. We first check that the queue is not empty.
+ */
+ entry = NULL;
+ while (!rt2x00queue_empty(queue)) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ if (rt2800usb_txdone_entry_check(entry, reg))
+ break;
+ entry = NULL;
+ }
+
+ if (entry)
+ rt2800_txdone_entry(entry, reg,
+ rt2800usb_get_txwi(entry));
+ }
+}
+
static void rt2800usb_work_txdone(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
@@ -464,7 +554,7 @@ static void rt2800usb_work_txdone(struct work_struct *work)
struct data_queue *queue;
struct queue_entry *entry;
- rt2800_txdone(rt2x00dev);
+ rt2800usb_txdone(rt2x00dev);
/*
* Process any trailing TX status reports for IO failures,
@@ -531,8 +621,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
skb_pull(entry->skb, RXINFO_DESC_SIZE);
/*
- * FIXME: we need to check for rx_pkt_len validity
+ * Check for rx_pkt_len validity. Return if invalid, leaving
+ * rxdesc->size zeroed out by the upper level.
*/
+ if (unlikely(rx_pkt_len == 0 ||
+ rx_pkt_len > entry->queue->data_size)) {
+ ERROR(entry->queue->rt2x00dev,
+ "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+ return;
+ }
+
rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
/*
@@ -679,6 +777,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
+ .sta_add = rt2x00mac_sta_add,
+ .sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
@@ -687,6 +787,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -735,6 +836,8 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+ .sta_add = rt2800_sta_add,
+ .sta_remove = rt2800_sta_remove,
};
static const struct data_queue_desc rt2800usb_queue_rx = {
@@ -790,6 +893,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x1482, 0x3c09) },
/* AirTies */
{ USB_DEVICE(0x1eda, 0x2012) },
+ { USB_DEVICE(0x1eda, 0x2210) },
{ USB_DEVICE(0x1eda, 0x2310) },
/* Allwin */
{ USB_DEVICE(0x8516, 0x2070) },
@@ -855,9 +959,13 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07d1, 0x3c15) },
{ USB_DEVICE(0x07d1, 0x3c16) },
{ USB_DEVICE(0x2001, 0x3c1b) },
+ { USB_DEVICE(0x2001, 0x3c1e) },
/* Draytek */
{ USB_DEVICE(0x07fa, 0x7712) },
+ /* DVICO */
+ { USB_DEVICE(0x0fe9, 0xb307) },
/* Edimax */
+ { USB_DEVICE(0x7392, 0x4085) },
{ USB_DEVICE(0x7392, 0x7711) },
{ USB_DEVICE(0x7392, 0x7717) },
{ USB_DEVICE(0x7392, 0x7718) },
@@ -923,6 +1031,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Ovislink */
{ USB_DEVICE(0x1b75, 0x3071) },
{ USB_DEVICE(0x1b75, 0x3072) },
+ { USB_DEVICE(0x1b75, 0xa200) },
/* Para */
{ USB_DEVICE(0x20b8, 0x8888) },
/* Pegatron */
@@ -933,6 +1042,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Philips */
{ USB_DEVICE(0x0471, 0x200f) },
/* Planex */
+ { USB_DEVICE(0x2019, 0x5201) },
{ USB_DEVICE(0x2019, 0xab25) },
{ USB_DEVICE(0x2019, 0xed06) },
/* Quanta */
@@ -982,6 +1092,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x177f, 0x0153) },
{ USB_DEVICE(0x177f, 0x0302) },
{ USB_DEVICE(0x177f, 0x0313) },
+ { USB_DEVICE(0x177f, 0x0323) },
/* U-Media */
{ USB_DEVICE(0x157e, 0x300e) },
{ USB_DEVICE(0x157e, 0x3013) },
@@ -1001,6 +1112,12 @@ static struct usb_device_id rt2800usb_device_table[] = {
#ifdef CONFIG_RT2800USB_RT33XX
/* Belkin */
{ USB_DEVICE(0x050d, 0x945b) },
+ /* D-Link */
+ { USB_DEVICE(0x2001, 0x3c17) },
+ /* Panasonic */
+ { USB_DEVICE(0x083a, 0xb511) },
+ /* Philips */
+ { USB_DEVICE(0x0471, 0x20dd) },
/* Ralink */
{ USB_DEVICE(0x148f, 0x3370) },
{ USB_DEVICE(0x148f, 0x8070) },
@@ -1012,6 +1129,10 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x8516, 0x3572) },
/* Askey */
{ USB_DEVICE(0x1690, 0x0744) },
+ { USB_DEVICE(0x1690, 0x0761) },
+ { USB_DEVICE(0x1690, 0x0764) },
+ /* ASUS */
+ { USB_DEVICE(0x0b05, 0x179d) },
/* Cisco */
{ USB_DEVICE(0x167b, 0x4001) },
/* EnGenius */
@@ -1026,6 +1147,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Sitecom */
{ USB_DEVICE(0x0df6, 0x0041) },
{ USB_DEVICE(0x0df6, 0x0062) },
+ { USB_DEVICE(0x0df6, 0x0065) },
+ { USB_DEVICE(0x0df6, 0x0066) },
+ { USB_DEVICE(0x0df6, 0x0068) },
/* Toshiba */
{ USB_DEVICE(0x0930, 0x0a07) },
/* Zinwell */
@@ -1035,6 +1159,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Azurewave */
{ USB_DEVICE(0x13d3, 0x3329) },
{ USB_DEVICE(0x13d3, 0x3365) },
+ /* D-Link */
+ { USB_DEVICE(0x2001, 0x3c1c) },
+ { USB_DEVICE(0x2001, 0x3c1d) },
/* Ralink */
{ USB_DEVICE(0x148f, 0x5370) },
{ USB_DEVICE(0x148f, 0x5372) },
@@ -1058,7 +1185,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0b05, 0x1760) },
{ USB_DEVICE(0x0b05, 0x1761) },
{ USB_DEVICE(0x0b05, 0x1790) },
- { USB_DEVICE(0x0b05, 0x179d) },
/* AzureWave */
{ USB_DEVICE(0x13d3, 0x3262) },
{ USB_DEVICE(0x13d3, 0x3284) },
@@ -1076,13 +1202,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* D-Link */
{ USB_DEVICE(0x07d1, 0x3c0b) },
{ USB_DEVICE(0x07d1, 0x3c17) },
- { USB_DEVICE(0x2001, 0x3c17) },
- /* Edimax */
- { USB_DEVICE(0x7392, 0x4085) },
/* Encore */
{ USB_DEVICE(0x203d, 0x14a1) },
- /* Fujitsu Stylistic 550 */
- { USB_DEVICE(0x1690, 0x0761) },
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0010) },
/* Gigabyte */
@@ -1103,7 +1224,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x05a6, 0x0101) },
{ USB_DEVICE(0x1d4d, 0x0010) },
/* Planex */
- { USB_DEVICE(0x2019, 0x5201) },
{ USB_DEVICE(0x2019, 0xab24) },
/* Qcom */
{ USB_DEVICE(0x18e8, 0x6259) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 8c82211..c778164 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -29,6 +29,7 @@
#define RT2X00_H
#include <linux/bitops.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
@@ -389,8 +390,7 @@ struct rt2x00_intf {
* for hardware which doesn't support hardware
* sequence counting.
*/
- spinlock_t seqlock;
- u16 seqno;
+ atomic_t seqno;
};
static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
@@ -477,6 +477,8 @@ struct rt2x00lib_crypto {
u8 key[16];
u8 tx_mic[8];
u8 rx_mic[8];
+
+ int wcid;
};
/*
@@ -511,6 +513,19 @@ struct rt2x00intf_conf {
};
/*
+ * Private structure for storing STA details
+ * wcid: Wireless Client ID
+ */
+struct rt2x00_sta {
+ int wcid;
+};
+
+static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
+{
+ return (struct rt2x00_sta *)sta->drv_priv;
+}
+
+/*
* rt2x00lib callback functions.
*/
struct rt2x00lib_ops {
@@ -619,6 +634,11 @@ struct rt2x00lib_ops {
void (*config) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int changed_flags);
+ int (*sta_add) (struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
+ int wcid);
};
/*
@@ -1226,6 +1246,12 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif);
+
+/*
* Interrupt context handlers.
*/
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
@@ -1261,6 +1287,10 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
#else
#define rt2x00mac_set_key NULL
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
@@ -1269,7 +1299,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
@@ -1277,6 +1308,7 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);
/*
* Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 1bb9d46..1ca4c7f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -45,11 +45,11 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
}
}
-void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 031aa2b..3de9875 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -33,6 +33,22 @@
#include "rt2x00lib.h"
/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif)
+{
+ /*
+ * When in STA mode, bssidx is always 0 otherwise local_address[5]
+ * contains the bss number, see BSS_ID_MASK comments for details.
+ */
+ if (rt2x00dev->intf_sta_count)
+ return 0;
+ return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx);
+
+/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -603,6 +619,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
/*
+ * Check for valid size in case we get corrupted descriptor from
+ * hardware.
+ */
+ if (unlikely(rxdesc.size == 0 ||
+ rxdesc.size > entry->queue->data_size)) {
+ ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
+ rxdesc.size, entry->queue->data_size);
+ dev_kfree_skb(entry->skb);
+ goto renew_skb;
+ }
+
+ /*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
@@ -662,6 +690,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
+renew_skb:
/*
* Replace the skb with the freshly allocated one.
*/
@@ -922,6 +951,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
/*
+ * Tell mac80211 about the size of our private STA structure.
+ */
+ rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta);
+
+ /*
* Allocate tx status FIFO for driver use.
*/
if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {
@@ -953,7 +987,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
tasklet_init(&rt2x00dev->taskletname, \
rt2x00dev->ops->lib->taskletname, \
(unsigned long)rt2x00dev); \
- tasklet_disable(&rt2x00dev->taskletname); \
}
RT2X00_TASKLET_INIT(txstatus_tasklet);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 322cc4f..4cdf247 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -336,7 +336,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
*/
#ifdef CONFIG_RT2X00_LIB_CRYPTO
enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
-void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc);
unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb);
@@ -354,7 +355,8 @@ static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *
return CIPHER_NONE;
}
-static inline void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+static inline void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index bc159be..ab19949 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -277,7 +277,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
else
rt2x00dev->intf_sta_count++;
- spin_lock_init(&intf->seqlock);
mutex_init(&intf->beacon_skb_mutex);
intf->beacon = entry;
@@ -503,6 +502,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct rt2x00lib_crypto crypto;
static const u8 bcast_addr[ETH_ALEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
+ struct rt2x00_sta *sta_priv = NULL;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
@@ -513,24 +513,20 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
memset(&crypto, 0, sizeof(crypto));
- /*
- * When in STA mode, bssidx is always 0 otherwise local_address[5]
- * contains the bss number, see BSS_ID_MASK comments for details.
- */
- if (rt2x00dev->intf_sta_count)
- crypto.bssidx = 0;
- else
- crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
-
+ crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);
crypto.cipher = rt2x00crypto_key_to_cipher(key);
if (crypto.cipher == CIPHER_NONE)
return -EOPNOTSUPP;
+ if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev))
+ return -EOPNOTSUPP;
crypto.cmd = cmd;
- if (sta)
+ if (sta) {
crypto.address = sta->addr;
- else
+ sta_priv = sta_to_rt2x00_sta(sta);
+ crypto.wcid = sta_priv->wcid;
+ } else
crypto.address = bcast_addr;
if (crypto.cipher == CIPHER_TKIP)
@@ -569,6 +565,39 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+ /*
+ * If there's no space left in the device table store
+ * -1 as wcid but tell mac80211 everything went ok.
+ */
+ if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
+ sta_priv->wcid = -1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
+
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+ /*
+ * If we never sent the STA to the device no need to clean it up.
+ */
+ if (sta_priv->wcid < 0)
+ return 0;
+
+ return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
+
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -624,20 +653,18 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->bssid);
/*
- * Update the beacon. This is only required on USB devices. PCI
- * devices fetch beacons periodically.
- */
- if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev))
- rt2x00queue_update_beacon(rt2x00dev, vif);
-
- /*
* Start/stop beaconing.
*/
if (changes & BSS_CHANGED_BEACON_ENABLED) {
if (!bss_conf->enable_beacon && intf->enable_beacon) {
- rt2x00queue_clear_beacon(rt2x00dev, vif);
rt2x00dev->intf_beaconing--;
intf->enable_beacon = false;
+ /*
+ * Clear beacon in the H/W for this vif. This is needed
+ * to disable beaconing on this particular interface
+ * and keep it running on other interfaces.
+ */
+ rt2x00queue_clear_beacon(rt2x00dev, vif);
if (rt2x00dev->intf_beaconing == 0) {
/*
@@ -648,11 +675,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
rt2x00queue_stop_queue(rt2x00dev->bcn);
mutex_unlock(&intf->beacon_skb_mutex);
}
-
-
} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
rt2x00dev->intf_beaconing++;
intf->enable_beacon = true;
+ /*
+ * Upload beacon to the H/W. This is only required on
+ * USB devices. PCI devices fetch beacons periodically.
+ */
+ if (rt2x00_is_usb(rt2x00dev))
+ rt2x00queue_update_beacon(rt2x00dev, vif);
if (rt2x00dev->intf_beaconing == 1) {
/*
@@ -694,7 +725,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -743,6 +775,9 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
struct rt2x00_dev *rt2x00dev = hw->priv;
struct data_queue *queue;
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+ return;
+
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_flush_queue(queue, drop);
}
@@ -828,3 +863,17 @@ void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
*rx_max = rt2x00dev->rx->limit;
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
+
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+
+ tx_queue_for_each(rt2x00dev, queue) {
+ if (!rt2x00queue_empty(queue))
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 2d7c59f..c5bdbe9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -148,72 +148,47 @@ void rt2x00queue_align_frame(struct sk_buff *skb)
skb_trim(skb, frame_length);
}
-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
+/*
+ * H/W needs L2 padding between the header and the paylod if header size
+ * is not 4 bytes aligned.
+ */
+void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
{
- unsigned int payload_length = skb->len - header_length;
- unsigned int header_align = ALIGN_SIZE(skb, 0);
- unsigned int payload_align = ALIGN_SIZE(skb, header_length);
- unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
-
- /*
- * Adjust the header alignment if the payload needs to be moved more
- * than the header.
- */
- if (payload_align > header_align)
- header_align += 4;
+ unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
- /* There is nothing to do if no alignment is needed */
- if (!header_align)
+ if (!l2pad)
return;
- /* Reserve the amount of space needed in front of the frame */
- skb_push(skb, header_align);
-
- /*
- * Move the header.
- */
- memmove(skb->data, skb->data + header_align, header_length);
-
- /* Move the payload, if present and if required */
- if (payload_length && payload_align)
- memmove(skb->data + header_length + l2pad,
- skb->data + header_length + l2pad + payload_align,
- payload_length);
-
- /* Trim the skb to the correct size */
- skb_trim(skb, header_length + l2pad + payload_length);
+ skb_push(skb, l2pad);
+ memmove(skb->data, skb->data + l2pad, hdr_len);
}
-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
+void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
{
- /*
- * L2 padding is only present if the skb contains more than just the
- * IEEE 802.11 header.
- */
- unsigned int l2pad = (skb->len > header_length) ?
- L2PAD_SIZE(header_length) : 0;
+ unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
if (!l2pad)
return;
- memmove(skb->data + l2pad, skb->data, header_length);
+ memmove(skb->data + l2pad, skb->data, hdr_len);
skb_pull(skb, l2pad);
}
-static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
- unsigned long irqflags;
+ u16 seqno;
if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
return;
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
- if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
+ if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags))
return;
/*
@@ -227,23 +202,21 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
* sequence counting per-frame, since those will override the
* sequence counter given by mac80211.
*/
- spin_lock_irqsave(&intf->seqlock, irqflags);
-
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
- intf->seqno += 0x10;
- hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
-
- spin_unlock_irqrestore(&intf->seqlock, irqflags);
+ seqno = atomic_add_return(0x10, &intf->seqno);
+ else
+ seqno = atomic_read(&intf->seqno);
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(seqno);
}
-static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc,
const struct rt2x00_rate *hwrate)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
unsigned int data_length;
unsigned int duration;
@@ -260,8 +233,8 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
txdesc->u.plcp.ifs = IFS_SIFS;
/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
- data_length = entry->skb->len + 4;
- data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);
+ data_length = skb->len + 4;
+ data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
/*
* PLCP setup
@@ -302,18 +275,24 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
}
}
-static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc,
const struct rt2x00_rate *hwrate)
{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct rt2x00_sta *sta_priv = NULL;
- if (tx_info->control.sta)
+ if (tx_info->control.sta) {
txdesc->u.ht.mpdu_density =
tx_info->control.sta->ht_cap.ampdu_density;
+ sta_priv = sta_to_rt2x00_sta(tx_info->control.sta);
+ txdesc->u.ht.wcid = sta_priv->wcid;
+ }
+
txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
/*
@@ -381,12 +360,12 @@ static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
txdesc->u.ht.txop = TXOP_HTTXOP;
}
-static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
struct ieee80211_rate *rate;
const struct rt2x00_rate *hwrate = NULL;
@@ -396,8 +375,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Header and frame information.
*/
- txdesc->length = entry->skb->len;
- txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+ txdesc->length = skb->len;
+ txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);
/*
* Check whether this frame is to be acked.
@@ -472,13 +451,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Apply TX descriptor handling by components
*/
- rt2x00crypto_create_tx_descriptor(entry, txdesc);
- rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
+ rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);
+ rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);
if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
- rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
+ rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,
+ hwrate);
else
- rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
+ rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
+ hwrate);
}
static int rt2x00queue_write_tx_data(struct queue_entry *entry,
@@ -563,36 +544,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
int ret = 0;
/*
- * That function must be called with bh disabled.
- */
- spin_lock(&queue->tx_lock);
-
- entry = rt2x00queue_get_entry(queue, Q_INDEX);
-
- if (unlikely(rt2x00queue_full(queue))) {
- ERROR(queue->rt2x00dev,
- "Dropping frame due to full tx queue %d.\n", queue->qid);
- ret = -ENOBUFS;
- goto out;
- }
-
- if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
- &entry->flags))) {
- ERROR(queue->rt2x00dev,
- "Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- queue->qid, DRV_PROJECT);
- ret = -EINVAL;
- goto out;
- }
-
- /*
* Copy all TX descriptor information into txdesc,
* after that we are free to use the skb->cb array
* for our information.
*/
- entry->skb = skb;
- rt2x00queue_create_tx_descriptor(entry, &txdesc);
+ rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc);
/*
* All information is retrieved from the skb->cb array,
@@ -604,7 +560,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
rate_flags = tx_info->control.rates[0].flags;
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
- skbdesc->entry = entry;
skbdesc->tx_rate_idx = rate_idx;
skbdesc->tx_rate_flags = rate_flags;
@@ -633,9 +588,36 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
* for PCI devices.
*/
if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
- rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
+ rt2x00queue_insert_l2pad(skb, txdesc.header_length);
else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
- rt2x00queue_align_frame(entry->skb);
+ rt2x00queue_align_frame(skb);
+
+ /*
+ * That function must be called with bh disabled.
+ */
+ spin_lock(&queue->tx_lock);
+
+ if (unlikely(rt2x00queue_full(queue))) {
+ ERROR(queue->rt2x00dev,
+ "Dropping frame due to full tx queue %d.\n", queue->qid);
+ ret = -ENOBUFS;
+ goto out;
+ }
+
+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
+
+ if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+ &entry->flags))) {
+ ERROR(queue->rt2x00dev,
+ "Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ queue->qid, DRV_PROJECT);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ skbdesc->entry = entry;
+ entry->skb = skb;
/*
* It could be possible that the queue was corrupted and this
@@ -711,7 +693,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
* after that we are free to use the skb->cb array
* for our information.
*/
- rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
+ rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc);
/*
* Fill in skb descriptor
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index ad3d527..349008d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -54,7 +54,7 @@
* @QID_RX: RX queue
* @QID_OTHER: None of the above (don't use, only present for completeness)
* @QID_BEACON: Beacon queue (value unspecified, don't send it to device)
- * @QID_ATIM: Atim queue (value unspeficied, don't send it to device)
+ * @QID_ATIM: Atim queue (value unspecified, don't send it to device)
*/
enum data_queue_qid {
QID_AC_VO = 0,
@@ -288,8 +288,8 @@ enum txentry_desc_flags {
* @signal: PLCP signal.
* @service: PLCP service.
* @msc: MCS.
- * @stbc: STBC.
- * @ba_size: BA size.
+ * @stbc: Use Space Time Block Coding (only available for MCS rates < 8).
+ * @ba_size: Size of the recepients RX reorder buffer - 1.
* @rate_mode: Rate mode (See @enum rate_modulation).
* @mpdu_density: MDPU density.
* @retry_limit: Max number of retries.
@@ -321,6 +321,7 @@ struct txentry_desc {
u8 ba_size;
u8 mpdu_density;
enum txop txop;
+ int wcid;
} ht;
} u;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 99fa416..ba28807 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -799,6 +799,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
int retval;
usb_dev = usb_get_dev(usb_dev);
+ usb_reset_device(usb_dev);
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index dd31588..3e058e5 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1142,11 +1142,6 @@ static void rt61pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- /*
- * Allow the tbtt tasklet to be scheduled.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
@@ -1230,7 +1225,7 @@ static void rt61pci_stop_queue(struct data_queue *queue)
/*
* Wait for possibly running tbtt tasklets.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
@@ -1731,13 +1726,6 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
-
- /*
- * Enable tasklets.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
- tasklet_enable(&rt2x00dev->autowake_tasklet);
}
/*
@@ -1772,9 +1760,10 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
/*
* Ensure that all tasklets are finished.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
- tasklet_disable(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
}
}
@@ -2299,22 +2288,24 @@ static void rt61pci_txstatus_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt61pci_txdone(rt2x00dev);
- rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
}
static void rt61pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
}
static void rt61pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
- rt2x00pci_rxdone(rt2x00dev);
- else
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
}
@@ -2324,7 +2315,8 @@ static void rt61pci_autowake_tasklet(unsigned long data)
rt61pci_wakeup(rt2x00dev);
rt2x00pci_register_write(rt2x00dev,
M2H_CMD_DONE_CSR, 0xffffffff);
- rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
}
static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
@@ -2830,8 +2822,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
for (i = 14; i < spec->num_channels; i++) {
info[i].max_power = MAX_TXPOWER;
- info[i].default_power1 =
- TXPOWER_FROM_DEV(tx_power[i - 14]);
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
}
}
@@ -2900,7 +2891,8 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+static int rt61pci_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -2916,7 +2908,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
* we are free to update the registers based on the value
* in the queue parameter.
*/
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
if (retval)
return retval;
@@ -2957,7 +2949,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
return 0;
}
-static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
+static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
@@ -2991,6 +2983,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 3b68155..9e724eb 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2167,8 +2167,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
for (i = 14; i < spec->num_channels; i++) {
info[i].max_power = MAX_TXPOWER;
- info[i].default_power1 =
- TXPOWER_FROM_DEV(tx_power[i - 14]);
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
}
}
@@ -2232,7 +2231,8 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+static int rt73usb_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -2248,7 +2248,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
* we are free to update the registers based on the value
* in the queue parameter.
*/
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
if (retval)
return retval;
@@ -2289,7 +2289,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
return 0;
}
-static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
+static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
@@ -2324,6 +2324,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2420,6 +2421,7 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x0b05, 0x1723) },
{ USB_DEVICE(0x0b05, 0x1724) },
/* Belkin */
+ { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050B ver. 3.x */
{ USB_DEVICE(0x050d, 0x705a) },
{ USB_DEVICE(0x050d, 0x905b) },
{ USB_DEVICE(0x050d, 0x905c) },
@@ -2429,6 +2431,7 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Buffalo */
{ USB_DEVICE(0x0411, 0x00d8) },
{ USB_DEVICE(0x0411, 0x00d9) },
+ { USB_DEVICE(0x0411, 0x00e6) },
{ USB_DEVICE(0x0411, 0x00f4) },
{ USB_DEVICE(0x0411, 0x0116) },
{ USB_DEVICE(0x0411, 0x0119) },
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 80db5ca..2f14a5f 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -16,11 +16,13 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/eeprom_93cx6.h>
+#include <linux/module.h>
#include <net/mac80211.h>
#include "rtl8180.h"
@@ -668,7 +670,8 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
rtl8180_free_tx_ring(dev, i);
}
-static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
+static u64 rtl8180_get_tsf(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif)
{
struct rtl8180_priv *priv = dev->priv;
@@ -700,7 +703,7 @@ static void rtl8180_beacon_work(struct work_struct *work)
* TODO: make hardware update beacon timestamp
*/
mgmt = (struct ieee80211_mgmt *)skb->data;
- mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev));
+ mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif));
/* TODO: use actual beacon queue */
skb_set_queue_mapping(skb, 0);
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index bf01d21..4e98c39 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/eeprom_93cx6.h>
+#include <linux/module.h>
#include <net/mac80211.h>
#include "rtl8187.h"
@@ -1241,7 +1242,8 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
}
-static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
+static int rtl8187_conf_tx(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct rtl8187_priv *priv = dev->priv;
@@ -1277,7 +1279,7 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
return 0;
}
-static u64 rtl8187_get_tsf(struct ieee80211_hw *dev)
+static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
{
struct rtl8187_priv *priv = dev->priv;
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
index f1cc907..6d3d653 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
@@ -15,6 +15,8 @@
#ifndef RTL8187_H
#define RTL8187_H
+#include <linux/cache.h>
+
#include "rtl818x.h"
#include "leds.h"
@@ -131,7 +133,10 @@ struct rtl8187_priv {
u8 aifsn[4];
u8 rfkill_mask;
struct {
- __le64 buf;
+ union {
+ __le64 buf;
+ u8 dummy1[L1_CACHE_BYTES];
+ } ____cacheline_aligned;
struct sk_buff_head queue;
} b_tx_status; /* This queue is used by both -b and non-b devices */
struct mutex io_mutex;
@@ -139,7 +144,8 @@ struct rtl8187_priv {
u8 bits8;
__le16 bits16;
__le32 bits32;
- } *io_dmabuf;
+ u8 dummy2[L1_CACHE_BYTES];
+ } *io_dmabuf ____cacheline_aligned;
bool rfkill_off;
};
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 5aee8b2..d6c42e6 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -12,7 +12,7 @@ config RTL8192CE
config RTL8192SE
tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter"
- depends on MAC80211 && EXPERIMENTAL
+ depends on MAC80211 && EXPERIMENTAL && PCI
select FW_LOADER
select RTLWIFI
---help---
@@ -21,6 +21,17 @@ config RTL8192SE
If you choose to build it as a module, it will be called rtl8192se
+config RTL8192DE
+ tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
+ depends on MAC80211 && EXPERIMENTAL && PCI
+ select FW_LOADER
+ select RTLWIFI
+ ---help---
+ This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
+ wireless network adapters.
+
+ If you choose to build it as a module, it will be called rtl8192de
+
config RTL8192CU
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
depends on MAC80211 && USB && EXPERIMENTAL
@@ -35,10 +46,10 @@ config RTL8192CU
config RTLWIFI
tristate
- depends on RTL8192CE || RTL8192CU || RTL8192SE
+ depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
default m
config RTL8192C_COMMON
tristate
- depends on RTL8192CE || RTL8192CU || RTL8192SE
+ depends on RTL8192CE || RTL8192CU
default m
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 7acce83..97935c5 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -23,5 +23,6 @@ obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/
obj-$(CONFIG_RTL8192CE) += rtl8192ce/
obj-$(CONFIG_RTL8192CU) += rtl8192cu/
obj-$(CONFIG_RTL8192SE) += rtl8192se/
+obj-$(CONFIG_RTL8192DE) += rtl8192de/
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index ccb6da3..a917a22 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -27,7 +27,11 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/ip.h>
+#include <linux/module.h>
+#include <linux/udp.h>
#include "wifi.h"
#include "rc.h"
#include "base.h"
@@ -309,6 +313,8 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_BEACON_FILTER |
IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_CONNECTION_MONITOR |
+ /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
/* swlps or hwlps has been set in diff chip in init_sw_vars */
@@ -397,8 +403,8 @@ void rtl_init_rfkill(struct ieee80211_hw *hw)
radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
if (valid) {
- printk(KERN_INFO "rtlwifi: wireless switch is %s\n",
- rtlpriv->rfkill.rfkill_state ? "on" : "off");
+ pr_info("wireless switch is %s\n",
+ rtlpriv->rfkill.rfkill_state ? "on" : "off");
rtlpriv->rfkill.rfkill_state = radio_state;
@@ -523,7 +529,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
mac->opmode == NL80211_IFTYPE_ADHOC)
bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- if ((bw_40 == true) && sgi_40)
+ if (bw_40 && sgi_40)
tcb_desc->use_shortgi = true;
else if ((bw_40 == false) && sgi_20)
tcb_desc->use_shortgi = true;
@@ -662,6 +668,167 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw)
return hw_rate;
}
+/* mac80211's rate_idx is like this:
+ *
+ * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ
+ *
+ * B/G rate:
+ * (rx_status->flag & RX_FLAG_HT) = 0,
+ * DESC92_RATE1M-->DESC92_RATE54M ==> idx is 0-->11,
+ *
+ * N rate:
+ * (rx_status->flag & RX_FLAG_HT) = 1,
+ * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15
+ *
+ * 5G band:rx_status->band == IEEE80211_BAND_5GHZ
+ * A rate:
+ * (rx_status->flag & RX_FLAG_HT) = 0,
+ * DESC92_RATE6M-->DESC92_RATE54M ==> idx is 0-->7,
+ *
+ * N rate:
+ * (rx_status->flag & RX_FLAG_HT) = 1,
+ * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15
+ */
+int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
+ bool isht, u8 desc_rate, bool first_ampdu)
+{
+ int rate_idx;
+
+ if (false == isht) {
+ if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) {
+ switch (desc_rate) {
+ case DESC92_RATE1M:
+ rate_idx = 0;
+ break;
+ case DESC92_RATE2M:
+ rate_idx = 1;
+ break;
+ case DESC92_RATE5_5M:
+ rate_idx = 2;
+ break;
+ case DESC92_RATE11M:
+ rate_idx = 3;
+ break;
+ case DESC92_RATE6M:
+ rate_idx = 4;
+ break;
+ case DESC92_RATE9M:
+ rate_idx = 5;
+ break;
+ case DESC92_RATE12M:
+ rate_idx = 6;
+ break;
+ case DESC92_RATE18M:
+ rate_idx = 7;
+ break;
+ case DESC92_RATE24M:
+ rate_idx = 8;
+ break;
+ case DESC92_RATE36M:
+ rate_idx = 9;
+ break;
+ case DESC92_RATE48M:
+ rate_idx = 10;
+ break;
+ case DESC92_RATE54M:
+ rate_idx = 11;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ } else {
+ switch (desc_rate) {
+ case DESC92_RATE6M:
+ rate_idx = 0;
+ break;
+ case DESC92_RATE9M:
+ rate_idx = 1;
+ break;
+ case DESC92_RATE12M:
+ rate_idx = 2;
+ break;
+ case DESC92_RATE18M:
+ rate_idx = 3;
+ break;
+ case DESC92_RATE24M:
+ rate_idx = 4;
+ break;
+ case DESC92_RATE36M:
+ rate_idx = 5;
+ break;
+ case DESC92_RATE48M:
+ rate_idx = 6;
+ break;
+ case DESC92_RATE54M:
+ rate_idx = 7;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ }
+
+ } else {
+
+ switch (desc_rate) {
+ case DESC92_RATEMCS0:
+ rate_idx = 0;
+ break;
+ case DESC92_RATEMCS1:
+ rate_idx = 1;
+ break;
+ case DESC92_RATEMCS2:
+ rate_idx = 2;
+ break;
+ case DESC92_RATEMCS3:
+ rate_idx = 3;
+ break;
+ case DESC92_RATEMCS4:
+ rate_idx = 4;
+ break;
+ case DESC92_RATEMCS5:
+ rate_idx = 5;
+ break;
+ case DESC92_RATEMCS6:
+ rate_idx = 6;
+ break;
+ case DESC92_RATEMCS7:
+ rate_idx = 7;
+ break;
+ case DESC92_RATEMCS8:
+ rate_idx = 8;
+ break;
+ case DESC92_RATEMCS9:
+ rate_idx = 9;
+ break;
+ case DESC92_RATEMCS10:
+ rate_idx = 10;
+ break;
+ case DESC92_RATEMCS11:
+ rate_idx = 11;
+ break;
+ case DESC92_RATEMCS12:
+ rate_idx = 12;
+ break;
+ case DESC92_RATEMCS13:
+ rate_idx = 13;
+ break;
+ case DESC92_RATEMCS14:
+ rate_idx = 14;
+ break;
+ case DESC92_RATEMCS15:
+ rate_idx = 15;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ }
+ return rate_idx;
+}
+EXPORT_SYMBOL(rtlwifi_rate_mapping);
+
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
@@ -687,7 +854,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
*So tcb_desc->hw_rate is just used for
*special data and mgt frames
*/
- if (info->control.rates[0].idx == 0 &&
+ if (info->control.rates[0].idx == 0 ||
ieee80211_is_nullfunc(fc)) {
tcb_desc->use_driver_rate = true;
tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
@@ -756,18 +923,17 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
return false;
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("%s ACT_ADDBAREQ From :" MAC_FMT "\n",
- is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
+ ("%s ACT_ADDBAREQ From :%pM\n",
+ is_tx ? "Tx" : "Rx", hdr->addr2));
break;
case ACT_ADDBARSP:
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("%s ACT_ADDBARSP From :" MAC_FMT "\n",
- is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
+ ("%s ACT_ADDBARSP From :%pM\n",
+ is_tx ? "Tx" : "Rx", hdr->addr2));
break;
case ACT_DELBA:
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("ACT_ADDBADEL From :" MAC_FMT "\n",
- MAC_ARG(hdr->addr2)));
+ ("ACT_ADDBADEL From :%pM\n", hdr->addr2));
break;
}
break;
@@ -791,60 +957,51 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
if (!ieee80211_is_data(fc))
return false;
+ ip = (const struct iphdr *)(skb->data + mac_hdr_len +
+ SNAP_SIZE + PROTOC_TYPE_SIZE);
+ ether_type = be16_to_cpup((__be16 *)
+ (skb->data + mac_hdr_len + SNAP_SIZE));
- ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
- SNAP_SIZE + PROTOC_TYPE_SIZE);
- ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
- /* ether_type = ntohs(ether_type); */
-
- if (ETH_P_IP == ether_type) {
- if (IPPROTO_UDP == ip->protocol) {
- struct udphdr *udp = (struct udphdr *)((u8 *) ip +
- (ip->ihl << 2));
- if (((((u8 *) udp)[1] == 68) &&
- (((u8 *) udp)[3] == 67)) ||
- ((((u8 *) udp)[1] == 67) &&
- (((u8 *) udp)[3] == 68))) {
- /*
- * 68 : UDP BOOTP client
- * 67 : UDP BOOTP server
- */
- RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
- DBG_DMESG, ("dhcp %s !!\n",
- (is_tx) ? "Tx" : "Rx"));
-
- if (is_tx) {
- rtl_lps_leave(hw);
- ppsc->last_delaylps_stamp_jiffies =
- jiffies;
- }
+ switch (ether_type) {
+ case ETH_P_IP: {
+ struct udphdr *udp;
+ u16 src;
+ u16 dst;
- return true;
- }
- }
- } else if (ETH_P_ARP == ether_type) {
- if (is_tx) {
- rtl_lps_leave(hw);
- ppsc->last_delaylps_stamp_jiffies = jiffies;
- }
-
- return true;
- } else if (ETH_P_PAE == ether_type) {
- RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"));
+ if (ip->protocol != IPPROTO_UDP)
+ return false;
+ udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
+ src = be16_to_cpu(udp->source);
+ dst = be16_to_cpu(udp->dest);
- if (is_tx) {
- rtl_lps_leave(hw);
- ppsc->last_delaylps_stamp_jiffies = jiffies;
- }
+ /* If this case involves port 68 (UDP BOOTP client) connecting
+ * with port 67 (UDP BOOTP server), then return true so that
+ * the lowest speed is used.
+ */
+ if (!((src == 68 && dst == 67) || (src == 67 && dst == 68)))
+ return false;
- return true;
- } else if (ETH_P_IPV6 == ether_type) {
- /* IPv6 */
- return true;
+ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
+ ("dhcp %s !!\n", is_tx ? "Tx" : "Rx"));
+ break;
}
-
- return false;
+ case ETH_P_ARP:
+ break;
+ case ETH_P_PAE:
+ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
+ ("802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"));
+ break;
+ case ETH_P_IPV6:
+ /* TODO: Is this right? */
+ return false;
+ default:
+ return false;
+ }
+ if (is_tx) {
+ rtl_lps_leave(hw);
+ ppsc->last_delaylps_stamp_jiffies = jiffies;
+ }
+ return true;
}
/*********************************************************
@@ -888,7 +1045,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
if (sta == NULL)
@@ -906,7 +1062,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
return -EINVAL;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
- tid_data = &sta_entry->tids[tid];
sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP;
ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid);
@@ -918,7 +1073,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
if (sta == NULL)
@@ -936,7 +1090,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
return -EINVAL;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
- tid_data = &sta_entry->tids[tid];
sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL;
return 0;
@@ -980,7 +1133,7 @@ void rtl_watchdog_wq_callback(void *data)
}
/*
- *<3> to check if traffic busy, if
+ *<2> to check if traffic busy, if
* busytraffic we don't change channel
*/
if (mac->link_state >= MAC80211_LINKED) {
@@ -1406,8 +1559,7 @@ MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
static int __init rtl_core_module_init(void)
{
if (rtl_rate_control_register())
- printk(KERN_ERR "rtlwifi: Unable to register rtl_rc,"
- "use default RC !!\n");
+ pr_err("Unable to register rtl_rc, use default RC !!\n");
return 0;
}
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index a91f3ee..4ae9059 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -140,4 +140,6 @@ u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid);
extern struct attribute_group rtl_attribute_group;
+int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
+ bool isht, u8 desc_rate, bool first_ampdu);
#endif
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 7295af0..dc36d74 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -27,6 +27,9 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/export.h>
#include "wifi.h"
#include "cam.h"
@@ -131,9 +134,9 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, "
- "ulUseDK=%x MacAddr" MAC_FMT "\n",
+ "ulUseDK=%x MacAddr %pM\n",
ul_entry_idx, ul_key_id, ul_enc_alg,
- ul_default_key, MAC_ARG(mac_addr)));
+ ul_default_key, mac_addr));
if (ul_key_id == TOTAL_CAM_ENTRY) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -347,7 +350,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
/* Remove from HW Security CAM */
memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
- printk(KERN_INFO "&&&&&&&&&del entry %d\n", i);
+ pr_info("&&&&&&&&&del entry %d\n", i);
}
}
return;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index ce0444c..4fa987b 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -131,6 +131,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
rtlpriv->cfg->maps
[RTL_IBSS_INT_MASKS]);
}
+ mac->link_state = MAC80211_LINKED;
break;
case NL80211_IFTYPE_ADHOC:
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
@@ -335,8 +336,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
* before going offchannel, or dis-association or delete BA will
* happen by AP
*/
- if (rtlpriv->mac80211.offchan_deley) {
- rtlpriv->mac80211.offchan_deley = false;
+ if (rtlpriv->mac80211.offchan_delay) {
+ rtlpriv->mac80211.offchan_delay = false;
mdelay(50);
}
rtlphy->current_channel = wide_chan;
@@ -443,11 +444,11 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
sta_entry->wireless_mode = WIRELESS_MODE_G;
if (sta->supp_rates[0] <= 0xf)
sta_entry->wireless_mode = WIRELESS_MODE_B;
- if (sta->ht_cap.ht_supported == true)
+ if (sta->ht_cap.ht_supported)
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
} else if (rtlhal->current_bandtype == BAND_ON_5G) {
sta_entry->wireless_mode = WIRELESS_MODE_A;
- if (sta->ht_cap.ht_supported == true)
+ if (sta->ht_cap.ht_supported)
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
}
@@ -456,7 +457,7 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
sta_entry->wireless_mode = WIRELESS_MODE_G;
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
- ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr)));
+ ("Add sta addr is %pM\n", sta->addr));
rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
}
return 0;
@@ -469,7 +470,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
struct rtl_sta_info *sta_entry;
if (sta) {
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
- ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr)));
+ ("Remove sta addr is %pM\n", sta->addr));
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
sta_entry->wireless_mode = 0;
sta_entry->ratr_index = 0;
@@ -504,7 +505,8 @@ static int _rtl_get_hal_qnum(u16 queue)
*for mac80211 VO=0, VI=1, BE=2, BK=3
*for rtl819x BE=0, BK=1, VI=2, VO=3
*/
-static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int rtl_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -655,7 +657,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
("BSS_CHANGED_HT\n"));
rcu_read_lock();
- sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+ sta = get_sta(hw, vif, bss_conf->bssid);
if (sta) {
if (sta->ht_cap.ampdu_density >
mac->current_ampdu_density)
@@ -683,14 +685,14 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
(u8 *) bss_conf->bssid);
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
- (MAC_FMT "\n", MAC_ARG(bss_conf->bssid)));
+ ("%pM\n", bss_conf->bssid));
mac->vendor = PEER_UNKNOWN;
memcpy(mac->bssid, bss_conf->bssid, 6);
rtlpriv->cfg->ops->set_network_type(hw, vif->type);
rcu_read_lock();
- sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+ sta = get_sta(hw, vif, bss_conf->bssid);
if (!sta) {
rcu_read_unlock();
goto out;
@@ -775,7 +777,7 @@ out:
mutex_unlock(&rtlpriv->locks.conf_mutex);
}
-static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
+static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u64 tsf;
@@ -784,7 +786,8 @@ static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u64 tsf)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -794,7 +797,8 @@ static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss));
}
-static void rtl_op_reset_tsf(struct ieee80211_hw *hw)
+static void rtl_op_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 tmp = 0;
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h
index 4b247db..f02824a 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/rtlwifi/core.h
@@ -30,6 +30,8 @@
#ifndef __RTL_CORE_H__
#define __RTL_CORE_H__
+#include <net/mac80211.h>
+
#define RTL_SUPPORTED_FILTERS \
(FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | FIF_CONTROL | \
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c
index 5fa7385..1b5cb71 100644
--- a/drivers/net/wireless/rtlwifi/debug.c
+++ b/drivers/net/wireless/rtlwifi/debug.c
@@ -33,8 +33,6 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 i;
- rtlpriv->dbg.global_debuglevel = DBG_EMERG;
-
rtlpriv->dbg.global_debugcomponents =
COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND |
COMP_MLME | COMP_SCAN | COMP_INTR | COMP_LED | COMP_SEC |
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index e4aa868..160dd06 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -204,10 +204,5 @@ enum dbgp_flag_e {
} \
} while (0);
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) \
- ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2],\
- ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
void rtl_dbgp_flag_init(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 50de6f5..ed1058b 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/export.h>
#include "wifi.h"
#include "efuse.h"
@@ -382,7 +383,7 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
}
}
- if (wordchanged == true)
+ if (wordchanged)
hdr_num++;
}
@@ -453,7 +454,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
base = offset * 8;
for (i = 0; i < 8; i++) {
- if (first_pg == true) {
+ if (first_pg) {
word_en &= ~(BIT(i / 2));
@@ -505,7 +506,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF,
rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
else
@@ -690,7 +691,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
}
}
- if (dataempty == true) {
+ if (dataempty) {
*readstate = PG_STATE_DATA;
} else {
*efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
@@ -925,7 +926,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct pgpkt_struct target_pkt;
u8 write_state = PG_STATE_HEADER;
- int continual = true, dataempty = true, result = true;
+ int continual = true, result = true;
u16 efuse_addr = 0;
u8 efuse_data;
u8 target_word_cnts = 0;
@@ -953,7 +954,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
(EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {
if (write_state == PG_STATE_HEADER) {
- dataempty = true;
badworden = 0x0F;
RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
("efuse PG_STATE_HEADER\n"));
@@ -1176,13 +1176,12 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw)
{
int continual = true;
u16 efuse_addr = 0;
- u8 hoffset, hworden;
+ u8 hworden;
u8 efuse_data, word_cnts;
while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data)
&& (efuse_addr < EFUSE_MAX_SIZE)) {
if (efuse_data != 0xFF) {
- hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
word_cnts = efuse_calculate_word_cnts(hworden);
efuse_addr = efuse_addr + (word_cnts * 2) + 1;
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index c29f398..38b793b 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/export.h>
#include "core.h"
#include "wifi.h"
#include "pci.h"
@@ -35,10 +36,10 @@
#include "efuse.h"
static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
- INTEL_VENDOR_ID,
- ATI_VENDOR_ID,
- AMD_VENDOR_ID,
- SIS_VENDOR_ID
+ PCI_VENDOR_ID_INTEL,
+ PCI_VENDOR_ID_ATI,
+ PCI_VENDOR_ID_AMD,
+ PCI_VENDOR_ID_SI
};
static const u8 ac_to_hwq[] = {
@@ -218,7 +219,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
/*Retrieve original configuration settings. */
u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
@@ -254,9 +254,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
udelay(50);
/*4 Disable Pci Bridge ASPM */
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + (num4bytes << 2));
- rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg);
+ pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
+ pcibridge_linkctrlreg);
udelay(50);
}
@@ -277,7 +276,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum;
u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum;
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
u16 aspmlevel;
u8 u_pcibridge_aspmsetting;
@@ -293,8 +291,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
}
/*4 Enable Pci Bridge ASPM */
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + (num4bytes << 2));
u_pcibridge_aspmsetting =
pcipriv->ndis_adapter.pcibridge_linkctrlreg |
@@ -303,7 +299,8 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
u_pcibridge_aspmsetting &= ~BIT(0);
- rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting);
+ pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
+ u_pcibridge_aspmsetting);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
("PlatformEnableASPM():PciBridge busnumber[%x], "
@@ -335,25 +332,18 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
{
- struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
bool status = false;
u8 offset_e0;
unsigned offset_e4;
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + 0xE0);
- rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, 0xA0);
+ pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0);
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + 0xE0);
- rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &offset_e0);
+ pci_read_config_byte(rtlpci->pdev, 0xe0, &offset_e0);
if (offset_e0 == 0xA0) {
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + 0xE4);
- rtl_pci_raw_read_port_ulong(PCI_CONF_DATA, &offset_e4);
+ pci_read_config_dword(rtlpci->pdev, 0xe4, &offset_e4);
if (offset_e4 & BIT(23))
status = true;
}
@@ -364,17 +354,15 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
{
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
u8 linkctrl_reg;
u8 num4bbytes;
num4bbytes = (capabilityoffset + 0x10) / 4;
/*Read Link Control Register */
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + (num4bbytes << 2));
- rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg);
+ pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
}
@@ -390,7 +378,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
u8 linkctrl_reg;
/*Link Control Register */
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg;
@@ -488,7 +476,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct sk_buff *skb = NULL;
struct ieee80211_tx_info *info = NULL;
- int tid; /* should be int */
+ int tid;
if (!rtlpriv->rtlhal.earlymode_enable)
return;
@@ -581,7 +569,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
fc = rtl_get_fc(skb);
if (ieee80211_is_nullfunc(fc)) {
if (ieee80211_has_pm(fc)) {
- rtlpriv->mac80211.offchan_deley = true;
+ rtlpriv->mac80211.offchan_delay = true;
rtlpriv->psc.state_inap = 1;
} else {
rtlpriv->psc.state_inap = 0;
@@ -622,10 +610,62 @@ tx_status_ok:
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtl_lps_leave(hw);
+ tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
}
}
+static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_rx_status rx_status)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+ __le16 fc = rtl_get_fc(skb);
+ bool unicast = false;
+ struct sk_buff *uskb = NULL;
+ u8 *pdata;
+
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+ if (is_broadcast_ether_addr(hdr->addr1)) {
+ ;/*TODO*/
+ } else if (is_multicast_ether_addr(hdr->addr1)) {
+ ;/*TODO*/
+ } else {
+ unicast = true;
+ rtlpriv->stats.rxbytesunicast += skb->len;
+ }
+
+ rtl_is_special_data(hw, skb, false);
+
+ if (ieee80211_is_data(fc)) {
+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+ if (unicast)
+ rtlpriv->link_info.num_rx_inperiod++;
+ }
+
+ /* for sw lps */
+ rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
+ rtl_recognize_peer(hw, (void *)skb->data, skb->len);
+ if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
+ (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) &&
+ (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)))
+ return;
+
+ if (unlikely(!rtl_action_proc(hw, skb, false)))
+ return;
+
+ uskb = dev_alloc_skb(skb->len + 128);
+ if (!uskb)
+ return; /* exit if allocation failed */
+ memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
+ pdata = (u8 *)skb_put(uskb, skb->len);
+ memcpy(pdata, skb->data, skb->len);
+
+ ieee80211_rx_irqsafe(hw, uskb);
+}
+
static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -637,185 +677,114 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
u8 own;
u8 tmp_one;
u32 bufferaddress;
- bool unicast = false;
struct rtl_stats stats = {
.signal = 0,
.noise = -98,
.rate = 0,
};
+ int index = rtlpci->rx_ring[rx_queue_idx].idx;
+ if (rtlpci->driver_is_goingto_unload)
+ return;
/*RX NORMAL PKT */
while (count--) {
/*rx descriptor */
struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[
- rtlpci->rx_ring[rx_queue_idx].idx];
+ index];
/*rx pkt */
struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
- rtlpci->rx_ring[rx_queue_idx].idx];
+ index];
+ struct sk_buff *new_skb = NULL;
own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
false, HW_DESC_OWN);
- if (own) {
- /*wait data to be filled by hardware */
- return;
- } else {
- struct ieee80211_hdr *hdr;
- __le16 fc;
- struct sk_buff *new_skb = NULL;
-
- rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
- &rx_status,
- (u8 *) pdesc, skb);
-
- new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
- if (unlikely(!new_skb)) {
- RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
- DBG_DMESG,
- ("can't alloc skb for rx\n"));
- goto done;
- }
+ /*wait data to be filled by hardware */
+ if (own)
+ break;
- pci_unmap_single(rtlpci->pdev,
- *((dma_addr_t *) skb->cb),
- rtlpci->rxbuffersize,
- PCI_DMA_FROMDEVICE);
+ rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+ &rx_status,
+ (u8 *) pdesc, skb);
- skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
- false,
- HW_DESC_RXPKT_LEN));
- skb_reserve(skb,
- stats.rx_drvinfo_size + stats.rx_bufshift);
+ if (stats.crc || stats.hwerror)
+ goto done;
- /*
- *NOTICE This can not be use for mac80211,
- *this is done in mac80211 code,
- *if you done here sec DHCP will fail
- *skb_trim(skb, skb->len - 4);
- */
+ new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
+ if (unlikely(!new_skb)) {
+ RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
+ DBG_DMESG,
+ ("can't alloc skb for rx\n"));
+ goto done;
+ }
- hdr = rtl_get_hdr(skb);
- fc = rtl_get_fc(skb);
-
- if (!stats.crc && !stats.hwerror) {
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
- sizeof(rx_status));
-
- if (is_broadcast_ether_addr(hdr->addr1)) {
- ;/*TODO*/
- } else if (is_multicast_ether_addr(hdr->addr1)) {
- ;/*TODO*/
- } else {
- unicast = true;
- rtlpriv->stats.rxbytesunicast +=
- skb->len;
- }
-
- rtl_is_special_data(hw, skb, false);
-
- if (ieee80211_is_data(fc)) {
- rtlpriv->cfg->ops->led_control(hw,
- LED_CTL_RX);
-
- if (unicast)
- rtlpriv->link_info.
- num_rx_inperiod++;
- }
-
- /* for sw lps */
- rtl_swlps_beacon(hw, (void *)skb->data,
- skb->len);
- rtl_recognize_peer(hw, (void *)skb->data,
- skb->len);
- if ((rtlpriv->mac80211.opmode ==
- NL80211_IFTYPE_AP) &&
- (rtlpriv->rtlhal.current_bandtype ==
- BAND_ON_2_4G) &&
- (ieee80211_is_beacon(fc) ||
- ieee80211_is_probe_resp(fc))) {
- dev_kfree_skb_any(skb);
- } else {
- if (unlikely(!rtl_action_proc(hw, skb,
- false))) {
- dev_kfree_skb_any(skb);
- } else {
- struct sk_buff *uskb = NULL;
- u8 *pdata;
- uskb = dev_alloc_skb(skb->len
- + 128);
- memcpy(IEEE80211_SKB_RXCB(uskb),
- &rx_status,
- sizeof(rx_status));
- pdata = (u8 *)skb_put(uskb,
- skb->len);
- memcpy(pdata, skb->data,
- skb->len);
- dev_kfree_skb_any(skb);
-
- ieee80211_rx_irqsafe(hw, uskb);
- }
- }
- } else {
- dev_kfree_skb_any(skb);
- }
+ pci_unmap_single(rtlpci->pdev,
+ *((dma_addr_t *) skb->cb),
+ rtlpci->rxbuffersize,
+ PCI_DMA_FROMDEVICE);
- if (((rtlpriv->link_info.num_rx_inperiod +
- rtlpriv->link_info.num_tx_inperiod) > 8) ||
- (rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtl_lps_leave(hw);
- }
+ skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false,
+ HW_DESC_RXPKT_LEN));
+ skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift);
+
+ /*
+ * NOTICE This can not be use for mac80211,
+ * this is done in mac80211 code,
+ * if you done here sec DHCP will fail
+ * skb_trim(skb, skb->len - 4);
+ */
- skb = new_skb;
+ _rtl_receive_one(hw, skb, rx_status);
- rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->
- rx_ring
- [rx_queue_idx].
- idx] = skb;
- *((dma_addr_t *) skb->cb) =
+ if (((rtlpriv->link_info.num_rx_inperiod +
+ rtlpriv->link_info.num_tx_inperiod) > 8) ||
+ (rtlpriv->link_info.num_rx_inperiod > 2)) {
+ tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
+ }
+
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+
+ rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
+ *((dma_addr_t *) skb->cb) =
pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
rtlpci->rxbuffersize,
PCI_DMA_FROMDEVICE);
- }
done:
bufferaddress = (*((dma_addr_t *)skb->cb));
tmp_one = 1;
rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
HW_DESC_RXBUFF_ADDR,
(u8 *)&bufferaddress);
- rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
- (u8 *)&tmp_one);
rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
HW_DESC_RXPKT_LEN,
(u8 *)&rtlpci->rxbuffersize);
- if (rtlpci->rx_ring[rx_queue_idx].idx ==
- rtlpci->rxringcount - 1)
+ if (index == rtlpci->rxringcount - 1)
rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
HW_DESC_RXERO,
(u8 *)&tmp_one);
- rtlpci->rx_ring[rx_queue_idx].idx =
- (rtlpci->rx_ring[rx_queue_idx].idx + 1) %
- rtlpci->rxringcount;
+ rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
+ (u8 *)&tmp_one);
+
+ index = (index + 1) % rtlpci->rxringcount;
}
+ rtlpci->rx_ring[rx_queue_idx].idx = index;
}
static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
{
struct ieee80211_hw *hw = dev_id;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
unsigned long flags;
u32 inta = 0;
u32 intb = 0;
- if (rtlpci->irq_enabled == 0)
- return IRQ_HANDLED;
-
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
/*read ISR: 4/8bytes */
@@ -938,6 +907,11 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
_rtl_pci_tx_chk_waitq(hw);
}
+static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw)
+{
+ rtl_lps_leave(hw);
+}
+
static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1041,6 +1015,9 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
(void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
(unsigned long)hw);
+ tasklet_init(&rtlpriv->works.ips_leave_tasklet,
+ (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet,
+ (unsigned long)hw);
}
static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1514,6 +1491,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
synchronize_irq(rtlpci->pdev->irq);
tasklet_kill(&rtlpriv->works.irq_tasklet);
+ tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
flush_workqueue(rtlpriv->works.rtl_wq);
destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1561,7 +1539,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
rtl_init_rx_config(hw);
- /*should after adapter start and interrupt enable. */
+ /*should be after adapter start and interrupt enable. */
set_hal_start(rtlhal);
RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
@@ -1582,12 +1560,14 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
u8 RFInProgressTimeOut = 0;
/*
- *should before disable interrrupt&adapter
+ *should be before disable interrupt&adapter
*and will do it immediately.
*/
set_hal_stop(rtlhal);
+ rtlpci->driver_is_goingto_unload = true;
rtlpriv->cfg->ops->disable_interrupt(hw);
+ tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
while (ppsc->rfchange_inprogress) {
@@ -1603,7 +1583,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
ppsc->rfchange_inprogress = true;
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
- rtlpci->driver_is_goingto_unload = true;
rtlpriv->cfg->ops->hw_disable(hw);
rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
@@ -1740,10 +1719,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
PCI_SLOT(bridge_pdev->devfn);
pcipriv->ndis_adapter.pcibridge_funcnum =
PCI_FUNC(bridge_pdev->devfn);
- pcipriv->ndis_adapter.pcicfg_addrport =
- (pcipriv->ndis_adapter.pcibridge_busnum << 16) |
- (pcipriv->ndis_adapter.pcibridge_devnum << 11) |
- (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31);
pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
pci_pcie_cap(bridge_pdev);
pcipriv->ndis_adapter.num4bytes =
@@ -2033,36 +2008,25 @@ call rtl_mac_stop() from the mac80211
suspend function first, So there is
no need to call hw_disable here.
****************************************/
-int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int rtl_pci_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->cfg->ops->hw_suspend(hw);
rtl_deinit_rfkill(hw);
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
EXPORT_SYMBOL(rtl_pci_suspend);
-int rtl_pci_resume(struct pci_dev *pdev)
+int rtl_pci_resume(struct device *dev)
{
- int ret;
+ struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct rtl_priv *rtlpriv = rtl_priv(hw);
- pci_set_power_state(pdev, PCI_D0);
- ret = pci_enable_device(pdev);
- if (ret) {
- RT_ASSERT(false, ("ERR: <======\n"));
- return ret;
- }
-
- pci_restore_state(pdev);
-
rtlpriv->cfg->ops->hw_resume(hw);
rtl_init_rfkill(hw);
return 0;
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 671b1f5..ebe0b42 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -62,12 +62,6 @@
.subdevice = PCI_ANY_ID,\
.driver_data = (kernel_ulong_t)&(cfg)
-#define INTEL_VENDOR_ID 0x8086
-#define SIS_VENDOR_ID 0x1039
-#define ATI_VENDOR_ID 0x1002
-#define ATI_DEVICE_ID 0x7914
-#define AMD_VENDOR_ID 0x1022
-
#define PCI_MAX_BRIDGE_NUMBER 255
#define PCI_MAX_DEVICES 32
#define PCI_MAX_FUNCTION 8
@@ -75,11 +69,6 @@
#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */
#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */
-#define PCI_CLASS_BRIDGE_DEV 0x06
-#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04
-#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10
-#define PCI_CAP_ID_EXP 0x10
-
#define U1DONTCARE 0xFF
#define U2DONTCARE 0xFFFF
#define U4DONTCARE 0xFFFFFFFF
@@ -169,7 +158,6 @@ struct rtl_pci {
bool first_init;
bool being_init_adapter;
bool init_ready;
- bool irq_enabled;
/*Tx */
struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT];
@@ -224,7 +212,6 @@ struct mp_adapter {
u16 pcibridge_vendorid;
u16 pcibridge_deviceid;
- u32 pcicfg_addrport;
u8 num4bytes;
u8 pcibridge_pciehdr_offset;
@@ -250,8 +237,8 @@ extern struct rtl_intf_ops rtl_pci_ops;
int __devinit rtl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
void rtl_pci_disconnect(struct pci_dev *pdev);
-int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-int rtl_pci_resume(struct pci_dev *pdev);
+int rtl_pci_suspend(struct device *dev);
+int rtl_pci_resume(struct device *dev);
static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
@@ -285,29 +272,4 @@ static inline void pci_write32_async(struct rtl_priv *rtlpriv,
writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
}
-static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val)
-{
- outl(val, port);
-}
-
-static inline void rtl_pci_raw_write_port_uchar(u32 port, u8 val)
-{
- outb(val, port);
-}
-
-static inline void rtl_pci_raw_read_port_uchar(u32 port, u8 *pval)
-{
- *pval = inb(port);
-}
-
-static inline void rtl_pci_raw_read_port_ushort(u32 port, u16 *pval)
-{
- *pval = inw(port);
-}
-
-static inline void rtl_pci_raw_read_port_ulong(u32 port, u32 *pval)
-{
- *pval = inl(port);
-}
-
#endif
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index 39b0297..55c8e50 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/export.h>
#include "wifi.h"
#include "base.h"
#include "ps.h"
@@ -68,6 +69,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
/*<2> Disable Interrupt */
rtlpriv->cfg->ops->disable_interrupt(hw);
+ tasklet_kill(&rtlpriv->works.irq_tasklet);
/*<3> Disable Adapter */
rtlpriv->cfg->ops->hw_disable(hw);
@@ -78,65 +80,18 @@ EXPORT_SYMBOL(rtl_ps_disable_nic);
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
enum rf_pwrstate state_toset,
- u32 changesource, bool protect_or_not)
+ u32 changesource)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- enum rf_pwrstate rtstate;
bool actionallowed = false;
- u16 rfwait_cnt = 0;
- unsigned long flag;
-
- /*protect_or_not = true; */
-
- if (protect_or_not)
- goto no_protect;
-
- /*
- *Only one thread can change
- *the RF state at one time, and others
- *should wait to be executed.
- */
- while (true) {
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- if (ppsc->rfchange_inprogress) {
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
- flag);
-
- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
- ("RF Change in progress!"
- "Wait to set..state_toset(%d).\n",
- state_toset));
-
- /* Set RF after the previous action is done. */
- while (ppsc->rfchange_inprogress) {
- rfwait_cnt++;
- mdelay(1);
-
- /*
- *Wait too long, return false to avoid
- *to be stuck here.
- */
- if (rfwait_cnt > 100)
- return false;
- }
- } else {
- ppsc->rfchange_inprogress = true;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
- flag);
- break;
- }
- }
-
-no_protect:
- rtstate = ppsc->rfpwr_state;
switch (state_toset) {
case ERFON:
ppsc->rfoff_reason &= (~changesource);
if ((changesource == RF_CHANGE_BY_HW) &&
- (ppsc->hwradiooff == true)) {
+ (ppsc->hwradiooff)) {
ppsc->hwradiooff = false;
}
@@ -172,12 +127,6 @@ no_protect:
if (actionallowed)
rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
- if (!protect_or_not) {
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- ppsc->rfchange_inprogress = false;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
- }
-
return actionallowed;
}
EXPORT_SYMBOL(rtl_ps_set_rf_state);
@@ -200,8 +149,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
}
}
- rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
- RF_CHANGE_BY_IPS, false);
+ rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
if (ppsc->inactive_pwrstate == ERFOFF &&
rtlhal->interface == INTF_PCI) {
@@ -289,12 +237,11 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
enum rf_pwrstate rtstate;
- unsigned long flags;
if (mac->opmode != NL80211_IFTYPE_STATION)
return;
- spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
+ spin_lock(&rtlpriv->locks.ips_lock);
if (ppsc->inactiveps) {
rtstate = ppsc->rfpwr_state;
@@ -310,7 +257,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
+ spin_unlock(&rtlpriv->locks.ips_lock);
}
/*for FW LPS*/
@@ -428,7 +375,6 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
- unsigned long flag;
if (!ppsc->fwctrl_lps)
return;
@@ -449,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
if (mac->link_state != MAC80211_LINKED)
return;
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+ spin_lock_irq(&rtlpriv->locks.lps_lock);
/* Idle for a while if we connect to AP a while ago. */
if (mac->cnt_after_linked >= 2) {
@@ -461,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_unlock_irq(&rtlpriv->locks.lps_lock);
}
/*Leave the leisure power save mode.*/
@@ -470,9 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- unsigned long flag;
+ unsigned long flags;
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
if (ppsc->fwctrl_lps) {
if (ppsc->dot11_psmode != EACTIVE) {
@@ -493,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
rtl_lps_set_psmode(hw, EACTIVE);
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
}
/* For sw LPS*/
@@ -582,7 +528,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- unsigned long flag;
if (!rtlpriv->psc.swctrl_lps)
return;
@@ -595,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
}
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_lock_irq(&rtlpriv->locks.lps_lock);
+ rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
+ spin_unlock_irq(&rtlpriv->locks.lps_lock);
}
void rtl_swlps_rfon_wq_callback(void *data)
@@ -614,7 +559,6 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- unsigned long flag;
u8 sleep_intv;
if (!rtlpriv->psc.sw_ps_enabled)
@@ -631,16 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
if (rtlpriv->link_info.busytraffic)
return;
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- if (rtlpriv->psc.rfchange_inprogress) {
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
- return;
- }
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
-
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_lock_irq(&rtlpriv->locks.lps_lock);
+ rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
+ spin_unlock_irq(&rtlpriv->locks.lps_lock);
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h
index e3bf898..84628e60 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/rtlwifi/ps.h
@@ -33,8 +33,7 @@
#define MAX_SW_LPS_SLEEP_INTV 5
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
- enum rf_pwrstate state_toset, u32 changesource,
- bool protect_or_not);
+ enum rf_pwrstate state_toset, u32 changesource);
bool rtl_ps_enable_nic(struct ieee80211_hw *hw);
bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
void rtl_ips_nic_off(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index 30da68a..539df66 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -200,7 +200,7 @@ static void rtl_tx_status(void *ppriv,
if (sta) {
/* Check if aggregation has to be enabled for this tid */
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
- if ((sta->ht_cap.ht_supported == true) &&
+ if ((sta->ht_cap.ht_supported) &&
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
if (ieee80211_is_data_qos(fc)) {
u8 tid = rtl_get_tid(skb);
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c
index 8f6718f..9fedb1f 100644
--- a/drivers/net/wireless/rtlwifi/regd.c
+++ b/drivers/net/wireless/rtlwifi/regd.c
@@ -303,22 +303,6 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,
return;
}
-static void _rtl_dump_channel_map(struct wiphy *wiphy)
-{
- enum ieee80211_band band;
- struct ieee80211_supported_band *sband;
- struct ieee80211_channel *ch;
- unsigned int i;
-
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
- if (!wiphy->bands[band])
- continue;
- sband = wiphy->bands[band];
- for (i = 0; i < sband->n_channels; i++)
- ch = &sband->channels[i];
- }
-}
-
static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
struct regulatory_request *request,
struct rtl_regulatory *reg)
@@ -336,8 +320,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
break;
}
- _rtl_dump_channel_map(wiphy);
-
return 0;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 2d33d7d..ba7ef2f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/export.h>
#include "dm_common.h"
#include "phy_common.h"
#include "../pci.h"
@@ -474,7 +475,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- if (mac->act_scanning == true)
+ if (mac->act_scanning)
return;
if (mac->link_state >= MAC80211_LINKED)
@@ -674,7 +675,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
int i;
bool is2t = IS_92C_SERIAL(rtlhal->version);
- u8 txpwr_level[2] = {0, 0};
+ s8 txpwr_level[2] = {0, 0};
u8 ofdm_min_index = 6, rf;
rtlpriv->dm.txpower_trackinginit = true;
@@ -1227,11 +1228,14 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
if (rtlhal->interface == INTF_PCI) {
rcu_read_lock();
sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ if (!sta)
+ goto out_unlock;
}
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
p_ra->ratr_state);
p_ra->pre_ratr_state = p_ra->ratr_state;
+ out_unlock:
if (rtlhal->interface == INTF_PCI)
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 50303e1..13fc0f9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -27,7 +27,10 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/firmware.h>
+#include <linux/export.h>
#include "../wifi.h"
#include "../pci.h"
#include "../base.h"
@@ -224,8 +227,7 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
u32 fwsize;
enum version_8192c version = rtlhal->version;
- printk(KERN_INFO "rtl8192c: Loading firmware file %s\n",
- rtlpriv->cfg->fw_name);
+ pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
if (!rtlhal->pfirmware)
return 1;
@@ -546,7 +548,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring;
struct rtl_tx_desc *pdesc;
- u8 own;
unsigned long flags;
struct sk_buff *pskb = NULL;
@@ -559,7 +560,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pdesc = &ring->desc[0];
- own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
@@ -752,6 +752,8 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
skb = dev_alloc_skb(totalpacketlen);
+ if (!skb)
+ return;
memcpy((u8 *) skb_put(skb, totalpacketlen),
&reserved_page_packet, totalpacketlen);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/rtlwifi/rtl8192c/main.c
index 2f624fc..605ff19 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/main.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/main.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/module.h>
#include "../wifi.h"
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index d2cc815..f20678a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -27,6 +27,7 @@
*
*****************************************************************************/
+#include <linux/export.h>
#include "../wifi.h"
#include "../rtl8192ce/reg.h"
#include "../rtl8192ce/def.h"
@@ -1253,10 +1254,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
const u32 retrycount = 2;
- u32 bbvalue;
-
if (t == 0) {
- bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+ /* dummy read */
+ rtl_get_bbreg(hw, 0x800, MASKDWORD);
_rtl92c_phy_save_adda_registers(hw, adda_reg,
rtlphy->adda_backup, 16);
@@ -1762,8 +1762,7 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
long result[4][8];
u8 i, final_candidate;
bool patha_ok, pathb_ok;
- long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
- reg_ecc, reg_tmp = 0;
+ long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4, reg_tmp = 0;
bool is12simular, is13simular, is23simular;
bool start_conttx = false, singletone = false;
u32 iqk_bb_reg[10] = {
@@ -1841,21 +1840,17 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
reg_e94 = result[i][0];
reg_e9c = result[i][1];
reg_ea4 = result[i][2];
- reg_eac = result[i][3];
reg_eb4 = result[i][4];
reg_ebc = result[i][5];
reg_ec4 = result[i][6];
- reg_ecc = result[i][7];
}
if (final_candidate != 0xff) {
rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
reg_ea4 = result[final_candidate][2];
- reg_eac = result[final_candidate][3];
rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
reg_ec4 = result[final_candidate][6];
- reg_ecc = result[final_candidate][7];
patha_ok = pathb_ok = true;
} else {
rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
@@ -1973,7 +1968,7 @@ void rtl92c_phy_set_io(struct ieee80211_hw *hw)
break;
case IO_CMD_PAUSE_DM_BY_SCAN:
rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
- dm_digtable.cur_igvalue = 0x17;
+ dm_digtable.cur_igvalue = 0x37;
rtl92c_dm_write_dig(hw);
break;
default:
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 35ff7df..7305a47 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -117,6 +117,7 @@
#define CHIP_VER_B BIT(4)
#define CHIP_92C_BITMASK BIT(0)
+#define CHIP_UNKNOWN BIT(7)
#define CHIP_92C_1T2R 0x03
#define CHIP_92C 0x01
#define CHIP_88C 0x00
@@ -142,8 +143,22 @@ enum version_8192c {
VERSION_UNKNOWN = 0x88,
};
+#define CUT_VERSION_MASK (BIT(6)|BIT(7))
+#define CHIP_VENDOR_UMC BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT BIT(6) /* Chip version for ECO */
+#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
#define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false)
+#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
#define IS_92C_SERIAL(version) ((version & CHIP_92C_BITMASK) ? true : false)
+#define IS_CHIP_VENDOR_UMC(version) \
+ ((version & CHIP_VENDOR_UMC) ? true : false)
+#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK)
+#define IS_81xxC_VENDOR_UMC_B_CUT(version) \
+ ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version) == CHIP_VENDOR_UMC_B_CUT) ? \
+ true : false) : false)
enum rtl819x_loopback_e {
RTL819X_NO_LOOPBACK = 0,
@@ -220,41 +235,6 @@ enum rtl_desc_qsel {
QSLT_CMD = 0x13,
};
-enum rtl_desc92c_rate {
- DESC92C_RATE1M = 0x00,
- DESC92C_RATE2M = 0x01,
- DESC92C_RATE5_5M = 0x02,
- DESC92C_RATE11M = 0x03,
-
- DESC92C_RATE6M = 0x04,
- DESC92C_RATE9M = 0x05,
- DESC92C_RATE12M = 0x06,
- DESC92C_RATE18M = 0x07,
- DESC92C_RATE24M = 0x08,
- DESC92C_RATE36M = 0x09,
- DESC92C_RATE48M = 0x0a,
- DESC92C_RATE54M = 0x0b,
-
- DESC92C_RATEMCS0 = 0x0c,
- DESC92C_RATEMCS1 = 0x0d,
- DESC92C_RATEMCS2 = 0x0e,
- DESC92C_RATEMCS3 = 0x0f,
- DESC92C_RATEMCS4 = 0x10,
- DESC92C_RATEMCS5 = 0x11,
- DESC92C_RATEMCS6 = 0x12,
- DESC92C_RATEMCS7 = 0x13,
- DESC92C_RATEMCS8 = 0x14,
- DESC92C_RATEMCS9 = 0x15,
- DESC92C_RATEMCS10 = 0x16,
- DESC92C_RATEMCS11 = 0x17,
- DESC92C_RATEMCS12 = 0x18,
- DESC92C_RATEMCS13 = 0x19,
- DESC92C_RATEMCS14 = 0x1a,
- DESC92C_RATEMCS15 = 0x1b,
- DESC92C_RATEMCS15_SG = 0x1c,
- DESC92C_RATEMCS32 = 0x20,
-};
-
struct phy_sts_cck_8192s_t {
u8 adc_pwdb_X[4];
u8 sq_rpt;
@@ -267,108 +247,4 @@ struct h2c_cmd_8192c {
u8 *p_cmdbuffer;
};
-/* NOTE: reference to rtl8192c_rates struct */
-static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT,
- u8 desc_rate, bool first_ampdu)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- int rate_idx = 0;
-
- if (first_ampdu) {
- if (false == isHT) {
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
- ("Rate %d is not support, set to "
- "1M rate.\n", desc_rate));
- rate_idx = 0;
- break;
- }
- } else {
- rate_idx = 11;
- }
- return rate_idx;
- }
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- /* TODO: How to mapping MCS rate? */
- /* NOTE: referenc to __ieee80211_rx */
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
-}
-
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index defb437..ce1fdbe 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -488,7 +488,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *) (val))[0];
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92ce_stop_tx_beacon(hw);
_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3));
@@ -500,7 +500,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92ce_resume_tx_beacon(hw);
break;
@@ -763,11 +763,9 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
u8 reg_bw_opmode;
- u32 reg_ratr, reg_prsr;
+ u32 reg_prsr;
reg_bw_opmode = BW_OPMODE_20MHZ;
- reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
- RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
@@ -907,14 +905,26 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
bool is92c;
int err;
u8 tmp_u1b;
+ unsigned long flags;
rtlpci->being_init_adapter = true;
+
+ /* Since this function can take a very long time (up to 350 ms)
+ * and can be called with irqs disabled, reenable the irqs
+ * to let the other devices continue being serviced.
+ *
+ * It is safe doing so since our own interrupts will only be enabled
+ * in a subsequent step.
+ */
+ local_save_flags(flags);
+ local_irq_enable();
+
rtlpriv->intf_ops->disable_aspm(hw);
rtstatus = _rtl92ce_init_mac(hw);
if (rtstatus != true) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Init MAC failed\n"));
err = 1;
- return err;
+ goto exit;
}
err = rtl92c_download_fw(hw);
@@ -924,7 +934,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
"without FW now..\n"));
err = 1;
rtlhal->fw_ready = false;
- return err;
+ goto exit;
} else {
rtlhal->fw_ready = true;
}
@@ -987,6 +997,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("under 1.5V\n"));
}
rtl92c_dm_init(hw);
+exit:
+ local_irq_restore(flags);
rtlpci->being_init_adapter = false;
return err;
}
@@ -1003,8 +1015,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :
VERSION_A_CHIP_88C;
} else {
- version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C :
- VERSION_B_CHIP_88C;
+ version = (enum version_8192c) (CHIP_VER_B |
+ ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) |
+ ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+ if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 &
+ CHIP_VER_RTL_MASK)) {
+ version = (enum version_8192c)(version |
+ ((((value32 & CHIP_VER_RTL_MASK) == BIT(12))
+ ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
+ CHIP_VENDOR_UMC));
+ }
}
switch (version) {
@@ -1123,7 +1143,7 @@ void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (check_bssid == true) {
+ if (check_bssid) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *) (&reg_rcr));
@@ -1185,7 +1205,6 @@ void rtl92ce_enable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
- rtlpci->irq_enabled = true;
}
void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1195,7 +1214,7 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
@@ -1586,7 +1605,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
for (i = 0; i < 6; i += 2) {
@@ -1595,7 +1614,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+ ("%pM\n", rtlefuse->dev_addr));
_rtl92ce_read_txpower_info_from_hwpg(hw,
rtlefuse->autoload_failflag,
@@ -1969,7 +1988,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+ enum rf_pwrstate e_rfpowerstate_toset;
u8 u1tmp;
bool actuallyset = false;
unsigned long flag;
@@ -1989,15 +2008,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
}
- cur_rfstate = ppsc->rfpwr_state;
-
rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
REG_MAC_PINMUX_CFG)&~(BIT(3)));
u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
- if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+ if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
("GPIOChangeRF - HW Radio ON, RF ON\n"));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
index 9dd1ed7..28a1a70 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
@@ -84,7 +84,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (pcipriv->ledctl.led_opendrain == true)
+ if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index abe0fcc..3b585aa 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -46,13 +46,12 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
struct rtl_phy *rtlphy = &(rtlpriv->phy);
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
"rfpath(%#x), bitmask(%#x)\n",
regaddr, rfpath, bitmask));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (rtlphy->rf_mode != RF_OP_BY_FW) {
original_value = _rtl92c_phy_rf_serial_read(hw,
@@ -65,7 +64,7 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
("regaddr(%#x), rfpath(%#x), "
@@ -120,13 +119,12 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 original_value, bitshift;
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
regaddr, bitmask, data, rfpath));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (rtlphy->rf_mode != RF_OP_BY_FW) {
if (bitmask != RFREG_OFFSET_MASK) {
@@ -153,7 +151,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
}
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
"bitmask(%#x), data(%#x), "
@@ -281,7 +279,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
{
int i;
- bool rtstatus = true;
u32 *radioa_array_table;
u32 *radiob_array_table;
u16 radioa_arraylen, radiob_arraylen;
@@ -308,7 +305,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
- rtstatus = true;
switch (rfpath) {
case RF90_PATH_A:
for (i = 0; i < radioa_arraylen; i = i + 2) {
@@ -521,7 +517,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
u8 i, queue_id;
struct rtl8192_tx_ring *ring = NULL;
- ppsc->set_rfpowerstate_inprogress = true;
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -574,7 +569,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
}
case ERFSLEEP:{
if (ppsc->rfpwr_state == ERFOFF)
- break;
+ return false;
for (queue_id = 0, i = 0;
queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
ring = &pcipriv->dev.tx_ring[queue_id];
@@ -617,7 +612,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
return bresult;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index 598cecc..ba5ff04 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -1074,10 +1074,10 @@
#define _SRL(x) (((x) & 0x3F) << 8)
#define _SIFS_CCK_CTX(x) ((x) & 0xFF)
-#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8);
+#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8)
#define _SIFS_OFDM_CTX(x) ((x) & 0xFF)
-#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8);
+#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8)
#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8)
@@ -1203,7 +1203,9 @@
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_LOAD 1
+#define HWSET_MAX_SIZE 128
#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE
+#define EFUSE_MAX_SECTION 16
#define WL_HWPDN_EN BIT(0)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index 90d0f2c..d3b01e6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -76,7 +76,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
if (rtlefuse->eeprom_regulatory != 0)
turbo_scanoff = true;
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 373dc78..df852e8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -28,6 +28,7 @@
*****************************************************************************/
#include <linux/vmalloc.h>
+#include <linux/module.h>
#include "../wifi.h"
#include "../core.h"
@@ -92,6 +93,8 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
const struct firmware *firmware;
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ char *fw_name = NULL;
rtl8192ce_bt_reg_init(hw);
@@ -129,10 +132,16 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0);
+ /* for debug level */
+ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
/* for LPS & IPS */
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("rtl8192ce: Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+ pr_info("rtl8192ce: FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
@@ -155,8 +164,16 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
}
/* request fw */
- err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
- rtlpriv->io.dev);
+ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+ !IS_92C_SERIAL(rtlhal->version)) {
+ fw_name = "rtlwifi/rtl8192cfwU.bin";
+ } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+ pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n");
+ } else {
+ fw_name = rtlpriv->cfg->fw_name;
+ }
+ err = request_firmware(&firmware, fw_name, rtlpriv->io.dev);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("Failed to request firmware!\n"));
@@ -241,6 +258,7 @@ static struct rtl_mod_params rtl92ce_mod_params = {
.inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
+ .debug = DBG_EMERG,
};
static struct rtl_hal_cfg rtl92ce_hal_cfg = {
@@ -318,21 +336,21 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
-
- .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
+ .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
+ .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
+ .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M,
+ .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M,
+ .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M,
+ .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M,
+ .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M,
+ .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M,
+ .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M,
+ .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M,
+ .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M,
+ .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M,
+
+ .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7,
+ .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = {
@@ -351,27 +369,35 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cfwU.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cfwU_B.bin");
module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92ce_mod_params.debug, int, 0444);
module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(fwlps, "using linked fw control power save "
- "(default 1 is open)\n");
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
+static const struct dev_pm_ops rtlwifi_pm_ops = {
+ .suspend = rtl_pci_suspend,
+ .resume = rtl_pci_resume,
+ .freeze = rtl_pci_suspend,
+ .thaw = rtl_pci_resume,
+ .poweroff = rtl_pci_suspend,
+ .restore = rtl_pci_resume,
+};
static struct pci_driver rtl92ce_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl92ce_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
-
-#ifdef CONFIG_PM
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
-#endif
-
+ .driver.pm = &rtlwifi_pm_ops,
};
static int __init rtl92ce_module_init(void)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 54b2bd5..4fb5ae2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -48,104 +48,6 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
return skb->priority;
}
-static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
-{
- int rate_idx;
-
- if (first_ampdu) {
- if (false == isht) {
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 0;
- break;
- }
- } else {
- rate_idx = 11;
- }
-
- return rate_idx;
- }
-
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
-}
-
static u8 _rtl92c_query_rxpwrpercentage(char antpower)
{
if ((antpower <= -100) || (antpower >= 20))
@@ -225,7 +127,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct phy_sts_cck_8192s_t *cck_buf;
- s8 rx_pwr_all, rx_pwr[4];
+ s8 rx_pwr_all = 0, rx_pwr[4];
u8 evm, pwdb_all, rf_rx_num = 0;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
@@ -336,8 +238,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
- if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 &&
- pdesc->rxmcs <= DESC92C_RATEMCS15)
+ if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 &&
+ pdesc->rxmcs <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
@@ -592,7 +494,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, c_fc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -604,7 +505,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
c_fc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid =
((IEEE80211_FTYPE_CTL != type) &&
@@ -672,15 +572,13 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
- rx_status->rate_idx = _rtl92ce_rate_mapping((bool)
- GET_RX_DESC_RXHT(pdesc),
- (u8)
- GET_RX_DESC_RXMCS(pdesc),
- (bool)
- GET_RX_DESC_PAGGR(pdesc));
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RXHT(pdesc),
+ (u8)GET_RX_DESC_RXMCS(pdesc),
+ (bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
stats->rx_bufshift);
@@ -770,7 +668,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_BW(pdesc, 0);
SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc,
- ((tcb_desc->rts_rate <= DESC92C_RATE54M) ?
+ ((tcb_desc->rts_rate <= DESC92_RATE54M) ?
(tcb_desc->rts_use_shortpreamble ? 1 : 0)
: (tcb_desc->rts_use_shortgi ? 1 : 0)));
@@ -888,7 +786,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
if (firstseg)
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
- SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
+ SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);
SET_TX_DESC_SEQ(pdesc, 0);
@@ -929,9 +827,10 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
@@ -945,6 +844,7 @@ void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
+ wmb();
SET_RX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
@@ -968,7 +868,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
{
u32 ret = 0;
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(p_desc);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
index 0f11771..c8977a5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
@@ -537,12 +537,6 @@ do { \
memset(__pdesc, 0, _size); \
} while (0);
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (_pdesc->rxmcs == DESC92C_RATE1M || \
- _pdesc->rxmcs == DESC92C_RATE2M || \
- _pdesc->rxmcs == DESC92C_RATE5_5M || \
- _pdesc->rxmcs == DESC92C_RATE11M)
-
struct rx_fwinfo_92c {
u8 gain_trsw[4];
u8 pwdb_all;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
index c54940e..d097efb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
@@ -50,10 +50,6 @@
#define IS_VENDOR_UMC(version) \
(((version) & CHIP_VENDOR_UMC) ? true : false)
-#define IS_VENDOR_UMC_A_CUT(version) \
- (((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6) | BIT(7))) ? \
- false : true) : false)
-
#define IS_VENDOR_8723_A_CUT(version) \
(((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6))) ? \
false : true) : false)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 52e2af5..79fc4b7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "../efuse.h"
#include "../base.h"
@@ -337,7 +339,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
rtlefuse->board_type = boardType;
if (IS_HIGHT_PA(rtlefuse->board_type))
rtlefuse->external_pa = 1;
- printk(KERN_INFO "rtl8192cu: Board Type %x\n", rtlefuse->board_type);
+ pr_info("Board Type %x\n", rtlefuse->board_type);
#ifdef CONFIG_ANTENNA_DIVERSITY
/* Antenna Diversity setting. */
@@ -346,8 +348,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
else
rtl_efuse->antenna_cfg = registry_par->antdiv_cfg; /* 0:OFF, */
- printk(KERN_INFO "rtl8192cu: Antenna Config %x\n",
- rtl_efuse->antenna_cfg);
+ pr_info("Antenna Config %x\n", rtl_efuse->antenna_cfg);
#endif
}
@@ -384,71 +385,57 @@ static void _update_bt_param(_adapter *padapter)
pbtpriv->bBTNonTrafficModeSet = _FALSE;
pbtpriv->CurrentState = 0;
pbtpriv->PreviousState = 0;
- printk(KERN_INFO "rtl8192cu: BT Coexistance = %s\n",
- (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
+ pr_info("BT Coexistance = %s\n",
+ (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
if (pbtpriv->BT_Coexist) {
if (pbtpriv->BT_Ant_Num == Ant_x2)
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "Ant_Num = Antx2\n");
+ pr_info("BlueTooth BT_Ant_Num = Antx2\n");
else if (pbtpriv->BT_Ant_Num == Ant_x1)
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "Ant_Num = Antx1\n");
+ pr_info("BlueTooth BT_Ant_Num = Antx1\n");
switch (pbtpriv->BT_CoexistType) {
case BT_2Wire:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_2Wire\n");
+ pr_info("BlueTooth BT_CoexistType = BT_2Wire\n");
break;
case BT_ISSC_3Wire:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_ISSC_3Wire\n");
+ pr_info("BlueTooth BT_CoexistType = BT_ISSC_3Wire\n");
break;
case BT_Accel:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_Accel\n");
+ pr_info("BlueTooth BT_CoexistType = BT_Accel\n");
break;
case BT_CSR_BC4:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_CSR_BC4\n");
+ pr_info("BlueTooth BT_CoexistType = BT_CSR_BC4\n");
break;
case BT_CSR_BC8:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_CSR_BC8\n");
+ pr_info("BlueTooth BT_CoexistType = BT_CSR_BC8\n");
break;
case BT_RTL8756:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_RTL8756\n");
+ pr_info("BlueTooth BT_CoexistType = BT_RTL8756\n");
break;
default:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = Unknown\n");
+ pr_info("BlueTooth BT_CoexistType = Unknown\n");
break;
}
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Ant_isolation = %d\n",
- pbtpriv->BT_Ant_isolation);
+ pr_info("BlueTooth BT_Ant_isolation = %d\n",
+ pbtpriv->BT_Ant_isolation);
switch (pbtpriv->BT_Service) {
case BT_OtherAction:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_OtherAction\n");
+ pr_info("BlueTooth BT_Service = BT_OtherAction\n");
break;
case BT_SCO:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_SCO\n");
+ pr_info("BlueTooth BT_Service = BT_SCO\n");
break;
case BT_Busy:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_Busy\n");
+ pr_info("BlueTooth BT_Service = BT_Busy\n");
break;
case BT_OtherBusy:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_OtherBusy\n");
+ pr_info("BlueTooth BT_Service = BT_OtherBusy\n");
break;
default:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_Idle\n");
+ pr_info("BlueTooth BT_Service = BT_Idle\n");
break;
}
- printk(KERN_INFO "rtl8192cu: BT_RadioSharedType = 0x%x\n",
- pbtpriv->BT_RadioSharedType);
+ pr_info("BT_RadioSharedType = 0x%x\n",
+ pbtpriv->BT_RadioSharedType);
}
}
@@ -520,13 +507,13 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
for (i = 0; i < 6; i += 2) {
usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
}
- printk(KERN_INFO "rtl8192cu: MAC address: %pM\n", rtlefuse->dev_addr);
+ pr_info("MAC address: %pM\n", rtlefuse->dev_addr);
_rtl92cu_read_txpower_info_from_hwpg(hw,
rtlefuse->autoload_failflag, hwinfo);
rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
@@ -665,7 +652,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
rtl_write_word(rtlpriv, REG_APS_FSMCO, value16);
do {
if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) {
- printk(KERN_INFO "rtl8192cu: MAC auto ON okay!\n");
+ pr_info("MAC auto ON okay!\n");
break;
}
if (pollingCount++ > 100) {
@@ -819,7 +806,7 @@ static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
}
_rtl92c_init_chipN_reg_priority(hw, value, value, value, value,
value, value);
- printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+ pr_info("Tx queue select: 0x%02x\n", queue_sel);
}
static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
@@ -863,7 +850,7 @@ static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
hiQ = valueHi;
}
_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
- printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+ pr_info("Tx queue select: 0x%02x\n", queue_sel);
}
static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw,
@@ -1171,12 +1158,23 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
int err = 0;
static bool iqk_initialized;
+ unsigned long flags;
+
+ /* As this function can take a very long time (up to 350 ms)
+ * and can be called with irqs disabled, reenable the irqs
+ * to let the other devices continue being serviced.
+ *
+ * It is safe doing so since our own interrupts will only be enabled
+ * in a subsequent step.
+ */
+ local_save_flags(flags);
+ local_irq_enable();
rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU;
err = _rtl92cu_init_mac(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("init mac failed!\n"));
- return err;
+ goto exit;
}
err = rtl92c_download_fw(hw);
if (err) {
@@ -1184,7 +1182,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
("Failed to download FW. Init HW without FW now..\n"));
err = 1;
rtlhal->fw_ready = false;
- return err;
+ goto exit;
} else {
rtlhal->fw_ready = true;
}
@@ -1225,6 +1223,8 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
_update_mac_setting(hw);
rtl92c_dm_init(hw);
_dump_registers(hw);
+exit:
+ local_irq_restore(flags);
return err;
}
@@ -1570,74 +1570,57 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
{
- /* dummy routine needed for callback from rtl_op_configure_filter() */
-}
-
-/*========================================================================== */
-
-static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
- enum nl80211_iftype type)
-{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
- struct rtl_phy *rtlphy = &(rtlpriv->phy);
- u8 filterout_non_associated_bssid = false;
+ u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
- switch (type) {
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_STATION:
- filterout_non_associated_bssid = true;
- break;
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_AP:
- default:
- break;
- }
- if (filterout_non_associated_bssid == true) {
+ if (rtlpriv->psc.rfpwr_state != ERFON)
+ return;
+
+ if (check_bssid) {
+ u8 tmp;
if (IS_NORMAL_CHIP(rtlhal->version)) {
- switch (rtlphy->current_io_type) {
- case IO_CMD_RESUME_DM_BY_SCAN:
- reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
- rtlpriv->cfg->ops->set_hw_reg(hw,
- HW_VAR_RCR, (u8 *)(&reg_rcr));
- /* enable update TSF */
- _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
- break;
- case IO_CMD_PAUSE_DM_BY_SCAN:
- reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
- rtlpriv->cfg->ops->set_hw_reg(hw,
- HW_VAR_RCR, (u8 *)(&reg_rcr));
- /* disable update TSF */
- _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
- break;
- }
+ reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ tmp = BIT(4);
} else {
- reg_rcr |= (RCR_CBSSID);
- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
- (u8 *)(&reg_rcr));
- _rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
+ reg_rcr |= RCR_CBSSID;
+ tmp = BIT(4) | BIT(5);
}
- } else if (filterout_non_associated_bssid == false) {
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+ (u8 *) (&reg_rcr));
+ _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
+ } else {
+ u8 tmp;
if (IS_NORMAL_CHIP(rtlhal->version)) {
- reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
- (u8 *)(&reg_rcr));
- _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+ reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ tmp = BIT(4);
} else {
- reg_rcr &= (~RCR_CBSSID);
- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
- (u8 *)(&reg_rcr));
- _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
+ reg_rcr &= ~RCR_CBSSID;
+ tmp = BIT(4) | BIT(5);
}
+ reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_RCR, (u8 *) (&reg_rcr));
+ _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0);
}
}
+/*========================================================================== */
+
int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
if (_rtl92cu_set_media_status(hw, type))
return -EOPNOTSUPP;
- _rtl92cu_set_check_bssid(hw, type);
+
+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+ if (type != NL80211_IFTYPE_AP)
+ rtl92cu_set_check_bssid(hw, true);
+ } else {
+ rtl92cu_set_check_bssid(hw, false);
+ }
+
return 0;
}
@@ -2155,7 +2138,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *) (val))[0];
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92cu_stop_tx_beacon(hw);
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf &
@@ -2163,7 +2146,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
rtl_write_dword(rtlpriv, REG_TSFTR + 4,
(u32)((mac->tsf >> 32) & 0xffffffff));
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92cu_resume_tx_beacon(hw);
break;
}
@@ -2251,8 +2234,6 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
(shortgi_rate << 4) | (shortgi_rate);
}
rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
- RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("%x\n", rtl_read_dword(rtlpriv,
- REG_ARFR0)));
}
void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
index 332c743..2ff9d83 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
@@ -82,7 +82,7 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (usbpriv->ledctl.led_opendrain == true)
+ if (usbpriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index f8514cb..5515215 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -26,6 +26,9 @@
* Larry Finger <Larry.Finger@lwfinger.net>
*
****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include "../wifi.h"
@@ -213,14 +216,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
for (i = 0; i < (boundary - 1); i++) {
rst = rtl92c_llt_write(hw, i , i + 1);
if (true != rst) {
- printk(KERN_ERR "===> %s #1 fail\n", __func__);
+ pr_err("===> %s #1 fail\n", __func__);
return rst;
}
}
/* end of list */
rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
if (true != rst) {
- printk(KERN_ERR "===> %s #2 fail\n", __func__);
+ pr_err("===> %s #2 fail\n", __func__);
return rst;
}
/* Make the other pages as ring buffer
@@ -231,14 +234,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
rst = rtl92c_llt_write(hw, i, (i + 1));
if (true != rst) {
- printk(KERN_ERR "===> %s #3 fail\n", __func__);
+ pr_err("===> %s #3 fail\n", __func__);
return rst;
}
}
/* Let last entry point to the start entry of ring buffer */
rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
if (true != rst) {
- printk(KERN_ERR "===> %s #4 fail\n", __func__);
+ pr_err("===> %s #4 fail\n", __func__);
return rst;
}
return rst;
@@ -380,13 +383,11 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
0xFFFFFFFF);
- rtlpci->irq_enabled = true;
} else {
rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
0xFFFFFFFF);
- rtlusb->irq_enabled = true;
}
}
@@ -398,16 +399,9 @@ void rtl92c_init_interrupt(struct ieee80211_hw *hw)
void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- if (IS_HARDWARE_TYPE_8192CE(rtlhal))
- rtlpci->irq_enabled = false;
- else if (IS_HARDWARE_TYPE_8192CU(rtlhal))
- rtlusb->irq_enabled = false;
}
void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
@@ -788,7 +782,7 @@ static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
struct rtl_stats *pstats,
- struct rx_desc_92c *pdesc,
+ struct rx_desc_92c *p_desc,
struct rx_fwinfo_92c *p_drvinfo,
bool packet_match_bssid,
bool packet_toself,
@@ -803,11 +797,11 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
u32 rssi, total_rssi = 0;
bool in_powersavemode = false;
bool is_cck_rate;
+ u8 *pdesc = (u8 *)p_desc;
- is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+ is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc);
pstats->packet_matchbssid = packet_match_bssid;
pstats->packet_toself = packet_toself;
- pstats->is_cck = is_cck_rate;
pstats->packet_beacon = packet_beacon;
pstats->is_cck = is_cck_rate;
pstats->RX_SIGQ[0] = -1;
@@ -898,8 +892,8 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
if (GET_RX_DESC_RX_MCS(pdesc) &&
- GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 &&
- GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15)
+ GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 &&
+ GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
@@ -1113,7 +1107,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, cpu_fc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -1124,7 +1117,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
cpu_fc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid =
((IEEE80211_FTYPE_CTL != type) &&
(!compare_ether_addr(mac->bssid,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
index 298fdb7..626d88e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
@@ -87,12 +87,6 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);
u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\
- GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\
- GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\
- GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M)
-
struct rx_fwinfo_92c {
u8 gain_trsw[4];
u8 pwdb_all;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
index 9a3d023..e49cf22 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
@@ -470,7 +470,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
u8 i, queue_id;
struct rtl8192_tx_ring *ring = NULL;
- ppsc->set_rfpowerstate_inprogress = true;
switch (rfpwr_state) {
case ERFON:
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -549,7 +548,7 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
break;
case ERFSLEEP:
if (ppsc->rfpwr_state == ERFOFF)
- break;
+ return false;
for (queue_id = 0, i = 0;
queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
ring = &pcipriv->dev.tx_ring[queue_id];
@@ -590,7 +589,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
return bresult;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index 3bee79e..d984867 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -82,20 +82,18 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
(rtlefuse->external_pa))
turbo_scanoff = true;
}
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
- if (turbo_scanoff) {
- for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
- tx_agc[idx1] = ppowerlevel[idx1] |
- (ppowerlevel[idx1] << 8) |
- (ppowerlevel[idx1] << 16) |
- (ppowerlevel[idx1] << 24);
- if (rtlhal->interface == INTF_USB) {
- if (tx_agc[idx1] > 0x20 &&
- rtlefuse->external_pa)
- tx_agc[idx1] = 0x20;
- }
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ tx_agc[idx1] = ppowerlevel[idx1] |
+ (ppowerlevel[idx1] << 8) |
+ (ppowerlevel[idx1] << 16) |
+ (ppowerlevel[idx1] << 24);
+ if (rtlhal->interface == INTF_USB) {
+ if (tx_agc[idx1] > 0x20 &&
+ rtlefuse->external_pa)
+ tx_agc[idx1] = 0x20;
}
}
} else {
@@ -107,7 +105,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
TXHIGHPWRLEVEL_LEVEL2) {
tx_agc[RF90_PATH_A] = 0x00000000;
tx_agc[RF90_PATH_B] = 0x00000000;
- } else{
+ } else {
for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
tx_agc[idx1] = ppowerlevel[idx1] |
(ppowerlevel[idx1] << 8) |
@@ -380,7 +378,12 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
regoffset == RTXAGC_B_MCS07_MCS04)
regoffset = 0xc98;
for (i = 0; i < 3; i++) {
- writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+ if (i != 2)
+ writeVal = (writeVal > 8) ?
+ (writeVal - 8) : 0;
+ else
+ writeVal = (writeVal > 6) ?
+ (writeVal - 6) : 0;
rtl_write_byte(rtlpriv, (u32)(regoffset + i),
(u8)writeVal);
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 354f9b1..e813eff 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -42,6 +42,7 @@
#include "led.h"
#include "hw.h"
#include <linux/vmalloc.h>
+#include <linux/module.h>
MODULE_AUTHOR("Georgia <georgia@realtek.com>");
MODULE_AUTHOR("Ziv Huang <ziv_huang@realtek.com>");
@@ -60,6 +61,7 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->dm.dm_flag = 0;
rtlpriv->dm.disable_framebursting = 0;
rtlpriv->dm.thermalvalue = 0;
+ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
if (!rtlpriv->rtlhal.pfirmware) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
@@ -149,8 +151,14 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
static struct rtl_mod_params rtl92cu_mod_params = {
.sw_crypto = 0,
+ .debug = DBG_EMERG,
};
+module_param_named(swenc, rtl92cu_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92cu_mod_params.debug, int, 0444);
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = {
/* rx */
.in_ep_num = RTL92C_USB_BULK_IN_NUM,
@@ -241,20 +249,20 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
- .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
+ .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
+ .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
+ .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M,
+ .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M,
+ .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M,
+ .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M,
+ .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M,
+ .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M,
+ .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M,
+ .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M,
+ .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M,
+ .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M,
+ .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7,
+ .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
#define USB_VENDER_ID_REALTEK 0x0bda
@@ -267,6 +275,8 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)},
/****** 8188CU ********/
+ /* RTL8188CTV */
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x018a, rtl92cu_hal_cfg)},
/* 8188CE-VAU USB minCard */
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)},
/* 8188cu 1*1 dongle */
@@ -281,14 +291,17 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)},
/* 8188CE-VAU USB minCard (b/g mode only) */
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)},
+ /* 8188RU in Alfa AWUS036NHR */
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
+ /* RTL8188CUS-VL */
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)},
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)},
/* 8188 Combo for BC4 */
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
/****** 8192CU ********/
- /* 8191cu 1*2 */
- {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)},
/* 8192cu 2*2 */
- {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)},
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8178, rtl92cu_hal_cfg)},
/* 8192CE-VAU USB minCard */
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)},
@@ -300,37 +313,81 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
{RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
- {RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+ {RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/
+ {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
+ {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
+ {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+ {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+ {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */
+ {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/
{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
+ {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/
/* HP - Lite-On ,8188CUS Slim Combo */
{RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
+ {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */
{RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/
+ {RTL_USB_DEVICE(0x2019, 0x4902, rtl92cu_hal_cfg)}, /*Planex - Etop*/
{RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/
+ /*SW-WF02-AD15 -Abocom*/
+ {RTL_USB_DEVICE(0x2019, 0xab2e, rtl92cu_hal_cfg)},
{RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/
{RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/
{RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/
- {RTL_USB_DEVICE(0x3358, 0x13d3, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
+ {RTL_USB_DEVICE(0x13d3, 0x3358, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
/* Russian customer -Azwave (8188CE-VAU b/g mode only) */
- {RTL_USB_DEVICE(0x3359, 0x13d3, rtl92cu_hal_cfg)},
+ {RTL_USB_DEVICE(0x13d3, 0x3359, rtl92cu_hal_cfg)},
+ {RTL_USB_DEVICE(0x4855, 0x0090, rtl92cu_hal_cfg)}, /* Feixun */
+ {RTL_USB_DEVICE(0x4855, 0x0091, rtl92cu_hal_cfg)}, /* NetweeN-Feixun */
+ {RTL_USB_DEVICE(0x9846, 0x9041, rtl92cu_hal_cfg)}, /* Netgear Cameo */
+
+ /****** 8188 RU ********/
+ /* Netcore */
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x317f, rtl92cu_hal_cfg)},
+
+ /****** 8188CUS Slim Solo********/
+ {RTL_USB_DEVICE(0x04f2, 0xaff7, rtl92cu_hal_cfg)}, /*Xavi*/
+ {RTL_USB_DEVICE(0x04f2, 0xaff9, rtl92cu_hal_cfg)}, /*Xavi*/
+ {RTL_USB_DEVICE(0x04f2, 0xaffa, rtl92cu_hal_cfg)}, /*Xavi*/
+
+ /****** 8188CUS Slim Combo ********/
+ {RTL_USB_DEVICE(0x04f2, 0xaff8, rtl92cu_hal_cfg)}, /*Xavi*/
+ {RTL_USB_DEVICE(0x04f2, 0xaffb, rtl92cu_hal_cfg)}, /*Xavi*/
+ {RTL_USB_DEVICE(0x04f2, 0xaffc, rtl92cu_hal_cfg)}, /*Xavi*/
+ {RTL_USB_DEVICE(0x2019, 0x1201, rtl92cu_hal_cfg)}, /*Planex-Vencer*/
/****** 8192CU ********/
+ {RTL_USB_DEVICE(0x050d, 0x2102, rtl92cu_hal_cfg)}, /*Belcom-Sercomm*/
+ {RTL_USB_DEVICE(0x050d, 0x2103, rtl92cu_hal_cfg)}, /*Belcom-Edimax*/
{RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/
{RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
{RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
- {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Abocom -Abocom*/
+ {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/
+ {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
+ {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/
+ {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/
+ {RTL_USB_DEVICE(0x0e66, 0x0019, rtl92cu_hal_cfg)}, /*Hawking-Edimax*/
{RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
{RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
{RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+ {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */
{RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
+ {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
+ {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/
{RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/
{}
};
MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids);
+static int rtl8192cu_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg);
+}
+
static struct usb_driver rtl8192cu_driver = {
.name = "rtl8192cu",
- .probe = rtl_usb_probe,
+ .probe = rtl8192cu_probe,
.disconnect = rtl_usb_disconnect,
.id_table = rtl8192c_usb_ids,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 10b2ef0..a6ea2d9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -303,10 +303,10 @@ out:
bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
struct rtl_stats *stats,
struct ieee80211_rx_status *rx_status,
- u8 *p_desc, struct sk_buff *skb)
+ u8 *pdesc, struct sk_buff *skb)
{
struct rx_fwinfo_92c *p_drvinfo;
- struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+ struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc;
u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc);
stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
@@ -337,18 +337,19 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
- rx_status->rate_idx = _rtl92c_rate_mapping(hw,
- (bool)GET_RX_DESC_RX_HT(pdesc),
- (u8)GET_RX_DESC_RX_MCS(pdesc),
- (bool)GET_RX_DESC_PAGGR(pdesc));
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RX_HT(pdesc),
+ (u8)GET_RX_DESC_RX_MCS(pdesc),
+ (bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
- if (phystatus == true) {
- p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
- rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
+ if (phystatus) {
+ p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
+ stats->rx_bufshift);
+ rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc,
p_drvinfo);
}
/*rx_status->qual = stats->signal; */
- rx_status->signal = stats->rssi + 10;
+ rx_status->signal = stats->recvsignalpower + 10;
/*rx_status->noise = -stats->noise; */
return true;
}
@@ -406,11 +407,10 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
if (GET_RX_DESC_RX_HT(rxdesc))
rx_status->flag |= RX_FLAG_HT;
/* Data rate */
- rx_status->rate_idx = _rtl92c_rate_mapping(hw,
- (bool)GET_RX_DESC_RX_HT(rxdesc),
- (u8)GET_RX_DESC_RX_MCS(rxdesc),
- (bool)GET_RX_DESC_PAGGR(rxdesc)
- );
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RX_HT(rxdesc),
+ (u8)GET_RX_DESC_RX_MCS(rxdesc),
+ (bool)GET_RX_DESC_PAGGR(rxdesc));
/* There is a phy status after this rx descriptor. */
if (GET_RX_DESC_PHY_STATUS(rxdesc)) {
p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE);
@@ -545,7 +545,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_BW(txdesc, 0);
SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(txdesc,
- ((tcb_desc->rts_rate <= DESC92C_RATE54M) ?
+ ((tcb_desc->rts_rate <= DESC92_RATE54M) ?
(tcb_desc->rts_use_shortpreamble ? 1 : 0)
: (tcb_desc->rts_use_shortgi ? 1 : 0)));
if (mac->bw_40) {
@@ -644,7 +644,7 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
}
SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */
SET_TX_DESC_OWN(pDesc, 1);
- SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M);
+ SET_TX_DESC_TX_RATE(pDesc, DESC92_RATE1M);
_rtl_tx_desc_checksum(pDesc);
}
@@ -660,7 +660,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
if (firstseg)
SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE);
- SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
+ SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);
SET_TX_DESC_SEQ(pdesc, 0);
SET_TX_DESC_LINIP(pdesc, 0);
SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
index 69828f2..c6c0448 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
@@ -33,37 +33,6 @@
#define RX_CMD_QUEUE 1
#define RX_MAX_QUEUE 2
-#define DESC92S_RATE1M 0x00
-#define DESC92S_RATE2M 0x01
-#define DESC92S_RATE5_5M 0x02
-#define DESC92S_RATE11M 0x03
-#define DESC92S_RATE6M 0x04
-#define DESC92S_RATE9M 0x05
-#define DESC92S_RATE12M 0x06
-#define DESC92S_RATE18M 0x07
-#define DESC92S_RATE24M 0x08
-#define DESC92S_RATE36M 0x09
-#define DESC92S_RATE48M 0x0a
-#define DESC92S_RATE54M 0x0b
-#define DESC92S_RATEMCS0 0x0c
-#define DESC92S_RATEMCS1 0x0d
-#define DESC92S_RATEMCS2 0x0e
-#define DESC92S_RATEMCS3 0x0f
-#define DESC92S_RATEMCS4 0x10
-#define DESC92S_RATEMCS5 0x11
-#define DESC92S_RATEMCS6 0x12
-#define DESC92S_RATEMCS7 0x13
-#define DESC92S_RATEMCS8 0x14
-#define DESC92S_RATEMCS9 0x15
-#define DESC92S_RATEMCS10 0x16
-#define DESC92S_RATEMCS11 0x17
-#define DESC92S_RATEMCS12 0x18
-#define DESC92S_RATEMCS13 0x19
-#define DESC92S_RATEMCS14 0x1a
-#define DESC92S_RATEMCS15 0x1b
-#define DESC92S_RATEMCS15_SG 0x1c
-#define DESC92S_RATEMCS32 0x20
-
#define SHORT_SLOT_TIME 9
#define NON_SHORT_SLOT_TIME 20
@@ -490,11 +459,11 @@ do { \
#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \
- GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \
- GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\
- GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M)
+#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
+ (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \
+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \
+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)
enum rf_optype {
RF_OP_BY_SW_3WIRE = 0,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index da86db8..4203a85 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -222,7 +222,6 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
u32 low_rssi_thresh = 0;
u32 middle_rssi_thresh = 0;
u32 high_rssi_thresh = 0;
- u8 rssi_level;
struct ieee80211_sta *sta = NULL;
if (is_hal_stop(rtlhal))
@@ -272,18 +271,14 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)high_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_HIGH;
- rssi_level = 1;
} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)middle_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- rssi_level = 3;
} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)low_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- rssi_level = 5;
} else {
ra->ratr_state = DM_RATR_STA_ULTRALOW;
- rssi_level = 6;
}
if (ra->pre_ratr_state != ra->ratr_state) {
@@ -457,7 +452,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (digtable.backoff_enable_flag == true)
+ if (digtable.backoff_enable_flag)
rtl92s_backoff_enable_flag(hw);
else
digtable.backoff_val = DM_DIG_BACKOFF;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 0c77a14..3fda6b1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -360,7 +360,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
struct fw_priv *pfw_priv = NULL;
u8 *puc_mappedfile = NULL;
u32 ul_filelength = 0;
- u32 file_length = 0;
u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
u8 fwstatus = FW_STATUS_INIT;
bool rtstatus = true;
@@ -372,7 +371,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
firmware->fwstatus = FW_STATUS_INIT;
puc_mappedfile = firmware->sz_fw_tmpbuffer;
- file_length = firmware->sz_fw_tmpbufferlen;
/* 1. Retrieve FW header. */
firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 2e9005d..503c160 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "../efuse.h"
#include "../base.h"
@@ -465,8 +467,7 @@ static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data)
if ((tmpvalue & BIT(6)))
break;
- printk(KERN_ERR "wait for BIT(6) return value %x\n",
- tmpvalue);
+ pr_err("wait for BIT(6) return value %x\n", tmpvalue);
if (waitcount == 0)
break;
@@ -516,7 +517,7 @@ static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw)
mdelay(10);
/* check GPIO3 */
- u1tmp = rtl_read_byte(rtlpriv, GPIO_IN);
+ u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE);
retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF;
return retval;
@@ -884,12 +885,10 @@ static void _rtl92se_hw_configure(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 reg_bw_opmode = 0;
- u32 reg_ratr = 0, reg_rrsr = 0;
+ u32 reg_rrsr = 0;
u8 regtmp = 0;
reg_bw_opmode = BW_OPMODE_20MHZ;
- reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS |
- RATE_ALL_OFDM_2SS;
reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL);
@@ -925,7 +924,7 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 tmp_byte = 0;
-
+ unsigned long flags;
bool rtstatus = true;
u8 tmp_u1b;
int err = false;
@@ -937,6 +936,16 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
rtlpci->being_init_adapter = true;
+ /* As this function can take a very long time (up to 350 ms)
+ * and can be called with irqs disabled, reenable the irqs
+ * to let the other devices continue being serviced.
+ *
+ * It is safe doing so since our own interrupts will only be enabled
+ * in a subsequent step.
+ */
+ local_save_flags(flags);
+ local_irq_enable();
+
rtlpriv->intf_ops->disable_aspm(hw);
/* 1. MAC Initialize */
@@ -970,7 +979,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
/* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */
if (rtl92s_phy_mac_config(hw) != true) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("MAC Config failed\n"));
- return rtstatus;
+ err = rtstatus;
+ goto exit;
}
/* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */
@@ -980,7 +990,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
/* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */
if (rtl92s_phy_bb_config(hw) != true) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("BB Config failed\n"));
- return rtstatus;
+ err = rtstatus;
+ goto exit;
}
/* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */
@@ -996,7 +1007,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;
rtlpriv->psc.rfpwr_state = ERFON;
- rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true);
+ /* FIXME: check spinlocks if this block is uncommented */
+ rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason);
} else {
/* gpio radio on/off is out of adapter start */
if (rtlpriv->psc.hwradiooff == false) {
@@ -1015,7 +1027,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
if (rtl92s_phy_rf_config(hw) != true) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("RF Config failed\n"));
- return rtstatus;
+ err = rtstatus;
+ goto exit;
}
/* After read predefined TXT, we must set BB/MAC/RF
@@ -1089,8 +1102,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON);
rtl92s_dm_init(hw);
+exit:
+ local_irq_restore(flags);
rtlpci->being_init_adapter = false;
-
return err;
}
@@ -1107,7 +1121,7 @@ void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (check_bssid == true) {
+ if (check_bssid) {
reg_rcr |= (RCR_CBSSID);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
} else if (check_bssid == false) {
@@ -1122,14 +1136,12 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
- enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
u32 temp;
bt_msr &= ~MSR_LINK_MASK;
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
- ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
("Set Network type to NO LINK!\n"));
break;
@@ -1140,7 +1152,6 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
break;
case NL80211_IFTYPE_STATION:
bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
- ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
("Set Network type to STA!\n"));
break;
@@ -1218,8 +1229,6 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
-
- rtlpci->irq_enabled = true;
}
void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
@@ -1230,7 +1239,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, INTA_MASK, 0);
rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
- rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
@@ -1261,8 +1270,7 @@ static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
if ((tmp & BIT(6)))
break;
- printk(KERN_ERR "wait for BIT(6) return value %x\n",
- tmp);
+ pr_err("wait for BIT(6) return value %x\n", tmp);
if (waitcnt == 0)
break;
@@ -1321,7 +1329,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
if (u1btmp & BIT(7)) {
u1btmp &= ~(BIT(6) | BIT(7));
if (!_rtl92s_set_sysclk(hw, u1btmp)) {
- printk(KERN_ERR "Switch ctrl path fail\n");
+ pr_err("Switch ctrl path fail\n");
return;
}
}
@@ -1388,7 +1396,7 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34);
/* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */
- tmpu1b = rtl_read_byte(rtlpriv, SYS_FUNC_EN + 1);
+ tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
/* If IPS we need to turn LED on. So we not
* not disable BIT 3/7 of reg3. */
@@ -1397,7 +1405,7 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
else
tmpu1b &= 0x73;
- rtl_write_byte(rtlpriv, SYS_FUNC_EN + 1, tmpu1b);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b);
/* wait for BIT 10/11/15 to pull high automatically!! */
mdelay(1);
@@ -1434,15 +1442,15 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0)));
/* Set Digital Vdd to Retention isolation Path. */
- tmpu2b = rtl_read_word(rtlpriv, SYS_ISO_CTRL);
- rtl_write_word(rtlpriv, SYS_ISO_CTRL, (tmpu2b | BIT(11)));
+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL);
+ rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11)));
/* For warm reboot NIC disappera bug. */
- tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN);
- rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(13)));
+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13)));
- rtl_write_byte(rtlpriv, SYS_ISO_CTRL + 1, 0x68);
+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68);
/* Enable AFE PLL Macro Block */
tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL);
@@ -1453,17 +1461,17 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
mdelay(1);
/* Release isolation AFE PLL & MD */
- rtl_write_byte(rtlpriv, SYS_ISO_CTRL, 0xA6);
+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6);
/* Enable MAC clock */
tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR);
rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11)));
/* Enable Core digital and enable IOREG R/W */
- tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN);
- rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11)));
+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11)));
/* enable REG_EN */
- rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15)));
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15)));
/* Switch the control path. */
tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR);
@@ -1655,7 +1663,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
_rtl8192se_get_IC_Inferiority(hw);
@@ -1688,7 +1696,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+ ("%pM\n", rtlefuse->dev_addr));
/* Get Tx Power Level by Channel */
/* Read Tx power of Channel 1 ~ 14 from EEPROM. */
@@ -2271,7 +2279,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- enum rf_pwrstate rfpwr_toset, cur_rfstate;
+ enum rf_pwrstate rfpwr_toset /*, cur_rfstate */;
unsigned long flag = 0;
bool actuallyset = false;
bool turnonbypowerdomain = false;
@@ -2292,7 +2300,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
}
- cur_rfstate = ppsc->rfpwr_state;
+ /* cur_rfstate = ppsc->rfpwr_state;*/
/* because after _rtl92s_phy_set_rfhalt, all power
* closed, so we must open some power for GPIO check,
@@ -2305,7 +2313,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
rfpwr_toset = _rtl92se_rf_onoff_detect(hw);
- if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) {
+ if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
("RFKILL-HW Radio ON, RF ON\n"));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
index 6d4f666..e3fe7c9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
@@ -90,7 +90,7 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (pcipriv->ledctl.led_opendrain == true)
+ if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));
else
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 63b45e6..f10ac1a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "../pci.h"
#include "../ps.h"
@@ -180,19 +182,18 @@ u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
"bitmask(%#x)\n", regaddr, rfpath, bitmask));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
"bitmask(%#x), original_value(%#x)\n", regaddr, rfpath,
@@ -207,7 +208,6 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 original_value, bitshift;
- unsigned long flags;
if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))
return;
@@ -215,7 +215,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
" data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (bitmask != RFREG_OFFSET_MASK) {
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
@@ -226,7 +226,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
_rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data);
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), "
"data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
@@ -263,7 +263,6 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 reg_bw_opmode;
- u8 reg_prsr_rsc;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n",
rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
@@ -277,7 +276,8 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
rtlphy->set_bwmode_inprogress = true;
reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE);
- reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2);
+ /* dummy read */
+ rtl_read_byte(rtlpriv, RRSR + 2);
switch (rtlphy->current_chan_bw) {
case HT_CHANNEL_WIDTH_20:
@@ -546,8 +546,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
if (rfpwr_state == ppsc->rfpwr_state)
return false;
- ppsc->set_rfpowerstate_inprogress = true;
-
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -604,7 +602,7 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
}
case ERFSLEEP:
if (ppsc->rfpwr_state == ERFOFF)
- break;
+ return false;
for (queue_id = 0, i = 0;
queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
@@ -659,8 +657,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
-
return bresult;
}
@@ -1022,8 +1018,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB);
if (rtstatus != true) {
- printk(KERN_ERR "_rtl92s_phy_bb_config_parafile(): "
- "AGC Table Fail\n");
+ pr_err("%s(): AGC Table Fail\n", __func__);
goto phy_BB8190_Config_ParaFile_Fail;
}
@@ -1422,7 +1417,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
break;
case FW_CMD_HIGH_PWR_ENABLE:
if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
- (rtlpriv->dm.dynamic_txpower_enable == true))
+ rtlpriv->dm.dynamic_txpower_enable)
break;
/* CCA threshold */
@@ -1614,7 +1609,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
- (rtlpriv->dm.dynamic_txpower_enable == true))
+ rtlpriv->dm.dynamic_txpower_enable)
fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
if ((digtable.dig_ext_port_stage ==
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
index 0116ead..11f125c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
@@ -248,12 +248,8 @@
#define PSTIME 0x02E0
#define TIMER0 0x02E4
#define TIMER1 0x02E8
-#define GPIO_CTRL 0x02EC
-#define GPIO_IN 0x02EC
-#define GPIO_OUT 0x02ED
+#define GPIO_IN_SE 0x02EC
#define GPIO_IO_SEL 0x02EE
-#define GPIO_MOD 0x02EF
-#define GPIO_INTCTRL 0x02F0
#define MAC_PINMUX_CFG 0x02F1
#define LEDCFG 0x02F2
#define PHY_REG 0x02F3
@@ -739,6 +735,7 @@
#define HWSET_MAX_SIZE_92S 128
#define EFUSE_MAX_SECTION 16
#define EFUSE_REAL_CONTENT_LEN 512
+#define EFUSE_OOB_PROTECT_BYTES 15
#define RTL8190_EEPROM_ID 0x8129
#define EEPROM_HPON 0x02
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
index 1d3a483..13081d9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "reg.h"
#include "def.h"
@@ -272,7 +274,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
rtlefuse->pwrgroup_ht40
[RF90_PATH_A][chnl - 1]) {
pwrdiff_limit[i] =
- rtlefuse->pwrgroup_ht20
+ rtlefuse->pwrgroup_ht40
[RF90_PATH_A][chnl - 1];
}
} else {
@@ -410,7 +412,7 @@ void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
(rtlefuse->eeprom_regulatory != 0)))
dont_inc_cck_or_turboscanoff = true;
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
txagc = 0x3f;
if (dont_inc_cck_or_turboscanoff)
txagc = pwrlevel;
@@ -507,7 +509,7 @@ bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw)
}
if (rtstatus != true) {
- printk(KERN_ERR "Radio[%d] Fail!!", rfpath);
+ pr_err("Radio[%d] Fail!!\n", rfpath);
goto fail;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 1c6cb1d..92f49d5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -27,7 +27,10 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/vmalloc.h>
+#include <linux/module.h>
#include "../wifi.h"
#include "../core.h"
@@ -158,10 +161,16 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
rtlpci->first_init = true;
+ /* for debug level */
+ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
/* for LPS & IPS */
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("rtl8192ce: Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+ pr_info("rtl8192ce: FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
@@ -183,8 +192,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
return 1;
}
- printk(KERN_INFO "rtl8192se: Driver for Realtek RTL8192SE/RTL8191SE\n"
- " Loading firmware %s\n", rtlpriv->cfg->fw_name);
+ pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
+ "Loading firmware %s\n", rtlpriv->cfg->fw_name);
/* request fw */
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
rtlpriv->io.dev);
@@ -266,6 +275,7 @@ static struct rtl_mod_params rtl92se_mod_params = {
.inactiveps = true,
.swctrl_lps = true,
.fwctrl_lps = false,
+ .debug = DBG_EMERG,
};
/* Because memory R/W bursting will cause system hang/crash
@@ -298,6 +308,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S,
.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+ .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
.maps[RWCAM] = REG_RWCAM,
.maps[WCAMI] = REG_WCAMI,
@@ -346,21 +357,21 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M,
-
- .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15,
+ .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
+ .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
+ .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M,
+ .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M,
+ .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M,
+ .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M,
+ .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M,
+ .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M,
+ .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M,
+ .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M,
+ .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M,
+ .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M,
+
+ .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7,
+ .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
static struct pci_device_id rtl92se_pci_ids[] __devinitdata = {
@@ -376,31 +387,37 @@ MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids);
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin");
module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92se_mod_params.debug, int, 0444);
module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is "
- "open)\n");
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+static const struct dev_pm_ops rtlwifi_pm_ops = {
+ .suspend = rtl_pci_suspend,
+ .resume = rtl_pci_resume,
+ .freeze = rtl_pci_suspend,
+ .thaw = rtl_pci_resume,
+ .poweroff = rtl_pci_suspend,
+ .restore = rtl_pci_resume,
+};
static struct pci_driver rtl92se_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl92se_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
-
-#ifdef CONFIG_PM
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
-#endif
-
+ .driver.pm = &rtlwifi_pm_ops,
};
static int __init rtl92se_module_init(void)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 5cf4423..542a871 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -51,104 +51,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue)
return skb->priority;
}
-static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
-{
- int rate_idx = 0;
-
- if (first_ampdu) {
- if (false == isht) {
- switch (desc_rate) {
- case DESC92S_RATE1M:
- rate_idx = 0;
- break;
- case DESC92S_RATE2M:
- rate_idx = 1;
- break;
- case DESC92S_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92S_RATE11M:
- rate_idx = 3;
- break;
- case DESC92S_RATE6M:
- rate_idx = 4;
- break;
- case DESC92S_RATE9M:
- rate_idx = 5;
- break;
- case DESC92S_RATE12M:
- rate_idx = 6;
- break;
- case DESC92S_RATE18M:
- rate_idx = 7;
- break;
- case DESC92S_RATE24M:
- rate_idx = 8;
- break;
- case DESC92S_RATE36M:
- rate_idx = 9;
- break;
- case DESC92S_RATE48M:
- rate_idx = 10;
- break;
- case DESC92S_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 0;
- break;
- }
- } else {
- rate_idx = 11;
- }
-
- return rate_idx;
- }
-
- switch (desc_rate) {
- case DESC92S_RATE1M:
- rate_idx = 0;
- break;
- case DESC92S_RATE2M:
- rate_idx = 1;
- break;
- case DESC92S_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92S_RATE11M:
- rate_idx = 3;
- break;
- case DESC92S_RATE6M:
- rate_idx = 4;
- break;
- case DESC92S_RATE9M:
- rate_idx = 5;
- break;
- case DESC92S_RATE12M:
- rate_idx = 6;
- break;
- case DESC92S_RATE18M:
- rate_idx = 7;
- break;
- case DESC92S_RATE24M:
- rate_idx = 8;
- break;
- case DESC92S_RATE36M:
- rate_idx = 9;
- break;
- case DESC92S_RATE48M:
- rate_idx = 10;
- break;
- case DESC92S_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
-}
-
static u8 _rtl92s_query_rxpwrpercentage(char antpower)
{
if ((antpower <= -100) || (antpower >= 20))
@@ -222,18 +124,15 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
bool in_powersavemode = false;
- bool is_cck_rate;
+ bool is_cck = pstats->is_cck;
- is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
pstats->packet_matchbssid = packet_match_bssid;
pstats->packet_toself = packet_toself;
- pstats->is_cck = is_cck_rate;
pstats->packet_beacon = packet_beacon;
- pstats->is_cck = is_cck_rate;
pstats->rx_mimo_signalquality[0] = -1;
pstats->rx_mimo_signalquality[1] = -1;
- if (is_cck_rate) {
+ if (is_cck) {
u8 report, cck_highpwr;
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
@@ -344,9 +243,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
- if (GET_RX_STATUS_DESC_RX_HT(pdesc) &&
- GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 &&
- GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15)
+ if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 &&
+ pstats->rate <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
@@ -364,7 +262,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
}
}
- if (is_cck_rate)
+ if (is_cck)
pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw,
pwdb_all));
else if (rf_rx_num != 0)
@@ -581,7 +479,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, cfc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -593,7 +490,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
cfc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
(!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
@@ -618,6 +514,8 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
{
struct rx_fwinfo *p_drvinfo;
u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc);
+ struct ieee80211_hdr *hdr;
+ bool first_ampdu = false;
stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc);
stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8;
@@ -630,8 +528,12 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc);
stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc);
stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1);
+ stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1)
+ && (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
+ stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc);
+ stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc);
if (stats->hwerror)
return false;
@@ -639,31 +541,40 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
rx_status->freq = hw->conf.channel->center_freq;
rx_status->band = hw->conf.channel->band;
- if (GET_RX_STATUS_DESC_CRC32(pdesc))
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
+ + stats->rx_bufshift);
- if (!GET_RX_STATUS_DESC_SWDEC(pdesc))
- rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (stats->crc)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (GET_RX_STATUS_DESC_BW(pdesc))
+ if (stats->rx_is40Mhzpacket)
rx_status->flag |= RX_FLAG_40MHZ;
- if (GET_RX_STATUS_DESC_RX_HT(pdesc))
+ if (stats->is_ht)
rx_status->flag |= RX_FLAG_HT;
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
- if (stats->decrypted)
- rx_status->flag |= RX_FLAG_DECRYPTED;
-
- rx_status->rate_idx = _rtl92se_rate_mapping((bool)
- GET_RX_STATUS_DESC_RX_HT(pdesc),
- (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc),
- (bool)GET_RX_STATUS_DESC_PAGGR(pdesc));
+ /* hw will set stats->decrypted true, if it finds the
+ * frame is open data frame or mgmt frame,
+ * hw will not decrypt robust managment frame
+ * for IEEE80211w but still set stats->decrypted
+ * true, so here we should set it back to undecrypted
+ * for IEEE80211w frame, and mac80211 sw will help
+ * to decrypt it */
+ if (stats->decrypted) {
+ if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+ (ieee80211_has_protected(hdr->frame_control)))
+ rx_status->flag &= ~RX_FLAG_DECRYPTED;
+ else
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ }
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ stats->is_ht, stats->rate, first_ampdu);
- rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ rx_status->mactime = stats->timestamp_low;
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo *)(skb->data +
stats->rx_bufshift);
_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
@@ -671,7 +582,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
}
/*rx_status->qual = stats->signal; */
- rx_status->signal = stats->rssi + 10;
+ rx_status->signal = stats->recvsignalpower + 10;
/*rx_status->noise = -stats->noise; */
return true;
@@ -725,14 +636,14 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid);
SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >=
- DESC92S_RATEMCS0) ? 1 : 0));
+ DESC92_RATEMCS0) ? 1 : 0));
if (rtlhal->version == VERSION_8192S_ACUT) {
- if (ptcb_desc->hw_rate == DESC92S_RATE1M ||
- ptcb_desc->hw_rate == DESC92S_RATE2M ||
- ptcb_desc->hw_rate == DESC92S_RATE5_5M ||
- ptcb_desc->hw_rate == DESC92S_RATE11M) {
- ptcb_desc->hw_rate = DESC92S_RATE12M;
+ if (ptcb_desc->hw_rate == DESC92_RATE1M ||
+ ptcb_desc->hw_rate == DESC92_RATE2M ||
+ ptcb_desc->hw_rate == DESC92_RATE5_5M ||
+ ptcb_desc->hw_rate == DESC92_RATE11M) {
+ ptcb_desc->hw_rate = DESC92_RATE12M;
}
}
@@ -761,7 +672,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0);
SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
- DESC92S_RATE54M) ?
+ DESC92_RATE54M) ?
(ptcb_desc->rts_use_shortpreamble ? 1 : 0)
: (ptcb_desc->rts_use_shortgi ? 1 : 0)));
@@ -875,6 +786,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
} else { /* H2C Command Desc format (Host TXCMD) */
/* 92SE must set as 1 for firmware download HW DMA error */
@@ -893,6 +805,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
}
@@ -900,9 +813,10 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
@@ -916,6 +830,7 @@ void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
+ wmb();
SET_RX_STATUS_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
@@ -939,7 +854,7 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
{
u32 ret = 0;
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(desc);
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index dbcf5a9..17e6429 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -24,7 +24,11 @@
* Hsinchu 300, Taiwan.
*
*****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/usb.h>
+#include <linux/export.h>
#include "core.h"
#include "wifi.h"
#include "usb.h"
@@ -40,8 +44,12 @@
static void usbctrl_async_callback(struct urb *urb)
{
- if (urb)
- kfree(urb->context);
+ if (urb) {
+ /* free dr */
+ kfree(urb->setup_packet);
+ /* free databuf */
+ kfree(urb->transfer_buffer);
+ }
}
static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
@@ -53,38 +61,46 @@ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
u8 reqtype;
struct usb_ctrlrequest *dr;
struct urb *urb;
- struct rtl819x_async_write_data {
- u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE];
- struct usb_ctrlrequest dr;
- } *buf;
+ const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE;
+ u8 *databuf;
+
+ if (WARN_ON_ONCE(len > databuf_maxlen))
+ len = databuf_maxlen;
pipe = usb_sndctrlpipe(udev, 0); /* write_out */
reqtype = REALTEK_USB_VENQT_WRITE;
- buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
- if (!buf)
+ dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+ if (!dr)
+ return -ENOMEM;
+
+ databuf = kmalloc(databuf_maxlen, GFP_ATOMIC);
+ if (!databuf) {
+ kfree(dr);
return -ENOMEM;
+ }
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- kfree(buf);
+ kfree(databuf);
+ kfree(dr);
return -ENOMEM;
}
- dr = &buf->dr;
-
dr->bRequestType = reqtype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(len);
- memcpy(buf, pdata, len);
+ memcpy(databuf, pdata, len);
usb_fill_control_urb(urb, udev, pipe,
- (unsigned char *)dr, buf, len,
- usbctrl_async_callback, buf);
+ (unsigned char *)dr, databuf, len,
+ usbctrl_async_callback, NULL);
rc = usb_submit_urb(urb, GFP_ATOMIC);
- if (rc < 0)
- kfree(buf);
+ if (rc < 0) {
+ kfree(databuf);
+ kfree(dr);
+ }
usb_free_urb(urb);
return rc;
}
@@ -101,55 +117,50 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
reqtype = REALTEK_USB_VENQT_READ;
status = usb_control_msg(udev, pipe, request, reqtype, value, index,
- pdata, len, 0); /* max. timeout */
+ pdata, len, 1000);
if (status < 0)
- printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! "
- "status:0x%x value=0x%x\n", value, status,
- *(u32 *)pdata);
+ pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n",
+ value, status, *(u32 *)pdata);
return status;
}
-static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
{
+ struct device *dev = rtlpriv->io.dev;
+ struct usb_device *udev = to_usb_device(dev);
u8 request;
u16 wvalue;
u16 index;
- u32 *data;
- u32 ret;
-
- data = kmalloc(sizeof(u32), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ __le32 *data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags);
+ if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
+ rtlpriv->usb_data_index = 0;
+ data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
+ spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags);
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)addr;
_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
- ret = *data;
- kfree(data);
- return ret;
+ return le32_to_cpu(*data);
}
static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+ return (u8)_usb_read_sync(rtlpriv, addr, 1);
}
static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+ return (u16)_usb_read_sync(rtlpriv, addr, 2);
}
static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_read_sync(to_usb_device(dev), addr, 4);
+ return _usb_read_sync(rtlpriv, addr, 4);
}
static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
@@ -189,44 +200,6 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
_usb_write_async(to_usb_device(dev), addr, val, 4);
}
-static int _usb_nbytes_read_write(struct usb_device *udev, bool read, u32 addr,
- u16 len, u8 *pdata)
-{
- int status;
- u8 request;
- u16 wvalue;
- u16 index;
-
- request = REALTEK_USB_VENQT_CMD_REQ;
- index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
- wvalue = (u16)addr;
- if (read)
- status = _usbctrl_vendorreq_sync_read(udev, request, wvalue,
- index, pdata, len);
- else
- status = _usbctrl_vendorreq_async_write(udev, request, wvalue,
- index, pdata, len);
- return status;
-}
-
-static int _usb_readN_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata)
-{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_nbytes_read_write(to_usb_device(dev), true, addr, len,
- pdata);
-}
-
-static int _usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata)
-{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_nbytes_read_write(to_usb_device(dev), false, addr, len,
- pdata);
-}
-
static void _rtl_usb_io_handler_init(struct device *dev,
struct ieee80211_hw *hw)
{
@@ -237,11 +210,9 @@ static void _rtl_usb_io_handler_init(struct device *dev,
rtlpriv->io.write8_async = _usb_write8_async;
rtlpriv->io.write16_async = _usb_write16_async;
rtlpriv->io.write32_async = _usb_write32_async;
- rtlpriv->io.writeN_async = _usb_writeN_async;
rtlpriv->io.read8_sync = _usb_read8_sync;
rtlpriv->io.read16_sync = _usb_read16_sync;
rtlpriv->io.read32_sync = _usb_read32_sync;
- rtlpriv->io.readN_sync = _usb_readN_sync;
}
static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
@@ -316,7 +287,7 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
rtlusb->usb_rx_segregate_hdl =
rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl;
- printk(KERN_INFO "rtl8192cu: rx_max_size %d, rx_urb_num %d, in_ep %d\n",
+ pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n",
rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep);
init_usb_anchor(&rtlusb->rx_submitted);
return 0;
@@ -518,12 +489,14 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
u8 *pdata;
uskb = dev_alloc_skb(skb->len + 128);
- memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
- sizeof(rx_status));
- pdata = (u8 *)skb_put(uskb, skb->len);
- memcpy(pdata, skb->data, skb->len);
+ if (uskb) { /* drop packet on allocation failure */
+ memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
+ sizeof(rx_status));
+ pdata = (u8 *)skb_put(uskb, skb->len);
+ memcpy(pdata, skb->data, skb->len);
+ ieee80211_rx_irqsafe(hw, uskb);
+ }
dev_kfree_skb_any(skb);
- ieee80211_rx_irqsafe(hw, uskb);
} else {
dev_kfree_skb_any(skb);
}
@@ -580,7 +553,7 @@ static void _rtl_rx_completed(struct urb *_urb)
} else{
/* TO DO */
_rtl_rx_pre_process(hw, skb);
- printk(KERN_ERR "rtlwifi: rx agg not supported\n");
+ pr_err("rx agg not supported\n");
}
goto resubmit;
}
@@ -839,6 +812,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
if (unlikely(!_urb)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("Can't allocate urb. Drop skb!\n"));
+ kfree_skb(skb);
return;
}
urb_list = &rtlusb->tx_pending[ep_num];
@@ -933,7 +907,8 @@ static struct rtl_intf_ops rtl_usb_ops = {
};
int __devinit rtl_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+ const struct usb_device_id *id,
+ struct rtl_hal_cfg *rtl_hal_cfg)
{
int err;
struct ieee80211_hw *hw = NULL;
@@ -948,6 +923,15 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
return -ENOMEM;
}
rtlpriv = hw->priv;
+ rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
+ GFP_KERNEL);
+ if (!rtlpriv->usb_data)
+ return -ENOMEM;
+
+ /* this spin lock must be initialized early */
+ spin_lock_init(&rtlpriv->locks.usb_lock);
+
+ rtlpriv->usb_data_index = 0;
SET_IEEE80211_DEV(hw, &intf->dev);
udev = interface_to_usbdev(intf);
usb_get_dev(udev);
@@ -958,7 +942,7 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, hw);
/* init cfg & intf_ops */
rtlpriv->rtlhal.interface = INTF_USB;
- rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info);
+ rtlpriv->cfg = rtl_hal_cfg;
rtlpriv->intf_ops = &rtl_usb_ops;
rtl_dbgp_flag_init(hw);
/* Init IO handler */
@@ -1025,6 +1009,7 @@ void rtl_usb_disconnect(struct usb_interface *intf)
/* rtl_deinit_rfkill(hw); */
rtl_usb_deinit(hw);
rtl_deinit_core(hw);
+ kfree(rtlpriv->usb_data);
rtlpriv->cfg->ops->deinit_sw_leds(hw);
rtlpriv->cfg->ops->deinit_sw_vars(hw);
_rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h
index d2a63fb..4dc4b1c 100644
--- a/drivers/net/wireless/rtlwifi/usb.h
+++ b/drivers/net/wireless/rtlwifi/usb.h
@@ -158,7 +158,8 @@ struct rtl_usb_priv {
int __devinit rtl_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id);
+ const struct usb_device_id *id,
+ struct rtl_hal_cfg *rtl92cu_hal_cfg);
void rtl_usb_disconnect(struct usb_interface *intf);
int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
int rtl_usb_resume(struct usb_interface *pusb_intf);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 2e3daea..5764ef7 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -32,7 +32,6 @@
#include <linux/sched.h>
#include <linux/firmware.h>
-#include <linux/version.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/usb.h>
@@ -64,7 +63,7 @@
#define AC_MAX 4
#define QOS_QUEUE_NUM 4
#define RTL_MAC80211_NUM_QUEUE 5
-
+#define RTL_USB_MAX_RX_COUNT 100
#define QBSS_LOAD_SIZE 5
#define MAX_WMMELE_LENGTH 64
@@ -74,11 +73,7 @@
#define RTL_SLOT_TIME_9 9
#define RTL_SLOT_TIME_20 20
-/*related with tcp/ip. */
-/*if_ehther.h*/
-#define ETH_P_PAE 0x888E /*Port Access Entity (IEEE 802.1X) */
-#define ETH_P_IP 0x0800 /*Internet Protocol packet */
-#define ETH_P_ARP 0x0806 /*Address Resolution packet */
+/*related to tcp/ip. */
#define SNAP_SIZE 6
#define PROTOC_TYPE_SIZE 2
@@ -166,6 +161,12 @@ enum hardware_type {
#define IS_HARDWARE_TYPE_8723U(rtlhal) \
(rtlhal->hw_type == HARDWARE_TYPE_RTL8723U)
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+ (_pdesc->rxmcs == DESC92_RATE1M || \
+ _pdesc->rxmcs == DESC92_RATE2M || \
+ _pdesc->rxmcs == DESC92_RATE5_5M || \
+ _pdesc->rxmcs == DESC92_RATE11M)
+
enum scan_operation_backup_opt {
SCAN_OPT_BACKUP = 0,
SCAN_OPT_RESTORE,
@@ -303,9 +304,6 @@ enum hw_variables {
HW_VAR_DATA_FILTER,
};
-#define HWSET_MAX_SIZE 128
-#define EFUSE_MAX_SECTION 16
-
enum _RT_MEDIA_STATUS {
RT_MEDIA_DISCONNECT = 0,
RT_MEDIA_CONNECT = 1
@@ -390,6 +388,41 @@ enum rtl_hal_state {
_HAL_STATE_START = 1,
};
+enum rtl_desc92_rate {
+ DESC92_RATE1M = 0x00,
+ DESC92_RATE2M = 0x01,
+ DESC92_RATE5_5M = 0x02,
+ DESC92_RATE11M = 0x03,
+
+ DESC92_RATE6M = 0x04,
+ DESC92_RATE9M = 0x05,
+ DESC92_RATE12M = 0x06,
+ DESC92_RATE18M = 0x07,
+ DESC92_RATE24M = 0x08,
+ DESC92_RATE36M = 0x09,
+ DESC92_RATE48M = 0x0a,
+ DESC92_RATE54M = 0x0b,
+
+ DESC92_RATEMCS0 = 0x0c,
+ DESC92_RATEMCS1 = 0x0d,
+ DESC92_RATEMCS2 = 0x0e,
+ DESC92_RATEMCS3 = 0x0f,
+ DESC92_RATEMCS4 = 0x10,
+ DESC92_RATEMCS5 = 0x11,
+ DESC92_RATEMCS6 = 0x12,
+ DESC92_RATEMCS7 = 0x13,
+ DESC92_RATEMCS8 = 0x14,
+ DESC92_RATEMCS9 = 0x15,
+ DESC92_RATEMCS10 = 0x16,
+ DESC92_RATEMCS11 = 0x17,
+ DESC92_RATEMCS12 = 0x18,
+ DESC92_RATEMCS13 = 0x19,
+ DESC92_RATEMCS14 = 0x1a,
+ DESC92_RATEMCS15 = 0x1b,
+ DESC92_RATEMCS15_SG = 0x1c,
+ DESC92_RATEMCS32 = 0x20,
+};
+
enum rtl_var_map {
/*reg map */
SYS_ISO_CTRL = 0,
@@ -413,6 +446,7 @@ enum rtl_var_map {
EFUSE_HWSET_MAX_SIZE,
EFUSE_MAX_SECTION_MAP,
EFUSE_REAL_CONTENT_SIZE,
+ EFUSE_OOB_PROTECT_BYTES_LEN,
/*CAM map */
RWCAM,
@@ -905,16 +939,12 @@ struct rtl_io {
unsigned long pci_base_addr; /*device I/O address */
void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
- void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
- void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
- int (*writeN_async) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata);
+ void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, __le16 val);
+ void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, __le32 val);
u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
- int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata);
};
@@ -938,7 +968,7 @@ struct rtl_mac {
int n_channels;
int n_bitrates;
- bool offchan_deley;
+ bool offchan_delay;
/*filters */
u32 rx_conf;
@@ -1188,7 +1218,6 @@ struct rtl_efuse {
struct rtl_ps_ctl {
bool pwrdomain_protect;
- bool set_rfpowerstate_inprogress;
bool in_powersavemode;
bool rfchange_inprogress;
bool swrf_processing;
@@ -1292,6 +1321,7 @@ struct rtl_stats {
s8 rx_mimo_signalquality[2];
bool packet_matchbssid;
bool is_cck;
+ bool is_ht;
bool packet_toself;
bool packet_beacon; /*for rssi */
char cck_adc_pwdb[4]; /*for rx path selection */
@@ -1453,6 +1483,9 @@ struct rtl_mod_params {
/* default: 0 = using hardware encryption */
int sw_crypto;
+ /* default: 0 = DBG_EMERG (0)*/
+ int debug;
+
/* default: 1 = using no linked power save */
bool inactiveps;
@@ -1513,6 +1546,7 @@ struct rtl_locks {
spinlock_t rf_lock;
spinlock_t lps_lock;
spinlock_t waitq_lock;
+ spinlock_t usb_lock;
/*Dual mac*/
spinlock_t cck_and_rw_pagea_lock;
@@ -1536,6 +1570,7 @@ struct rtl_works {
/* For SW LPS */
struct delayed_work ps_work;
struct delayed_work ps_rfon_wq;
+ struct tasklet_struct ips_leave_tasklet;
};
struct rtl_debug {
@@ -1583,6 +1618,10 @@ struct rtl_priv {
interface or hardware */
unsigned long status;
+ /* data buffer pointer for USB reads */
+ __le32 *usb_data;
+ int usb_data_index;
+
/*This must be the last item so
that it points to the data allocated
beyond this structure like:
@@ -1983,7 +2022,7 @@ static inline u16 rtl_get_tid(struct sk_buff *skb)
static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- u8 *bssid)
+ const u8 *bssid)
{
return ieee80211_find_sta(vif, bssid);
}
diff --git a/drivers/net/wireless/wl1251/acx.c b/drivers/net/wireless/wl1251/acx.c
index ef8370e..ad87a1a 100644
--- a/drivers/net/wireless/wl1251/acx.c
+++ b/drivers/net/wireless/wl1251/acx.c
@@ -140,8 +140,6 @@ int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
auth->sleep_auth = sleep_auth;
ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
- if (ret < 0)
- return ret;
out:
kfree(auth);
@@ -681,10 +679,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl)
ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
detection, sizeof(*detection));
- if (ret < 0) {
+ if (ret < 0)
wl1251_warning("failed to set cca threshold: %d", ret);
- return ret;
- }
out:
kfree(detection);
diff --git a/drivers/net/wireless/wl1251/cmd.c b/drivers/net/wireless/wl1251/cmd.c
index 81f164b..d14d69d 100644
--- a/drivers/net/wireless/wl1251/cmd.c
+++ b/drivers/net/wireless/wl1251/cmd.c
@@ -241,7 +241,7 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
if (ret < 0) {
wl1251_error("tx %s cmd for channel %d failed",
enable ? "start" : "stop", channel);
- return ret;
+ goto out;
}
wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h
index 79ca527..ee4f2b3 100644
--- a/drivers/net/wireless/wl1251/cmd.h
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -269,7 +269,7 @@ struct cmd_join {
u8 bss_type;
u8 channel;
u8 ssid_len;
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ctrl; /* JOIN_CMD_CTRL_* */
u8 tx_mgt_frame_rate; /* OBSOLETE */
u8 tx_mgt_frame_mod; /* OBSOLETE */
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index de9210c..40c1574 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -1159,7 +1159,8 @@ static struct ieee80211_channel wl1251_channels[] = {
{ .hw_value = 13, .center_freq = 2472},
};
-static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int wl1251_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
enum wl1251_acx_ps_scheme ps_scheme;
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index 4cf5c2e..e2750a1 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -19,6 +19,7 @@
* Copyright (C) 2008 Google Inc
* Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mmc/sdio_func.h>
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
index 49f3651..134ae9c 100644
--- a/drivers/net/wireless/wl1251/spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h
index 1417b14..04ed514 100644
--- a/drivers/net/wireless/wl1251/wl12xx_80211.h
+++ b/drivers/net/wireless/wl1251/wl12xx_80211.h
@@ -76,7 +76,7 @@ struct wl12xx_ie_header {
struct wl12xx_ie_ssid {
struct wl12xx_ie_header header;
- char ssid[IW_ESSID_MAX_SIZE];
+ char ssid[IEEE80211_MAX_SSID_LEN];
} __packed;
struct wl12xx_ie_rates {
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 35ce7b0..3fe388b 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -11,7 +11,6 @@ config WL12XX
depends on WL12XX_MENU && GENERIC_HARDIRQS
depends on INET
select FW_LOADER
- select CRC7
---help---
This module adds support for wireless adapters based on TI wl1271 and
TI wl1273 chipsets. This module does *not* include support for wl1251.
@@ -20,19 +19,10 @@ config WL12XX
If you choose to build a module, it will be called wl12xx. Say N if
unsure.
-config WL12XX_HT
- bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)"
- depends on WL12XX && EXPERIMENTAL
- default n
- ---help---
- This will enable 802.11 HT support in the wl12xx module.
-
- That configuration is temporary due to the code incomplete and
- still in testing process.
-
config WL12XX_SPI
tristate "TI wl12xx SPI support"
depends on WL12XX && SPI_MASTER
+ select CRC7
---help---
This module adds support for the SPI interface of adapters using
TI wl12xx chipsets. Select this if your platform is using
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index 521c041..621b348 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,16 +1,16 @@
wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
boot.o init.o debugfs.o scan.o
-wl12xx_spi-objs = spi.o
+wl12xx_spi-objs = spi.o
wl12xx_sdio-objs = sdio.o
-wl12xx_sdio_test-objs = sdio_test.o
+wl12xx_sdio_test-objs = sdio_test.o
wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_WL12XX) += wl12xx.o
obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o
obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
-obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o
+obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o
# small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index c6ee530..ca044a7 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -47,6 +46,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
goto out;
}
+ wake_up->role_id = wl->role_id;
wake_up->wake_up_event = wl->conf.conn.wake_up_event;
wake_up->listen_interval = wl->conf.conn.listen_interval;
@@ -78,8 +78,6 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
auth->sleep_auth = sleep_auth;
ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
- if (ret < 0)
- return ret;
out:
kfree(auth);
@@ -91,7 +89,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
struct acx_current_tx_power *acx;
int ret;
- wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+ wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr %d", power);
if (power < 0 || power > 25)
return -EINVAL;
@@ -102,6 +100,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
goto out;
}
+ acx->role_id = wl->role_id;
acx->current_tx_power = power * 10;
ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
@@ -129,6 +128,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl)
}
/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+ feature->role_id = wl->role_id;
feature->data_flow_options = 0;
feature->options = 0;
@@ -184,34 +184,6 @@ out:
return ret;
}
-int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
-{
- struct acx_rx_config *rx_config;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx rx config");
-
- rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
- if (!rx_config) {
- ret = -ENOMEM;
- goto out;
- }
-
- rx_config->config_options = cpu_to_le32(config);
- rx_config->filter_options = cpu_to_le32(filter);
-
- ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
- rx_config, sizeof(*rx_config));
- if (ret < 0) {
- wl1271_warning("failed to set rx config: %d", ret);
- goto out;
- }
-
-out:
- kfree(rx_config);
- return ret;
-}
-
int wl1271_acx_pd_threshold(struct wl1271 *wl)
{
struct acx_packet_detection *pd;
@@ -251,6 +223,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
goto out;
}
+ slot->role_id = wl->role_id;
slot->wone_index = STATION_WONE_INDEX;
slot->slot_time = slot_time;
@@ -280,6 +253,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
}
/* MAC filtering */
+ acx->role_id = wl->role_id;
acx->enabled = enable;
acx->num_groups = mc_list_len;
memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
@@ -309,6 +283,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
wl1271_debug(DEBUG_ACX, "acx service period timeout");
+ rx_timeout->role_id = wl->role_id;
rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
@@ -345,6 +320,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
goto out;
}
+ rts->role_id = wl->role_id;
rts->threshold = cpu_to_le16((u16)rts_threshold);
ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
@@ -404,6 +380,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
goto out;
}
+ beacon_filter->role_id = wl->role_id;
beacon_filter->enable = enable_filter;
/*
@@ -440,6 +417,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
}
/* configure default beacon pass-through rules */
+ ie_table->role_id = wl->role_id;
ie_table->num_ie = 0;
for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
@@ -501,6 +479,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
timeout = wl->conf.conn.bss_lose_timeout;
}
+ acx->role_id = wl->role_id;
acx->synch_fail_thold = cpu_to_le32(threshold);
acx->bss_lose_timeout = cpu_to_le32(timeout);
@@ -547,43 +526,13 @@ out:
return ret;
}
-int wl1271_acx_sta_sg_cfg(struct wl1271 *wl)
-{
- struct acx_sta_bt_wlan_coex_param *param;
- struct conf_sg_settings *c = &wl->conf.sg;
- int i, ret;
-
- wl1271_debug(DEBUG_ACX, "acx sg sta cfg");
-
- param = kzalloc(sizeof(*param), GFP_KERNEL);
- if (!param) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* BT-WLAN coext parameters */
- for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++)
- param->params[i] = cpu_to_le32(c->sta_params[i]);
- param->param_idx = CONF_SG_PARAMS_ALL;
-
- ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
- if (ret < 0) {
- wl1271_warning("failed to set sg config: %d", ret);
- goto out;
- }
-
-out:
- kfree(param);
- return ret;
-}
-
-int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
+int wl12xx_acx_sg_cfg(struct wl1271 *wl)
{
- struct acx_ap_bt_wlan_coex_param *param;
+ struct acx_bt_wlan_coex_param *param;
struct conf_sg_settings *c = &wl->conf.sg;
int i, ret;
- wl1271_debug(DEBUG_ACX, "acx sg ap cfg");
+ wl1271_debug(DEBUG_ACX, "acx sg cfg");
param = kzalloc(sizeof(*param), GFP_KERNEL);
if (!param) {
@@ -592,8 +541,8 @@ int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
}
/* BT-WLAN coext parameters */
- for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++)
- param->params[i] = cpu_to_le32(c->ap_params[i]);
+ for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
+ param->params[i] = cpu_to_le32(c->params[i]);
param->param_idx = CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
@@ -625,10 +574,8 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
detection, sizeof(*detection));
- if (ret < 0) {
+ if (ret < 0)
wl1271_warning("failed to set cca threshold: %d", ret);
- return ret;
- }
out:
kfree(detection);
@@ -648,6 +595,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
goto out;
}
+ bb->role_id = wl->role_id;
bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
@@ -677,6 +625,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
goto out;
}
+ acx_aid->role_id = wl->role_id;
acx_aid->aid = cpu_to_le16(aid);
ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
@@ -732,6 +681,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
goto out;
}
+ acx->role_id = wl->role_id;
acx->preamble = preamble;
ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
@@ -759,6 +709,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
goto out;
}
+ acx->role_id = wl->role_id;
acx->ctsprotect = ctsprotect;
ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
@@ -790,9 +741,8 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
{
- struct acx_sta_rate_policy *acx;
+ struct acx_rate_policy *acx;
struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
- int idx = 0;
int ret = 0;
wl1271_debug(DEBUG_ACX, "acx rate policies");
@@ -804,25 +754,46 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
goto out;
}
+ wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
+ wl->basic_rate, wl->rate_set);
+
/* configure one basic rate class */
- idx = ACX_TX_BASIC_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
- acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
- acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
- acx->rate_class[idx].aflags = c->aflags;
+ acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE);
+ acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate);
+ acx->rate_policy.short_retry_limit = c->short_retry_limit;
+ acx->rate_policy.long_retry_limit = c->long_retry_limit;
+ acx->rate_policy.aflags = c->aflags;
+
+ ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of rate policies failed: %d", ret);
+ goto out;
+ }
/* configure one AP supported rate class */
- idx = ACX_TX_AP_FULL_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
- acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
- acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
- acx->rate_class[idx].aflags = c->aflags;
+ acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE);
+ acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set);
+ acx->rate_policy.short_retry_limit = c->short_retry_limit;
+ acx->rate_policy.long_retry_limit = c->long_retry_limit;
+ acx->rate_policy.aflags = c->aflags;
- acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
+ ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of rate policies failed: %d", ret);
+ goto out;
+ }
- wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
- acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
- acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
+ /*
+ * configure one rate class for basic p2p operations.
+ * (p2p packets should always go out with OFDM rates, even
+ * if we are currently connected to 11b AP)
+ */
+ acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P);
+ acx->rate_policy.enabled_rates =
+ cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P);
+ acx->rate_policy.short_retry_limit = c->short_retry_limit;
+ acx->rate_policy.long_retry_limit = c->long_retry_limit;
+ acx->rate_policy.aflags = c->aflags;
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) {
@@ -838,7 +809,7 @@ out:
int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
u8 idx)
{
- struct acx_ap_rate_policy *acx;
+ struct acx_rate_policy *acx;
int ret = 0;
wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x",
@@ -884,6 +855,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
goto out;
}
+ acx->role_id = wl->role_id;
acx->ac = ac;
acx->cw_min = cw_min;
acx->cw_max = cpu_to_le16(cw_max);
@@ -917,6 +889,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
goto out;
}
+ acx->role_id = wl->role_id;
acx->queue_id = queue_id;
acx->channel_type = channel_type;
acx->tsid = tsid;
@@ -996,52 +969,9 @@ out:
return ret;
}
-int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
+int wl12xx_acx_mem_cfg(struct wl1271 *wl)
{
- struct wl1271_acx_ap_config_memory *mem_conf;
- struct conf_memory_settings *mem;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
-
- mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
- if (!mem_conf) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (wl->chip.id == CHIP_ID_1283_PG20)
- /*
- * FIXME: The 128x AP FW does not yet support dynamic memory.
- * Use the base memory configuration for 128x for now. This
- * should be fine tuned in the future.
- */
- mem = &wl->conf.mem_wl128x;
- else
- mem = &wl->conf.mem_wl127x;
-
- /* memory config */
- mem_conf->num_stations = mem->num_stations;
- mem_conf->rx_mem_block_num = mem->rx_block_num;
- mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
- mem_conf->num_ssid_profiles = mem->ssid_profiles;
- mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
-
- ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
- sizeof(*mem_conf));
- if (ret < 0) {
- wl1271_warning("wl1271 mem config failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(mem_conf);
- return ret;
-}
-
-int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
-{
- struct wl1271_acx_sta_config_memory *mem_conf;
+ struct wl12xx_acx_config_memory *mem_conf;
struct conf_memory_settings *mem;
int ret;
@@ -1068,6 +998,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
mem_conf->tx_free_req = mem->min_req_tx_blocks;
mem_conf->rx_free_req = mem->min_req_rx_blocks;
mem_conf->tx_min = mem->tx_min;
+ mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
sizeof(*mem_conf));
@@ -1183,6 +1114,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
goto out;
}
+ acx->role_id = wl->role_id;
acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
@@ -1210,6 +1142,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
goto out;
}
+ acx->role_id = wl->role_id;
acx->version = ACX_IPV4_VERSION;
acx->enable = enable;
@@ -1269,6 +1202,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
goto out;
}
+ acx->role_id = wl->role_id;
acx->enabled = enable;
ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
@@ -1295,6 +1229,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
goto out;
}
+ acx->role_id = wl->role_id;
acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
acx->index = index;
acx->tpl_validation = tpl_valid;
@@ -1328,6 +1263,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
wl->last_rssi_event = -1;
+ acx->role_id = wl->role_id;
acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
@@ -1366,6 +1302,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
goto out;
}
+ acx->role_id = wl->role_id;
acx->rssi_beacon = c->avg_weight_rssi_beacon;
acx->rssi_data = c->avg_weight_rssi_data;
acx->snr_beacon = c->avg_weight_snr_beacon;
@@ -1384,14 +1321,15 @@ out:
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap,
- bool allow_ht_operation)
+ bool allow_ht_operation, u8 hlid)
{
struct wl1271_acx_ht_capabilities *acx;
- u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int ret = 0;
u32 ht_capabilites = 0;
- wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
+ wl1271_debug(DEBUG_ACX, "acx ht capabilities setting "
+ "sta supp: %d sta cap: %d", ht_cap->ht_supported,
+ ht_cap->cap);
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) {
@@ -1399,26 +1337,22 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
goto out;
}
- /* Allow HT Operation ? */
- if (allow_ht_operation) {
- ht_capabilites =
- WL1271_ACX_FW_CAP_HT_OPERATION;
- if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
- ht_capabilites |=
- WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
- if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
- ht_capabilites |=
- WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
- if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
- ht_capabilites |=
- WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
+ if (allow_ht_operation && ht_cap->ht_supported) {
+ /* no need to translate capabilities - use the spec values */
+ ht_capabilites = ht_cap->cap;
+
+ /*
+ * this bit is not employed by the spec but only by FW to
+ * indicate peer HT support
+ */
+ ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
/* get data from A-MPDU parameters field */
acx->ampdu_max_length = ht_cap->ampdu_factor;
acx->ampdu_min_spacing = ht_cap->ampdu_density;
}
- memcpy(acx->mac_address, mac_address, ETH_ALEN);
+ acx->hlid = hlid;
acx->ht_capabilites = cpu_to_le32(ht_capabilites);
ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
@@ -1446,6 +1380,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
goto out;
}
+ acx->role_id = wl->role_id;
acx->ht_protection =
(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
acx->rifs_mode = 0;
@@ -1467,14 +1402,12 @@ out:
}
/* Configure BA session initiator/receiver parameters setting in the FW. */
-int wl1271_acx_set_ba_session(struct wl1271 *wl,
- enum ieee80211_back_parties direction,
- u8 tid_index, u8 policy)
+int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
{
- struct wl1271_acx_ba_session_policy *acx;
+ struct wl1271_acx_ba_initiator_policy *acx;
int ret;
- wl1271_debug(DEBUG_ACX, "acx ba session setting");
+ wl1271_debug(DEBUG_ACX, "acx ba initiator policy");
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) {
@@ -1482,33 +1415,18 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
goto out;
}
- /* ANY role */
- acx->role_id = 0xff;
- acx->tid = tid_index;
- acx->enable = policy;
- acx->ba_direction = direction;
-
- switch (direction) {
- case WLAN_BACK_INITIATOR:
- acx->win_size = wl->conf.ht.tx_ba_win_size;
- acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
- break;
- case WLAN_BACK_RECIPIENT:
- acx->win_size = RX_BA_WIN_SIZE;
- acx->inactivity_timeout = 0;
- break;
- default:
- wl1271_error("Incorrect acx command id=%x\n", direction);
- ret = -EINVAL;
- goto out;
- }
+ /* set for the current role */
+ acx->role_id = wl->role_id;
+ acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap;
+ acx->win_size = wl->conf.ht.tx_ba_win_size;
+ acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
ret = wl1271_cmd_configure(wl,
- ACX_BA_SESSION_POLICY_CFG,
+ ACX_BA_SESSION_INIT_POLICY,
acx,
sizeof(*acx));
if (ret < 0) {
- wl1271_warning("acx ba session setting failed: %d", ret);
+ wl1271_warning("acx ba initiator policy failed: %d", ret);
goto out;
}
@@ -1518,8 +1436,8 @@ out:
}
/* setup BA session receiver setting in the FW. */
-int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
- bool enable)
+int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
+ u16 ssn, bool enable, u8 peer_hlid)
{
struct wl1271_acx_ba_receiver_setup *acx;
int ret;
@@ -1532,11 +1450,10 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
goto out;
}
- /* Single link for now */
- acx->link_id = 1;
+ acx->hlid = peer_hlid;
acx->tid = tid_index;
acx->enable = enable;
- acx->win_size = 0;
+ acx->win_size = wl->conf.ht.rx_ba_win_size;
acx->ssn = ssn;
ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
@@ -1577,22 +1494,71 @@ out:
return ret;
}
-int wl1271_acx_max_tx_retry(struct wl1271 *wl)
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
{
- struct wl1271_acx_max_tx_retry *acx = NULL;
+ struct wl1271_acx_ps_rx_streaming *rx_streaming;
+ u32 conf_queues, enable_queues;
+ int i, ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx ps rx streaming");
+
+ rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL);
+ if (!rx_streaming) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ conf_queues = wl->conf.rx_streaming.queues;
+ if (enable)
+ enable_queues = conf_queues;
+ else
+ enable_queues = 0;
+
+ for (i = 0; i < 8; i++) {
+ /*
+ * Skip non-changed queues, to avoid redundant acxs.
+ * this check assumes conf.rx_streaming.queues can't
+ * be changed while rx_streaming is enabled.
+ */
+ if (!(conf_queues & BIT(i)))
+ continue;
+
+ rx_streaming->role_id = wl->role_id;
+ rx_streaming->tid = i;
+ rx_streaming->enable = enable_queues & BIT(i);
+ rx_streaming->period = wl->conf.rx_streaming.interval;
+ rx_streaming->timeout = wl->conf.rx_streaming.interval;
+
+ ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,
+ rx_streaming,
+ sizeof(*rx_streaming));
+ if (ret < 0) {
+ wl1271_warning("acx ps rx streaming failed: %d", ret);
+ goto out;
+ }
+ }
+out:
+ kfree(rx_streaming);
+ return ret;
+}
+
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
+{
+ struct wl1271_acx_ap_max_tx_retry *acx = NULL;
int ret;
- wl1271_debug(DEBUG_ACX, "acx max tx retry");
+ wl1271_debug(DEBUG_ACX, "acx ap max tx retry");
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx)
return -ENOMEM;
- acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
+ acx->role_id = wl->role_id;
+ acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
if (ret < 0) {
- wl1271_warning("acx max tx retry failed: %d", ret);
+ wl1271_warning("acx ap max tx retry failed: %d", ret);
goto out;
}
@@ -1656,31 +1622,6 @@ out:
return ret;
}
-int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable)
-{
- struct acx_ap_beacon_filter *acx = NULL;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable);
-
- acx = kzalloc(sizeof(*acx), GFP_KERNEL);
- if (!acx)
- return -ENOMEM;
-
- acx->enable = enable ? 1 : 0;
-
- ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT,
- acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("acx set ap beacon filter failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(acx);
- return ret;
-}
-
int wl1271_acx_fm_coex(struct wl1271 *wl)
{
struct wl1271_acx_fm_coex *acx;
@@ -1720,3 +1661,85 @@ out:
kfree(acx);
return ret;
}
+
+int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl)
+{
+ struct wl12xx_acx_set_rate_mgmt_params *acx = NULL;
+ struct conf_rate_policy_settings *conf = &wl->conf.rate;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx set rate mgmt params");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx)
+ return -ENOMEM;
+
+ acx->index = ACX_RATE_MGMT_ALL_PARAMS;
+ acx->rate_retry_score = cpu_to_le16(conf->rate_retry_score);
+ acx->per_add = cpu_to_le16(conf->per_add);
+ acx->per_th1 = cpu_to_le16(conf->per_th1);
+ acx->per_th2 = cpu_to_le16(conf->per_th2);
+ acx->max_per = cpu_to_le16(conf->max_per);
+ acx->inverse_curiosity_factor = conf->inverse_curiosity_factor;
+ acx->tx_fail_low_th = conf->tx_fail_low_th;
+ acx->tx_fail_high_th = conf->tx_fail_high_th;
+ acx->per_alpha_shift = conf->per_alpha_shift;
+ acx->per_add_shift = conf->per_add_shift;
+ acx->per_beta1_shift = conf->per_beta1_shift;
+ acx->per_beta2_shift = conf->per_beta2_shift;
+ acx->rate_check_up = conf->rate_check_up;
+ acx->rate_check_down = conf->rate_check_down;
+ memcpy(acx->rate_retry_policy, conf->rate_retry_policy,
+ sizeof(acx->rate_retry_policy));
+
+ ret = wl1271_cmd_configure(wl, ACX_SET_RATE_MGMT_PARAMS,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("acx set rate mgmt params failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl12xx_acx_config_hangover(struct wl1271 *wl)
+{
+ struct wl12xx_acx_config_hangover *acx;
+ struct conf_hangover_settings *conf = &wl->conf.hangover;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx config hangover");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->recover_time = cpu_to_le32(conf->recover_time);
+ acx->hangover_period = conf->hangover_period;
+ acx->dynamic_mode = conf->dynamic_mode;
+ acx->early_termination_mode = conf->early_termination_mode;
+ acx->max_period = conf->max_period;
+ acx->min_period = conf->min_period;
+ acx->increase_delta = conf->increase_delta;
+ acx->decrease_delta = conf->decrease_delta;
+ acx->quiet_time = conf->quiet_time;
+ acx->increase_time = conf->increase_time;
+ acx->window_size = acx->window_size;
+
+ ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx,
+ sizeof(*acx));
+
+ if (ret < 0) {
+ wl1271_warning("acx config hangover failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 9a895e3..e3f93b4 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -101,6 +101,17 @@ struct acx_error_counter {
__le32 seq_num_miss;
} __packed;
+enum wl12xx_role {
+ WL1271_ROLE_STA = 0,
+ WL1271_ROLE_IBSS,
+ WL1271_ROLE_AP,
+ WL1271_ROLE_DEVICE,
+ WL1271_ROLE_P2P_CL,
+ WL1271_ROLE_P2P_GO,
+
+ WL12XX_INVALID_ROLE_TYPE = 0xff
+};
+
enum wl1271_psm_mode {
/* Active mode */
WL1271_PSM_CAM = 0,
@@ -160,94 +171,6 @@ struct acx_rx_msdu_lifetime {
__le32 lifetime;
} __packed;
-/*
- * RX Config Options Table
- * Bit Definition
- * === ==========
- * 31:14 Reserved
- * 13 Copy RX Status - when set, write three receive status words
- * to top of rx'd MPDUs.
- * When cleared, do not write three status words (added rev 1.5)
- * 12 Reserved
- * 11 RX Complete upon FCS error - when set, give rx complete
- * interrupt for FCS errors, after the rx filtering, e.g. unicast
- * frames not to us with FCS error will not generate an interrupt.
- * 10 SSID Filter Enable - When set, the WiLink discards all beacon,
- * probe request, and probe response frames with an SSID that does
- * not match the SSID specified by the host in the START/JOIN
- * command.
- * When clear, the WiLink receives frames with any SSID.
- * 9 Broadcast Filter Enable - When set, the WiLink discards all
- * broadcast frames. When clear, the WiLink receives all received
- * broadcast frames.
- * 8:6 Reserved
- * 5 BSSID Filter Enable - When set, the WiLink discards any frames
- * with a BSSID that does not match the BSSID specified by the
- * host.
- * When clear, the WiLink receives frames from any BSSID.
- * 4 MAC Addr Filter - When set, the WiLink discards any frames
- * with a destination address that does not match the MAC address
- * of the adaptor.
- * When clear, the WiLink receives frames destined to any MAC
- * address.
- * 3 Promiscuous - When set, the WiLink receives all valid frames
- * (i.e., all frames that pass the FCS check).
- * When clear, only frames that pass the other filters specified
- * are received.
- * 2 FCS - When set, the WiLink includes the FCS with the received
- * frame.
- * When cleared, the FCS is discarded.
- * 1 PLCP header - When set, write all data from baseband to frame
- * buffer including PHY header.
- * 0 Reserved - Always equal to 0.
- *
- * RX Filter Options Table
- * Bit Definition
- * === ==========
- * 31:12 Reserved - Always equal to 0.
- * 11 Association - When set, the WiLink receives all association
- * related frames (association request/response, reassocation
- * request/response, and disassociation). When clear, these frames
- * are discarded.
- * 10 Auth/De auth - When set, the WiLink receives all authentication
- * and de-authentication frames. When clear, these frames are
- * discarded.
- * 9 Beacon - When set, the WiLink receives all beacon frames.
- * When clear, these frames are discarded.
- * 8 Contention Free - When set, the WiLink receives all contention
- * free frames.
- * When clear, these frames are discarded.
- * 7 Control - When set, the WiLink receives all control frames.
- * When clear, these frames are discarded.
- * 6 Data - When set, the WiLink receives all data frames.
- * When clear, these frames are discarded.
- * 5 FCS Error - When set, the WiLink receives frames that have FCS
- * errors.
- * When clear, these frames are discarded.
- * 4 Management - When set, the WiLink receives all management
- * frames.
- * When clear, these frames are discarded.
- * 3 Probe Request - When set, the WiLink receives all probe request
- * frames.
- * When clear, these frames are discarded.
- * 2 Probe Response - When set, the WiLink receives all probe
- * response frames.
- * When clear, these frames are discarded.
- * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
- * frames.
- * When clear, these frames are discarded.
- * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames
- * that have reserved frame types and sub types as defined by the
- * 802.11 specification.
- * When clear, these frames are discarded.
- */
-struct acx_rx_config {
- struct acx_header header;
-
- __le32 config_options;
- __le32 filter_options;
-} __packed;
-
struct acx_packet_detection {
struct acx_header header;
@@ -267,9 +190,10 @@ enum acx_slot_type {
struct acx_slot {
struct acx_header header;
+ u8 role_id;
u8 wone_index; /* Reserved */
u8 slot_time;
- u8 reserved[6];
+ u8 reserved[5];
} __packed;
@@ -279,29 +203,35 @@ struct acx_slot {
struct acx_dot11_grp_addr_tbl {
struct acx_header header;
+ u8 role_id;
u8 enabled;
u8 num_groups;
- u8 pad[2];
+ u8 pad[1];
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
} __packed;
struct acx_rx_timeout {
struct acx_header header;
+ u8 role_id;
+ u8 reserved;
__le16 ps_poll_timeout;
__le16 upsd_timeout;
+ u8 padding[2];
} __packed;
struct acx_rts_threshold {
struct acx_header header;
+ u8 role_id;
+ u8 reserved;
__le16 threshold;
- u8 pad[2];
} __packed;
struct acx_beacon_filter_option {
struct acx_header header;
+ u8 role_id;
u8 enable;
/*
* The number of beacons without the unicast TIM
@@ -311,7 +241,7 @@ struct acx_beacon_filter_option {
* without the unicast TIM bit set are dropped.
*/
u8 max_num_beacons;
- u8 pad[2];
+ u8 pad[1];
} __packed;
/*
@@ -350,14 +280,17 @@ struct acx_beacon_filter_option {
struct acx_beacon_filter_ie_table {
struct acx_header header;
+ u8 role_id;
u8 num_ie;
- u8 pad[3];
+ u8 pad[2];
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
} __packed;
struct acx_conn_monit_params {
struct acx_header header;
+ u8 role_id;
+ u8 padding[3];
__le32 synch_fail_thold; /* number of beacons missed */
__le32 bss_lose_timeout; /* number of TU's from synch fail */
} __packed;
@@ -369,23 +302,14 @@ struct acx_bt_wlan_coex {
u8 pad[3];
} __packed;
-struct acx_sta_bt_wlan_coex_param {
- struct acx_header header;
-
- __le32 params[CONF_SG_STA_PARAMS_MAX];
- u8 param_idx;
- u8 padding[3];
-} __packed;
-
-struct acx_ap_bt_wlan_coex_param {
+struct acx_bt_wlan_coex_param {
struct acx_header header;
- __le32 params[CONF_SG_AP_PARAMS_MAX];
+ __le32 params[CONF_SG_PARAMS_MAX];
u8 param_idx;
u8 padding[3];
} __packed;
-
struct acx_dco_itrim_params {
struct acx_header header;
@@ -406,15 +330,16 @@ struct acx_energy_detection {
struct acx_beacon_broadcast {
struct acx_header header;
- __le16 beacon_rx_timeout;
- __le16 broadcast_timeout;
-
+ u8 role_id;
/* Enables receiving of broadcast packets in PS mode */
u8 rx_broadcast_in_ps;
+ __le16 beacon_rx_timeout;
+ __le16 broadcast_timeout;
+
/* Consecutive PS Poll failures before updating the host */
u8 ps_poll_threshold;
- u8 pad[2];
+ u8 pad[1];
} __packed;
struct acx_event_mask {
@@ -424,35 +349,6 @@ struct acx_event_mask {
__le32 high_event_mask; /* Unused */
} __packed;
-#define CFG_RX_FCS BIT(2)
-#define CFG_RX_ALL_GOOD BIT(3)
-#define CFG_UNI_FILTER_EN BIT(4)
-#define CFG_BSSID_FILTER_EN BIT(5)
-#define CFG_MC_FILTER_EN BIT(6)
-#define CFG_MC_ADDR0_EN BIT(7)
-#define CFG_MC_ADDR1_EN BIT(8)
-#define CFG_BC_REJECT_EN BIT(9)
-#define CFG_SSID_FILTER_EN BIT(10)
-#define CFG_RX_INT_FCS_ERROR BIT(11)
-#define CFG_RX_INT_ENCRYPTED BIT(12)
-#define CFG_RX_WR_RX_STATUS BIT(13)
-#define CFG_RX_FILTER_NULTI BIT(14)
-#define CFG_RX_RESERVE BIT(15)
-#define CFG_RX_TIMESTAMP_TSF BIT(16)
-
-#define CFG_RX_RSV_EN BIT(0)
-#define CFG_RX_RCTS_ACK BIT(1)
-#define CFG_RX_PRSP_EN BIT(2)
-#define CFG_RX_PREQ_EN BIT(3)
-#define CFG_RX_MGMT_EN BIT(4)
-#define CFG_RX_FCS_ERROR BIT(5)
-#define CFG_RX_DATA_EN BIT(6)
-#define CFG_RX_CTL_EN BIT(7)
-#define CFG_RX_CF_EN BIT(8)
-#define CFG_RX_BCN_EN BIT(9)
-#define CFG_RX_AUTH_EN BIT(10)
-#define CFG_RX_ASSOC_EN BIT(11)
-
#define SCAN_PASSIVE BIT(0)
#define SCAN_5GHZ_BAND BIT(1)
#define SCAN_TRIGGERED BIT(2)
@@ -465,6 +361,8 @@ struct acx_event_mask {
struct acx_feature_config {
struct acx_header header;
+ u8 role_id;
+ u8 padding[3];
__le32 options;
__le32 data_flow_options;
} __packed;
@@ -472,16 +370,18 @@ struct acx_feature_config {
struct acx_current_tx_power {
struct acx_header header;
+ u8 role_id;
u8 current_tx_power;
- u8 padding[3];
+ u8 padding[2];
} __packed;
struct acx_wake_up_condition {
struct acx_header header;
+ u8 role_id;
u8 wake_up_event; /* Only one bit can be set */
u8 listen_interval;
- u8 pad[2];
+ u8 pad[1];
} __packed;
struct acx_aid {
@@ -490,8 +390,9 @@ struct acx_aid {
/*
* To be set when associated with an AP.
*/
+ u8 role_id;
+ u8 reserved;
__le16 aid;
- u8 pad[2];
} __packed;
enum acx_preamble_type {
@@ -506,8 +407,9 @@ struct acx_preamble {
* When set, the WiLink transmits the frames with a short preamble and
* when cleared, the WiLink transmits the frames with a long preamble.
*/
+ u8 role_id;
u8 preamble;
- u8 padding[3];
+ u8 padding[2];
} __packed;
enum acx_ctsprotect_type {
@@ -517,8 +419,9 @@ enum acx_ctsprotect_type {
struct acx_ctsprotect {
struct acx_header header;
+ u8 role_id;
u8 ctsprotect;
- u8 padding[3];
+ u8 padding[2];
} __packed;
struct acx_tx_statistics {
@@ -753,18 +656,10 @@ struct acx_rate_class {
#define ACX_TX_BASIC_RATE 0
#define ACX_TX_AP_FULL_RATE 1
-#define ACX_TX_RATE_POLICY_CNT 2
-struct acx_sta_rate_policy {
- struct acx_header header;
-
- __le32 rate_class_cnt;
- struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
-} __packed;
-
-
+#define ACX_TX_BASIC_RATE_P2P 2
#define ACX_TX_AP_MODE_MGMT_RATE 4
#define ACX_TX_AP_MODE_BCST_RATE 5
-struct acx_ap_rate_policy {
+struct acx_rate_policy {
struct acx_header header;
__le32 rate_policy_idx;
@@ -773,22 +668,23 @@ struct acx_ap_rate_policy {
struct acx_ac_cfg {
struct acx_header header;
+ u8 role_id;
u8 ac;
+ u8 aifsn;
u8 cw_min;
__le16 cw_max;
- u8 aifsn;
- u8 reserved;
__le16 tx_op_limit;
} __packed;
struct acx_tid_config {
struct acx_header header;
+ u8 role_id;
u8 queue_id;
u8 channel_type;
u8 tsid;
u8 ps_scheme;
u8 ack_policy;
- u8 padding[3];
+ u8 padding[2];
__le32 apsd_conf[2];
} __packed;
@@ -804,19 +700,7 @@ struct acx_tx_config_options {
__le16 tx_compl_threshold; /* number of packets */
} __packed;
-#define ACX_TX_DESCRIPTORS 32
-
-struct wl1271_acx_ap_config_memory {
- struct acx_header header;
-
- u8 rx_mem_block_num;
- u8 tx_min_mem_block_num;
- u8 num_stations;
- u8 num_ssid_profiles;
- __le32 total_tx_descriptors;
-} __packed;
-
-struct wl1271_acx_sta_config_memory {
+struct wl12xx_acx_config_memory {
struct acx_header header;
u8 rx_mem_block_num;
@@ -828,6 +712,8 @@ struct wl1271_acx_sta_config_memory {
u8 tx_free_req;
u8 rx_free_req;
u8 tx_min;
+ u8 fwlog_blocks;
+ u8 padding[3];
} __packed;
struct wl1271_acx_mem_map {
@@ -888,9 +774,10 @@ struct wl1271_acx_rx_config_opt {
struct wl1271_acx_bet_enable {
struct acx_header header;
+ u8 role_id;
u8 enable;
u8 max_consecutive;
- u8 padding[2];
+ u8 padding[1];
} __packed;
#define ACX_IPV4_VERSION 4
@@ -903,9 +790,10 @@ struct wl1271_acx_bet_enable {
struct wl1271_acx_arp_filter {
struct acx_header header;
+ u8 role_id;
u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
u8 enable; /* bitmap of enabled ARP filtering features */
- u8 padding[2];
+ u8 padding[1];
u8 address[16]; /* The configured device IP address - all ARP
requests directed to this IP address will pass
through. For IPv4, the first four bytes are
@@ -923,8 +811,9 @@ struct wl1271_acx_pm_config {
struct wl1271_acx_keep_alive_mode {
struct acx_header header;
+ u8 role_id;
u8 enabled;
- u8 padding[3];
+ u8 padding[2];
} __packed;
enum {
@@ -940,11 +829,11 @@ enum {
struct wl1271_acx_keep_alive_config {
struct acx_header header;
- __le32 period;
+ u8 role_id;
u8 index;
u8 tpl_validation;
u8 trigger;
- u8 padding;
+ __le32 period;
} __packed;
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
@@ -988,26 +877,33 @@ enum {
struct wl1271_acx_rssi_snr_trigger {
struct acx_header header;
- __le16 threshold;
- __le16 pacing; /* 0 - 60000 ms */
+ u8 role_id;
u8 metric;
u8 type;
u8 dir;
+ __le16 threshold;
+ __le16 pacing; /* 0 - 60000 ms */
u8 hysteresis;
u8 index;
u8 enable;
- u8 padding[2];
+ u8 padding[1];
};
struct wl1271_acx_rssi_snr_avg_weights {
struct acx_header header;
+ u8 role_id;
+ u8 padding[3];
u8 rssi_beacon;
u8 rssi_data;
u8 snr_beacon;
u8 snr_data;
};
+
+/* special capability bit (not employed by the 802.11n spec) */
+#define WL12XX_HT_CAP_HT_OPERATION BIT(16)
+
/*
* ACX_PEER_HT_CAP
* Configure HT capabilities - declare the capabilities of the peer
@@ -1016,28 +912,11 @@ struct wl1271_acx_rssi_snr_avg_weights {
struct wl1271_acx_ht_capabilities {
struct acx_header header;
- /*
- * bit 0 - Allow HT Operation
- * bit 1 - Allow Greenfield format in TX
- * bit 2 - Allow Short GI in TX
- * bit 3 - Allow L-SIG TXOP Protection in TX
- * bit 4 - Allow HT Control fields in TX.
- * Note, driver will still leave space for HT control in packets
- * regardless of the value of this field. FW will be responsible
- * to drop the HT field from any frame when this Bit set to 0.
- * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD.
- * Exact policy setting for this feature is TBD.
- * Note, this bit can only be set to 1 if bit 3 is set to 1.
- */
+ /* bitmask of capability bits supported by the peer */
__le32 ht_capabilites;
- /*
- * Indicates to which peer these capabilities apply.
- * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance
- * for all peers.
- * Only valid for IBSS/DLS operation.
- */
- u8 mac_address[ETH_ALEN];
+ /* Indicates to which link these capabilities apply. */
+ u8 hlid;
/*
* This the maximum A-MPDU length supported by the AP. The FW may not
@@ -1047,16 +926,9 @@ struct wl1271_acx_ht_capabilities {
/* This is the minimal spacing required when sending A-MPDUs to the AP*/
u8 ampdu_min_spacing;
-} __packed;
-
-/* HT Capabilites Fw Bit Mask Mapping */
-#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0)
-#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1)
-#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2)
-#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3)
-#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4)
-#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5)
+ u8 padding;
+} __packed;
/*
* ACX_HT_BSS_OPERATION
@@ -1065,6 +937,8 @@ struct wl1271_acx_ht_capabilities {
struct wl1271_acx_ht_information {
struct acx_header header;
+ u8 role_id;
+
/* Values: 0 - RIFS not allowed, 1 - RIFS allowed */
u8 rifs_mode;
@@ -1086,60 +960,51 @@ struct wl1271_acx_ht_information {
*/
u8 dual_cts_protection;
- u8 padding[3];
+ u8 padding[2];
} __packed;
-#define RX_BA_WIN_SIZE 8
+#define RX_BA_MAX_SESSIONS 2
-struct wl1271_acx_ba_session_policy {
+struct wl1271_acx_ba_initiator_policy {
struct acx_header header;
- /*
- * Specifies role Id, Range 0-7, 0xFF means ANY role.
- * Future use. For now this field is irrelevant
- */
+
+ /* Specifies role Id, Range 0-7, 0xFF means ANY role. */
u8 role_id;
+
/*
- * Specifies Link Id, Range 0-31, 0xFF means ANY Link Id.
- * Not applicable if Role Id is set to ANY.
+ * Per TID setting for allowing TX BA. Set a bit to 1 to allow
+ * TX BA sessions for the corresponding TID.
*/
- u8 link_id;
-
- u8 tid;
-
- u8 enable;
+ u8 tid_bitmap;
/* Windows size in number of packets */
- u16 win_size;
+ u8 win_size;
- /*
- * As initiator inactivity timeout in time units(TU) of 1024us.
- * As receiver reserved
- */
- u16 inactivity_timeout;
+ u8 padding1[1];
- /* Initiator = 1/Receiver = 0 */
- u8 ba_direction;
+ /* As initiator inactivity timeout in time units(TU) of 1024us */
+ u16 inactivity_timeout;
- u8 padding[3];
+ u8 padding[2];
} __packed;
struct wl1271_acx_ba_receiver_setup {
struct acx_header header;
- /* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */
- u8 link_id;
+ /* Specifies link id, range 0-31 */
+ u8 hlid;
u8 tid;
u8 enable;
- u8 padding[1];
-
/* Windows size in number of packets */
- u16 win_size;
+ u8 win_size;
/* BA session starting sequence number. RANGE 0-FFF */
u16 ssn;
+
+ u8 padding[2];
} __packed;
struct wl1271_acx_fw_tsf_information {
@@ -1153,15 +1018,32 @@ struct wl1271_acx_fw_tsf_information {
u8 padding[3];
} __packed;
-struct wl1271_acx_max_tx_retry {
+struct wl1271_acx_ps_rx_streaming {
struct acx_header header;
+ u8 role_id;
+ u8 tid;
+ u8 enable;
+
+ /* interval between triggers (10-100 msec) */
+ u8 period;
+
+ /* timeout before first trigger (0-200 msec) */
+ u8 timeout;
+ u8 padding[3];
+} __packed;
+
+struct wl1271_acx_ap_max_tx_retry {
+ struct acx_header header;
+
+ u8 role_id;
+ u8 padding_1;
+
/*
* the number of frames transmission failures before
* issuing the aging event.
*/
__le16 max_tx_retry;
- u8 padding_1[2];
} __packed;
struct wl1271_acx_config_ps {
@@ -1180,13 +1062,6 @@ struct wl1271_acx_inconnection_sta {
u8 padding1[2];
} __packed;
-struct acx_ap_beacon_filter {
- struct acx_header header;
-
- u8 enable;
- u8 pad[3];
-} __packed;
-
/*
* ACX_FM_COEX_CFG
* set the FM co-existence parameters.
@@ -1246,6 +1121,47 @@ struct wl1271_acx_fm_coex {
u8 swallow_clk_diff;
} __packed;
+#define ACX_RATE_MGMT_ALL_PARAMS 0xff
+struct wl12xx_acx_set_rate_mgmt_params {
+ struct acx_header header;
+
+ u8 index; /* 0xff to configure all params */
+ u8 padding1;
+ __le16 rate_retry_score;
+ __le16 per_add;
+ __le16 per_th1;
+ __le16 per_th2;
+ __le16 max_per;
+ u8 inverse_curiosity_factor;
+ u8 tx_fail_low_th;
+ u8 tx_fail_high_th;
+ u8 per_alpha_shift;
+ u8 per_add_shift;
+ u8 per_beta1_shift;
+ u8 per_beta2_shift;
+ u8 rate_check_up;
+ u8 rate_check_down;
+ u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
+ u8 padding2[2];
+} __packed;
+
+struct wl12xx_acx_config_hangover {
+ struct acx_header header;
+
+ __le32 recover_time;
+ u8 hangover_period;
+ u8 dynamic_mode;
+ u8 early_termination_mode;
+ u8 max_period;
+ u8 min_period;
+ u8 increase_delta;
+ u8 decrease_delta;
+ u8 quiet_time;
+ u8 increase_time;
+ u8 window_size;
+ u8 padding[2];
+} __packed;
+
enum {
ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003,
@@ -1253,10 +1169,7 @@ enum {
ACX_AC_CFG = 0x0007,
ACX_MEM_MAP = 0x0008,
ACX_AID = 0x000A,
- /* ACX_FW_REV is missing in the ref driver, but seems to work */
- ACX_FW_REV = 0x000D,
ACX_MEDIUM_USAGE = 0x000F,
- ACX_RX_CFG = 0x0010,
ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */
ACX_STATISTICS = 0x0013, /* Debug API */
ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
@@ -1264,7 +1177,6 @@ enum {
ACX_TID_CFG = 0x001A,
ACX_PS_RX_STREAMING = 0x001B,
ACX_BEACON_FILTER_OPT = 0x001F,
- ACX_AP_BEACON_FILTER_OPT = 0x0020,
ACX_NOISE_HIST = 0x0021,
ACX_HDK_VERSION = 0x0022, /* ??? */
ACX_PD_THRESHOLD = 0x0023,
@@ -1272,7 +1184,6 @@ enum {
ACX_CCA_THRESHOLD = 0x0025,
ACX_EVENT_MBOX_MASK = 0x0026,
ACX_CONN_MONIT_PARAMS = 0x002D,
- ACX_CONS_TX_FAILURE = 0x002F,
ACX_BCN_DTIM_OPTIONS = 0x0031,
ACX_SG_ENABLE = 0x0032,
ACX_SG_CFG = 0x0033,
@@ -1299,11 +1210,14 @@ enum {
ACX_RSSI_SNR_WEIGHTS = 0x0052,
ACX_KEEP_ALIVE_MODE = 0x0053,
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
- ACX_BA_SESSION_POLICY_CFG = 0x0055,
+ ACX_BA_SESSION_INIT_POLICY = 0x0055,
ACX_BA_SESSION_RX_SETUP = 0x0056,
ACX_PEER_HT_CAP = 0x0057,
ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059,
+ ACX_BURST_MODE = 0x005C,
+ ACX_SET_RATE_MGMT_PARAMS = 0x005D,
+ ACX_SET_RATE_ADAPT_PARAMS = 0x0060,
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
ACX_GEN_FW_CMD = 0x0070,
ACX_HOST_IF_CFG_BITMAP = 0x0071,
@@ -1327,7 +1241,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl);
int wl1271_acx_mem_map(struct wl1271 *wl,
struct acx_header *mem_map, size_t len);
int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
-int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
int wl1271_acx_pd_threshold(struct wl1271 *wl);
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
@@ -1339,8 +1252,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable);
int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
-int wl1271_acx_sta_sg_cfg(struct wl1271 *wl);
-int wl1271_acx_ap_sg_cfg(struct wl1271 *wl);
+int wl12xx_acx_sg_cfg(struct wl1271 *wl);
int wl1271_acx_cca_threshold(struct wl1271 *wl);
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
@@ -1359,8 +1271,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
u32 apsd_conf0, u32 apsd_conf1);
int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
-int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
+int wl12xx_acx_mem_cfg(struct wl1271 *wl);
int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
@@ -1375,19 +1286,19 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl);
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap,
- bool allow_ht_operation);
+ bool allow_ht_operation, u8 hlid);
int wl1271_acx_set_ht_information(struct wl1271 *wl,
u16 ht_operation_mode);
-int wl1271_acx_set_ba_session(struct wl1271 *wl,
- enum ieee80211_back_parties direction,
- u8 tid_index, u8 policy);
-int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
- bool enable);
+int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl);
+int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
+ u16 ssn, bool enable, u8 peer_hlid);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
-int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
-int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
int wl1271_acx_fm_coex(struct wl1271 *wl);
+int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
+int wl12xx_acx_config_hangover(struct wl1271 *wl);
#endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index e0e1688..a7b327d 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/wl12xx.h>
+#include <linux/export.h>
#include "acx.h"
#include "reg.h"
@@ -102,6 +103,23 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
+static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
+{
+ unsigned int quirks = 0;
+ unsigned int *fw_ver = wl->chip.fw_ver;
+
+ /* Only new station firmwares support routing fw logs to the host */
+ if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
+ (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
+ quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+ /* This feature is not yet supported for AP mode */
+ if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
+ quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+ return quirks;
+}
+
static void wl1271_parse_fw_ver(struct wl1271 *wl)
{
int ret;
@@ -116,6 +134,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)
memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
return;
}
+
+ /* Check if any quirks are needed with older fw versions */
+ wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
}
static void wl1271_boot_fw_version(struct wl1271 *wl)
@@ -274,9 +295,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/
if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
- /* for now 11a is unsupported in AP mode */
- if (wl->bss_type != BSS_TYPE_AP_BSS &&
- nvs->general_params.dual_mode_select)
+ if (nvs->general_params.dual_mode_select)
wl->enable_11a = true;
}
@@ -488,18 +507,19 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl->event_mask = BSS_LOSE_EVENT_ID |
SCAN_COMPLETE_EVENT_ID |
PS_REPORT_EVENT_ID |
- JOIN_EVENT_COMPLETE_ID |
DISCONNECT_EVENT_COMPLETE_ID |
RSSI_SNR_TRIGGER_0_EVENT_ID |
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
SOFT_GEMINI_SENSE_EVENT_ID |
PERIODIC_SCAN_REPORT_EVENT_ID |
- PERIODIC_SCAN_COMPLETE_EVENT_ID;
-
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
- else
- wl->event_mask |= DUMMY_PACKET_EVENT_ID;
+ PERIODIC_SCAN_COMPLETE_EVENT_ID |
+ DUMMY_PACKET_EVENT_ID |
+ PEER_REMOVE_COMPLETE_EVENT_ID |
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID |
+ REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
+ INACTIVE_STA_EVENT_ID |
+ MAX_TX_RETRY_EVENT_ID |
+ CHANNEL_SWITCH_COMPLETE_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {
@@ -530,13 +550,13 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
{
u32 fuse;
- fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1);
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
+ else
+ fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
wl->hw_pg_ver = (s8)fuse;
-
- if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
- wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
}
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
@@ -677,7 +697,8 @@ static int wl127x_boot_clk(struct wl1271 *wl)
u32 pause;
u32 clk;
- wl1271_boot_hw_version(wl);
+ if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
+ wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
wl->ref_clock == CONF_REF_CLK_38_4_E ||
@@ -731,6 +752,8 @@ int wl1271_load_firmware(struct wl1271 *wl)
u32 tmp, clk;
int selected_clock = -1;
+ wl1271_boot_hw_version(wl);
+
if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl128x_boot_clk(wl, &selected_clock);
if (ret < 0)
@@ -830,9 +853,6 @@ int wl1271_boot(struct wl1271 *wl)
/* Enable firmware interrupts now */
wl1271_boot_enable_interrupts(wl);
- /* set the wl1271 default filters */
- wl1271_set_default_filters(wl);
-
wl1271_event_mbox_config(wl);
out:
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index e8f8255..06dad93 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -55,7 +55,8 @@ struct wl1271_static_data {
#define OCP_REG_CLK_POLARITY 0x0cb2
#define OCP_REG_CLK_PULL 0x0cb4
-#define REG_FUSE_DATA_2_1 0x050a
+#define WL127X_REG_FUSE_DATA_2_1 0x050a
+#define WL128X_REG_FUSE_DATA_2_1 0x2152
#define PG_VER_MASK 0x3c
#define PG_VER_OFFSET 2
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index b8ec8cd..54a0d66 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
@@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
fail:
WARN_ON(1);
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
return ret;
}
@@ -374,74 +373,483 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
if (ret != 0) {
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
return ret;
}
return 0;
}
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
+int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id)
{
- struct wl1271_cmd_join *join;
- int ret, i;
- u8 *bssid;
+ struct wl12xx_cmd_role_enable *cmd;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd role enable");
- join = kzalloc(sizeof(*join), GFP_KERNEL);
- if (!join) {
+ if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID))
+ return -EBUSY;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
ret = -ENOMEM;
goto out;
}
- wl1271_debug(DEBUG_CMD, "cmd join");
+ /* get role id */
+ cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES);
+ if (cmd->role_id >= WL12XX_MAX_ROLES) {
+ ret = -EBUSY;
+ goto out_free;
+ }
+
+ memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN);
+ cmd->role_type = role_type;
- /* Reverse order BSSID */
- bssid = (u8 *) &join->bssid_lsb;
- for (i = 0; i < ETH_ALEN; i++)
- bssid[i] = wl->bssid[ETH_ALEN - i - 1];
+ ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role enable");
+ goto out_free;
+ }
+
+ __set_bit(cmd->role_id, wl->roles_map);
+ *role_id = cmd->role_id;
+
+out_free:
+ kfree(cmd);
- join->rx_config_options = cpu_to_le32(wl->rx_config);
- join->rx_filter_options = cpu_to_le32(wl->rx_filter);
- join->bss_type = bss_type;
- join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
- join->supported_rate_set = cpu_to_le32(wl->rate_set);
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id)
+{
+ struct wl12xx_cmd_role_disable *cmd;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd role disable");
+
+ if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID))
+ return -ENOENT;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ cmd->role_id = *role_id;
+ ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role disable");
+ goto out_free;
+ }
+
+ __clear_bit(*role_id, wl->roles_map);
+ *role_id = WL12XX_INVALID_ROLE_ID;
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid)
+{
+ u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
+ if (link >= WL12XX_MAX_LINKS)
+ return -EBUSY;
+
+ __set_bit(link, wl->links_map);
+ *hlid = link;
+ return 0;
+}
+
+static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
+{
+ if (*hlid == WL12XX_INVALID_LINK_ID)
+ return;
+
+ __clear_bit(*hlid, wl->links_map);
+ *hlid = WL12XX_INVALID_LINK_ID;
+}
+
+static int wl12xx_get_new_session_id(struct wl1271 *wl)
+{
+ if (wl->session_counter >= SESSION_COUNTER_MAX)
+ wl->session_counter = 0;
+
+ wl->session_counter++;
+
+ return wl->session_counter;
+}
+
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id);
+
+ cmd->role_id = wl->dev_role_id;
if (wl->band == IEEE80211_BAND_5GHZ)
- join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
+ cmd->band = WL12XX_BAND_5GHZ;
+ cmd->channel = wl->channel;
+
+ if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) {
+ ret = wl12xx_allocate_link(wl, &wl->dev_hlid);
+ if (ret)
+ goto out_free;
+ }
+ cmd->device.hlid = wl->dev_hlid;
+ cmd->device.session = wl->session_counter;
+
+ wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
+ cmd->role_id, cmd->device.hlid, cmd->device.session);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role enable");
+ goto err_hlid;
+ }
+
+ goto out_free;
+
+err_hlid:
+ /* clear links on error */
+ __clear_bit(wl->dev_hlid, wl->links_map);
+ wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_stop *cmd;
+ int ret;
- join->beacon_interval = cpu_to_le16(wl->beacon_int);
- join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
+ if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID))
+ return -EINVAL;
- join->channel = wl->channel;
- join->ssid_len = wl->ssid_len;
- memcpy(join->ssid, wl->ssid, wl->ssid_len);
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
- join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
+ wl1271_debug(DEBUG_CMD, "cmd role stop dev");
- /* reset TX security counters */
- wl->tx_security_last_seq = 0;
- wl->tx_security_seq = 0;
+ cmd->role_id = wl->dev_role_id;
+ cmd->disc_type = DISCONNECT_IMMEDIATE;
+ cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
- wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
- join->basic_rate_set, join->supported_rate_set);
+ ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role stop");
+ goto out_free;
+ }
- ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
+ ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
if (ret < 0) {
- wl1271_error("failed to initiate cmd join");
+ wl1271_error("cmd role stop dev event completion error");
goto out_free;
}
- ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID);
+ wl12xx_free_link(wl, &wl->dev_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+ if (wl->band == IEEE80211_BAND_5GHZ)
+ cmd->band = WL12XX_BAND_5GHZ;
+ cmd->channel = wl->channel;
+ cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+ cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int);
+ cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY;
+ cmd->sta.ssid_len = wl->ssid_len;
+ memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len);
+ memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN);
+ cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
+
+ if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
+ ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
+ if (ret)
+ goto out_free;
+ }
+ cmd->sta.hlid = wl->sta_hlid;
+ cmd->sta.session = wl12xx_get_new_session_id(wl);
+ cmd->sta.remote_rates = cpu_to_le32(wl->rate_set);
+
+ wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
+ "basic_rate_set: 0x%x, remote_rates: 0x%x",
+ wl->role_id, cmd->sta.hlid, cmd->sta.session,
+ wl->basic_rate_set, wl->rate_set);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role start sta");
+ goto err_hlid;
+ }
+
+ goto out_free;
+
+err_hlid:
+ /* clear links on error. */
+ wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+/* use this function to stop ibss as well */
+int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_stop *cmd;
+ int ret;
+
+ if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID))
+ return -EINVAL;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+ cmd->disc_type = DISCONNECT_IMMEDIATE;
+ cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role stop sta");
+ goto out_free;
+ }
+
+ wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id);
+
+ /* trying to use hidden SSID with an old hostapd version */
+ if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) {
+ wl1271_error("got a null SSID from beacon/bss");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid);
+ if (ret < 0)
+ goto out_free;
+
+ ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid);
if (ret < 0)
- wl1271_error("cmd join event completion error");
+ goto out_free_global;
+
+ cmd->role_id = wl->role_id;
+ cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
+ cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
+ cmd->ap.global_hlid = wl->ap_global_hlid;
+ cmd->ap.broadcast_hlid = wl->ap_bcast_hlid;
+ cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+ cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int);
+ cmd->ap.dtim_interval = bss_conf->dtim_period;
+ cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
+ cmd->channel = wl->channel;
+
+ if (!bss_conf->hidden_ssid) {
+ /* take the SSID from the beacon for backward compatibility */
+ cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
+ cmd->ap.ssid_len = wl->ssid_len;
+ memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
+ } else {
+ cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN;
+ cmd->ap.ssid_len = bss_conf->ssid_len;
+ memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len);
+ }
+
+ cmd->ap.local_rates = cpu_to_le32(0xffffffff);
+
+ switch (wl->band) {
+ case IEEE80211_BAND_2GHZ:
+ cmd->band = RADIO_BAND_2_4GHZ;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ cmd->band = RADIO_BAND_5GHZ;
+ break;
+ default:
+ wl1271_warning("ap start - unknown band: %d", (int)wl->band);
+ cmd->band = RADIO_BAND_2_4GHZ;
+ break;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role start ap");
+ goto out_free_bcast;
+ }
+
+ goto out_free;
+
+out_free_bcast:
+ wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+
+out_free_global:
+ wl12xx_free_link(wl, &wl->ap_global_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_stop *cmd;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role stop ap");
+ goto out_free;
+ }
+
+ wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+ wl12xx_free_link(wl, &wl->ap_global_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+ if (wl->band == IEEE80211_BAND_5GHZ)
+ cmd->band = WL12XX_BAND_5GHZ;
+ cmd->channel = wl->channel;
+ cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+ cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int);
+ cmd->ibss.dtim_interval = bss_conf->dtim_period;
+ cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY;
+ cmd->ibss.ssid_len = wl->ssid_len;
+ memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len);
+ memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN);
+ cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
+
+ if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
+ ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
+ if (ret)
+ goto out_free;
+ }
+ cmd->ibss.hlid = wl->sta_hlid;
+ cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set);
+
+ wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
+ "basic_rate_set: 0x%x, remote_rates: 0x%x",
+ wl->role_id, cmd->sta.hlid, cmd->sta.session,
+ wl->basic_rate_set, wl->rate_set);
+
+ wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role enable");
+ goto err_hlid;
+ }
+
+ goto out_free;
+
+err_hlid:
+ /* clear links on error. */
+ wl12xx_free_link(wl, &wl->sta_hlid);
out_free:
- kfree(join);
+ kfree(cmd);
out:
return ret;
}
+
/**
* send test command to firmware
*
@@ -510,7 +918,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
struct acx_header *acx = buf;
int ret;
- wl1271_debug(DEBUG_CMD, "cmd configure");
+ wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id);
acx->id = cpu_to_le16(id);
@@ -589,6 +997,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
goto out;
}
+ ps_params->role_id = wl->role_id;
ps_params->ps_mode = ps_mode;
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
@@ -720,6 +1129,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
{
struct sk_buff *skb;
int ret;
+ u32 rate;
skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
ie, ie_len);
@@ -730,14 +1140,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate);
+ skb->data, skb->len, 0, rate);
else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate_5);
+ skb->data, skb->len, 0, rate);
out:
dev_kfree_skb(skb);
@@ -748,6 +1157,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
struct sk_buff *skb)
{
int ret;
+ u32 rate;
if (!skb)
skb = ieee80211_ap_probereq_get(wl->hw, wl->vif);
@@ -756,14 +1166,13 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]);
if (wl->band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate);
+ skb->data, skb->len, 0, rate);
else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate_5);
+ skb->data, skb->len, 0, rate);
if (ret < 0)
wl1271_error("Unable to set ap probe request template.");
@@ -835,9 +1244,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
wl->basic_rate);
}
-int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
+int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid)
{
- struct wl1271_cmd_set_sta_keys *cmd;
+ struct wl1271_cmd_set_keys *cmd;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
@@ -848,36 +1257,7 @@ int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
goto out;
}
- cmd->id = id;
- cmd->key_action = cpu_to_le16(KEY_SET_ID);
- cmd->key_type = KEY_WEP;
-
- ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
- if (ret < 0) {
- wl1271_warning("cmd set_default_wep_key failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(cmd);
-
- return ret;
-}
-
-int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
-{
- struct wl1271_cmd_set_ap_keys *cmd;
- int ret = 0;
-
- wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd) {
- ret = -ENOMEM;
- goto out;
- }
-
- cmd->hlid = WL1271_AP_BROADCAST_HLID;
+ cmd->hlid = hlid;
cmd->key_id = id;
cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
cmd->key_action = cpu_to_le16(KEY_SET_ID);
@@ -885,7 +1265,7 @@ int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
+ wl1271_warning("cmd set_default_wep_key failed: %d", ret);
goto out;
}
@@ -899,17 +1279,27 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16)
{
- struct wl1271_cmd_set_sta_keys *cmd;
+ struct wl1271_cmd_set_keys *cmd;
int ret = 0;
+ /* hlid might have already been deleted */
+ if (wl->sta_hlid == WL12XX_INVALID_LINK_ID)
+ return 0;
+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
- if (key_type != KEY_WEP)
- memcpy(cmd->addr, addr, ETH_ALEN);
+ cmd->hlid = wl->sta_hlid;
+
+ if (key_type == KEY_WEP)
+ cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
+ else if (is_broadcast_ether_addr(addr))
+ cmd->lid_key_type = BROADCAST_LID_TYPE;
+ else
+ cmd->lid_key_type = UNICAST_LID_TYPE;
cmd->key_action = cpu_to_le16(action);
cmd->key_size = key_size;
@@ -918,10 +1308,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
- /* we have only one SSID profile */
- cmd->ssid_profile = 0;
-
- cmd->id = id;
+ cmd->key_id = id;
if (key_type == KEY_TKIP) {
/*
@@ -952,11 +1339,15 @@ out:
return ret;
}
+/*
+ * TODO: merge with sta/ibss into 1 set_key function.
+ * note there are slight diffs
+ */
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16)
{
- struct wl1271_cmd_set_ap_keys *cmd;
+ struct wl1271_cmd_set_keys *cmd;
int ret = 0;
u8 lid_type;
@@ -964,7 +1355,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
if (!cmd)
return -ENOMEM;
- if (hlid == WL1271_AP_BROADCAST_HLID) {
+ if (hlid == wl->ap_bcast_hlid) {
if (key_type == KEY_WEP)
lid_type = WEP_DEFAULT_LID_TYPE;
else
@@ -1013,12 +1404,12 @@ out:
return ret;
}
-int wl1271_cmd_disconnect(struct wl1271 *wl)
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
{
- struct wl1271_cmd_disconnect *cmd;
+ struct wl12xx_cmd_set_peer_state *cmd;
int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd disconnect");
+ wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1026,21 +1417,15 @@ int wl1271_cmd_disconnect(struct wl1271 *wl)
goto out;
}
- cmd->rx_config_options = cpu_to_le32(wl->rx_config);
- cmd->rx_filter_options = cpu_to_le32(wl->rx_filter);
- /* disconnect reason is not used in immediate disconnections */
- cmd->type = DISCONNECT_IMMEDIATE;
+ cmd->hlid = hlid;
+ cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
- ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send disconnect command");
+ wl1271_error("failed to send set peer state command");
goto out_free;
}
- ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
- if (ret < 0)
- wl1271_error("cmd disconnect event completion error");
-
out_free:
kfree(cmd);
@@ -1048,12 +1433,13 @@ out:
return ret;
}
-int wl1271_cmd_set_sta_state(struct wl1271 *wl)
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
{
- struct wl1271_cmd_set_sta_state *cmd;
- int ret = 0;
+ struct wl12xx_cmd_add_peer *cmd;
+ int i, ret;
+ u32 sta_rates;
- wl1271_debug(DEBUG_CMD, "cmd set sta state");
+ wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1061,11 +1447,33 @@ int wl1271_cmd_set_sta_state(struct wl1271 *wl)
goto out;
}
- cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
+ memcpy(cmd->addr, sta->addr, ETH_ALEN);
+ cmd->bss_index = WL1271_AP_BSS_INDEX;
+ cmd->aid = sta->aid;
+ cmd->hlid = hlid;
+ cmd->sp_len = sta->max_sp;
+ cmd->wmm = sta->wme ? 1 : 0;
+
+ for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++)
+ if (sta->wme && (sta->uapsd_queues & BIT(i)))
+ cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER;
+ else
+ cmd->psd_type[i] = WL1271_PSD_LEGACY;
+
+ sta_rates = sta->supp_rates[wl->band];
+ if (sta->ht_cap.ht_supported)
+ sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
+
+ cmd->supported_rates =
+ cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
+ wl->band));
+
+ wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
+ cmd->supported_rates, sta->uapsd_queues);
- ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send set STA state command");
+ wl1271_error("failed to initiate cmd add peer");
goto out_free;
}
@@ -1076,45 +1484,146 @@ out:
return ret;
}
-int wl1271_cmd_start_bss(struct wl1271 *wl)
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{
- struct wl1271_cmd_bss_start *cmd;
- struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ struct wl12xx_cmd_remove_peer *cmd;
int ret;
- wl1271_debug(DEBUG_CMD, "cmd start bss");
+ wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->hlid = hlid;
+ /* We never send a deauth, mac80211 is in charge of this */
+ cmd->reason_opcode = 0;
+ cmd->send_deauth_flag = 0;
+
+ ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd remove peer");
+ goto out_free;
+ }
/*
- * FIXME: We currently do not support hidden SSID. The real SSID
- * should be fetched from mac80211 first.
+ * We are ok with a timeout here. The event is sometimes not sent
+ * due to a firmware bug.
*/
- if (wl->ssid_len == 0) {
- wl1271_warning("Hidden SSID currently not supported for AP");
- ret = -EINVAL;
+ wl1271_cmd_wait_for_event_or_timeout(wl,
+ PEER_REMOVE_COMPLETE_EVENT_ID);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_config_fwlog *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd config firmware logger");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
goto out;
}
+ cmd->logger_mode = wl->conf.fwlog.mode;
+ cmd->log_severity = wl->conf.fwlog.severity;
+ cmd->timestamp = wl->conf.fwlog.timestamp;
+ cmd->output = wl->conf.fwlog.output;
+ cmd->threshold = wl->conf.fwlog.threshold;
+
+ ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send config firmware logger command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_start_fwlog *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd start firmware logger");
+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
- memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
+ ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send start firmware logger command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
- cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
- cmd->bss_index = WL1271_AP_BSS_INDEX;
- cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
- cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
- cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
- cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
- cmd->dtim_interval = bss_conf->dtim_period;
- cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
- cmd->channel = wl->channel;
- cmd->ssid_len = wl->ssid_len;
- cmd->ssid_type = SSID_TYPE_PUBLIC;
- memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
+out:
+ return ret;
+}
+
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_stop_fwlog *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd stop firmware logger");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send stop firmware logger command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
+{
+ struct wl12xx_cmd_roc *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id);
+
+ if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
+ return -EINVAL;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ cmd->role_id = role_id;
+ cmd->channel = wl->channel;
switch (wl->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
@@ -1123,14 +1632,15 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)
cmd->band = RADIO_BAND_5GHZ;
break;
default:
- wl1271_warning("bss start - unknown band: %d", (int)wl->band);
- cmd->band = RADIO_BAND_2_4GHZ;
- break;
+ wl1271_error("roc - unknown band: %d", (int)wl->band);
+ ret = -EINVAL;
+ goto out_free;
}
- ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
+
+ ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd start bss");
+ wl1271_error("failed to send ROC command");
goto out_free;
}
@@ -1141,24 +1651,24 @@ out:
return ret;
}
-int wl1271_cmd_stop_bss(struct wl1271 *wl)
+static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
{
- struct wl1271_cmd_bss_start *cmd;
- int ret;
+ struct wl12xx_cmd_croc *cmd;
+ int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd stop bss");
+ wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
+ cmd->role_id = role_id;
- cmd->bss_index = WL1271_AP_BSS_INDEX;
-
- ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd,
+ sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd stop bss");
+ wl1271_error("failed to send ROC command");
goto out_free;
}
@@ -1169,43 +1679,67 @@ out:
return ret;
}
-int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
+int wl12xx_roc(struct wl1271 *wl, u8 role_id)
{
- struct wl1271_cmd_add_sta *cmd;
- int ret;
+ int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
+ if (WARN_ON(test_bit(role_id, wl->roc_map)))
+ return 0;
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd) {
- ret = -ENOMEM;
+ ret = wl12xx_cmd_roc(wl, role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_cmd_wait_for_event(wl,
+ REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID);
+ if (ret < 0) {
+ wl1271_error("cmd roc event completion error");
goto out;
}
- /* currently we don't support UAPSD */
- cmd->sp_len = 0;
+ __set_bit(role_id, wl->roc_map);
+out:
+ return ret;
+}
- memcpy(cmd->addr, sta->addr, ETH_ALEN);
- cmd->bss_index = WL1271_AP_BSS_INDEX;
- cmd->aid = sta->aid;
- cmd->hlid = hlid;
+int wl12xx_croc(struct wl1271 *wl, u8 role_id)
+{
+ int ret = 0;
- /*
- * FIXME: Does STA support QOS? We need to propagate this info from
- * hostapd. Currently not that important since this is only used for
- * sending the correct flavor of null-data packet in response to a
- * trigger.
- */
- cmd->wmm = 0;
+ if (WARN_ON(!test_bit(role_id, wl->roc_map)))
+ return 0;
+
+ ret = wl12xx_cmd_croc(wl, role_id);
+ if (ret < 0)
+ goto out;
+
+ __clear_bit(role_id, wl->roc_map);
+out:
+ return ret;
+}
- cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
- sta->supp_rates[wl->band]));
+int wl12xx_cmd_channel_switch(struct wl1271 *wl,
+ struct ieee80211_channel_switch *ch_switch)
+{
+ struct wl12xx_cmd_channel_switch *cmd;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "cmd channel switch");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
- wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
+ cmd->channel = ch_switch->channel->hw_value;
+ cmd->switch_time = ch_switch->count;
+ cmd->tx_suspend = ch_switch->block_tx;
+ cmd->flush = 0; /* this value is ignored by the FW */
- ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd add sta");
+ wl1271_error("failed to send channel switch command");
goto out_free;
}
@@ -1216,12 +1750,12 @@ out:
return ret;
}
-int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
+int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
{
- struct wl1271_cmd_remove_sta *cmd;
+ struct wl12xx_cmd_stop_channel_switch *cmd;
int ret;
- wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
+ wl1271_debug(DEBUG_ACX, "cmd stop channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1229,23 +1763,12 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
goto out;
}
- cmd->hlid = hlid;
- /* We never send a deauth, mac80211 is in charge of this */
- cmd->reason_opcode = 0;
- cmd->send_deauth_flag = 0;
-
- ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd remove sta");
+ wl1271_error("failed to stop channel switch command");
goto out_free;
}
- /*
- * We are ok with a timeout here. The event is sometimes not sent
- * due to a firmware bug.
- */
- wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID);
-
out_free:
kfree(cmd);
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 5cac95d..b7bd427 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -36,7 +36,15 @@ int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
+int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id);
+int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl);
+int wl12xx_cmd_role_start_sta(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_sta(struct wl1271 *wl);
+int wl12xx_cmd_role_start_ap(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_ap(struct wl1271 *wl);
+int wl12xx_cmd_role_start_ibss(struct wl1271 *wl);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
@@ -56,20 +64,24 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
int wl1271_build_qos_null_data(struct wl1271 *wl);
int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
-int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id);
-int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
+int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid);
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16);
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16);
-int wl1271_cmd_disconnect(struct wl1271 *wl);
-int wl1271_cmd_set_sta_state(struct wl1271 *wl);
-int wl1271_cmd_start_bss(struct wl1271 *wl);
-int wl1271_cmd_stop_bss(struct wl1271 *wl);
-int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
-int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid);
+int wl12xx_roc(struct wl1271 *wl, u8 role_id);
+int wl12xx_croc(struct wl1271 *wl, u8 role_id);
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
+int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_channel_switch(struct wl1271 *wl,
+ struct ieee80211_channel_switch *ch_switch);
+int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -80,25 +92,21 @@ enum wl1271_commands {
CMD_DISABLE_TX = 6,
CMD_SCAN = 8,
CMD_STOP_SCAN = 9,
- CMD_START_JOIN = 11,
CMD_SET_KEYS = 12,
CMD_READ_MEMORY = 13,
CMD_WRITE_MEMORY = 14,
CMD_SET_TEMPLATE = 19,
CMD_TEST = 23,
CMD_NOISE_HIST = 28,
- CMD_LNA_CONTROL = 32,
+ CMD_QUIET_ELEMENT_SET_STATE = 29,
CMD_SET_BCN_MODE = 33,
CMD_MEASUREMENT = 34,
CMD_STOP_MEASUREMENT = 35,
- CMD_DISCONNECT = 36,
CMD_SET_PS_MODE = 37,
CMD_CHANNEL_SWITCH = 38,
CMD_STOP_CHANNEL_SWICTH = 39,
CMD_AP_DISCOVERY = 40,
CMD_STOP_AP_DISCOVERY = 41,
- CMD_SPS_SCAN = 42,
- CMD_STOP_SPS_SCAN = 43,
CMD_HEALTH_CHECK = 45,
CMD_DEBUG = 46,
CMD_TRIGGER_SCAN_TO = 47,
@@ -106,13 +114,30 @@ enum wl1271_commands {
CMD_CONNECTION_SCAN_SSID_CFG = 49,
CMD_START_PERIODIC_SCAN = 50,
CMD_STOP_PERIODIC_SCAN = 51,
- CMD_SET_STA_STATE = 52,
+ CMD_SET_PEER_STATE = 52,
+ CMD_REMAIN_ON_CHANNEL = 53,
+ CMD_CANCEL_REMAIN_ON_CHANNEL = 54,
- /* AP mode commands */
- CMD_BSS_START = 60,
- CMD_BSS_STOP = 61,
- CMD_ADD_STA = 62,
- CMD_REMOVE_STA = 63,
+ CMD_CONFIG_FWLOGGER = 55,
+ CMD_START_FWLOGGER = 56,
+ CMD_STOP_FWLOGGER = 57,
+
+ /* AP commands */
+ CMD_ADD_PEER = 62,
+ CMD_REMOVE_PEER = 63,
+
+ /* Role API */
+ CMD_ROLE_ENABLE = 70,
+ CMD_ROLE_DISABLE = 71,
+ CMD_ROLE_START = 72,
+ CMD_ROLE_STOP = 73,
+
+ /* WIFI Direct */
+ CMD_WFD_START_DISCOVERY = 80,
+ CMD_WFD_STOP_DISCOVERY = 81,
+ CMD_WFD_ATTRIBUTE_CONFIG = 82,
+
+ CMD_NOP = 100,
NUM_COMMANDS,
MAX_COMMAND_ID = 0xFFFF,
@@ -141,21 +166,20 @@ enum cmd_templ {
CMD_TEMPL_CTS, /*
* For CTS-to-self (FastCTS) mechanism
* for BT/WLAN coexistence (SoftGemini). */
- CMD_TEMPL_ARP_RSP,
- CMD_TEMPL_LINK_MEASUREMENT_REPORT,
-
- /* AP-mode specific */
- CMD_TEMPL_AP_BEACON = 13,
+ CMD_TEMPL_AP_BEACON,
CMD_TEMPL_AP_PROBE_RESPONSE,
- CMD_TEMPL_AP_ARP_RSP,
+ CMD_TEMPL_ARP_RSP,
CMD_TEMPL_DEAUTH_AP,
+ CMD_TEMPL_TEMPORARY,
+ CMD_TEMPL_LINK_MEASUREMENT_REPORT,
CMD_TEMPL_MAX = 0xff
};
/* unit ms */
#define WL1271_COMMAND_TIMEOUT 2000
-#define WL1271_CMD_TEMPL_MAX_SIZE 252
+#define WL1271_CMD_TEMPL_DFLT_SIZE 252
+#define WL1271_CMD_TEMPL_MAX_SIZE 548
#define WL1271_EVENT_TIMEOUT 750
struct wl1271_cmd_header {
@@ -187,6 +211,8 @@ enum {
CMD_STATUS_WRONG_NESTING = 19,
CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/
CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/
+ CMD_STATUS_TEMPLATE_OOM = 23,
+ CMD_STATUS_NO_RX_BA_SESSION = 24,
MAX_COMMAND_STATUS = 0xff
};
@@ -204,38 +230,114 @@ enum {
#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
#define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10
-struct wl1271_cmd_join {
+struct wl12xx_cmd_role_enable {
struct wl1271_cmd_header header;
- __le32 bssid_lsb;
- __le16 bssid_msb;
- __le16 beacon_interval; /* in TBTTs */
- __le32 rx_config_options;
- __le32 rx_filter_options;
+ u8 role_id;
+ u8 role_type;
+ u8 mac_address[ETH_ALEN];
+} __packed;
- /*
- * The target uses this field to determine the rate at
- * which to transmit control frame responses (such as
- * ACK or CTS frames).
- */
- __le32 basic_rate_set;
- __le32 supported_rate_set;
- u8 dtim_interval;
- /*
- * bits 0-2: This bitwise field specifies the type
- * of BSS to start or join (BSS_TYPE_*).
- * bit 4: Band - The radio band in which to join
- * or start.
- * 0 - 2.4GHz band
- * 1 - 5GHz band
- * bits 3, 5-7: Reserved
- */
- u8 bss_type;
+struct wl12xx_cmd_role_disable {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 padding[3];
+} __packed;
+
+enum wl12xx_band {
+ WL12XX_BAND_2_4GHZ = 0,
+ WL12XX_BAND_5GHZ = 1,
+ WL12XX_BAND_JAPAN_4_9_GHZ = 2,
+ WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ,
+ WL12XX_BAND_INVALID = 0x7E,
+ WL12XX_BAND_MAX_RADIO = 0x7F,
+};
+
+struct wl12xx_cmd_role_start {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 band;
u8 channel;
- u8 ssid_len;
- u8 ssid[IW_ESSID_MAX_SIZE];
- u8 ctrl; /* JOIN_CMD_CTRL_* */
- u8 reserved[3];
+ u8 padding;
+
+ union {
+ struct {
+ u8 hlid;
+ u8 session;
+ u8 padding_1[54];
+ } __packed device;
+ /* sta & p2p_cli use the same struct */
+ struct {
+ u8 bssid[ETH_ALEN];
+ u8 hlid; /* data hlid */
+ u8 session;
+ __le32 remote_rates; /* remote supported rates */
+
+ /*
+ * The target uses this field to determine the rate at
+ * which to transmit control frame responses (such as
+ * ACK or CTS frames).
+ */
+ __le32 basic_rate_set;
+ __le32 local_rates; /* local supported rates */
+
+ u8 ssid_type;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+ __le16 beacon_interval; /* in TBTTs */
+ } __packed sta;
+ struct {
+ u8 bssid[ETH_ALEN];
+ u8 hlid; /* data hlid */
+ u8 dtim_interval;
+ __le32 remote_rates; /* remote supported rates */
+
+ __le32 basic_rate_set;
+ __le32 local_rates; /* local supported rates */
+
+ u8 ssid_type;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+ __le16 beacon_interval; /* in TBTTs */
+
+ u8 padding_1[4];
+ } __packed ibss;
+ /* ap & p2p_go use the same struct */
+ struct {
+ __le16 aging_period; /* in secs */
+ u8 beacon_expiry; /* in ms */
+ u8 bss_index;
+ /* The host link id for the AP's global queue */
+ u8 global_hlid;
+ /* The host link id for the AP's broadcast queue */
+ u8 broadcast_hlid;
+
+ __le16 beacon_interval; /* in TBTTs */
+
+ __le32 basic_rate_set;
+ __le32 local_rates; /* local supported rates */
+
+ u8 dtim_interval;
+
+ u8 ssid_type;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+ u8 padding_1[5];
+ } __packed ap;
+ };
+} __packed;
+
+struct wl12xx_cmd_role_stop {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 disc_type; /* only STA and P2P_CLI */
+ __le16 reason; /* only STA and P2P_CLI */
} __packed;
struct cmd_enabledisable_path {
@@ -281,8 +383,9 @@ enum wl1271_cmd_ps_mode {
struct wl1271_cmd_ps_params {
struct wl1271_cmd_header header;
+ u8 role_id;
u8 ps_mode; /* STATION_* */
- u8 padding[3];
+ u8 padding[2];
} __packed;
/* HW encryption keys */
@@ -295,6 +398,12 @@ enum wl1271_cmd_key_action {
MAX_KEY_ACTION = 0xffff,
};
+enum wl1271_cmd_lid_key_type {
+ UNICAST_LID_TYPE = 0,
+ BROADCAST_LID_TYPE = 1,
+ WEP_DEFAULT_LID_TYPE = 2
+};
+
enum wl1271_cmd_key_type {
KEY_NONE = 0,
KEY_WEP = 1,
@@ -303,44 +412,7 @@ enum wl1271_cmd_key_type {
KEY_GEM = 4,
};
-/* FIXME: Add description for key-types */
-
-struct wl1271_cmd_set_sta_keys {
- struct wl1271_cmd_header header;
-
- /* Ignored for default WEP key */
- u8 addr[ETH_ALEN];
-
- /* key_action_e */
- __le16 key_action;
-
- __le16 reserved_1;
-
- /* key size in bytes */
- u8 key_size;
-
- /* key_type_e */
- u8 key_type;
- u8 ssid_profile;
-
- /*
- * TKIP, AES: frame's key id field.
- * For WEP default key: key id;
- */
- u8 id;
- u8 reserved_2[6];
- u8 key[MAX_KEY_SIZE];
- __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
- __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __packed;
-
-enum wl1271_cmd_lid_key_type {
- UNICAST_LID_TYPE = 0,
- BROADCAST_LID_TYPE = 1,
- WEP_DEFAULT_LID_TYPE = 2
-};
-
-struct wl1271_cmd_set_ap_keys {
+struct wl1271_cmd_set_keys {
struct wl1271_cmd_header header;
/*
@@ -490,69 +562,46 @@ enum wl1271_disconnect_type {
DISCONNECT_DISASSOC
};
-struct wl1271_cmd_disconnect {
- struct wl1271_cmd_header header;
-
- __le32 rx_config_options;
- __le32 rx_filter_options;
-
- __le16 reason;
- u8 type;
-
- u8 padding;
-} __packed;
-
#define WL1271_CMD_STA_STATE_CONNECTED 1
-struct wl1271_cmd_set_sta_state {
+struct wl12xx_cmd_set_peer_state {
struct wl1271_cmd_header header;
+ u8 hlid;
u8 state;
- u8 padding[3];
+ u8 padding[2];
} __packed;
-enum wl1271_ssid_type {
- SSID_TYPE_PUBLIC = 0,
- SSID_TYPE_HIDDEN = 1
+struct wl12xx_cmd_roc {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 channel;
+ u8 band;
+ u8 padding;
};
-struct wl1271_cmd_bss_start {
+struct wl12xx_cmd_croc {
struct wl1271_cmd_header header;
- /* wl1271_ssid_type */
- u8 ssid_type;
- u8 ssid_len;
- u8 ssid[IW_ESSID_MAX_SIZE];
- u8 padding_1[2];
+ u8 role_id;
+ u8 padding[3];
+};
- /* Basic rate set */
- __le32 basic_rate_set;
- /* Aging period in seconds*/
- __le16 aging_period;
+enum wl12xx_ssid_type {
+ WL12XX_SSID_TYPE_PUBLIC = 0,
+ WL12XX_SSID_TYPE_HIDDEN = 1,
+ WL12XX_SSID_TYPE_ANY = 2,
+};
- /*
- * This field specifies the time between target beacon
- * transmission times (TBTTs), in time units (TUs).
- * Valid values are 1 to 1024.
- */
- __le16 beacon_interval;
- u8 bssid[ETH_ALEN];
- u8 bss_index;
- /* Radio band */
- u8 band;
- u8 channel;
- /* The host link id for the AP's global queue */
- u8 global_hlid;
- /* The host link id for the AP's broadcast queue */
- u8 broadcast_hlid;
- /* DTIM count */
- u8 dtim_interval;
- /* Beacon expiry time in ms */
- u8 beacon_expiry;
- u8 padding_2[3];
-} __packed;
+enum wl1271_psd_type {
+ WL1271_PSD_LEGACY = 0,
+ WL1271_PSD_UPSD_TRIGGER = 1,
+ WL1271_PSD_LEGACY_PSPOLL = 2,
+ WL1271_PSD_SAPSD = 3
+};
-struct wl1271_cmd_add_sta {
+struct wl12xx_cmd_add_peer {
struct wl1271_cmd_header header;
u8 addr[ETH_ALEN];
@@ -566,7 +615,7 @@ struct wl1271_cmd_add_sta {
u8 padding1;
} __packed;
-struct wl1271_cmd_remove_sta {
+struct wl12xx_cmd_remove_peer {
struct wl1271_cmd_header header;
u8 hlid;
@@ -575,4 +624,77 @@ struct wl1271_cmd_remove_sta {
u8 padding1;
} __packed;
+/*
+ * Continuous mode - packets are transferred to the host periodically
+ * via the data path.
+ * On demand - Log messages are stored in a cyclic buffer in the
+ * firmware, and only transferred to the host when explicitly requested
+ */
+enum wl12xx_fwlogger_log_mode {
+ WL12XX_FWLOG_CONTINUOUS,
+ WL12XX_FWLOG_ON_DEMAND
+};
+
+/* Include/exclude timestamps from the log messages */
+enum wl12xx_fwlogger_timestamp {
+ WL12XX_FWLOG_TIMESTAMP_DISABLED,
+ WL12XX_FWLOG_TIMESTAMP_ENABLED
+};
+
+/*
+ * Logs can be routed to the debug pinouts (where available), to the host bus
+ * (SDIO/SPI), or dropped
+ */
+enum wl12xx_fwlogger_output {
+ WL12XX_FWLOG_OUTPUT_NONE,
+ WL12XX_FWLOG_OUTPUT_DBG_PINS,
+ WL12XX_FWLOG_OUTPUT_HOST,
+};
+
+struct wl12xx_cmd_config_fwlog {
+ struct wl1271_cmd_header header;
+
+ /* See enum wl12xx_fwlogger_log_mode */
+ u8 logger_mode;
+
+ /* Minimum log level threshold */
+ u8 log_severity;
+
+ /* Include/exclude timestamps from the log messages */
+ u8 timestamp;
+
+ /* See enum wl1271_fwlogger_output */
+ u8 output;
+
+ /* Regulates the frequency of log messages */
+ u8 threshold;
+
+ u8 padding[3];
+} __packed;
+
+struct wl12xx_cmd_start_fwlog {
+ struct wl1271_cmd_header header;
+} __packed;
+
+struct wl12xx_cmd_stop_fwlog {
+ struct wl1271_cmd_header header;
+} __packed;
+
+struct wl12xx_cmd_channel_switch {
+ struct wl1271_cmd_header header;
+
+ /* The new serving channel */
+ u8 channel;
+ /* Relative time of the serving channel switch in TBTT units */
+ u8 switch_time;
+ /* 1: Suspend TX till switch time; 0: Do not suspend TX */
+ u8 tx_suspend;
+ /* 1: Flush TX at switch time; 0: Do not flush */
+ u8 flush;
+} __packed;
+
+struct wl12xx_cmd_stop_channel_switch {
+ struct wl1271_cmd_header header;
+} __packed;
+
#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index c83fefb..04bb8fb 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -99,40 +99,75 @@ enum {
enum {
/*
- * PER threshold in PPM of the BT voice
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT master basic rate
*
- * Range: 0 - 10000000
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_BT_PER_THRESHOLD = 0,
+ CONF_SG_ACL_BT_MASTER_MIN_BR = 0,
+ CONF_SG_ACL_BT_MASTER_MAX_BR,
/*
- * Number of consequent RX_ACTIVE activities to override BT voice
- * frames to ensure WLAN connection
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT slave basic rate
*
- * Range: 0 - 100
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_HV3_MAX_OVERRIDE,
+ CONF_SG_ACL_BT_SLAVE_MIN_BR,
+ CONF_SG_ACL_BT_SLAVE_MAX_BR,
/*
- * Defines the PER threshold of the BT voice
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT master EDR
*
- * Range: 0 - 65000
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_BT_NFS_SAMPLE_INTERVAL,
+ CONF_SG_ACL_BT_MASTER_MIN_EDR,
+ CONF_SG_ACL_BT_MASTER_MAX_EDR,
/*
- * Defines the load ratio of BT
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT slave EDR
*
- * Range: 0 - 100 (%)
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_BT_LOAD_RATIO,
+ CONF_SG_ACL_BT_SLAVE_MIN_EDR,
+ CONF_SG_ACL_BT_SLAVE_MAX_EDR,
/*
- * Defines whether the SG will force WLAN host to enter/exit PSM
+ * The maximum time WLAN can gain the antenna
+ * in WLAN PSM / BT master/slave BR
*
- * Range: 1 - SG can force, 0 - host handles PSM
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_AUTO_PS_MODE,
+ CONF_SG_ACL_WLAN_PS_MASTER_BR,
+ CONF_SG_ACL_WLAN_PS_SLAVE_BR,
+
+ /*
+ * The maximum time WLAN can gain the antenna
+ * in WLAN PSM / BT master/slave EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_ACL_WLAN_PS_MASTER_EDR,
+ CONF_SG_ACL_WLAN_PS_SLAVE_EDR,
+
+ /* TODO: explain these values */
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR,
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR,
+
+ CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR,
+ CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR,
+ CONF_SG_ACL_PASSIVE_SCAN_BT_BR,
+ CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR,
+ CONF_SG_ACL_PASSIVE_SCAN_BT_EDR,
+ CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR,
/*
* Compensation percentage of probe requests when scan initiated
@@ -151,102 +186,70 @@ enum {
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
/*
- * Defines antenna configuration (single/dual antenna)
- *
- * Range: 0 - single antenna, 1 - dual antenna
- */
- CONF_SG_ANTENNA_CONFIGURATION,
-
- /*
- * The threshold (percent) of max consequtive beacon misses before
- * increasing priority of beacon reception.
- *
- * Range: 0 - 100 (%)
- */
- CONF_SG_BEACON_MISS_PERCENT,
-
- /*
- * The rate threshold below which receiving a data frame from the AP
- * will increase the priority of the data frame above BT traffic.
- *
- * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54
- */
- CONF_SG_RATE_ADAPT_THRESH,
-
- /*
- * Not used currently.
+ * Compensation percentage of WLAN active scan window if initiated
+ * during BT A2DP
*
- * Range: 0
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_RATE_ADAPT_SNR,
+ CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT master basic rate
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP BR
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR,
/*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT master basic rate
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP EDR
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT slave basic rate
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT voice
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
- /*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT slave basic rate
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
+ /* TODO: explain these values */
+ CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
+ CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN,
+ CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT master EDR
+ * Defines whether the SG will force WLAN host to enter/exit PSM
*
- * Range: 0 - 255 (ms)
+ * Range: 1 - SG can force, 0 - host handles PSM
*/
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
+ CONF_SG_STA_FORCE_PS_IN_BT_SCO,
/*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT master EDR
+ * Defines antenna configuration (single/dual antenna)
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - single antenna, 1 - dual antenna
*/
- CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
+ CONF_SG_ANTENNA_CONFIGURATION,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT slave EDR
+ * The threshold (percent) of max consecutive beacon misses before
+ * increasing priority of beacon reception.
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 100 (%)
*/
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
+ CONF_SG_BEACON_MISS_PERCENT,
/*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT slave EDR
+ * Protection time of the DHCP procedure.
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 100000 (ms)
*/
- CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
+ CONF_SG_DHCP_TIME,
/*
* RX guard time before the beginning of a new BT voice frame during
@@ -273,166 +276,59 @@ enum {
*/
CONF_SG_ADAPTIVE_RXT_TXT,
- /*
- * The used WLAN legacy service period during active BT ACL link
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_PS_POLL_TIMEOUT,
-
- /*
- * The used WLAN UPSD service period during active BT ACL link
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_UPSD_TIMEOUT,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN Active / BT master EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
- CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
-
- /*
- * The maximum time WLAN can gain the antenna for
- * in WLAN Active / BT master EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN Active / BT slave EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
- CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
+ /* TODO: explain this value */
+ CONF_SG_GENERAL_USAGE_BIT_MAP,
/*
- * The maximum time WLAN can gain the antenna for
- * in WLAN Active / BT slave EDR
+ * Number of consecutive BT voice frames not interrupted by WLAN
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 100
*/
- CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
+ CONF_SG_HV3_MAX_SERVED,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN Active / BT basic rate
+ * The used WLAN legacy service period during active BT ACL link
*
* Range: 0 - 255 (ms)
*/
- CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
- CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
+ CONF_SG_PS_POLL_TIMEOUT,
/*
- * The maximum time WLAN can gain the antenna for
- * in WLAN Active / BT basic rate
+ * The used WLAN UPSD service period during active BT ACL link
*
* Range: 0 - 255 (ms)
*/
- CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT voice
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT A2DP
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
-
- /*
- * Fixed time ensured for BT traffic to gain the antenna during WLAN
- * passive scan.
- *
- * Range: 0 - 1000 ms
- */
- CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME,
-
- /*
- * Fixed time ensured for WLAN traffic to gain the antenna during WLAN
- * passive scan.
- *
- * Range: 0 - 1000 ms
- */
- CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
+ CONF_SG_UPSD_TIMEOUT,
- /*
- * Number of consequent BT voice frames not interrupted by WLAN
- *
- * Range: 0 - 100
- */
- CONF_SG_HV3_MAX_SERVED,
+ CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
+ CONF_SG_STA_RX_WINDOW_AFTER_DTIM,
+ CONF_SG_STA_CONNECTION_PROTECTION_TIME,
- /*
- * Protection time of the DHCP procedure.
- *
- * Range: 0 - 100000 (ms)
- */
- CONF_SG_DHCP_TIME,
+ /* AP params */
+ CONF_AP_BEACON_MISS_TX,
+ CONF_AP_RX_WINDOW_AFTER_BEACON,
+ CONF_AP_BEACON_WINDOW_INTERVAL,
+ CONF_AP_CONNECTION_PROTECTION_TIME,
+ CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
+ CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
- /*
- * Compensation percentage of WLAN active scan window if initiated
- * during BT A2DP
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
CONF_SG_TEMP_PARAM_1,
CONF_SG_TEMP_PARAM_2,
CONF_SG_TEMP_PARAM_3,
CONF_SG_TEMP_PARAM_4,
CONF_SG_TEMP_PARAM_5,
-
- /*
- * AP beacon miss
- *
- * Range: 0 - 255
- */
- CONF_SG_AP_BEACON_MISS_TX,
-
- /*
- * AP RX window length
- *
- * Range: 0 - 50
- */
- CONF_SG_RX_WINDOW_LENGTH,
-
- /*
- * AP connection protection time
- *
- * Range: 0 - 5000
- */
- CONF_SG_AP_CONNECTION_PROTECTION_TIME,
-
CONF_SG_TEMP_PARAM_6,
CONF_SG_TEMP_PARAM_7,
CONF_SG_TEMP_PARAM_8,
CONF_SG_TEMP_PARAM_9,
CONF_SG_TEMP_PARAM_10,
- CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1,
- CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1,
-
+ CONF_SG_PARAMS_MAX,
CONF_SG_PARAMS_ALL = 0xff
};
struct conf_sg_settings {
- u32 sta_params[CONF_SG_STA_PARAMS_MAX];
- u32 ap_params[CONF_SG_AP_PARAMS_MAX];
+ u32 params[CONF_SG_PARAMS_MAX];
u8 state;
};
@@ -520,13 +416,17 @@ struct conf_rx_settings {
u8 queue_type;
};
-#define CONF_TX_MAX_RATE_CLASSES 8
+#define CONF_TX_MAX_RATE_CLASSES 10
#define CONF_TX_RATE_MASK_UNSPECIFIED 0
#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS)
#define CONF_TX_RATE_RETRY_LIMIT 10
+/* basic rates for p2p operations (probe req/resp, etc.) */
+#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \
+ CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS)
+
/*
* Rates supported for data packets when operating as AP. Note the absence
* of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
@@ -545,6 +445,11 @@ struct conf_rx_settings {
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
CONF_HW_BIT_RATE_54MBPS)
+#define CONF_TX_MCS_RATES (CONF_HW_BIT_RATE_MCS_0 | \
+ CONF_HW_BIT_RATE_MCS_1 | CONF_HW_BIT_RATE_MCS_2 | \
+ CONF_HW_BIT_RATE_MCS_3 | CONF_HW_BIT_RATE_MCS_4 | \
+ CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \
+ CONF_HW_BIT_RATE_MCS_7)
/*
* Default rates for management traffic when operating in AP mode. This
@@ -553,12 +458,10 @@ struct conf_rx_settings {
#define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
-/*
- * Default rates for working as IBSS. use 11b rates
- */
+/* default rates for working as IBSS (11b and OFDM) */
#define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
- CONF_HW_BIT_RATE_11MBPS);
+ CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES);
struct conf_tx_rate_class {
@@ -661,6 +564,9 @@ struct conf_tx_ac_category {
#define CONF_TX_MAX_TID_COUNT 8
+/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */
+#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F
+
enum {
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/
@@ -713,8 +619,16 @@ struct conf_tx_settings {
/*
* AP-mode - allow this number of TX retries to a station before an
* event is triggered from FW.
+ * In AP-mode the hlids of unreachable stations are given in the
+ * "sta_tx_retry_exceeded" member in the event mailbox.
+ */
+ u8 max_tx_retries;
+
+ /*
+ * AP-mode - after this number of seconds a connected station is
+ * considered inactive.
*/
- u16 ap_max_tx_retries;
+ u16 ap_aging_period;
/*
* Configuration for TID parameters.
@@ -905,7 +819,7 @@ struct conf_conn_settings {
struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT];
/*
- * The number of consequtive beacons to lose, before the firmware
+ * The number of consecutive beacons to lose, before the firmware
* becomes out of synch.
*
* Range: u32
@@ -943,7 +857,7 @@ struct conf_conn_settings {
u8 rx_broadcast_in_ps;
/*
- * Consequtive PS Poll failures before sending event to driver
+ * Consecutive PS Poll failures before sending event to driver
*
* Range: u8
*/
@@ -1004,14 +918,6 @@ struct conf_conn_settings {
u8 psm_entry_nullfunc_retries;
/*
- * Specifies the time to linger in active mode after successfully
- * transmitting the PSM entry null-func frame.
- *
- * Range 0 - 255 TU's
- */
- u8 psm_entry_hangover_period;
-
- /*
*
* Specifies the interval of the connection keep-alive null-func
* frame in ms.
@@ -1191,8 +1097,12 @@ struct conf_rf_settings {
};
struct conf_ht_setting {
- u16 tx_ba_win_size;
+ u8 rx_ba_win_size;
+ u8 tx_ba_win_size;
u16 inactivity_timeout;
+
+ /* bitmap of enabled TIDs for TX BA sessions */
+ u8 tx_ba_tid_bitmap;
};
struct conf_memory_settings {
@@ -1248,6 +1158,92 @@ struct conf_fm_coex {
u8 swallow_clk_diff;
};
+struct conf_rx_streaming_settings {
+ /*
+ * RX Streaming duration (in msec) from last tx/rx
+ *
+ * Range: u32
+ */
+ u32 duration;
+
+ /*
+ * Bitmap of tids to be polled during RX streaming.
+ * (Note: it doesn't look like it really matters)
+ *
+ * Range: 0x1-0xff
+ */
+ u8 queues;
+
+ /*
+ * RX Streaming interval.
+ * (Note:this value is also used as the rx streaming timeout)
+ * Range: 0 (disabled), 10 - 100
+ */
+ u8 interval;
+
+ /*
+ * enable rx streaming also when there is no coex activity
+ */
+ u8 always;
+};
+
+struct conf_fwlog {
+ /* Continuous or on-demand */
+ u8 mode;
+
+ /*
+ * Number of memory blocks dedicated for the FW logger
+ *
+ * Range: 1-3, or 0 to disable the FW logger
+ */
+ u8 mem_blocks;
+
+ /* Minimum log level threshold */
+ u8 severity;
+
+ /* Include/exclude timestamps from the log messages */
+ u8 timestamp;
+
+ /* See enum wl1271_fwlogger_output */
+ u8 output;
+
+ /* Regulates the frequency of log messages */
+ u8 threshold;
+};
+
+#define ACX_RATE_MGMT_NUM_OF_RATES 13
+struct conf_rate_policy_settings {
+ u16 rate_retry_score;
+ u16 per_add;
+ u16 per_th1;
+ u16 per_th2;
+ u16 max_per;
+ u8 inverse_curiosity_factor;
+ u8 tx_fail_low_th;
+ u8 tx_fail_high_th;
+ u8 per_alpha_shift;
+ u8 per_add_shift;
+ u8 per_beta1_shift;
+ u8 per_beta2_shift;
+ u8 rate_check_up;
+ u8 rate_check_down;
+ u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
+};
+
+struct conf_hangover_settings {
+ u32 recover_time;
+ u8 hangover_period;
+ u8 dynamic_mode;
+ u8 early_termination_mode;
+ u8 max_period;
+ u8 min_period;
+ u8 increase_delta;
+ u8 decrease_delta;
+ u8 quiet_time;
+ u8 increase_time;
+ u8 window_size;
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
@@ -1263,6 +1259,10 @@ struct conf_drv_settings {
struct conf_memory_settings mem_wl127x;
struct conf_memory_settings mem_wl128x;
struct conf_fm_coex fm_coex;
+ struct conf_rx_streaming_settings rx_streaming;
+ struct conf_fwlog fwlog;
+ struct conf_rate_policy_settings rate;
+ struct conf_hangover_settings hangover;
u8 hci_io_ds;
};
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index f1f8df9..3999fd5 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -30,6 +30,7 @@
#include "acx.h"
#include "ps.h"
#include "io.h"
+#include "tx.h"
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
@@ -71,6 +72,14 @@ static const struct file_operations name## _ops = { \
if (!entry || IS_ERR(entry)) \
goto err; \
+#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
+ do { \
+ entry = debugfs_create_file(#name, 0400, parent, \
+ wl, &prefix## _## name## _ops); \
+ if (!entry || IS_ERR(entry)) \
+ goto err; \
+ } while (0);
+
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \
static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
@@ -225,7 +234,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
char buf[20];
int res;
- queue_len = wl->tx_queue_count;
+ queue_len = wl1271_tx_total_queue_count(wl);
res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
@@ -256,18 +265,10 @@ static ssize_t gpio_power_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len)) {
- return -EFAULT;
- }
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value in gpio_power");
return -EINVAL;
@@ -298,7 +299,7 @@ static ssize_t start_recovery_write(struct file *file,
struct wl1271 *wl = file->private_data;
mutex_lock(&wl->mutex);
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
mutex_unlock(&wl->mutex);
return count;
@@ -331,17 +332,21 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(tx_blocks_available);
DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
DRIVER_STATE_PRINT_INT(tx_frames_cnt);
DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
- DRIVER_STATE_PRINT_INT(tx_queue_count);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
DRIVER_STATE_PRINT_INT(tx_packets_count);
DRIVER_STATE_PRINT_INT(tx_results_count);
DRIVER_STATE_PRINT_LHEX(flags);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]);
- DRIVER_STATE_PRINT_INT(tx_security_last_seq);
+ DRIVER_STATE_PRINT_INT(tx_blocks_freed);
+ DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
DRIVER_STATE_PRINT_INT(rx_counter);
DRIVER_STATE_PRINT_INT(session_counter);
DRIVER_STATE_PRINT_INT(state);
@@ -354,9 +359,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(beacon_int);
DRIVER_STATE_PRINT_INT(psm_entry_retry);
DRIVER_STATE_PRINT_INT(ps_poll_failures);
- DRIVER_STATE_PRINT_HEX(filters);
- DRIVER_STATE_PRINT_HEX(rx_config);
- DRIVER_STATE_PRINT_HEX(rx_filter);
DRIVER_STATE_PRINT_INT(power_level);
DRIVER_STATE_PRINT_INT(rssi_thold);
DRIVER_STATE_PRINT_INT(last_rssi_event);
@@ -417,17 +419,10 @@ static ssize_t dtim_interval_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value for dtim_interval");
return -EINVAL;
@@ -482,17 +477,10 @@ static ssize_t beacon_interval_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value for beacon_interval");
return -EINVAL;
@@ -527,11 +515,156 @@ static const struct file_operations beacon_interval_ops = {
.llseek = default_llseek,
};
+static ssize_t rx_streaming_interval_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
+ if (ret < 0) {
+ wl1271_warning("illegal value in rx_streaming_interval!");
+ return -EINVAL;
+ }
+
+ /* valid values: 0, 10-100 */
+ if (value && (value < 10 || value > 100)) {
+ wl1271_warning("value is not in range!");
+ return -ERANGE;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ wl->conf.rx_streaming.interval = value;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1271_recalc_rx_streaming(wl);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static ssize_t rx_streaming_interval_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ return wl1271_format_buffer(userbuf, count, ppos,
+ "%d\n", wl->conf.rx_streaming.interval);
+}
+
+static const struct file_operations rx_streaming_interval_ops = {
+ .read = rx_streaming_interval_read,
+ .write = rx_streaming_interval_write,
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
+};
+
+static ssize_t rx_streaming_always_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
+ if (ret < 0) {
+ wl1271_warning("illegal value in rx_streaming_write!");
+ return -EINVAL;
+ }
+
+ /* valid values: 0, 10-100 */
+ if (!(value == 0 || value == 1)) {
+ wl1271_warning("value is not in valid!");
+ return -EINVAL;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ wl->conf.rx_streaming.always = value;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1271_recalc_rx_streaming(wl);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static ssize_t rx_streaming_always_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ return wl1271_format_buffer(userbuf, count, ppos,
+ "%d\n", wl->conf.rx_streaming.always);
+}
+
+static const struct file_operations rx_streaming_always_ops = {
+ .read = rx_streaming_always_read,
+ .write = rx_streaming_always_write,
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
+};
+
+static ssize_t beacon_filtering_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ char buf[10];
+ size_t len;
+ unsigned long value;
+ int ret;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret < 0) {
+ wl1271_warning("illegal value for beacon_filtering!");
+ return -EINVAL;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_beacon_filter_opt(wl, !!value);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static const struct file_operations beacon_filtering_ops = {
+ .write = beacon_filtering_write,
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
+};
+
static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
int ret = 0;
- struct dentry *entry, *stats;
+ struct dentry *entry, *stats, *streaming;
stats = debugfs_create_dir("fw-statistics", rootdir);
if (!stats || IS_ERR(stats)) {
@@ -639,6 +772,15 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(driver_state, rootdir);
DEBUGFS_ADD(dtim_interval, rootdir);
DEBUGFS_ADD(beacon_interval, rootdir);
+ DEBUGFS_ADD(beacon_filtering, rootdir);
+
+ streaming = debugfs_create_dir("rx_streaming", rootdir);
+ if (!streaming || IS_ERR(streaming))
+ goto err;
+
+ DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
+ DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
+
return 0;
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index c3c554c..674ad2a 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -133,10 +133,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
if (ret < 0)
break;
- /* enable beacon early termination */
- ret = wl1271_acx_bet_enable(wl, true);
- if (ret < 0)
- break;
+ /*
+ * BET has only a minor effect in 5GHz and masks
+ * channel switch IEs, so we only enable BET on 2.4GHz
+ */
+ if (wl->band == IEEE80211_BAND_2GHZ)
+ /* enable beacon early termination */
+ ret = wl1271_acx_bet_enable(wl, true);
if (wl->ps_compl) {
complete(wl->ps_compl);
@@ -168,6 +171,43 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
wl->last_rssi_event = event;
}
+static void wl1271_stop_ba_event(struct wl1271 *wl)
+{
+ if (wl->bss_type != BSS_TYPE_AP_BSS) {
+ if (!wl->ba_rx_bitmap)
+ return;
+ ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap,
+ wl->bssid);
+ } else {
+ int i;
+ struct wl1271_link *lnk;
+ for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) {
+ lnk = &wl->links[i];
+ if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
+ continue;
+
+ ieee80211_stop_rx_ba_session(wl->vif,
+ lnk->ba_bitmap,
+ lnk->addr);
+ }
+ }
+}
+
+static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
+ u8 enable)
+{
+ if (enable) {
+ /* disable dynamic PS when requested by the firmware */
+ ieee80211_disable_dyn_ps(wl->vif);
+ set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
+ } else {
+ ieee80211_enable_dyn_ps(wl->vif);
+ clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
+ wl1271_recalc_rx_streaming(wl);
+ }
+
+}
+
static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
{
wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -181,6 +221,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
u32 vector;
bool beacon_loss = false;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+ bool disconnect_sta = false;
+ unsigned long sta_bitmap = 0;
wl1271_event_mbox_dump(mbox);
@@ -211,14 +253,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
- /* disable dynamic PS when requested by the firmware */
if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
- wl->bss_type == BSS_TYPE_STA_BSS) {
- if (mbox->soft_gemini_sense_info)
- ieee80211_disable_dyn_ps(wl->vif);
- else
- ieee80211_enable_dyn_ps(wl->vif);
- }
+ wl->bss_type == BSS_TYPE_STA_BSS)
+ wl12xx_event_soft_gemini_sense(wl,
+ mbox->soft_gemini_sense_info);
/*
* The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
@@ -252,12 +290,77 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_event_rssi_trigger(wl, mbox);
}
- if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
+ if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) {
+ wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
+ "ba_allowed = 0x%x", mbox->rx_ba_allowed);
+
+ wl->ba_allowed = !!mbox->rx_ba_allowed;
+
+ if (wl->vif && !wl->ba_allowed)
+ wl1271_stop_ba_event(wl);
+ }
+
+ if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) {
+ wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
+ "status = 0x%x",
+ mbox->channel_switch_status);
+ /*
+ * That event uses for two cases:
+ * 1) channel switch complete with status=0
+ * 2) channel switch failed status=1
+ */
+ if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) &&
+ (wl->vif))
+ ieee80211_chswitch_done(wl->vif,
+ mbox->channel_switch_status ? false : true);
+ }
+
+ if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif)
wl1271_tx_dummy_packet(wl);
}
+ /*
+ * "TX retries exceeded" has a different meaning according to mode.
+ * In AP mode the offending station is disconnected.
+ */
+ if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) {
+ wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
+ sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
+ disconnect_sta = true;
+ }
+
+ if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
+ wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
+ sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
+ disconnect_sta = true;
+ }
+
+ if (is_ap && disconnect_sta) {
+ u32 num_packets = wl->conf.tx.max_tx_retries;
+ struct ieee80211_sta *sta;
+ const u8 *addr;
+ int h;
+
+ for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
+ h < AP_MAX_LINKS;
+ h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
+ if (!wl1271_is_active_sta(wl, h))
+ continue;
+
+ addr = wl->links[h].addr;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(wl->vif, addr);
+ if (sta) {
+ wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
+ ieee80211_report_low_ack(sta, num_packets);
+ }
+ rcu_read_unlock();
+ }
+ }
+
if (wl->vif && beacon_loss)
ieee80211_connection_loss(wl->vif);
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index b6cf06e..49c1a0e 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -49,29 +49,27 @@ enum {
MEASUREMENT_START_EVENT_ID = BIT(8),
MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
SCAN_COMPLETE_EVENT_ID = BIT(10),
- SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11),
+ WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
PS_REPORT_EVENT_ID = BIT(13),
PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
DISCONNECT_EVENT_COMPLETE_ID = BIT(15),
- JOIN_EVENT_COMPLETE_ID = BIT(16),
+ /* BIT(16) is reserved */
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
- ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
- /* STA: dummy paket for dynamic mem blocks */
- DUMMY_PACKET_EVENT_ID = BIT(21),
- /* AP: STA remove complete */
- STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
+ MAX_TX_RETRY_EVENT_ID = BIT(20),
+ DUMMY_PACKET_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
- SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
+ CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
- DBG_EVENT_ID = BIT(26),
- HEALTH_CHECK_REPLY_EVENT_ID = BIT(27),
+ INACTIVE_STA_EVENT_ID = BIT(26),
+ PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27),
PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
- BA_SESSION_TEAR_DOWN_EVENT_ID = BIT(30),
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
+ REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31),
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
};
@@ -80,15 +78,6 @@ enum {
EVENT_ENTER_POWER_SAVE_SUCCESS,
};
-struct event_debug_report {
- u8 debug_event_id;
- u8 num_params;
- __le16 pad;
- __le32 report_1;
- __le32 report_2;
- __le32 report_3;
-} __packed;
-
#define NUM_OF_RSSI_SNR_TRIGGERS 8
struct event_mailbox {
@@ -97,32 +86,45 @@ struct event_mailbox {
__le32 reserved_1;
__le32 reserved_2;
- u8 dbg_event_id;
- u8 num_relevant_params;
- __le16 reserved_3;
- __le32 event_report_p1;
- __le32 event_report_p2;
- __le32 event_report_p3;
-
u8 number_of_scan_results;
u8 scan_tag;
- u8 reserved_4[2];
- __le32 compl_scheduled_scan_status;
+ u8 completed_scan_status;
+ u8 reserved_3;
- __le16 scheduled_scan_attended_channels;
u8 soft_gemini_sense_info;
u8 soft_gemini_protective_info;
s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
u8 channel_switch_status;
u8 scheduled_scan_status;
u8 ps_status;
+ /* tuned channel (roc) */
+ u8 roc_channel;
- /* AP FW only */
- u8 hlid_removed;
+ __le16 hlid_removed_bitmap;
+
+ /* bitmap of aged stations (by HLID) */
__le16 sta_aging_status;
+
+ /* bitmap of stations (by HLID) which exceeded max tx retries */
__le16 sta_tx_retry_exceeded;
- u8 reserved_5[24];
+ /* discovery completed results */
+ u8 discovery_tag;
+ u8 number_of_preq_results;
+ u8 number_of_prsp_results;
+ u8 reserved_5;
+
+ /* rx ba constraint */
+ u8 role_id; /* 0xFF means any role. */
+ u8 rx_ba_allowed;
+ u8 reserved_6[2];
+
+ u8 ps_poll_delivery_failure_role_ids;
+ u8 stopped_role_ids;
+ u8 started_role_ids;
+ u8 change_auto_mode_timeout;
+
+ u8 reserved_7[12];
} __packed;
int wl1271_event_unmask(struct wl1271 *wl);
@@ -130,4 +132,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
void wl1271_pspoll_work(struct work_struct *work);
+/* Functions from main.c */
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
+
#endif
diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h
index 1420c84..4cf9ecc 100644
--- a/drivers/net/wireless/wl12xx/ini.h
+++ b/drivers/net/wireless/wl12xx/ini.h
@@ -24,6 +24,9 @@
#ifndef __INI_H__
#define __INI_H__
+#define GENERAL_SETTINGS_DRPW_LPD 0xc0
+#define SCRATCH_ENABLE_LPD BIT(25)
+
#define WL1271_INI_MAX_SMART_REFLEX_PARAM 16
struct wl1271_ini_general_params {
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index a8f4f15..04db64c 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -39,13 +39,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
/* send empty templates for fw memory reservation */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
- WL1271_CMD_TEMPL_MAX_SIZE,
+ WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
+ NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0,
WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -70,15 +70,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
- sizeof
- (struct wl12xx_probe_resp_template),
+ WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
- sizeof
- (struct wl12xx_beacon_template),
+ WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -92,7 +90,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
- WL1271_CMD_TEMPL_MAX_SIZE, i,
+ WL1271_CMD_TEMPL_DFLT_SIZE, i,
WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -105,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
{
struct wl12xx_disconn_template *tmpl;
int ret;
+ u32 rate;
tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
if (!tmpl) {
@@ -115,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_DEAUTH);
+ rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
- tmpl, sizeof(*tmpl), 0,
- wl1271_tx_min_rate_get(wl));
+ tmpl, sizeof(*tmpl), 0, rate);
out:
kfree(tmpl);
@@ -128,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
{
struct ieee80211_hdr_3addr *nullfunc;
int ret;
+ u32 rate;
nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
if (!nullfunc) {
@@ -144,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
+ rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
- sizeof(*nullfunc), 0,
- wl1271_tx_min_rate_get(wl));
+ sizeof(*nullfunc), 0, rate);
out:
kfree(nullfunc);
@@ -157,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
{
struct ieee80211_qos_hdr *qosnull;
int ret;
+ u32 rate;
qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
if (!qosnull) {
@@ -173,9 +174,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
+ rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
- sizeof(*qosnull), 0,
- wl1271_tx_min_rate_get(wl));
+ sizeof(*qosnull), 0, rate);
out:
kfree(qosnull);
@@ -191,15 +192,13 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
* reserve memory for later.
*/
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
- sizeof
- (struct wl12xx_probe_resp_template),
+ WL1271_CMD_TEMPL_MAX_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
- sizeof
- (struct wl12xx_beacon_template),
+ WL1271_CMD_TEMPL_MAX_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -227,7 +226,7 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
return 0;
}
-static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
+static int wl12xx_init_rx_config(struct wl1271 *wl)
{
int ret;
@@ -235,10 +234,6 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
if (ret < 0)
return ret;
- ret = wl1271_acx_rx_config(wl, config, filter);
- if (ret < 0)
- return ret;
-
return 0;
}
@@ -285,10 +280,7 @@ int wl1271_init_pta(struct wl1271 *wl)
{
int ret;
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- ret = wl1271_acx_ap_sg_cfg(wl);
- else
- ret = wl1271_acx_sta_sg_cfg(wl);
+ ret = wl12xx_acx_sg_cfg(wl);
if (ret < 0)
return ret;
@@ -321,6 +313,20 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
return 0;
}
+static int wl12xx_init_fwlog(struct wl1271 *wl)
+{
+ int ret;
+
+ if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
+ return 0;
+
+ ret = wl12xx_cmd_config_fwlog(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int wl1271_sta_hw_init(struct wl1271 *wl)
{
int ret;
@@ -378,7 +384,12 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_sta_mem_cfg(wl);
+ ret = wl12xx_acx_mem_cfg(wl);
+ if (ret < 0)
+ return ret;
+
+ /* Configure the FW logger */
+ ret = wl12xx_init_fwlog(wl);
if (ret < 0)
return ret;
@@ -389,12 +400,6 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
{
int ret, i;
- ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
- if (ret < 0) {
- wl1271_warning("couldn't set default key");
- return ret;
- }
-
/* disable all keep-alive templates */
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_acx_keep_alive_config(wl, i,
@@ -428,11 +433,16 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_max_tx_retry(wl);
+ ret = wl1271_acx_ap_max_tx_retry(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0)
return ret;
- ret = wl1271_acx_ap_mem_cfg(wl);
+ /* initialize Tx power */
+ ret = wl1271_acx_tx_power(wl, wl->power_level);
if (ret < 0)
return ret;
@@ -459,7 +469,7 @@ int wl1271_ap_init_templates(struct wl1271 *wl)
* when operating as AP we want to receive external beacons for
* configuring ERP protection.
*/
- ret = wl1271_acx_set_ap_beacon_filter(wl, false);
+ ret = wl1271_acx_beacon_filter_opt(wl, false);
if (ret < 0)
return ret;
@@ -491,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return ret;
/* use the min basic rate for AP broadcast/multicast */
- rc.enabled_rates = wl1271_tx_min_rate_get(wl);
+ rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
rc.short_retry_limit = 10;
rc.long_retry_limit = 10;
rc.aflags = 0;
@@ -508,6 +518,9 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
else
supported_rates = CONF_TX_AP_ENABLED_RATES;
+ /* unconditionally enable HT rates */
+ supported_rates |= CONF_TX_MCS_RATES;
+
/* configure unicast TX rate classes */
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
rc.enabled_rates = supported_rates;
@@ -522,40 +535,24 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return 0;
}
-static void wl1271_check_ba_support(struct wl1271 *wl)
-{
- /* validate FW cose ver x.x.x.50-60.x */
- if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
- (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
- wl->ba_support = true;
- return;
- }
-
- wl->ba_support = false;
-}
-
static int wl1271_set_ba_policies(struct wl1271 *wl)
{
- u8 tid_index;
- int ret = 0;
-
/* Reset the BA RX indicators */
wl->ba_rx_bitmap = 0;
+ wl->ba_allowed = true;
+ wl->ba_rx_session_count = 0;
+
+ /* BA is supported in STA/AP modes */
+ if (wl->bss_type != BSS_TYPE_AP_BSS &&
+ wl->bss_type != BSS_TYPE_STA_BSS) {
+ wl->ba_support = false;
+ return 0;
+ }
- /* validate that FW support BA */
- wl1271_check_ba_support(wl);
-
- if (wl->ba_support)
- /* 802.11n initiator BA session setting */
- for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
- ++tid_index) {
- ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
- tid_index, true);
- if (ret < 0)
- break;
- }
+ wl->ba_support = true;
- return ret;
+ /* 802.11n initiator BA session setting */
+ return wl12xx_acx_set_ba_initiator_policy(wl);
}
int wl1271_chip_specific_init(struct wl1271 *wl)
@@ -625,11 +622,7 @@ int wl1271_hw_init(struct wl1271 *wl)
return ret;
/* RX config */
- ret = wl1271_init_rx_config(wl,
- RX_CFG_PROMISCUOUS | RX_CFG_TSF,
- RX_FILTER_OPTION_DEF);
- /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
- RX_FILTER_OPTION_FILTER_ALL); */
+ ret = wl12xx_init_rx_config(wl);
if (ret < 0)
goto out_free_memmap;
@@ -708,11 +701,20 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
+ ret = wl12xx_acx_set_rate_mgmt_params(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
/* Configure initiator BA sessions policies */
ret = wl1271_set_ba_policies(wl);
if (ret < 0)
goto out_free_memmap;
+ /* configure hangover */
+ ret = wl12xx_acx_config_hangover(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
return 0;
out_free_memmap:
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index da5c1ad..c2da66f 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include "wl12xx.h"
@@ -128,12 +127,14 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);
void wl1271_io_reset(struct wl1271 *wl)
{
- wl->if_ops->reset(wl);
+ if (wl->if_ops->reset)
+ wl->if_ops->reset(wl);
}
void wl1271_io_init(struct wl1271 *wl)
{
- wl->if_ops->init(wl);
+ if (wl->if_ops->init)
+ wl->if_ops->init(wl);
}
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index beed621..e839341 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -25,6 +25,7 @@
#ifndef __IO_H__
#define __IO_H__
+#include <linux/irqreturn.h>
#include "reg.h"
#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
@@ -128,6 +129,20 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
wl1271_raw_write(wl, physical, buf, len, fixed);
}
+static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
+ void *buf, size_t len, bool fixed)
+{
+ int physical;
+ int addr;
+
+ /* Addresses are stored internally as addresses to 32 bytes blocks */
+ addr = hwaddr << 5;
+
+ physical = wl1271_translate_addr(wl, addr);
+
+ wl1271_raw_read(wl, physical, buf, len, fixed);
+}
+
static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
{
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
@@ -171,6 +186,5 @@ int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);
-void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters);
#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e6497dc..884f82b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/wl12xx.h>
+#include <linux/sched.h>
#include "wl12xx.h"
#include "wl12xx_80211.h"
@@ -51,110 +52,67 @@
static struct conf_drv_settings default_conf = {
.sg = {
- .sta_params = {
- [CONF_SG_BT_PER_THRESHOLD] = 7500,
- [CONF_SG_HV3_MAX_OVERRIDE] = 0,
- [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
- [CONF_SG_BT_LOAD_RATIO] = 200,
- [CONF_SG_AUTO_PS_MODE] = 1,
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
- [CONF_SG_RATE_ADAPT_THRESH] = 12,
- [CONF_SG_RATE_ADAPT_SNR] = 0,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50,
- /* Note: with UPSD, this should be 4 */
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20,
- /* Note: with UPDS, this should be 15 */
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8,
- /* Note: with UPDS, this should be 50 */
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40,
- /* Note: with UPDS, this should be 10 */
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20,
- [CONF_SG_RXT] = 1200,
- [CONF_SG_TXT] = 1000,
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
- [CONF_SG_UPSD_TIMEOUT] = 10,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
- [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75,
- [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15,
- [CONF_SG_HV3_MAX_SERVED] = 6,
- [CONF_SG_DHCP_TIME] = 5000,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
- },
- .ap_params = {
- [CONF_SG_BT_PER_THRESHOLD] = 7500,
- [CONF_SG_HV3_MAX_OVERRIDE] = 0,
- [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
- [CONF_SG_BT_LOAD_RATIO] = 50,
- [CONF_SG_AUTO_PS_MODE] = 1,
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
- [CONF_SG_RATE_ADAPT_THRESH] = 64,
- [CONF_SG_RATE_ADAPT_SNR] = 1,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25,
- [CONF_SG_RXT] = 1200,
- [CONF_SG_TXT] = 1000,
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
- [CONF_SG_UPSD_TIMEOUT] = 10,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
- [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75,
- [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15,
- [CONF_SG_HV3_MAX_SERVED] = 6,
- [CONF_SG_DHCP_TIME] = 5000,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
- [CONF_SG_TEMP_PARAM_1] = 0,
- [CONF_SG_TEMP_PARAM_2] = 0,
- [CONF_SG_TEMP_PARAM_3] = 0,
- [CONF_SG_TEMP_PARAM_4] = 0,
- [CONF_SG_TEMP_PARAM_5] = 0,
- [CONF_SG_AP_BEACON_MISS_TX] = 3,
- [CONF_SG_RX_WINDOW_LENGTH] = 6,
- [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50,
- [CONF_SG_TEMP_PARAM_6] = 1,
+ .params = {
+ [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
+ [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
+ [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
+ [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
+ [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
+ [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
+ [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
+ [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
+ [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
+ [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
+ [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
+ [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
+ [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
+ [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
+ [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
+ [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
+ [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
+ [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
+ /* active scan params */
+ [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+ [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+ [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
+ /* passive scan params */
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+ /* passive scan in dual antenna params */
+ [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
+ [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
+ [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
+ /* general params */
+ [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
+ [CONF_SG_ANTENNA_CONFIGURATION] = 0,
+ [CONF_SG_BEACON_MISS_PERCENT] = 60,
+ [CONF_SG_DHCP_TIME] = 5000,
+ [CONF_SG_RXT] = 1200,
+ [CONF_SG_TXT] = 1000,
+ [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+ [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
+ [CONF_SG_HV3_MAX_SERVED] = 6,
+ [CONF_SG_PS_POLL_TIMEOUT] = 10,
+ [CONF_SG_UPSD_TIMEOUT] = 10,
+ [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
+ [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
+ [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
+ /* AP params */
+ [CONF_AP_BEACON_MISS_TX] = 3,
+ [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
+ [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
+ [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
+ [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
+ [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
},
.state = CONF_SG_PROTECTIVE,
},
@@ -209,7 +167,8 @@ static struct conf_drv_settings default_conf = {
.tx_op_limit = 1504,
},
},
- .ap_max_tx_retries = 100,
+ .max_tx_retries = 100,
+ .ap_aging_period = 300,
.tid_conf_count = 4,
.tid_conf = {
[CONF_TX_AC_BE] = {
@@ -277,10 +236,9 @@ static struct conf_drv_settings default_conf = {
.ps_poll_recovery_period = 700,
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 50,
- .psm_entry_retries = 5,
+ .psm_entry_retries = 8,
.psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3,
- .psm_entry_hangover_period = 1,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
},
@@ -308,8 +266,8 @@ static struct conf_drv_settings default_conf = {
},
.sched_scan = {
/* sched_scan requires dwell times in TU instead of TU/1000 */
- .min_dwell_time_active = 8,
- .max_dwell_time_active = 30,
+ .min_dwell_time_active = 30,
+ .max_dwell_time_active = 60,
.dwell_time_passive = 100,
.dwell_time_dfs = 150,
.num_probe_reqs = 2,
@@ -327,8 +285,10 @@ static struct conf_drv_settings default_conf = {
},
},
.ht = {
+ .rx_ba_win_size = 8,
.tx_ba_win_size = 64,
.inactivity_timeout = 10000,
+ .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
},
.mem_wl127x = {
.num_stations = 1,
@@ -362,9 +322,60 @@ static struct conf_drv_settings default_conf = {
.fm_disturbed_band_margin = 0xff, /* default */
.swallow_clk_diff = 0xff, /* default */
},
+ .rx_streaming = {
+ .duration = 150,
+ .queues = 0x1,
+ .interval = 20,
+ .always = 0,
+ },
+ .fwlog = {
+ .mode = WL12XX_FWLOG_ON_DEMAND,
+ .mem_blocks = 2,
+ .severity = 0,
+ .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
+ .output = WL12XX_FWLOG_OUTPUT_HOST,
+ .threshold = 0,
+ },
.hci_io_ds = HCI_IO_DS_6MA,
+ .rate = {
+ .rate_retry_score = 32000,
+ .per_add = 8192,
+ .per_th1 = 2048,
+ .per_th2 = 4096,
+ .max_per = 8100,
+ .inverse_curiosity_factor = 5,
+ .tx_fail_low_th = 4,
+ .tx_fail_high_th = 10,
+ .per_alpha_shift = 4,
+ .per_add_shift = 13,
+ .per_beta1_shift = 10,
+ .per_beta2_shift = 8,
+ .rate_check_up = 2,
+ .rate_check_down = 12,
+ .rate_retry_policy = {
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ },
+ },
+ .hangover = {
+ .recover_time = 0,
+ .hangover_period = 20,
+ .dynamic_mode = 1,
+ .early_termination_mode = 1,
+ .max_period = 20,
+ .min_period = 1,
+ .increase_delta = 1,
+ .decrease_delta = 2,
+ .quiet_time = 4,
+ .increase_time = 1,
+ .window_size = 16,
+ },
};
+static char *fwlog_param;
+static bool bug_on_recovery;
+
static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues);
static void wl1271_free_ap_keys(struct wl1271 *wl);
@@ -388,6 +399,24 @@ static struct platform_device wl1271_device = {
static DEFINE_MUTEX(wl_list_mutex);
static LIST_HEAD(wl_list);
+static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
+{
+ int ret;
+ if (operstate != IF_OPER_UP)
+ return 0;
+
+ if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
+ return 0;
+
+ ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid);
+ if (ret < 0)
+ return ret;
+
+ wl12xx_croc(wl, wl->role_id);
+
+ wl1271_info("Association completed.");
+ return 0;
+}
static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
void *arg)
{
@@ -437,11 +466,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
if (ret < 0)
goto out;
- if ((dev->operstate == IF_OPER_UP) &&
- !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {
- wl1271_cmd_set_sta_state(wl);
- wl1271_info("Association completed.");
- }
+ wl1271_check_operstate(wl, dev->operstate);
wl1271_ps_elp_sleep(wl);
@@ -473,6 +498,117 @@ static int wl1271_reg_notify(struct wiphy *wiphy,
return 0;
}
+static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable)
+{
+ int ret = 0;
+
+ /* we should hold wl->mutex */
+ ret = wl1271_acx_ps_rx_streaming(wl, enable);
+ if (ret < 0)
+ goto out;
+
+ if (enable)
+ set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+ else
+ clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+out:
+ return ret;
+}
+
+/*
+ * this function is being called when the rx_streaming interval
+ * has beed changed or rx_streaming should be disabled
+ */
+int wl1271_recalc_rx_streaming(struct wl1271 *wl)
+{
+ int ret = 0;
+ int period = wl->conf.rx_streaming.interval;
+
+ /* don't reconfigure if rx_streaming is disabled */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ goto out;
+
+ /* reconfigure/disable according to new streaming_period */
+ if (period &&
+ test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
+ ret = wl1271_set_rx_streaming(wl, true);
+ else {
+ ret = wl1271_set_rx_streaming(wl, false);
+ /* don't cancel_work_sync since we might deadlock */
+ del_timer_sync(&wl->rx_streaming_timer);
+ }
+out:
+ return ret;
+}
+
+static void wl1271_rx_streaming_enable_work(struct work_struct *work)
+{
+ int ret;
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, rx_streaming_enable_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) ||
+ !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ (!wl->conf.rx_streaming.always &&
+ !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
+ goto out;
+
+ if (!wl->conf.rx_streaming.interval)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_set_rx_streaming(wl, true);
+ if (ret < 0)
+ goto out_sleep;
+
+ /* stop it after some time of inactivity */
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_rx_streaming_disable_work(struct work_struct *work)
+{
+ int ret;
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, rx_streaming_disable_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_set_rx_streaming(wl, false);
+ if (ret)
+ goto out_sleep;
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_rx_streaming_timer(unsigned long data)
+{
+ struct wl1271 *wl = (struct wl1271 *)data;
+ ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work);
+}
+
static void wl1271_conf_init(struct wl1271 *wl)
{
@@ -488,8 +624,24 @@ static void wl1271_conf_init(struct wl1271 *wl)
/* apply driver default configuration */
memcpy(&wl->conf, &default_conf, sizeof(default_conf));
-}
+ /* Adjust settings according to optional module parameters */
+ if (fwlog_param) {
+ if (!strcmp(fwlog_param, "continuous")) {
+ wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
+ } else if (!strcmp(fwlog_param, "ondemand")) {
+ wl->conf.fwlog.mode = WL12XX_FWLOG_ON_DEMAND;
+ } else if (!strcmp(fwlog_param, "dbgpins")) {
+ wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_DBG_PINS;
+ } else if (!strcmp(fwlog_param, "disable")) {
+ wl->conf.fwlog.mem_blocks = 0;
+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_NONE;
+ } else {
+ wl1271_error("Unknown fwlog parameter %s", fwlog_param);
+ }
+ }
+}
static int wl1271_plt_init(struct wl1271 *wl)
{
@@ -561,7 +713,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- ret = wl1271_acx_sta_mem_cfg(wl);
+ ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0)
goto out_free_memmap;
@@ -616,33 +768,52 @@ static int wl1271_plt_init(struct wl1271 *wl)
return ret;
}
-static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
+static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
{
- bool fw_ps;
+ bool fw_ps, single_sta;
/* only regulate station links */
if (hlid < WL1271_AP_STA_HLID_START)
return;
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+ single_sta = (wl->active_sta_count == 1);
/*
* Wake up from high level PS if the STA is asleep with too little
- * blocks in FW or if the STA is awake.
+ * packets in FW or if the STA is awake.
*/
- if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
+ if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_end(wl, hlid);
- /* Start high-level PS if the STA is asleep with enough blocks in FW */
- else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+ /*
+ * Start high-level PS if the STA is asleep with enough blocks in FW.
+ * Make an exception if this is the only connected station. In this
+ * case FW-memory congestion is not a problem.
+ */
+ else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_start(wl, hlid, true);
}
-static void wl1271_irq_update_links_status(struct wl1271 *wl,
- struct wl1271_fw_ap_status *status)
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
+{
+ int id;
+
+ /* global/broadcast "stations" are always active */
+ if (hlid < WL1271_AP_STA_HLID_START)
+ return true;
+
+ id = hlid - WL1271_AP_STA_HLID_START;
+ return test_bit(id, wl->ap_hlid_map);
+}
+
+static void wl12xx_irq_update_links_status(struct wl1271 *wl,
+ struct wl12xx_fw_status *status)
{
u32 cur_fw_ps_map;
- u8 hlid;
+ u8 hlid, cnt;
+
+ /* TODO: also use link_fast_bitmap here */
cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
if (wl->ap_fw_ps_map != cur_fw_ps_map) {
@@ -655,34 +826,30 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
}
for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
- u8 cnt = status->tx_lnk_free_blks[hlid] -
- wl->links[hlid].prev_freed_blks;
+ if (!wl1271_is_active_sta(wl, hlid))
+ continue;
+
+ cnt = status->tx_lnk_free_pkts[hlid] -
+ wl->links[hlid].prev_freed_pkts;
- wl->links[hlid].prev_freed_blks =
- status->tx_lnk_free_blks[hlid];
- wl->links[hlid].allocated_blks -= cnt;
+ wl->links[hlid].prev_freed_pkts =
+ status->tx_lnk_free_pkts[hlid];
+ wl->links[hlid].allocated_pkts -= cnt;
- wl1271_irq_ps_regulate_link(wl, hlid,
- wl->links[hlid].allocated_blks);
+ wl12xx_irq_ps_regulate_link(wl, hlid,
+ wl->links[hlid].allocated_pkts);
}
}
-static void wl1271_fw_status(struct wl1271 *wl,
- struct wl1271_fw_full_status *full_status)
+static void wl12xx_fw_status(struct wl1271 *wl,
+ struct wl12xx_fw_status *status)
{
- struct wl1271_fw_common_status *status = &full_status->common;
struct timespec ts;
u32 old_tx_blk_count = wl->tx_blocks_available;
- u32 freed_blocks = 0;
+ int avail, freed_blocks;
int i;
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- wl1271_raw_read(wl, FW_STATUS_ADDR, status,
- sizeof(struct wl1271_fw_ap_status), false);
- } else {
- wl1271_raw_read(wl, FW_STATUS_ADDR, status,
- sizeof(struct wl1271_fw_sta_status), false);
- }
+ wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
@@ -691,40 +858,49 @@ static void wl1271_fw_status(struct wl1271 *wl,
status->drv_rx_counter,
status->tx_results_counter);
- /* update number of available TX blocks */
for (i = 0; i < NUM_TX_QUEUES; i++) {
- freed_blocks += le32_to_cpu(status->tx_released_blks[i]) -
- wl->tx_blocks_freed[i];
+ /* prevent wrap-around in freed-packets counter */
+ wl->tx_allocated_pkts[i] -=
+ (status->tx_released_pkts[i] -
+ wl->tx_pkts_freed[i]) & 0xff;
- wl->tx_blocks_freed[i] =
- le32_to_cpu(status->tx_released_blks[i]);
+ wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
}
+ /* prevent wrap-around in total blocks counter */
+ if (likely(wl->tx_blocks_freed <=
+ le32_to_cpu(status->total_released_blks)))
+ freed_blocks = le32_to_cpu(status->total_released_blks) -
+ wl->tx_blocks_freed;
+ else
+ freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
+ le32_to_cpu(status->total_released_blks);
+
+ wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks);
+
wl->tx_allocated_blocks -= freed_blocks;
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- /* Update num of allocated TX blocks per link and ps status */
- wl1271_irq_update_links_status(wl, &full_status->ap);
- wl->tx_blocks_available += freed_blocks;
- } else {
- int avail = full_status->sta.tx_total - wl->tx_allocated_blocks;
+ avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
- /*
- * The FW might change the total number of TX memblocks before
- * we get a notification about blocks being released. Thus, the
- * available blocks calculation might yield a temporary result
- * which is lower than the actual available blocks. Keeping in
- * mind that only blocks that were allocated can be moved from
- * TX to RX, tx_blocks_available should never decrease here.
- */
- wl->tx_blocks_available = max((int)wl->tx_blocks_available,
- avail);
- }
+ /*
+ * The FW might change the total number of TX memblocks before
+ * we get a notification about blocks being released. Thus, the
+ * available blocks calculation might yield a temporary result
+ * which is lower than the actual available blocks. Keeping in
+ * mind that only blocks that were allocated can be moved from
+ * TX to RX, tx_blocks_available should never decrease here.
+ */
+ wl->tx_blocks_available = max((int)wl->tx_blocks_available,
+ avail);
/* if more blocks are available now, tx work can be scheduled */
if (wl->tx_blocks_available > old_tx_blk_count)
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
+ /* for AP update num of allocated TX blocks per link and ps status */
+ if (wl->bss_type == BSS_TYPE_AP_BSS)
+ wl12xx_irq_update_links_status(wl, status);
+
/* update the host-chipset time offset */
getnstimeofday(&ts);
wl->time_offset = (timespec_to_ns(&ts) >> 10) -
@@ -741,7 +917,7 @@ static void wl1271_flush_deferred_work(struct wl1271 *wl)
/* Return sent skbs to the network stack */
while ((skb = skb_dequeue(&wl->deferred_tx_queue)))
- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status_ni(wl->hw, skb);
}
static void wl1271_netstack_work(struct work_struct *work)
@@ -797,8 +973,8 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
smp_mb__after_clear_bit();
- wl1271_fw_status(wl, wl->fw_status);
- intr = le32_to_cpu(wl->fw_status->common.intr);
+ wl12xx_fw_status(wl, wl->fw_status);
+ intr = le32_to_cpu(wl->fw_status->intr);
intr &= WL1271_INTR_MASK;
if (!intr) {
done = true;
@@ -808,7 +984,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
wl1271_error("watchdog interrupt received! "
"starting recovery.");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
/* restarting the chip. ignore any other interrupt. */
goto out;
@@ -817,12 +993,12 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
if (likely(intr & WL1271_ACX_INTR_DATA)) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
- wl1271_rx(wl, &wl->fw_status->common);
+ wl12xx_rx(wl, wl->fw_status);
/* Check if any tx blocks were freed */
spin_lock_irqsave(&wl->wl_lock, flags);
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
- wl->tx_queue_count) {
+ wl1271_tx_total_queue_count(wl) > 0) {
spin_unlock_irqrestore(&wl->wl_lock, flags);
/*
* In order to avoid starvation of the TX path,
@@ -834,7 +1010,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
}
/* check for tx results */
- if (wl->fw_status->common.tx_results_counter !=
+ if (wl->fw_status->tx_results_counter !=
(wl->tx_results_count & 0xff))
wl1271_tx_complete(wl);
@@ -870,7 +1046,7 @@ out:
/* In case TX was not handled here, queue TX work */
clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
- wl->tx_queue_count)
+ wl1271_tx_total_queue_count(wl) > 0)
ieee80211_queue_work(wl->hw, &wl->tx_work);
spin_unlock_irqrestore(&wl->wl_lock, flags);
@@ -886,25 +1062,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
const char *fw_name;
int ret;
- switch (wl->bss_type) {
- case BSS_TYPE_AP_BSS:
- if (wl->chip.id == CHIP_ID_1283_PG20)
- fw_name = WL128X_AP_FW_NAME;
- else
- fw_name = WL127X_AP_FW_NAME;
- break;
- case BSS_TYPE_IBSS:
- case BSS_TYPE_STA_BSS:
- if (wl->chip.id == CHIP_ID_1283_PG20)
- fw_name = WL128X_FW_NAME;
- else
- fw_name = WL1271_FW_NAME;
- break;
- default:
- wl1271_error("no compatible firmware for bss_type %d",
- wl->bss_type);
- return -EINVAL;
- }
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ fw_name = WL128X_FW_NAME;
+ else
+ fw_name = WL127X_FW_NAME;
wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name);
@@ -933,7 +1094,6 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
}
memcpy(wl->fw, fw->data, wl->fw_len);
- wl->fw_bss_type = wl->bss_type;
ret = 0;
out:
@@ -970,6 +1130,89 @@ out:
return ret;
}
+void wl12xx_queue_recovery_work(struct wl1271 *wl)
+{
+ if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
+}
+
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
+{
+ size_t len = 0;
+
+ /* The FW log is a length-value list, find where the log end */
+ while (len < maxlen) {
+ if (memblock[len] == 0)
+ break;
+ if (len + memblock[len] + 1 > maxlen)
+ break;
+ len += memblock[len] + 1;
+ }
+
+ /* Make sure we have enough room */
+ len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size));
+
+ /* Fill the FW log file, consumed by the sysfs fwlog entry */
+ memcpy(wl->fwlog + wl->fwlog_size, memblock, len);
+ wl->fwlog_size += len;
+
+ return len;
+}
+
+static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
+{
+ u32 addr;
+ u32 first_addr;
+ u8 *block;
+
+ if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
+ (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
+ (wl->conf.fwlog.mem_blocks == 0))
+ return;
+
+ wl1271_info("Reading FW panic log");
+
+ block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL);
+ if (!block)
+ return;
+
+ /*
+ * Make sure the chip is awake and the logger isn't active.
+ * This might fail if the firmware hanged.
+ */
+ if (!wl1271_ps_elp_wakeup(wl))
+ wl12xx_cmd_stop_fwlog(wl);
+
+ /* Read the first memory block address */
+ wl12xx_fw_status(wl, wl->fw_status);
+ first_addr = le32_to_cpu(wl->fw_status->log_start_addr);
+ if (!first_addr)
+ goto out;
+
+ /* Traverse the memory blocks linked list */
+ addr = first_addr;
+ do {
+ memset(block, 0, WL12XX_HW_BLOCK_SIZE);
+ wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,
+ false);
+
+ /*
+ * Memory blocks are linked to one another. The first 4 bytes
+ * of each memory block hold the hardware address of the next
+ * one. The last memory block points to the first one.
+ */
+ addr = le32_to_cpup((__le32 *)block);
+ if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),
+ WL12XX_HW_BLOCK_SIZE - sizeof(addr)))
+ break;
+ } while (addr && (addr != first_addr));
+
+ wake_up_interruptible(&wl->fwlog_waitq);
+
+out:
+ kfree(block);
+}
+
static void wl1271_recovery_work(struct work_struct *work)
{
struct wl1271 *wl =
@@ -980,11 +1223,24 @@ static void wl1271_recovery_work(struct work_struct *work)
if (wl->state != WL1271_STATE_ON)
goto out;
+ /* Avoid a recursive recovery */
+ set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+
+ wl12xx_read_fwlog_panic(wl);
+
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
- ieee80211_connection_loss(wl->vif);
+ BUG_ON(bug_on_recovery);
+
+ /*
+ * Advance security sequence number to overcome potential progress
+ * in the firmware during recovery. This doens't hurt if the network is
+ * not encrypted.
+ */
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING;
/* Prevent spurious TX during FW restart */
ieee80211_stop_queues(wl->hw);
@@ -996,6 +1252,9 @@ static void wl1271_recovery_work(struct work_struct *work)
/* reboot the chipset */
__wl1271_op_remove_interface(wl, false);
+
+ clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+
ieee80211_restart_hw(wl->hw);
/*
@@ -1074,10 +1333,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
wl->chip.id);
- /* end-of-transaction flag should be set in wl127x AP mode */
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
-
ret = wl1271_setup(wl);
if (ret < 0)
goto out;
@@ -1089,6 +1344,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
ret = wl1271_setup(wl);
if (ret < 0)
goto out;
+
if (wl1271_set_block_size(wl))
wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT;
break;
@@ -1099,8 +1355,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
goto out;
}
- /* Make sure the firmware type matches the BSS type */
- if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) {
+ if (wl->fw == NULL) {
ret = wl1271_fetch_firmware(wl);
if (ret < 0)
goto out;
@@ -1117,27 +1372,10 @@ out:
return ret;
}
-static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl)
-{
- unsigned int quirks = 0;
- unsigned int *fw_ver = wl->chip.fw_ver;
-
- /* Only for wl127x */
- if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
- /* Check STA version */
- (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
- (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
- /* Check AP version */
- ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
- (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
- quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
-
- return quirks;
-}
-
int wl1271_plt_start(struct wl1271 *wl)
{
int retries = WL1271_BOOT_RETRIES;
+ struct wiphy *wiphy = wl->hw->wiphy;
int ret;
mutex_lock(&wl->mutex);
@@ -1171,8 +1409,11 @@ int wl1271_plt_start(struct wl1271 *wl)
wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver_str);
- /* Check if any quirks are needed with older fw versions */
- wl->quirks |= wl1271_get_fw_ver_quirks(wl);
+ /* update hw/fw version info in wiphy struct */
+ wiphy->hw_version = wl->chip.id;
+ strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
+ sizeof(wiphy->fw_version));
+
goto out;
irq_disable:
@@ -1242,36 +1483,44 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1271 *wl = hw->priv;
unsigned long flags;
- int q;
+ int q, mapping;
u8 hlid = 0;
- q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+ mapping = skb_get_queue_mapping(skb);
+ q = wl1271_tx_get_queue(mapping);
if (wl->bss_type == BSS_TYPE_AP_BSS)
- hlid = wl1271_tx_get_hlid(skb);
+ hlid = wl12xx_tx_get_hlid_ap(wl, skb);
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count++;
-
- /*
- * The workqueue is slow to process the tx_queue and we need stop
- * the queue here, otherwise the queue will get too long.
- */
- if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
- wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
- ieee80211_stop_queues(wl->hw);
- set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
- }
-
/* queue the packet */
if (wl->bss_type == BSS_TYPE_AP_BSS) {
+ if (!wl1271_is_active_sta(wl, hlid)) {
+ wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d",
+ hlid, q);
+ dev_kfree_skb(skb);
+ goto out;
+ }
+
wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
} else {
skb_queue_tail(&wl->tx_queue[q], skb);
}
+ wl->tx_queue_count[q]++;
+
+ /*
+ * The workqueue is slow to process the tx_queue and we need stop
+ * the queue here, otherwise the queue will get too long.
+ */
+ if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
+ wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
+ ieee80211_stop_queue(wl->hw, mapping);
+ set_bit(q, &wl->stopped_queues_map);
+ }
+
/*
* The chip specific setup must run before the first TX packet -
* before that, the tx_work will not be initialized!
@@ -1281,16 +1530,24 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
!test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
ieee80211_queue_work(wl->hw, &wl->tx_work);
+out:
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
int wl1271_tx_dummy_packet(struct wl1271 *wl)
{
unsigned long flags;
+ int q;
+
+ /* no need to queue a new dummy packet if one is already pending */
+ if (test_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags))
+ return 0;
+
+ q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
spin_lock_irqsave(&wl->wl_lock, flags);
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
- wl->tx_queue_count++;
+ wl->tx_queue_count[q]++;
spin_unlock_irqrestore(&wl->wl_lock, flags);
/* The FW is low on RX memory blocks, so send the dummy packet asap */
@@ -1352,15 +1609,15 @@ static struct notifier_block wl1271_dev_notifier = {
};
#ifdef CONFIG_PM
-static int wl1271_configure_suspend(struct wl1271 *wl)
+static int wl1271_configure_suspend_sta(struct wl1271 *wl)
{
- int ret;
-
- if (wl->bss_type != BSS_TYPE_STA_BSS)
- return 0;
+ int ret = 0;
mutex_lock(&wl->mutex);
+ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ goto out_unlock;
+
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out_unlock;
@@ -1403,11 +1660,44 @@ out:
}
+static int wl1271_configure_suspend_ap(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ mutex_lock(&wl->mutex);
+
+ if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ goto out_unlock;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
+ ret = wl1271_acx_beacon_filter_opt(wl, true);
+
+ wl1271_ps_elp_sleep(wl);
+out_unlock:
+ mutex_unlock(&wl->mutex);
+ return ret;
+
+}
+
+static int wl1271_configure_suspend(struct wl1271 *wl)
+{
+ if (wl->bss_type == BSS_TYPE_STA_BSS)
+ return wl1271_configure_suspend_sta(wl);
+ if (wl->bss_type == BSS_TYPE_AP_BSS)
+ return wl1271_configure_suspend_ap(wl);
+ return 0;
+}
+
static void wl1271_configure_resume(struct wl1271 *wl)
{
int ret;
+ bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS;
+ bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS;
- if (wl->bss_type != BSS_TYPE_STA_BSS)
+ if (!is_sta && !is_ap)
return;
mutex_lock(&wl->mutex);
@@ -1415,10 +1705,14 @@ static void wl1271_configure_resume(struct wl1271 *wl)
if (ret < 0)
goto out;
- /* exit psm if it wasn't configured */
- if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
- wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- wl->basic_rate, true);
+ if (is_sta) {
+ /* exit psm if it wasn't configured */
+ if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
+ wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+ wl->basic_rate, true);
+ } else if (is_ap) {
+ wl1271_acx_beacon_filter_opt(wl, false);
+ }
wl1271_ps_elp_sleep(wl);
out:
@@ -1429,69 +1723,68 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wow)
{
struct wl1271 *wl = hw->priv;
+ int ret;
+
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
- wl->wow_enabled = !!wow;
- if (wl->wow_enabled) {
- int ret;
- ret = wl1271_configure_suspend(wl);
- if (ret < 0) {
- wl1271_warning("couldn't prepare device to suspend");
- return ret;
- }
- /* flush any remaining work */
- wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
- flush_delayed_work(&wl->scan_complete_work);
+ WARN_ON(!wow || !wow->any);
- /*
- * disable and re-enable interrupts in order to flush
- * the threaded_irq
- */
- wl1271_disable_interrupts(wl);
+ wl->wow_enabled = true;
+ ret = wl1271_configure_suspend(wl);
+ if (ret < 0) {
+ wl1271_warning("couldn't prepare device to suspend");
+ return ret;
+ }
+ /* flush any remaining work */
+ wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
- /*
- * set suspended flag to avoid triggering a new threaded_irq
- * work. no need for spinlock as interrupts are disabled.
- */
- set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+ /*
+ * disable and re-enable interrupts in order to flush
+ * the threaded_irq
+ */
+ wl1271_disable_interrupts(wl);
+
+ /*
+ * set suspended flag to avoid triggering a new threaded_irq
+ * work. no need for spinlock as interrupts are disabled.
+ */
+ set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+
+ wl1271_enable_interrupts(wl);
+ flush_work(&wl->tx_work);
+ flush_delayed_work(&wl->pspoll_work);
+ flush_delayed_work(&wl->elp_work);
- wl1271_enable_interrupts(wl);
- flush_work(&wl->tx_work);
- flush_delayed_work(&wl->pspoll_work);
- flush_delayed_work(&wl->elp_work);
- }
return 0;
}
static int wl1271_op_resume(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
+ unsigned long flags;
+ bool run_irq_work = false;
+
wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
wl->wow_enabled);
+ WARN_ON(!wl->wow_enabled);
/*
* re-enable irq_work enqueuing, and call irq_work directly if
* there is a pending work.
*/
- if (wl->wow_enabled) {
- struct wl1271 *wl = hw->priv;
- unsigned long flags;
- bool run_irq_work = false;
-
- spin_lock_irqsave(&wl->wl_lock, flags);
- clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
- if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
- run_irq_work = true;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
-
- if (run_irq_work) {
- wl1271_debug(DEBUG_MAC80211,
- "run postponed irq_work directly");
- wl1271_irq(0, wl);
- wl1271_enable_interrupts(wl);
- }
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+ if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
+ run_irq_work = true;
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
- wl1271_configure_resume(wl);
+ if (run_irq_work) {
+ wl1271_debug(DEBUG_MAC80211,
+ "run postponed irq_work directly");
+ wl1271_irq(0, wl);
+ wl1271_enable_interrupts(wl);
}
+ wl1271_configure_resume(wl);
+ wl->wow_enabled = false;
return 0;
}
@@ -1510,9 +1803,6 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
*
* The MAC address is first known when the corresponding interface
* is added. That is where we will initialize the hardware.
- *
- * In addition, we currently have different firmwares for AP and managed
- * operation. We will know which to boot according to interface type.
*/
return 0;
@@ -1523,6 +1813,30 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
}
+static u8 wl12xx_get_role_type(struct wl1271 *wl)
+{
+ switch (wl->bss_type) {
+ case BSS_TYPE_AP_BSS:
+ if (wl->p2p)
+ return WL1271_ROLE_P2P_GO;
+ else
+ return WL1271_ROLE_AP;
+
+ case BSS_TYPE_STA_BSS:
+ if (wl->p2p)
+ return WL1271_ROLE_P2P_CL;
+ else
+ return WL1271_ROLE_STA;
+
+ case BSS_TYPE_IBSS:
+ return WL1271_ROLE_IBSS;
+
+ default:
+ wl1271_error("invalid bss_type: %d", wl->bss_type);
+ }
+ return WL12XX_INVALID_ROLE_TYPE;
+}
+
static int wl1271_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -1530,10 +1844,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
struct wiphy *wiphy = hw->wiphy;
int retries = WL1271_BOOT_RETRIES;
int ret = 0;
+ u8 role_type;
bool booted = false;
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
- vif->type, vif->addr);
+ ieee80211_vif_type_p2p(vif), vif->addr);
mutex_lock(&wl->mutex);
if (wl->vif) {
@@ -1553,7 +1868,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
- switch (vif->type) {
+ switch (ieee80211_vif_type_p2p(vif)) {
+ case NL80211_IFTYPE_P2P_CLIENT:
+ wl->p2p = 1;
+ /* fall-through */
case NL80211_IFTYPE_STATION:
wl->bss_type = BSS_TYPE_STA_BSS;
wl->set_bss_type = BSS_TYPE_STA_BSS;
@@ -1562,6 +1880,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl->bss_type = BSS_TYPE_IBSS;
wl->set_bss_type = BSS_TYPE_STA_BSS;
break;
+ case NL80211_IFTYPE_P2P_GO:
+ wl->p2p = 1;
+ /* fall-through */
case NL80211_IFTYPE_AP:
wl->bss_type = BSS_TYPE_AP_BSS;
break;
@@ -1570,6 +1891,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
+ role_type = wl12xx_get_role_type(wl);
+ if (role_type == WL12XX_INVALID_ROLE_TYPE) {
+ ret = -EINVAL;
+ goto out;
+ }
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
if (wl->state != WL1271_STATE_OFF) {
@@ -1589,6 +1915,25 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
if (ret < 0)
goto power_off;
+ if (wl->bss_type == BSS_TYPE_STA_BSS ||
+ wl->bss_type == BSS_TYPE_IBSS) {
+ /*
+ * The device role is a special role used for
+ * rx and tx frames prior to association (as
+ * the STA role can get packets only from
+ * its associated bssid)
+ */
+ ret = wl12xx_cmd_role_enable(wl,
+ WL1271_ROLE_DEVICE,
+ &wl->dev_role_id);
+ if (ret < 0)
+ goto irq_disable;
+ }
+
+ ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id);
+ if (ret < 0)
+ goto irq_disable;
+
ret = wl1271_hw_init(wl);
if (ret < 0)
goto irq_disable;
@@ -1629,9 +1974,6 @@ power_off:
strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));
- /* Check if any quirks are needed with older fw versions */
- wl->quirks |= wl1271_get_fw_ver_quirks(wl);
-
/*
* Now we know if 11a is supported (info from the NVS), so disable
* 11a channels if not supported
@@ -1656,7 +1998,7 @@ out:
static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues)
{
- int i;
+ int ret, i;
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
@@ -1681,6 +2023,31 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
ieee80211_scan_completed(wl->hw, true);
}
+ if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
+ /* disable active roles */
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto deinit;
+
+ if (wl->bss_type == BSS_TYPE_STA_BSS) {
+ ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id);
+ if (ret < 0)
+ goto deinit;
+ }
+
+ ret = wl12xx_cmd_role_disable(wl, &wl->role_id);
+ if (ret < 0)
+ goto deinit;
+
+ wl1271_ps_elp_sleep(wl);
+ }
+deinit:
+ /* clear all hlids (except system_hlid) */
+ wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+ wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+ wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+ wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
+
/*
* this must be before the cancel_work calls below, so that the work
* functions don't perform further work.
@@ -1694,6 +2061,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->tx_work);
+ del_timer_sync(&wl->rx_streaming_timer);
+ cancel_work_sync(&wl->rx_streaming_enable_work);
+ cancel_work_sync(&wl->rx_streaming_disable_work);
cancel_delayed_work_sync(&wl->pspoll_work);
cancel_delayed_work_sync(&wl->elp_work);
@@ -1704,10 +2074,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl1271_power_off(wl);
memset(wl->bssid, 0, ETH_ALEN);
- memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
+ memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
wl->ssid_len = 0;
wl->bss_type = MAX_BSS_TYPE;
wl->set_bss_type = MAX_BSS_TYPE;
+ wl->p2p = 0;
wl->band = IEEE80211_BAND_2GHZ;
wl->rx_counter = 0;
@@ -1717,18 +2088,27 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl->tx_allocated_blocks = 0;
wl->tx_results_count = 0;
wl->tx_packets_count = 0;
- wl->tx_security_last_seq = 0;
- wl->tx_security_seq = 0;
wl->time_offset = 0;
wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+ wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
+ wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
wl->vif = NULL;
- wl->filters = 0;
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl1271_free_ap_keys(wl);
memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
wl->ap_fw_ps_map = 0;
wl->ap_ps_map = 0;
wl->sched_scanning = false;
+ wl->role_id = WL12XX_INVALID_ROLE_ID;
+ wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
+ memset(wl->roles_map, 0, sizeof(wl->roles_map));
+ memset(wl->links_map, 0, sizeof(wl->links_map));
+ memset(wl->roc_map, 0, sizeof(wl->roc_map));
+ wl->active_sta_count = 0;
+
+ /* The system link is always allocated */
+ __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
/*
* this is performed after the cancel_work calls and the associated
@@ -1737,8 +2117,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
*/
wl->flags = 0;
- for (i = 0; i < NUM_TX_QUEUES; i++)
- wl->tx_blocks_freed[i] = 0;
+ wl->tx_blocks_freed = 0;
+
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ wl->tx_pkts_freed[i] = 0;
+ wl->tx_allocated_pkts[i] = 0;
+ }
wl1271_debugfs_reset(wl);
@@ -1769,64 +2153,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
cancel_work_sync(&wl->recovery_work);
}
-void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
-{
- wl1271_set_default_filters(wl);
-
- /* combine requested filters with current filter config */
- filters = wl->filters | filters;
-
- wl1271_debug(DEBUG_FILTERS, "RX filters set: ");
-
- if (filters & FIF_PROMISC_IN_BSS) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS");
- wl->rx_config &= ~CFG_UNI_FILTER_EN;
- wl->rx_config |= CFG_BSSID_FILTER_EN;
- }
- if (filters & FIF_BCN_PRBRESP_PROMISC) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC");
- wl->rx_config &= ~CFG_BSSID_FILTER_EN;
- wl->rx_config &= ~CFG_SSID_FILTER_EN;
- }
- if (filters & FIF_OTHER_BSS) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS");
- wl->rx_config &= ~CFG_BSSID_FILTER_EN;
- }
- if (filters & FIF_CONTROL) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL");
- wl->rx_filter |= CFG_RX_CTL_EN;
- }
- if (filters & FIF_FCSFAIL) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL");
- wl->rx_filter |= CFG_RX_FCS_ERROR;
- }
-}
-
-static int wl1271_dummy_join(struct wl1271 *wl)
-{
- int ret = 0;
- /* we need to use a dummy BSSID for now */
- static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
- 0xad, 0xbe, 0xef };
-
- memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
-
- /* pass through frames from all BSS */
- wl1271_configure_filters(wl, FIF_OTHER_BSS);
-
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
- if (ret < 0)
- goto out;
-
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
-out:
- return ret;
-}
-
static int wl1271_join(struct wl1271 *wl, bool set_assoc)
{
int ret;
+ bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
/*
* One of the side effects of the JOIN command is that is clears
@@ -1843,12 +2173,13 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
if (set_assoc)
set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
+ if (is_ibss)
+ ret = wl12xx_cmd_role_start_ibss(wl);
+ else
+ ret = wl12xx_cmd_role_start_sta(wl);
if (ret < 0)
goto out;
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
goto out;
@@ -1883,16 +2214,21 @@ static int wl1271_unjoin(struct wl1271 *wl)
{
int ret;
+ if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
+ wl12xx_cmd_stop_channel_switch(wl);
+ ieee80211_chswitch_done(wl->vif, false);
+ }
+
/* to stop listening to a channel, we disconnect */
- ret = wl1271_cmd_disconnect(wl);
+ ret = wl12xx_cmd_role_stop_sta(wl);
if (ret < 0)
goto out;
- clear_bit(WL1271_FLAG_JOINED, &wl->flags);
memset(wl->bssid, 0, ETH_ALEN);
- /* stop filtering packets based on bssid */
- wl1271_configure_filters(wl, FIF_OTHER_BSS);
+ /* reset TX security counters on a clean disconnect */
+ wl->tx_security_last_seq_lsb = 0;
+ wl->tx_security_seq = 0;
out:
return ret;
@@ -1900,10 +2236,19 @@ out:
static void wl1271_set_band_rate(struct wl1271 *wl)
{
- if (wl->band == IEEE80211_BAND_2GHZ)
- wl->basic_rate_set = wl->conf.tx.basic_rate;
- else
- wl->basic_rate_set = wl->conf.tx.basic_rate_5;
+ wl->basic_rate_set = wl->bitrate_masks[wl->band];
+ wl->rate_set = wl->basic_rate_set;
+}
+
+static bool wl12xx_is_roc(struct wl1271 *wl)
+{
+ u8 role_id;
+
+ role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES);
+ if (role_id >= WL12XX_MAX_ROLES)
+ return false;
+
+ return true;
}
static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
@@ -1911,12 +2256,17 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
int ret;
if (idle) {
- if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
- ret = wl1271_unjoin(wl);
+ /* no need to croc if we weren't busy (e.g. during boot) */
+ if (wl12xx_is_roc(wl)) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_role_stop_dev(wl);
if (ret < 0)
goto out;
}
- wl->rate_set = wl1271_tx_min_rate_get(wl);
+ wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
goto out;
@@ -1927,18 +2277,17 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
goto out;
set_bit(WL1271_FLAG_IDLE, &wl->flags);
} else {
- /* increment the session counter */
- wl->session_counter++;
- if (wl->session_counter >= SESSION_COUNTER_MAX)
- wl->session_counter = 0;
-
/* The current firmware only supports sched_scan in idle */
if (wl->sched_scanning) {
wl1271_scan_sched_scan_stop(wl);
ieee80211_sched_scan_stopped(wl->hw);
}
- ret = wl1271_dummy_join(wl);
+ ret = wl12xx_cmd_role_start_dev(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_roc(wl, wl->dev_role_id);
if (ret < 0)
goto out;
clear_bit(WL1271_FLAG_IDLE, &wl->flags);
@@ -1983,6 +2332,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wl->channel = channel;
}
+ if ((changed & IEEE80211_CONF_CHANGE_POWER))
+ wl->power_level = conf->power_level;
+
goto out;
}
@@ -1996,6 +2348,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
((wl->band != conf->channel->band) ||
(wl->channel != channel))) {
+ /* send all pending packets */
+ wl1271_tx_work_locked(wl);
wl->band = conf->channel->band;
wl->channel = channel;
@@ -2009,17 +2363,41 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
wl1271_set_band_rate(wl);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
wl1271_warning("rate policy for channel "
"failed %d", ret);
- if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ if (wl12xx_is_roc(wl)) {
+ /* roaming */
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out_sleep;
+ }
ret = wl1271_join(wl, false);
if (ret < 0)
wl1271_warning("cmd join on channel "
"failed %d", ret);
+ } else {
+ /*
+ * change the ROC channel. do it only if we are
+ * not idle. otherwise, CROC will be called
+ * anyway.
+ */
+ if (wl12xx_is_roc(wl) &&
+ !(conf->flags & IEEE80211_CONF_IDLE)) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl12xx_roc(wl, wl->dev_role_id);
+ if (ret < 0)
+ wl1271_warning("roc failed %d",
+ ret);
+ }
}
}
}
@@ -2159,18 +2537,11 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
goto out_sleep;
}
- /* determine, whether supported filter values have changed */
- if (changed == 0)
- goto out_sleep;
-
- /* configure filters */
- wl->filters = *total;
- wl1271_configure_filters(wl, 0);
-
- /* apply configured filters */
- ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
- if (ret < 0)
- goto out_sleep;
+ /*
+ * the fw doesn't provide an api to configure the filters. instead,
+ * the filters configuration is based on the active roles / ROC
+ * state.
+ */
out_sleep:
wl1271_ps_elp_sleep(wl);
@@ -2242,14 +2613,19 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
bool wep_key_added = false;
for (i = 0; i < MAX_NUM_KEYS; i++) {
+ u8 hlid;
if (wl->recorded_ap_keys[i] == NULL)
break;
key = wl->recorded_ap_keys[i];
+ hlid = key->hlid;
+ if (hlid == WL12XX_INVALID_LINK_ID)
+ hlid = wl->ap_bcast_hlid;
+
ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE,
key->id, key->key_type,
key->key_size, key->key,
- key->hlid, key->tx_seq_32,
+ hlid, key->tx_seq_32,
key->tx_seq_16);
if (ret < 0)
goto out;
@@ -2259,7 +2635,8 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
}
if (wep_key_added) {
- ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key);
+ ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key,
+ wl->ap_bcast_hlid);
if (ret < 0)
goto out;
}
@@ -2284,7 +2661,7 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
wl_sta = (struct wl1271_station *)sta->drv_priv;
hlid = wl_sta->hlid;
} else {
- hlid = WL1271_AP_BROADCAST_HLID;
+ hlid = wl->ap_bcast_hlid;
}
if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
@@ -2314,6 +2691,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
+ /*
+ * A STA set to GEM cipher requires 2 tx spare blocks.
+ * Return to default value when GEM cipher key is removed
+ */
+ if (key_type == KEY_GEM) {
+ if (action == KEY_ADD_OR_REPLACE)
+ wl->tx_spare_blocks = 2;
+ else if (action == KEY_REMOVE)
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ }
+
addr = sta ? sta->addr : bcast_addr;
if (is_zero_ether_addr(addr)) {
@@ -2328,6 +2716,11 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr))
return 0;
+ /* don't remove key if hlid was already deleted */
+ if (action == KEY_REMOVE &&
+ wl->sta_hlid == WL12XX_INVALID_LINK_ID)
+ return 0;
+
ret = wl1271_cmd_set_sta_key(wl, action,
id, key_type, key_size,
key, addr, tx_seq_32,
@@ -2337,8 +2730,9 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
/* the default WEP key needs to be configured at least once */
if (key_type == KEY_WEP) {
- ret = wl1271_cmd_set_sta_default_wep_key(wl,
- wl->default_key);
+ ret = wl12xx_cmd_set_default_wep_key(wl,
+ wl->default_key,
+ wl->sta_hlid);
if (ret < 0)
return ret;
}
@@ -2480,16 +2874,64 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- ret = wl1271_scan(hw->priv, ssid, len, req);
+ /* cancel ROC before scanning */
+ if (wl12xx_is_roc(wl)) {
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ /* don't allow scanning right now */
+ ret = -EBUSY;
+ goto out_sleep;
+ }
+ wl12xx_croc(wl, wl->dev_role_id);
+ wl12xx_cmd_role_stop_dev(wl);
+ }
+ ret = wl1271_scan(hw->priv, ssid, len, req);
+out_sleep:
wl1271_ps_elp_sleep(wl);
-
out:
mutex_unlock(&wl->mutex);
return ret;
}
+static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ if (wl->scan.state != WL1271_SCAN_STATE_DONE) {
+ ret = wl1271_scan_stop(wl);
+ if (ret < 0)
+ goto out_sleep;
+ }
+ wl->scan.state = WL1271_SCAN_STATE_IDLE;
+ memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
+ wl->scan.req = NULL;
+ ieee80211_scan_completed(wl->hw, true);
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+
+ cancel_delayed_work_sync(&wl->scan_complete_work);
+}
+
static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
@@ -2623,6 +3065,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
return 0;
}
+static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset)
+{
+ int len;
+ const u8 *next, *end = skb->data + skb->len;
+ u8 *ie = (u8 *)cfg80211_find_ie(eid, skb->data + ieoffset,
+ skb->len - ieoffset);
+ if (!ie)
+ return;
+ len = ie[1] + 2;
+ next = ie + len;
+ memmove(ie, next, end - next);
+ skb_trim(skb, skb->len - len);
+}
+
+static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
+ unsigned int oui, u8 oui_type,
+ int ieoffset)
+{
+ int len;
+ const u8 *next, *end = skb->data + skb->len;
+ u8 *ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
+ skb->data + ieoffset,
+ skb->len - ieoffset);
+ if (!ie)
+ return;
+ len = ie[1] + 2;
+ next = ie + len;
+ memmove(ie, next, end - next);
+ skb_trim(skb, skb->len - len);
+}
+
+static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
+ u8 *probe_rsp_data,
+ size_t probe_rsp_len,
+ u32 rates)
+{
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE];
+ int ssid_ie_offset, ie_offset, templ_len;
+ const u8 *ptr;
+
+ /* no need to change probe response if the SSID is set correctly */
+ if (wl->ssid_len > 0)
+ return wl1271_cmd_template_set(wl,
+ CMD_TEMPL_AP_PROBE_RESPONSE,
+ probe_rsp_data,
+ probe_rsp_len, 0,
+ rates);
+
+ if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) {
+ wl1271_error("probe_rsp template too big");
+ return -EINVAL;
+ }
+
+ /* start searching from IE offset */
+ ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+
+ ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset,
+ probe_rsp_len - ie_offset);
+ if (!ptr) {
+ wl1271_error("No SSID in beacon!");
+ return -EINVAL;
+ }
+
+ ssid_ie_offset = ptr - probe_rsp_data;
+ ptr += (ptr[1] + 2);
+
+ memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset);
+
+ /* insert SSID from bss_conf */
+ probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID;
+ probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len;
+ memcpy(probe_rsp_templ + ssid_ie_offset + 2,
+ bss_conf->ssid, bss_conf->ssid_len);
+ templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len;
+
+ memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len,
+ ptr, probe_rsp_len - (ptr - probe_rsp_data));
+ templ_len += probe_rsp_len - (ptr - probe_rsp_data);
+
+ return wl1271_cmd_template_set(wl,
+ CMD_TEMPL_AP_PROBE_RESPONSE,
+ probe_rsp_templ,
+ templ_len, 0,
+ rates);
+}
+
static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
struct ieee80211_bss_conf *bss_conf,
u32 changed)
@@ -2679,6 +3208,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BEACON)) {
struct ieee80211_hdr *hdr;
+ u32 min_rate;
int ieoffset = offsetof(struct ieee80211_mgmt,
u.beacon.variable);
struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
@@ -2694,28 +3224,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
dev_kfree_skb(beacon);
goto out;
}
+ min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
CMD_TEMPL_BEACON;
ret = wl1271_cmd_template_set(wl, tmpl_id,
beacon->data,
beacon->len, 0,
- wl1271_tx_min_rate_get(wl));
+ min_rate);
if (ret < 0) {
dev_kfree_skb(beacon);
goto out;
}
+ /* remove TIM ie from probe response */
+ wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
+
+ /*
+ * remove p2p ie from probe response.
+ * the fw reponds to probe requests that don't include
+ * the p2p ie. probe requests with p2p ie will be passed,
+ * and will be responded by the supplicant (the spec
+ * forbids including the p2p ie when responding to probe
+ * requests that didn't include it).
+ */
+ wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA,
+ WLAN_OUI_TYPE_WFA_P2P, ieoffset);
+
hdr = (struct ieee80211_hdr *) beacon->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
-
- tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
- CMD_TEMPL_PROBE_RESPONSE;
- ret = wl1271_cmd_template_set(wl,
- tmpl_id,
- beacon->data,
- beacon->len, 0,
- wl1271_tx_min_rate_get(wl));
+ if (is_ap)
+ ret = wl1271_ap_set_probe_resp_tmpl(wl,
+ beacon->data,
+ beacon->len,
+ min_rate);
+ else
+ ret = wl1271_cmd_template_set(wl,
+ CMD_TEMPL_PROBE_RESPONSE,
+ beacon->data,
+ beacon->len, 0,
+ min_rate);
dev_kfree_skb(beacon);
if (ret < 0)
goto out;
@@ -2736,8 +3284,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BASIC_RATES)) {
u32 rates = bss_conf->basic_rates;
- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates,
+ wl->band);
+ wl->basic_rate = wl1271_tx_min_rate_get(wl,
+ wl->basic_rate_set);
ret = wl1271_init_ap_rates(wl);
if (ret < 0) {
@@ -2757,20 +3307,20 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BEACON_ENABLED)) {
if (bss_conf->enable_beacon) {
if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
- ret = wl1271_cmd_start_bss(wl);
+ ret = wl12xx_cmd_role_start_ap(wl);
if (ret < 0)
goto out;
- set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
- wl1271_debug(DEBUG_AP, "started AP");
-
ret = wl1271_ap_init_hwenc(wl);
if (ret < 0)
goto out;
+
+ set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+ wl1271_debug(DEBUG_AP, "started AP");
}
} else {
if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
- ret = wl1271_cmd_stop_bss(wl);
+ ret = wl12xx_cmd_role_stop_ap(wl);
if (ret < 0)
goto out;
@@ -2780,27 +3330,21 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
}
}
- if (changed & BSS_CHANGED_IBSS) {
- wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
- bss_conf->ibss_joined);
-
- if (bss_conf->ibss_joined) {
- u32 rates = bss_conf->basic_rates;
- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
- rates);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
+ if (ret < 0)
+ goto out;
- /* by default, use 11b rates */
- wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
- ret = wl1271_acx_sta_rate_policies(wl);
- if (ret < 0)
- goto out;
+ /* Handle HT information change */
+ if ((changed & BSS_CHANGED_HT) &&
+ (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ ret = wl1271_acx_set_ht_information(wl,
+ bss_conf->ht_operation_mode);
+ if (ret < 0) {
+ wl1271_warning("Set ht information failed %d", ret);
+ goto out;
}
}
- ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
- if (ret < 0)
- goto out;
out:
return;
}
@@ -2813,6 +3357,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
{
bool do_join = false, set_assoc = false;
bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+ bool ibss_joined = false;
u32 sta_rate_set = 0;
int ret;
struct ieee80211_sta *sta;
@@ -2826,14 +3371,28 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
goto out;
}
- if ((changed & BSS_CHANGED_BEACON_INT) && is_ibss)
+ if (changed & BSS_CHANGED_IBSS) {
+ if (bss_conf->ibss_joined) {
+ set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags);
+ ibss_joined = true;
+ } else {
+ if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED,
+ &wl->flags)) {
+ wl1271_unjoin(wl);
+ wl12xx_cmd_role_start_dev(wl);
+ wl12xx_roc(wl, wl->dev_role_id);
+ }
+ }
+ }
+
+ if ((changed & BSS_CHANGED_BEACON_INT) && ibss_joined)
do_join = true;
/* Need to update the SSID (for filtering etc) */
- if ((changed & BSS_CHANGED_BEACON) && is_ibss)
+ if ((changed & BSS_CHANGED_BEACON) && ibss_joined)
do_join = true;
- if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) {
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) && ibss_joined) {
wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s",
bss_conf->enable_beacon ? "enabled" : "disabled");
@@ -2873,17 +3432,17 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if (ret < 0)
goto out;
- /* filter out all packets not from this BSSID */
- wl1271_configure_filters(wl, 0);
-
/* Need to update the BSSID (for filtering etc) */
do_join = true;
}
}
- rcu_read_lock();
- sta = ieee80211_find_sta(vif, bss_conf->bssid);
- if (sta) {
+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(vif, bss_conf->bssid);
+ if (!sta)
+ goto sta_not_found;
+
/* save the supp_rates of the ap */
sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
if (sta->ht_cap.ht_supported)
@@ -2891,38 +3450,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
sta_ht_cap = sta->ht_cap;
sta_exists = true;
- }
- rcu_read_unlock();
- if (sta_exists) {
- /* handle new association with HT and HT information change */
- if ((changed & BSS_CHANGED_HT) &&
- (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
- ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
- true);
- if (ret < 0) {
- wl1271_warning("Set ht cap true failed %d",
- ret);
- goto out;
- }
- ret = wl1271_acx_set_ht_information(wl,
- bss_conf->ht_operation_mode);
- if (ret < 0) {
- wl1271_warning("Set ht information failed %d",
- ret);
- goto out;
- }
- }
- /* handle new association without HT and disassociation */
- else if (changed & BSS_CHANGED_ASSOC) {
- ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
- false);
- if (ret < 0) {
- wl1271_warning("Set ht cap false failed %d",
- ret);
- goto out;
- }
- }
+sta_not_found:
+ rcu_read_unlock();
}
if ((changed & BSS_CHANGED_ASSOC)) {
@@ -2939,12 +3469,15 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
* to use with control frames.
*/
rates = bss_conf->basic_rates;
- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
- rates);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate_set =
+ wl1271_tx_enabled_rates_get(wl, rates,
+ wl->band);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
if (sta_rate_set)
wl->rate_set = wl1271_tx_enabled_rates_get(wl,
- sta_rate_set);
+ sta_rate_set,
+ wl->band);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
goto out;
@@ -2972,25 +3505,14 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
ret = wl1271_acx_conn_monit_params(wl, true);
if (ret < 0)
goto out;
-
- /* If we want to go in PSM but we're not there yet */
- if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
- !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- enum wl1271_cmd_ps_mode mode;
-
- mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode,
- wl->basic_rate,
- true);
- if (ret < 0)
- goto out;
- }
} else {
/* use defaults when not associated */
bool was_assoc =
!!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED,
&wl->flags);
- clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
+ bool was_ifup =
+ !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT,
+ &wl->flags);
wl->aid = 0;
/* free probe-request template */
@@ -3002,7 +3524,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
/* revert back to minimum rates for the current band */
wl1271_set_band_rate(wl);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
goto out;
@@ -3017,12 +3540,56 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
/* restore the bssid filter and go to dummy bssid */
if (was_assoc) {
+ u32 conf_flags = wl->hw->conf.flags;
+ /*
+ * we might have to disable roc, if there was
+ * no IF_OPER_UP notification.
+ */
+ if (!was_ifup) {
+ ret = wl12xx_croc(wl, wl->role_id);
+ if (ret < 0)
+ goto out;
+ }
+ /*
+ * (we also need to disable roc in case of
+ * roaming on the same channel. until we will
+ * have a better flow...)
+ */
+ if (test_bit(wl->dev_role_id, wl->roc_map)) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+ }
+
wl1271_unjoin(wl);
- wl1271_dummy_join(wl);
+ if (!(conf_flags & IEEE80211_CONF_IDLE)) {
+ wl12xx_cmd_role_start_dev(wl);
+ wl12xx_roc(wl, wl->dev_role_id);
+ }
}
}
}
+ if (changed & BSS_CHANGED_IBSS) {
+ wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
+ bss_conf->ibss_joined);
+
+ if (bss_conf->ibss_joined) {
+ u32 rates = bss_conf->basic_rates;
+ wl->basic_rate_set =
+ wl1271_tx_enabled_rates_get(wl, rates,
+ wl->band);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
+
+ /* by default, use 11b + OFDM rates */
+ wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
+ ret = wl1271_acx_sta_rate_policies(wl);
+ if (ret < 0)
+ goto out;
+ }
+ }
+
ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
if (ret < 0)
goto out;
@@ -3061,6 +3628,81 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
wl1271_warning("cmd join failed %d", ret);
goto out;
}
+
+ /* ROC until connected (after EAPOL exchange) */
+ if (!is_ibss) {
+ ret = wl12xx_roc(wl, wl->role_id);
+ if (ret < 0)
+ goto out;
+
+ wl1271_check_operstate(wl,
+ ieee80211_get_operstate(vif));
+ }
+ /*
+ * stop device role if started (we might already be in
+ * STA role). TODO: make it better.
+ */
+ if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_role_stop_dev(wl);
+ if (ret < 0)
+ goto out;
+ }
+
+ /* If we want to go in PSM but we're not there yet */
+ if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
+ !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ enum wl1271_cmd_ps_mode mode;
+
+ mode = STATION_POWER_SAVE_MODE;
+ ret = wl1271_ps_set_mode(wl, mode,
+ wl->basic_rate,
+ true);
+ if (ret < 0)
+ goto out;
+ }
+ }
+
+ /* Handle new association with HT. Do this after join. */
+ if (sta_exists) {
+ if ((changed & BSS_CHANGED_HT) &&
+ (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ ret = wl1271_acx_set_ht_capabilities(wl,
+ &sta_ht_cap,
+ true,
+ wl->sta_hlid);
+ if (ret < 0) {
+ wl1271_warning("Set ht cap true failed %d",
+ ret);
+ goto out;
+ }
+ }
+ /* handle new association without HT and disassociation */
+ else if (changed & BSS_CHANGED_ASSOC) {
+ ret = wl1271_acx_set_ht_capabilities(wl,
+ &sta_ht_cap,
+ false,
+ wl->sta_hlid);
+ if (ret < 0) {
+ wl1271_warning("Set ht cap false failed %d",
+ ret);
+ goto out;
+ }
+ }
+ }
+
+ /* Handle HT information change. Done after join. */
+ if ((changed & BSS_CHANGED_HT) &&
+ (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ ret = wl1271_acx_set_ht_information(wl,
+ bss_conf->ht_operation_mode);
+ if (ret < 0) {
+ wl1271_warning("Set ht information failed %d", ret);
+ goto out;
+ }
}
out:
@@ -3099,7 +3741,8 @@ out:
mutex_unlock(&wl->mutex);
}
-static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int wl1271_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct wl1271 *wl = hw->priv;
@@ -3170,7 +3813,8 @@ out:
return ret;
}
-static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw)
+static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct wl1271 *wl = hw->priv;
@@ -3230,25 +3874,31 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
}
wl_sta = (struct wl1271_station *)sta->drv_priv;
- __set_bit(id, wl->ap_hlid_map);
+ set_bit(id, wl->ap_hlid_map);
wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
*hlid = wl_sta->hlid;
memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
+ wl->active_sta_count++;
return 0;
}
-static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
+void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
{
int id = hlid - WL1271_AP_STA_HLID_START;
- if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+ if (hlid < WL1271_AP_STA_HLID_START)
return;
- __clear_bit(id, wl->ap_hlid_map);
+ if (!test_bit(id, wl->ap_hlid_map))
+ return;
+
+ clear_bit(id, wl->ap_hlid_map);
memset(wl->links[hlid].addr, 0, ETH_ALEN);
+ wl->links[hlid].ba_bitmap = 0;
wl1271_tx_reset_link_queues(wl, hlid);
__clear_bit(hlid, &wl->ap_ps_map);
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+ wl->active_sta_count--;
}
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
@@ -3277,7 +3927,15 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
if (ret < 0)
goto out_free_sta;
- ret = wl1271_cmd_add_sta(wl, sta, hlid);
+ ret = wl12xx_cmd_add_peer(wl, sta, hlid);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl12xx_cmd_set_peer_state(wl, hlid);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid);
if (ret < 0)
goto out_sleep;
@@ -3320,7 +3978,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
+ ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
if (ret < 0)
goto out_sleep;
@@ -3342,6 +4000,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
{
struct wl1271 *wl = hw->priv;
int ret;
+ u8 hlid, *ba_bitmap;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
+ tid);
+
+ /* sanity check - the fields in FW are only 8bits wide */
+ if (WARN_ON(tid > 0xFF))
+ return -ENOTSUPP;
mutex_lock(&wl->mutex);
@@ -3350,26 +4016,69 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
goto out;
}
+ if (wl->bss_type == BSS_TYPE_STA_BSS) {
+ hlid = wl->sta_hlid;
+ ba_bitmap = &wl->ba_rx_bitmap;
+ } else if (wl->bss_type == BSS_TYPE_AP_BSS) {
+ struct wl1271_station *wl_sta;
+
+ wl_sta = (struct wl1271_station *)sta->drv_priv;
+ hlid = wl_sta->hlid;
+ ba_bitmap = &wl->links[hlid].ba_bitmap;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
+
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
+ wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu: Rx tid %d action %d",
+ tid, action);
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
- if (wl->ba_support) {
- ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
- true);
- if (!ret)
- wl->ba_rx_bitmap |= BIT(tid);
- } else {
+ if (!wl->ba_support || !wl->ba_allowed) {
ret = -ENOTSUPP;
+ break;
+ }
+
+ if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) {
+ ret = -EBUSY;
+ wl1271_error("exceeded max RX BA sessions");
+ break;
+ }
+
+ if (*ba_bitmap & BIT(tid)) {
+ ret = -EINVAL;
+ wl1271_error("cannot enable RX BA session on active "
+ "tid: %d", tid);
+ break;
+ }
+
+ ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
+ hlid);
+ if (!ret) {
+ *ba_bitmap |= BIT(tid);
+ wl->ba_rx_session_count++;
}
break;
case IEEE80211_AMPDU_RX_STOP:
- ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
- if (!ret)
- wl->ba_rx_bitmap &= ~BIT(tid);
+ if (!(*ba_bitmap & BIT(tid))) {
+ ret = -EINVAL;
+ wl1271_error("no active RX BA session on tid: %d",
+ tid);
+ break;
+ }
+
+ ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
+ hlid);
+ if (!ret) {
+ *ba_bitmap &= ~BIT(tid);
+ wl->ba_rx_session_count--;
+ }
break;
/*
@@ -3395,6 +4104,60 @@ out:
return ret;
}
+static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct wl1271 *wl = hw->priv;
+ int i;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x",
+ mask->control[NL80211_BAND_2GHZ].legacy,
+ mask->control[NL80211_BAND_5GHZ].legacy);
+
+ mutex_lock(&wl->mutex);
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ wl->bitrate_masks[i] =
+ wl1271_tx_enabled_rates_get(wl,
+ mask->control[i].legacy,
+ i);
+ mutex_unlock(&wl->mutex);
+
+ return 0;
+}
+
+static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF)) {
+ mutex_unlock(&wl->mutex);
+ ieee80211_chswitch_done(wl->vif, false);
+ return;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_channel_switch(wl, ch_switch);
+
+ if (!ret)
+ set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags);
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
@@ -3406,7 +4169,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
goto out;
/* packets are considered pending if in the TX queue or the FW */
- ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0);
+ ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0);
/* the above is appropriate for STA mode for PS purposes */
WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
@@ -3511,7 +4274,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
/* 11n STA capabilities */
#define HW_RX_HIGHEST_RATE 72
-#ifdef CONFIG_WL12XX_HT
#define WL12XX_HT_CAP { \
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
@@ -3524,11 +4286,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
.tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
}, \
}
-#else
-#define WL12XX_HT_CAP { \
- .ht_supported = false, \
-}
-#endif
/* can't be const, mac80211 writes to this */
static struct ieee80211_supported_band wl1271_band_2ghz = {
@@ -3569,40 +4326,40 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
/* 5 GHz band channels for WL1273 */
static struct ieee80211_channel wl1271_channels_5ghz[] = {
- { .hw_value = 7, .center_freq = 5035},
- { .hw_value = 8, .center_freq = 5040},
- { .hw_value = 9, .center_freq = 5045},
- { .hw_value = 11, .center_freq = 5055},
- { .hw_value = 12, .center_freq = 5060},
- { .hw_value = 16, .center_freq = 5080},
- { .hw_value = 34, .center_freq = 5170},
- { .hw_value = 36, .center_freq = 5180},
- { .hw_value = 38, .center_freq = 5190},
- { .hw_value = 40, .center_freq = 5200},
- { .hw_value = 42, .center_freq = 5210},
- { .hw_value = 44, .center_freq = 5220},
- { .hw_value = 46, .center_freq = 5230},
- { .hw_value = 48, .center_freq = 5240},
- { .hw_value = 52, .center_freq = 5260},
- { .hw_value = 56, .center_freq = 5280},
- { .hw_value = 60, .center_freq = 5300},
- { .hw_value = 64, .center_freq = 5320},
- { .hw_value = 100, .center_freq = 5500},
- { .hw_value = 104, .center_freq = 5520},
- { .hw_value = 108, .center_freq = 5540},
- { .hw_value = 112, .center_freq = 5560},
- { .hw_value = 116, .center_freq = 5580},
- { .hw_value = 120, .center_freq = 5600},
- { .hw_value = 124, .center_freq = 5620},
- { .hw_value = 128, .center_freq = 5640},
- { .hw_value = 132, .center_freq = 5660},
- { .hw_value = 136, .center_freq = 5680},
- { .hw_value = 140, .center_freq = 5700},
- { .hw_value = 149, .center_freq = 5745},
- { .hw_value = 153, .center_freq = 5765},
- { .hw_value = 157, .center_freq = 5785},
- { .hw_value = 161, .center_freq = 5805},
- { .hw_value = 165, .center_freq = 5825},
+ { .hw_value = 7, .center_freq = 5035, .max_power = 25 },
+ { .hw_value = 8, .center_freq = 5040, .max_power = 25 },
+ { .hw_value = 9, .center_freq = 5045, .max_power = 25 },
+ { .hw_value = 11, .center_freq = 5055, .max_power = 25 },
+ { .hw_value = 12, .center_freq = 5060, .max_power = 25 },
+ { .hw_value = 16, .center_freq = 5080, .max_power = 25 },
+ { .hw_value = 34, .center_freq = 5170, .max_power = 25 },
+ { .hw_value = 36, .center_freq = 5180, .max_power = 25 },
+ { .hw_value = 38, .center_freq = 5190, .max_power = 25 },
+ { .hw_value = 40, .center_freq = 5200, .max_power = 25 },
+ { .hw_value = 42, .center_freq = 5210, .max_power = 25 },
+ { .hw_value = 44, .center_freq = 5220, .max_power = 25 },
+ { .hw_value = 46, .center_freq = 5230, .max_power = 25 },
+ { .hw_value = 48, .center_freq = 5240, .max_power = 25 },
+ { .hw_value = 52, .center_freq = 5260, .max_power = 25 },
+ { .hw_value = 56, .center_freq = 5280, .max_power = 25 },
+ { .hw_value = 60, .center_freq = 5300, .max_power = 25 },
+ { .hw_value = 64, .center_freq = 5320, .max_power = 25 },
+ { .hw_value = 100, .center_freq = 5500, .max_power = 25 },
+ { .hw_value = 104, .center_freq = 5520, .max_power = 25 },
+ { .hw_value = 108, .center_freq = 5540, .max_power = 25 },
+ { .hw_value = 112, .center_freq = 5560, .max_power = 25 },
+ { .hw_value = 116, .center_freq = 5580, .max_power = 25 },
+ { .hw_value = 120, .center_freq = 5600, .max_power = 25 },
+ { .hw_value = 124, .center_freq = 5620, .max_power = 25 },
+ { .hw_value = 128, .center_freq = 5640, .max_power = 25 },
+ { .hw_value = 132, .center_freq = 5660, .max_power = 25 },
+ { .hw_value = 136, .center_freq = 5680, .max_power = 25 },
+ { .hw_value = 140, .center_freq = 5700, .max_power = 25 },
+ { .hw_value = 149, .center_freq = 5745, .max_power = 25 },
+ { .hw_value = 153, .center_freq = 5765, .max_power = 25 },
+ { .hw_value = 157, .center_freq = 5785, .max_power = 25 },
+ { .hw_value = 161, .center_freq = 5805, .max_power = 25 },
+ { .hw_value = 165, .center_freq = 5825, .max_power = 25 },
};
/* mapping to indexes for wl1271_rates_5ghz */
@@ -3663,6 +4420,7 @@ static const struct ieee80211_ops wl1271_ops = {
.tx = wl1271_op_tx,
.set_key = wl1271_op_set_key,
.hw_scan = wl1271_op_hw_scan,
+ .cancel_hw_scan = wl1271_op_cancel_hw_scan,
.sched_scan_start = wl1271_op_sched_scan_start,
.sched_scan_stop = wl1271_op_sched_scan_stop,
.bss_info_changed = wl1271_op_bss_info_changed,
@@ -3675,6 +4433,8 @@ static const struct ieee80211_ops wl1271_ops = {
.sta_remove = wl1271_op_sta_remove,
.ampdu_action = wl1271_op_ampdu_action,
.tx_frames_pending = wl1271_tx_frames_pending,
+ .set_bitrate_mask = wl12xx_set_bitrate_mask,
+ .channel_switch = wl12xx_op_channel_switch,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
@@ -3778,9 +4538,72 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
return len;
}
-static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(hw_pg_ver, S_IRUGO,
wl1271_sysfs_show_hw_pg_ver, NULL);
+static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct wl1271 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+ int ret;
+
+ ret = mutex_lock_interruptible(&wl->mutex);
+ if (ret < 0)
+ return -ERESTARTSYS;
+
+ /* Let only one thread read the log at a time, blocking others */
+ while (wl->fwlog_size == 0) {
+ DEFINE_WAIT(wait);
+
+ prepare_to_wait_exclusive(&wl->fwlog_waitq,
+ &wait,
+ TASK_INTERRUPTIBLE);
+
+ if (wl->fwlog_size != 0) {
+ finish_wait(&wl->fwlog_waitq, &wait);
+ break;
+ }
+
+ mutex_unlock(&wl->mutex);
+
+ schedule();
+ finish_wait(&wl->fwlog_waitq, &wait);
+
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ ret = mutex_lock_interruptible(&wl->mutex);
+ if (ret < 0)
+ return -ERESTARTSYS;
+ }
+
+ /* Check if the fwlog is still valid */
+ if (wl->fwlog_size < 0) {
+ mutex_unlock(&wl->mutex);
+ return 0;
+ }
+
+ /* Seeking is not supported - old logs are not kept. Disregard pos. */
+ len = min(count, (size_t)wl->fwlog_size);
+ wl->fwlog_size -= len;
+ memcpy(buffer, wl->fwlog, len);
+
+ /* Make room for new messages */
+ memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);
+
+ mutex_unlock(&wl->mutex);
+
+ return len;
+}
+
+static struct bin_attribute fwlog_attr = {
+ .attr = {.name = "fwlog", .mode = S_IRUSR},
+ .read = wl1271_sysfs_read_fwlog,
+};
+
int wl1271_register_hw(struct wl1271 *wl)
{
int ret;
@@ -3864,22 +4687,32 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_SUPPORTS_CQM_RSSI |
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_AP_LINK_PS;
+ IEEE80211_HW_AP_LINK_PS |
+ IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_TX_AMPDU_SETUP_IN_HW;
wl->hw->wiphy->cipher_suites = cipher_suites;
wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+ BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
wl->hw->wiphy->max_scan_ssids = 1;
+ wl->hw->wiphy->max_sched_scan_ssids = 16;
+ wl->hw->wiphy->max_match_sets = 16;
/*
* Maximum length of elements in scanning probe request templates
* should be the maximum length possible for a template, without
* the IEEE80211 header of the template
*/
- wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
+ wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
sizeof(struct ieee80211_header);
+ wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
+ sizeof(struct ieee80211_header);
+
+ wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+
/* make sure all our channels fit in the scanned_ch bitmask */
BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
ARRAY_SIZE(wl1271_channels_5ghz) >
@@ -3923,6 +4756,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
int i, j, ret;
unsigned int order;
+ BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS);
+
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
wl1271_error("could not alloc ieee80211_hw");
@@ -3961,12 +4796,21 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_WORK(&wl->tx_work, wl1271_tx_work);
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+ INIT_WORK(&wl->rx_streaming_enable_work,
+ wl1271_rx_streaming_enable_work);
+ INIT_WORK(&wl->rx_streaming_disable_work,
+ wl1271_rx_streaming_disable_work);
+
+ wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
+ if (!wl->freezable_wq) {
+ ret = -ENOMEM;
+ goto err_hw;
+ }
+
wl->channel = WL1271_DEFAULT_CHANNEL;
wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
wl->default_key = 0;
wl->rx_counter = 0;
- wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
- wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
wl->psm_entry_retry = 0;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
@@ -3979,13 +4823,31 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->hw_pg_ver = -1;
wl->bss_type = MAX_BSS_TYPE;
wl->set_bss_type = MAX_BSS_TYPE;
- wl->fw_bss_type = MAX_BSS_TYPE;
wl->last_tx_hlid = 0;
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
wl->quirks = 0;
wl->platform_quirks = 0;
wl->sched_scanning = false;
+ wl->tx_security_seq = 0;
+ wl->tx_security_last_seq_lsb = 0;
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ wl->role_id = WL12XX_INVALID_ROLE_ID;
+ wl->system_hlid = WL12XX_SYSTEM_HLID;
+ wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+ wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
+ wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+ wl->session_counter = 0;
+ wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+ wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
+ wl->active_sta_count = 0;
+ setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
+ (unsigned long) wl);
+ wl->fwlog_size = 0;
+ init_waitqueue_head(&wl->fwlog_waitq);
+
+ /* The system link is always allocated */
+ __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
@@ -3998,12 +4860,14 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
/* Apply default driver configuration. */
wl1271_conf_init(wl);
+ wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
+ wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
order = get_order(WL1271_AGGR_BUFFER_SIZE);
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
if (!wl->aggr_buf) {
ret = -ENOMEM;
- goto err_hw;
+ goto err_wq;
}
wl->dummy_packet = wl12xx_alloc_dummy_packet(wl);
@@ -4012,11 +4876,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
goto err_aggr;
}
+ /* Allocate one page for the FW log */
+ wl->fwlog = (u8 *)get_zeroed_page(GFP_KERNEL);
+ if (!wl->fwlog) {
+ ret = -ENOMEM;
+ goto err_dummy_packet;
+ }
+
/* Register platform device */
ret = platform_device_register(wl->plat_dev);
if (ret) {
wl1271_error("couldn't register platform device");
- goto err_dummy_packet;
+ goto err_fwlog;
}
dev_set_drvdata(&wl->plat_dev->dev, wl);
@@ -4034,20 +4905,36 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
goto err_bt_coex_state;
}
+ /* Create sysfs file for the FW log */
+ ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr);
+ if (ret < 0) {
+ wl1271_error("failed to create sysfs file fwlog");
+ goto err_hw_pg_ver;
+ }
+
return hw;
+err_hw_pg_ver:
+ device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver);
+
err_bt_coex_state:
device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);
err_platform:
platform_device_unregister(wl->plat_dev);
+err_fwlog:
+ free_page((unsigned long)wl->fwlog);
+
err_dummy_packet:
dev_kfree_skb(wl->dummy_packet);
err_aggr:
free_pages((unsigned long)wl->aggr_buf, order);
+err_wq:
+ destroy_workqueue(wl->freezable_wq);
+
err_hw:
wl1271_debugfs_exit(wl);
kfree(plat_dev);
@@ -4063,7 +4950,19 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int wl1271_free_hw(struct wl1271 *wl)
{
+ /* Unblock any fwlog readers */
+ mutex_lock(&wl->mutex);
+ wl->fwlog_size = -1;
+ wake_up_interruptible_all(&wl->fwlog_waitq);
+ mutex_unlock(&wl->mutex);
+
+ device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr);
+
+ device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver);
+
+ device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);
platform_device_unregister(wl->plat_dev);
+ free_page((unsigned long)wl->fwlog);
dev_kfree_skb(wl->dummy_packet);
free_pages((unsigned long)wl->aggr_buf,
get_order(WL1271_AGGR_BUFFER_SIZE));
@@ -4078,6 +4977,7 @@ int wl1271_free_hw(struct wl1271 *wl)
kfree(wl->fw_status);
kfree(wl->tx_res_if);
+ destroy_workqueue(wl->freezable_wq);
ieee80211_free_hw(wl->hw);
@@ -4090,6 +4990,13 @@ EXPORT_SYMBOL_GPL(wl12xx_debug_level);
module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
+module_param_named(fwlog, fwlog_param, charp, 0);
+MODULE_PARM_DESC(keymap,
+ "FW logger options: continuous, ondemand, dbgpins or disable");
+
+module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index b59b677..c15ebf2 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
if (ret == 0) {
wl1271_error("ELP wakeup timeout!");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
ret = -ETIMEDOUT;
goto err;
} else if (ret < 0) {
@@ -169,9 +169,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
wl1271_debug(DEBUG_PSM, "leaving psm");
/* disable beacon early termination */
- ret = wl1271_acx_bet_enable(wl, false);
- if (ret < 0)
- return ret;
+ if (wl->band == IEEE80211_BAND_2GHZ) {
+ ret = wl1271_acx_bet_enable(wl, false);
+ if (ret < 0)
+ return ret;
+ }
/* disable beacon filtering */
ret = wl1271_acx_beacon_filter_opt(wl, false);
@@ -191,24 +193,31 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
{
- int i, filtered = 0;
+ int i;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
unsigned long flags;
+ int filtered[NUM_TX_QUEUES];
- /* filter all frames currently the low level queus for this hlid */
+ /* filter all frames currently in the low level queues for this hlid */
for (i = 0; i < NUM_TX_QUEUES; i++) {
+ filtered[i] = 0;
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+ filtered[i]++;
+
+ if (WARN_ON(wl12xx_is_dummy_packet(wl, skb)))
+ continue;
+
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
info->status.rates[0].idx = -1;
- ieee80211_tx_status(wl->hw, skb);
- filtered++;
+ ieee80211_tx_status_ni(wl->hw, skb);
}
}
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count -= filtered;
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] -= filtered[i];
spin_unlock_irqrestore(&wl->wl_lock, flags);
wl1271_handle_tx_low_watermark(wl);
@@ -221,8 +230,8 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
if (test_bit(hlid, &wl->ap_ps_map))
return;
- wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
- "clean_queues %d", hlid, wl->links[hlid].allocated_blks,
+ wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
+ "clean_queues %d", hlid, wl->links[hlid].allocated_pkts,
clean_queues);
rcu_read_lock();
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h
index 440a4ee..3f570f3 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/reg.h
@@ -296,81 +296,6 @@
===============================================*/
#define REG_EVENT_MAILBOX_PTR (SCR_PAD1)
-
-/* Misc */
-
-#define REG_ENABLE_TX_RX (ENABLE)
-/*
- * Rx configuration (filter) information element
- * ---------------------------------------------
- */
-#define REG_RX_CONFIG (RX_CFG)
-#define REG_RX_FILTER (RX_FILTER_CFG)
-
-
-#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002
-
-/* promiscuous - receives all valid frames */
-#define RX_CFG_PROMISCUOUS 0x0008
-
-/* receives frames from any BSSID */
-#define RX_CFG_BSSID 0x0020
-
-/* receives frames destined to any MAC address */
-#define RX_CFG_MAC 0x0010
-
-#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010
-#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000
-#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020
-#define RX_CFG_ENABLE_ANY_BSSID 0x0000
-
-/* discards all broadcast frames */
-#define RX_CFG_DISABLE_BCAST 0x0200
-
-#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400
-#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
-#define RX_CFG_COPY_RX_STATUS 0x2000
-#define RX_CFG_TSF 0x10000
-
-#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
- RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
- | RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
- RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
- | RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \
- | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
- | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
-
-#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \
- RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \
- RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
- | CFG_RX_CTL_EN | CFG_RX_BCN_EN\
- | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
-
-#define RX_FILTER_OPTION_FILTER_ALL 0
-
-#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
- | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
-
-#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
- | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
- | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
- | CFG_RX_PRSP_EN)
-
-
/*===============================================
EEPROM Read/Write Request 32bit RW
------------------------------------------
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 7009103..dee4cfe 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -22,6 +22,7 @@
*/
#include <linux/gfp.h>
+#include <linux/sched.h>
#include "wl12xx.h"
#include "acx.h"
@@ -29,20 +30,28 @@
#include "rx.h"
#include "io.h"
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
+static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
{
return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_MEM_BLOCK_MASK;
}
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
+static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
{
return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
}
+static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
+ u32 drv_rx_counter)
+{
+ /* Convert the value to bool */
+ return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
+ RX_BUF_UNALIGNED_PAYLOAD);
+}
+
static void wl1271_rx_status(struct wl1271 *wl,
struct wl1271_rx_descriptor *desc,
struct ieee80211_rx_status *status,
@@ -57,11 +66,9 @@ static void wl1271_rx_status(struct wl1271 *wl,
status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
-#ifdef CONFIG_WL12XX_HT
/* 11n support */
if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
status->flag |= RX_FLAG_HT;
-#endif
status->signal = desc->rssi;
@@ -88,13 +95,17 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
}
-static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
+static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
+ bool unaligned)
{
struct wl1271_rx_descriptor *desc;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
u8 *buf;
u8 beacon = 0;
+ u8 is_data = 0;
+ u8 reserved = unaligned ? NET_IP_ALIGN : 0;
+ u16 seq_num;
/*
* In PLT mode we seem to get frames and mac80211 warns about them,
@@ -106,6 +117,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) data;
+ if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) {
+ size_t len = length - sizeof(*desc);
+ wl12xx_copy_fwlog(wl, data + sizeof(*desc), len);
+ wake_up_interruptible(&wl->fwlog_waitq);
+ return 0;
+ }
+
switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {
/* discard corrupted packets */
case WL1271_RX_DESC_DRIVER_RX_Q_FAIL:
@@ -122,37 +140,49 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
return -EINVAL;
}
- skb = __dev_alloc_skb(length, GFP_KERNEL);
+ /* skb length not included rx descriptor */
+ skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL);
if (!skb) {
wl1271_error("Couldn't allocate RX frame");
return -ENOMEM;
}
- buf = skb_put(skb, length);
- memcpy(buf, data, length);
+ /* reserve the unaligned payload(if any) */
+ skb_reserve(skb, reserved);
+
+ buf = skb_put(skb, length - sizeof(*desc));
- /* now we pull the descriptor out of the buffer */
- skb_pull(skb, sizeof(*desc));
+ /*
+ * Copy packets from aggregation buffer to the skbs without rx
+ * descriptor and with packet payload aligned care. In case of unaligned
+ * packets copy the packets in offset of 2 bytes guarantee IP header
+ * payload aligned to 4 bytes.
+ */
+ memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control))
beacon = 1;
+ if (ieee80211_is_data_present(hdr->frame_control))
+ is_data = 1;
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
- wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb,
+ seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+ wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb,
skb->len - desc->pad_len,
- beacon ? "beacon" : "");
+ beacon ? "beacon" : "",
+ seq_num);
skb_trim(skb, skb->len - desc->pad_len);
skb_queue_tail(&wl->deferred_rx_queue, skb);
- ieee80211_queue_work(wl->hw, &wl->netstack_work);
+ queue_work(wl->freezable_wq, &wl->netstack_work);
- return 0;
+ return is_data;
}
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
+void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
u32 buf_size;
@@ -162,12 +192,15 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
u32 mem_block;
u32 pkt_length;
u32 pkt_offset;
+ bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+ bool had_data = false;
+ bool unaligned = false;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
rx_counter = drv_rx_counter;
while (rx_counter != fw_rx_counter) {
- pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
+ pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
break;
buf_size += pkt_length;
@@ -186,7 +219,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* For aggregated packets, only the first memory block
* should be retrieved. The FW takes care of the rest.
*/
- mem_block = wl1271_rx_get_mem_block(status,
+ mem_block = wl12xx_rx_get_mem_block(status,
drv_rx_counter);
wl->rx_mem_pool_addr.addr = (mem_block << 8) +
@@ -207,16 +240,22 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
/* Split data into separate packets */
pkt_offset = 0;
while (pkt_offset < buf_size) {
- pkt_length = wl1271_rx_get_buf_size(status,
+ pkt_length = wl12xx_rx_get_buf_size(status,
drv_rx_counter);
+
+ unaligned = wl12xx_rx_get_unaligned(status,
+ drv_rx_counter);
+
/*
* the handle data call can only fail in memory-outage
* conditions, in that case the received frame will just
* be dropped.
*/
- wl1271_rx_handle_data(wl,
- wl->aggr_buf + pkt_offset,
- pkt_length);
+ if (wl1271_rx_handle_data(wl,
+ wl->aggr_buf + pkt_offset,
+ pkt_length, unaligned) == 1)
+ had_data = true;
+
wl->rx_counter++;
drv_rx_counter++;
drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
@@ -230,15 +269,18 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
*/
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
-}
-void wl1271_set_default_filters(struct wl1271 *wl)
-{
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
- wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
- } else {
- wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
- wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
+ if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+ u32 timeout = wl->conf.rx_streaming.duration;
+
+ /* restart rx streaming */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ ieee80211_queue_work(wl->hw,
+ &wl->rx_streaming_enable_work);
+
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(timeout));
}
}
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 75fabf8..86ba6b1 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -86,16 +86,30 @@
* Bits 3-5 - process_id tag (AP mode FW)
* Bits 6-7 - reserved
*/
-#define WL1271_RX_DESC_STATUS_MASK 0x07
+#define WL1271_RX_DESC_STATUS_MASK 0x03
#define WL1271_RX_DESC_SUCCESS 0x00
#define WL1271_RX_DESC_DECRYPT_FAIL 0x01
#define WL1271_RX_DESC_MIC_FAIL 0x02
#define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03
-#define RX_MEM_BLOCK_MASK 0xFF
-#define RX_BUF_SIZE_MASK 0xFFF00
-#define RX_BUF_SIZE_SHIFT_DIV 6
+#define RX_MEM_BLOCK_MASK 0xFF
+#define RX_BUF_SIZE_MASK 0xFFF00
+#define RX_BUF_SIZE_SHIFT_DIV 6
+/* If set, the start of IP payload is not 4 bytes aligned */
+#define RX_BUF_UNALIGNED_PAYLOAD BIT(20)
+
+enum {
+ WL12XX_RX_CLASS_UNKNOWN,
+ WL12XX_RX_CLASS_MANAGEMENT,
+ WL12XX_RX_CLASS_DATA,
+ WL12XX_RX_CLASS_QOS_DATA,
+ WL12XX_RX_CLASS_BCN_PRBRSP,
+ WL12XX_RX_CLASS_EAPOL,
+ WL12XX_RX_CLASS_BA_EVENT,
+ WL12XX_RX_CLASS_AMSDU,
+ WL12XX_RX_CLASS_LOGGER,
+};
struct wl1271_rx_descriptor {
__le16 length;
@@ -107,16 +121,12 @@ struct wl1271_rx_descriptor {
u8 snr;
__le32 timestamp;
u8 packet_class;
- union {
- u8 process_id; /* STA FW */
- u8 hlid; /* AP FW */
- } __packed;
+ u8 hlid;
u8 pad_len;
u8 reserved;
} __packed;
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
+void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
-void wl1271_set_default_filters(struct wl1271 *wl);
#endif
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 9542e46..fc29c67 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -28,11 +28,14 @@
#include "scan.h"
#include "acx.h"
#include "ps.h"
+#include "tx.h"
void wl1271_scan_complete_work(struct work_struct *work)
{
struct delayed_work *dwork;
struct wl1271 *wl;
+ int ret;
+ bool is_sta, is_ibss;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, scan_complete_work);
@@ -50,21 +53,35 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan.req = NULL;
- ieee80211_scan_completed(wl->hw, false);
- /* restore hardware connection monitoring template */
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
- if (wl1271_ps_elp_wakeup(wl) == 0) {
- wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
- wl1271_ps_elp_sleep(wl);
- }
+ /* restore hardware connection monitoring template */
+ wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
}
+ /* return to ROC if needed */
+ is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
+ is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+ if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
+ (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
+ !test_bit(wl->dev_role_id, wl->roc_map)) {
+ /* restore remain on channel */
+ wl12xx_cmd_role_start_dev(wl);
+ wl12xx_roc(wl, wl->dev_role_id);
+ }
+ wl1271_ps_elp_sleep(wl);
+
if (wl->scan.failed) {
wl1271_info("Scan completed due to error.");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
}
+ ieee80211_scan_completed(wl->hw, false);
+
out:
mutex_unlock(&wl->mutex);
@@ -157,12 +174,14 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
goto out;
}
- /* We always use high priority scans */
- scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
-
if (passive)
scan_options |= WL1271_SCAN_OPT_PASSIVE;
+ if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ cmd->params.role_id = wl->role_id;
cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
@@ -174,10 +193,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
}
cmd->params.tx_rate = cpu_to_le32(basic_rate);
- cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
- cmd->params.rx_filter_options =
- cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
-
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.tid_trigger = 0;
@@ -193,6 +208,8 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
}
+ memcpy(cmd->addr, wl->mac_addr, ETH_ALEN);
+
ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
wl->scan.req->ie, wl->scan.req->ie_len,
band);
@@ -227,14 +244,17 @@ out:
void wl1271_scan_stm(struct wl1271 *wl)
{
int ret = 0;
+ enum ieee80211_band band;
+ u32 rate;
switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE:
break;
case WL1271_SCAN_STATE_2GHZ_ACTIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false,
- wl->conf.tx.basic_rate);
+ band = IEEE80211_BAND_2GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
wl1271_scan_stm(wl);
@@ -243,8 +263,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_2GHZ_PASSIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
- wl->conf.tx.basic_rate);
+ band = IEEE80211_BAND_2GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
@@ -256,8 +277,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_5GHZ_ACTIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false,
- wl->conf.tx.basic_rate_5);
+ band = IEEE80211_BAND_5GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
wl1271_scan_stm(wl);
@@ -266,8 +288,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_5GHZ_PASSIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true,
- wl->conf.tx.basic_rate_5);
+ band = IEEE80211_BAND_5GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl);
@@ -328,12 +351,39 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
return 0;
}
+int wl1271_scan_stop(struct wl1271 *wl)
+{
+ struct wl1271_cmd_header *cmd = NULL;
+ int ret = 0;
+
+ if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE))
+ return -EINVAL;
+
+ wl1271_debug(DEBUG_CMD, "cmd scan stop");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd,
+ sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("cmd stop_scan failed");
+ goto out;
+ }
+out:
+ kfree(cmd);
+ return ret;
+}
+
static int
wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct conn_scan_ch_params *channels,
u32 band, bool radar, bool passive,
- int start)
+ int start, int max_channels)
{
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
int i, j;
@@ -341,7 +391,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
bool force_passive = !req->n_ssids;
for (i = 0, j = start;
- i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS;
+ i < req->n_channels && j < max_channels;
i++) {
flags = req->channels[i]->flags;
@@ -387,46 +437,42 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
return j - start;
}
-static int
+static bool
wl1271_scan_sched_scan_channels(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct wl1271_cmd_sched_scan_config *cfg)
{
- int idx = 0;
-
cfg->passive[0] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,
IEEE80211_BAND_2GHZ,
- false, true, idx);
- idx += cfg->passive[0];
-
+ false, true, 0,
+ MAX_CHANNELS_2GHZ);
cfg->active[0] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,
IEEE80211_BAND_2GHZ,
- false, false, idx);
- /*
- * 5GHz channels always start at position 14, not immediately
- * after the last 2.4GHz channel
- */
- idx = 14;
-
+ false, false,
+ cfg->passive[0],
+ MAX_CHANNELS_2GHZ);
cfg->passive[1] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
IEEE80211_BAND_5GHZ,
- false, true, idx);
- idx += cfg->passive[1];
-
+ false, true, 0,
+ MAX_CHANNELS_5GHZ);
cfg->dfs =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
IEEE80211_BAND_5GHZ,
- true, true, idx);
- idx += cfg->dfs;
-
+ true, true,
+ cfg->passive[1],
+ MAX_CHANNELS_5GHZ);
cfg->active[1] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
IEEE80211_BAND_5GHZ,
- false, false, idx);
- idx += cfg->active[1];
+ false, false,
+ cfg->passive[1] + cfg->dfs,
+ MAX_CHANNELS_5GHZ);
+ /* 802.11j channels are not supported yet */
+ cfg->passive[2] = 0;
+ cfg->active[2] = 0;
wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d",
cfg->active[0], cfg->passive[0]);
@@ -434,7 +480,108 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->active[1], cfg->passive[1]);
wl1271_debug(DEBUG_SCAN, " DFS: %d", cfg->dfs);
- return idx;
+ return cfg->passive[0] || cfg->active[0] ||
+ cfg->passive[1] || cfg->active[1] || cfg->dfs ||
+ cfg->passive[2] || cfg->active[2];
+}
+
+/* Returns the scan type to be used or a negative value on error */
+static int
+wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
+ struct cfg80211_match_set *sets = req->match_sets;
+ struct cfg80211_ssid *ssids = req->ssids;
+ int ret = 0, type, i, j, n_match_ssids = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
+
+ /* count the match sets that contain SSIDs */
+ for (i = 0; i < req->n_match_sets; i++)
+ if (sets[i].ssid.ssid_len > 0)
+ n_match_ssids++;
+
+ /* No filter, no ssids or only bcast ssid */
+ if (!n_match_ssids &&
+ (!req->n_ssids ||
+ (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
+ type = SCAN_SSID_FILTER_ANY;
+ goto out;
+ }
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!n_match_ssids) {
+ /* No filter, with ssids */
+ type = SCAN_SSID_FILTER_DISABLED;
+
+ for (i = 0; i < req->n_ssids; i++) {
+ cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
+ SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
+ cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
+ ssids[i].ssid_len);
+ cmd->n_ssids++;
+ }
+ } else {
+ type = SCAN_SSID_FILTER_LIST;
+
+ /* Add all SSIDs from the filters */
+ for (i = 0; i < req->n_match_sets; i++) {
+ /* ignore sets without SSIDs */
+ if (!sets[i].ssid.ssid_len)
+ continue;
+
+ cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
+ cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid,
+ sets[i].ssid.ssid, sets[i].ssid.ssid_len);
+ cmd->n_ssids++;
+ }
+ if ((req->n_ssids > 1) ||
+ (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
+ /*
+ * Mark all the SSIDs passed in the SSID list as HIDDEN,
+ * so they're used in probe requests.
+ */
+ for (i = 0; i < req->n_ssids; i++) {
+ for (j = 0; j < cmd->n_ssids; j++)
+ if (!memcmp(req->ssids[i].ssid,
+ cmd->ssids[j].ssid,
+ req->ssids[i].ssid_len)) {
+ cmd->ssids[j].type =
+ SCAN_SSID_TYPE_HIDDEN;
+ break;
+ }
+ /* Fail if SSID isn't present in the filters */
+ if (j == cmd->n_ssids) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ }
+ }
+ }
+
+ wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
+
+ ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
+ sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("cmd sched scan ssid list failed");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+out:
+ if (ret < 0)
+ return ret;
+ return type;
}
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
@@ -443,7 +590,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
{
struct wl1271_cmd_sched_scan_config *cfg = NULL;
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
- int i, total_channels, ret;
+ int i, ret;
bool force_passive = !req->n_ssids;
wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
@@ -468,18 +615,16 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
cfg->intervals[i] = cpu_to_le32(req->interval);
- if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {
- cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
- cfg->ssid_len = req->ssids[0].ssid_len;
- memcpy(cfg->ssid, req->ssids[0].ssid,
- req->ssids[0].ssid_len);
- } else {
- cfg->filter_type = SCAN_SSID_FILTER_ANY;
- cfg->ssid_len = 0;
- }
+ cfg->ssid_len = 0;
+ ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
+ if (ret < 0)
+ goto out;
+
+ cfg->filter_type = ret;
+
+ wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
- total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg);
- if (total_channels == 0) {
+ if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
wl1271_error("scan channel list is empty");
ret = -EINVAL;
goto out;
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index a0b6c5d..9211515 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -28,6 +28,7 @@
int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
struct cfg80211_scan_request *req);
+int wl1271_scan_stop(struct wl1271 *wl);
int wl1271_scan_build_probe_req(struct wl1271 *wl,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band);
@@ -45,7 +46,10 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
#define WL1271_SCAN_CURRENT_TX_PWR 0
#define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1
+#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
+/* scan even if we fail to enter psm */
+#define WL1271_SCAN_OPT_FORCE 8
#define WL1271_SCAN_BAND_2_4_GHZ 0
#define WL1271_SCAN_BAND_5_GHZ 1
@@ -61,27 +65,27 @@ enum {
};
struct basic_scan_params {
- __le32 rx_config_options;
- __le32 rx_filter_options;
/* Scan option flags (WL1271_SCAN_OPT_*) */
__le16 scan_options;
+ u8 role_id;
/* Number of scan channels in the list (maximum 30) */
u8 n_ch;
/* This field indicates the number of probe requests to send
per channel for an active scan */
u8 n_probe_reqs;
- /* Rate bit field for sending the probes */
- __le32 tx_rate;
u8 tid_trigger;
u8 ssid_len;
- /* in order to align */
- u8 padding1[2];
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 use_ssid_list;
+
+ /* Rate bit field for sending the probes */
+ __le32 tx_rate;
+
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
/* Band to scan */
u8 band;
- u8 use_ssid_list;
+
u8 scan_tag;
- u8 padding2;
+ u8 padding2[2];
} __packed;
struct basic_scan_channel_params {
@@ -104,6 +108,10 @@ struct wl1271_cmd_scan {
struct basic_scan_params params;
struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
+
+ /* src mac address */
+ u8 addr[ETH_ALEN];
+ u8 padding[2];
} __packed;
struct wl1271_cmd_trigger_scan_to {
@@ -112,19 +120,14 @@ struct wl1271_cmd_trigger_scan_to {
__le32 timeout;
} __packed;
-#define MAX_CHANNELS_ALL_BANDS 41
+#define MAX_CHANNELS_2GHZ 14
+#define MAX_CHANNELS_5GHZ 23
+#define MAX_CHANNELS_4GHZ 4
+
#define SCAN_MAX_CYCLE_INTERVALS 16
#define SCAN_MAX_BANDS 3
enum {
- SCAN_CHANNEL_TYPE_2GHZ_PASSIVE,
- SCAN_CHANNEL_TYPE_2GHZ_ACTIVE,
- SCAN_CHANNEL_TYPE_5GHZ_PASSIVE,
- SCAN_CHANNEL_TYPE_5GHZ_ACTIVE,
- SCAN_CHANNEL_TYPE_5GHZ_DFS,
-};
-
-enum {
SCAN_SSID_FILTER_ANY = 0,
SCAN_SSID_FILTER_SPECIFIC = 1,
SCAN_SSID_FILTER_LIST = 2,
@@ -171,7 +174,7 @@ struct wl1271_cmd_sched_scan_config {
u8 filter_type;
u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 n_probe_reqs; /* Number of probes requests per channel */
@@ -182,11 +185,13 @@ struct wl1271_cmd_sched_scan_config {
u8 padding[3];
- struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS];
+ struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ];
+ struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ];
+ struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
} __packed;
-#define SCHED_SCAN_MAX_SSIDS 8
+#define SCHED_SCAN_MAX_SSIDS 16
enum {
SCAN_SSID_TYPE_PUBLIC = 0,
@@ -196,7 +201,7 @@ enum {
struct wl1271_ssid {
u8 type;
u8 len;
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
/* u8 padding[2]; */
} __packed;
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 536e506..516a898 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -23,7 +23,6 @@
#include <linux/irq.h>
#include <linux/module.h>
-#include <linux/crc7.h>
#include <linux/vmalloc.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
@@ -45,7 +44,7 @@
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
-static const struct sdio_device_id wl1271_devices[] = {
+static const struct sdio_device_id wl1271_devices[] __devinitconst = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
{}
};
@@ -107,14 +106,6 @@ static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)
enable_irq(wl->irq);
}
-static void wl1271_sdio_reset(struct wl1271 *wl)
-{
-}
-
-static void wl1271_sdio_init(struct wl1271 *wl)
-{
-}
-
static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
@@ -170,15 +161,17 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
struct sdio_func *func = wl_to_func(wl);
int ret;
- /* Make sure the card will not be powered off by runtime PM */
- ret = pm_runtime_get_sync(&func->dev);
- if (ret < 0)
- goto out;
-
- /* Runtime PM might be disabled, so power up the card manually */
- ret = mmc_power_restore_host(func->card->host);
- if (ret < 0)
- goto out;
+ /* If enabled, tell runtime PM not to power off the card */
+ if (pm_runtime_enabled(&func->dev)) {
+ ret = pm_runtime_get_sync(&func->dev);
+ if (ret < 0)
+ goto out;
+ } else {
+ /* Runtime PM is disabled: power up the card manually */
+ ret = mmc_power_restore_host(func->card->host);
+ if (ret < 0)
+ goto out;
+ }
sdio_claim_host(func);
sdio_enable_func(func);
@@ -195,13 +188,16 @@ static int wl1271_sdio_power_off(struct wl1271 *wl)
sdio_disable_func(func);
sdio_release_host(func);
- /* Runtime PM might be disabled, so power off the card manually */
+ /* Power off the card manually, even if runtime PM is enabled. */
ret = mmc_power_save_host(func->card->host);
if (ret < 0)
return ret;
- /* Let runtime PM know the card is powered off */
- return pm_runtime_put_sync(&func->dev);
+ /* If enabled, let runtime PM know the card is powered off */
+ if (pm_runtime_enabled(&func->dev))
+ ret = pm_runtime_put_sync(&func->dev);
+
+ return ret;
}
static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
@@ -215,8 +211,6 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
static struct wl1271_if_operations sdio_ops = {
.read = wl1271_sdio_raw_read,
.write = wl1271_sdio_raw_write,
- .reset = wl1271_sdio_reset,
- .init = wl1271_sdio_init,
.power = wl1271_sdio_set_power,
.dev = wl1271_sdio_wl_to_dev,
.enable_irq = wl1271_sdio_enable_interrupts,
@@ -278,17 +272,19 @@ static int __devinit wl1271_probe(struct sdio_func *func,
goto out_free;
}
- enable_irq_wake(wl->irq);
- device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
+ ret = enable_irq_wake(wl->irq);
+ if (!ret) {
+ wl->irq_wake_enabled = true;
+ device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
- disable_irq(wl->irq);
-
- /* if sdio can keep power while host is suspended, enable wow */
- mmcflags = sdio_get_host_pm_caps(func);
- wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
+ /* if sdio can keep power while host is suspended, enable wow */
+ mmcflags = sdio_get_host_pm_caps(func);
+ wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
- if (mmcflags & MMC_PM_KEEP_POWER)
- hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+ if (mmcflags & MMC_PM_KEEP_POWER)
+ hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+ }
+ disable_irq(wl->irq);
ret = wl1271_init_ieee80211(wl);
if (ret)
@@ -303,8 +299,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle(&func->dev);
- wl1271_notice("initialized");
-
return 0;
out_irq:
@@ -324,8 +318,10 @@ static void __devexit wl1271_remove(struct sdio_func *func)
pm_runtime_get_noresume(&func->dev);
wl1271_unregister_hw(wl);
- device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
- disable_irq_wake(wl->irq);
+ if (wl->irq_wake_enabled) {
+ device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
+ disable_irq_wake(wl->irq);
+ }
free_irq(wl->irq, wl);
wl1271_free_hw(wl);
}
@@ -402,23 +398,12 @@ static struct sdio_driver wl1271_sdio_driver = {
static int __init wl1271_init(void)
{
- int ret;
-
- ret = sdio_register_driver(&wl1271_sdio_driver);
- if (ret < 0) {
- wl1271_error("failed to register sdio driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
+ return sdio_register_driver(&wl1271_sdio_driver);
}
static void __exit wl1271_exit(void)
{
sdio_unregister_driver(&wl1271_sdio_driver);
-
- wl1271_notice("unloaded");
}
module_init(wl1271_init);
@@ -427,7 +412,5 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL127X_AP_FW_NAME);
-MODULE_FIRMWARE(WL128X_AP_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index f289153..f25d5d9 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -30,6 +30,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include <linux/gpio.h>
#include <linux/wl12xx.h>
#include <linux/kthread.h>
@@ -142,14 +143,23 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
ret = pm_runtime_get_sync(&func->dev);
if (ret < 0)
goto out;
+
+ /* Runtime PM might be disabled, power up the card manually */
+ ret = mmc_power_restore_host(func->card->host);
+ if (ret < 0)
+ goto out;
+
sdio_claim_host(func);
sdio_enable_func(func);
- sdio_release_host(func);
} else {
- sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
+ /* Runtime PM might be disabled, power off the card manually */
+ ret = mmc_power_save_host(func->card->host);
+ if (ret < 0)
+ goto out;
+
/* Power down the card */
ret = pm_runtime_put_sync(&func->dev);
}
@@ -193,7 +203,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
ret = request_firmware(&fw, WL128X_FW_NAME,
wl1271_wl_to_dev(wl));
else
- ret = request_firmware(&fw, WL1271_FW_NAME,
+ ret = request_firmware(&fw, WL127X_FW_NAME,
wl1271_wl_to_dev(wl));
if (ret < 0) {
@@ -433,7 +443,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
sdio_set_drvdata(func, wl_test);
-
/* power up the device */
ret = wl1271_chip_wakeup(wl);
if (ret) {
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 51662bb..0f97186 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
@@ -435,8 +436,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
if (ret)
goto out_irq;
- wl1271_notice("initialized");
-
return 0;
out_irq:
@@ -473,23 +472,12 @@ static struct spi_driver wl1271_spi_driver = {
static int __init wl1271_init(void)
{
- int ret;
-
- ret = spi_register_driver(&wl1271_spi_driver);
- if (ret < 0) {
- wl1271_error("failed to register spi driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
+ return spi_register_driver(&wl1271_spi_driver);
}
static void __exit wl1271_exit(void)
{
spi_unregister_driver(&wl1271_spi_driver);
-
- wl1271_notice("unloaded");
}
module_init(wl1271_init);
@@ -498,8 +486,6 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL127X_AP_FW_NAME);
-MODULE_FIRMWARE(WL128X_AP_FW_NAME);
MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
index da351d7..abfb120 100644
--- a/drivers/net/wireless/wl12xx/testmode.c
+++ b/drivers/net/wireless/wl12xx/testmode.c
@@ -36,7 +36,7 @@ enum wl1271_tm_commands {
WL1271_TM_CMD_TEST,
WL1271_TM_CMD_INTERROGATE,
WL1271_TM_CMD_CONFIGURE,
- WL1271_TM_CMD_NVS_PUSH,
+ WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */
WL1271_TM_CMD_SET_PLT_MODE,
WL1271_TM_CMD_RECOVER,
@@ -139,12 +139,15 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
if (ret < 0) {
wl1271_warning("testmode cmd interrogate failed: %d", ret);
+ kfree(cmd);
return ret;
}
skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
- if (!skb)
+ if (!skb) {
+ kfree(cmd);
return -ENOMEM;
+ }
NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
@@ -187,48 +190,6 @@ static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
return 0;
}
-static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
-{
- int ret = 0;
- size_t len;
- void *buf;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push");
-
- if (!tb[WL1271_TM_ATTR_DATA])
- return -EINVAL;
-
- buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
- len = nla_len(tb[WL1271_TM_ATTR_DATA]);
-
- mutex_lock(&wl->mutex);
-
- kfree(wl->nvs);
-
- if ((wl->chip.id == CHIP_ID_1283_PG20) &&
- (len != sizeof(struct wl128x_nvs_file)))
- return -EINVAL;
- else if (len != sizeof(struct wl1271_nvs_file))
- return -EINVAL;
-
- wl->nvs = kzalloc(len, GFP_KERNEL);
- if (!wl->nvs) {
- wl1271_error("could not allocate memory for the nvs file");
- ret = -ENOMEM;
- goto out;
- }
-
- memcpy(wl->nvs, buf, len);
- wl->nvs_len = len;
-
- wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
-
-out:
- mutex_unlock(&wl->mutex);
-
- return ret;
-}
-
static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
{
u32 val;
@@ -260,7 +221,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
{
wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
return 0;
}
@@ -285,8 +246,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
return wl1271_tm_cmd_interrogate(wl, tb);
case WL1271_TM_CMD_CONFIGURE:
return wl1271_tm_cmd_configure(wl, tb);
- case WL1271_TM_CMD_NVS_PUSH:
- return wl1271_tm_cmd_nvs_push(wl, tb);
case WL1271_TM_CMD_SET_PLT_MODE:
return wl1271_tm_cmd_set_plt_mode(wl, tb);
case WL1271_TM_CMD_RECOVER:
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ca3ab1c..bad9e29 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -30,6 +30,7 @@
#include "reg.h"
#include "ps.h"
#include "tx.h"
+#include "event.h"
static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
{
@@ -37,9 +38,10 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
if (is_ap)
- ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
+ ret = wl12xx_cmd_set_default_wep_key(wl, id,
+ wl->ap_bcast_hlid);
else
- ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
+ ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid);
if (ret < 0)
return ret;
@@ -77,9 +79,9 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
+ int ret;
- hdr = (struct ieee80211_hdr *)(skb->data +
- sizeof(struct wl1271_tx_hw_descr));
+ hdr = (struct ieee80211_hdr *)skb->data;
/*
* stop bssid-based filtering before transmitting authentication
@@ -90,9 +92,19 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
if (!ieee80211_is_auth(hdr->frame_control))
return 0;
- wl1271_configure_filters(wl, FIF_OTHER_BSS);
+ if (wl->dev_hlid != WL12XX_INVALID_LINK_ID)
+ goto out;
+
+ wl1271_debug(DEBUG_CMD, "starting device role for roaming");
+ ret = wl12xx_cmd_role_start_dev(wl);
+ if (ret < 0)
+ goto out;
- return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
+ ret = wl12xx_roc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+out:
+ return 0;
}
static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
@@ -113,25 +125,36 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
{
- bool fw_ps;
- u8 tx_blks;
+ bool fw_ps, single_sta;
+ u8 tx_pkts;
/* only regulate station links */
if (hlid < WL1271_AP_STA_HLID_START)
return;
+ if (WARN_ON(!wl1271_is_active_sta(wl, hlid)))
+ return;
+
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
- tx_blks = wl->links[hlid].allocated_blks;
+ tx_pkts = wl->links[hlid].allocated_pkts;
+ single_sta = (wl->active_sta_count == 1);
/*
* if in FW PS and there is enough data in FW we can put the link
* into high-level PS and clean out its TX queues.
+ * Make an exception if this is the only connected station. In this
+ * case FW-memory congestion is not a problem.
*/
- if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+ if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_start(wl, hlid, true);
}
-u8 wl1271_tx_get_hlid(struct sk_buff *skb)
+bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
+{
+ return wl->dummy_packet == skb;
+}
+
+u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
{
struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
@@ -144,14 +167,38 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
} else {
struct ieee80211_hdr *hdr;
+ if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ return wl->system_hlid;
+
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_mgmt(hdr->frame_control))
- return WL1271_AP_GLOBAL_HLID;
+ return wl->ap_global_hlid;
else
- return WL1271_AP_BROADCAST_HLID;
+ return wl->ap_bcast_hlid;
}
}
+static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (wl12xx_is_dummy_packet(wl, skb))
+ return wl->system_hlid;
+
+ if (wl->bss_type == BSS_TYPE_AP_BSS)
+ return wl12xx_tx_get_hlid_ap(wl, skb);
+
+ wl1271_tx_update_filters(wl, skb);
+
+ if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) &&
+ !ieee80211_is_auth(hdr->frame_control) &&
+ !ieee80211_is_assoc_req(hdr->frame_control))
+ return wl->sta_hlid;
+ else
+ return wl->dev_hlid;
+}
+
static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
unsigned int packet_length)
{
@@ -168,13 +215,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 len;
u32 total_blocks;
- int id, ret = -EBUSY;
- u32 spare_blocks;
-
- if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
- spare_blocks = 2;
- else
- spare_blocks = 1;
+ int id, ret = -EBUSY, ac;
+ u32 spare_blocks = wl->tx_spare_blocks;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN;
@@ -188,6 +230,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
in the firmware */
len = wl12xx_calc_packet_alignment(wl, total_len);
+ /* in case of a dummy packet, use default amount of spare mem blocks */
+ if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
+ spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+
total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
spare_blocks;
@@ -208,8 +254,12 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
wl->tx_blocks_available -= total_blocks;
wl->tx_allocated_blocks += total_blocks;
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->links[hlid].allocated_blks += total_blocks;
+ ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+ wl->tx_allocated_pkts[ac]++;
+
+ if (wl->bss_type == BSS_TYPE_AP_BSS &&
+ hlid >= WL1271_AP_STA_HLID_START)
+ wl->links[hlid].allocated_pkts++;
ret = 0;
@@ -223,11 +273,6 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
return ret;
}
-static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
-{
- return wl->dummy_packet == skb;
-}
-
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control,
u8 hlid)
@@ -278,9 +323,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
}
- if (wl->bss_type != BSS_TYPE_AP_BSS) {
- desc->aid = hlid;
+ desc->hlid = hlid;
+ if (wl->bss_type != BSS_TYPE_AP_BSS) {
/* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default
basic rates */
@@ -289,18 +334,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else
rate_idx = ACX_TX_BASIC_RATE;
} else {
- desc->hlid = hlid;
- switch (hlid) {
- case WL1271_AP_GLOBAL_HLID:
+ if (hlid == wl->ap_global_hlid)
rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
- break;
- case WL1271_AP_BROADCAST_HLID:
+ else if (hlid == wl->ap_bcast_hlid)
rate_idx = ACX_TX_AP_MODE_BCST_RATE;
- break;
- default:
+ else
rate_idx = ac;
- break;
- }
}
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
@@ -374,24 +413,23 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
}
}
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- hlid = wl1271_tx_get_hlid(skb);
- else
- hlid = TX_HW_DEFAULT_AID;
+ hlid = wl1271_tx_get_hlid(wl, skb);
+ if (hlid == WL12XX_INVALID_LINK_ID) {
+ wl1271_error("invalid hlid. dropping skb 0x%p", skb);
+ return -EINVAL;
+ }
ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
if (ret < 0)
return ret;
+ wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
+
if (wl->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, hlid);
- } else {
- wl1271_tx_update_filters(wl, skb);
}
- wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
-
/*
* The length of each packet is stored in terms of
* words. Thus, we must pad the skb data to make sure its
@@ -412,20 +450,20 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
return total_len;
}
-u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
+u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
+ enum ieee80211_band rate_band)
{
struct ieee80211_supported_band *band;
u32 enabled_rates = 0;
int bit;
- band = wl->hw->wiphy->bands[wl->band];
+ band = wl->hw->wiphy->bands[rate_band];
for (bit = 0; bit < band->n_bitrates; bit++) {
if (rate_set & 0x1)
enabled_rates |= band->bitrates[bit].hw_value;
rate_set >>= 1;
}
-#ifdef CONFIG_WL12XX_HT
/* MCS rates indication are on bits 16 - 23 */
rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;
@@ -434,7 +472,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
rate_set >>= 1;
}
-#endif
return enabled_rates;
}
@@ -442,37 +479,66 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
{
unsigned long flags;
+ int i;
- if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) &&
- wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) {
- /* firmware buffer has space, restart queues */
- spin_lock_irqsave(&wl->wl_lock, flags);
- ieee80211_wake_queues(wl->hw);
- clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
- spin_unlock_irqrestore(&wl->wl_lock, flags);
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ if (test_bit(i, &wl->stopped_queues_map) &&
+ wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) {
+ /* firmware buffer has space, restart queues */
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ ieee80211_wake_queue(wl->hw,
+ wl1271_tx_get_mac80211_queue(i));
+ clear_bit(i, &wl->stopped_queues_map);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+ }
+ }
+}
+
+static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
+ struct sk_buff_head *queues)
+{
+ int i, q = -1, ac;
+ u32 min_pkts = 0xffffffff;
+
+ /*
+ * Find a non-empty ac where:
+ * 1. There are packets to transmit
+ * 2. The FW has the least allocated blocks
+ *
+ * We prioritize the ACs according to VO>VI>BE>BK
+ */
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ ac = wl1271_tx_get_queue(i);
+ if (!skb_queue_empty(&queues[ac]) &&
+ (wl->tx_allocated_pkts[ac] < min_pkts)) {
+ q = ac;
+ min_pkts = wl->tx_allocated_pkts[q];
+ }
}
+
+ if (q == -1)
+ return NULL;
+
+ return &queues[q];
}
static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
{
struct sk_buff *skb = NULL;
unsigned long flags;
+ struct sk_buff_head *queue;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
- if (skb)
+ queue = wl1271_select_queue(wl, wl->tx_queue);
+ if (!queue)
goto out;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);
+
+ skb = skb_dequeue(queue);
out:
if (skb) {
+ int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count--;
+ wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -484,6 +550,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
struct sk_buff *skb = NULL;
unsigned long flags;
int i, h, start_hlid;
+ struct sk_buff_head *queue;
/* start from the link after the last one */
start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
@@ -492,25 +559,25 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
for (i = 0; i < AP_MAX_LINKS; i++) {
h = (start_hlid + i) % AP_MAX_LINKS;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+ /* only consider connected stations */
+ if (h >= WL1271_AP_STA_HLID_START &&
+ !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
+ continue;
+
+ queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
+ if (!queue)
+ continue;
+
+ skb = skb_dequeue(queue);
if (skb)
- goto out;
+ break;
}
-out:
if (skb) {
+ int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->last_tx_hlid = h;
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count--;
+ wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
} else {
wl->last_tx_hlid = 0;
@@ -531,9 +598,12 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
+ int q;
+
skb = wl->dummy_packet;
+ q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count--;
+ wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -548,7 +618,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
if (wl12xx_is_dummy_packet(wl, skb)) {
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
} else if (wl->bss_type == BSS_TYPE_AP_BSS) {
- u8 hlid = wl1271_tx_get_hlid(skb);
+ u8 hlid = wl1271_tx_get_hlid(wl, skb);
skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
/* make sure we dequeue the same packet next time */
@@ -558,21 +628,33 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
}
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count++;
+ wl->tx_queue_count[q]++;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
+static bool wl1271_tx_is_data_present(struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+
+ return ieee80211_is_data_present(hdr->frame_control);
+}
+
void wl1271_tx_work_locked(struct wl1271 *wl)
{
struct sk_buff *skb;
u32 buf_offset = 0;
bool sent_packets = false;
+ bool had_data = false;
+ bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
int ret;
if (unlikely(wl->state == WL1271_STATE_OFF))
return;
while ((skb = wl1271_skb_dequeue(wl))) {
+ if (wl1271_tx_is_data_present(skb))
+ had_data = true;
+
ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
if (ret == -EAGAIN) {
/*
@@ -619,6 +701,19 @@ out_ack:
wl1271_handle_tx_low_watermark(wl);
}
+ if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+ u32 timeout = wl->conf.rx_streaming.duration;
+
+ /* enable rx streaming */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ ieee80211_queue_work(wl->hw,
+ &wl->rx_streaming_enable_work);
+
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ }
}
void wl1271_tx_work(struct work_struct *work)
@@ -679,10 +774,24 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
wl->stats.retry_count += result->ack_failures;
- /* update security sequence number */
- wl->tx_security_seq += (result->lsb_security_sequence_number -
- wl->tx_security_last_seq);
- wl->tx_security_last_seq = result->lsb_security_sequence_number;
+ /*
+ * update sequence number only when relevant, i.e. only in
+ * sessions of TKIP, AES and GEM (not in open or WEP sessions)
+ */
+ if (info->control.hw_key &&
+ (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
+ info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
+ u8 fw_lsb = result->tx_security_sequence_number_lsb;
+ u8 cur_lsb = wl->tx_security_last_seq_lsb;
+
+ /*
+ * update security sequence number, taking care of potential
+ * wrap-around
+ */
+ wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
+ wl->tx_security_last_seq_lsb = fw_lsb;
+ }
/* remove private header from packet */
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
@@ -702,7 +811,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* return the packet to the stack */
skb_queue_tail(&wl->deferred_tx_queue, skb);
- ieee80211_queue_work(wl->hw, &wl->netstack_work);
+ queue_work(wl->freezable_wq, &wl->netstack_work);
wl1271_free_tx_id(wl, result->id);
}
@@ -747,23 +856,30 @@ void wl1271_tx_complete(struct wl1271 *wl)
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
{
struct sk_buff *skb;
- int i, total = 0;
+ int i;
unsigned long flags;
struct ieee80211_tx_info *info;
+ int total[NUM_TX_QUEUES];
for (i = 0; i < NUM_TX_QUEUES; i++) {
+ total[i] = 0;
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
- info = IEEE80211_SKB_CB(skb);
- info->status.rates[0].idx = -1;
- info->status.rates[0].count = 0;
- ieee80211_tx_status(wl->hw, skb);
- total++;
+
+ if (!wl12xx_is_dummy_packet(wl, skb)) {
+ info = IEEE80211_SKB_CB(skb);
+ info->status.rates[0].idx = -1;
+ info->status.rates[0].count = 0;
+ ieee80211_tx_status_ni(wl->hw, skb);
+ }
+
+ total[i]++;
}
}
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count -= total;
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] -= total[i];
spin_unlock_irqrestore(&wl->wl_lock, flags);
wl1271_handle_tx_low_watermark(wl);
@@ -779,9 +895,10 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
/* TX failure */
if (wl->bss_type == BSS_TYPE_AP_BSS) {
for (i = 0; i < AP_MAX_LINKS; i++) {
+ wl1271_free_sta(wl, i);
wl1271_tx_reset_link_queues(wl, i);
- wl->links[i].allocated_blks = 0;
- wl->links[i].prev_freed_blks = 0;
+ wl->links[i].allocated_pkts = 0;
+ wl->links[i].prev_freed_pkts = 0;
}
wl->last_tx_hlid = 0;
@@ -795,13 +912,18 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info = IEEE80211_SKB_CB(skb);
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status_ni(wl->hw, skb);
}
}
}
+
+ wl->ba_rx_bitmap = 0;
}
- wl->tx_queue_count = 0;
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] = 0;
+
+ wl->stopped_queues_map = 0;
/*
* Make sure the driver is at a consistent state, in case this
@@ -838,7 +960,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status_ni(wl->hw, skb);
}
}
}
@@ -854,8 +976,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
while (!time_after(jiffies, timeout)) {
mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
- wl->tx_frames_cnt, wl->tx_queue_count);
- if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
+ wl->tx_frames_cnt,
+ wl1271_tx_total_queue_count(wl));
+ if ((wl->tx_frames_cnt == 0) &&
+ (wl1271_tx_total_queue_count(wl) == 0)) {
mutex_unlock(&wl->mutex);
return;
}
@@ -866,20 +990,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
wl1271_warning("Unable to flush all TX buffers, timed out.");
}
-u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
{
- int i;
- u32 rate = 0;
-
- if (!wl->basic_rate_set) {
- WARN_ON(1);
- wl->basic_rate_set = wl->conf.tx.basic_rate;
- }
-
- for (i = 0; !rate; i++) {
- if ((wl->basic_rate_set >> i) & 0x1)
- rate = 1 << i;
- }
+ if (WARN_ON(!rate_set))
+ return 0;
- return rate;
+ return BIT(__ffs(rate_set));
}
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 832f925..dc4f09a 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -25,13 +25,11 @@
#ifndef __TX_H__
#define __TX_H__
+#define TX_HW_BLOCK_SPARE_DEFAULT 1
#define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
#define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000
-/* The chipset reference driver states, that the "aid" value 1
- * is for infra-BSS, but is still always used */
-#define TX_HW_DEFAULT_AID 1
#define TX_HW_ATTR_SAVE_RETRIES BIT(0)
#define TX_HW_ATTR_HEADER_PAD BIT(1)
@@ -116,12 +114,8 @@ struct wl1271_tx_hw_descr {
u8 id;
/* The packet TID value (as User-Priority) */
u8 tid;
- union {
- /* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
- u8 aid;
- /* AP - host link ID (HLID) */
- u8 hlid;
- } __packed;
+ /* host link ID (HLID) */
+ u8 hlid;
u8 reserved;
} __packed;
@@ -133,7 +127,8 @@ enum wl1271_tx_hw_res_status {
TX_TIMEOUT = 4,
TX_KEY_NOT_FOUND = 5,
TX_PEER_NOT_FOUND = 6,
- TX_SESSION_MISMATCH = 7
+ TX_SESSION_MISMATCH = 7,
+ TX_LINK_NOT_VALID = 8,
};
struct wl1271_tx_hw_res_descr {
@@ -150,7 +145,7 @@ struct wl1271_tx_hw_res_descr {
(from 1st EDCA AIFS counter until TX Complete). */
__le32 medium_delay;
/* LS-byte of last TKIP seq-num (saved per AC for recovery). */
- u8 lsb_security_sequence_number;
+ u8 tx_security_sequence_number_lsb;
/* Retry count - number of transmissions without successful ACK.*/
u8 ack_failures;
/* The rate that succeeded getting ACK
@@ -182,16 +177,47 @@ static inline int wl1271_tx_get_queue(int queue)
}
}
+static inline int wl1271_tx_get_mac80211_queue(int queue)
+{
+ switch (queue) {
+ case CONF_TX_AC_VO:
+ return 0;
+ case CONF_TX_AC_VI:
+ return 1;
+ case CONF_TX_AC_BE:
+ return 2;
+ case CONF_TX_AC_BK:
+ return 3;
+ default:
+ return 2;
+ }
+}
+
+static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
+{
+ int i, count = 0;
+
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ count += wl->tx_queue_count[i];
+
+ return count;
+}
+
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_work_locked(struct wl1271 *wl);
void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
-u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
-u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
-u8 wl1271_tx_get_hlid(struct sk_buff *skb);
+u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
+ enum ieee80211_band rate_band);
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set);
+u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
+bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
+
+/* from main.c */
+void wl1271_free_sta(struct wl1271 *wl, u8 hlid);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index fbe8f46..1ec90fc 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -112,28 +112,8 @@ extern u32 wl12xx_debug_level;
true); \
} while (0)
-#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \
- CFG_BSSID_FILTER_EN | \
- CFG_MC_FILTER_EN)
-
-#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
- CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
- CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
- CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
-
-#define WL1271_DEFAULT_AP_RX_CONFIG 0
-
-#define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
- CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
- CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
- CFG_RX_ASSOC_EN)
-
-
-
-#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
-#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
-#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
-#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"
+#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
+#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
/*
* wl127x and wl128x are using the same NVS file name. However, the
@@ -144,6 +124,7 @@ extern u32 wl12xx_debug_level;
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
+#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
#define WL1271_CIPHER_SUITE_GEM 0x00147201
@@ -156,26 +137,34 @@ extern u32 wl12xx_debug_level;
#define WL1271_DEFAULT_BEACON_INT 100
#define WL1271_DEFAULT_DTIM_PERIOD 1
-#define WL1271_AP_GLOBAL_HLID 0
-#define WL1271_AP_BROADCAST_HLID 1
-#define WL1271_AP_STA_HLID_START 2
+#define WL12XX_MAX_ROLES 4
+#define WL12XX_MAX_LINKS 12
+#define WL12XX_INVALID_ROLE_ID 0xff
+#define WL12XX_INVALID_LINK_ID 0xff
+
+/* Defined by FW as 0. Will not be freed or allocated. */
+#define WL12XX_SYSTEM_HLID 0
+
+/*
+ * TODO: we currently don't support multirole. remove
+ * this constant from the code when we do.
+ */
+#define WL1271_AP_STA_HLID_START 3
/*
- * When in AP-mode, we allow (at least) this number of mem-blocks
+ * When in AP-mode, we allow (at least) this number of packets
* to be transmitted to FW for a STA in PS-mode. Only when packets are
* present in the FW buffers it will wake the sleeping STA. We want to put
* enough packets for the driver to transmit all of its buffered data before
- * the STA goes to sleep again. But we don't want to take too much mem-blocks
+ * the STA goes to sleep again. But we don't want to take too much memory
* as it might hurt the throughput of active STAs.
- * The number of blocks (18) is enough for 2 large packets.
*/
-#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)
+#define WL1271_PS_STA_MAX_PACKETS 2
#define WL1271_AP_BSS_INDEX 0
-#define WL1271_AP_DEF_INACTIV_SEC 300
#define WL1271_AP_DEF_BEACON_EXP 20
-#define ACX_TX_DESCRIPTORS 32
+#define ACX_TX_DESCRIPTORS 16
#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
@@ -226,6 +215,8 @@ enum {
#define FW_VER_MINOR_1_SPARE_STA_MIN 58
#define FW_VER_MINOR_1_SPARE_AP_MIN 47
+#define FW_VER_MINOR_FWLOG_STA_MIN 70
+
struct wl1271_chip {
u32 id;
char fw_ver_str[ETHTOOL_BUSINFO_LEN];
@@ -243,28 +234,24 @@ struct wl1271_stats {
#define NUM_TX_QUEUES 4
#define NUM_RX_PKT_DESC 8
-#define AP_MAX_STATIONS 5
+#define AP_MAX_STATIONS 8
-/* Broadcast and Global links + links to stations */
-#define AP_MAX_LINKS (AP_MAX_STATIONS + 2)
+/* Broadcast and Global links + system link + links to stations */
+/*
+ * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
+ * the places that use this.
+ */
+#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START)
-/* FW status registers common for AP/STA */
-struct wl1271_fw_common_status {
+/* FW status registers */
+struct wl12xx_fw_status {
__le32 intr;
u8 fw_rx_counter;
u8 drv_rx_counter;
u8 reserved;
u8 tx_results_counter;
__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
- __le32 tx_released_blks[NUM_TX_QUEUES];
__le32 fw_localtime;
-} __packed;
-
-/* FW status registers for AP */
-struct wl1271_fw_ap_status {
- struct wl1271_fw_common_status common;
-
- /* Next fields valid only in AP FW */
/*
* A bitmap (where each bit represents a single HLID)
@@ -272,30 +259,29 @@ struct wl1271_fw_ap_status {
*/
__le32 link_ps_bitmap;
- /* Number of freed MBs per HLID */
- u8 tx_lnk_free_blks[AP_MAX_LINKS];
- u8 padding_1[1];
-} __packed;
+ /*
+ * A bitmap (where each bit represents a single HLID) to indicate
+ * if the station is in Fast mode
+ */
+ __le32 link_fast_bitmap;
-/* FW status registers for STA */
-struct wl1271_fw_sta_status {
- struct wl1271_fw_common_status common;
+ /* Cumulative counter of total released mem blocks since FW-reset */
+ __le32 total_released_blks;
- u8 tx_total;
- u8 reserved1;
- __le16 reserved2;
- /* Total structure size is 68 bytes */
- u32 padding;
-} __packed;
+ /* Size (in Memory Blocks) of TX pool */
+ __le32 tx_total;
-struct wl1271_fw_full_status {
- union {
- struct wl1271_fw_common_status common;
- struct wl1271_fw_sta_status sta;
- struct wl1271_fw_ap_status ap;
- };
-} __packed;
+ /* Cumulative counter of released packets per AC */
+ u8 tx_released_pkts[NUM_TX_QUEUES];
+
+ /* Cumulative counter of freed packets per HLID */
+ u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
+ /* Cumulative counter of released Voice memory blocks */
+ u8 tx_voice_released_blks;
+ u8 padding_1[3];
+ __le32 log_start_addr;
+} __packed;
struct wl1271_rx_mem_pool_addr {
u32 addr;
@@ -308,7 +294,7 @@ struct wl1271_scan {
unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)];
bool failed;
u8 state;
- u8 ssid[IW_ESSID_MAX_SIZE+1];
+ u8 ssid[IEEE80211_MAX_SSID_LEN+1];
size_t ssid_len;
};
@@ -341,7 +327,7 @@ struct wl1271_ap_key {
enum wl12xx_flags {
WL1271_FLAG_STA_ASSOCIATED,
- WL1271_FLAG_JOINED,
+ WL1271_FLAG_IBSS_JOINED,
WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_TX_PENDING,
@@ -359,17 +345,24 @@ enum wl12xx_flags {
WL1271_FLAG_DUMMY_PACKET_PENDING,
WL1271_FLAG_SUSPENDED,
WL1271_FLAG_PENDING_WORK,
+ WL1271_FLAG_SOFT_GEMINI,
+ WL1271_FLAG_RX_STREAMING_STARTED,
+ WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ WL1271_FLAG_CS_PROGRESS,
};
struct wl1271_link {
/* AP-mode - TX queue per AC in link */
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
- /* accounting for allocated / available TX blocks in FW */
- u8 allocated_blks;
- u8 prev_freed_blks;
+ /* accounting for allocated / freed packets in FW */
+ u8 allocated_pkts;
+ u8 prev_freed_pkts;
u8 addr[ETH_ALEN];
+
+ /* bitmap of TIDs where RX BA sessions are active for this link */
+ u8 ba_bitmap;
};
struct wl1271 {
@@ -401,7 +394,6 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
- u8 fw_bss_type;
void *nvs;
size_t nvs_len;
@@ -411,18 +403,37 @@ struct wl1271 {
u8 mac_addr[ETH_ALEN];
u8 bss_type;
u8 set_bss_type;
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 p2p; /* we are using p2p role */
+ u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
int channel;
+ u8 role_id;
+ u8 dev_role_id;
+ u8 system_hlid;
+ u8 sta_hlid;
+ u8 dev_hlid;
+ u8 ap_global_hlid;
+ u8 ap_bcast_hlid;
+
+ unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+ unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+ unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
struct wl1271_acx_mem_map *target_mem_map;
/* Accounting for allocated / available TX blocks on HW */
- u32 tx_blocks_freed[NUM_TX_QUEUES];
+ u32 tx_blocks_freed;
u32 tx_blocks_available;
u32 tx_allocated_blocks;
u32 tx_results_count;
+ /* amount of spare TX blocks to use */
+ u32 tx_spare_blocks;
+
+ /* Accounting for allocated / available Tx packets in HW */
+ u32 tx_pkts_freed[NUM_TX_QUEUES];
+ u32 tx_allocated_pkts[NUM_TX_QUEUES];
+
/* Transmitted TX packets counter for chipset interface */
u32 tx_packets_count;
@@ -434,7 +445,8 @@ struct wl1271 {
/* Frames scheduled for transmission, not handled yet */
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
- int tx_queue_count;
+ int tx_queue_count[NUM_TX_QUEUES];
+ long stopped_queues_map;
/* Frames received, not handled yet by mac80211 */
struct sk_buff_head deferred_rx_queue;
@@ -443,15 +455,23 @@ struct wl1271 {
struct sk_buff_head deferred_tx_queue;
struct work_struct tx_work;
+ struct workqueue_struct *freezable_wq;
/* Pending TX frames */
unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)];
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
int tx_frames_cnt;
- /* Security sequence number counters */
- u8 tx_security_last_seq;
- s64 tx_security_seq;
+ /*
+ * Security sequence number
+ * bits 0-15: lower 16 bits part of sequence number
+ * bits 16-47: higher 32 bits part of sequence number
+ * bits 48-63: not in use
+ */
+ u64 tx_security_seq;
+
+ /* 8 bits of the last sequence number in use */
+ u8 tx_security_last_seq_lsb;
/* FW Rx counter */
u32 rx_counter;
@@ -468,6 +488,15 @@ struct wl1271 {
/* Network stack work */
struct work_struct netstack_work;
+ /* FW log buffer */
+ u8 *fwlog;
+
+ /* Number of valid bytes in the FW log buffer */
+ ssize_t fwlog_size;
+
+ /* Sysfs FW log entry readers wait queue */
+ wait_queue_head_t fwlog_waitq;
+
/* Hardware recovery work */
struct work_struct recovery_work;
@@ -498,6 +527,7 @@ struct wl1271 {
u32 basic_rate_set;
u32 basic_rate;
u32 rate_set;
+ u32 bitrate_masks[IEEE80211_NUM_BANDS];
/* The current band */
enum ieee80211_band band;
@@ -508,9 +538,10 @@ struct wl1271 {
/* Default key (for WEP) */
u32 default_key;
- unsigned int filters;
- unsigned int rx_config;
- unsigned int rx_filter;
+ /* Rx Streaming */
+ struct work_struct rx_streaming_enable_work;
+ struct work_struct rx_streaming_disable_work;
+ struct timer_list rx_streaming_timer;
struct completion *elp_compl;
struct completion *ps_compl;
@@ -535,7 +566,7 @@ struct wl1271 {
u32 buffer_cmd;
u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
- struct wl1271_fw_full_status *fw_status;
+ struct wl12xx_fw_status *fw_status;
struct wl1271_tx_hw_res_if *tx_res_if;
struct ieee80211_vif *vif;
@@ -564,6 +595,7 @@ struct wl1271 {
/* RX BA constraint value */
bool ba_support;
u8 ba_rx_bitmap;
+ bool ba_allowed;
int tcxo_clock;
@@ -572,6 +604,7 @@ struct wl1271 {
* (currently, only "ANY" trigger is supported)
*/
bool wow_enabled;
+ bool irq_wake_enabled;
/*
* AP-mode - links indexed by HLID. The global and broadcast links
@@ -593,6 +626,12 @@ struct wl1271 {
/* Platform limitations */
unsigned int platform_quirks;
+
+ /* number of currently active RX BA sessions */
+ int ba_rx_session_count;
+
+ /* AP-mode - number of currently connected stations */
+ int active_sta_count;
};
struct wl1271_station {
@@ -601,6 +640,9 @@ struct wl1271_station {
int wl1271_plt_start(struct wl1271 *wl);
int wl1271_plt_stop(struct wl1271 *wl);
+int wl1271_recalc_rx_streaming(struct wl1271 *wl);
+void wl12xx_queue_recovery_work(struct wl1271 *wl);
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
@@ -608,8 +650,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_DEFAULT_POWER_LEVEL 0
-#define WL1271_TX_QUEUE_LOW_WATERMARK 10
-#define WL1271_TX_QUEUE_HIGH_WATERMARK 25
+#define WL1271_TX_QUEUE_LOW_WATERMARK 32
+#define WL1271_TX_QUEUE_HIGH_WATERMARK 256
#define WL1271_DEFERRED_QUEUE_LIMIT 64
@@ -627,13 +669,12 @@ int wl1271_plt_stop(struct wl1271 *wl);
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
-/*
- * Older firmwares use 2 spare TX blocks
- * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
- */
-#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1)
-
/* WL128X requires aggregated packets to be aligned to the SDIO block size */
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
+/* Older firmwares did not implement the FW logger over bus feature */
+#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)
+
+#define WL12XX_HW_BLOCK_SIZE 256
+
#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index 18fe542..f7971d3 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -77,7 +77,7 @@ struct wl12xx_ie_header {
struct wl12xx_ie_ssid {
struct wl12xx_ie_header header;
- char ssid[IW_ESSID_MAX_SIZE];
+ char ssid[IEEE80211_MAX_SSID_LEN];
} __packed;
struct wl12xx_ie_rates {
@@ -105,18 +105,6 @@ struct wl12xx_ie_country {
/* Templates */
-struct wl12xx_beacon_template {
- struct ieee80211_header header;
- __le32 time_stamp[2];
- __le16 beacon_interval;
- __le16 capability;
- struct wl12xx_ie_ssid ssid;
- struct wl12xx_ie_rates rates;
- struct wl12xx_ie_rates ext_rates;
- struct wl12xx_ie_ds_params ds_params;
- struct wl12xx_ie_country country;
-} __packed;
-
struct wl12xx_null_data_template {
struct ieee80211_header header;
} __packed;
@@ -146,19 +134,6 @@ struct wl12xx_arp_rsp_template {
__be32 target_ip;
} __packed;
-
-struct wl12xx_probe_resp_template {
- struct ieee80211_header header;
- __le32 time_stamp[2];
- __le16 beacon_interval;
- __le16 capability;
- struct wl12xx_ie_ssid ssid;
- struct wl12xx_ie_rates rates;
- struct wl12xx_ie_rates ext_rates;
- struct wl12xx_ie_ds_params ds_params;
- struct wl12xx_ie_country country;
-} __packed;
-
struct wl12xx_disconn_template {
struct ieee80211_header header;
__le16 disconn_reason;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 4be7c3b..117c412 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -21,6 +21,8 @@
#ifndef _ZD_CHIP_H
#define _ZD_CHIP_H
+#include <net/mac80211.h>
+
#include "zd_rf.h"
#include "zd_usb.h"
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 5463ca9..9a1b013 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t;
if (net_ratelimit()) \
dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
} while (0)
+# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
+ bool __cond = !!(cond); \
+ if (unlikely(__cond)) \
+ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+})
#else
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
# define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
+# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
#endif /* DEBUG */
#ifdef DEBUG
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 5037c8b..0a70149 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -143,7 +143,7 @@ static void beacon_enable(struct zd_mac *mac);
static void beacon_disable(struct zd_mac *mac);
static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
static int zd_mac_config_beacon(struct ieee80211_hw *hw,
- struct sk_buff *beacon);
+ struct sk_buff *beacon, bool in_intr);
static int zd_reg2alpha2(u8 regdomain, char *alpha2)
{
@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2)
return 1;
}
+static int zd_check_signal(struct ieee80211_hw *hw, int signal)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
+
+ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
+ "%s: signal value from device not in range 0..100, "
+ "but %d.\n", __func__, signal);
+
+ if (signal < 0)
+ signal = 0;
+ else if (signal > 100)
+ signal = 100;
+
+ return signal;
+}
+
int zd_mac_preinit_hw(struct ieee80211_hw *hw)
{
int r;
@@ -387,10 +403,8 @@ int zd_restore_settings(struct zd_mac *mac)
mac->type == NL80211_IFTYPE_AP) {
if (mac->vif != NULL) {
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
- if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
- }
+ if (beacon)
+ zd_mac_config_beacon(mac->hw, beacon, false);
}
zd_set_beacon_interval(&mac->chip, beacon_interval,
@@ -461,7 +475,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
if (i<IEEE80211_TX_MAX_RATES)
info->status.rates[i].idx = -1; /* terminate */
- info->status.ack_signal = ackssi;
+ info->status.ack_signal = zd_check_signal(hw, ackssi);
ieee80211_tx_status_irqsafe(hw, skb);
}
@@ -664,7 +678,34 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
/* FIXME: Management frame? */
}
-static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
+{
+ if (!mac->beacon.cur_beacon)
+ return false;
+
+ if (mac->beacon.cur_beacon->len != beacon->len)
+ return false;
+
+ return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
+}
+
+static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
+{
+ ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
+
+ kfree_skb(mac->beacon.cur_beacon);
+ mac->beacon.cur_beacon = NULL;
+}
+
+static void zd_mac_free_cur_beacon(struct zd_mac *mac)
+{
+ mutex_lock(&mac->chip.mutex);
+ zd_mac_free_cur_beacon_locked(mac);
+ mutex_unlock(&mac->chip.mutex);
+}
+
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
+ bool in_intr)
{
struct zd_mac *mac = zd_hw_mac(hw);
int r, ret, num_cmds, req_pos = 0;
@@ -674,13 +715,21 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
unsigned long end_jiffies, message_jiffies;
struct zd_ioreq32 *ioreqs;
+ mutex_lock(&mac->chip.mutex);
+
+ /* Check if hw already has this beacon. */
+ if (zd_mac_match_cur_beacon(mac, beacon)) {
+ r = 0;
+ goto out_nofree;
+ }
+
/* Alloc memory for full beacon write at once. */
num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
- if (!ioreqs)
- return -ENOMEM;
-
- mutex_lock(&mac->chip.mutex);
+ if (!ioreqs) {
+ r = -ENOMEM;
+ goto out_nofree;
+ }
r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
if (r < 0)
@@ -688,6 +737,10 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
if (r < 0)
goto release_sema;
+ if (in_intr && tmp & 0x2) {
+ r = -EBUSY;
+ goto release_sema;
+ }
end_jiffies = jiffies + HZ / 2; /*~500ms*/
message_jiffies = jiffies + HZ / 10; /*~100ms*/
@@ -742,7 +795,7 @@ release_sema:
end_jiffies = jiffies + HZ / 2; /*~500ms*/
ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
while (ret < 0) {
- if (time_is_before_eq_jiffies(end_jiffies)) {
+ if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
ret = -ETIMEDOUT;
break;
}
@@ -757,9 +810,19 @@ release_sema:
if (r < 0 || ret < 0) {
if (r >= 0)
r = ret;
+
+ /* We don't know if beacon was written successfully or not,
+ * so clear current. */
+ zd_mac_free_cur_beacon_locked(mac);
+
goto out;
}
+ /* Beacon has now been written successfully, update current. */
+ zd_mac_free_cur_beacon_locked(mac);
+ mac->beacon.cur_beacon = beacon;
+ beacon = NULL;
+
/* 802.11b/g 2.4G CCK 1Mb
* 802.11a, not yet implemented, uses different values (see GPL vendor
* driver)
@@ -767,11 +830,17 @@ release_sema:
r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
CR_BCN_PLCP_CFG);
out:
- mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
+out_nofree:
+ kfree_skb(beacon);
+ mutex_unlock(&mac->chip.mutex);
+
return r;
reset_device:
+ zd_mac_free_cur_beacon_locked(mac);
+ kfree_skb(beacon);
+
mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
@@ -982,7 +1051,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
stats.band = IEEE80211_BAND_2GHZ;
- stats.signal = status->signal_strength;
+ stats.signal = zd_check_signal(hw, status->signal_strength);
rate = zd_rx_rate(buffer, status);
@@ -1057,6 +1126,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
mac->vif = NULL;
zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
zd_write_mac_addr(&mac->chip, NULL);
+
+ zd_mac_free_cur_beacon(mac);
}
static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -1094,10 +1165,8 @@ static void zd_beacon_done(struct zd_mac *mac)
* Fetch next beacon so that tim_count is updated.
*/
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
- if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
- }
+ if (beacon)
+ zd_mac_config_beacon(mac->hw, beacon, true);
spin_lock_irq(&mac->lock);
mac->beacon.last_update = jiffies;
@@ -1222,9 +1291,8 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
if (beacon) {
zd_chip_disable_hwint(&mac->chip);
- zd_mac_config_beacon(hw, beacon);
+ zd_mac_config_beacon(hw, beacon, false);
zd_chip_enable_hwint(&mac->chip);
- kfree_skb(beacon);
}
}
@@ -1264,7 +1332,7 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
-static u64 zd_op_get_tsf(struct ieee80211_hw *hw)
+static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct zd_mac *mac = zd_hw_mac(hw);
return zd_chip_get_tsf(&mac->chip);
@@ -1361,7 +1429,8 @@ static void beacon_watchdog_handler(struct work_struct *work)
spin_lock_irq(&mac->lock);
interval = mac->beacon.interval;
period = mac->beacon.period;
- timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+ timeout = mac->beacon.last_update +
+ msecs_to_jiffies(interval * 1024 / 1000) * 3;
spin_unlock_irq(&mac->lock);
if (interval > 0 && time_is_before_jiffies(timeout)) {
@@ -1374,8 +1443,9 @@ static void beacon_watchdog_handler(struct work_struct *work)
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
+ zd_mac_free_cur_beacon(mac);
+
+ zd_mac_config_beacon(mac->hw, beacon, false);
}
zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
@@ -1410,6 +1480,8 @@ static void beacon_disable(struct zd_mac *mac)
{
dev_dbg_f(zd_mac_dev(mac), "\n");
cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+
+ zd_mac_free_cur_beacon(mac);
}
#define LINK_LED_WORK_DELAY HZ
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index f8c93c3..c01eca8 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -165,6 +165,7 @@ struct housekeeping {
struct beacon {
struct delayed_work watchdog_work;
+ struct sk_buff *cur_beacon;
unsigned long last_update;
u16 interval;
u8 period;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 631194d..785bdbe 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -28,6 +28,7 @@
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
+#include <linux/module.h>
#include <net/mac80211.h>
#include <asm/unaligned.h>
@@ -111,6 +112,9 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
#define FW_ZD1211_PREFIX "zd1211/zd1211_"
#define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+ unsigned int count);
+
/* USB device initialization */
static void int_urb_complete(struct urb *urb);
@@ -365,6 +369,20 @@ exit:
#define urb_dev(urb) (&(urb)->dev->dev)
+static inline void handle_regs_int_override(struct urb *urb)
+{
+ struct zd_usb *usb = urb->context;
+ struct zd_usb_interrupt *intr = &usb->intr;
+
+ spin_lock(&intr->lock);
+ if (atomic_read(&intr->read_regs_enabled)) {
+ atomic_set(&intr->read_regs_enabled, 0);
+ intr->read_regs_int_overridden = 1;
+ complete(&intr->read_regs.completion);
+ }
+ spin_unlock(&intr->lock);
+}
+
static inline void handle_regs_int(struct urb *urb)
{
struct zd_usb *usb = urb->context;
@@ -383,25 +401,45 @@ static inline void handle_regs_int(struct urb *urb)
USB_MAX_EP_INT_BUFFER);
spin_unlock(&mac->lock);
schedule_work(&mac->process_intr);
- } else if (intr->read_regs_enabled) {
- intr->read_regs.length = len = urb->actual_length;
-
+ } else if (atomic_read(&intr->read_regs_enabled)) {
+ len = urb->actual_length;
+ intr->read_regs.length = urb->actual_length;
if (len > sizeof(intr->read_regs.buffer))
len = sizeof(intr->read_regs.buffer);
+
memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
- intr->read_regs_enabled = 0;
+
+ /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
+ * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
+ * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
+ * retry unhandled. Next read-reg command then might catch
+ * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
+ */
+ if (!check_read_regs(usb, intr->read_regs.req,
+ intr->read_regs.req_count))
+ goto out;
+
+ atomic_set(&intr->read_regs_enabled, 0);
+ intr->read_regs_int_overridden = 0;
complete(&intr->read_regs.completion);
+
goto out;
}
out:
spin_unlock(&intr->lock);
+
+ /* CR_INTERRUPT might override read_reg too. */
+ if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
+ handle_regs_int_override(urb);
}
static void int_urb_complete(struct urb *urb)
{
int r;
struct usb_int_header *hdr;
+ struct zd_usb *usb;
+ struct zd_usb_interrupt *intr;
switch (urb->status) {
case 0:
@@ -430,6 +468,14 @@ static void int_urb_complete(struct urb *urb)
goto resubmit;
}
+ /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
+ * pending USB_INT_ID_REGS causing read command timeout.
+ */
+ usb = urb->context;
+ intr = &usb->intr;
+ if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
+ handle_regs_int_override(urb);
+
switch (hdr->id) {
case USB_INT_ID_REGS:
handle_regs_int(urb);
@@ -579,8 +625,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
if (length < sizeof(struct rx_length_info)) {
/* It's not a complete packet anyhow. */
- printk("%s: invalid, small RX packet : %d\n",
- __func__, length);
+ dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
+ length);
return;
}
length_info = (struct rx_length_info *)
@@ -1129,6 +1175,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
spin_lock_init(&intr->lock);
intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
init_completion(&intr->read_regs.completion);
+ atomic_set(&intr->read_regs_enabled, 0);
intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
}
@@ -1563,12 +1610,16 @@ static int usb_int_regs_length(unsigned int count)
return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
}
-static void prepare_read_regs_int(struct zd_usb *usb)
+static void prepare_read_regs_int(struct zd_usb *usb,
+ struct usb_req_read_regs *req,
+ unsigned int count)
{
struct zd_usb_interrupt *intr = &usb->intr;
spin_lock_irq(&intr->lock);
- intr->read_regs_enabled = 1;
+ atomic_set(&intr->read_regs_enabled, 1);
+ intr->read_regs.req = req;
+ intr->read_regs.req_count = count;
INIT_COMPLETION(intr->read_regs.completion);
spin_unlock_irq(&intr->lock);
}
@@ -1578,22 +1629,18 @@ static void disable_read_regs_int(struct zd_usb *usb)
struct zd_usb_interrupt *intr = &usb->intr;
spin_lock_irq(&intr->lock);
- intr->read_regs_enabled = 0;
+ atomic_set(&intr->read_regs_enabled, 0);
spin_unlock_irq(&intr->lock);
}
-static int get_results(struct zd_usb *usb, u16 *values,
- struct usb_req_read_regs *req, unsigned int count)
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+ unsigned int count)
{
- int r;
int i;
struct zd_usb_interrupt *intr = &usb->intr;
struct read_regs_int *rr = &intr->read_regs;
struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
- spin_lock_irq(&intr->lock);
-
- r = -EIO;
/* The created block size seems to be larger than expected.
* However results appear to be correct.
*/
@@ -1601,13 +1648,14 @@ static int get_results(struct zd_usb *usb, u16 *values,
dev_dbg_f(zd_usb_dev(usb),
"error: actual length %d less than expected %d\n",
rr->length, usb_int_regs_length(count));
- goto error_unlock;
+ return false;
}
+
if (rr->length > sizeof(rr->buffer)) {
dev_dbg_f(zd_usb_dev(usb),
"error: actual length %d exceeds buffer size %zu\n",
rr->length, sizeof(rr->buffer));
- goto error_unlock;
+ return false;
}
for (i = 0; i < count; i++) {
@@ -1617,8 +1665,39 @@ static int get_results(struct zd_usb *usb, u16 *values,
"rd[%d] addr %#06hx expected %#06hx\n", i,
le16_to_cpu(rd->addr),
le16_to_cpu(req->addr[i]));
- goto error_unlock;
+ return false;
}
+ }
+
+ return true;
+}
+
+static int get_results(struct zd_usb *usb, u16 *values,
+ struct usb_req_read_regs *req, unsigned int count,
+ bool *retry)
+{
+ int r;
+ int i;
+ struct zd_usb_interrupt *intr = &usb->intr;
+ struct read_regs_int *rr = &intr->read_regs;
+ struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+ spin_lock_irq(&intr->lock);
+
+ r = -EIO;
+
+ /* Read failed because firmware bug? */
+ *retry = !!intr->read_regs_int_overridden;
+ if (*retry)
+ goto error_unlock;
+
+ if (!check_read_regs(usb, req, count)) {
+ dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
+ goto error_unlock;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct reg_data *rd = &regs->regs[i];
values[i] = le16_to_cpu(rd->value);
}
@@ -1631,11 +1710,11 @@ error_unlock:
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
const zd_addr_t *addresses, unsigned int count)
{
- int r;
- int i, req_len, actual_req_len;
+ int r, i, req_len, actual_req_len, try_count = 0;
struct usb_device *udev;
struct usb_req_read_regs *req = NULL;
unsigned long timeout;
+ bool retry = false;
if (count < 1) {
dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
@@ -1671,8 +1750,10 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
for (i = 0; i < count; i++)
req->addr[i] = cpu_to_le16((u16)addresses[i]);
+retry_read:
+ try_count++;
udev = zd_usb_to_usbdev(usb);
- prepare_read_regs_int(usb);
+ prepare_read_regs_int(usb, req, count);
r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
if (r) {
dev_dbg_f(zd_usb_dev(usb),
@@ -1696,7 +1777,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
goto error;
}
- r = get_results(usb, values, req, count);
+ r = get_results(usb, values, req, count, &retry);
+ if (retry && try_count < 20) {
+ dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
+ try_count);
+ goto retry_read;
+ }
error:
return r;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index bf94284..99193b4 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -144,6 +144,8 @@ struct usb_int_retry_fail {
struct read_regs_int {
struct completion completion;
+ struct usb_req_read_regs *req;
+ unsigned int req_count;
/* Stores the USB int structure and contains the USB address of the
* first requested register before request.
*/
@@ -169,7 +171,8 @@ struct zd_usb_interrupt {
void *buffer;
dma_addr_t buffer_dma;
int interval;
- u8 read_regs_enabled:1;
+ atomic_t read_regs_enabled;
+ u8 read_regs_int_overridden:1;
};
static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 810a472..093bf0a 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -58,10 +58,6 @@ struct xenvif {
u8 fe_dev_addr[6];
/* Physical parameters of the comms window. */
- grant_handle_t tx_shmem_handle;
- grant_ref_t tx_shmem_ref;
- grant_handle_t rx_shmem_handle;
- grant_ref_t rx_shmem_ref;
unsigned int irq;
/* List of frontends to notify after a batch of frames sent. */
@@ -70,8 +66,6 @@ struct xenvif {
/* The shared rings and indexes. */
struct xen_netif_tx_back_ring tx;
struct xen_netif_rx_back_ring rx;
- struct vm_struct *tx_comms_area;
- struct vm_struct *rx_comms_area;
/* Frontend feature information. */
u8 can_sg:1;
@@ -94,6 +88,7 @@ struct xenvif {
unsigned long credit_usec;
unsigned long remaining_credit;
struct timer_list credit_timeout;
+ u64 credit_window_start;
/* Statistics */
unsigned long rx_gso_checksum_fixup;
@@ -106,6 +101,11 @@ struct xenvif {
wait_queue_head_t waiting_to_free;
};
+static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif)
+{
+ return to_xenbus_device(vif->dev->dev.parent);
+}
+
#define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
#define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 8eaf0e2..2cb9c92 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -272,8 +272,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
vif->credit_bytes = vif->remaining_credit = ~0UL;
vif->credit_usec = 0UL;
init_timer(&vif->credit_timeout);
- /* Initialize 'expires' now: it's used to track the credit window. */
- vif->credit_timeout.expires = jiffies;
+ vif->credit_window_start = get_jiffies_64();
dev->netdev_ops = &xenvif_netdev_ops;
dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 1260bf0..b2528f6 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -46,11 +46,33 @@
#include <asm/xen/hypercall.h>
#include <asm/xen/page.h>
+/*
+ * This is the maximum slots a skb can have. If a guest sends a skb
+ * which exceeds this limit it is considered malicious.
+ */
+#define FATAL_SKB_SLOTS_DEFAULT 20
+static unsigned int fatal_skb_slots = FATAL_SKB_SLOTS_DEFAULT;
+module_param(fatal_skb_slots, uint, 0444);
+
+/*
+ * To avoid confusion, we define XEN_NETBK_LEGACY_SLOTS_MAX indicating
+ * the maximum slots a valid packet can use. Now this value is defined
+ * to be XEN_NETIF_NR_SLOTS_MIN, which is supposed to be supported by
+ * all backend.
+ */
+#define XEN_NETBK_LEGACY_SLOTS_MAX XEN_NETIF_NR_SLOTS_MIN
+
+typedef unsigned int pending_ring_idx_t;
+#define INVALID_PENDING_RING_IDX (~0U)
+
struct pending_tx_info {
- struct xen_netif_tx_request req;
+ struct xen_netif_tx_request req; /* coalesced tx request */
struct xenvif *vif;
+ pending_ring_idx_t head; /* head != INVALID_PENDING_RING_IDX
+ * if it is head of one or more tx
+ * reqs
+ */
};
-typedef unsigned int pending_ring_idx_t;
struct netbk_rx_meta {
int id;
@@ -60,6 +82,9 @@ struct netbk_rx_meta {
#define MAX_PENDING_REQS 256
+/* Discriminate from any valid pending_idx value. */
+#define INVALID_PENDING_IDX 0xFFFF
+
#define MAX_BUFFER_OFFSET PAGE_SIZE
/* extra field used in struct page */
@@ -98,7 +123,11 @@ struct xen_netbk {
atomic_t netfront_count;
struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
- struct gnttab_copy tx_copy_ops[MAX_PENDING_REQS];
+ /* Coalescing tx requests before copying makes number of grant
+ * copy ops greater or equal to number of slots required. In
+ * worst case a tx request consumes 2 gnttab_copy.
+ */
+ struct gnttab_copy tx_copy_ops[2*MAX_PENDING_REQS];
u16 pending_ring[MAX_PENDING_REQS];
@@ -114,6 +143,16 @@ struct xen_netbk {
static struct xen_netbk *xen_netbk;
static int xen_netbk_group_nr;
+/*
+ * If head != INVALID_PENDING_RING_IDX, it means this tx request is head of
+ * one or more merged tx requests, otherwise it is the continuation of
+ * previous tx request.
+ */
+static inline int pending_tx_is_head(struct xen_netbk *netbk, RING_IDX idx)
+{
+ return netbk->pending_tx_info[idx].head != INVALID_PENDING_RING_IDX;
+}
+
void xen_netbk_add_xenvif(struct xenvif *vif)
{
int i;
@@ -156,13 +195,13 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
u16 flags);
static inline unsigned long idx_to_pfn(struct xen_netbk *netbk,
- unsigned int idx)
+ u16 idx)
{
return page_to_pfn(netbk->mmap_pages[idx]);
}
static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk,
- unsigned int idx)
+ u16 idx)
{
return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx));
}
@@ -216,6 +255,16 @@ static int get_page_ext(struct page *pg,
sizeof(struct iphdr) + MAX_IPOPTLEN + \
sizeof(struct tcphdr) + MAX_TCP_OPTION_SPACE)
+static u16 frag_get_pending_idx(skb_frag_t *frag)
+{
+ return (u16)frag->page_offset;
+}
+
+static void frag_set_pending_idx(skb_frag_t *frag, u16 pending_idx)
+{
+ frag->page_offset = pending_idx;
+}
+
static inline pending_ring_idx_t pending_index(unsigned i)
{
return i & (MAX_PENDING_REQS-1);
@@ -236,6 +285,7 @@ static int max_required_rx_slots(struct xenvif *vif)
{
int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
+ /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
if (vif->can_sg || vif->gso || vif->gso_prefix)
max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
@@ -296,8 +346,8 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head)
* into multiple copies tend to give large frags their
* own buffers as before.
*/
- if ((offset + size > MAX_BUFFER_OFFSET) &&
- (size <= MAX_BUFFER_OFFSET) && offset && !head)
+ BUG_ON(size > MAX_BUFFER_OFFSET);
+ if ((offset + size > MAX_BUFFER_OFFSET) && offset && !head)
return true;
return false;
@@ -322,7 +372,7 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
count++;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- unsigned long size = skb_shinfo(skb)->frags[i].size;
+ unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
unsigned long bytes;
while (size > 0) {
BUG_ON(copy_off > MAX_BUFFER_OFFSET);
@@ -513,8 +563,8 @@ static int netbk_gop_skb(struct sk_buff *skb,
for (i = 0; i < nr_frags; i++) {
netbk_gop_frag_copy(vif, skb, npo,
- skb_shinfo(skb)->frags[i].page,
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_page(&skb_shinfo(skb)->frags[i]),
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
skb_shinfo(skb)->frags[i].page_offset,
&head);
}
@@ -614,6 +664,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
__skb_queue_tail(&rxq, skb);
/* Filled the batch queue? */
+ /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE)
break;
}
@@ -861,48 +912,100 @@ static int netbk_count_requests(struct xenvif *vif,
int work_to_do)
{
RING_IDX cons = vif->tx.req_cons;
- int frags = 0;
+ int slots = 0;
+ int drop_err = 0;
+ int more_data;
if (!(first->flags & XEN_NETTXF_more_data))
return 0;
do {
- if (frags >= work_to_do) {
- netdev_err(vif->dev, "Need more frags\n");
+ struct xen_netif_tx_request dropped_tx = { 0 };
+
+ if (slots >= work_to_do) {
+ netdev_err(vif->dev,
+ "Asked for %d slots but exceeds this limit\n",
+ work_to_do);
netbk_fatal_tx_err(vif);
return -ENODATA;
}
- if (unlikely(frags >= MAX_SKB_FRAGS)) {
- netdev_err(vif->dev, "Too many frags\n");
+ /* This guest is really using too many slots and
+ * considered malicious.
+ */
+ if (unlikely(slots >= fatal_skb_slots)) {
+ netdev_err(vif->dev,
+ "Malicious frontend using %d slots, threshold %u\n",
+ slots, fatal_skb_slots);
netbk_fatal_tx_err(vif);
return -E2BIG;
}
- memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
+ /* Xen network protocol had implicit dependency on
+ * MAX_SKB_FRAGS. XEN_NETBK_LEGACY_SLOTS_MAX is set to
+ * the historical MAX_SKB_FRAGS value 18 to honor the
+ * same behavior as before. Any packet using more than
+ * 18 slots but less than fatal_skb_slots slots is
+ * dropped
+ */
+ if (!drop_err && slots >= XEN_NETBK_LEGACY_SLOTS_MAX) {
+ if (net_ratelimit())
+ netdev_dbg(vif->dev,
+ "Too many slots (%d) exceeding limit (%d), dropping packet\n",
+ slots, XEN_NETBK_LEGACY_SLOTS_MAX);
+ drop_err = -E2BIG;
+ }
+
+ if (drop_err)
+ txp = &dropped_tx;
+
+ memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + slots),
sizeof(*txp));
- if (txp->size > first->size) {
- netdev_err(vif->dev, "Frag is bigger than frame.\n");
- netbk_fatal_tx_err(vif);
- return -EIO;
+
+ /* If the guest submitted a frame >= 64 KiB then
+ * first->size overflowed and following slots will
+ * appear to be larger than the frame.
+ *
+ * This cannot be fatal error as there are buggy
+ * frontends that do this.
+ *
+ * Consume all slots and drop the packet.
+ */
+ if (!drop_err && txp->size > first->size) {
+ if (net_ratelimit())
+ netdev_dbg(vif->dev,
+ "Invalid tx request, slot size %u > remaining size %u\n",
+ txp->size, first->size);
+ drop_err = -EIO;
}
first->size -= txp->size;
- frags++;
+ slots++;
if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
- netdev_err(vif->dev, "txp->offset: %x, size: %u\n",
+ netdev_err(vif->dev, "Cross page boundary, txp->offset: %x, size: %u\n",
txp->offset, txp->size);
netbk_fatal_tx_err(vif);
return -EINVAL;
}
- } while ((txp++)->flags & XEN_NETTXF_more_data);
- return frags;
+
+ more_data = txp->flags & XEN_NETTXF_more_data;
+
+ if (!drop_err)
+ txp++;
+
+ } while (more_data);
+
+ if (drop_err) {
+ netbk_tx_err(vif, first, cons + slots);
+ return drop_err;
+ }
+
+ return slots;
}
static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
- struct sk_buff *skb,
- unsigned long pending_idx)
+ u16 pending_idx)
{
struct page *page;
page = alloc_page(GFP_KERNEL|__GFP_COLD);
@@ -921,51 +1024,115 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
skb_frag_t *frags = shinfo->frags;
- unsigned long pending_idx = *((u16 *)skb->data);
- int i, start;
+ u16 pending_idx = *((u16 *)skb->data);
+ u16 head_idx = 0;
+ int slot, start;
+ struct page *page;
+ pending_ring_idx_t index, start_idx = 0;
+ uint16_t dst_offset;
+ unsigned int nr_slots;
+ struct pending_tx_info *first = NULL;
+
+ /* At this point shinfo->nr_frags is in fact the number of
+ * slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
+ */
+ nr_slots = shinfo->nr_frags;
/* Skip first skb fragment if it is on same page as header fragment. */
- start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+ start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
- for (i = start; i < shinfo->nr_frags; i++, txp++) {
- struct page *page;
- pending_ring_idx_t index;
+ /* Coalesce tx requests, at this point the packet passed in
+ * should be <= 64K. Any packets larger than 64K have been
+ * handled in netbk_count_requests().
+ */
+ for (shinfo->nr_frags = slot = start; slot < nr_slots;
+ shinfo->nr_frags++) {
struct pending_tx_info *pending_tx_info =
netbk->pending_tx_info;
- index = pending_index(netbk->pending_cons++);
- pending_idx = netbk->pending_ring[index];
- page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+ page = alloc_page(GFP_KERNEL|__GFP_COLD);
if (!page)
goto err;
- netbk->mmap_pages[pending_idx] = page;
-
- gop->source.u.ref = txp->gref;
- gop->source.domid = vif->domid;
- gop->source.offset = txp->offset;
-
- gop->dest.u.gmfn = virt_to_mfn(page_address(page));
- gop->dest.domid = DOMID_SELF;
- gop->dest.offset = txp->offset;
-
- gop->len = txp->size;
- gop->flags = GNTCOPY_source_gref;
+ dst_offset = 0;
+ first = NULL;
+ while (dst_offset < PAGE_SIZE && slot < nr_slots) {
+ gop->flags = GNTCOPY_source_gref;
+
+ gop->source.u.ref = txp->gref;
+ gop->source.domid = vif->domid;
+ gop->source.offset = txp->offset;
+
+ gop->dest.domid = DOMID_SELF;
+
+ gop->dest.offset = dst_offset;
+ gop->dest.u.gmfn = virt_to_mfn(page_address(page));
+
+ if (dst_offset + txp->size > PAGE_SIZE) {
+ /* This page can only merge a portion
+ * of tx request. Do not increment any
+ * pointer / counter here. The txp
+ * will be dealt with in future
+ * rounds, eventually hitting the
+ * `else` branch.
+ */
+ gop->len = PAGE_SIZE - dst_offset;
+ txp->offset += gop->len;
+ txp->size -= gop->len;
+ dst_offset += gop->len; /* quit loop */
+ } else {
+ /* This tx request can be merged in the page */
+ gop->len = txp->size;
+ dst_offset += gop->len;
+
+ index = pending_index(netbk->pending_cons++);
+
+ pending_idx = netbk->pending_ring[index];
+
+ memcpy(&pending_tx_info[pending_idx].req, txp,
+ sizeof(*txp));
+ xenvif_get(vif);
+
+ pending_tx_info[pending_idx].vif = vif;
+
+ /* Poison these fields, corresponding
+ * fields for head tx req will be set
+ * to correct values after the loop.
+ */
+ netbk->mmap_pages[pending_idx] = (void *)(~0UL);
+ pending_tx_info[pending_idx].head =
+ INVALID_PENDING_RING_IDX;
+
+ if (!first) {
+ first = &pending_tx_info[pending_idx];
+ start_idx = index;
+ head_idx = pending_idx;
+ }
+
+ txp++;
+ slot++;
+ }
- gop++;
+ gop++;
+ }
- memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
- xenvif_get(vif);
- pending_tx_info[pending_idx].vif = vif;
- frags[i].page = (void *)pending_idx;
+ first->req.offset = 0;
+ first->req.size = dst_offset;
+ first->head = start_idx;
+ set_page_ext(page, netbk, head_idx);
+ netbk->mmap_pages[head_idx] = page;
+ frag_set_pending_idx(&frags[shinfo->nr_frags], head_idx);
}
+ BUG_ON(shinfo->nr_frags > MAX_SKB_FRAGS);
+
return gop;
err:
/* Unwind, freeing all pages and sending error responses. */
- while (i-- > start) {
- xen_netbk_idx_release(netbk, (unsigned long)shinfo->frags[i].page,
- XEN_NETIF_RSP_ERROR);
+ while (shinfo->nr_frags-- > start) {
+ xen_netbk_idx_release(netbk,
+ frag_get_pending_idx(&frags[shinfo->nr_frags]),
+ XEN_NETIF_RSP_ERROR);
}
/* The head too, if necessary. */
if (start)
@@ -979,10 +1146,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
struct gnttab_copy **gopp)
{
struct gnttab_copy *gop = *gopp;
- int pending_idx = *((u16 *)skb->data);
+ u16 pending_idx = *((u16 *)skb->data);
struct skb_shared_info *shinfo = skb_shinfo(skb);
+ struct pending_tx_info *tx_info;
int nr_frags = shinfo->nr_frags;
int i, err, start;
+ u16 peek; /* peek into next tx request */
/* Check status of header. */
err = gop->status;
@@ -990,15 +1159,24 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
/* Skip first skb fragment if it is on same page as header fragment. */
- start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+ start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
for (i = start; i < nr_frags; i++) {
int j, newerr;
+ pending_ring_idx_t head;
- pending_idx = (unsigned long)shinfo->frags[i].page;
+ pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
+ tx_info = &netbk->pending_tx_info[pending_idx];
+ head = tx_info->head;
/* Check error status: if okay then remember grant handle. */
- newerr = (++gop)->status;
+ do {
+ newerr = (++gop)->status;
+ if (newerr)
+ break;
+ peek = netbk->pending_ring[pending_index(++head)];
+ } while (!pending_tx_is_head(netbk, peek));
+
if (likely(!newerr)) {
/* Had a previous error? Invalidate this fragment. */
if (unlikely(err))
@@ -1017,7 +1195,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
pending_idx = *((u16 *)skb->data);
xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
for (j = start; j < i; j++) {
- pending_idx = (unsigned long)shinfo->frags[i].page;
+ pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
}
@@ -1038,15 +1216,14 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)
for (i = 0; i < nr_frags; i++) {
skb_frag_t *frag = shinfo->frags + i;
struct xen_netif_tx_request *txp;
- unsigned long pending_idx;
+ struct page *page;
+ u16 pending_idx;
- pending_idx = (unsigned long)frag->page;
+ pending_idx = frag_get_pending_idx(frag);
txp = &netbk->pending_tx_info[pending_idx].req;
- frag->page = virt_to_page(idx_to_kaddr(netbk, pending_idx));
- frag->size = txp->size;
- frag->page_offset = txp->offset;
-
+ page = virt_to_page(idx_to_kaddr(netbk, pending_idx));
+ __skb_fill_page_desc(skb, i, page, txp->offset, txp->size);
skb->len += txp->size;
skb->data_len += txp->size;
skb->truesize += txp->size;
@@ -1188,9 +1365,8 @@ out:
static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
{
- unsigned long now = jiffies;
- unsigned long next_credit =
- vif->credit_timeout.expires +
+ u64 now = get_jiffies_64();
+ u64 next_credit = vif->credit_window_start +
msecs_to_jiffies(vif->credit_usec / 1000);
/* Timer could already be pending in rare cases. */
@@ -1198,8 +1374,8 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
return true;
/* Passed the point where we can replenish credit? */
- if (time_after_eq(now, next_credit)) {
- vif->credit_timeout.expires = now;
+ if (time_after_eq64(now, next_credit)) {
+ vif->credit_window_start = now;
tx_add_credit(vif);
}
@@ -1211,6 +1387,7 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
tx_credit_callback;
mod_timer(&vif->credit_timeout,
next_credit);
+ vif->credit_window_start = next_credit;
return true;
}
@@ -1224,11 +1401,12 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
struct sk_buff *skb;
int ret;
- while (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+ while ((nr_pending_reqs(netbk) + XEN_NETBK_LEGACY_SLOTS_MAX
+ < MAX_PENDING_REQS) &&
!list_empty(&netbk->net_schedule_list)) {
struct xenvif *vif;
struct xen_netif_tx_request txreq;
- struct xen_netif_tx_request txfrags[MAX_SKB_FRAGS];
+ struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX];
struct page *page;
struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1];
u16 pending_idx;
@@ -1316,7 +1494,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
pending_idx = netbk->pending_ring[index];
data_len = (txreq.size > PKT_PROT_LEN &&
- ret < MAX_SKB_FRAGS) ?
+ ret < XEN_NETBK_LEGACY_SLOTS_MAX) ?
PKT_PROT_LEN : txreq.size;
skb = alloc_skb(data_len + NET_SKB_PAD + NET_IP_ALIGN,
@@ -1343,15 +1521,13 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
}
/* XXX could copy straight to head */
- page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+ page = xen_netbk_alloc_page(netbk, pending_idx);
if (!page) {
kfree_skb(skb);
netbk_tx_err(vif, &txreq, idx);
continue;
}
- netbk->mmap_pages[pending_idx] = page;
-
gop->source.u.ref = txreq.gref;
gop->source.domid = vif->domid;
gop->source.offset = txreq.offset;
@@ -1368,6 +1544,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
memcpy(&netbk->pending_tx_info[pending_idx].req,
&txreq, sizeof(txreq));
netbk->pending_tx_info[pending_idx].vif = vif;
+ netbk->pending_tx_info[pending_idx].head = index;
*((u16 *)skb->data) = pending_idx;
__skb_put(skb, data_len);
@@ -1375,11 +1552,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
skb_shinfo(skb)->nr_frags = ret;
if (data_len < txreq.size) {
skb_shinfo(skb)->nr_frags++;
- skb_shinfo(skb)->frags[0].page =
- (void *)(unsigned long)pending_idx;
+ frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
+ pending_idx);
} else {
- /* Discriminate from any valid pending_idx value. */
- skb_shinfo(skb)->frags[0].page = (void *)~0UL;
+ frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
+ INVALID_PENDING_IDX);
}
__skb_queue_tail(&netbk->tx_queue, skb);
@@ -1498,7 +1675,10 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
{
struct xenvif *vif;
struct pending_tx_info *pending_tx_info;
- pending_ring_idx_t index;
+ pending_ring_idx_t head;
+ u16 peek; /* peek into next tx request */
+
+ BUG_ON(netbk->mmap_pages[pending_idx] == (void *)(~0UL));
/* Already complete? */
if (netbk->mmap_pages[pending_idx] == NULL)
@@ -1507,19 +1687,40 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
pending_tx_info = &netbk->pending_tx_info[pending_idx];
vif = pending_tx_info->vif;
+ head = pending_tx_info->head;
+
+ BUG_ON(!pending_tx_is_head(netbk, head));
+ BUG_ON(netbk->pending_ring[pending_index(head)] != pending_idx);
- make_tx_response(vif, &pending_tx_info->req, status);
+ do {
+ pending_ring_idx_t index;
+ pending_ring_idx_t idx = pending_index(head);
+ u16 info_idx = netbk->pending_ring[idx];
- index = pending_index(netbk->pending_prod++);
- netbk->pending_ring[index] = pending_idx;
+ pending_tx_info = &netbk->pending_tx_info[info_idx];
+ make_tx_response(vif, &pending_tx_info->req, status);
- xenvif_put(vif);
+ /* Setting any number other than
+ * INVALID_PENDING_RING_IDX indicates this slot is
+ * starting a new packet / ending a previous packet.
+ */
+ pending_tx_info->head = 0;
+
+ index = pending_index(netbk->pending_prod++);
+ netbk->pending_ring[index] = netbk->pending_ring[info_idx];
+
+ xenvif_put(vif);
+
+ peek = netbk->pending_ring[pending_index(++head)];
+
+ } while (!pending_tx_is_head(netbk, peek));
netbk->mmap_pages[pending_idx]->mapping = 0;
put_page(netbk->mmap_pages[pending_idx]);
netbk->mmap_pages[pending_idx] = NULL;
}
+
static void make_tx_response(struct xenvif *vif,
struct xen_netif_tx_request *txp,
s8 st)
@@ -1572,8 +1773,9 @@ static inline int rx_work_todo(struct xen_netbk *netbk)
static inline int tx_work_todo(struct xen_netbk *netbk)
{
- if (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
- !list_empty(&netbk->net_schedule_list))
+ if ((nr_pending_reqs(netbk) + XEN_NETBK_LEGACY_SLOTS_MAX
+ < MAX_PENDING_REQS) &&
+ !list_empty(&netbk->net_schedule_list))
return 1;
return 0;
@@ -1604,88 +1806,42 @@ static int xen_netbk_kthread(void *data)
void xen_netbk_unmap_frontend_rings(struct xenvif *vif)
{
- struct gnttab_unmap_grant_ref op;
-
- if (vif->tx.sring) {
- gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr,
- GNTMAP_host_map, vif->tx_shmem_handle);
-
- if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
- BUG();
- }
-
- if (vif->rx.sring) {
- gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr,
- GNTMAP_host_map, vif->rx_shmem_handle);
-
- if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
- BUG();
- }
- if (vif->rx_comms_area)
- free_vm_area(vif->rx_comms_area);
- if (vif->tx_comms_area)
- free_vm_area(vif->tx_comms_area);
+ if (vif->tx.sring)
+ xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif),
+ vif->tx.sring);
+ if (vif->rx.sring)
+ xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif),
+ vif->rx.sring);
}
int xen_netbk_map_frontend_rings(struct xenvif *vif,
grant_ref_t tx_ring_ref,
grant_ref_t rx_ring_ref)
{
- struct gnttab_map_grant_ref op;
+ void *addr;
struct xen_netif_tx_sring *txs;
struct xen_netif_rx_sring *rxs;
int err = -ENOMEM;
- vif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
- if (vif->tx_comms_area == NULL)
- goto err;
-
- vif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
- if (vif->rx_comms_area == NULL)
- goto err;
-
- gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr,
- GNTMAP_host_map, tx_ring_ref, vif->domid);
-
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
-
- if (op.status) {
- netdev_warn(vif->dev,
- "failed to map tx ring. err=%d status=%d\n",
- err, op.status);
- err = op.status;
+ err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif),
+ tx_ring_ref, &addr);
+ if (err)
goto err;
- }
-
- vif->tx_shmem_ref = tx_ring_ref;
- vif->tx_shmem_handle = op.handle;
- txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr;
+ txs = (struct xen_netif_tx_sring *)addr;
BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE);
- gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr,
- GNTMAP_host_map, rx_ring_ref, vif->domid);
-
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
-
- if (op.status) {
- netdev_warn(vif->dev,
- "failed to map rx ring. err=%d status=%d\n",
- err, op.status);
- err = op.status;
+ err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif),
+ rx_ring_ref, &addr);
+ if (err)
goto err;
- }
- vif->rx_shmem_ref = rx_ring_ref;
- vif->rx_shmem_handle = op.handle;
- vif->rx_req_cons_peek = 0;
-
- rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr;
+ rxs = (struct xen_netif_rx_sring *)addr;
BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE);
+ vif->rx_req_cons_peek = 0;
+
return 0;
err:
@@ -1702,6 +1858,13 @@ static int __init netback_init(void)
if (!xen_pv_domain())
return -ENODEV;
+ if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) {
+ printk(KERN_INFO
+ "xen-netback: fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n",
+ fatal_skb_slots, XEN_NETBK_LEGACY_SLOTS_MAX);
+ fatal_skb_slots = XEN_NETBK_LEGACY_SLOTS_MAX;
+ }
+
xen_netbk_group_nr = num_online_cpus();
xen_netbk = vzalloc(sizeof(struct xen_netbk) * xen_netbk_group_nr);
if (!xen_netbk) {
@@ -1729,7 +1892,7 @@ static int __init netback_init(void)
"netback/%u", group);
if (IS_ERR(netbk->task)) {
- printk(KERN_ALERT "kthread_run() fails at netback\n");
+ printk(KERN_ALERT "kthread_create() fails at netback\n");
del_timer(&netbk->net_timer);
rc = PTR_ERR(netbk->task);
goto failed_init;
@@ -1770,3 +1933,4 @@ failed_init:
module_init(netback_init);
MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("xen-backend:vif");
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 1ce729d..b7d782f 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -27,6 +27,8 @@ struct backend_info {
enum xenbus_state frontend_state;
struct xenbus_watch hotplug_status_watch;
u8 have_hotplug_status_watch:1;
+
+ const char *hotplug_script;
};
static int connect_rings(struct backend_info *);
@@ -45,6 +47,7 @@ static int netback_remove(struct xenbus_device *dev)
xenvif_disconnect(be->vif);
be->vif = NULL;
}
+ kfree(be->hotplug_script);
kfree(be);
dev_set_drvdata(&dev->dev, NULL);
return 0;
@@ -62,6 +65,7 @@ static int netback_probe(struct xenbus_device *dev,
struct xenbus_transaction xbt;
int err;
int sg;
+ const char *script;
struct backend_info *be = kzalloc(sizeof(struct backend_info),
GFP_KERNEL);
if (!be) {
@@ -122,6 +126,15 @@ static int netback_probe(struct xenbus_device *dev,
goto fail;
}
+ script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL);
+ if (IS_ERR(script)) {
+ err = PTR_ERR(script);
+ xenbus_dev_fatal(dev, err, "reading script");
+ goto fail;
+ }
+
+ be->hotplug_script = script;
+
err = xenbus_switch_state(dev, XenbusStateInitWait);
if (err)
goto fail;
@@ -150,22 +163,14 @@ static int netback_uevent(struct xenbus_device *xdev,
struct kobj_uevent_env *env)
{
struct backend_info *be = dev_get_drvdata(&xdev->dev);
- char *val;
- val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
- if (IS_ERR(val)) {
- int err = PTR_ERR(val);
- xenbus_dev_fatal(xdev, err, "reading script");
- return err;
- } else {
- if (add_uevent_var(env, "script=%s", val)) {
- kfree(val);
- return -ENOMEM;
- }
- kfree(val);
- }
+ if (!be)
+ return 0;
+
+ if (add_uevent_var(env, "script=%s", be->hotplug_script))
+ return -ENOMEM;
- if (!be || !be->vif)
+ if (!be->vif)
return 0;
return add_uevent_var(env, "vif=%s", be->vif->dev->name);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d06a637..cac63c9 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -71,8 +71,14 @@ config OF_MDIO
config OF_PCI
def_tristate PCI
- depends on PCI && (PPC || MICROBLAZE || X86)
+ depends on PCI
help
OpenFirmware PCI bus accessors
+config OF_PCI_IRQ
+ def_tristate PCI
+ depends on OF_PCI && OF_IRQ
+ help
+ OpenFirmware PCI IRQ routing helpers
+
endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index f7861ed..dccb117 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_NET) += of_net.o
obj-$(CONFIG_OF_SPI) += of_spi.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
+obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index b4559c5..39016a0 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -97,8 +97,13 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
static int of_bus_pci_match(struct device_node *np)
{
- /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
- return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
+ /*
+ * "pciex" is PCI Express
+ * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
+ * "ht" is hypertransport
+ */
+ return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") ||
+ !strcmp(np->type, "vci") || !strcmp(np->type, "ht");
}
static void of_bus_pci_count_cells(struct device_node *np,
@@ -328,6 +333,22 @@ static struct of_bus *of_match_bus(struct device_node *np)
return NULL;
}
+static int of_empty_ranges_quirk(void)
+{
+#ifdef CONFIG_PPC
+ /* To save cycles, we cache the result */
+ static int quirk_state = -1;
+
+ if (quirk_state < 0)
+ quirk_state =
+ of_machine_is_compatible("Power Macintosh") ||
+ of_machine_is_compatible("MacRISC");
+ return quirk_state;
+#else
+ return false;
+#endif
+}
+
static int of_translate_one(struct device_node *parent, struct of_bus *bus,
struct of_bus *pbus, u32 *addr,
int na, int ns, int pna, const char *rprop)
@@ -353,12 +374,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
* This code is only enabled on powerpc. --gcl
*/
ranges = of_get_property(parent, rprop, &rlen);
-#if !defined(CONFIG_PPC)
- if (ranges == NULL) {
+ if (ranges == NULL && !of_empty_ranges_quirk()) {
pr_err("OF: no ranges; cannot translate\n");
return 1;
}
-#endif /* !defined(CONFIG_PPC) */
if (ranges == NULL || rlen == 0) {
offset = of_read_number(addr, na);
memset(addr, 0, pna * 4);
@@ -577,6 +596,24 @@ int of_address_to_resource(struct device_node *dev, int index,
}
EXPORT_SYMBOL_GPL(of_address_to_resource);
+struct device_node *of_find_matching_node_by_address(struct device_node *from,
+ const struct of_device_id *matches,
+ u64 base_address)
+{
+ struct device_node *dn = of_find_matching_node(from, matches);
+ struct resource res;
+
+ while (dn) {
+ if (!of_address_to_resource(dn, 0, &res) &&
+ res.start == base_address)
+ return dn;
+
+ dn = of_find_matching_node(dn, matches);
+ }
+
+ return NULL;
+}
+
/**
* of_iomap - Maps the memory mapped IO for a given device_node
@@ -592,6 +629,6 @@ void __iomem *of_iomap(struct device_node *np, int index)
if (of_address_to_resource(np, index, &res))
return NULL;
- return ioremap(res.start, 1 + res.end - res.start);
+ return ioremap(res.start, resource_size(&res));
}
EXPORT_SYMBOL(of_iomap);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 632ebae..2193558 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,39 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+ struct list_head link;
+ const char *alias;
+ struct device_node *np;
+ int id;
+ char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
struct device_node *allnodes;
struct device_node *of_chosen;
+struct device_node *of_aliases;
+
+static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node.
@@ -596,6 +621,221 @@ struct device_node *of_find_node_by_phandle(phandle handle)
EXPORT_SYMBOL(of_find_node_by_phandle);
/**
+ * of_property_read_u32_array - Find and read an array of 32 bit integers
+ * from a property.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_value is modified only if a valid u32 value can be decoded.
+ */
+int of_property_read_u32_array(const struct device_node *np,
+ const char *propname, u32 *out_values,
+ size_t sz)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ const __be32 *val;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if ((sz * sizeof(*out_values)) > prop->length)
+ return -EOVERFLOW;
+
+ val = prop->value;
+ while (sz--)
+ *out_values++ = be32_to_cpup(val++);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u32_array);
+
+/**
+ * of_property_read_u64 - Find and read a 64 bit integer from a property
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ *
+ * Search for a property in a device node and read a 64-bit value from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_value is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64(const struct device_node *np, const char *propname,
+ u64 *out_value)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (sizeof(*out_value) > prop->length)
+ return -EOVERFLOW;
+ *out_value = of_read_number(prop->value, 2);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u64);
+
+/**
+ * of_property_read_string - Find and read a string from a property
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_string: pointer to null terminated return string, modified only if
+ * return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy). Returns 0 on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string(struct device_node *np, const char *propname,
+ const char **out_string)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (strnlen(prop->value, prop->length) >= prop->length)
+ return -EILSEQ;
+ *out_string = prop->value;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string);
+
+/**
+ * of_property_read_string_index - Find and read a string from a multiple
+ * strings property.
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @index: index of the string in the list of strings
+ * @out_string: pointer to null terminated return string, modified only if
+ * return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string_index(struct device_node *np, const char *propname,
+ int index, const char **output)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ int i = 0;
+ size_t l = 0, total = 0;
+ const char *p;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (strnlen(prop->value, prop->length) >= prop->length)
+ return -EILSEQ;
+
+ p = prop->value;
+
+ for (i = 0; total < prop->length; total += l, p += l) {
+ l = strlen(p) + 1;
+ if ((*p != 0) && (i++ == index)) {
+ *output = p;
+ return 0;
+ }
+ }
+ return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string_index);
+
+/**
+ * of_property_match_string() - Find string in a list and return index
+ * @np: pointer to node containing string list property
+ * @propname: string list property name
+ * @string: pointer to string to search for in string list
+ *
+ * This function searches a string list property and returns the index
+ * of a specific string value.
+ */
+int of_property_match_string(struct device_node *np, const char *propname,
+ const char *string)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ size_t l;
+ int i;
+ const char *p, *end;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ p = prop->value;
+ end = p + prop->length;
+
+ for (i = 0; p < end; i++, p += l) {
+ l = strlen(p) + 1;
+ if (p + l > end)
+ return -EILSEQ;
+ pr_debug("comparing %s with %s\n", string, p);
+ if (strcmp(string, p) == 0)
+ return i; /* Found it; return index */
+ }
+ return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_match_string);
+
+/**
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ int i = 0;
+ size_t l = 0, total = 0;
+ const char *p;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (strnlen(prop->value, prop->length) >= prop->length)
+ return -EILSEQ;
+
+ p = prop->value;
+
+ for (i = 0; total < prop->length; total += l, p += l) {
+ l = strlen(p) + 1;
+ if (*p != 0)
+ i++;
+ }
+ return i;
+}
+EXPORT_SYMBOL_GPL(of_property_count_strings);
+
+/**
* of_parse_phandle - Resolve a phandle property to a device_node pointer
* @np: Pointer to device node holding phandle property
* @phandle_name: Name of property holding a phandle value
@@ -922,3 +1162,100 @@ out_unlock:
}
#endif /* defined(CONFIG_OF_DYNAMIC) */
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+ int id, const char *stem, int stem_len)
+{
+ ap->np = np;
+ ap->id = id;
+ strncpy(ap->stem, stem, stem_len);
+ ap->stem[stem_len] = 0;
+ list_add_tail(&ap->link, &aliases_lookup);
+ pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+ ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties. It returns the
+ * number of alias_prop found, or error code in error case.
+ *
+ * @dt_alloc: An allocator that provides a virtual address to memory
+ * for the resulting tree
+ */
+void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
+{
+ struct property *pp;
+
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ if (!of_aliases)
+ return;
+
+ for_each_property(pp, of_aliases->properties) {
+ const char *start = pp->name;
+ const char *end = start + strlen(start);
+ struct device_node *np;
+ struct alias_prop *ap;
+ int id, len;
+
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name") ||
+ !strcmp(pp->name, "phandle") ||
+ !strcmp(pp->name, "linux,phandle"))
+ continue;
+
+ np = of_find_node_by_path(pp->value);
+ if (!np)
+ continue;
+
+ /* walk the alias backwards to extract the id and work out
+ * the 'stem' string */
+ while (isdigit(*(end-1)) && end > start)
+ end--;
+ len = end - start;
+
+ if (kstrtoint(end, 10, &id) < 0)
+ continue;
+
+ /* Allocate an alias_prop with enough space for the stem */
+ ap = dt_alloc(sizeof(*ap) + len + 1, 4);
+ if (!ap)
+ continue;
+ memset(ap, 0, sizeof(*ap) + len + 1);
+ ap->alias = start;
+ of_alias_add(ap, np, id, start, len);
+ }
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np: Pointer to the given device_node
+ * @stem: Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem. It returns the alias id if find it.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+ struct alias_prop *app;
+ int id = -ENODEV;
+
+ mutex_lock(&of_aliases_mutex);
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem) != 0)
+ continue;
+
+ if (np == app->np) {
+ id = app->id;
+ break;
+ }
+ }
+ mutex_unlock(&of_aliases_mutex);
+
+ return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index d3645f6..b77808c 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -683,9 +683,14 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
if (p != NULL && l > 0)
strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
+ /*
+ * CONFIG_CMDLINE is meant to be a default in case nothing else
+ * managed to set the command line, unless CONFIG_CMDLINE_FORCE
+ * is set in which case we override whatever was found earlier.
+ */
#ifdef CONFIG_CMDLINE
#ifndef CONFIG_CMDLINE_FORCE
- if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+ if (!((char *)data)[0])
#endif
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif /* CONFIG_CMDLINE */
@@ -709,10 +714,8 @@ void __init unflatten_device_tree(void)
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
- /* Get pointer to OF "/chosen" node for use everywhere */
- of_chosen = of_find_node_by_path("/chosen");
- if (of_chosen == NULL)
- of_chosen = of_find_node_by_path("/chosen@0");
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_alias_scan(early_init_dt_alloc_memory_arch);
}
#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 9059603..ef0105f 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -21,8 +21,9 @@
#include <linux/slab.h>
/**
- * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API
+ * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
* @np: device node to get GPIO from
+ * @propname: property name containing gpio specifier(s)
* @index: index of the GPIO
* @flags: a flags pointer to fill in
*
@@ -30,8 +31,8 @@
* value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO.
*/
-int of_get_gpio_flags(struct device_node *np, int index,
- enum of_gpio_flags *flags)
+int of_get_named_gpio_flags(struct device_node *np, const char *propname,
+ int index, enum of_gpio_flags *flags)
{
int ret;
struct device_node *gpio_np;
@@ -40,7 +41,7 @@ int of_get_gpio_flags(struct device_node *np, int index,
const void *gpio_spec;
const __be32 *gpio_cells;
- ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+ ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
&gpio_np, &gpio_spec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
@@ -79,7 +80,7 @@ err0:
pr_debug("%s exited with status %d\n", __func__, ret);
return ret;
}
-EXPORT_SYMBOL(of_get_gpio_flags);
+EXPORT_SYMBOL(of_get_named_gpio_flags);
/**
* of_gpio_count - Count GPIOs for a device
@@ -126,8 +127,8 @@ EXPORT_SYMBOL(of_gpio_count);
* gpio chips. This function performs only one sanity check: whether gpio
* is less than ngpios (that is specified in the gpio_chip).
*/
-static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
- const void *gpio_spec, u32 *flags)
+int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
+ const void *gpio_spec, u32 *flags)
{
const __be32 *gpio = gpio_spec;
const u32 n = be32_to_cpup(gpio);
@@ -151,6 +152,7 @@ static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
return n;
}
+EXPORT_SYMBOL(of_gpio_simple_xlate);
/**
* of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 9f689f1..0f0cfa3 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -19,15 +19,12 @@
*/
#include <linux/errno.h>
+#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/string.h>
-
-/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
-#ifndef NO_IRQ
-#define NO_IRQ 0
-#endif
+#include <linux/slab.h>
/**
* irq_of_parse_and_map - Parse and map an interrupt into linux virq space
@@ -42,7 +39,7 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
struct of_irq oirq;
if (of_irq_map_one(dev, index, &oirq))
- return NO_IRQ;
+ return 0;
return irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
@@ -343,7 +340,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
/* Only dereference the resource if both the
* resource and the irq are valid. */
- if (r && irq != NO_IRQ) {
+ if (r && irq) {
r->start = r->end = irq;
r->flags = IORESOURCE_IRQ;
r->name = dev->full_name;
@@ -361,7 +358,7 @@ int of_irq_count(struct device_node *dev)
{
int nr = 0;
- while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ)
+ while (of_irq_to_resource(dev, nr, NULL))
nr++;
return nr;
@@ -381,8 +378,115 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
int i;
for (i = 0; i < nr_irqs; i++, res++)
- if (of_irq_to_resource(dev, i, res) == NO_IRQ)
+ if (!of_irq_to_resource(dev, i, res))
break;
return i;
}
+
+struct intc_desc {
+ struct list_head list;
+ struct device_node *dev;
+ struct device_node *interrupt_parent;
+};
+
+/**
+ * of_irq_init - Scan and init matching interrupt controllers in DT
+ * @matches: 0 terminated array of nodes to match and init function to call
+ *
+ * This function scans the device tree for matching interrupt controller nodes,
+ * and calls their initialization functions in order with parents first.
+ */
+void __init of_irq_init(const struct of_device_id *matches)
+{
+ struct device_node *np, *parent = NULL;
+ struct intc_desc *desc, *temp_desc;
+ struct list_head intc_desc_list, intc_parent_list;
+
+ INIT_LIST_HEAD(&intc_desc_list);
+ INIT_LIST_HEAD(&intc_parent_list);
+
+ for_each_matching_node(np, matches) {
+ if (!of_find_property(np, "interrupt-controller", NULL))
+ continue;
+ /*
+ * Here, we allocate and populate an intc_desc with the node
+ * pointer, interrupt-parent device_node etc.
+ */
+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ if (WARN_ON(!desc))
+ goto err;
+
+ desc->dev = np;
+ desc->interrupt_parent = of_irq_find_parent(np);
+ if (desc->interrupt_parent == np)
+ desc->interrupt_parent = NULL;
+ list_add_tail(&desc->list, &intc_desc_list);
+ }
+
+ /*
+ * The root irq controller is the one without an interrupt-parent.
+ * That one goes first, followed by the controllers that reference it,
+ * followed by the ones that reference the 2nd level controllers, etc.
+ */
+ while (!list_empty(&intc_desc_list)) {
+ /*
+ * Process all controllers with the current 'parent'.
+ * First pass will be looking for NULL as the parent.
+ * The assumption is that NULL parent means a root controller.
+ */
+ list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
+ const struct of_device_id *match;
+ int ret;
+ of_irq_init_cb_t irq_init_cb;
+
+ if (desc->interrupt_parent != parent)
+ continue;
+
+ list_del(&desc->list);
+ match = of_match_node(matches, desc->dev);
+ if (WARN(!match->data,
+ "of_irq_init: no init function for %s\n",
+ match->compatible)) {
+ kfree(desc);
+ continue;
+ }
+
+ pr_debug("of_irq_init: init %s @ %p, parent %p\n",
+ match->compatible,
+ desc->dev, desc->interrupt_parent);
+ irq_init_cb = match->data;
+ ret = irq_init_cb(desc->dev, desc->interrupt_parent);
+ if (ret) {
+ kfree(desc);
+ continue;
+ }
+
+ /*
+ * This one is now set up; add it to the parent list so
+ * its children can get processed in a subsequent pass.
+ */
+ list_add_tail(&desc->list, &intc_parent_list);
+ }
+
+ /* Get the next pending parent that might have children */
+ desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
+ if (list_empty(&intc_parent_list) || !desc) {
+ pr_err("of_irq_init: children remain, but no parents\n");
+ break;
+ }
+ list_del(&desc->list);
+ parent = desc->dev;
+ kfree(desc);
+ }
+
+ list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
+ list_del(&desc->list);
+ kfree(desc);
+ }
+err:
+ list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
+ list_del(&desc->list);
+ kfree(desc);
+ }
+}
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index d35e300..980c079 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -83,7 +83,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
addr);
continue;
}
- phy_scan_fixups(phy);
/* Associate the OF node with the device structure so it
* can be looked up later */
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
index 86f334a..ffab033 100644
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -8,6 +8,52 @@
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/of_net.h>
+#include <linux/phy.h>
+#include <linux/export.h>
+
+/**
+ * It maps 'enum phy_interface_t' found in include/linux/phy.h
+ * into the device tree binding of 'phy-mode', so that Ethernet
+ * device driver can get phy interface from device tree.
+ */
+static const char *phy_modes[] = {
+ [PHY_INTERFACE_MODE_NA] = "",
+ [PHY_INTERFACE_MODE_MII] = "mii",
+ [PHY_INTERFACE_MODE_GMII] = "gmii",
+ [PHY_INTERFACE_MODE_SGMII] = "sgmii",
+ [PHY_INTERFACE_MODE_TBI] = "tbi",
+ [PHY_INTERFACE_MODE_RMII] = "rmii",
+ [PHY_INTERFACE_MODE_RGMII] = "rgmii",
+ [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id",
+ [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
+ [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+ [PHY_INTERFACE_MODE_RTBI] = "rtbi",
+ [PHY_INTERFACE_MODE_SMII] = "smii",
+};
+
+/**
+ * of_get_phy_mode - Get phy mode for given device_node
+ * @np: Pointer to the given device_node
+ *
+ * The function gets phy interface string from property 'phy-mode',
+ * and return its index in phy_modes table, or errno in error case.
+ */
+const int of_get_phy_mode(struct device_node *np)
+{
+ const char *pm;
+ int err, i;
+
+ err = of_property_read_string(np, "phy-mode", &pm);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
+ if (!strcasecmp(pm, phy_modes[i]))
+ return i;
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(of_get_phy_mode);
/**
* Search the device tree for the best MAC address to use. 'mac-address' is
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ac1ec54..13e37e2 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -1,92 +1,42 @@
#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/of.h>
#include <linux/of_pci.h>
-#include <linux/of_irq.h>
#include <asm/prom.h>
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev: the device whose interrupt is to be resolved
- * @out_irq: structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+static inline int __of_pci_pci_compare(struct device_node *node,
+ unsigned int devfn)
{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- __be32 lspec_be;
- __be32 laddr[3];
- u8 pin;
- int rc;
+ unsigned int size;
+ const __be32 *reg = of_get_property(node, "reg", &size);
- /* Check if we have a device node, if yes, fallback to standard
- * device tree parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn) {
- rc = of_irq_map_one(dn, 0, out_irq);
- if (!rc)
- return rc;
- }
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
- ppnode = pci_bus_to_OF_node(pdev->bus);
-
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else {
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
- }
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't
- * include the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
+ if (!reg || size < 5 * sizeof(__be32))
+ return 0;
+ return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn;
+}
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
+struct device_node *of_pci_find_child_device(struct device_node *parent,
+ unsigned int devfn)
+{
+ struct device_node *node, *node2;
+
+ for_each_child_of_node(parent, node) {
+ if (__of_pci_pci_compare(node, devfn))
+ return node;
+ /*
+ * Some OFs create a parent node "multifunc-device" as
+ * a fake root for all functions of a multi-function
+ * device we go down them as well.
*/
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
+ if (!strcmp(node->name, "multifunc-device")) {
+ for_each_child_of_node(node, node2) {
+ if (__of_pci_pci_compare(node2, devfn)) {
+ of_node_put(node);
+ return node2;
+ }
+ }
+ }
}
-
- lspec_be = cpu_to_be32(lspec);
- laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
- laddr[1] = laddr[2] = cpu_to_be32(0);
- return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+ return NULL;
}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
+EXPORT_SYMBOL_GPL(of_pci_find_child_device);
diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c
index 1dbce58..6dbc074 100644
--- a/drivers/of/of_spi.c
+++ b/drivers/of/of_spi.c
@@ -6,6 +6,7 @@
* tree.
*/
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 4d87b5d..bc5b399 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
return ret;
}
+static void *kernel_tree_alloc(u64 size, u64 align)
+{
+ return prom_early_alloc(size);
+}
+
void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
{
struct device_node **nextp;
@@ -245,4 +250,7 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
nextp = &allnodes->allnext;
allnodes->child = of_pdt_build_tree(allnodes,
of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_alias_scan(kernel_tree_alloc);
}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 63d3cb7..63b3ec4 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -13,6 +13,7 @@
*/
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/amba/bus.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
@@ -22,6 +23,14 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+const struct of_device_id of_default_bus_match_table[] = {
+ { .compatible = "simple-bus", },
+#ifdef CONFIG_ARM_AMBA
+ { .compatible = "arm,amba-bus", },
+#endif /* CONFIG_ARM_AMBA */
+ {} /* Empty terminated list */
+};
+
static int of_dev_node_match(struct device *dev, void *data)
{
return dev->of_node == data;
@@ -153,7 +162,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
}
dev->dev.of_node = of_node_get(np);
-#if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
+#if defined(CONFIG_MICROBLAZE)
dev->dev.dma_mask = &dev->archdata.dma_mask;
#endif
dev->dev.parent = parent;
@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np,
EXPORT_SYMBOL(of_device_alloc);
/**
- * of_platform_device_create - Alloc, initialize and register an of_device
+ * of_platform_device_create_pdata - Alloc, initialize and register an of_device
* @np: pointer to node to create device for
* @bus_id: name to assign device
+ * @platform_data: pointer to populate platform_data pointer with
* @parent: Linux device model parent device.
*
* Returns pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
-struct platform_device *of_platform_device_create(struct device_node *np,
- const char *bus_id,
- struct device *parent)
+struct platform_device *of_platform_device_create_pdata(
+ struct device_node *np,
+ const char *bus_id,
+ void *platform_data,
+ struct device *parent)
{
struct platform_device *dev;
@@ -189,11 +201,12 @@ struct platform_device *of_platform_device_create(struct device_node *np,
if (!dev)
return NULL;
-#if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
+#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
#endif
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->dev.bus = &platform_bus_type;
+ dev->dev.platform_data = platform_data;
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
@@ -207,33 +220,162 @@ struct platform_device *of_platform_device_create(struct device_node *np,
return dev;
}
+
+/**
+ * of_platform_device_create - Alloc, initialize and register an of_device
+ * @np: pointer to node to create device for
+ * @bus_id: name to assign device
+ * @parent: Linux device model parent device.
+ *
+ * Returns pointer to created platform device, or NULL if a device was not
+ * registered. Unavailable devices will not get registered.
+ */
+struct platform_device *of_platform_device_create(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ return of_platform_device_create_pdata(np, bus_id, NULL, parent);
+}
EXPORT_SYMBOL(of_platform_device_create);
+#ifdef CONFIG_ARM_AMBA
+static struct amba_device *of_amba_device_create(struct device_node *node,
+ const char *bus_id,
+ void *platform_data,
+ struct device *parent)
+{
+ struct amba_device *dev;
+ const void *prop;
+ int i, ret;
+
+ pr_debug("Creating amba device %s\n", node->full_name);
+
+ if (!of_device_is_available(node))
+ return NULL;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ /* setup generic device info */
+ dev->dev.coherent_dma_mask = ~0;
+ dev->dev.of_node = of_node_get(node);
+ dev->dev.parent = parent;
+ dev->dev.platform_data = platform_data;
+ if (bus_id)
+ dev_set_name(&dev->dev, "%s", bus_id);
+ else
+ of_device_make_bus_id(&dev->dev);
+
+ /* setup amba-specific device info */
+ dev->dma_mask = ~0;
+
+ /* Allow the HW Peripheral ID to be overridden */
+ prop = of_get_property(node, "arm,primecell-periphid", NULL);
+ if (prop)
+ dev->periphid = of_read_ulong(prop, 1);
+
+ /* Decode the IRQs and address ranges */
+ for (i = 0; i < AMBA_NR_IRQS; i++)
+ dev->irq[i] = irq_of_parse_and_map(node, i);
+
+ ret = of_address_to_resource(node, 0, &dev->res);
+ if (ret)
+ goto err_free;
+
+ ret = amba_device_register(dev, &iomem_resource);
+ if (ret)
+ goto err_free;
+
+ return dev;
+
+err_free:
+ kfree(dev);
+ return NULL;
+}
+#else /* CONFIG_ARM_AMBA */
+static struct amba_device *of_amba_device_create(struct device_node *node,
+ const char *bus_id,
+ void *platform_data,
+ struct device *parent)
+{
+ return NULL;
+}
+#endif /* CONFIG_ARM_AMBA */
+
+/**
+ * of_devname_lookup() - Given a device node, lookup the preferred Linux name
+ */
+static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
+ struct device_node *np)
+{
+ struct resource res;
+
+ if (!lookup)
+ return NULL;
+
+ for(; lookup->compatible != NULL; lookup++) {
+ if (!of_device_is_compatible(np, lookup->compatible))
+ continue;
+ if (of_address_to_resource(np, 0, &res))
+ continue;
+ if (res.start != lookup->phys_addr)
+ continue;
+ pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
+ return lookup;
+ }
+
+ return NULL;
+}
+
/**
* of_platform_bus_create() - Create a device for a node and its children.
* @bus: device node of the bus to instantiate
* @matches: match table for bus nodes
- * disallow recursive creation of child buses
+ * @lookup: auxdata table for matching id and platform_data with device nodes
* @parent: parent for new device, or NULL for top level.
+ * @strict: require compatible property
*
* Creates a platform_device for the provided device_node, and optionally
* recursively create devices for all the child nodes.
*/
static int of_platform_bus_create(struct device_node *bus,
const struct of_device_id *matches,
- struct device *parent)
+ const struct of_dev_auxdata *lookup,
+ struct device *parent, bool strict)
{
+ const struct of_dev_auxdata *auxdata;
struct device_node *child;
struct platform_device *dev;
+ const char *bus_id = NULL;
+ void *platform_data = NULL;
int rc = 0;
- dev = of_platform_device_create(bus, NULL, parent);
+ /* Make sure it has a compatible property */
+ if (strict && (!of_get_property(bus, "compatible", NULL))) {
+ pr_debug("%s() - skipping %s, no compatible prop\n",
+ __func__, bus->full_name);
+ return 0;
+ }
+
+ auxdata = of_dev_lookup(lookup, bus);
+ if (auxdata) {
+ bus_id = auxdata->name;
+ platform_data = auxdata->platform_data;
+ }
+
+ if (of_device_is_compatible(bus, "arm,primecell")) {
+ of_amba_device_create(bus, bus_id, platform_data, parent);
+ return 0;
+ }
+
+ dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
if (!dev || !of_match_node(matches, bus))
return 0;
for_each_child_of_node(bus, child) {
pr_debug(" create child: %s\n", child->full_name);
- rc = of_platform_bus_create(child, matches, &dev->dev);
+ rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
if (rc) {
of_node_put(child);
break;
@@ -267,11 +409,11 @@ int of_platform_bus_probe(struct device_node *root,
/* Do a self check of bus type, if there's a match, create children */
if (of_match_node(matches, root)) {
- rc = of_platform_bus_create(root, matches, parent);
+ rc = of_platform_bus_create(root, matches, NULL, parent, false);
} else for_each_child_of_node(root, child) {
if (!of_match_node(matches, child))
continue;
- rc = of_platform_bus_create(child, matches, parent);
+ rc = of_platform_bus_create(child, matches, NULL, parent, false);
if (rc)
break;
}
@@ -280,4 +422,44 @@ int of_platform_bus_probe(struct device_node *root,
return rc;
}
EXPORT_SYMBOL(of_platform_bus_probe);
+
+/**
+ * of_platform_populate() - Populate platform_devices from device tree data
+ * @root: parent of the first level to probe or NULL for the root of the tree
+ * @matches: match table, NULL to use the default
+ * @parent: parent to hook devices from, NULL for toplevel
+ *
+ * Similar to of_platform_bus_probe(), this function walks the device tree
+ * and creates devices from nodes. It differs in that it follows the modern
+ * convention of requiring all device nodes to have a 'compatible' property,
+ * and it is suitable for creating devices which are children of the root
+ * node (of_platform_bus_probe will only create children of the root which
+ * are selected by the @matches argument).
+ *
+ * New board support should be using this function instead of
+ * of_platform_bus_probe().
+ *
+ * Returns 0 on success, < 0 on failure.
+ */
+int of_platform_populate(struct device_node *root,
+ const struct of_device_id *matches,
+ const struct of_dev_auxdata *lookup,
+ struct device *parent)
+{
+ struct device_node *child;
+ int rc = 0;
+
+ root = root ? of_node_get(root) : of_find_node_by_path("/");
+ if (!root)
+ return -EINVAL;
+
+ for_each_child_of_node(root, child) {
+ rc = of_platform_bus_create(child, matches, lookup, parent, true);
+ if (rc)
+ break;
+ }
+
+ of_node_put(root);
+ return rc;
+}
#endif /* !CONFIG_SPARC */
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index dd87e86..c0cc4e7 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -82,10 +82,10 @@ int alloc_event_buffer(void)
{
unsigned long flags;
- spin_lock_irqsave(&oprofilefs_lock, flags);
+ raw_spin_lock_irqsave(&oprofilefs_lock, flags);
buffer_size = oprofile_buffer_size;
buffer_watershed = oprofile_buffer_watershed;
- spin_unlock_irqrestore(&oprofilefs_lock, flags);
+ raw_spin_unlock_irqrestore(&oprofilefs_lock, flags);
if (buffer_watershed >= buffer_size)
return -EINVAL;
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index 137406c..efc4b7f 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -31,7 +31,7 @@ static int num_counters;
/*
* Overflow callback for oprofile.
*/
-static void op_overflow_handler(struct perf_event *event, int unused,
+static void op_overflow_handler(struct perf_event *event,
struct perf_sample_data *data, struct pt_regs *regs)
{
int id;
@@ -79,7 +79,7 @@ static int op_create_counter(int cpu, int event)
pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
cpu, NULL,
- op_overflow_handler);
+ op_overflow_handler, NULL);
if (IS_ERR(pevent))
return PTR_ERR(pevent);
@@ -160,9 +160,9 @@ static int oprofile_perf_create_files(struct super_block *sb, struct dentry *roo
static int oprofile_perf_setup(void)
{
- spin_lock(&oprofilefs_lock);
+ raw_spin_lock(&oprofilefs_lock);
op_perf_setup();
- spin_unlock(&oprofilefs_lock);
+ raw_spin_unlock(&oprofilefs_lock);
return 0;
}
diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h
index 0b54e46..38b6fc0 100644
--- a/drivers/oprofile/oprofile_stats.h
+++ b/drivers/oprofile/oprofile_stats.h
@@ -10,7 +10,7 @@
#ifndef OPROFILE_STATS_H
#define OPROFILE_STATS_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct oprofile_stat_struct {
atomic_t sample_lost_no_mm;
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 1c0b799..2f0aa0f 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -21,7 +21,7 @@
#define OPROFILEFS_MAGIC 0x6f70726f
-DEFINE_SPINLOCK(oprofilefs_lock);
+DEFINE_RAW_SPINLOCK(oprofilefs_lock);
static struct inode *oprofilefs_get_inode(struct super_block *sb, int mode)
{
@@ -83,9 +83,9 @@ int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_
if (copy_from_user(tmpbuf, buf, count))
return -EFAULT;
- spin_lock_irqsave(&oprofilefs_lock, flags);
+ raw_spin_lock_irqsave(&oprofilefs_lock, flags);
*val = simple_strtoul(tmpbuf, NULL, 0);
- spin_unlock_irqrestore(&oprofilefs_lock, flags);
+ raw_spin_unlock_irqrestore(&oprofilefs_lock, flags);
return count;
}
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 75a80e4..8b490d7 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -44,6 +44,7 @@
#include <linux/seq_file.h>
#include <linux/scatterlist.h>
#include <linux/iommu-helper.h>
+#include <linux/export.h>
#include <asm/byteorder.h>
#include <asm/cache.h> /* for L1_CACHE_BYTES */
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 57a6d19..8644d53 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -39,6 +39,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <asm/ropes.h>
#include <asm/mckinley.h> /* for proc_mckinley_root */
@@ -668,7 +669,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
* @dev: instance of PCI owned by the driver that's asking
* @mask: number of address bits this PCI device can handle
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static int sba_dma_supported( struct device *dev, u64 mask)
{
@@ -680,7 +681,7 @@ static int sba_dma_supported( struct device *dev, u64 mask)
return(0);
}
- /* Documentation/PCI/PCI-DMA-mapping.txt tells drivers to try 64-bit
+ /* Documentation/DMA-API-HOWTO.txt tells drivers to try 64-bit
* first, then fall back to 32-bit if that fails.
* We are just "encouraging" 32-bit DMA masks here since we can
* never allow IOMMU bypass unless we add special support for ZX1.
@@ -706,7 +707,7 @@ static int sba_dma_supported( struct device *dev, u64 mask)
* @size: number of bytes to map in driver buffer.
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static dma_addr_t
sba_map_single(struct device *dev, void *addr, size_t size,
@@ -785,7 +786,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
* @size: number of bytes mapped in driver buffer.
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void
sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
@@ -861,7 +862,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* @size: number of bytes mapped in driver buffer.
* @dma_handle: IOVA of new buffer.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void *sba_alloc_consistent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
@@ -892,7 +893,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size,
* @vaddr: virtual address IOVA of "consistent" buffer.
* @dma_handler: IO virtual address of "consistent" buffer.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void
sba_free_consistent(struct device *hwdev, size_t size, void *vaddr,
@@ -927,7 +928,7 @@ int dump_run_sg = 0;
* @nents: number of entries in list
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static int
sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
@@ -1011,7 +1012,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
* @nents: number of entries in list
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void
sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
index 2c5ac2b..844f613 100644
--- a/drivers/parport/parport_ax88796.c
+++ b/drivers/parport/parport_ax88796.c
@@ -293,7 +293,7 @@ static int parport_ax88796_probe(struct platform_device *pdev)
goto exit_mem;
}
- size = (res->end - res->start) + 1;
+ size = resource_size(res);
spacing = size / 3;
dd->io = request_mem_region(res->start, size, pdev->name);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index f330338..5a4432d 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2595,14 +2595,17 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
break;
case 0x6:
printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n");
+ release_region(inta_addr[i], 32);
return 0;
case 0x8:
printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n");
+ release_region(inta_addr[i], 32);
return 0;
default:
printk(KERN_INFO "parport_pc: unknown ITE887x\n");
printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' "
"output to Rich.Liu@ite.com.tw\n");
+ release_region(inta_addr[i], 32);
return 0;
}
@@ -2864,24 +2867,6 @@ enum parport_pc_pci_cards {
lava_parallel_dual_b,
boca_ioppar,
plx_9050,
- timedia_4078a,
- timedia_4079h,
- timedia_4085h,
- timedia_4088a,
- timedia_4089a,
- timedia_4095a,
- timedia_4096a,
- timedia_4078u,
- timedia_4079a,
- timedia_4085u,
- timedia_4079r,
- timedia_4079s,
- timedia_4079d,
- timedia_4079e,
- timedia_4079f,
- timedia_9079a,
- timedia_9079b,
- timedia_9079c,
timedia_4006a,
timedia_4014,
timedia_4008a,
@@ -2890,8 +2875,6 @@ enum parport_pc_pci_cards {
syba_2p_epp,
syba_1p_ecp,
titan_010l,
- titan_1284p1,
- titan_1284p2,
avlab_1p,
avlab_2p,
oxsemi_952,
@@ -2940,24 +2923,6 @@ static struct parport_pc_pci {
/* lava_parallel_dual_b */ { 1, { { 0, -1 }, } },
/* boca_ioppar */ { 1, { { 0, -1 }, } },
/* plx_9050 */ { 2, { { 4, -1 }, { 5, -1 }, } },
- /* timedia_4078a */ { 1, { { 2, -1 }, } },
- /* timedia_4079h */ { 1, { { 2, 3 }, } },
- /* timedia_4085h */ { 2, { { 2, -1 }, { 4, -1 }, } },
- /* timedia_4088a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4089a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4095a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4096a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4078u */ { 1, { { 2, -1 }, } },
- /* timedia_4079a */ { 1, { { 2, 3 }, } },
- /* timedia_4085u */ { 2, { { 2, -1 }, { 4, -1 }, } },
- /* timedia_4079r */ { 1, { { 2, 3 }, } },
- /* timedia_4079s */ { 1, { { 2, 3 }, } },
- /* timedia_4079d */ { 1, { { 2, 3 }, } },
- /* timedia_4079e */ { 1, { { 2, 3 }, } },
- /* timedia_4079f */ { 1, { { 2, 3 }, } },
- /* timedia_9079a */ { 1, { { 2, 3 }, } },
- /* timedia_9079b */ { 1, { { 2, 3 }, } },
- /* timedia_9079c */ { 1, { { 2, 3 }, } },
/* timedia_4006a */ { 1, { { 0, -1 }, } },
/* timedia_4014 */ { 2, { { 0, -1 }, { 2, -1 }, } },
/* timedia_4008a */ { 1, { { 0, 1 }, } },
@@ -2968,8 +2933,6 @@ static struct parport_pc_pci {
/* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } },
/* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } },
/* titan_010l */ { 1, { { 3, -1 }, } },
- /* titan_1284p1 */ { 1, { { 0, 1 }, } },
- /* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } },
/* avlab_1p */ { 1, { { 0, 1}, } },
/* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} },
/* The Oxford Semi cards are unusual: 954 doesn't support ECP,
@@ -2985,8 +2948,8 @@ static struct parport_pc_pci {
/* netmos_9705 */ { 1, { { 0, -1 }, } },
/* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} },
/* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} },
- /* netmos_9805 */ { 1, { { 0, -1 }, } },
- /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } },
+ /* netmos_9805 */ { 1, { { 0, 1 }, } },
+ /* netmos_9815 */ { 2, { { 0, 1 }, { 2, 3 }, } },
/* netmos_9901 */ { 1, { { 0, -1 }, } },
/* netmos_9865 */ { 1, { { 0, -1 }, } },
/* quatech_sppxp100 */ { 1, { { 0, 1 }, } },
@@ -3019,24 +2982,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 },
/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
- { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
- { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
- { 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
- { 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
- { 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
- { 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
- { 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
- { 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
- { 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
- { 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
- { 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
- { 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
- { 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
- { 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
- { 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
- { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
- { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
- { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
{ 0x1409, 0x7268, 0x1409, 0x0101, 0, 0, timedia_4006a },
{ 0x1409, 0x7268, 0x1409, 0x0102, 0, 0, timedia_4014 },
{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },
@@ -3048,8 +2993,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
- { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 },
- { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
/* AFAVLAB_TK9902 */
{ 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p},
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index f01e264..e9c3227 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -33,6 +33,9 @@ enum parport_pc_pci_cards {
netmos_9xx5_combo,
netmos_9855,
netmos_9855_2p,
+ netmos_9900,
+ netmos_9900_2p,
+ netmos_99xx_1p,
avlab_1s1p,
avlab_1s2p,
avlab_2s1p,
@@ -41,6 +44,24 @@ enum parport_pc_pci_cards {
siig_2p1s_20x,
siig_1s1p_20x,
siig_2s1p_20x,
+ timedia_4078a,
+ timedia_4079h,
+ timedia_4085h,
+ timedia_4088a,
+ timedia_4089a,
+ timedia_4095a,
+ timedia_4096a,
+ timedia_4078u,
+ timedia_4079a,
+ timedia_4085u,
+ timedia_4079r,
+ timedia_4079s,
+ timedia_4079d,
+ timedia_4079e,
+ timedia_4079f,
+ timedia_9079a,
+ timedia_9079b,
+ timedia_9079c,
};
/* each element directly indexed from enum list, above */
@@ -72,22 +93,20 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
dev->subsystem_device == 0x0299)
return -ENODEV;
- /*
- * Netmos uses the subdevice ID to indicate the number of parallel
- * and serial ports. The form is 0x00PS, where <P> is the number of
- * parallel ports and <S> is the number of serial ports.
- */
- par->numports = (dev->subsystem_device & 0xf0) >> 4;
- if (par->numports > ARRAY_SIZE(par->addr))
- par->numports = ARRAY_SIZE(par->addr);
- /*
- * This function is currently only called for cards with up to
- * one parallel port.
- * Parallel port BAR is either before or after serial ports BARS;
- * hence, lo should be either 0 or equal to the number of serial ports.
- */
- if (par->addr[0].lo != 0)
- par->addr[0].lo = dev->subsystem_device & 0xf;
+
+ if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
+ par->numports = 1;
+ } else {
+ /*
+ * Netmos uses the subdevice ID to indicate the number of parallel
+ * and serial ports. The form is 0x00PS, where <P> is the number of
+ * parallel ports and <S> is the number of serial ports.
+ */
+ par->numports = (dev->subsystem_device & 0xf0) >> 4;
+ if (par->numports > ARRAY_SIZE(par->addr))
+ par->numports = ARRAY_SIZE(par->addr);
+ }
+
return 0;
}
@@ -97,6 +116,9 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
/* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init },
/* netmos_9855_2p */ { 2, { { 0, -1 }, { 2, -1 }, } },
+ /* netmos_9900 */ {1, { { 3, 4 }, }, netmos_parallel_init },
+ /* netmos_9900_2p */ {2, { { 0, 1 }, { 3, 4 }, } },
+ /* netmos_99xx_1p */ {1, { { 0, 1 }, } },
/* avlab_1s1p */ { 1, { { 1, 2}, } },
/* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} },
/* avlab_2s1p */ { 1, { { 2, 3}, } },
@@ -105,6 +127,24 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* siig_2p1s_20x */ { 2, { { 1, 2 }, { 3, 4 }, } },
/* siig_1s1p_20x */ { 1, { { 1, 2 }, } },
/* siig_2s1p_20x */ { 1, { { 2, 3 }, } },
+ /* timedia_4078a */ { 1, { { 2, -1 }, } },
+ /* timedia_4079h */ { 1, { { 2, 3 }, } },
+ /* timedia_4085h */ { 2, { { 2, -1 }, { 4, -1 }, } },
+ /* timedia_4088a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4089a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4095a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4096a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4078u */ { 1, { { 2, -1 }, } },
+ /* timedia_4079a */ { 1, { { 2, 3 }, } },
+ /* timedia_4085u */ { 2, { { 2, -1 }, { 4, -1 }, } },
+ /* timedia_4079r */ { 1, { { 2, 3 }, } },
+ /* timedia_4079s */ { 1, { { 2, 3 }, } },
+ /* timedia_4079d */ { 1, { { 2, 3 }, } },
+ /* timedia_4079e */ { 1, { { 2, 3 }, } },
+ /* timedia_4079f */ { 1, { { 2, 3 }, } },
+ /* timedia_9079a */ { 1, { { 2, 3 }, } },
+ /* timedia_9079b */ { 1, { { 2, 3 }, } },
+ /* timedia_9079c */ { 1, { { 2, 3 }, } },
};
static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -127,6 +167,14 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
0x1000, 0x0022, 0, 0, netmos_9855_2p },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3011, 0, 0, netmos_9900 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3012, 0, 0, netmos_9900 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3020, 0, 0, netmos_9900_2p },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+ 0xA000, 0x2000, 0, 0, netmos_99xx_1p },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ PCI_VENDOR_ID_AFAVLAB, 0x2110,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
@@ -176,6 +224,25 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+ /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
+ { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
+ { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
+ { 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
+ { 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
+ { 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
+ { 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
+ { 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
+ { 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
+ { 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
+ { 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
+ { 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
+ { 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
+ { 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
+ { 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
+ { 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
+ { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
+ { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
+ { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
{ 0, } /* terminate list */
};
@@ -219,6 +286,24 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 8,
},
+ [netmos_9900] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [netmos_9900_2p] = { /* parallel only */ /* n/t */
+ .flags = FL_BASE0,
+ .num_ports = 0,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [netmos_99xx_1p] = { /* parallel only */ /* n/t */
+ .flags = FL_BASE0,
+ .num_ports = 0,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[avlab_1s1p] = { /* n/t */
.flags = FL_BASE0 | FL_BASE_BARS,
.num_ports = 1,
@@ -267,6 +352,114 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 8,
},
+ [timedia_4078a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079h] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4085h] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4088a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4089a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4095a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4096a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4078u] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4085u] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079r] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079s] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079d] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079e] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079f] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_9079a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_9079b] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_9079c] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
};
struct parport_serial_private {
@@ -285,6 +478,10 @@ static int __devinit serial_register (struct pci_dev *dev,
struct serial_private *serial;
board = &pci_parport_serial_boards[id->driver_data];
+
+ if (board->num_ports == 0)
+ return 0;
+
serial = pciserial_init_ports(dev, board);
if (IS_ERR(serial))
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0fa466a..f02b523 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -51,17 +51,6 @@ config XEN_PCIDEV_FRONTEND
The PCI device frontend driver allows the kernel to import arbitrary
PCI devices from a PCI backend to support PCI driver domains.
-config XEN_PCIDEV_FE_DEBUG
- bool "Xen PCI Frontend debugging"
- depends on XEN_PCIDEV_FRONTEND && PCI_DEBUG
- help
- Say Y here if you want the Xen PCI frontend to produce a bunch of debug
- messages to the system log. Select this if you are having a
- problem with Xen PCI frontend support and want to see more of what is
- going on.
-
- When in doubt, say N.
-
config HT_IRQ
bool "Interrupts on hypertransport devices"
default y
@@ -71,9 +60,13 @@ config HT_IRQ
If unsure say Y.
+config PCI_ATS
+ bool
+
config PCI_IOV
bool "PCI IOV support"
depends on PCI
+ select PCI_ATS
help
I/O Virtualization is a PCI feature supported by some devices
which allows them to create virtual devices which share their
@@ -81,6 +74,29 @@ config PCI_IOV
If unsure, say N.
+config PCI_PRI
+ bool "PCI PRI support"
+ depends on PCI
+ select PCI_ATS
+ help
+ PRI is the PCI Page Request Interface. It allows PCI devices that are
+ behind an IOMMU to recover from page faults.
+
+ If unsure, say N.
+
+config PCI_PASID
+ bool "PCI PASID support"
+ depends on PCI
+ select PCI_ATS
+ help
+ Process Address Space Identifiers (PASIDs) can be used by PCI devices
+ to access more than one IO address space at the same time. To make
+ use of this feature an IOMMU is required which also supports PASIDs.
+ Select this option if you have such an IOMMU and want to compile the
+ driver for it into your kernel.
+
+ If unsure, say N.
+
config PCI_IOAPIC
bool
depends on PCI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 9eff33b..165274c 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -29,11 +29,7 @@ obj-$(CONFIG_PCI_MSI) += msi.o
# Build the Hypertransport interrupt support
obj-$(CONFIG_HT_IRQ) += htirq.o
-# Build Intel IOMMU support
-obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
-
-obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
-
+obj-$(CONFIG_PCI_ATS) += ats.o
obj-$(CONFIG_PCI_IOV) += iov.o
#
@@ -72,4 +68,6 @@ obj-$(CONFIG_PCI_STUB) += pci-stub.o
obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
+obj-$(CONFIG_OF) += of.o
+
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index fdaa42a..fac01f8 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -355,6 +355,56 @@ static const struct pci_vpd_ops pci_vpd_pci22_ops = {
.release = pci_vpd_pci22_release,
};
+static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
+ void *arg)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ ssize_t ret;
+
+ if (!tdev)
+ return -ENODEV;
+
+ ret = pci_read_vpd(tdev, pos, count, arg);
+ pci_dev_put(tdev);
+ return ret;
+}
+
+static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
+ const void *arg)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ ssize_t ret;
+
+ if (!tdev)
+ return -ENODEV;
+
+ ret = pci_write_vpd(tdev, pos, count, arg);
+ pci_dev_put(tdev);
+ return ret;
+}
+
+static const struct pci_vpd_ops pci_vpd_f0_ops = {
+ .read = pci_vpd_f0_read,
+ .write = pci_vpd_f0_write,
+ .release = pci_vpd_pci22_release,
+};
+
+static int pci_vpd_f0_dev_check(struct pci_dev *dev)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ int ret = 0;
+
+ if (!tdev)
+ return -ENODEV;
+ if (!tdev->vpd || !tdev->multifunction ||
+ dev->class != tdev->class || dev->vendor != tdev->vendor ||
+ dev->device != tdev->device)
+ ret = -ENODEV;
+
+ pci_dev_put(tdev);
+ return ret;
+}
+
int pci_vpd_pci22_init(struct pci_dev *dev)
{
struct pci_vpd_pci22 *vpd;
@@ -363,12 +413,21 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
if (!cap)
return -ENODEV;
+ if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
+ int ret = pci_vpd_f0_dev_check(dev);
+
+ if (ret)
+ return ret;
+ }
vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
if (!vpd)
return -ENOMEM;
vpd->base.len = PCI_VPD_PCI22_SIZE;
- vpd->base.ops = &pci_vpd_pci22_ops;
+ if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
+ vpd->base.ops = &pci_vpd_f0_ops;
+ else
+ vpd->base.ops = &pci_vpd_pci22_ops;
mutex_init(&vpd->lock);
vpd->cap = cap;
vpd->busy = false;
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
deleted file mode 100644
index 6dcc7e2..0000000
--- a/drivers/pci/dmar.c
+++ /dev/null
@@ -1,1461 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Ashok Raj <ashok.raj@intel.com>
- * Author: Shaohua Li <shaohua.li@intel.com>
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *
- * This file implements early detection/parsing of Remapping Devices
- * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI
- * tables.
- *
- * These routines are used by both DMA-remapping and Interrupt-remapping
- */
-
-#include <linux/pci.h>
-#include <linux/dmar.h>
-#include <linux/iova.h>
-#include <linux/intel-iommu.h>
-#include <linux/timer.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/tboot.h>
-#include <linux/dmi.h>
-#include <linux/slab.h>
-#include <asm/iommu_table.h>
-
-#define PREFIX "DMAR: "
-
-/* No locks are needed as DMA remapping hardware unit
- * list is constructed at boot time and hotplug of
- * these units are not supported by the architecture.
- */
-LIST_HEAD(dmar_drhd_units);
-
-static struct acpi_table_header * __initdata dmar_tbl;
-static acpi_size dmar_tbl_size;
-
-static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
-{
- /*
- * add INCLUDE_ALL at the tail, so scan the list will find it at
- * the very end.
- */
- if (drhd->include_all)
- list_add_tail(&drhd->list, &dmar_drhd_units);
- else
- list_add(&drhd->list, &dmar_drhd_units);
-}
-
-static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
- struct pci_dev **dev, u16 segment)
-{
- struct pci_bus *bus;
- struct pci_dev *pdev = NULL;
- struct acpi_dmar_pci_path *path;
- int count;
-
- bus = pci_find_bus(segment, scope->bus);
- path = (struct acpi_dmar_pci_path *)(scope + 1);
- count = (scope->length - sizeof(struct acpi_dmar_device_scope))
- / sizeof(struct acpi_dmar_pci_path);
-
- while (count) {
- if (pdev)
- pci_dev_put(pdev);
- /*
- * Some BIOSes list non-exist devices in DMAR table, just
- * ignore it
- */
- if (!bus) {
- printk(KERN_WARNING
- PREFIX "Device scope bus [%d] not found\n",
- scope->bus);
- break;
- }
- pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
- if (!pdev) {
- printk(KERN_WARNING PREFIX
- "Device scope device [%04x:%02x:%02x.%02x] not found\n",
- segment, bus->number, path->dev, path->fn);
- break;
- }
- path ++;
- count --;
- bus = pdev->subordinate;
- }
- if (!pdev) {
- printk(KERN_WARNING PREFIX
- "Device scope device [%04x:%02x:%02x.%02x] not found\n",
- segment, scope->bus, path->dev, path->fn);
- *dev = NULL;
- return 0;
- }
- if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
- pdev->subordinate) || (scope->entry_type == \
- ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
- pci_dev_put(pdev);
- printk(KERN_WARNING PREFIX
- "Device scope type does not match for %s\n",
- pci_name(pdev));
- return -EINVAL;
- }
- *dev = pdev;
- return 0;
-}
-
-static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
- struct pci_dev ***devices, u16 segment)
-{
- struct acpi_dmar_device_scope *scope;
- void * tmp = start;
- int index;
- int ret;
-
- *cnt = 0;
- while (start < end) {
- scope = start;
- if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
- scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
- (*cnt)++;
- else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
- printk(KERN_WARNING PREFIX
- "Unsupported device scope\n");
- }
- start += scope->length;
- }
- if (*cnt == 0)
- return 0;
-
- *devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL);
- if (!*devices)
- return -ENOMEM;
-
- start = tmp;
- index = 0;
- while (start < end) {
- scope = start;
- if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
- scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) {
- ret = dmar_parse_one_dev_scope(scope,
- &(*devices)[index], segment);
- if (ret) {
- kfree(*devices);
- return ret;
- }
- index ++;
- }
- start += scope->length;
- }
-
- return 0;
-}
-
-/**
- * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
- * structure which uniquely represent one DMA remapping hardware unit
- * present in the platform
- */
-static int __init
-dmar_parse_one_drhd(struct acpi_dmar_header *header)
-{
- struct acpi_dmar_hardware_unit *drhd;
- struct dmar_drhd_unit *dmaru;
- int ret = 0;
-
- drhd = (struct acpi_dmar_hardware_unit *)header;
- dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
- if (!dmaru)
- return -ENOMEM;
-
- dmaru->hdr = header;
- dmaru->reg_base_addr = drhd->address;
- dmaru->segment = drhd->segment;
- dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
-
- ret = alloc_iommu(dmaru);
- if (ret) {
- kfree(dmaru);
- return ret;
- }
- dmar_register_drhd_unit(dmaru);
- return 0;
-}
-
-static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
-{
- struct acpi_dmar_hardware_unit *drhd;
- int ret = 0;
-
- drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
-
- if (dmaru->include_all)
- return 0;
-
- ret = dmar_parse_dev_scope((void *)(drhd + 1),
- ((void *)drhd) + drhd->header.length,
- &dmaru->devices_cnt, &dmaru->devices,
- drhd->segment);
- if (ret) {
- list_del(&dmaru->list);
- kfree(dmaru);
- }
- return ret;
-}
-
-#ifdef CONFIG_DMAR
-LIST_HEAD(dmar_rmrr_units);
-
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
- list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
-
-static int __init
-dmar_parse_one_rmrr(struct acpi_dmar_header *header)
-{
- struct acpi_dmar_reserved_memory *rmrr;
- struct dmar_rmrr_unit *rmrru;
-
- rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
- if (!rmrru)
- return -ENOMEM;
-
- rmrru->hdr = header;
- rmrr = (struct acpi_dmar_reserved_memory *)header;
- rmrru->base_address = rmrr->base_address;
- rmrru->end_address = rmrr->end_address;
-
- dmar_register_rmrr_unit(rmrru);
- return 0;
-}
-
-static int __init
-rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
-{
- struct acpi_dmar_reserved_memory *rmrr;
- int ret;
-
- rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
- ret = dmar_parse_dev_scope((void *)(rmrr + 1),
- ((void *)rmrr) + rmrr->header.length,
- &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
-
- if (ret || (rmrru->devices_cnt == 0)) {
- list_del(&rmrru->list);
- kfree(rmrru);
- }
- return ret;
-}
-
-static LIST_HEAD(dmar_atsr_units);
-
-static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
-{
- struct acpi_dmar_atsr *atsr;
- struct dmar_atsr_unit *atsru;
-
- atsr = container_of(hdr, struct acpi_dmar_atsr, header);
- atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
- if (!atsru)
- return -ENOMEM;
-
- atsru->hdr = hdr;
- atsru->include_all = atsr->flags & 0x1;
-
- list_add(&atsru->list, &dmar_atsr_units);
-
- return 0;
-}
-
-static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
-{
- int rc;
- struct acpi_dmar_atsr *atsr;
-
- if (atsru->include_all)
- return 0;
-
- atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
- rc = dmar_parse_dev_scope((void *)(atsr + 1),
- (void *)atsr + atsr->header.length,
- &atsru->devices_cnt, &atsru->devices,
- atsr->segment);
- if (rc || !atsru->devices_cnt) {
- list_del(&atsru->list);
- kfree(atsru);
- }
-
- return rc;
-}
-
-int dmar_find_matched_atsr_unit(struct pci_dev *dev)
-{
- int i;
- struct pci_bus *bus;
- struct acpi_dmar_atsr *atsr;
- struct dmar_atsr_unit *atsru;
-
- dev = pci_physfn(dev);
-
- list_for_each_entry(atsru, &dmar_atsr_units, list) {
- atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
- if (atsr->segment == pci_domain_nr(dev->bus))
- goto found;
- }
-
- return 0;
-
-found:
- for (bus = dev->bus; bus; bus = bus->parent) {
- struct pci_dev *bridge = bus->self;
-
- if (!bridge || !pci_is_pcie(bridge) ||
- bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
- return 0;
-
- if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
- for (i = 0; i < atsru->devices_cnt; i++)
- if (atsru->devices[i] == bridge)
- return 1;
- break;
- }
- }
-
- if (atsru->include_all)
- return 1;
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_ACPI_NUMA
-static int __init
-dmar_parse_one_rhsa(struct acpi_dmar_header *header)
-{
- struct acpi_dmar_rhsa *rhsa;
- struct dmar_drhd_unit *drhd;
-
- rhsa = (struct acpi_dmar_rhsa *)header;
- for_each_drhd_unit(drhd) {
- if (drhd->reg_base_addr == rhsa->base_address) {
- int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
-
- if (!node_online(node))
- node = -1;
- drhd->iommu->node = node;
- return 0;
- }
- }
- WARN_TAINT(
- 1, TAINT_FIRMWARE_WORKAROUND,
- "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
- "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
- drhd->reg_base_addr,
- dmi_get_system_info(DMI_BIOS_VENDOR),
- dmi_get_system_info(DMI_BIOS_VERSION),
- dmi_get_system_info(DMI_PRODUCT_VERSION));
-
- return 0;
-}
-#endif
-
-static void __init
-dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
-{
- struct acpi_dmar_hardware_unit *drhd;
- struct acpi_dmar_reserved_memory *rmrr;
- struct acpi_dmar_atsr *atsr;
- struct acpi_dmar_rhsa *rhsa;
-
- switch (header->type) {
- case ACPI_DMAR_TYPE_HARDWARE_UNIT:
- drhd = container_of(header, struct acpi_dmar_hardware_unit,
- header);
- printk (KERN_INFO PREFIX
- "DRHD base: %#016Lx flags: %#x\n",
- (unsigned long long)drhd->address, drhd->flags);
- break;
- case ACPI_DMAR_TYPE_RESERVED_MEMORY:
- rmrr = container_of(header, struct acpi_dmar_reserved_memory,
- header);
- printk (KERN_INFO PREFIX
- "RMRR base: %#016Lx end: %#016Lx\n",
- (unsigned long long)rmrr->base_address,
- (unsigned long long)rmrr->end_address);
- break;
- case ACPI_DMAR_TYPE_ATSR:
- atsr = container_of(header, struct acpi_dmar_atsr, header);
- printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
- break;
- case ACPI_DMAR_HARDWARE_AFFINITY:
- rhsa = container_of(header, struct acpi_dmar_rhsa, header);
- printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
- (unsigned long long)rhsa->base_address,
- rhsa->proximity_domain);
- break;
- }
-}
-
-/**
- * dmar_table_detect - checks to see if the platform supports DMAR devices
- */
-static int __init dmar_table_detect(void)
-{
- acpi_status status = AE_OK;
-
- /* if we could find DMAR table, then there are DMAR devices */
- status = acpi_get_table_with_size(ACPI_SIG_DMAR, 0,
- (struct acpi_table_header **)&dmar_tbl,
- &dmar_tbl_size);
-
- if (ACPI_SUCCESS(status) && !dmar_tbl) {
- printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
- status = AE_NOT_FOUND;
- }
-
- return (ACPI_SUCCESS(status) ? 1 : 0);
-}
-
-/**
- * parse_dmar_table - parses the DMA reporting table
- */
-static int __init
-parse_dmar_table(void)
-{
- struct acpi_table_dmar *dmar;
- struct acpi_dmar_header *entry_header;
- int ret = 0;
-
- /*
- * Do it again, earlier dmar_tbl mapping could be mapped with
- * fixed map.
- */
- dmar_table_detect();
-
- /*
- * ACPI tables may not be DMA protected by tboot, so use DMAR copy
- * SINIT saved in SinitMleData in TXT heap (which is DMA protected)
- */
- dmar_tbl = tboot_get_dmar_table(dmar_tbl);
-
- dmar = (struct acpi_table_dmar *)dmar_tbl;
- if (!dmar)
- return -ENODEV;
-
- if (dmar->width < PAGE_SHIFT - 1) {
- printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
- return -EINVAL;
- }
-
- printk (KERN_INFO PREFIX "Host address width %d\n",
- dmar->width + 1);
-
- entry_header = (struct acpi_dmar_header *)(dmar + 1);
- while (((unsigned long)entry_header) <
- (((unsigned long)dmar) + dmar_tbl->length)) {
- /* Avoid looping forever on bad ACPI tables */
- if (entry_header->length == 0) {
- printk(KERN_WARNING PREFIX
- "Invalid 0-length structure\n");
- ret = -EINVAL;
- break;
- }
-
- dmar_table_print_dmar_entry(entry_header);
-
- switch (entry_header->type) {
- case ACPI_DMAR_TYPE_HARDWARE_UNIT:
- ret = dmar_parse_one_drhd(entry_header);
- break;
- case ACPI_DMAR_TYPE_RESERVED_MEMORY:
-#ifdef CONFIG_DMAR
- ret = dmar_parse_one_rmrr(entry_header);
-#endif
- break;
- case ACPI_DMAR_TYPE_ATSR:
-#ifdef CONFIG_DMAR
- ret = dmar_parse_one_atsr(entry_header);
-#endif
- break;
- case ACPI_DMAR_HARDWARE_AFFINITY:
-#ifdef CONFIG_ACPI_NUMA
- ret = dmar_parse_one_rhsa(entry_header);
-#endif
- break;
- default:
- printk(KERN_WARNING PREFIX
- "Unknown DMAR structure type %d\n",
- entry_header->type);
- ret = 0; /* for forward compatibility */
- break;
- }
- if (ret)
- break;
-
- entry_header = ((void *)entry_header + entry_header->length);
- }
- return ret;
-}
-
-static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
- struct pci_dev *dev)
-{
- int index;
-
- while (dev) {
- for (index = 0; index < cnt; index++)
- if (dev == devices[index])
- return 1;
-
- /* Check our parent */
- dev = dev->bus->self;
- }
-
- return 0;
-}
-
-struct dmar_drhd_unit *
-dmar_find_matched_drhd_unit(struct pci_dev *dev)
-{
- struct dmar_drhd_unit *dmaru = NULL;
- struct acpi_dmar_hardware_unit *drhd;
-
- dev = pci_physfn(dev);
-
- list_for_each_entry(dmaru, &dmar_drhd_units, list) {
- drhd = container_of(dmaru->hdr,
- struct acpi_dmar_hardware_unit,
- header);
-
- if (dmaru->include_all &&
- drhd->segment == pci_domain_nr(dev->bus))
- return dmaru;
-
- if (dmar_pci_device_match(dmaru->devices,
- dmaru->devices_cnt, dev))
- return dmaru;
- }
-
- return NULL;
-}
-
-int __init dmar_dev_scope_init(void)
-{
- struct dmar_drhd_unit *drhd, *drhd_n;
- int ret = -ENODEV;
-
- list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
- ret = dmar_parse_dev(drhd);
- if (ret)
- return ret;
- }
-
-#ifdef CONFIG_DMAR
- {
- struct dmar_rmrr_unit *rmrr, *rmrr_n;
- struct dmar_atsr_unit *atsr, *atsr_n;
-
- list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
- ret = rmrr_parse_dev(rmrr);
- if (ret)
- return ret;
- }
-
- list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
- ret = atsr_parse_dev(atsr);
- if (ret)
- return ret;
- }
- }
-#endif
-
- return ret;
-}
-
-
-int __init dmar_table_init(void)
-{
- static int dmar_table_initialized;
- int ret;
-
- if (dmar_table_initialized)
- return 0;
-
- dmar_table_initialized = 1;
-
- ret = parse_dmar_table();
- if (ret) {
- if (ret != -ENODEV)
- printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
- return ret;
- }
-
- if (list_empty(&dmar_drhd_units)) {
- printk(KERN_INFO PREFIX "No DMAR devices found\n");
- return -ENODEV;
- }
-
-#ifdef CONFIG_DMAR
- if (list_empty(&dmar_rmrr_units))
- printk(KERN_INFO PREFIX "No RMRR found\n");
-
- if (list_empty(&dmar_atsr_units))
- printk(KERN_INFO PREFIX "No ATSR found\n");
-#endif
-
- return 0;
-}
-
-static void warn_invalid_dmar(u64 addr, const char *message)
-{
- WARN_TAINT_ONCE(
- 1, TAINT_FIRMWARE_WORKAROUND,
- "Your BIOS is broken; DMAR reported at address %llx%s!\n"
- "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
- addr, message,
- dmi_get_system_info(DMI_BIOS_VENDOR),
- dmi_get_system_info(DMI_BIOS_VERSION),
- dmi_get_system_info(DMI_PRODUCT_VERSION));
-}
-
-int __init check_zero_address(void)
-{
- struct acpi_table_dmar *dmar;
- struct acpi_dmar_header *entry_header;
- struct acpi_dmar_hardware_unit *drhd;
-
- dmar = (struct acpi_table_dmar *)dmar_tbl;
- entry_header = (struct acpi_dmar_header *)(dmar + 1);
-
- while (((unsigned long)entry_header) <
- (((unsigned long)dmar) + dmar_tbl->length)) {
- /* Avoid looping forever on bad ACPI tables */
- if (entry_header->length == 0) {
- printk(KERN_WARNING PREFIX
- "Invalid 0-length structure\n");
- return 0;
- }
-
- if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
- void __iomem *addr;
- u64 cap, ecap;
-
- drhd = (void *)entry_header;
- if (!drhd->address) {
- warn_invalid_dmar(0, "");
- goto failed;
- }
-
- addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
- if (!addr ) {
- printk("IOMMU: can't validate: %llx\n", drhd->address);
- goto failed;
- }
- cap = dmar_readq(addr + DMAR_CAP_REG);
- ecap = dmar_readq(addr + DMAR_ECAP_REG);
- early_iounmap(addr, VTD_PAGE_SIZE);
- if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
- warn_invalid_dmar(drhd->address,
- " returns all ones");
- goto failed;
- }
- }
-
- entry_header = ((void *)entry_header + entry_header->length);
- }
- return 1;
-
-failed:
-#ifdef CONFIG_DMAR
- dmar_disabled = 1;
-#endif
- return 0;
-}
-
-int __init detect_intel_iommu(void)
-{
- int ret;
-
- ret = dmar_table_detect();
- if (ret)
- ret = check_zero_address();
- {
-#ifdef CONFIG_INTR_REMAP
- struct acpi_table_dmar *dmar;
-
- dmar = (struct acpi_table_dmar *) dmar_tbl;
- if (ret && cpu_has_x2apic && dmar->flags & 0x1)
- printk(KERN_INFO
- "Queued invalidation will be enabled to support "
- "x2apic and Intr-remapping.\n");
-#endif
-#ifdef CONFIG_DMAR
- if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
- iommu_detected = 1;
- /* Make sure ACS will be enabled */
- pci_request_acs();
- }
-#endif
-#ifdef CONFIG_X86
- if (ret)
- x86_init.iommu.iommu_init = intel_iommu_init;
-#endif
- }
- early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
- dmar_tbl = NULL;
-
- return ret ? 1 : -ENODEV;
-}
-
-
-int alloc_iommu(struct dmar_drhd_unit *drhd)
-{
- struct intel_iommu *iommu;
- int map_size;
- u32 ver;
- static int iommu_allocated = 0;
- int agaw = 0;
- int msagaw = 0;
-
- if (!drhd->reg_base_addr) {
- warn_invalid_dmar(0, "");
- return -EINVAL;
- }
-
- iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
- if (!iommu)
- return -ENOMEM;
-
- iommu->seq_id = iommu_allocated++;
- sprintf (iommu->name, "dmar%d", iommu->seq_id);
-
- iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
- if (!iommu->reg) {
- printk(KERN_ERR "IOMMU: can't map the region\n");
- goto error;
- }
- iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
- iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
-
- if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
- warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
- goto err_unmap;
- }
-
-#ifdef CONFIG_DMAR
- agaw = iommu_calculate_agaw(iommu);
- if (agaw < 0) {
- printk(KERN_ERR
- "Cannot get a valid agaw for iommu (seq_id = %d)\n",
- iommu->seq_id);
- goto err_unmap;
- }
- msagaw = iommu_calculate_max_sagaw(iommu);
- if (msagaw < 0) {
- printk(KERN_ERR
- "Cannot get a valid max agaw for iommu (seq_id = %d)\n",
- iommu->seq_id);
- goto err_unmap;
- }
-#endif
- iommu->agaw = agaw;
- iommu->msagaw = msagaw;
-
- iommu->node = -1;
-
- /* the registers might be more than one page */
- map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
- cap_max_fault_reg_offset(iommu->cap));
- map_size = VTD_PAGE_ALIGN(map_size);
- if (map_size > VTD_PAGE_SIZE) {
- iounmap(iommu->reg);
- iommu->reg = ioremap(drhd->reg_base_addr, map_size);
- if (!iommu->reg) {
- printk(KERN_ERR "IOMMU: can't map the region\n");
- goto error;
- }
- }
-
- ver = readl(iommu->reg + DMAR_VER_REG);
- pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
- iommu->seq_id,
- (unsigned long long)drhd->reg_base_addr,
- DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
- (unsigned long long)iommu->cap,
- (unsigned long long)iommu->ecap);
-
- spin_lock_init(&iommu->register_lock);
-
- drhd->iommu = iommu;
- return 0;
-
- err_unmap:
- iounmap(iommu->reg);
- error:
- kfree(iommu);
- return -1;
-}
-
-void free_iommu(struct intel_iommu *iommu)
-{
- if (!iommu)
- return;
-
-#ifdef CONFIG_DMAR
- free_dmar_iommu(iommu);
-#endif
-
- if (iommu->reg)
- iounmap(iommu->reg);
- kfree(iommu);
-}
-
-/*
- * Reclaim all the submitted descriptors which have completed its work.
- */
-static inline void reclaim_free_desc(struct q_inval *qi)
-{
- while (qi->desc_status[qi->free_tail] == QI_DONE ||
- qi->desc_status[qi->free_tail] == QI_ABORT) {
- qi->desc_status[qi->free_tail] = QI_FREE;
- qi->free_tail = (qi->free_tail + 1) % QI_LENGTH;
- qi->free_cnt++;
- }
-}
-
-static int qi_check_fault(struct intel_iommu *iommu, int index)
-{
- u32 fault;
- int head, tail;
- struct q_inval *qi = iommu->qi;
- int wait_index = (index + 1) % QI_LENGTH;
-
- if (qi->desc_status[wait_index] == QI_ABORT)
- return -EAGAIN;
-
- fault = readl(iommu->reg + DMAR_FSTS_REG);
-
- /*
- * If IQE happens, the head points to the descriptor associated
- * with the error. No new descriptors are fetched until the IQE
- * is cleared.
- */
- if (fault & DMA_FSTS_IQE) {
- head = readl(iommu->reg + DMAR_IQH_REG);
- if ((head >> DMAR_IQ_SHIFT) == index) {
- printk(KERN_ERR "VT-d detected invalid descriptor: "
- "low=%llx, high=%llx\n",
- (unsigned long long)qi->desc[index].low,
- (unsigned long long)qi->desc[index].high);
- memcpy(&qi->desc[index], &qi->desc[wait_index],
- sizeof(struct qi_desc));
- __iommu_flush_cache(iommu, &qi->desc[index],
- sizeof(struct qi_desc));
- writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG);
- return -EINVAL;
- }
- }
-
- /*
- * If ITE happens, all pending wait_desc commands are aborted.
- * No new descriptors are fetched until the ITE is cleared.
- */
- if (fault & DMA_FSTS_ITE) {
- head = readl(iommu->reg + DMAR_IQH_REG);
- head = ((head >> DMAR_IQ_SHIFT) - 1 + QI_LENGTH) % QI_LENGTH;
- head |= 1;
- tail = readl(iommu->reg + DMAR_IQT_REG);
- tail = ((tail >> DMAR_IQ_SHIFT) - 1 + QI_LENGTH) % QI_LENGTH;
-
- writel(DMA_FSTS_ITE, iommu->reg + DMAR_FSTS_REG);
-
- do {
- if (qi->desc_status[head] == QI_IN_USE)
- qi->desc_status[head] = QI_ABORT;
- head = (head - 2 + QI_LENGTH) % QI_LENGTH;
- } while (head != tail);
-
- if (qi->desc_status[wait_index] == QI_ABORT)
- return -EAGAIN;
- }
-
- if (fault & DMA_FSTS_ICE)
- writel(DMA_FSTS_ICE, iommu->reg + DMAR_FSTS_REG);
-
- return 0;
-}
-
-/*
- * Submit the queued invalidation descriptor to the remapping
- * hardware unit and wait for its completion.
- */
-int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
-{
- int rc;
- struct q_inval *qi = iommu->qi;
- struct qi_desc *hw, wait_desc;
- int wait_index, index;
- unsigned long flags;
-
- if (!qi)
- return 0;
-
- hw = qi->desc;
-
-restart:
- rc = 0;
-
- spin_lock_irqsave(&qi->q_lock, flags);
- while (qi->free_cnt < 3) {
- spin_unlock_irqrestore(&qi->q_lock, flags);
- cpu_relax();
- spin_lock_irqsave(&qi->q_lock, flags);
- }
-
- index = qi->free_head;
- wait_index = (index + 1) % QI_LENGTH;
-
- qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE;
-
- hw[index] = *desc;
-
- wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) |
- QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
- wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
-
- hw[wait_index] = wait_desc;
-
- __iommu_flush_cache(iommu, &hw[index], sizeof(struct qi_desc));
- __iommu_flush_cache(iommu, &hw[wait_index], sizeof(struct qi_desc));
-
- qi->free_head = (qi->free_head + 2) % QI_LENGTH;
- qi->free_cnt -= 2;
-
- /*
- * update the HW tail register indicating the presence of
- * new descriptors.
- */
- writel(qi->free_head << DMAR_IQ_SHIFT, iommu->reg + DMAR_IQT_REG);
-
- while (qi->desc_status[wait_index] != QI_DONE) {
- /*
- * We will leave the interrupts disabled, to prevent interrupt
- * context to queue another cmd while a cmd is already submitted
- * and waiting for completion on this cpu. This is to avoid
- * a deadlock where the interrupt context can wait indefinitely
- * for free slots in the queue.
- */
- rc = qi_check_fault(iommu, index);
- if (rc)
- break;
-
- spin_unlock(&qi->q_lock);
- cpu_relax();
- spin_lock(&qi->q_lock);
- }
-
- qi->desc_status[index] = QI_DONE;
-
- reclaim_free_desc(qi);
- spin_unlock_irqrestore(&qi->q_lock, flags);
-
- if (rc == -EAGAIN)
- goto restart;
-
- return rc;
-}
-
-/*
- * Flush the global interrupt entry cache.
- */
-void qi_global_iec(struct intel_iommu *iommu)
-{
- struct qi_desc desc;
-
- desc.low = QI_IEC_TYPE;
- desc.high = 0;
-
- /* should never fail */
- qi_submit_sync(&desc, iommu);
-}
-
-void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
- u64 type)
-{
- struct qi_desc desc;
-
- desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did)
- | QI_CC_GRAN(type) | QI_CC_TYPE;
- desc.high = 0;
-
- qi_submit_sync(&desc, iommu);
-}
-
-void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
- unsigned int size_order, u64 type)
-{
- u8 dw = 0, dr = 0;
-
- struct qi_desc desc;
- int ih = 0;
-
- if (cap_write_drain(iommu->cap))
- dw = 1;
-
- if (cap_read_drain(iommu->cap))
- dr = 1;
-
- desc.low = QI_IOTLB_DID(did) | QI_IOTLB_DR(dr) | QI_IOTLB_DW(dw)
- | QI_IOTLB_GRAN(type) | QI_IOTLB_TYPE;
- desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
- | QI_IOTLB_AM(size_order);
-
- qi_submit_sync(&desc, iommu);
-}
-
-void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
- u64 addr, unsigned mask)
-{
- struct qi_desc desc;
-
- if (mask) {
- BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
- addr |= (1 << (VTD_PAGE_SHIFT + mask - 1)) - 1;
- desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
- } else
- desc.high = QI_DEV_IOTLB_ADDR(addr);
-
- if (qdep >= QI_DEV_IOTLB_MAX_INVS)
- qdep = 0;
-
- desc.low = QI_DEV_IOTLB_SID(sid) | QI_DEV_IOTLB_QDEP(qdep) |
- QI_DIOTLB_TYPE;
-
- qi_submit_sync(&desc, iommu);
-}
-
-/*
- * Disable Queued Invalidation interface.
- */
-void dmar_disable_qi(struct intel_iommu *iommu)
-{
- unsigned long flags;
- u32 sts;
- cycles_t start_time = get_cycles();
-
- if (!ecap_qis(iommu->ecap))
- return;
-
- spin_lock_irqsave(&iommu->register_lock, flags);
-
- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
- if (!(sts & DMA_GSTS_QIES))
- goto end;
-
- /*
- * Give a chance to HW to complete the pending invalidation requests.
- */
- while ((readl(iommu->reg + DMAR_IQT_REG) !=
- readl(iommu->reg + DMAR_IQH_REG)) &&
- (DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time)))
- cpu_relax();
-
- iommu->gcmd &= ~DMA_GCMD_QIE;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
- !(sts & DMA_GSTS_QIES), sts);
-end:
- spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-/*
- * Enable queued invalidation.
- */
-static void __dmar_enable_qi(struct intel_iommu *iommu)
-{
- u32 sts;
- unsigned long flags;
- struct q_inval *qi = iommu->qi;
-
- qi->free_head = qi->free_tail = 0;
- qi->free_cnt = QI_LENGTH;
-
- spin_lock_irqsave(&iommu->register_lock, flags);
-
- /* write zero to the tail reg */
- writel(0, iommu->reg + DMAR_IQT_REG);
-
- dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
-
- iommu->gcmd |= DMA_GCMD_QIE;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
-
- spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-/*
- * Enable Queued Invalidation interface. This is a must to support
- * interrupt-remapping. Also used by DMA-remapping, which replaces
- * register based IOTLB invalidation.
- */
-int dmar_enable_qi(struct intel_iommu *iommu)
-{
- struct q_inval *qi;
- struct page *desc_page;
-
- if (!ecap_qis(iommu->ecap))
- return -ENOENT;
-
- /*
- * queued invalidation is already setup and enabled.
- */
- if (iommu->qi)
- return 0;
-
- iommu->qi = kmalloc(sizeof(*qi), GFP_ATOMIC);
- if (!iommu->qi)
- return -ENOMEM;
-
- qi = iommu->qi;
-
-
- desc_page = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO, 0);
- if (!desc_page) {
- kfree(qi);
- iommu->qi = 0;
- return -ENOMEM;
- }
-
- qi->desc = page_address(desc_page);
-
- qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
- if (!qi->desc_status) {
- free_page((unsigned long) qi->desc);
- kfree(qi);
- iommu->qi = 0;
- return -ENOMEM;
- }
-
- qi->free_head = qi->free_tail = 0;
- qi->free_cnt = QI_LENGTH;
-
- spin_lock_init(&qi->q_lock);
-
- __dmar_enable_qi(iommu);
-
- return 0;
-}
-
-/* iommu interrupt handling. Most stuff are MSI-like. */
-
-enum faulttype {
- DMA_REMAP,
- INTR_REMAP,
- UNKNOWN,
-};
-
-static const char *dma_remap_fault_reasons[] =
-{
- "Software",
- "Present bit in root entry is clear",
- "Present bit in context entry is clear",
- "Invalid context entry",
- "Access beyond MGAW",
- "PTE Write access is not set",
- "PTE Read access is not set",
- "Next page table ptr is invalid",
- "Root table address invalid",
- "Context table ptr is invalid",
- "non-zero reserved fields in RTP",
- "non-zero reserved fields in CTP",
- "non-zero reserved fields in PTE",
-};
-
-static const char *intr_remap_fault_reasons[] =
-{
- "Detected reserved fields in the decoded interrupt-remapped request",
- "Interrupt index exceeded the interrupt-remapping table size",
- "Present field in the IRTE entry is clear",
- "Error accessing interrupt-remapping table pointed by IRTA_REG",
- "Detected reserved fields in the IRTE entry",
- "Blocked a compatibility format interrupt request",
- "Blocked an interrupt request due to source-id verification failure",
-};
-
-#define MAX_FAULT_REASON_IDX (ARRAY_SIZE(fault_reason_strings) - 1)
-
-const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
-{
- if (fault_reason >= 0x20 && (fault_reason <= 0x20 +
- ARRAY_SIZE(intr_remap_fault_reasons))) {
- *fault_type = INTR_REMAP;
- return intr_remap_fault_reasons[fault_reason - 0x20];
- } else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
- *fault_type = DMA_REMAP;
- return dma_remap_fault_reasons[fault_reason];
- } else {
- *fault_type = UNKNOWN;
- return "Unknown";
- }
-}
-
-void dmar_msi_unmask(struct irq_data *data)
-{
- struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
- unsigned long flag;
-
- /* unmask it */
- spin_lock_irqsave(&iommu->register_lock, flag);
- writel(0, iommu->reg + DMAR_FECTL_REG);
- /* Read a reg to force flush the post write */
- readl(iommu->reg + DMAR_FECTL_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_mask(struct irq_data *data)
-{
- unsigned long flag;
- struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
-
- /* mask it */
- spin_lock_irqsave(&iommu->register_lock, flag);
- writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
- /* Read a reg to force flush the post write */
- readl(iommu->reg + DMAR_FECTL_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_write(int irq, struct msi_msg *msg)
-{
- struct intel_iommu *iommu = irq_get_handler_data(irq);
- unsigned long flag;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
- writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
- writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_read(int irq, struct msi_msg *msg)
-{
- struct intel_iommu *iommu = irq_get_handler_data(irq);
- unsigned long flag;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
- msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
- msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
- u8 fault_reason, u16 source_id, unsigned long long addr)
-{
- const char *reason;
- int fault_type;
-
- reason = dmar_get_fault_reason(fault_reason, &fault_type);
-
- if (fault_type == INTR_REMAP)
- printk(KERN_ERR "INTR-REMAP: Request device [[%02x:%02x.%d] "
- "fault index %llx\n"
- "INTR-REMAP:[fault reason %02d] %s\n",
- (source_id >> 8), PCI_SLOT(source_id & 0xFF),
- PCI_FUNC(source_id & 0xFF), addr >> 48,
- fault_reason, reason);
- else
- printk(KERN_ERR
- "DMAR:[%s] Request device [%02x:%02x.%d] "
- "fault addr %llx \n"
- "DMAR:[fault reason %02d] %s\n",
- (type ? "DMA Read" : "DMA Write"),
- (source_id >> 8), PCI_SLOT(source_id & 0xFF),
- PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
- return 0;
-}
-
-#define PRIMARY_FAULT_REG_LEN (16)
-irqreturn_t dmar_fault(int irq, void *dev_id)
-{
- struct intel_iommu *iommu = dev_id;
- int reg, fault_index;
- u32 fault_status;
- unsigned long flag;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- fault_status = readl(iommu->reg + DMAR_FSTS_REG);
- if (fault_status)
- printk(KERN_ERR "DRHD: handling fault status reg %x\n",
- fault_status);
-
- /* TBD: ignore advanced fault log currently */
- if (!(fault_status & DMA_FSTS_PPF))
- goto clear_rest;
-
- fault_index = dma_fsts_fault_record_index(fault_status);
- reg = cap_fault_reg_offset(iommu->cap);
- while (1) {
- u8 fault_reason;
- u16 source_id;
- u64 guest_addr;
- int type;
- u32 data;
-
- /* highest 32 bits */
- data = readl(iommu->reg + reg +
- fault_index * PRIMARY_FAULT_REG_LEN + 12);
- if (!(data & DMA_FRCD_F))
- break;
-
- fault_reason = dma_frcd_fault_reason(data);
- type = dma_frcd_type(data);
-
- data = readl(iommu->reg + reg +
- fault_index * PRIMARY_FAULT_REG_LEN + 8);
- source_id = dma_frcd_source_id(data);
-
- guest_addr = dmar_readq(iommu->reg + reg +
- fault_index * PRIMARY_FAULT_REG_LEN);
- guest_addr = dma_frcd_page_addr(guest_addr);
- /* clear the fault */
- writel(DMA_FRCD_F, iommu->reg + reg +
- fault_index * PRIMARY_FAULT_REG_LEN + 12);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-
- dmar_fault_do_one(iommu, type, fault_reason,
- source_id, guest_addr);
-
- fault_index++;
- if (fault_index >= cap_num_fault_regs(iommu->cap))
- fault_index = 0;
- spin_lock_irqsave(&iommu->register_lock, flag);
- }
-clear_rest:
- /* clear all the other faults */
- fault_status = readl(iommu->reg + DMAR_FSTS_REG);
- writel(fault_status, iommu->reg + DMAR_FSTS_REG);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
- return IRQ_HANDLED;
-}
-
-int dmar_set_interrupt(struct intel_iommu *iommu)
-{
- int irq, ret;
-
- /*
- * Check if the fault interrupt is already initialized.
- */
- if (iommu->irq)
- return 0;
-
- irq = create_irq();
- if (!irq) {
- printk(KERN_ERR "IOMMU: no free vectors\n");
- return -EINVAL;
- }
-
- irq_set_handler_data(irq, iommu);
- iommu->irq = irq;
-
- ret = arch_setup_dmar_msi(irq);
- if (ret) {
- irq_set_handler_data(irq, NULL);
- iommu->irq = 0;
- destroy_irq(irq);
- return ret;
- }
-
- ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
- if (ret)
- printk(KERN_ERR "IOMMU: can't request irq\n");
- return ret;
-}
-
-int __init enable_drhd_fault_handling(void)
-{
- struct dmar_drhd_unit *drhd;
-
- /*
- * Enable fault control interrupt.
- */
- for_each_drhd_unit(drhd) {
- int ret;
- struct intel_iommu *iommu = drhd->iommu;
- ret = dmar_set_interrupt(iommu);
-
- if (ret) {
- printk(KERN_ERR "DRHD %Lx: failed to enable fault, "
- " interrupt, ret %d\n",
- (unsigned long long)drhd->reg_base_addr, ret);
- return -1;
- }
-
- /*
- * Clear any previous faults.
- */
- dmar_fault(iommu->irq, iommu);
- }
-
- return 0;
-}
-
-/*
- * Re-enable Queued Invalidation interface.
- */
-int dmar_reenable_qi(struct intel_iommu *iommu)
-{
- if (!ecap_qis(iommu->ecap))
- return -ENOENT;
-
- if (!iommu->qi)
- return -ENOENT;
-
- /*
- * First disable queued invalidation.
- */
- dmar_disable_qi(iommu);
- /*
- * Then enable queued invalidation again. Since there is no pending
- * invalidation requests now, it's safe to re-enable queued
- * invalidation.
- */
- __dmar_enable_qi(iommu);
-
- return 0;
-}
-
-/*
- * Check interrupt remapping support in DMAR table description.
- */
-int __init dmar_ir_support(void)
-{
- struct acpi_table_dmar *dmar;
- dmar = (struct acpi_table_dmar *)dmar_tbl;
- if (!dmar)
- return 0;
- return dmar->flags & 0x1;
-}
-IOMMU_INIT_POST(detect_intel_iommu);
diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c
index 4d4a6447..d3509cd 100644
--- a/drivers/pci/hotplug-pci.c
+++ b/drivers/pci/hotplug-pci.c
@@ -1,6 +1,7 @@
/* Core PCI functionality used only by PCI hotplug */
#include <linux/pci.h>
+#include <linux/export.h>
#include "pci.h"
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index 2b5352a..3b70f5c 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -27,7 +27,7 @@ int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM;
- if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+ if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X",
pdev->vendor, pdev->device,
pdev->subsystem_vendor, pdev->subsystem_device,
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 8f3faf3..095f29e 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -408,7 +408,7 @@ got_one:
}
EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
-static int is_ejectable(acpi_handle handle)
+static int pcihp_is_ejectable(acpi_handle handle)
{
acpi_status status;
acpi_handle tmp;
@@ -442,7 +442,7 @@ int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle)
return 0;
if (bridge_handle != parent_handle)
return 0;
- return is_ejectable(handle);
+ return pcihp_is_ejectable(handle);
}
EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable);
@@ -450,7 +450,7 @@ static acpi_status
check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int *found = (int *)context;
- if (is_ejectable(handle)) {
+ if (pcihp_is_ejectable(handle)) {
*found = 1;
return AE_CTRL_TERMINATE;
}
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 7bd3694..74d38ca 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -48,6 +48,7 @@
#include <linux/pci-acpi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
#include "../pci.h"
#include "acpiphp.h"
@@ -110,7 +111,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
}
-static struct acpi_dock_ops acpiphp_dock_ops = {
+static const struct acpi_dock_ops acpiphp_dock_ops = {
.handler = handle_hotplug_event_func,
};
@@ -140,6 +141,18 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
device = (adr >> 16) & 0xffff;
function = adr & 0xffff;
+ pdev = pbus->self;
+ if (pdev && pci_is_pcie(pdev)) {
+ tmp = acpi_find_root_bridge_handle(pdev);
+ if (tmp) {
+ struct acpi_pci_root *root = acpi_pci_find_root(tmp);
+
+ if (root && (root->osc_control_set &
+ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
+ return AE_OK;
+ }
+ }
+
newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
if (!newfunc)
return AE_NO_MEMORY;
@@ -217,7 +230,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
if (pdev) {
- pdev->current_state = PCI_D0;
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
pci_dev_put(pdev);
}
@@ -1154,15 +1166,35 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK ;
}
-/**
- * handle_hotplug_event_bridge - handle ACPI event on bridges
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @context: pointer to acpiphp_bridge structure
- *
- * Handles ACPI event notification on {host,p2p} bridges.
- */
-static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
+struct acpiphp_hp_work {
+ struct work_struct work;
+ acpi_handle handle;
+ u32 type;
+ void *context;
+};
+
+static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
+ void *context,
+ void (*func)(struct work_struct *work))
+{
+ struct acpiphp_hp_work *hp_work;
+ int ret;
+
+ hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
+ if (!hp_work)
+ return;
+
+ hp_work->handle = handle;
+ hp_work->type = type;
+ hp_work->context = context;
+
+ INIT_WORK(&hp_work->work, func);
+ ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
+ if (!ret)
+ kfree(hp_work);
+}
+
+static void _handle_hotplug_event_bridge(struct work_struct *work)
{
struct acpiphp_bridge *bridge;
char objname[64];
@@ -1170,11 +1202,18 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
.pointer = objname };
struct acpi_device *device;
int num_sub_bridges = 0;
+ struct acpiphp_hp_work *hp_work;
+ acpi_handle handle;
+ u32 type;
+
+ hp_work = container_of(work, struct acpiphp_hp_work, work);
+ handle = hp_work->handle;
+ type = hp_work->type;
if (acpi_bus_get_device(handle, &device)) {
/* This bridge must have just been physically inserted */
handle_bridge_insertion(handle, type);
- return;
+ goto out;
}
bridge = acpiphp_handle_to_bridge(handle);
@@ -1185,7 +1224,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
if (!bridge && !num_sub_bridges) {
err("cannot get bridge info\n");
- return;
+ goto out;
}
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1246,22 +1285,49 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
+
+out:
+ kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
}
/**
- * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
+ * handle_hotplug_event_bridge - handle ACPI event on bridges
* @handle: Notify()'ed acpi_handle
* @type: Notify code
- * @context: pointer to acpiphp_func structure
+ * @context: pointer to acpiphp_bridge structure
*
- * Handles ACPI event notification on slots.
+ * Handles ACPI event notification on {host,p2p} bridges.
*/
-static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
+static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
+ void *context)
+{
+ /*
+ * Currently the code adds all hotplug events to the kacpid_wq
+ * queue when it should add hotplug events to the kacpi_hotplug_wq.
+ * The proper way to fix this is to reorganize the code so that
+ * drivers (dock, etc.) do not call acpi_os_execute(), etc.
+ * For now just re-add this work to the kacpi_hotplug_wq so we
+ * don't deadlock on hotplug actions.
+ */
+ alloc_acpiphp_hp_work(handle, type, context,
+ _handle_hotplug_event_bridge);
+}
+
+static void _handle_hotplug_event_func(struct work_struct *work)
{
struct acpiphp_func *func;
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
+ struct acpiphp_hp_work *hp_work;
+ acpi_handle handle;
+ u32 type;
+ void *context;
+
+ hp_work = container_of(work, struct acpiphp_hp_work, work);
+ handle = hp_work->handle;
+ type = hp_work->type;
+ context = hp_work->context;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1296,19 +1362,45 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
+
+ kfree(hp_work); /* allocated in handle_hotplug_event_func */
}
+/**
+ * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
+ * @handle: Notify()'ed acpi_handle
+ * @type: Notify code
+ * @context: pointer to acpiphp_func structure
+ *
+ * Handles ACPI event notification on slots.
+ */
+static void handle_hotplug_event_func(acpi_handle handle, u32 type,
+ void *context)
+{
+ /*
+ * Currently the code adds all hotplug events to the kacpid_wq
+ * queue when it should add hotplug events to the kacpi_hotplug_wq.
+ * The proper way to fix this is to reorganize the code so that
+ * drivers (dock, etc.) do not call acpi_os_execute(), etc.
+ * For now just re-add this work to the kacpi_hotplug_wq so we
+ * don't deadlock on hotplug actions.
+ */
+ alloc_acpiphp_hp_work(handle, type, context,
+ _handle_hotplug_event_func);
+}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int *count = (int *)context;
- if (acpi_is_root_bridge(handle)) {
- acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_bridge, NULL);
- (*count)++;
- }
+ if (!acpi_is_root_bridge(handle))
+ return AE_OK;
+
+ (*count)++;
+ acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ handle_hotplug_event_bridge, NULL);
+
return AE_OK ;
}
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index d703e73..3fadf2f 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -32,7 +32,7 @@
#include <linux/pci_hotplug.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include "cpci_hotplug.h"
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 4952c3b..f1ce99c 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -840,8 +840,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Need to read VID early b/c it's used to differentiate CPQ and INTC
* discovery
*/
- rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
- if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
+ vendor_id = pdev->vendor;
+ if ((vendor_id != PCI_VENDOR_ID_COMPAQ) &&
+ (vendor_id != PCI_VENDOR_ID_INTEL)) {
err(msg_HPC_non_compaq_or_intel);
rc = -ENODEV;
goto err_disable_device;
@@ -868,11 +869,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* TODO: This code can be made to support non-Compaq or Intel
* subsystem IDs
*/
- rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
- if (rc) {
- err("%s : pci_read_config_word failed\n", __func__);
- goto err_disable_device;
- }
+ subsystem_vid = pdev->subsystem_vendor;
dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
err(msg_HPC_non_compaq_or_intel);
@@ -887,11 +884,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_disable_device;
}
- rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
- if (rc) {
- err("%s : pci_read_config_word failed\n", __func__);
- goto err_free_ctrl;
- }
+ subsystem_deviceid = pdev->subsystem_device;
info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 838f571..4fff912 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -44,8 +44,6 @@ extern int pciehp_poll_mode;
extern int pciehp_poll_time;
extern int pciehp_debug;
extern int pciehp_force;
-extern struct workqueue_struct *pciehp_wq;
-extern struct workqueue_struct *pciehp_ordered_wq;
#define dbg(format, arg...) \
do { \
@@ -79,6 +77,7 @@ struct slot {
struct hotplug_slot *hotplug_slot;
struct delayed_work work; /* work for button event */
struct mutex lock;
+ struct workqueue_struct *wq;
};
struct event_info {
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 5f72262..376d70d 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "pciehp.h"
#define PCIEHP_DETECT_PCIE (0)
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 7ac8358..dc126a2 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -42,8 +42,6 @@ int pciehp_debug;
int pciehp_poll_mode;
int pciehp_poll_time;
int pciehp_force;
-struct workqueue_struct *pciehp_wq;
-struct workqueue_struct *pciehp_ordered_wq;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -239,6 +237,13 @@ static int pciehp_probe(struct pcie_device *dev)
else if (pciehp_acpi_slot_detection_check(dev->port))
goto err_out_none;
+ if (!dev->port->subordinate) {
+ /* Can happen if we run out of bus numbers during probe */
+ dev_err(&dev->device,
+ "Hotplug bridge without secondary bus, ignoring\n");
+ goto err_out_none;
+ }
+
ctrl = pcie_init(dev);
if (!ctrl) {
dev_err(&dev->device, "Controller initialization failed\n");
@@ -341,33 +346,19 @@ static int __init pcied_init(void)
{
int retval = 0;
- pciehp_wq = alloc_workqueue("pciehp", 0, 0);
- if (!pciehp_wq)
- return -ENOMEM;
-
- pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0);
- if (!pciehp_ordered_wq) {
- destroy_workqueue(pciehp_wq);
- return -ENOMEM;
- }
-
pciehp_firmware_init();
retval = pcie_port_service_register(&hpdriver_portdrv);
dbg("pcie_port_service_register = %d\n", retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- if (retval) {
- destroy_workqueue(pciehp_ordered_wq);
- destroy_workqueue(pciehp_wq);
+ if (retval)
dbg("Failure to register service\n");
- }
+
return retval;
}
static void __exit pcied_cleanup(void)
{
dbg("unload_pciehpd()\n");
- destroy_workqueue(pciehp_ordered_wq);
- destroy_workqueue(pciehp_wq);
pcie_port_service_unregister(&hpdriver_portdrv);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
}
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 085dbb5..38f0186 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
info->p_slot = p_slot;
INIT_WORK(&info->work, interrupt_event_handler);
- queue_work(pciehp_wq, &info->work);
+ queue_work(p_slot->wq, &info->work);
return 0;
}
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
kfree(info);
goto out;
}
- queue_work(pciehp_ordered_wq, &info->work);
+ queue_work(p_slot->wq, &info->work);
out:
mutex_unlock(&p_slot->lock);
}
@@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot)
if (ATTN_LED(ctrl))
pciehp_set_attention_status(p_slot, 0);
- queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
+ queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot)
else
p_slot->state = POWERON_STATE;
- queue_work(pciehp_ordered_wq, &info->work);
+ queue_work(p_slot->wq, &info->work);
}
static void interrupt_event_handler(struct work_struct *work)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 50a23da..fef1748 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -275,18 +275,19 @@ int pciehp_check_link_status(struct controller *ctrl)
* hot-plug capable downstream port. But old controller might
* not implement it. In this case, we wait for 1000 ms.
*/
- if (ctrl->link_active_reporting){
- /* Wait for Data Link Layer Link Active bit to be set */
+ if (ctrl->link_active_reporting)
pcie_wait_link_active(ctrl);
- /*
- * We must wait for 100 ms after the Data Link Layer
- * Link Active bit reads 1b before initiating a
- * configuration access to the hot added device.
- */
- msleep(100);
- } else
+ else
msleep(1000);
+ /*
+ * Need to wait for 1000 ms after Data Link Layer Link Active
+ * (DLLLA) bit reads 1b before sending configuration request.
+ * We need it before checking Link Training (LT) bit becuase
+ * LT is still set even after DLLLA bit is set on some platform.
+ */
+ msleep(1000);
+
retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
if (retval) {
ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
@@ -301,6 +302,16 @@ int pciehp_check_link_status(struct controller *ctrl)
return retval;
}
+ /*
+ * If the port supports Link speeds greater than 5.0 GT/s, we
+ * must wait for 100 ms after Link training completes before
+ * sending configuration request.
+ */
+ if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
+ msleep(100);
+
+ pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
+
return retval;
}
@@ -491,7 +502,6 @@ int pciehp_power_on_slot(struct slot * slot)
u16 slot_cmd;
u16 cmd_mask;
u16 slot_status;
- u16 lnk_status;
int retval = 0;
/* Clear sticky power-fault bit from previous power failures */
@@ -523,14 +533,6 @@ int pciehp_power_on_slot(struct slot * slot)
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
- retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
- if (retval) {
- ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n",
- __func__);
- return retval;
- }
- pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
-
return retval;
}
@@ -787,24 +789,32 @@ static void pcie_shutdown_notification(struct controller *ctrl)
static int pcie_init_slot(struct controller *ctrl)
{
struct slot *slot;
+ char name[32];
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
return -ENOMEM;
+ snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl));
+ slot->wq = alloc_workqueue(name, 0, 0);
+ if (!slot->wq)
+ goto abort;
+
slot->ctrl = ctrl;
mutex_init(&slot->lock);
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
ctrl->slot = slot;
return 0;
+abort:
+ kfree(slot);
+ return -ENOMEM;
}
static void pcie_cleanup_slot(struct controller *ctrl)
{
struct slot *slot = ctrl->slot;
cancel_delayed_work(&slot->work);
- flush_workqueue(pciehp_wq);
- flush_workqueue(pciehp_ordered_wq);
+ destroy_workqueue(slot->wq);
kfree(slot);
}
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c
index 749fdf0..8c05a18 100644
--- a/drivers/pci/hotplug/pcihp_slot.c
+++ b/drivers/pci/hotplug/pcihp_slot.c
@@ -24,6 +24,7 @@
*/
#include <linux/pci.h>
+#include <linux/export.h>
#include <linux/pci_hotplug.h>
static struct hpp_type0 pci_default_type0 = {
@@ -158,47 +159,6 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
*/
}
-/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
-static int pci_set_payload(struct pci_dev *dev)
-{
- int pos, ppos;
- u16 pctl, psz;
- u16 dctl, dsz, dcap, dmax;
- struct pci_dev *parent;
-
- parent = dev->bus->self;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
- if (!pos)
- return 0;
-
- /* Read Device MaxPayload capability and setting */
- pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
- pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
- dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
- dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);
-
- /* Read Parent MaxPayload setting */
- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
- if (!ppos)
- return 0;
- pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
- psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
-
- /* If parent payload > device max payload -> error
- * If parent payload > device payload -> set speed
- * If parent payload <= device payload -> do nothing
- */
- if (psz > dmax)
- return -1;
- else if (psz > dsz) {
- dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
- pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
- (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
- (psz << 5));
- }
- return 0;
-}
-
void pci_configure_slot(struct pci_dev *dev)
{
struct pci_dev *cdev;
@@ -210,9 +170,9 @@ void pci_configure_slot(struct pci_dev *dev)
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
return;
- ret = pci_set_payload(dev);
- if (ret)
- dev_warn(&dev->dev, "could not set device max payload\n");
+ if (dev->bus && dev->bus->self)
+ pcie_bus_configure_settings(dev->bus,
+ dev->bus->self->pcie_mpss);
memset(&hpp, 0, sizeof(hpp));
ret = pci_get_hp_params(dev, &hpp);
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 0830347..c56a941 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -18,6 +18,7 @@
#undef DEBUG
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
@@ -158,7 +159,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
/* Scan below the new bridge */
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
- of_scan_pci_bridge(dn, dev);
+ of_scan_pci_bridge(dev);
/* Map IO space for child bus, which may or may not succeed */
pcibios_map_io_space(dev->subordinate);
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index e0c90e6..2c2ac80 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -46,8 +46,6 @@
extern int shpchp_poll_mode;
extern int shpchp_poll_time;
extern int shpchp_debug;
-extern struct workqueue_struct *shpchp_wq;
-extern struct workqueue_struct *shpchp_ordered_wq;
#define dbg(format, arg...) \
do { \
@@ -91,6 +89,7 @@ struct slot {
struct list_head slot_list;
struct delayed_work work; /* work for button event */
struct mutex lock;
+ struct workqueue_struct *wq;
u8 hp_slot;
};
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index dd7e0c5..754a7cd 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -39,8 +39,6 @@
int shpchp_debug;
int shpchp_poll_mode;
int shpchp_poll_time;
-struct workqueue_struct *shpchp_wq;
-struct workqueue_struct *shpchp_ordered_wq;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -123,6 +121,14 @@ static int init_slots(struct controller *ctrl)
slot->device = ctrl->slot_device_offset + i;
slot->hpc_ops = ctrl->hpc_ops;
slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
+
+ snprintf(name, sizeof(name), "shpchp-%d", slot->number);
+ slot->wq = alloc_workqueue(name, 0, 0);
+ if (!slot->wq) {
+ retval = -ENOMEM;
+ goto error_info;
+ }
+
mutex_init(&slot->lock);
INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
@@ -142,7 +148,7 @@ static int init_slots(struct controller *ctrl)
if (retval) {
ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
retval);
- goto error_info;
+ goto error_slotwq;
}
get_power_status(hotplug_slot, &info->power_status);
@@ -154,6 +160,8 @@ static int init_slots(struct controller *ctrl)
}
return 0;
+error_slotwq:
+ destroy_workqueue(slot->wq);
error_info:
kfree(info);
error_hpslot:
@@ -174,8 +182,7 @@ void cleanup_slots(struct controller *ctrl)
slot = list_entry(tmp, struct slot, slot_list);
list_del(&slot->slot_list);
cancel_delayed_work(&slot->work);
- flush_workqueue(shpchp_wq);
- flush_workqueue(shpchp_ordered_wq);
+ destroy_workqueue(slot->wq);
pci_hp_deregister(slot->hotplug_slot);
}
}
@@ -358,25 +365,12 @@ static struct pci_driver shpc_driver = {
static int __init shpcd_init(void)
{
- int retval = 0;
-
- shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
- if (!shpchp_wq)
- return -ENOMEM;
-
- shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
- if (!shpchp_ordered_wq) {
- destroy_workqueue(shpchp_wq);
- return -ENOMEM;
- }
+ int retval;
retval = pci_register_driver(&shpc_driver);
dbg("%s: pci_register_driver = %d\n", __func__, retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- if (retval) {
- destroy_workqueue(shpchp_ordered_wq);
- destroy_workqueue(shpchp_wq);
- }
+
return retval;
}
@@ -384,8 +378,6 @@ static void __exit shpcd_cleanup(void)
{
dbg("unload_shpchpd()\n");
pci_unregister_driver(&shpc_driver);
- destroy_workqueue(shpchp_ordered_wq);
- destroy_workqueue(shpchp_wq);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
}
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index b00b09b..b888675 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
info->p_slot = p_slot;
INIT_WORK(&info->work, interrupt_event_handler);
- queue_work(shpchp_wq, &info->work);
+ queue_work(p_slot->wq, &info->work);
return 0;
}
@@ -285,8 +285,8 @@ static int board_added(struct slot *p_slot)
return WRONG_BUS_FREQUENCY;
}
- bsp = ctrl->pci_dev->bus->cur_bus_speed;
- msp = ctrl->pci_dev->bus->max_bus_speed;
+ bsp = ctrl->pci_dev->subordinate->cur_bus_speed;
+ msp = ctrl->pci_dev->subordinate->max_bus_speed;
/* Check if there are other slots or devices on the same bus */
if (!list_empty(&ctrl->pci_dev->subordinate->devices))
@@ -456,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
kfree(info);
goto out;
}
- queue_work(shpchp_ordered_wq, &info->work);
+ queue_work(p_slot->wq, &info->work);
out:
mutex_unlock(&p_slot->lock);
}
@@ -504,7 +504,7 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->hpc_ops->green_led_blink(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
+ queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index 071b7dc..efa30da 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -50,29 +50,26 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
pci_bus_for_each_resource(bus, res, index) {
if (res && (res->flags & IORESOURCE_MEM) &&
!(res->flags & IORESOURCE_PREFETCH)) {
- out += sprintf(out, "start = %8.8llx, "
- "length = %8.8llx\n",
- (unsigned long long)res->start,
- (unsigned long long)(res->end - res->start));
+ out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)resource_size(res));
}
}
out += sprintf(out, "Free resources: prefetchable memory\n");
pci_bus_for_each_resource(bus, res, index) {
if (res && (res->flags & IORESOURCE_MEM) &&
(res->flags & IORESOURCE_PREFETCH)) {
- out += sprintf(out, "start = %8.8llx, "
- "length = %8.8llx\n",
- (unsigned long long)res->start,
- (unsigned long long)(res->end - res->start));
+ out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)resource_size(res));
}
}
out += sprintf(out, "Free resources: IO\n");
pci_bus_for_each_resource(bus, res, index) {
if (res && (res->flags & IORESOURCE_IO)) {
- out += sprintf(out, "start = %8.8llx, "
- "length = %8.8llx\n",
- (unsigned long long)res->start,
- (unsigned long long)(res->end - res->start));
+ out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)resource_size(res));
}
}
out += sprintf(out, "Free resources: bus numbers\n");
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index db057b6..6e373ea 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -9,6 +9,7 @@
#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/htirq.h>
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
deleted file mode 100644
index 68baf17..0000000
--- a/drivers/pci/intel-iommu.c
+++ /dev/null
@@ -1,4059 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Ashok Raj <ashok.raj@intel.com>
- * Author: Shaohua Li <shaohua.li@intel.com>
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- * Author: Fenghua Yu <fenghua.yu@intel.com>
- */
-
-#include <linux/init.h>
-#include <linux/bitmap.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-#include <linux/dmar.h>
-#include <linux/dma-mapping.h>
-#include <linux/mempool.h>
-#include <linux/timer.h>
-#include <linux/iova.h>
-#include <linux/iommu.h>
-#include <linux/intel-iommu.h>
-#include <linux/syscore_ops.h>
-#include <linux/tboot.h>
-#include <linux/dmi.h>
-#include <linux/pci-ats.h>
-#include <asm/cacheflush.h>
-#include <asm/iommu.h>
-#include "pci.h"
-
-#define ROOT_SIZE VTD_PAGE_SIZE
-#define CONTEXT_SIZE VTD_PAGE_SIZE
-
-#define IS_BRIDGE_HOST_DEVICE(pdev) \
- ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
-#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
-#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
-#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
-
-#define IOAPIC_RANGE_START (0xfee00000)
-#define IOAPIC_RANGE_END (0xfeefffff)
-#define IOVA_START_ADDR (0x1000)
-
-#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
-
-#define MAX_AGAW_WIDTH 64
-
-#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
-#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
-
-/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
- to match. That way, we can use 'unsigned long' for PFNs with impunity. */
-#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
- __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
-#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
-
-#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
-#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))
-#define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64))
-
-/* page table handling */
-#define LEVEL_STRIDE (9)
-#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
-
-static inline int agaw_to_level(int agaw)
-{
- return agaw + 2;
-}
-
-static inline int agaw_to_width(int agaw)
-{
- return 30 + agaw * LEVEL_STRIDE;
-}
-
-static inline int width_to_agaw(int width)
-{
- return (width - 30) / LEVEL_STRIDE;
-}
-
-static inline unsigned int level_to_offset_bits(int level)
-{
- return (level - 1) * LEVEL_STRIDE;
-}
-
-static inline int pfn_level_offset(unsigned long pfn, int level)
-{
- return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
-}
-
-static inline unsigned long level_mask(int level)
-{
- return -1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long level_size(int level)
-{
- return 1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long align_to_level(unsigned long pfn, int level)
-{
- return (pfn + level_size(level) - 1) & level_mask(level);
-}
-
-static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
-{
- return 1 << ((lvl - 1) * LEVEL_STRIDE);
-}
-
-/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
- are never going to work. */
-static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
-{
- return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
-}
-
-static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
-{
- return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
-}
-static inline unsigned long page_to_dma_pfn(struct page *pg)
-{
- return mm_to_dma_pfn(page_to_pfn(pg));
-}
-static inline unsigned long virt_to_dma_pfn(void *p)
-{
- return page_to_dma_pfn(virt_to_page(p));
-}
-
-/* global iommu list, set NULL for ignored DMAR units */
-static struct intel_iommu **g_iommus;
-
-static void __init check_tylersburg_isoch(void);
-static int rwbf_quirk;
-
-/*
- * set to 1 to panic kernel if can't successfully enable VT-d
- * (used when kernel is launched w/ TXT)
- */
-static int force_on = 0;
-
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
- u64 val;
- u64 rsvd1;
-};
-#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
- return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
- root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
- root->val |= value & VTD_PAGE_MASK;
-}
-
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
- return (struct context_entry *)
- (root_present(root)?phys_to_virt(
- root->val & VTD_PAGE_MASK) :
- NULL);
-}
-
-/*
- * low 64 bits:
- * 0: present
- * 1: fault processing disable
- * 2-3: translation type
- * 12-63: address space root
- * high 64 bits:
- * 0-2: address width
- * 3-6: aval
- * 8-23: domain id
- */
-struct context_entry {
- u64 lo;
- u64 hi;
-};
-
-static inline bool context_present(struct context_entry *context)
-{
- return (context->lo & 1);
-}
-static inline void context_set_present(struct context_entry *context)
-{
- context->lo |= 1;
-}
-
-static inline void context_set_fault_enable(struct context_entry *context)
-{
- context->lo &= (((u64)-1) << 2) | 1;
-}
-
-static inline void context_set_translation_type(struct context_entry *context,
- unsigned long value)
-{
- context->lo &= (((u64)-1) << 4) | 3;
- context->lo |= (value & 3) << 2;
-}
-
-static inline void context_set_address_root(struct context_entry *context,
- unsigned long value)
-{
- context->lo |= value & VTD_PAGE_MASK;
-}
-
-static inline void context_set_address_width(struct context_entry *context,
- unsigned long value)
-{
- context->hi |= value & 7;
-}
-
-static inline void context_set_domain_id(struct context_entry *context,
- unsigned long value)
-{
- context->hi |= (value & ((1 << 16) - 1)) << 8;
-}
-
-static inline void context_clear_entry(struct context_entry *context)
-{
- context->lo = 0;
- context->hi = 0;
-}
-
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-10: available
- * 11: snoop behavior
- * 12-63: Host physcial address
- */
-struct dma_pte {
- u64 val;
-};
-
-static inline void dma_clear_pte(struct dma_pte *pte)
-{
- pte->val = 0;
-}
-
-static inline void dma_set_pte_readable(struct dma_pte *pte)
-{
- pte->val |= DMA_PTE_READ;
-}
-
-static inline void dma_set_pte_writable(struct dma_pte *pte)
-{
- pte->val |= DMA_PTE_WRITE;
-}
-
-static inline void dma_set_pte_snp(struct dma_pte *pte)
-{
- pte->val |= DMA_PTE_SNP;
-}
-
-static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
-{
- pte->val = (pte->val & ~3) | (prot & 3);
-}
-
-static inline u64 dma_pte_addr(struct dma_pte *pte)
-{
-#ifdef CONFIG_64BIT
- return pte->val & VTD_PAGE_MASK;
-#else
- /* Must have a full atomic 64-bit read */
- return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
-#endif
-}
-
-static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn)
-{
- pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT;
-}
-
-static inline bool dma_pte_present(struct dma_pte *pte)
-{
- return (pte->val & 3) != 0;
-}
-
-static inline bool dma_pte_superpage(struct dma_pte *pte)
-{
- return (pte->val & (1 << 7));
-}
-
-static inline int first_pte_in_page(struct dma_pte *pte)
-{
- return !((unsigned long)pte & ~VTD_PAGE_MASK);
-}
-
-/*
- * This domain is a statically identity mapping domain.
- * 1. This domain creats a static 1:1 mapping to all usable memory.
- * 2. It maps to each iommu if successful.
- * 3. Each iommu mapps to this domain if successful.
- */
-static struct dmar_domain *si_domain;
-static int hw_pass_through = 1;
-
-/* devices under the same p2p bridge are owned in one domain */
-#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
-
-/* domain represents a virtual machine, more than one devices
- * across iommus may be owned in one domain, e.g. kvm guest.
- */
-#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 1)
-
-/* si_domain contains mulitple devices */
-#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2)
-
-struct dmar_domain {
- int id; /* domain id */
- int nid; /* node id */
- unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/
-
- struct list_head devices; /* all devices' list */
- struct iova_domain iovad; /* iova's that belong to this domain */
-
- struct dma_pte *pgd; /* virtual address */
- int gaw; /* max guest address width */
-
- /* adjusted guest address width, 0 is level 2 30-bit */
- int agaw;
-
- int flags; /* flags to find out type of domain */
-
- int iommu_coherency;/* indicate coherency of iommu access */
- int iommu_snooping; /* indicate snooping control feature*/
- int iommu_count; /* reference count of iommu */
- int iommu_superpage;/* Level of superpages supported:
- 0 == 4KiB (no superpages), 1 == 2MiB,
- 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
- spinlock_t iommu_lock; /* protect iommu set in domain */
- u64 max_addr; /* maximum mapped address */
-};
-
-/* PCI domain-device relationship */
-struct device_domain_info {
- struct list_head link; /* link to domain siblings */
- struct list_head global; /* link to global list */
- int segment; /* PCI domain */
- u8 bus; /* PCI bus number */
- u8 devfn; /* PCI devfn number */
- struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */
- struct intel_iommu *iommu; /* IOMMU used by this device */
- struct dmar_domain *domain; /* pointer to domain */
-};
-
-static void flush_unmaps_timeout(unsigned long data);
-
-DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
-
-#define HIGH_WATER_MARK 250
-struct deferred_flush_tables {
- int next;
- struct iova *iova[HIGH_WATER_MARK];
- struct dmar_domain *domain[HIGH_WATER_MARK];
-};
-
-static struct deferred_flush_tables *deferred_flush;
-
-/* bitmap for indexing intel_iommus */
-static int g_num_of_iommus;
-
-static DEFINE_SPINLOCK(async_umap_flush_lock);
-static LIST_HEAD(unmaps_to_do);
-
-static int timer_on;
-static long list_size;
-
-static void domain_remove_dev_info(struct dmar_domain *domain);
-
-#ifdef CONFIG_DMAR_DEFAULT_ON
-int dmar_disabled = 0;
-#else
-int dmar_disabled = 1;
-#endif /*CONFIG_DMAR_DEFAULT_ON*/
-
-static int dmar_map_gfx = 1;
-static int dmar_forcedac;
-static int intel_iommu_strict;
-static int intel_iommu_superpage = 1;
-
-#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
-static DEFINE_SPINLOCK(device_domain_lock);
-static LIST_HEAD(device_domain_list);
-
-static struct iommu_ops intel_iommu_ops;
-
-static int __init intel_iommu_setup(char *str)
-{
- if (!str)
- return -EINVAL;
- while (*str) {
- if (!strncmp(str, "on", 2)) {
- dmar_disabled = 0;
- printk(KERN_INFO "Intel-IOMMU: enabled\n");
- } else if (!strncmp(str, "off", 3)) {
- dmar_disabled = 1;
- printk(KERN_INFO "Intel-IOMMU: disabled\n");
- } else if (!strncmp(str, "igfx_off", 8)) {
- dmar_map_gfx = 0;
- printk(KERN_INFO
- "Intel-IOMMU: disable GFX device mapping\n");
- } else if (!strncmp(str, "forcedac", 8)) {
- printk(KERN_INFO
- "Intel-IOMMU: Forcing DAC for PCI devices\n");
- dmar_forcedac = 1;
- } else if (!strncmp(str, "strict", 6)) {
- printk(KERN_INFO
- "Intel-IOMMU: disable batched IOTLB flush\n");
- intel_iommu_strict = 1;
- } else if (!strncmp(str, "sp_off", 6)) {
- printk(KERN_INFO
- "Intel-IOMMU: disable supported super page\n");
- intel_iommu_superpage = 0;
- }
-
- str += strcspn(str, ",");
- while (*str == ',')
- str++;
- }
- return 0;
-}
-__setup("intel_iommu=", intel_iommu_setup);
-
-static struct kmem_cache *iommu_domain_cache;
-static struct kmem_cache *iommu_devinfo_cache;
-static struct kmem_cache *iommu_iova_cache;
-
-static inline void *alloc_pgtable_page(int node)
-{
- struct page *page;
- void *vaddr = NULL;
-
- page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
- if (page)
- vaddr = page_address(page);
- return vaddr;
-}
-
-static inline void free_pgtable_page(void *vaddr)
-{
- free_page((unsigned long)vaddr);
-}
-
-static inline void *alloc_domain_mem(void)
-{
- return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
-}
-
-static void free_domain_mem(void *vaddr)
-{
- kmem_cache_free(iommu_domain_cache, vaddr);
-}
-
-static inline void * alloc_devinfo_mem(void)
-{
- return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
-}
-
-static inline void free_devinfo_mem(void *vaddr)
-{
- kmem_cache_free(iommu_devinfo_cache, vaddr);
-}
-
-struct iova *alloc_iova_mem(void)
-{
- return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
-}
-
-void free_iova_mem(struct iova *iova)
-{
- kmem_cache_free(iommu_iova_cache, iova);
-}
-
-
-static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
-{
- unsigned long sagaw;
- int agaw = -1;
-
- sagaw = cap_sagaw(iommu->cap);
- for (agaw = width_to_agaw(max_gaw);
- agaw >= 0; agaw--) {
- if (test_bit(agaw, &sagaw))
- break;
- }
-
- return agaw;
-}
-
-/*
- * Calculate max SAGAW for each iommu.
- */
-int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
-{
- return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
-}
-
-/*
- * calculate agaw for each iommu.
- * "SAGAW" may be different across iommus, use a default agaw, and
- * get a supported less agaw for iommus that don't support the default agaw.
- */
-int iommu_calculate_agaw(struct intel_iommu *iommu)
-{
- return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
-}
-
-/* This functionin only returns single iommu in a domain */
-static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
-{
- int iommu_id;
-
- /* si_domain and vm domain should not get here. */
- BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
- BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY);
-
- iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
- if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
- return NULL;
-
- return g_iommus[iommu_id];
-}
-
-static void domain_update_iommu_coherency(struct dmar_domain *domain)
-{
- int i;
-
- domain->iommu_coherency = 1;
-
- for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
- if (!ecap_coherent(g_iommus[i]->ecap)) {
- domain->iommu_coherency = 0;
- break;
- }
- }
-}
-
-static void domain_update_iommu_snooping(struct dmar_domain *domain)
-{
- int i;
-
- domain->iommu_snooping = 1;
-
- for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
- if (!ecap_sc_support(g_iommus[i]->ecap)) {
- domain->iommu_snooping = 0;
- break;
- }
- }
-}
-
-static void domain_update_iommu_superpage(struct dmar_domain *domain)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu = NULL;
- int mask = 0xf;
-
- if (!intel_iommu_superpage) {
- domain->iommu_superpage = 0;
- return;
- }
-
- /* set iommu_superpage to the smallest common denominator */
- for_each_active_iommu(iommu, drhd) {
- mask &= cap_super_page_val(iommu->cap);
- if (!mask) {
- break;
- }
- }
- domain->iommu_superpage = fls(mask);
-}
-
-/* Some capabilities may be different across iommus */
-static void domain_update_iommu_cap(struct dmar_domain *domain)
-{
- domain_update_iommu_coherency(domain);
- domain_update_iommu_snooping(domain);
- domain_update_iommu_superpage(domain);
-}
-
-static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
-{
- struct dmar_drhd_unit *drhd = NULL;
- int i;
-
- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
- if (segment != drhd->segment)
- continue;
-
- for (i = 0; i < drhd->devices_cnt; i++) {
- if (drhd->devices[i] &&
- drhd->devices[i]->bus->number == bus &&
- drhd->devices[i]->devfn == devfn)
- return drhd->iommu;
- if (drhd->devices[i] &&
- drhd->devices[i]->subordinate &&
- drhd->devices[i]->subordinate->number <= bus &&
- drhd->devices[i]->subordinate->subordinate >= bus)
- return drhd->iommu;
- }
-
- if (drhd->include_all)
- return drhd->iommu;
- }
-
- return NULL;
-}
-
-static void domain_flush_cache(struct dmar_domain *domain,
- void *addr, int size)
-{
- if (!domain->iommu_coherency)
- clflush_cache_range(addr, size);
-}
-
-/* Gets context entry for a given bus and devfn */
-static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
- u8 bus, u8 devfn)
-{
- struct root_entry *root;
- struct context_entry *context;
- unsigned long phy_addr;
- unsigned long flags;
-
- spin_lock_irqsave(&iommu->lock, flags);
- root = &iommu->root_entry[bus];
- context = get_context_addr_from_root(root);
- if (!context) {
- context = (struct context_entry *)
- alloc_pgtable_page(iommu->node);
- if (!context) {
- spin_unlock_irqrestore(&iommu->lock, flags);
- return NULL;
- }
- __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
- phy_addr = virt_to_phys((void *)context);
- set_root_value(root, phy_addr);
- set_root_present(root);
- __iommu_flush_cache(iommu, root, sizeof(*root));
- }
- spin_unlock_irqrestore(&iommu->lock, flags);
- return &context[devfn];
-}
-
-static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
-{
- struct root_entry *root;
- struct context_entry *context;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&iommu->lock, flags);
- root = &iommu->root_entry[bus];
- context = get_context_addr_from_root(root);
- if (!context) {
- ret = 0;
- goto out;
- }
- ret = context_present(&context[devfn]);
-out:
- spin_unlock_irqrestore(&iommu->lock, flags);
- return ret;
-}
-
-static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
-{
- struct root_entry *root;
- struct context_entry *context;
- unsigned long flags;
-
- spin_lock_irqsave(&iommu->lock, flags);
- root = &iommu->root_entry[bus];
- context = get_context_addr_from_root(root);
- if (context) {
- context_clear_entry(&context[devfn]);
- __iommu_flush_cache(iommu, &context[devfn], \
- sizeof(*context));
- }
- spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static void free_context_table(struct intel_iommu *iommu)
-{
- struct root_entry *root;
- int i;
- unsigned long flags;
- struct context_entry *context;
-
- spin_lock_irqsave(&iommu->lock, flags);
- if (!iommu->root_entry) {
- goto out;
- }
- for (i = 0; i < ROOT_ENTRY_NR; i++) {
- root = &iommu->root_entry[i];
- context = get_context_addr_from_root(root);
- if (context)
- free_pgtable_page(context);
- }
- free_pgtable_page(iommu->root_entry);
- iommu->root_entry = NULL;
-out:
- spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
- unsigned long pfn, int target_level)
-{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
- struct dma_pte *parent, *pte = NULL;
- int level = agaw_to_level(domain->agaw);
- int offset;
-
- BUG_ON(!domain->pgd);
- BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
- parent = domain->pgd;
-
- while (level > 0) {
- void *tmp_page;
-
- offset = pfn_level_offset(pfn, level);
- pte = &parent[offset];
- if (!target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
- break;
- if (level == target_level)
- break;
-
- if (!dma_pte_present(pte)) {
- uint64_t pteval;
-
- tmp_page = alloc_pgtable_page(domain->nid);
-
- if (!tmp_page)
- return NULL;
-
- domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
- pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
- if (cmpxchg64(&pte->val, 0ULL, pteval)) {
- /* Someone else set it while we were thinking; use theirs. */
- free_pgtable_page(tmp_page);
- } else {
- dma_pte_addr(pte);
- domain_flush_cache(domain, pte, sizeof(*pte));
- }
- }
- parent = phys_to_virt(dma_pte_addr(pte));
- level--;
- }
-
- return pte;
-}
-
-
-/* return address's pte at specific level */
-static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
- unsigned long pfn,
- int level, int *large_page)
-{
- struct dma_pte *parent, *pte = NULL;
- int total = agaw_to_level(domain->agaw);
- int offset;
-
- parent = domain->pgd;
- while (level <= total) {
- offset = pfn_level_offset(pfn, total);
- pte = &parent[offset];
- if (level == total)
- return pte;
-
- if (!dma_pte_present(pte)) {
- *large_page = total;
- break;
- }
-
- if (pte->val & DMA_PTE_LARGE_PAGE) {
- *large_page = total;
- return pte;
- }
-
- parent = phys_to_virt(dma_pte_addr(pte));
- total--;
- }
- return NULL;
-}
-
-/* clear last level pte, a tlb flush should be followed */
-static int dma_pte_clear_range(struct dmar_domain *domain,
- unsigned long start_pfn,
- unsigned long last_pfn)
-{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
- unsigned int large_page = 1;
- struct dma_pte *first_pte, *pte;
- int order;
-
- BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
- BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
- BUG_ON(start_pfn > last_pfn);
-
- /* we don't need lock here; nobody else touches the iova range */
- do {
- large_page = 1;
- first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
- if (!pte) {
- start_pfn = align_to_level(start_pfn + 1, large_page + 1);
- continue;
- }
- do {
- dma_clear_pte(pte);
- start_pfn += lvl_to_nr_pages(large_page);
- pte++;
- } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
-
- domain_flush_cache(domain, first_pte,
- (void *)pte - (void *)first_pte);
-
- } while (start_pfn && start_pfn <= last_pfn);
-
- order = (large_page - 1) * 9;
- return order;
-}
-
-static void dma_pte_free_level(struct dmar_domain *domain, int level,
- struct dma_pte *pte, unsigned long pfn,
- unsigned long start_pfn, unsigned long last_pfn)
-{
- pfn = max(start_pfn, pfn);
- pte = &pte[pfn_level_offset(pfn, level)];
-
- do {
- unsigned long level_pfn;
- struct dma_pte *level_pte;
-
- if (!dma_pte_present(pte) || dma_pte_superpage(pte))
- goto next;
-
- level_pfn = pfn & level_mask(level - 1);
- level_pte = phys_to_virt(dma_pte_addr(pte));
-
- if (level > 2)
- dma_pte_free_level(domain, level - 1, level_pte,
- level_pfn, start_pfn, last_pfn);
-
- /* If range covers entire pagetable, free it */
- if (!(start_pfn > level_pfn ||
- last_pfn < level_pfn + level_size(level))) {
- dma_clear_pte(pte);
- domain_flush_cache(domain, pte, sizeof(*pte));
- free_pgtable_page(level_pte);
- }
-next:
- pfn += level_size(level);
- } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
-}
-
-/* free page table pages. last level pte should already be cleared */
-static void dma_pte_free_pagetable(struct dmar_domain *domain,
- unsigned long start_pfn,
- unsigned long last_pfn)
-{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-
- BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
- BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
- BUG_ON(start_pfn > last_pfn);
-
- /* We don't need lock here; nobody else touches the iova range */
- dma_pte_free_level(domain, agaw_to_level(domain->agaw),
- domain->pgd, 0, start_pfn, last_pfn);
-
- /* free pgd */
- if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
- free_pgtable_page(domain->pgd);
- domain->pgd = NULL;
- }
-}
-
-/* iommu handling */
-static int iommu_alloc_root_entry(struct intel_iommu *iommu)
-{
- struct root_entry *root;
- unsigned long flags;
-
- root = (struct root_entry *)alloc_pgtable_page(iommu->node);
- if (!root)
- return -ENOMEM;
-
- __iommu_flush_cache(iommu, root, ROOT_SIZE);
-
- spin_lock_irqsave(&iommu->lock, flags);
- iommu->root_entry = root;
- spin_unlock_irqrestore(&iommu->lock, flags);
-
- return 0;
-}
-
-static void iommu_set_root_entry(struct intel_iommu *iommu)
-{
- void *addr;
- u32 sts;
- unsigned long flag;
-
- addr = iommu->root_entry;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
-
- writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (sts & DMA_GSTS_RTPS), sts);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-static void iommu_flush_write_buffer(struct intel_iommu *iommu)
-{
- u32 val;
- unsigned long flag;
-
- if (!rwbf_quirk && !cap_rwbf(iommu->cap))
- return;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (!(val & DMA_GSTS_WBFS)), val);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-/* return value determine if we need a write buffer flush */
-static void __iommu_flush_context(struct intel_iommu *iommu,
- u16 did, u16 source_id, u8 function_mask,
- u64 type)
-{
- u64 val = 0;
- unsigned long flag;
-
- switch (type) {
- case DMA_CCMD_GLOBAL_INVL:
- val = DMA_CCMD_GLOBAL_INVL;
- break;
- case DMA_CCMD_DOMAIN_INVL:
- val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
- break;
- case DMA_CCMD_DEVICE_INVL:
- val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
- | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
- break;
- default:
- BUG();
- }
- val |= DMA_CCMD_ICC;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
- dmar_readq, (!(val & DMA_CCMD_ICC)), val);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-/* return value determine if we need a write buffer flush */
-static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
- u64 addr, unsigned int size_order, u64 type)
-{
- int tlb_offset = ecap_iotlb_offset(iommu->ecap);
- u64 val = 0, val_iva = 0;
- unsigned long flag;
-
- switch (type) {
- case DMA_TLB_GLOBAL_FLUSH:
- /* global flush doesn't need set IVA_REG */
- val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
- break;
- case DMA_TLB_DSI_FLUSH:
- val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
- break;
- case DMA_TLB_PSI_FLUSH:
- val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
- /* Note: always flush non-leaf currently */
- val_iva = size_order | addr;
- break;
- default:
- BUG();
- }
- /* Note: set drain read/write */
-#if 0
- /*
- * This is probably to be super secure.. Looks like we can
- * ignore it without any impact.
- */
- if (cap_read_drain(iommu->cap))
- val |= DMA_TLB_READ_DRAIN;
-#endif
- if (cap_write_drain(iommu->cap))
- val |= DMA_TLB_WRITE_DRAIN;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- /* Note: Only uses first TLB reg currently */
- if (val_iva)
- dmar_writeq(iommu->reg + tlb_offset, val_iva);
- dmar_writeq(iommu->reg + tlb_offset + 8, val);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, tlb_offset + 8,
- dmar_readq, (!(val & DMA_TLB_IVT)), val);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
-
- /* check IOTLB invalidation granularity */
- if (DMA_TLB_IAIG(val) == 0)
- printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
- if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
- pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
- (unsigned long long)DMA_TLB_IIRG(type),
- (unsigned long long)DMA_TLB_IAIG(val));
-}
-
-static struct device_domain_info *iommu_support_dev_iotlb(
- struct dmar_domain *domain, int segment, u8 bus, u8 devfn)
-{
- int found = 0;
- unsigned long flags;
- struct device_domain_info *info;
- struct intel_iommu *iommu = device_to_iommu(segment, bus, devfn);
-
- if (!ecap_dev_iotlb_support(iommu->ecap))
- return NULL;
-
- if (!iommu->qi)
- return NULL;
-
- spin_lock_irqsave(&device_domain_lock, flags);
- list_for_each_entry(info, &domain->devices, link)
- if (info->bus == bus && info->devfn == devfn) {
- found = 1;
- break;
- }
- spin_unlock_irqrestore(&device_domain_lock, flags);
-
- if (!found || !info->dev)
- return NULL;
-
- if (!pci_find_ext_capability(info->dev, PCI_EXT_CAP_ID_ATS))
- return NULL;
-
- if (!dmar_find_matched_atsr_unit(info->dev))
- return NULL;
-
- info->iommu = iommu;
-
- return info;
-}
-
-static void iommu_enable_dev_iotlb(struct device_domain_info *info)
-{
- if (!info)
- return;
-
- pci_enable_ats(info->dev, VTD_PAGE_SHIFT);
-}
-
-static void iommu_disable_dev_iotlb(struct device_domain_info *info)
-{
- if (!info->dev || !pci_ats_enabled(info->dev))
- return;
-
- pci_disable_ats(info->dev);
-}
-
-static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
- u64 addr, unsigned mask)
-{
- u16 sid, qdep;
- unsigned long flags;
- struct device_domain_info *info;
-
- spin_lock_irqsave(&device_domain_lock, flags);
- list_for_each_entry(info, &domain->devices, link) {
- if (!info->dev || !pci_ats_enabled(info->dev))
- continue;
-
- sid = info->bus << 8 | info->devfn;
- qdep = pci_ats_queue_depth(info->dev);
- qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
- }
- spin_unlock_irqrestore(&device_domain_lock, flags);
-}
-
-static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
- unsigned long pfn, unsigned int pages, int map)
-{
- unsigned int mask = ilog2(__roundup_pow_of_two(pages));
- uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
-
- BUG_ON(pages == 0);
-
- /*
- * Fallback to domain selective flush if no PSI support or the size is
- * too big.
- * PSI requires page size to be 2 ^ x, and the base address is naturally
- * aligned to the size
- */
- if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
- iommu->flush.flush_iotlb(iommu, did, 0, 0,
- DMA_TLB_DSI_FLUSH);
- else
- iommu->flush.flush_iotlb(iommu, did, addr, mask,
- DMA_TLB_PSI_FLUSH);
-
- /*
- * In caching mode, changes of pages from non-present to present require
- * flush. However, device IOTLB doesn't need to be flushed in this case.
- */
- if (!cap_caching_mode(iommu->cap) || !map)
- iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
-}
-
-static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
-{
- u32 pmen;
- unsigned long flags;
-
- spin_lock_irqsave(&iommu->register_lock, flags);
- pmen = readl(iommu->reg + DMAR_PMEN_REG);
- pmen &= ~DMA_PMEN_EPM;
- writel(pmen, iommu->reg + DMAR_PMEN_REG);
-
- /* wait for the protected region status bit to clear */
- IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
- readl, !(pmen & DMA_PMEN_PRS), pmen);
-
- spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-static int iommu_enable_translation(struct intel_iommu *iommu)
-{
- u32 sts;
- unsigned long flags;
-
- spin_lock_irqsave(&iommu->register_lock, flags);
- iommu->gcmd |= DMA_GCMD_TE;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (sts & DMA_GSTS_TES), sts);
-
- spin_unlock_irqrestore(&iommu->register_lock, flags);
- return 0;
-}
-
-static int iommu_disable_translation(struct intel_iommu *iommu)
-{
- u32 sts;
- unsigned long flag;
-
- spin_lock_irqsave(&iommu->register_lock, flag);
- iommu->gcmd &= ~DMA_GCMD_TE;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- /* Make sure hardware complete it */
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (!(sts & DMA_GSTS_TES)), sts);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
- return 0;
-}
-
-
-static int iommu_init_domains(struct intel_iommu *iommu)
-{
- unsigned long ndomains;
- unsigned long nlongs;
-
- ndomains = cap_ndoms(iommu->cap);
- pr_debug("IOMMU %d: Number of Domains supportd <%ld>\n", iommu->seq_id,
- ndomains);
- nlongs = BITS_TO_LONGS(ndomains);
-
- spin_lock_init(&iommu->lock);
-
- /* TBD: there might be 64K domains,
- * consider other allocation for future chip
- */
- iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
- if (!iommu->domain_ids) {
- printk(KERN_ERR "Allocating domain id array failed\n");
- return -ENOMEM;
- }
- iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
- GFP_KERNEL);
- if (!iommu->domains) {
- printk(KERN_ERR "Allocating domain array failed\n");
- return -ENOMEM;
- }
-
- /*
- * if Caching mode is set, then invalid translations are tagged
- * with domainid 0. Hence we need to pre-allocate it.
- */
- if (cap_caching_mode(iommu->cap))
- set_bit(0, iommu->domain_ids);
- return 0;
-}
-
-
-static void domain_exit(struct dmar_domain *domain);
-static void vm_domain_exit(struct dmar_domain *domain);
-
-void free_dmar_iommu(struct intel_iommu *iommu)
-{
- struct dmar_domain *domain;
- int i;
- unsigned long flags;
-
- if ((iommu->domains) && (iommu->domain_ids)) {
- for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
- domain = iommu->domains[i];
- clear_bit(i, iommu->domain_ids);
-
- spin_lock_irqsave(&domain->iommu_lock, flags);
- if (--domain->iommu_count == 0) {
- if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
- vm_domain_exit(domain);
- else
- domain_exit(domain);
- }
- spin_unlock_irqrestore(&domain->iommu_lock, flags);
- }
- }
-
- if (iommu->gcmd & DMA_GCMD_TE)
- iommu_disable_translation(iommu);
-
- if (iommu->irq) {
- irq_set_handler_data(iommu->irq, NULL);
- /* This will mask the irq */
- free_irq(iommu->irq, iommu);
- destroy_irq(iommu->irq);
- }
-
- kfree(iommu->domains);
- kfree(iommu->domain_ids);
-
- g_iommus[iommu->seq_id] = NULL;
-
- /* if all iommus are freed, free g_iommus */
- for (i = 0; i < g_num_of_iommus; i++) {
- if (g_iommus[i])
- break;
- }
-
- if (i == g_num_of_iommus)
- kfree(g_iommus);
-
- /* free context mapping */
- free_context_table(iommu);
-}
-
-static struct dmar_domain *alloc_domain(void)
-{
- struct dmar_domain *domain;
-
- domain = alloc_domain_mem();
- if (!domain)
- return NULL;
-
- domain->nid = -1;
- memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
- domain->flags = 0;
-
- return domain;
-}
-
-static int iommu_attach_domain(struct dmar_domain *domain,
- struct intel_iommu *iommu)
-{
- int num;
- unsigned long ndomains;
- unsigned long flags;
-
- ndomains = cap_ndoms(iommu->cap);
-
- spin_lock_irqsave(&iommu->lock, flags);
-
- num = find_first_zero_bit(iommu->domain_ids, ndomains);
- if (num >= ndomains) {
- spin_unlock_irqrestore(&iommu->lock, flags);
- printk(KERN_ERR "IOMMU: no free domain ids\n");
- return -ENOMEM;
- }
-
- domain->id = num;
- set_bit(num, iommu->domain_ids);
- set_bit(iommu->seq_id, &domain->iommu_bmp);
- iommu->domains[num] = domain;
- spin_unlock_irqrestore(&iommu->lock, flags);
-
- return 0;
-}
-
-static void iommu_detach_domain(struct dmar_domain *domain,
- struct intel_iommu *iommu)
-{
- unsigned long flags;
- int num, ndomains;
- int found = 0;
-
- spin_lock_irqsave(&iommu->lock, flags);
- ndomains = cap_ndoms(iommu->cap);
- for_each_set_bit(num, iommu->domain_ids, ndomains) {
- if (iommu->domains[num] == domain) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- clear_bit(num, iommu->domain_ids);
- clear_bit(iommu->seq_id, &domain->iommu_bmp);
- iommu->domains[num] = NULL;
- }
- spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static struct iova_domain reserved_iova_list;
-static struct lock_class_key reserved_rbtree_key;
-
-static int dmar_init_reserved_ranges(void)
-{
- struct pci_dev *pdev = NULL;
- struct iova *iova;
- int i;
-
- init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
-
- lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
- &reserved_rbtree_key);
-
- /* IOAPIC ranges shouldn't be accessed by DMA */
- iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
- IOVA_PFN(IOAPIC_RANGE_END));
- if (!iova) {
- printk(KERN_ERR "Reserve IOAPIC range failed\n");
- return -ENODEV;
- }
-
- /* Reserve all PCI MMIO to avoid peer-to-peer access */
- for_each_pci_dev(pdev) {
- struct resource *r;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- r = &pdev->resource[i];
- if (!r->flags || !(r->flags & IORESOURCE_MEM))
- continue;
- iova = reserve_iova(&reserved_iova_list,
- IOVA_PFN(r->start),
- IOVA_PFN(r->end));
- if (!iova) {
- printk(KERN_ERR "Reserve iova failed\n");
- return -ENODEV;
- }
- }
- }
- return 0;
-}
-
-static void domain_reserve_special_ranges(struct dmar_domain *domain)
-{
- copy_reserved_iova(&reserved_iova_list, &domain->iovad);
-}
-
-static inline int guestwidth_to_adjustwidth(int gaw)
-{
- int agaw;
- int r = (gaw - 12) % 9;
-
- if (r == 0)
- agaw = gaw;
- else
- agaw = gaw + 9 - r;
- if (agaw > 64)
- agaw = 64;
- return agaw;
-}
-
-static int domain_init(struct dmar_domain *domain, int guest_width)
-{
- struct intel_iommu *iommu;
- int adjust_width, agaw;
- unsigned long sagaw;
-
- init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
- spin_lock_init(&domain->iommu_lock);
-
- domain_reserve_special_ranges(domain);
-
- /* calculate AGAW */
- iommu = domain_get_iommu(domain);
- if (guest_width > cap_mgaw(iommu->cap))
- guest_width = cap_mgaw(iommu->cap);
- domain->gaw = guest_width;
- adjust_width = guestwidth_to_adjustwidth(guest_width);
- agaw = width_to_agaw(adjust_width);
- sagaw = cap_sagaw(iommu->cap);
- if (!test_bit(agaw, &sagaw)) {
- /* hardware doesn't support it, choose a bigger one */
- pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
- agaw = find_next_bit(&sagaw, 5, agaw);
- if (agaw >= 5)
- return -ENODEV;
- }
- domain->agaw = agaw;
- INIT_LIST_HEAD(&domain->devices);
-
- if (ecap_coherent(iommu->ecap))
- domain->iommu_coherency = 1;
- else
- domain->iommu_coherency = 0;
-
- if (ecap_sc_support(iommu->ecap))
- domain->iommu_snooping = 1;
- else
- domain->iommu_snooping = 0;
-
- domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
- domain->iommu_count = 1;
- domain->nid = iommu->node;
-
- /* always allocate the top pgd */
- domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
- if (!domain->pgd)
- return -ENOMEM;
- __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
- return 0;
-}
-
-static void domain_exit(struct dmar_domain *domain)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu;
-
- /* Domain 0 is reserved, so dont process it */
- if (!domain)
- return;
-
- /* Flush any lazy unmaps that may reference this domain */
- if (!intel_iommu_strict)
- flush_unmaps_timeout(0);
-
- domain_remove_dev_info(domain);
- /* destroy iovas */
- put_iova_domain(&domain->iovad);
-
- /* clear ptes */
- dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
- /* free page tables */
- dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
- for_each_active_iommu(iommu, drhd)
- if (test_bit(iommu->seq_id, &domain->iommu_bmp))
- iommu_detach_domain(domain, iommu);
-
- free_domain_mem(domain);
-}
-
-static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
- u8 bus, u8 devfn, int translation)
-{
- struct context_entry *context;
- unsigned long flags;
- struct intel_iommu *iommu;
- struct dma_pte *pgd;
- unsigned long num;
- unsigned long ndomains;
- int id;
- int agaw;
- struct device_domain_info *info = NULL;
-
- pr_debug("Set context mapping for %02x:%02x.%d\n",
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
- BUG_ON(!domain->pgd);
- BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
- translation != CONTEXT_TT_MULTI_LEVEL);
-
- iommu = device_to_iommu(segment, bus, devfn);
- if (!iommu)
- return -ENODEV;
-
- context = device_to_context_entry(iommu, bus, devfn);
- if (!context)
- return -ENOMEM;
- spin_lock_irqsave(&iommu->lock, flags);
- if (context_present(context)) {
- spin_unlock_irqrestore(&iommu->lock, flags);
- return 0;
- }
-
- id = domain->id;
- pgd = domain->pgd;
-
- if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
- domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) {
- int found = 0;
-
- /* find an available domain id for this device in iommu */
- ndomains = cap_ndoms(iommu->cap);
- for_each_set_bit(num, iommu->domain_ids, ndomains) {
- if (iommu->domains[num] == domain) {
- id = num;
- found = 1;
- break;
- }
- }
-
- if (found == 0) {
- num = find_first_zero_bit(iommu->domain_ids, ndomains);
- if (num >= ndomains) {
- spin_unlock_irqrestore(&iommu->lock, flags);
- printk(KERN_ERR "IOMMU: no free domain ids\n");
- return -EFAULT;
- }
-
- set_bit(num, iommu->domain_ids);
- iommu->domains[num] = domain;
- id = num;
- }
-
- /* Skip top levels of page tables for
- * iommu which has less agaw than default.
- * Unnecessary for PT mode.
- */
- if (translation != CONTEXT_TT_PASS_THROUGH) {
- for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
- pgd = phys_to_virt(dma_pte_addr(pgd));
- if (!dma_pte_present(pgd)) {
- spin_unlock_irqrestore(&iommu->lock, flags);
- return -ENOMEM;
- }
- }
- }
- }
-
- context_set_domain_id(context, id);
-
- if (translation != CONTEXT_TT_PASS_THROUGH) {
- info = iommu_support_dev_iotlb(domain, segment, bus, devfn);
- translation = info ? CONTEXT_TT_DEV_IOTLB :
- CONTEXT_TT_MULTI_LEVEL;
- }
- /*
- * In pass through mode, AW must be programmed to indicate the largest
- * AGAW value supported by hardware. And ASR is ignored by hardware.
- */
- if (unlikely(translation == CONTEXT_TT_PASS_THROUGH))
- context_set_address_width(context, iommu->msagaw);
- else {
- context_set_address_root(context, virt_to_phys(pgd));
- context_set_address_width(context, iommu->agaw);
- }
-
- context_set_translation_type(context, translation);
- context_set_fault_enable(context);
- context_set_present(context);
- domain_flush_cache(domain, context, sizeof(*context));
-
- /*
- * It's a non-present to present mapping. If hardware doesn't cache
- * non-present entry we only need to flush the write-buffer. If the
- * _does_ cache non-present entries, then it does so in the special
- * domain #0, which we have to flush:
- */
- if (cap_caching_mode(iommu->cap)) {
- iommu->flush.flush_context(iommu, 0,
- (((u16)bus) << 8) | devfn,
- DMA_CCMD_MASK_NOBIT,
- DMA_CCMD_DEVICE_INVL);
- iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH);
- } else {
- iommu_flush_write_buffer(iommu);
- }
- iommu_enable_dev_iotlb(info);
- spin_unlock_irqrestore(&iommu->lock, flags);
-
- spin_lock_irqsave(&domain->iommu_lock, flags);
- if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
- domain->iommu_count++;
- if (domain->iommu_count == 1)
- domain->nid = iommu->node;
- domain_update_iommu_cap(domain);
- }
- spin_unlock_irqrestore(&domain->iommu_lock, flags);
- return 0;
-}
-
-static int
-domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
- int translation)
-{
- int ret;
- struct pci_dev *tmp, *parent;
-
- ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus),
- pdev->bus->number, pdev->devfn,
- translation);
- if (ret)
- return ret;
-
- /* dependent device mapping */
- tmp = pci_find_upstream_pcie_bridge(pdev);
- if (!tmp)
- return 0;
- /* Secondary interface's bus number and devfn 0 */
- parent = pdev->bus->self;
- while (parent != tmp) {
- ret = domain_context_mapping_one(domain,
- pci_domain_nr(parent->bus),
- parent->bus->number,
- parent->devfn, translation);
- if (ret)
- return ret;
- parent = parent->bus->self;
- }
- if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
- return domain_context_mapping_one(domain,
- pci_domain_nr(tmp->subordinate),
- tmp->subordinate->number, 0,
- translation);
- else /* this is a legacy PCI bridge */
- return domain_context_mapping_one(domain,
- pci_domain_nr(tmp->bus),
- tmp->bus->number,
- tmp->devfn,
- translation);
-}
-
-static int domain_context_mapped(struct pci_dev *pdev)
-{
- int ret;
- struct pci_dev *tmp, *parent;
- struct intel_iommu *iommu;
-
- iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
- pdev->devfn);
- if (!iommu)
- return -ENODEV;
-
- ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn);
- if (!ret)
- return ret;
- /* dependent device mapping */
- tmp = pci_find_upstream_pcie_bridge(pdev);
- if (!tmp)
- return ret;
- /* Secondary interface's bus number and devfn 0 */
- parent = pdev->bus->self;
- while (parent != tmp) {
- ret = device_context_mapped(iommu, parent->bus->number,
- parent->devfn);
- if (!ret)
- return ret;
- parent = parent->bus->self;
- }
- if (pci_is_pcie(tmp))
- return device_context_mapped(iommu, tmp->subordinate->number,
- 0);
- else
- return device_context_mapped(iommu, tmp->bus->number,
- tmp->devfn);
-}
-
-/* Returns a number of VTD pages, but aligned to MM page size */
-static inline unsigned long aligned_nrpages(unsigned long host_addr,
- size_t size)
-{
- host_addr &= ~PAGE_MASK;
- return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
-}
-
-/* Return largest possible superpage level for a given mapping */
-static inline int hardware_largepage_caps(struct dmar_domain *domain,
- unsigned long iov_pfn,
- unsigned long phy_pfn,
- unsigned long pages)
-{
- int support, level = 1;
- unsigned long pfnmerge;
-
- support = domain->iommu_superpage;
-
- /* To use a large page, the virtual *and* physical addresses
- must be aligned to 2MiB/1GiB/etc. Lower bits set in either
- of them will mean we have to use smaller pages. So just
- merge them and check both at once. */
- pfnmerge = iov_pfn | phy_pfn;
-
- while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
- pages >>= VTD_STRIDE_SHIFT;
- if (!pages)
- break;
- pfnmerge >>= VTD_STRIDE_SHIFT;
- level++;
- support--;
- }
- return level;
-}
-
-static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
- struct scatterlist *sg, unsigned long phys_pfn,
- unsigned long nr_pages, int prot)
-{
- struct dma_pte *first_pte = NULL, *pte = NULL;
- phys_addr_t uninitialized_var(pteval);
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
- unsigned long sg_res;
- unsigned int largepage_lvl = 0;
- unsigned long lvl_pages = 0;
-
- BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
-
- if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
- return -EINVAL;
-
- prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
-
- if (sg)
- sg_res = 0;
- else {
- sg_res = nr_pages + 1;
- pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
- }
-
- while (nr_pages > 0) {
- uint64_t tmp;
-
- if (!sg_res) {
- sg_res = aligned_nrpages(sg->offset, sg->length);
- sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
- sg->dma_length = sg->length;
- pteval = page_to_phys(sg_page(sg)) | prot;
- phys_pfn = pteval >> VTD_PAGE_SHIFT;
- }
-
- if (!pte) {
- largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
-
- first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, largepage_lvl);
- if (!pte)
- return -ENOMEM;
- /* It is large page*/
- if (largepage_lvl > 1) {
- pteval |= DMA_PTE_LARGE_PAGE;
- /* Ensure that old small page tables are removed to make room
- for superpage, if they exist. */
- dma_pte_clear_range(domain, iov_pfn,
- iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
- dma_pte_free_pagetable(domain, iov_pfn,
- iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
- } else {
- pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
- }
-
- }
- /* We don't need lock here, nobody else
- * touches the iova range
- */
- tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
- if (tmp) {
- static int dumps = 5;
- printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
- iov_pfn, tmp, (unsigned long long)pteval);
- if (dumps) {
- dumps--;
- debug_dma_dump_mappings(NULL);
- }
- WARN_ON(1);
- }
-
- lvl_pages = lvl_to_nr_pages(largepage_lvl);
-
- BUG_ON(nr_pages < lvl_pages);
- BUG_ON(sg_res < lvl_pages);
-
- nr_pages -= lvl_pages;
- iov_pfn += lvl_pages;
- phys_pfn += lvl_pages;
- pteval += lvl_pages * VTD_PAGE_SIZE;
- sg_res -= lvl_pages;
-
- /* If the next PTE would be the first in a new page, then we
- need to flush the cache on the entries we've just written.
- And then we'll need to recalculate 'pte', so clear it and
- let it get set again in the if (!pte) block above.
-
- If we're done (!nr_pages) we need to flush the cache too.
-
- Also if we've been setting superpages, we may need to
- recalculate 'pte' and switch back to smaller pages for the
- end of the mapping, if the trailing size is not enough to
- use another superpage (i.e. sg_res < lvl_pages). */
- pte++;
- if (!nr_pages || first_pte_in_page(pte) ||
- (largepage_lvl > 1 && sg_res < lvl_pages)) {
- domain_flush_cache(domain, first_pte,
- (void *)pte - (void *)first_pte);
- pte = NULL;
- }
-
- if (!sg_res && nr_pages)
- sg = sg_next(sg);
- }
- return 0;
-}
-
-static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
- struct scatterlist *sg, unsigned long nr_pages,
- int prot)
-{
- return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
-}
-
-static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
- unsigned long phys_pfn, unsigned long nr_pages,
- int prot)
-{
- return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
-}
-
-static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
-{
- if (!iommu)
- return;
-
- clear_context_table(iommu, bus, devfn);
- iommu->flush.flush_context(iommu, 0, 0, 0,
- DMA_CCMD_GLOBAL_INVL);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-}
-
-static void domain_remove_dev_info(struct dmar_domain *domain)
-{
- struct device_domain_info *info;
- unsigned long flags;
- struct intel_iommu *iommu;
-
- spin_lock_irqsave(&device_domain_lock, flags);
- while (!list_empty(&domain->devices)) {
- info = list_entry(domain->devices.next,
- struct device_domain_info, link);
- list_del(&info->link);
- list_del(&info->global);
- if (info->dev)
- info->dev->dev.archdata.iommu = NULL;
- spin_unlock_irqrestore(&device_domain_lock, flags);
-
- iommu_disable_dev_iotlb(info);
- iommu = device_to_iommu(info->segment, info->bus, info->devfn);
- iommu_detach_dev(iommu, info->bus, info->devfn);
- free_devinfo_mem(info);
-
- spin_lock_irqsave(&device_domain_lock, flags);
- }
- spin_unlock_irqrestore(&device_domain_lock, flags);
-}
-
-/*
- * find_domain
- * Note: we use struct pci_dev->dev.archdata.iommu stores the info
- */
-static struct dmar_domain *
-find_domain(struct pci_dev *pdev)
-{
- struct device_domain_info *info;
-
- /* No lock here, assumes no domain exit in normal case */
- info = pdev->dev.archdata.iommu;
- if (info)
- return info->domain;
- return NULL;
-}
-
-/* domain is initialized */
-static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
-{
- struct dmar_domain *domain, *found = NULL;
- struct intel_iommu *iommu;
- struct dmar_drhd_unit *drhd;
- struct device_domain_info *info, *tmp;
- struct pci_dev *dev_tmp;
- unsigned long flags;
- int bus = 0, devfn = 0;
- int segment;
- int ret;
-
- domain = find_domain(pdev);
- if (domain)
- return domain;
-
- segment = pci_domain_nr(pdev->bus);
-
- dev_tmp = pci_find_upstream_pcie_bridge(pdev);
- if (dev_tmp) {
- if (pci_is_pcie(dev_tmp)) {
- bus = dev_tmp->subordinate->number;
- devfn = 0;
- } else {
- bus = dev_tmp->bus->number;
- devfn = dev_tmp->devfn;
- }
- spin_lock_irqsave(&device_domain_lock, flags);
- list_for_each_entry(info, &device_domain_list, global) {
- if (info->segment == segment &&
- info->bus == bus && info->devfn == devfn) {
- found = info->domain;
- break;
- }
- }
- spin_unlock_irqrestore(&device_domain_lock, flags);
- /* pcie-pci bridge already has a domain, uses it */
- if (found) {
- domain = found;
- goto found_domain;
- }
- }
-
- domain = alloc_domain();
- if (!domain)
- goto error;
-
- /* Allocate new domain for the device */
- drhd = dmar_find_matched_drhd_unit(pdev);
- if (!drhd) {
- printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
- pci_name(pdev));
- return NULL;
- }
- iommu = drhd->iommu;
-
- ret = iommu_attach_domain(domain, iommu);
- if (ret) {
- free_domain_mem(domain);
- goto error;
- }
-
- if (domain_init(domain, gaw)) {
- domain_exit(domain);
- goto error;
- }
-
- /* register pcie-to-pci device */
- if (dev_tmp) {
- info = alloc_devinfo_mem();
- if (!info) {
- domain_exit(domain);
- goto error;
- }
- info->segment = segment;
- info->bus = bus;
- info->devfn = devfn;
- info->dev = NULL;
- info->domain = domain;
- /* This domain is shared by devices under p2p bridge */
- domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
-
- /* pcie-to-pci bridge already has a domain, uses it */
- found = NULL;
- spin_lock_irqsave(&device_domain_lock, flags);
- list_for_each_entry(tmp, &device_domain_list, global) {
- if (tmp->segment == segment &&
- tmp->bus == bus && tmp->devfn == devfn) {
- found = tmp->domain;
- break;
- }
- }
- if (found) {
- spin_unlock_irqrestore(&device_domain_lock, flags);
- free_devinfo_mem(info);
- domain_exit(domain);
- domain = found;
- } else {
- list_add(&info->link, &domain->devices);
- list_add(&info->global, &device_domain_list);
- spin_unlock_irqrestore(&device_domain_lock, flags);
- }
- }
-
-found_domain:
- info = alloc_devinfo_mem();
- if (!info)
- goto error;
- info->segment = segment;
- info->bus = pdev->bus->number;
- info->devfn = pdev->devfn;
- info->dev = pdev;
- info->domain = domain;
- spin_lock_irqsave(&device_domain_lock, flags);
- /* somebody is fast */
- found = find_domain(pdev);
- if (found != NULL) {
- spin_unlock_irqrestore(&device_domain_lock, flags);
- if (found != domain) {
- domain_exit(domain);
- domain = found;
- }
- free_devinfo_mem(info);
- return domain;
- }
- list_add(&info->link, &domain->devices);
- list_add(&info->global, &device_domain_list);
- pdev->dev.archdata.iommu = info;
- spin_unlock_irqrestore(&device_domain_lock, flags);
- return domain;
-error:
- /* recheck it here, maybe others set it */
- return find_domain(pdev);
-}
-
-static int iommu_identity_mapping;
-#define IDENTMAP_ALL 1
-#define IDENTMAP_GFX 2
-#define IDENTMAP_AZALIA 4
-
-static int iommu_domain_identity_map(struct dmar_domain *domain,
- unsigned long long start,
- unsigned long long end)
-{
- unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
- unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
-
- if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
- dma_to_mm_pfn(last_vpfn))) {
- printk(KERN_ERR "IOMMU: reserve iova failed\n");
- return -ENOMEM;
- }
-
- pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
- start, end, domain->id);
- /*
- * RMRR range might have overlap with physical memory range,
- * clear it first
- */
- dma_pte_clear_range(domain, first_vpfn, last_vpfn);
-
- return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
- last_vpfn - first_vpfn + 1,
- DMA_PTE_READ|DMA_PTE_WRITE);
-}
-
-static int iommu_prepare_identity_map(struct pci_dev *pdev,
- unsigned long long start,
- unsigned long long end)
-{
- struct dmar_domain *domain;
- int ret;
-
- domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
- if (!domain)
- return -ENOMEM;
-
- /* For _hardware_ passthrough, don't bother. But for software
- passthrough, we do it anyway -- it may indicate a memory
- range which is reserved in E820, so which didn't get set
- up to start with in si_domain */
- if (domain == si_domain && hw_pass_through) {
- printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
- pci_name(pdev), start, end);
- return 0;
- }
-
- printk(KERN_INFO
- "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
- pci_name(pdev), start, end);
-
- if (end < start) {
- WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
- "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
- dmi_get_system_info(DMI_BIOS_VENDOR),
- dmi_get_system_info(DMI_BIOS_VERSION),
- dmi_get_system_info(DMI_PRODUCT_VERSION));
- ret = -EIO;
- goto error;
- }
-
- if (end >> agaw_to_width(domain->agaw)) {
- WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
- "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
- agaw_to_width(domain->agaw),
- dmi_get_system_info(DMI_BIOS_VENDOR),
- dmi_get_system_info(DMI_BIOS_VERSION),
- dmi_get_system_info(DMI_PRODUCT_VERSION));
- ret = -EIO;
- goto error;
- }
-
- ret = iommu_domain_identity_map(domain, start, end);
- if (ret)
- goto error;
-
- /* context entry init */
- ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
- if (ret)
- goto error;
-
- return 0;
-
- error:
- domain_exit(domain);
- return ret;
-}
-
-static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
- struct pci_dev *pdev)
-{
- if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
- return 0;
- return iommu_prepare_identity_map(pdev, rmrr->base_address,
- rmrr->end_address);
-}
-
-#ifdef CONFIG_DMAR_FLOPPY_WA
-static inline void iommu_prepare_isa(void)
-{
- struct pci_dev *pdev;
- int ret;
-
- pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
- if (!pdev)
- return;
-
- printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
- ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024 - 1);
-
- if (ret)
- printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
- "floppy might not work\n");
-
-}
-#else
-static inline void iommu_prepare_isa(void)
-{
- return;
-}
-#endif /* !CONFIG_DMAR_FLPY_WA */
-
-static int md_domain_init(struct dmar_domain *domain, int guest_width);
-
-static int __init si_domain_work_fn(unsigned long start_pfn,
- unsigned long end_pfn, void *datax)
-{
- int *ret = datax;
-
- *ret = iommu_domain_identity_map(si_domain,
- (uint64_t)start_pfn << PAGE_SHIFT,
- (uint64_t)end_pfn << PAGE_SHIFT);
- return *ret;
-
-}
-
-static int __init si_domain_init(int hw)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu;
- int nid, ret = 0;
-
- si_domain = alloc_domain();
- if (!si_domain)
- return -EFAULT;
-
- pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
-
- for_each_active_iommu(iommu, drhd) {
- ret = iommu_attach_domain(si_domain, iommu);
- if (ret) {
- domain_exit(si_domain);
- return -EFAULT;
- }
- }
-
- if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
- domain_exit(si_domain);
- return -EFAULT;
- }
-
- si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
-
- if (hw)
- return 0;
-
- for_each_online_node(nid) {
- work_with_active_regions(nid, si_domain_work_fn, &ret);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static void domain_remove_one_dev_info(struct dmar_domain *domain,
- struct pci_dev *pdev);
-static int identity_mapping(struct pci_dev *pdev)
-{
- struct device_domain_info *info;
-
- if (likely(!iommu_identity_mapping))
- return 0;
-
- info = pdev->dev.archdata.iommu;
- if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
- return (info->domain == si_domain);
-
- return 0;
-}
-
-static int domain_add_dev_info(struct dmar_domain *domain,
- struct pci_dev *pdev,
- int translation)
-{
- struct device_domain_info *info;
- unsigned long flags;
- int ret;
-
- info = alloc_devinfo_mem();
- if (!info)
- return -ENOMEM;
-
- ret = domain_context_mapping(domain, pdev, translation);
- if (ret) {
- free_devinfo_mem(info);
- return ret;
- }
-
- info->segment = pci_domain_nr(pdev->bus);
- info->bus = pdev->bus->number;
- info->devfn = pdev->devfn;
- info->dev = pdev;
- info->domain = domain;
-
- spin_lock_irqsave(&device_domain_lock, flags);
- list_add(&info->link, &domain->devices);
- list_add(&info->global, &device_domain_list);
- pdev->dev.archdata.iommu = info;
- spin_unlock_irqrestore(&device_domain_lock, flags);
-
- return 0;
-}
-
-static bool device_has_rmrr(struct pci_dev *dev)
-{
- struct dmar_rmrr_unit *rmrr;
- int i;
-
- for_each_rmrr_units(rmrr) {
- for (i = 0; i < rmrr->devices_cnt; i++) {
- /*
- * Return TRUE if this RMRR contains the device that
- * is passed in.
- */
- if (rmrr->devices[i] == dev)
- return true;
- }
- }
- return false;
-}
-
-static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
-{
-
- /*
- * We want to prevent any device associated with an RMRR from
- * getting placed into the SI Domain. This is done because
- * problems exist when devices are moved in and out of domains
- * and their respective RMRR info is lost. We exempt USB devices
- * from this process due to their usage of RMRRs that are known
- * to not be needed after BIOS hand-off to OS.
- */
- if (device_has_rmrr(pdev) &&
- (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
- return 0;
-
- if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
- return 1;
-
- if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
- return 1;
-
- if (!(iommu_identity_mapping & IDENTMAP_ALL))
- return 0;
-
- /*
- * We want to start off with all devices in the 1:1 domain, and
- * take them out later if we find they can't access all of memory.
- *
- * However, we can't do this for PCI devices behind bridges,
- * because all PCI devices behind the same bridge will end up
- * with the same source-id on their transactions.
- *
- * Practically speaking, we can't change things around for these
- * devices at run-time, because we can't be sure there'll be no
- * DMA transactions in flight for any of their siblings.
- *
- * So PCI devices (unless they're on the root bus) as well as
- * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
- * the 1:1 domain, just in _case_ one of their siblings turns out
- * not to be able to map all of memory.
- */
- if (!pci_is_pcie(pdev)) {
- if (!pci_is_root_bus(pdev->bus))
- return 0;
- if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
- return 0;
- } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
- return 0;
-
- /*
- * At boot time, we don't yet know if devices will be 64-bit capable.
- * Assume that they will -- if they turn out not to be, then we can
- * take them out of the 1:1 domain later.
- */
- if (!startup) {
- /*
- * If the device's dma_mask is less than the system's memory
- * size then this is not a candidate for identity mapping.
- */
- u64 dma_mask = pdev->dma_mask;
-
- if (pdev->dev.coherent_dma_mask &&
- pdev->dev.coherent_dma_mask < dma_mask)
- dma_mask = pdev->dev.coherent_dma_mask;
-
- return dma_mask >= dma_get_required_mask(&pdev->dev);
- }
-
- return 1;
-}
-
-static int __init iommu_prepare_static_identity_mapping(int hw)
-{
- struct pci_dev *pdev = NULL;
- int ret;
-
- ret = si_domain_init(hw);
- if (ret)
- return -EFAULT;
-
- for_each_pci_dev(pdev) {
- /* Skip Host/PCI Bridge devices */
- if (IS_BRIDGE_HOST_DEVICE(pdev))
- continue;
- if (iommu_should_identity_map(pdev, 1)) {
- printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n",
- hw ? "hardware" : "software", pci_name(pdev));
-
- ret = domain_add_dev_info(si_domain, pdev,
- hw ? CONTEXT_TT_PASS_THROUGH :
- CONTEXT_TT_MULTI_LEVEL);
- if (ret)
- return ret;
- }
- }
-
- return 0;
-}
-
-static int __init init_dmars(void)
-{
- struct dmar_drhd_unit *drhd;
- struct dmar_rmrr_unit *rmrr;
- struct pci_dev *pdev;
- struct intel_iommu *iommu;
- int i, ret;
-
- /*
- * for each drhd
- * allocate root
- * initialize and program root entry to not present
- * endfor
- */
- for_each_drhd_unit(drhd) {
- g_num_of_iommus++;
- /*
- * lock not needed as this is only incremented in the single
- * threaded kernel __init code path all other access are read
- * only
- */
- }
-
- g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
- GFP_KERNEL);
- if (!g_iommus) {
- printk(KERN_ERR "Allocating global iommu array failed\n");
- ret = -ENOMEM;
- goto error;
- }
-
- deferred_flush = kzalloc(g_num_of_iommus *
- sizeof(struct deferred_flush_tables), GFP_KERNEL);
- if (!deferred_flush) {
- ret = -ENOMEM;
- goto error;
- }
-
- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
-
- iommu = drhd->iommu;
- g_iommus[iommu->seq_id] = iommu;
-
- ret = iommu_init_domains(iommu);
- if (ret)
- goto error;
-
- /*
- * TBD:
- * we could share the same root & context tables
- * among all IOMMU's. Need to Split it later.
- */
- ret = iommu_alloc_root_entry(iommu);
- if (ret) {
- printk(KERN_ERR "IOMMU: allocate root entry failed\n");
- goto error;
- }
- if (!ecap_pass_through(iommu->ecap))
- hw_pass_through = 0;
- }
-
- /*
- * Start from the sane iommu hardware state.
- */
- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
-
- iommu = drhd->iommu;
-
- /*
- * If the queued invalidation is already initialized by us
- * (for example, while enabling interrupt-remapping) then
- * we got the things already rolling from a sane state.
- */
- if (iommu->qi)
- continue;
-
- /*
- * Clear any previous faults.
- */
- dmar_fault(-1, iommu);
- /*
- * Disable queued invalidation if supported and already enabled
- * before OS handover.
- */
- dmar_disable_qi(iommu);
- }
-
- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
-
- iommu = drhd->iommu;
-
- if (dmar_enable_qi(iommu)) {
- /*
- * Queued Invalidate not enabled, use Register Based
- * Invalidate
- */
- iommu->flush.flush_context = __iommu_flush_context;
- iommu->flush.flush_iotlb = __iommu_flush_iotlb;
- printk(KERN_INFO "IOMMU %d 0x%Lx: using Register based "
- "invalidation\n",
- iommu->seq_id,
- (unsigned long long)drhd->reg_base_addr);
- } else {
- iommu->flush.flush_context = qi_flush_context;
- iommu->flush.flush_iotlb = qi_flush_iotlb;
- printk(KERN_INFO "IOMMU %d 0x%Lx: using Queued "
- "invalidation\n",
- iommu->seq_id,
- (unsigned long long)drhd->reg_base_addr);
- }
- }
-
- if (iommu_pass_through)
- iommu_identity_mapping |= IDENTMAP_ALL;
-
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
- iommu_identity_mapping |= IDENTMAP_GFX;
-#endif
-
- check_tylersburg_isoch();
-
- /*
- * If pass through is not set or not enabled, setup context entries for
- * identity mappings for rmrr, gfx, and isa and may fall back to static
- * identity mapping if iommu_identity_mapping is set.
- */
- if (iommu_identity_mapping) {
- ret = iommu_prepare_static_identity_mapping(hw_pass_through);
- if (ret) {
- printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
- goto error;
- }
- }
- /*
- * For each rmrr
- * for each dev attached to rmrr
- * do
- * locate drhd for dev, alloc domain for dev
- * allocate free domain
- * allocate page table entries for rmrr
- * if context not allocated for bus
- * allocate and init context
- * set present in root table for this bus
- * init context with domain, translation etc
- * endfor
- * endfor
- */
- printk(KERN_INFO "IOMMU: Setting RMRR:\n");
- for_each_rmrr_units(rmrr) {
- for (i = 0; i < rmrr->devices_cnt; i++) {
- pdev = rmrr->devices[i];
- /*
- * some BIOS lists non-exist devices in DMAR
- * table.
- */
- if (!pdev)
- continue;
- ret = iommu_prepare_rmrr_dev(rmrr, pdev);
- if (ret)
- printk(KERN_ERR
- "IOMMU: mapping reserved region failed\n");
- }
- }
-
- iommu_prepare_isa();
-
- /*
- * for each drhd
- * enable fault log
- * global invalidate context cache
- * global invalidate iotlb
- * enable translation
- */
- for_each_drhd_unit(drhd) {
- if (drhd->ignored) {
- /*
- * we always have to disable PMRs or DMA may fail on
- * this device
- */
- if (force_on)
- iommu_disable_protect_mem_regions(drhd->iommu);
- continue;
- }
- iommu = drhd->iommu;
-
- iommu_flush_write_buffer(iommu);
-
- ret = dmar_set_interrupt(iommu);
- if (ret)
- goto error;
-
- iommu_set_root_entry(iommu);
-
- iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
- ret = iommu_enable_translation(iommu);
- if (ret)
- goto error;
-
- iommu_disable_protect_mem_regions(iommu);
- }
-
- return 0;
-error:
- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
- iommu = drhd->iommu;
- free_iommu(iommu);
- }
- kfree(g_iommus);
- return ret;
-}
-
-/* This takes a number of _MM_ pages, not VTD pages */
-static struct iova *intel_alloc_iova(struct device *dev,
- struct dmar_domain *domain,
- unsigned long nrpages, uint64_t dma_mask)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct iova *iova = NULL;
-
- /* Restrict dma_mask to the width that the iommu can handle */
- dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
-
- if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
- /*
- * First try to allocate an io virtual address in
- * DMA_BIT_MASK(32) and if that fails then try allocating
- * from higher range
- */
- iova = alloc_iova(&domain->iovad, nrpages,
- IOVA_PFN(DMA_BIT_MASK(32)), 1);
- if (iova)
- return iova;
- }
- iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
- if (unlikely(!iova)) {
- printk(KERN_ERR "Allocating %ld-page iova for %s failed",
- nrpages, pci_name(pdev));
- return NULL;
- }
-
- return iova;
-}
-
-static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
-{
- struct dmar_domain *domain;
- int ret;
-
- domain = get_domain_for_dev(pdev,
- DEFAULT_DOMAIN_ADDRESS_WIDTH);
- if (!domain) {
- printk(KERN_ERR
- "Allocating domain for %s failed", pci_name(pdev));
- return NULL;
- }
-
- /* make sure context mapping is ok */
- if (unlikely(!domain_context_mapped(pdev))) {
- ret = domain_context_mapping(domain, pdev,
- CONTEXT_TT_MULTI_LEVEL);
- if (ret) {
- printk(KERN_ERR
- "Domain context map for %s failed",
- pci_name(pdev));
- return NULL;
- }
- }
-
- return domain;
-}
-
-static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev)
-{
- struct device_domain_info *info;
-
- /* No lock here, assumes no domain exit in normal case */
- info = dev->dev.archdata.iommu;
- if (likely(info))
- return info->domain;
-
- return __get_valid_domain_for_dev(dev);
-}
-
-static int iommu_dummy(struct pci_dev *pdev)
-{
- return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
-}
-
-/* Check if the pdev needs to go through non-identity map and unmap process.*/
-static int iommu_no_mapping(struct device *dev)
-{
- struct pci_dev *pdev;
- int found;
-
- if (unlikely(dev->bus != &pci_bus_type))
- return 1;
-
- pdev = to_pci_dev(dev);
- if (iommu_dummy(pdev))
- return 1;
-
- if (!iommu_identity_mapping)
- return 0;
-
- found = identity_mapping(pdev);
- if (found) {
- if (iommu_should_identity_map(pdev, 0))
- return 1;
- else {
- /*
- * 32 bit DMA is removed from si_domain and fall back
- * to non-identity mapping.
- */
- domain_remove_one_dev_info(si_domain, pdev);
- printk(KERN_INFO "32bit %s uses non-identity mapping\n",
- pci_name(pdev));
- return 0;
- }
- } else {
- /*
- * In case of a detached 64 bit DMA device from vm, the device
- * is put into si_domain for identity mapping.
- */
- if (iommu_should_identity_map(pdev, 0)) {
- int ret;
- ret = domain_add_dev_info(si_domain, pdev,
- hw_pass_through ?
- CONTEXT_TT_PASS_THROUGH :
- CONTEXT_TT_MULTI_LEVEL);
- if (!ret) {
- printk(KERN_INFO "64bit %s uses identity mapping\n",
- pci_name(pdev));
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
- size_t size, int dir, u64 dma_mask)
-{
- struct pci_dev *pdev = to_pci_dev(hwdev);
- struct dmar_domain *domain;
- phys_addr_t start_paddr;
- struct iova *iova;
- int prot = 0;
- int ret;
- struct intel_iommu *iommu;
- unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
-
- BUG_ON(dir == DMA_NONE);
-
- if (iommu_no_mapping(hwdev))
- return paddr;
-
- domain = get_valid_domain_for_dev(pdev);
- if (!domain)
- return 0;
-
- iommu = domain_get_iommu(domain);
- size = aligned_nrpages(paddr, size);
-
- iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask);
- if (!iova)
- goto error;
-
- /*
- * Check if DMAR supports zero-length reads on write only
- * mappings..
- */
- if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
- !cap_zlr(iommu->cap))
- prot |= DMA_PTE_READ;
- if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
- prot |= DMA_PTE_WRITE;
- /*
- * paddr - (paddr + size) might be partial page, we should map the whole
- * page. Note: if two part of one page are separately mapped, we
- * might have two guest_addr mapping to the same host paddr, but this
- * is not a big problem
- */
- ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
- mm_to_dma_pfn(paddr_pfn), size, prot);
- if (ret)
- goto error;
-
- /* it's a non-present to present mapping. Only flush if caching mode */
- if (cap_caching_mode(iommu->cap))
- iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 1);
- else
- iommu_flush_write_buffer(iommu);
-
- start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
- start_paddr += paddr & ~PAGE_MASK;
- return start_paddr;
-
-error:
- if (iova)
- __free_iova(&domain->iovad, iova);
- printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
- pci_name(pdev), size, (unsigned long long)paddr, dir);
- return 0;
-}
-
-static dma_addr_t intel_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- struct dma_attrs *attrs)
-{
- return __intel_map_single(dev, page_to_phys(page) + offset, size,
- dir, to_pci_dev(dev)->dma_mask);
-}
-
-static void flush_unmaps(void)
-{
- int i, j;
-
- timer_on = 0;
-
- /* just flush them all */
- for (i = 0; i < g_num_of_iommus; i++) {
- struct intel_iommu *iommu = g_iommus[i];
- if (!iommu)
- continue;
-
- if (!deferred_flush[i].next)
- continue;
-
- /* In caching mode, global flushes turn emulation expensive */
- if (!cap_caching_mode(iommu->cap))
- iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH);
- for (j = 0; j < deferred_flush[i].next; j++) {
- unsigned long mask;
- struct iova *iova = deferred_flush[i].iova[j];
- struct dmar_domain *domain = deferred_flush[i].domain[j];
-
- /* On real hardware multiple invalidations are expensive */
- if (cap_caching_mode(iommu->cap))
- iommu_flush_iotlb_psi(iommu, domain->id,
- iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1, 0);
- else {
- mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
- iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
- (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
- }
- __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
- }
- deferred_flush[i].next = 0;
- }
-
- list_size = 0;
-}
-
-static void flush_unmaps_timeout(unsigned long data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&async_umap_flush_lock, flags);
- flush_unmaps();
- spin_unlock_irqrestore(&async_umap_flush_lock, flags);
-}
-
-static void add_unmap(struct dmar_domain *dom, struct iova *iova)
-{
- unsigned long flags;
- int next, iommu_id;
- struct intel_iommu *iommu;
-
- spin_lock_irqsave(&async_umap_flush_lock, flags);
- if (list_size == HIGH_WATER_MARK)
- flush_unmaps();
-
- iommu = domain_get_iommu(dom);
- iommu_id = iommu->seq_id;
-
- next = deferred_flush[iommu_id].next;
- deferred_flush[iommu_id].domain[next] = dom;
- deferred_flush[iommu_id].iova[next] = iova;
- deferred_flush[iommu_id].next++;
-
- if (!timer_on) {
- mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
- timer_on = 1;
- }
- list_size++;
- spin_unlock_irqrestore(&async_umap_flush_lock, flags);
-}
-
-static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct dmar_domain *domain;
- unsigned long start_pfn, last_pfn;
- struct iova *iova;
- struct intel_iommu *iommu;
-
- if (iommu_no_mapping(dev))
- return;
-
- domain = find_domain(pdev);
- BUG_ON(!domain);
-
- iommu = domain_get_iommu(domain);
-
- iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
- if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
- (unsigned long long)dev_addr))
- return;
-
- start_pfn = mm_to_dma_pfn(iova->pfn_lo);
- last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
-
- pr_debug("Device %s unmapping: pfn %lx-%lx\n",
- pci_name(pdev), start_pfn, last_pfn);
-
- /* clear the whole page */
- dma_pte_clear_range(domain, start_pfn, last_pfn);
-
- /* free page tables */
- dma_pte_free_pagetable(domain, start_pfn, last_pfn);
-
- if (intel_iommu_strict) {
- iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
- last_pfn - start_pfn + 1, 0);
- /* free iova */
- __free_iova(&domain->iovad, iova);
- } else {
- add_unmap(domain, iova);
- /*
- * queue up the release of the unmap to save the 1/6th of the
- * cpu used up by the iotlb flush operation...
- */
- }
-}
-
-static void *intel_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags)
-{
- void *vaddr;
- int order;
-
- size = PAGE_ALIGN(size);
- order = get_order(size);
-
- if (!iommu_no_mapping(hwdev))
- flags &= ~(GFP_DMA | GFP_DMA32);
- else if (hwdev->coherent_dma_mask < dma_get_required_mask(hwdev)) {
- if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32))
- flags |= GFP_DMA;
- else
- flags |= GFP_DMA32;
- }
-
- vaddr = (void *)__get_free_pages(flags, order);
- if (!vaddr)
- return NULL;
- memset(vaddr, 0, size);
-
- *dma_handle = __intel_map_single(hwdev, virt_to_bus(vaddr), size,
- DMA_BIDIRECTIONAL,
- hwdev->coherent_dma_mask);
- if (*dma_handle)
- return vaddr;
- free_pages((unsigned long)vaddr, order);
- return NULL;
-}
-
-static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
-{
- int order;
-
- size = PAGE_ALIGN(size);
- order = get_order(size);
-
- intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
- free_pages((unsigned long)vaddr, order);
-}
-
-static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
-{
- struct pci_dev *pdev = to_pci_dev(hwdev);
- struct dmar_domain *domain;
- unsigned long start_pfn, last_pfn;
- struct iova *iova;
- struct intel_iommu *iommu;
-
- if (iommu_no_mapping(hwdev))
- return;
-
- domain = find_domain(pdev);
- BUG_ON(!domain);
-
- iommu = domain_get_iommu(domain);
-
- iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
- if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
- (unsigned long long)sglist[0].dma_address))
- return;
-
- start_pfn = mm_to_dma_pfn(iova->pfn_lo);
- last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
-
- /* clear the whole page */
- dma_pte_clear_range(domain, start_pfn, last_pfn);
-
- /* free page tables */
- dma_pte_free_pagetable(domain, start_pfn, last_pfn);
-
- if (intel_iommu_strict) {
- iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
- last_pfn - start_pfn + 1, 0);
- /* free iova */
- __free_iova(&domain->iovad, iova);
- } else {
- add_unmap(domain, iova);
- /*
- * queue up the release of the unmap to save the 1/6th of the
- * cpu used up by the iotlb flush operation...
- */
- }
-}
-
-static int intel_nontranslate_map_sg(struct device *hddev,
- struct scatterlist *sglist, int nelems, int dir)
-{
- int i;
- struct scatterlist *sg;
-
- for_each_sg(sglist, sg, nelems, i) {
- BUG_ON(!sg_page(sg));
- sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
- sg->dma_length = sg->length;
- }
- return nelems;
-}
-
-static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
- enum dma_data_direction dir, struct dma_attrs *attrs)
-{
- int i;
- struct pci_dev *pdev = to_pci_dev(hwdev);
- struct dmar_domain *domain;
- size_t size = 0;
- int prot = 0;
- struct iova *iova = NULL;
- int ret;
- struct scatterlist *sg;
- unsigned long start_vpfn;
- struct intel_iommu *iommu;
-
- BUG_ON(dir == DMA_NONE);
- if (iommu_no_mapping(hwdev))
- return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
-
- domain = get_valid_domain_for_dev(pdev);
- if (!domain)
- return 0;
-
- iommu = domain_get_iommu(domain);
-
- for_each_sg(sglist, sg, nelems, i)
- size += aligned_nrpages(sg->offset, sg->length);
-
- iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
- pdev->dma_mask);
- if (!iova) {
- sglist->dma_length = 0;
- return 0;
- }
-
- /*
- * Check if DMAR supports zero-length reads on write only
- * mappings..
- */
- if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
- !cap_zlr(iommu->cap))
- prot |= DMA_PTE_READ;
- if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
- prot |= DMA_PTE_WRITE;
-
- start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
-
- ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
- if (unlikely(ret)) {
- /* clear the page */
- dma_pte_clear_range(domain, start_vpfn,
- start_vpfn + size - 1);
- /* free page tables */
- dma_pte_free_pagetable(domain, start_vpfn,
- start_vpfn + size - 1);
- /* free iova */
- __free_iova(&domain->iovad, iova);
- return 0;
- }
-
- /* it's a non-present to present mapping. Only flush if caching mode */
- if (cap_caching_mode(iommu->cap))
- iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 1);
- else
- iommu_flush_write_buffer(iommu);
-
- return nelems;
-}
-
-static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
- return !dma_addr;
-}
-
-struct dma_map_ops intel_dma_ops = {
- .alloc_coherent = intel_alloc_coherent,
- .free_coherent = intel_free_coherent,
- .map_sg = intel_map_sg,
- .unmap_sg = intel_unmap_sg,
- .map_page = intel_map_page,
- .unmap_page = intel_unmap_page,
- .mapping_error = intel_mapping_error,
-};
-
-static inline int iommu_domain_cache_init(void)
-{
- int ret = 0;
-
- iommu_domain_cache = kmem_cache_create("iommu_domain",
- sizeof(struct dmar_domain),
- 0,
- SLAB_HWCACHE_ALIGN,
-
- NULL);
- if (!iommu_domain_cache) {
- printk(KERN_ERR "Couldn't create iommu_domain cache\n");
- ret = -ENOMEM;
- }
-
- return ret;
-}
-
-static inline int iommu_devinfo_cache_init(void)
-{
- int ret = 0;
-
- iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
- sizeof(struct device_domain_info),
- 0,
- SLAB_HWCACHE_ALIGN,
- NULL);
- if (!iommu_devinfo_cache) {
- printk(KERN_ERR "Couldn't create devinfo cache\n");
- ret = -ENOMEM;
- }
-
- return ret;
-}
-
-static inline int iommu_iova_cache_init(void)
-{
- int ret = 0;
-
- iommu_iova_cache = kmem_cache_create("iommu_iova",
- sizeof(struct iova),
- 0,
- SLAB_HWCACHE_ALIGN,
- NULL);
- if (!iommu_iova_cache) {
- printk(KERN_ERR "Couldn't create iova cache\n");
- ret = -ENOMEM;
- }
-
- return ret;
-}
-
-static int __init iommu_init_mempool(void)
-{
- int ret;
- ret = iommu_iova_cache_init();
- if (ret)
- return ret;
-
- ret = iommu_domain_cache_init();
- if (ret)
- goto domain_error;
-
- ret = iommu_devinfo_cache_init();
- if (!ret)
- return ret;
-
- kmem_cache_destroy(iommu_domain_cache);
-domain_error:
- kmem_cache_destroy(iommu_iova_cache);
-
- return -ENOMEM;
-}
-
-static void __init iommu_exit_mempool(void)
-{
- kmem_cache_destroy(iommu_devinfo_cache);
- kmem_cache_destroy(iommu_domain_cache);
- kmem_cache_destroy(iommu_iova_cache);
-
-}
-
-static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
-{
- struct dmar_drhd_unit *drhd;
- u32 vtbar;
- int rc;
-
- /* We know that this device on this chipset has its own IOMMU.
- * If we find it under a different IOMMU, then the BIOS is lying
- * to us. Hope that the IOMMU for this device is actually
- * disabled, and it needs no translation...
- */
- rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
- if (rc) {
- /* "can't" happen */
- dev_info(&pdev->dev, "failed to run vt-d quirk\n");
- return;
- }
- vtbar &= 0xffff0000;
-
- /* we know that the this iommu should be at offset 0xa000 from vtbar */
- drhd = dmar_find_matched_drhd_unit(pdev);
- if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
- TAINT_FIRMWARE_WORKAROUND,
- "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
- pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
-}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
-
-static void __init init_no_remapping_devices(void)
-{
- struct dmar_drhd_unit *drhd;
-
- for_each_drhd_unit(drhd) {
- if (!drhd->include_all) {
- int i;
- for (i = 0; i < drhd->devices_cnt; i++)
- if (drhd->devices[i] != NULL)
- break;
- /* ignore DMAR unit if no pci devices exist */
- if (i == drhd->devices_cnt)
- drhd->ignored = 1;
- }
- }
-
- if (dmar_map_gfx)
- return;
-
- for_each_drhd_unit(drhd) {
- int i;
- if (drhd->ignored || drhd->include_all)
- continue;
-
- for (i = 0; i < drhd->devices_cnt; i++)
- if (drhd->devices[i] &&
- !IS_GFX_DEVICE(drhd->devices[i]))
- break;
-
- if (i < drhd->devices_cnt)
- continue;
-
- /* bypass IOMMU if it is just for gfx devices */
- drhd->ignored = 1;
- for (i = 0; i < drhd->devices_cnt; i++) {
- if (!drhd->devices[i])
- continue;
- drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
- }
- }
-}
-
-#ifdef CONFIG_SUSPEND
-static int init_iommu_hw(void)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu = NULL;
-
- for_each_active_iommu(iommu, drhd)
- if (iommu->qi)
- dmar_reenable_qi(iommu);
-
- for_each_iommu(iommu, drhd) {
- if (drhd->ignored) {
- /*
- * we always have to disable PMRs or DMA may fail on
- * this device
- */
- if (force_on)
- iommu_disable_protect_mem_regions(iommu);
- continue;
- }
-
- iommu_flush_write_buffer(iommu);
-
- iommu_set_root_entry(iommu);
-
- iommu->flush.flush_context(iommu, 0, 0, 0,
- DMA_CCMD_GLOBAL_INVL);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH);
- if (iommu_enable_translation(iommu))
- return 1;
- iommu_disable_protect_mem_regions(iommu);
- }
-
- return 0;
-}
-
-static void iommu_flush_all(void)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu;
-
- for_each_active_iommu(iommu, drhd) {
- iommu->flush.flush_context(iommu, 0, 0, 0,
- DMA_CCMD_GLOBAL_INVL);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH);
- }
-}
-
-static int iommu_suspend(void)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu = NULL;
- unsigned long flag;
-
- for_each_active_iommu(iommu, drhd) {
- iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
- GFP_ATOMIC);
- if (!iommu->iommu_state)
- goto nomem;
- }
-
- iommu_flush_all();
-
- for_each_active_iommu(iommu, drhd) {
- iommu_disable_translation(iommu);
-
- spin_lock_irqsave(&iommu->register_lock, flag);
-
- iommu->iommu_state[SR_DMAR_FECTL_REG] =
- readl(iommu->reg + DMAR_FECTL_REG);
- iommu->iommu_state[SR_DMAR_FEDATA_REG] =
- readl(iommu->reg + DMAR_FEDATA_REG);
- iommu->iommu_state[SR_DMAR_FEADDR_REG] =
- readl(iommu->reg + DMAR_FEADDR_REG);
- iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
- readl(iommu->reg + DMAR_FEUADDR_REG);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
- }
- return 0;
-
-nomem:
- for_each_active_iommu(iommu, drhd)
- kfree(iommu->iommu_state);
-
- return -ENOMEM;
-}
-
-static void iommu_resume(void)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu = NULL;
- unsigned long flag;
-
- if (init_iommu_hw()) {
- if (force_on)
- panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
- else
- WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
- return;
- }
-
- for_each_active_iommu(iommu, drhd) {
-
- spin_lock_irqsave(&iommu->register_lock, flag);
-
- writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
- iommu->reg + DMAR_FECTL_REG);
- writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
- iommu->reg + DMAR_FEDATA_REG);
- writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
- iommu->reg + DMAR_FEADDR_REG);
- writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
- iommu->reg + DMAR_FEUADDR_REG);
-
- spin_unlock_irqrestore(&iommu->register_lock, flag);
- }
-
- for_each_active_iommu(iommu, drhd)
- kfree(iommu->iommu_state);
-}
-
-static struct syscore_ops iommu_syscore_ops = {
- .resume = iommu_resume,
- .suspend = iommu_suspend,
-};
-
-static void __init init_iommu_pm_ops(void)
-{
- register_syscore_ops(&iommu_syscore_ops);
-}
-
-#else
-static inline void init_iommu_pm_ops(void) {}
-#endif /* CONFIG_PM */
-
-/*
- * Here we only respond to action of unbound device from driver.
- *
- * Added device is not attached to its DMAR domain here yet. That will happen
- * when mapping the device to iova.
- */
-static int device_notifier(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct device *dev = data;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct dmar_domain *domain;
-
- if (iommu_no_mapping(dev))
- return 0;
-
- domain = find_domain(pdev);
- if (!domain)
- return 0;
-
- if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
- domain_remove_one_dev_info(domain, pdev);
-
- if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
- !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
- list_empty(&domain->devices))
- domain_exit(domain);
- }
-
- return 0;
-}
-
-static struct notifier_block device_nb = {
- .notifier_call = device_notifier,
-};
-
-int __init intel_iommu_init(void)
-{
- int ret = 0;
-
- /* VT-d is required for a TXT/tboot launch, so enforce that */
- force_on = tboot_force_iommu();
-
- if (dmar_table_init()) {
- if (force_on)
- panic("tboot: Failed to initialize DMAR table\n");
- return -ENODEV;
- }
-
- if (dmar_dev_scope_init()) {
- if (force_on)
- panic("tboot: Failed to initialize DMAR device scope\n");
- return -ENODEV;
- }
-
- /*
- * Check the need for DMA-remapping initialization now.
- * Above initialization will also be used by Interrupt-remapping.
- */
- if (no_iommu || dmar_disabled)
- return -ENODEV;
-
- if (iommu_init_mempool()) {
- if (force_on)
- panic("tboot: Failed to initialize iommu memory\n");
- return -ENODEV;
- }
-
- if (dmar_init_reserved_ranges()) {
- if (force_on)
- panic("tboot: Failed to reserve iommu ranges\n");
- return -ENODEV;
- }
-
- init_no_remapping_devices();
-
- ret = init_dmars();
- if (ret) {
- if (force_on)
- panic("tboot: Failed to initialize DMARs\n");
- printk(KERN_ERR "IOMMU: dmar init failed\n");
- put_iova_domain(&reserved_iova_list);
- iommu_exit_mempool();
- return ret;
- }
- printk(KERN_INFO
- "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
-
- init_timer(&unmap_timer);
-#ifdef CONFIG_SWIOTLB
- swiotlb = 0;
-#endif
- dma_ops = &intel_dma_ops;
-
- init_iommu_pm_ops();
-
- register_iommu(&intel_iommu_ops);
-
- bus_register_notifier(&pci_bus_type, &device_nb);
-
- return 0;
-}
-
-static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
- struct pci_dev *pdev)
-{
- struct pci_dev *tmp, *parent;
-
- if (!iommu || !pdev)
- return;
-
- /* dependent device detach */
- tmp = pci_find_upstream_pcie_bridge(pdev);
- /* Secondary interface's bus number and devfn 0 */
- if (tmp) {
- parent = pdev->bus->self;
- while (parent != tmp) {
- iommu_detach_dev(iommu, parent->bus->number,
- parent->devfn);
- parent = parent->bus->self;
- }
- if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
- iommu_detach_dev(iommu,
- tmp->subordinate->number, 0);
- else /* this is a legacy PCI bridge */
- iommu_detach_dev(iommu, tmp->bus->number,
- tmp->devfn);
- }
-}
-
-static void domain_remove_one_dev_info(struct dmar_domain *domain,
- struct pci_dev *pdev)
-{
- struct device_domain_info *info;
- struct intel_iommu *iommu;
- unsigned long flags;
- int found = 0;
- struct list_head *entry, *tmp;
-
- iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
- pdev->devfn);
- if (!iommu)
- return;
-
- spin_lock_irqsave(&device_domain_lock, flags);
- list_for_each_safe(entry, tmp, &domain->devices) {
- info = list_entry(entry, struct device_domain_info, link);
- if (info->segment == pci_domain_nr(pdev->bus) &&
- info->bus == pdev->bus->number &&
- info->devfn == pdev->devfn) {
- list_del(&info->link);
- list_del(&info->global);
- if (info->dev)
- info->dev->dev.archdata.iommu = NULL;
- spin_unlock_irqrestore(&device_domain_lock, flags);
-
- iommu_disable_dev_iotlb(info);
- iommu_detach_dev(iommu, info->bus, info->devfn);
- iommu_detach_dependent_devices(iommu, pdev);
- free_devinfo_mem(info);
-
- spin_lock_irqsave(&device_domain_lock, flags);
-
- if (found)
- break;
- else
- continue;
- }
-
- /* if there is no other devices under the same iommu
- * owned by this domain, clear this iommu in iommu_bmp
- * update iommu count and coherency
- */
- if (iommu == device_to_iommu(info->segment, info->bus,
- info->devfn))
- found = 1;
- }
-
- spin_unlock_irqrestore(&device_domain_lock, flags);
-
- if (found == 0) {
- unsigned long tmp_flags;
- spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
- clear_bit(iommu->seq_id, &domain->iommu_bmp);
- domain->iommu_count--;
- domain_update_iommu_cap(domain);
- spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
-
- if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
- !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
- spin_lock_irqsave(&iommu->lock, tmp_flags);
- clear_bit(domain->id, iommu->domain_ids);
- iommu->domains[domain->id] = NULL;
- spin_unlock_irqrestore(&iommu->lock, tmp_flags);
- }
- }
-}
-
-static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
-{
- struct device_domain_info *info;
- struct intel_iommu *iommu;
- unsigned long flags1, flags2;
-
- spin_lock_irqsave(&device_domain_lock, flags1);
- while (!list_empty(&domain->devices)) {
- info = list_entry(domain->devices.next,
- struct device_domain_info, link);
- list_del(&info->link);
- list_del(&info->global);
- if (info->dev)
- info->dev->dev.archdata.iommu = NULL;
-
- spin_unlock_irqrestore(&device_domain_lock, flags1);
-
- iommu_disable_dev_iotlb(info);
- iommu = device_to_iommu(info->segment, info->bus, info->devfn);
- iommu_detach_dev(iommu, info->bus, info->devfn);
- iommu_detach_dependent_devices(iommu, info->dev);
-
- /* clear this iommu in iommu_bmp, update iommu count
- * and capabilities
- */
- spin_lock_irqsave(&domain->iommu_lock, flags2);
- if (test_and_clear_bit(iommu->seq_id,
- &domain->iommu_bmp)) {
- domain->iommu_count--;
- domain_update_iommu_cap(domain);
- }
- spin_unlock_irqrestore(&domain->iommu_lock, flags2);
-
- free_devinfo_mem(info);
- spin_lock_irqsave(&device_domain_lock, flags1);
- }
- spin_unlock_irqrestore(&device_domain_lock, flags1);
-}
-
-/* domain id for virtual machine, it won't be set in context */
-static unsigned long vm_domid;
-
-static struct dmar_domain *iommu_alloc_vm_domain(void)
-{
- struct dmar_domain *domain;
-
- domain = alloc_domain_mem();
- if (!domain)
- return NULL;
-
- domain->id = vm_domid++;
- domain->nid = -1;
- memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
- domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
-
- return domain;
-}
-
-static int md_domain_init(struct dmar_domain *domain, int guest_width)
-{
- int adjust_width;
-
- init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
- spin_lock_init(&domain->iommu_lock);
-
- domain_reserve_special_ranges(domain);
-
- /* calculate AGAW */
- domain->gaw = guest_width;
- adjust_width = guestwidth_to_adjustwidth(guest_width);
- domain->agaw = width_to_agaw(adjust_width);
-
- INIT_LIST_HEAD(&domain->devices);
-
- domain->iommu_count = 0;
- domain->iommu_coherency = 0;
- domain->iommu_snooping = 0;
- domain->iommu_superpage = 0;
- domain->max_addr = 0;
- domain->nid = -1;
-
- /* always allocate the top pgd */
- domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
- if (!domain->pgd)
- return -ENOMEM;
- domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
- return 0;
-}
-
-static void iommu_free_vm_domain(struct dmar_domain *domain)
-{
- unsigned long flags;
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu;
- unsigned long i;
- unsigned long ndomains;
-
- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
- iommu = drhd->iommu;
-
- ndomains = cap_ndoms(iommu->cap);
- for_each_set_bit(i, iommu->domain_ids, ndomains) {
- if (iommu->domains[i] == domain) {
- spin_lock_irqsave(&iommu->lock, flags);
- clear_bit(i, iommu->domain_ids);
- iommu->domains[i] = NULL;
- spin_unlock_irqrestore(&iommu->lock, flags);
- break;
- }
- }
- }
-}
-
-static void vm_domain_exit(struct dmar_domain *domain)
-{
- /* Domain 0 is reserved, so dont process it */
- if (!domain)
- return;
-
- vm_domain_remove_all_dev_info(domain);
- /* destroy iovas */
- put_iova_domain(&domain->iovad);
-
- /* clear ptes */
- dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
- /* free page tables */
- dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
- iommu_free_vm_domain(domain);
- free_domain_mem(domain);
-}
-
-static int intel_iommu_domain_init(struct iommu_domain *domain)
-{
- struct dmar_domain *dmar_domain;
-
- dmar_domain = iommu_alloc_vm_domain();
- if (!dmar_domain) {
- printk(KERN_ERR
- "intel_iommu_domain_init: dmar_domain == NULL\n");
- return -ENOMEM;
- }
- if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
- printk(KERN_ERR
- "intel_iommu_domain_init() failed\n");
- vm_domain_exit(dmar_domain);
- return -ENOMEM;
- }
- domain_update_iommu_cap(dmar_domain);
- domain->priv = dmar_domain;
-
- return 0;
-}
-
-static void intel_iommu_domain_destroy(struct iommu_domain *domain)
-{
- struct dmar_domain *dmar_domain = domain->priv;
-
- domain->priv = NULL;
- vm_domain_exit(dmar_domain);
-}
-
-static int intel_iommu_attach_device(struct iommu_domain *domain,
- struct device *dev)
-{
- struct dmar_domain *dmar_domain = domain->priv;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct intel_iommu *iommu;
- int addr_width;
-
- /* normally pdev is not mapped */
- if (unlikely(domain_context_mapped(pdev))) {
- struct dmar_domain *old_domain;
-
- old_domain = find_domain(pdev);
- if (old_domain) {
- if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
- dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
- domain_remove_one_dev_info(old_domain, pdev);
- else
- domain_remove_dev_info(old_domain);
- }
- }
-
- iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
- pdev->devfn);
- if (!iommu)
- return -ENODEV;
-
- /* check if this iommu agaw is sufficient for max mapped address */
- addr_width = agaw_to_width(iommu->agaw);
- if (addr_width > cap_mgaw(iommu->cap))
- addr_width = cap_mgaw(iommu->cap);
-
- if (dmar_domain->max_addr > (1LL << addr_width)) {
- printk(KERN_ERR "%s: iommu width (%d) is not "
- "sufficient for the mapped address (%llx)\n",
- __func__, addr_width, dmar_domain->max_addr);
- return -EFAULT;
- }
- dmar_domain->gaw = addr_width;
-
- /*
- * Knock out extra levels of page tables if necessary
- */
- while (iommu->agaw < dmar_domain->agaw) {
- struct dma_pte *pte;
-
- pte = dmar_domain->pgd;
- if (dma_pte_present(pte)) {
- dmar_domain->pgd = (struct dma_pte *)
- phys_to_virt(dma_pte_addr(pte));
- free_pgtable_page(pte);
- }
- dmar_domain->agaw--;
- }
-
- return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
-}
-
-static void intel_iommu_detach_device(struct iommu_domain *domain,
- struct device *dev)
-{
- struct dmar_domain *dmar_domain = domain->priv;
- struct pci_dev *pdev = to_pci_dev(dev);
-
- domain_remove_one_dev_info(dmar_domain, pdev);
-}
-
-static int intel_iommu_map(struct iommu_domain *domain,
- unsigned long iova, phys_addr_t hpa,
- int gfp_order, int iommu_prot)
-{
- struct dmar_domain *dmar_domain = domain->priv;
- u64 max_addr;
- int prot = 0;
- size_t size;
- int ret;
-
- if (iommu_prot & IOMMU_READ)
- prot |= DMA_PTE_READ;
- if (iommu_prot & IOMMU_WRITE)
- prot |= DMA_PTE_WRITE;
- if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
- prot |= DMA_PTE_SNP;
-
- size = PAGE_SIZE << gfp_order;
- max_addr = iova + size;
- if (dmar_domain->max_addr < max_addr) {
- u64 end;
-
- /* check if minimum agaw is sufficient for mapped address */
- end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
- if (end < max_addr) {
- printk(KERN_ERR "%s: iommu width (%d) is not "
- "sufficient for the mapped address (%llx)\n",
- __func__, dmar_domain->gaw, max_addr);
- return -EFAULT;
- }
- dmar_domain->max_addr = max_addr;
- }
- /* Round up size to next multiple of PAGE_SIZE, if it and
- the low bits of hpa would take us onto the next page */
- size = aligned_nrpages(hpa, size);
- ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
- hpa >> VTD_PAGE_SHIFT, size, prot);
- return ret;
-}
-
-static int intel_iommu_unmap(struct iommu_domain *domain,
- unsigned long iova, int gfp_order)
-{
- struct dmar_domain *dmar_domain = domain->priv;
- size_t size = PAGE_SIZE << gfp_order;
- int order;
-
- order = dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
- (iova + size - 1) >> VTD_PAGE_SHIFT);
-
- if (dmar_domain->max_addr == iova + size)
- dmar_domain->max_addr = iova;
-
- return order;
-}
-
-static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
- unsigned long iova)
-{
- struct dmar_domain *dmar_domain = domain->priv;
- struct dma_pte *pte;
- u64 phys = 0;
-
- pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, 0);
- if (pte)
- phys = dma_pte_addr(pte);
-
- return phys;
-}
-
-static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
- unsigned long cap)
-{
- struct dmar_domain *dmar_domain = domain->priv;
-
- if (cap == IOMMU_CAP_CACHE_COHERENCY)
- return dmar_domain->iommu_snooping;
- if (cap == IOMMU_CAP_INTR_REMAP)
- return intr_remapping_enabled;
-
- return 0;
-}
-
-static struct iommu_ops intel_iommu_ops = {
- .domain_init = intel_iommu_domain_init,
- .domain_destroy = intel_iommu_domain_destroy,
- .attach_dev = intel_iommu_attach_device,
- .detach_dev = intel_iommu_detach_device,
- .map = intel_iommu_map,
- .unmap = intel_iommu_unmap,
- .iova_to_phys = intel_iommu_iova_to_phys,
- .domain_has_cap = intel_iommu_domain_has_cap,
-};
-
-static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
-{
- /*
- * Mobile 4 Series Chipset neglects to set RWBF capability,
- * but needs it:
- */
- printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
- rwbf_quirk = 1;
-
- /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
- if (dev->revision == 0x07) {
- printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
- dmar_map_gfx = 0;
- }
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
-
-#define GGC 0x52
-#define GGC_MEMORY_SIZE_MASK (0xf << 8)
-#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
-#define GGC_MEMORY_SIZE_1M (0x1 << 8)
-#define GGC_MEMORY_SIZE_2M (0x3 << 8)
-#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
-#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
-#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
-#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
-
-static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
-{
- unsigned short ggc;
-
- if (pci_read_config_word(dev, GGC, &ggc))
- return;
-
- if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
- printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
- dmar_map_gfx = 0;
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
-
-/* On Tylersburg chipsets, some BIOSes have been known to enable the
- ISOCH DMAR unit for the Azalia sound device, but not give it any
- TLB entries, which causes it to deadlock. Check for that. We do
- this in a function called from init_dmars(), instead of in a PCI
- quirk, because we don't want to print the obnoxious "BIOS broken"
- message if VT-d is actually disabled.
-*/
-static void __init check_tylersburg_isoch(void)
-{
- struct pci_dev *pdev;
- uint32_t vtisochctrl;
-
- /* If there's no Azalia in the system anyway, forget it. */
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
- if (!pdev)
- return;
- pci_dev_put(pdev);
-
- /* System Management Registers. Might be hidden, in which case
- we can't do the sanity check. But that's OK, because the
- known-broken BIOSes _don't_ actually hide it, so far. */
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
- if (!pdev)
- return;
-
- if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
- pci_dev_put(pdev);
- return;
- }
-
- pci_dev_put(pdev);
-
- /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
- if (vtisochctrl & 1)
- return;
-
- /* Drop all bits other than the number of TLB entries */
- vtisochctrl &= 0x1c;
-
- /* If we have the recommended number of TLB entries (16), fine. */
- if (vtisochctrl == 0x10)
- return;
-
- /* Zero TLB entries? You get to ride the short bus to school. */
- if (!vtisochctrl) {
- WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
- "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
- dmi_get_system_info(DMI_BIOS_VENDOR),
- dmi_get_system_info(DMI_BIOS_VERSION),
- dmi_get_system_info(DMI_PRODUCT_VERSION));
- iommu_identity_mapping |= IDENTMAP_AZALIA;
- return;
- }
-
- printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
- vtisochctrl);
-}
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
deleted file mode 100644
index 3607faf..0000000
--- a/drivers/pci/intr_remapping.c
+++ /dev/null
@@ -1,798 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/dmar.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/hpet.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <asm/io_apic.h>
-#include <asm/smp.h>
-#include <asm/cpu.h>
-#include <linux/intel-iommu.h>
-#include "intr_remapping.h"
-#include <acpi/acpi.h>
-#include <asm/pci-direct.h>
-#include "pci.h"
-
-static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
-static struct hpet_scope ir_hpet[MAX_HPET_TBS];
-static int ir_ioapic_num, ir_hpet_num;
-int intr_remapping_enabled;
-
-static int disable_intremap;
-static int disable_sourceid_checking;
-
-static __init int setup_nointremap(char *str)
-{
- disable_intremap = 1;
- return 0;
-}
-early_param("nointremap", setup_nointremap);
-
-static __init int setup_intremap(char *str)
-{
- if (!str)
- return -EINVAL;
-
- if (!strncmp(str, "on", 2))
- disable_intremap = 0;
- else if (!strncmp(str, "off", 3))
- disable_intremap = 1;
- else if (!strncmp(str, "nosid", 5))
- disable_sourceid_checking = 1;
-
- return 0;
-}
-early_param("intremap", setup_intremap);
-
-static DEFINE_SPINLOCK(irq_2_ir_lock);
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
- return cfg ? &cfg->irq_2_iommu : NULL;
-}
-
-int get_irte(int irq, struct irte *entry)
-{
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- unsigned long flags;
- int index;
-
- if (!entry || !irq_iommu)
- return -1;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- index = irq_iommu->irte_index + irq_iommu->sub_handle;
- *entry = *(irq_iommu->iommu->ir_table->base + index);
-
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return 0;
-}
-
-int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
-{
- struct ir_table *table = iommu->ir_table;
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- u16 index, start_index;
- unsigned int mask = 0;
- unsigned long flags;
- int i;
-
- if (!count || !irq_iommu)
- return -1;
-
- /*
- * start the IRTE search from index 0.
- */
- index = start_index = 0;
-
- if (count > 1) {
- count = __roundup_pow_of_two(count);
- mask = ilog2(count);
- }
-
- if (mask > ecap_max_handle_mask(iommu->ecap)) {
- printk(KERN_ERR
- "Requested mask %x exceeds the max invalidation handle"
- " mask value %Lx\n", mask,
- ecap_max_handle_mask(iommu->ecap));
- return -1;
- }
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- do {
- for (i = index; i < index + count; i++)
- if (table->base[i].present)
- break;
- /* empty index found */
- if (i == index + count)
- break;
-
- index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
-
- if (index == start_index) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate an IRTE\n");
- return -1;
- }
- } while (1);
-
- for (i = index; i < index + count; i++)
- table->base[i].present = 1;
-
- irq_iommu->iommu = iommu;
- irq_iommu->irte_index = index;
- irq_iommu->sub_handle = 0;
- irq_iommu->irte_mask = mask;
-
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return index;
-}
-
-static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
-{
- struct qi_desc desc;
-
- desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask)
- | QI_IEC_SELECTIVE;
- desc.high = 0;
-
- return qi_submit_sync(&desc, iommu);
-}
-
-int map_irq_to_irte_handle(int irq, u16 *sub_handle)
-{
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- unsigned long flags;
- int index;
-
- if (!irq_iommu)
- return -1;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- *sub_handle = irq_iommu->sub_handle;
- index = irq_iommu->irte_index;
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return index;
-}
-
-int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
-{
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- unsigned long flags;
-
- if (!irq_iommu)
- return -1;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- irq_iommu->iommu = iommu;
- irq_iommu->irte_index = index;
- irq_iommu->sub_handle = subhandle;
- irq_iommu->irte_mask = 0;
-
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return 0;
-}
-
-int modify_irte(int irq, struct irte *irte_modified)
-{
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- struct intel_iommu *iommu;
- unsigned long flags;
- struct irte *irte;
- int rc, index;
-
- if (!irq_iommu)
- return -1;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- iommu = irq_iommu->iommu;
-
- index = irq_iommu->irte_index + irq_iommu->sub_handle;
- irte = &iommu->ir_table->base[index];
-
- set_64bit(&irte->low, irte_modified->low);
- set_64bit(&irte->high, irte_modified->high);
- __iommu_flush_cache(iommu, irte, sizeof(*irte));
-
- rc = qi_flush_iec(iommu, index, 0);
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return rc;
-}
-
-struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
-{
- int i;
-
- for (i = 0; i < MAX_HPET_TBS; i++)
- if (ir_hpet[i].id == hpet_id)
- return ir_hpet[i].iommu;
- return NULL;
-}
-
-struct intel_iommu *map_ioapic_to_ir(int apic)
-{
- int i;
-
- for (i = 0; i < MAX_IO_APICS; i++)
- if (ir_ioapic[i].id == apic)
- return ir_ioapic[i].iommu;
- return NULL;
-}
-
-struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
-{
- struct dmar_drhd_unit *drhd;
-
- drhd = dmar_find_matched_drhd_unit(dev);
- if (!drhd)
- return NULL;
-
- return drhd->iommu;
-}
-
-static int clear_entries(struct irq_2_iommu *irq_iommu)
-{
- struct irte *start, *entry, *end;
- struct intel_iommu *iommu;
- int index;
-
- if (irq_iommu->sub_handle)
- return 0;
-
- iommu = irq_iommu->iommu;
- index = irq_iommu->irte_index + irq_iommu->sub_handle;
-
- start = iommu->ir_table->base + index;
- end = start + (1 << irq_iommu->irte_mask);
-
- for (entry = start; entry < end; entry++) {
- set_64bit(&entry->low, 0);
- set_64bit(&entry->high, 0);
- }
-
- return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
-}
-
-int free_irte(int irq)
-{
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- unsigned long flags;
- int rc;
-
- if (!irq_iommu)
- return -1;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- rc = clear_entries(irq_iommu);
-
- irq_iommu->iommu = NULL;
- irq_iommu->irte_index = 0;
- irq_iommu->sub_handle = 0;
- irq_iommu->irte_mask = 0;
-
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return rc;
-}
-
-/*
- * source validation type
- */
-#define SVT_NO_VERIFY 0x0 /* no verification is required */
-#define SVT_VERIFY_SID_SQ 0x1 /* verify using SID and SQ fields */
-#define SVT_VERIFY_BUS 0x2 /* verify bus of request-id */
-
-/*
- * source-id qualifier
- */
-#define SQ_ALL_16 0x0 /* verify all 16 bits of request-id */
-#define SQ_13_IGNORE_1 0x1 /* verify most significant 13 bits, ignore
- * the third least significant bit
- */
-#define SQ_13_IGNORE_2 0x2 /* verify most significant 13 bits, ignore
- * the second and third least significant bits
- */
-#define SQ_13_IGNORE_3 0x3 /* verify most significant 13 bits, ignore
- * the least three significant bits
- */
-
-/*
- * set SVT, SQ and SID fields of irte to verify
- * source ids of interrupt requests
- */
-static void set_irte_sid(struct irte *irte, unsigned int svt,
- unsigned int sq, unsigned int sid)
-{
- if (disable_sourceid_checking)
- svt = SVT_NO_VERIFY;
- irte->svt = svt;
- irte->sq = sq;
- irte->sid = sid;
-}
-
-int set_ioapic_sid(struct irte *irte, int apic)
-{
- int i;
- u16 sid = 0;
-
- if (!irte)
- return -1;
-
- for (i = 0; i < MAX_IO_APICS; i++) {
- if (ir_ioapic[i].id == apic) {
- sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
- break;
- }
- }
-
- if (sid == 0) {
- pr_warning("Failed to set source-id of IOAPIC (%d)\n", apic);
- return -1;
- }
-
- set_irte_sid(irte, 1, 0, sid);
-
- return 0;
-}
-
-int set_hpet_sid(struct irte *irte, u8 id)
-{
- int i;
- u16 sid = 0;
-
- if (!irte)
- return -1;
-
- for (i = 0; i < MAX_HPET_TBS; i++) {
- if (ir_hpet[i].id == id) {
- sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
- break;
- }
- }
-
- if (sid == 0) {
- pr_warning("Failed to set source-id of HPET block (%d)\n", id);
- return -1;
- }
-
- /*
- * Should really use SQ_ALL_16. Some platforms are broken.
- * While we figure out the right quirks for these broken platforms, use
- * SQ_13_IGNORE_3 for now.
- */
- set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_13_IGNORE_3, sid);
-
- return 0;
-}
-
-int set_msi_sid(struct irte *irte, struct pci_dev *dev)
-{
- struct pci_dev *bridge;
-
- if (!irte || !dev)
- return -1;
-
- /* PCIe device or Root Complex integrated PCI device */
- if (pci_is_pcie(dev) || !dev->bus->parent) {
- set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
- (dev->bus->number << 8) | dev->devfn);
- return 0;
- }
-
- bridge = pci_find_upstream_pcie_bridge(dev);
- if (bridge) {
- if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
- set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
- (bridge->bus->number << 8) | dev->bus->number);
- else /* this is a legacy PCI bridge */
- set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
- (bridge->bus->number << 8) | bridge->devfn);
- }
-
- return 0;
-}
-
-static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
-{
- u64 addr;
- u32 sts;
- unsigned long flags;
-
- addr = virt_to_phys((void *)iommu->ir_table->base);
-
- spin_lock_irqsave(&iommu->register_lock, flags);
-
- dmar_writeq(iommu->reg + DMAR_IRTA_REG,
- (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
-
- /* Set interrupt-remapping table pointer */
- iommu->gcmd |= DMA_GCMD_SIRTP;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (sts & DMA_GSTS_IRTPS), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
-
- /*
- * global invalidation of interrupt entry cache before enabling
- * interrupt-remapping.
- */
- qi_global_iec(iommu);
-
- spin_lock_irqsave(&iommu->register_lock, flags);
-
- /* Enable interrupt-remapping */
- iommu->gcmd |= DMA_GCMD_IRE;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (sts & DMA_GSTS_IRES), sts);
-
- spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-
-static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
-{
- struct ir_table *ir_table;
- struct page *pages;
-
- ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
- GFP_ATOMIC);
-
- if (!iommu->ir_table)
- return -ENOMEM;
-
- pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
- INTR_REMAP_PAGE_ORDER);
-
- if (!pages) {
- printk(KERN_ERR "failed to allocate pages of order %d\n",
- INTR_REMAP_PAGE_ORDER);
- kfree(iommu->ir_table);
- return -ENOMEM;
- }
-
- ir_table->base = page_address(pages);
-
- iommu_set_intr_remapping(iommu, mode);
- return 0;
-}
-
-/*
- * Disable Interrupt Remapping.
- */
-static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
-{
- unsigned long flags;
- u32 sts;
-
- if (!ecap_ir_support(iommu->ecap))
- return;
-
- /*
- * global invalidation of interrupt entry cache before disabling
- * interrupt-remapping.
- */
- qi_global_iec(iommu);
-
- spin_lock_irqsave(&iommu->register_lock, flags);
-
- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
- if (!(sts & DMA_GSTS_IRES))
- goto end;
-
- iommu->gcmd &= ~DMA_GCMD_IRE;
- writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, !(sts & DMA_GSTS_IRES), sts);
-
-end:
- spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-int __init intr_remapping_supported(void)
-{
- struct dmar_drhd_unit *drhd;
-
- if (disable_intremap)
- return 0;
-
- if (!dmar_ir_support())
- return 0;
-
- for_each_drhd_unit(drhd) {
- struct intel_iommu *iommu = drhd->iommu;
-
- if (!ecap_ir_support(iommu->ecap))
- return 0;
- }
-
- return 1;
-}
-
-int __init enable_intr_remapping(int eim)
-{
- struct dmar_drhd_unit *drhd;
- int setup = 0;
-
- if (parse_ioapics_under_ir() != 1) {
- printk(KERN_INFO "Not enable interrupt remapping\n");
- return -1;
- }
-
- for_each_drhd_unit(drhd) {
- struct intel_iommu *iommu = drhd->iommu;
-
- /*
- * If the queued invalidation is already initialized,
- * shouldn't disable it.
- */
- if (iommu->qi)
- continue;
-
- /*
- * Clear previous faults.
- */
- dmar_fault(-1, iommu);
-
- /*
- * Disable intr remapping and queued invalidation, if already
- * enabled prior to OS handover.
- */
- iommu_disable_intr_remapping(iommu);
-
- dmar_disable_qi(iommu);
- }
-
- /*
- * check for the Interrupt-remapping support
- */
- for_each_drhd_unit(drhd) {
- struct intel_iommu *iommu = drhd->iommu;
-
- if (!ecap_ir_support(iommu->ecap))
- continue;
-
- if (eim && !ecap_eim_support(iommu->ecap)) {
- printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
- " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
- return -1;
- }
- }
-
- /*
- * Enable queued invalidation for all the DRHD's.
- */
- for_each_drhd_unit(drhd) {
- int ret;
- struct intel_iommu *iommu = drhd->iommu;
- ret = dmar_enable_qi(iommu);
-
- if (ret) {
- printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
- " invalidation, ecap %Lx, ret %d\n",
- drhd->reg_base_addr, iommu->ecap, ret);
- return -1;
- }
- }
-
- /*
- * Setup Interrupt-remapping for all the DRHD's now.
- */
- for_each_drhd_unit(drhd) {
- struct intel_iommu *iommu = drhd->iommu;
-
- if (!ecap_ir_support(iommu->ecap))
- continue;
-
- if (setup_intr_remapping(iommu, eim))
- goto error;
-
- setup = 1;
- }
-
- if (!setup)
- goto error;
-
- intr_remapping_enabled = 1;
-
- return 0;
-
-error:
- /*
- * handle error condition gracefully here!
- */
- return -1;
-}
-
-static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope,
- struct intel_iommu *iommu)
-{
- struct acpi_dmar_pci_path *path;
- u8 bus;
- int count;
-
- bus = scope->bus;
- path = (struct acpi_dmar_pci_path *)(scope + 1);
- count = (scope->length - sizeof(struct acpi_dmar_device_scope))
- / sizeof(struct acpi_dmar_pci_path);
-
- while (--count > 0) {
- /*
- * Access PCI directly due to the PCI
- * subsystem isn't initialized yet.
- */
- bus = read_pci_config_byte(bus, path->dev, path->fn,
- PCI_SECONDARY_BUS);
- path++;
- }
- ir_hpet[ir_hpet_num].bus = bus;
- ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn);
- ir_hpet[ir_hpet_num].iommu = iommu;
- ir_hpet[ir_hpet_num].id = scope->enumeration_id;
- ir_hpet_num++;
-}
-
-static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
- struct intel_iommu *iommu)
-{
- struct acpi_dmar_pci_path *path;
- u8 bus;
- int count;
-
- bus = scope->bus;
- path = (struct acpi_dmar_pci_path *)(scope + 1);
- count = (scope->length - sizeof(struct acpi_dmar_device_scope))
- / sizeof(struct acpi_dmar_pci_path);
-
- while (--count > 0) {
- /*
- * Access PCI directly due to the PCI
- * subsystem isn't initialized yet.
- */
- bus = read_pci_config_byte(bus, path->dev, path->fn,
- PCI_SECONDARY_BUS);
- path++;
- }
-
- ir_ioapic[ir_ioapic_num].bus = bus;
- ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn);
- ir_ioapic[ir_ioapic_num].iommu = iommu;
- ir_ioapic[ir_ioapic_num].id = scope->enumeration_id;
- ir_ioapic_num++;
-}
-
-static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header,
- struct intel_iommu *iommu)
-{
- struct acpi_dmar_hardware_unit *drhd;
- struct acpi_dmar_device_scope *scope;
- void *start, *end;
-
- drhd = (struct acpi_dmar_hardware_unit *)header;
-
- start = (void *)(drhd + 1);
- end = ((void *)drhd) + header->length;
-
- while (start < end) {
- scope = start;
- if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
- if (ir_ioapic_num == MAX_IO_APICS) {
- printk(KERN_WARNING "Exceeded Max IO APICS\n");
- return -1;
- }
-
- printk(KERN_INFO "IOAPIC id %d under DRHD base "
- " 0x%Lx IOMMU %d\n", scope->enumeration_id,
- drhd->address, iommu->seq_id);
-
- ir_parse_one_ioapic_scope(scope, iommu);
- } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
- if (ir_hpet_num == MAX_HPET_TBS) {
- printk(KERN_WARNING "Exceeded Max HPET blocks\n");
- return -1;
- }
-
- printk(KERN_INFO "HPET id %d under DRHD base"
- " 0x%Lx\n", scope->enumeration_id,
- drhd->address);
-
- ir_parse_one_hpet_scope(scope, iommu);
- }
- start += scope->length;
- }
-
- return 0;
-}
-
-/*
- * Finds the assocaition between IOAPIC's and its Interrupt-remapping
- * hardware unit.
- */
-int __init parse_ioapics_under_ir(void)
-{
- struct dmar_drhd_unit *drhd;
- int ir_supported = 0;
-
- for_each_drhd_unit(drhd) {
- struct intel_iommu *iommu = drhd->iommu;
-
- if (ecap_ir_support(iommu->ecap)) {
- if (ir_parse_ioapic_hpet_scope(drhd->hdr, iommu))
- return -1;
-
- ir_supported = 1;
- }
- }
-
- if (ir_supported && ir_ioapic_num != nr_ioapics) {
- printk(KERN_WARNING
- "Not all IO-APIC's listed under remapping hardware\n");
- return -1;
- }
-
- return ir_supported;
-}
-
-void disable_intr_remapping(void)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu = NULL;
-
- /*
- * Disable Interrupt-remapping for all the DRHD's now.
- */
- for_each_iommu(iommu, drhd) {
- if (!ecap_ir_support(iommu->ecap))
- continue;
-
- iommu_disable_intr_remapping(iommu);
- }
-}
-
-int reenable_intr_remapping(int eim)
-{
- struct dmar_drhd_unit *drhd;
- int setup = 0;
- struct intel_iommu *iommu = NULL;
-
- for_each_iommu(iommu, drhd)
- if (iommu->qi)
- dmar_reenable_qi(iommu);
-
- /*
- * Setup Interrupt-remapping for all the DRHD's now.
- */
- for_each_iommu(iommu, drhd) {
- if (!ecap_ir_support(iommu->ecap))
- continue;
-
- /* Set up interrupt remapping for iommu.*/
- iommu_set_intr_remapping(iommu, eim);
- setup = 1;
- }
-
- if (!setup)
- goto error;
-
- return 0;
-
-error:
- /*
- * handle error condition gracefully here!
- */
- return -1;
-}
-
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h
deleted file mode 100644
index 5662fec..0000000
--- a/drivers/pci/intr_remapping.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <linux/intel-iommu.h>
-
-struct ioapic_scope {
- struct intel_iommu *iommu;
- unsigned int id;
- unsigned int bus; /* PCI bus number */
- unsigned int devfn; /* PCI devfn number */
-};
-
-struct hpet_scope {
- struct intel_iommu *iommu;
- u8 id;
- unsigned int bus;
- unsigned int devfn;
-};
-
-#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 203508b..5775638 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -17,6 +17,7 @@
*/
#include <linux/pci.h>
+#include <linux/export.h>
#include <linux/acpi.h>
#include <linux/slab.h>
#include <acpi/acpi_bus.h>
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 42fae47..1969a3e 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/mutex.h>
+#include <linux/export.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/pci-ats.h>
@@ -282,6 +283,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
struct resource *res;
struct pci_dev *pdev;
struct pci_sriov *iov = dev->sriov;
+ int bars = 0;
if (!nr_virtfn)
return 0;
@@ -306,6 +308,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+ bars |= (1 << (i + PCI_IOV_RESOURCES));
res = dev->resource + PCI_IOV_RESOURCES + i;
if (res->parent)
nres++;
@@ -323,6 +326,11 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return -ENOMEM;
}
+ if (pci_enable_resources(dev, bars)) {
+ dev_err(&dev->dev, "SR-IOV: IOV BARS not allocated\n");
+ return -ENOMEM;
+ }
+
if (iov->link != dev->devfn) {
pdev = pci_get_slot(dev->bus, iov->link);
if (!pdev)
@@ -722,145 +730,3 @@ int pci_num_vf(struct pci_dev *dev)
return dev->sriov->nr_virtfn;
}
EXPORT_SYMBOL_GPL(pci_num_vf);
-
-static int ats_alloc_one(struct pci_dev *dev, int ps)
-{
- int pos;
- u16 cap;
- struct pci_ats *ats;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
- if (!pos)
- return -ENODEV;
-
- ats = kzalloc(sizeof(*ats), GFP_KERNEL);
- if (!ats)
- return -ENOMEM;
-
- ats->pos = pos;
- ats->stu = ps;
- pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
- ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
- PCI_ATS_MAX_QDEP;
- dev->ats = ats;
-
- return 0;
-}
-
-static void ats_free_one(struct pci_dev *dev)
-{
- kfree(dev->ats);
- dev->ats = NULL;
-}
-
-/**
- * pci_enable_ats - enable the ATS capability
- * @dev: the PCI device
- * @ps: the IOMMU page shift
- *
- * Returns 0 on success, or negative on failure.
- */
-int pci_enable_ats(struct pci_dev *dev, int ps)
-{
- int rc;
- u16 ctrl;
-
- BUG_ON(dev->ats && dev->ats->is_enabled);
-
- if (ps < PCI_ATS_MIN_STU)
- return -EINVAL;
-
- if (dev->is_physfn || dev->is_virtfn) {
- struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
-
- mutex_lock(&pdev->sriov->lock);
- if (pdev->ats)
- rc = pdev->ats->stu == ps ? 0 : -EINVAL;
- else
- rc = ats_alloc_one(pdev, ps);
-
- if (!rc)
- pdev->ats->ref_cnt++;
- mutex_unlock(&pdev->sriov->lock);
- if (rc)
- return rc;
- }
-
- if (!dev->is_physfn) {
- rc = ats_alloc_one(dev, ps);
- if (rc)
- return rc;
- }
-
- ctrl = PCI_ATS_CTRL_ENABLE;
- if (!dev->is_virtfn)
- ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
- dev->ats->is_enabled = 1;
-
- return 0;
-}
-
-/**
- * pci_disable_ats - disable the ATS capability
- * @dev: the PCI device
- */
-void pci_disable_ats(struct pci_dev *dev)
-{
- u16 ctrl;
-
- BUG_ON(!dev->ats || !dev->ats->is_enabled);
-
- pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
- ctrl &= ~PCI_ATS_CTRL_ENABLE;
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
- dev->ats->is_enabled = 0;
-
- if (dev->is_physfn || dev->is_virtfn) {
- struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
-
- mutex_lock(&pdev->sriov->lock);
- pdev->ats->ref_cnt--;
- if (!pdev->ats->ref_cnt)
- ats_free_one(pdev);
- mutex_unlock(&pdev->sriov->lock);
- }
-
- if (!dev->is_physfn)
- ats_free_one(dev);
-}
-
-/**
- * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
- * @dev: the PCI device
- *
- * Returns the queue depth on success, or negative on failure.
- *
- * The ATS spec uses 0 in the Invalidate Queue Depth field to
- * indicate that the function can accept 32 Invalidate Request.
- * But here we use the `real' values (i.e. 1~32) for the Queue
- * Depth; and 0 indicates the function shares the Queue with
- * other functions (doesn't exclusively own a Queue).
- */
-int pci_ats_queue_depth(struct pci_dev *dev)
-{
- int pos;
- u16 cap;
-
- if (dev->is_virtfn)
- return 0;
-
- if (dev->ats)
- return dev->ats->qdep;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
- if (!pos)
- return -ENODEV;
-
- pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
-
- return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
- PCI_ATS_MAX_QDEP;
-}
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
deleted file mode 100644
index c5c274a..0000000
--- a/drivers/pci/iova.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright © 2006-2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- */
-
-#include <linux/iova.h>
-
-void
-init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
-{
- spin_lock_init(&iovad->iova_rbtree_lock);
- iovad->rbroot = RB_ROOT;
- iovad->cached32_node = NULL;
- iovad->dma_32bit_pfn = pfn_32bit;
-}
-
-static struct rb_node *
-__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
-{
- if ((*limit_pfn != iovad->dma_32bit_pfn) ||
- (iovad->cached32_node == NULL))
- return rb_last(&iovad->rbroot);
- else {
- struct rb_node *prev_node = rb_prev(iovad->cached32_node);
- struct iova *curr_iova =
- container_of(iovad->cached32_node, struct iova, node);
- *limit_pfn = curr_iova->pfn_lo - 1;
- return prev_node;
- }
-}
-
-static void
-__cached_rbnode_insert_update(struct iova_domain *iovad,
- unsigned long limit_pfn, struct iova *new)
-{
- if (limit_pfn != iovad->dma_32bit_pfn)
- return;
- iovad->cached32_node = &new->node;
-}
-
-static void
-__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
-{
- struct iova *cached_iova;
- struct rb_node *curr;
-
- if (!iovad->cached32_node)
- return;
- curr = iovad->cached32_node;
- cached_iova = container_of(curr, struct iova, node);
-
- if (free->pfn_lo >= cached_iova->pfn_lo) {
- struct rb_node *node = rb_next(&free->node);
- struct iova *iova = container_of(node, struct iova, node);
-
- /* only cache if it's below 32bit pfn */
- if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
- iovad->cached32_node = node;
- else
- iovad->cached32_node = NULL;
- }
-}
-
-/* Computes the padding size required, to make the
- * the start address naturally aligned on its size
- */
-static int
-iova_get_pad_size(int size, unsigned int limit_pfn)
-{
- unsigned int pad_size = 0;
- unsigned int order = ilog2(size);
-
- if (order)
- pad_size = (limit_pfn + 1) % (1 << order);
-
- return pad_size;
-}
-
-static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
- unsigned long size, unsigned long limit_pfn,
- struct iova *new, bool size_aligned)
-{
- struct rb_node *prev, *curr = NULL;
- unsigned long flags;
- unsigned long saved_pfn;
- unsigned int pad_size = 0;
-
- /* Walk the tree backwards */
- spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
- saved_pfn = limit_pfn;
- curr = __get_cached_rbnode(iovad, &limit_pfn);
- prev = curr;
- while (curr) {
- struct iova *curr_iova = container_of(curr, struct iova, node);
-
- if (limit_pfn < curr_iova->pfn_lo)
- goto move_left;
- else if (limit_pfn < curr_iova->pfn_hi)
- goto adjust_limit_pfn;
- else {
- if (size_aligned)
- pad_size = iova_get_pad_size(size, limit_pfn);
- if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn)
- break; /* found a free slot */
- }
-adjust_limit_pfn:
- limit_pfn = curr_iova->pfn_lo - 1;
-move_left:
- prev = curr;
- curr = rb_prev(curr);
- }
-
- if (!curr) {
- if (size_aligned)
- pad_size = iova_get_pad_size(size, limit_pfn);
- if ((IOVA_START_PFN + size + pad_size) > limit_pfn) {
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
- return -ENOMEM;
- }
- }
-
- /* pfn_lo will point to size aligned address if size_aligned is set */
- new->pfn_lo = limit_pfn - (size + pad_size) + 1;
- new->pfn_hi = new->pfn_lo + size - 1;
-
- /* Insert the new_iova into domain rbtree by holding writer lock */
- /* Add new node and rebalance tree. */
- {
- struct rb_node **entry, *parent = NULL;
-
- /* If we have 'prev', it's a valid place to start the
- insertion. Otherwise, start from the root. */
- if (prev)
- entry = &prev;
- else
- entry = &iovad->rbroot.rb_node;
-
- /* Figure out where to put new node */
- while (*entry) {
- struct iova *this = container_of(*entry,
- struct iova, node);
- parent = *entry;
-
- if (new->pfn_lo < this->pfn_lo)
- entry = &((*entry)->rb_left);
- else if (new->pfn_lo > this->pfn_lo)
- entry = &((*entry)->rb_right);
- else
- BUG(); /* this should not happen */
- }
-
- /* Add new node and rebalance tree. */
- rb_link_node(&new->node, parent, entry);
- rb_insert_color(&new->node, &iovad->rbroot);
- }
- __cached_rbnode_insert_update(iovad, saved_pfn, new);
-
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-
-
- return 0;
-}
-
-static void
-iova_insert_rbtree(struct rb_root *root, struct iova *iova)
-{
- struct rb_node **new = &(root->rb_node), *parent = NULL;
- /* Figure out where to put new node */
- while (*new) {
- struct iova *this = container_of(*new, struct iova, node);
- parent = *new;
-
- if (iova->pfn_lo < this->pfn_lo)
- new = &((*new)->rb_left);
- else if (iova->pfn_lo > this->pfn_lo)
- new = &((*new)->rb_right);
- else
- BUG(); /* this should not happen */
- }
- /* Add new node and rebalance tree. */
- rb_link_node(&iova->node, parent, new);
- rb_insert_color(&iova->node, root);
-}
-
-/**
- * alloc_iova - allocates an iova
- * @iovad - iova domain in question
- * @size - size of page frames to allocate
- * @limit_pfn - max limit address
- * @size_aligned - set if size_aligned address range is required
- * This function allocates an iova in the range limit_pfn to IOVA_START_PFN
- * looking from limit_pfn instead from IOVA_START_PFN. If the size_aligned
- * flag is set then the allocated address iova->pfn_lo will be naturally
- * aligned on roundup_power_of_two(size).
- */
-struct iova *
-alloc_iova(struct iova_domain *iovad, unsigned long size,
- unsigned long limit_pfn,
- bool size_aligned)
-{
- struct iova *new_iova;
- int ret;
-
- new_iova = alloc_iova_mem();
- if (!new_iova)
- return NULL;
-
- /* If size aligned is set then round the size to
- * to next power of two.
- */
- if (size_aligned)
- size = __roundup_pow_of_two(size);
-
- ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
- new_iova, size_aligned);
-
- if (ret) {
- free_iova_mem(new_iova);
- return NULL;
- }
-
- return new_iova;
-}
-
-/**
- * find_iova - find's an iova for a given pfn
- * @iovad - iova domain in question.
- * pfn - page frame number
- * This function finds and returns an iova belonging to the
- * given doamin which matches the given pfn.
- */
-struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
-{
- unsigned long flags;
- struct rb_node *node;
-
- /* Take the lock so that no other thread is manipulating the rbtree */
- spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
- node = iovad->rbroot.rb_node;
- while (node) {
- struct iova *iova = container_of(node, struct iova, node);
-
- /* If pfn falls within iova's range, return iova */
- if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
- /* We are not holding the lock while this iova
- * is referenced by the caller as the same thread
- * which called this function also calls __free_iova()
- * and it is by desing that only one thread can possibly
- * reference a particular iova and hence no conflict.
- */
- return iova;
- }
-
- if (pfn < iova->pfn_lo)
- node = node->rb_left;
- else if (pfn > iova->pfn_lo)
- node = node->rb_right;
- }
-
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
- return NULL;
-}
-
-/**
- * __free_iova - frees the given iova
- * @iovad: iova domain in question.
- * @iova: iova in question.
- * Frees the given iova belonging to the giving domain
- */
-void
-__free_iova(struct iova_domain *iovad, struct iova *iova)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
- __cached_rbnode_delete_update(iovad, iova);
- rb_erase(&iova->node, &iovad->rbroot);
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
- free_iova_mem(iova);
-}
-
-/**
- * free_iova - finds and frees the iova for a given pfn
- * @iovad: - iova domain in question.
- * @pfn: - pfn that is allocated previously
- * This functions finds an iova for a given pfn and then
- * frees the iova from that domain.
- */
-void
-free_iova(struct iova_domain *iovad, unsigned long pfn)
-{
- struct iova *iova = find_iova(iovad, pfn);
- if (iova)
- __free_iova(iovad, iova);
-
-}
-
-/**
- * put_iova_domain - destroys the iova doamin
- * @iovad: - iova domain in question.
- * All the iova's in that domain are destroyed.
- */
-void put_iova_domain(struct iova_domain *iovad)
-{
- struct rb_node *node;
- unsigned long flags;
-
- spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
- node = rb_first(&iovad->rbroot);
- while (node) {
- struct iova *iova = container_of(node, struct iova, node);
- rb_erase(node, &iovad->rbroot);
- free_iova_mem(iova);
- node = rb_first(&iovad->rbroot);
- }
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-}
-
-static int
-__is_range_overlap(struct rb_node *node,
- unsigned long pfn_lo, unsigned long pfn_hi)
-{
- struct iova *iova = container_of(node, struct iova, node);
-
- if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo))
- return 1;
- return 0;
-}
-
-static struct iova *
-__insert_new_range(struct iova_domain *iovad,
- unsigned long pfn_lo, unsigned long pfn_hi)
-{
- struct iova *iova;
-
- iova = alloc_iova_mem();
- if (!iova)
- return iova;
-
- iova->pfn_hi = pfn_hi;
- iova->pfn_lo = pfn_lo;
- iova_insert_rbtree(&iovad->rbroot, iova);
- return iova;
-}
-
-static void
-__adjust_overlap_range(struct iova *iova,
- unsigned long *pfn_lo, unsigned long *pfn_hi)
-{
- if (*pfn_lo < iova->pfn_lo)
- iova->pfn_lo = *pfn_lo;
- if (*pfn_hi > iova->pfn_hi)
- *pfn_lo = iova->pfn_hi + 1;
-}
-
-/**
- * reserve_iova - reserves an iova in the given range
- * @iovad: - iova domain pointer
- * @pfn_lo: - lower page frame address
- * @pfn_hi:- higher pfn adderss
- * This function allocates reserves the address range from pfn_lo to pfn_hi so
- * that this address is not dished out as part of alloc_iova.
- */
-struct iova *
-reserve_iova(struct iova_domain *iovad,
- unsigned long pfn_lo, unsigned long pfn_hi)
-{
- struct rb_node *node;
- unsigned long flags;
- struct iova *iova;
- unsigned int overlap = 0;
-
- spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
- for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
- if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
- iova = container_of(node, struct iova, node);
- __adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
- if ((pfn_lo >= iova->pfn_lo) &&
- (pfn_hi <= iova->pfn_hi))
- goto finish;
- overlap = 1;
-
- } else if (overlap)
- break;
- }
-
- /* We are here either because this is the first reserver node
- * or need to insert remaining non overlap addr range
- */
- iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
-finish:
-
- spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
- return iova;
-}
-
-/**
- * copy_reserved_iova - copies the reserved between domains
- * @from: - source doamin from where to copy
- * @to: - destination domin where to copy
- * This function copies reserved iova's from one doamin to
- * other.
- */
-void
-copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
-{
- unsigned long flags;
- struct rb_node *node;
-
- spin_lock_irqsave(&from->iova_rbtree_lock, flags);
- for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
- struct iova *iova = container_of(node, struct iova, node);
- struct iova *new_iova;
- new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi);
- if (!new_iova)
- printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
- iova->pfn_lo, iova->pfn_lo);
- }
- spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
-}
diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c
index de01174..e5f69a4 100644
--- a/drivers/pci/irq.c
+++ b/drivers/pci/irq.c
@@ -7,6 +7,7 @@
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/pci.h>
static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index e174982..e3efb43 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -11,6 +11,7 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/export.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 56b04bc..c8e7585 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -46,6 +46,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
struct pci_dev *pci_dev = context;
if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) {
+ if (pci_dev->pme_poll)
+ pci_dev->pme_poll = false;
+
pci_wakeup_event(pci_dev);
pci_check_pme_status(pci_dev);
pm_runtime_resume(&pci_dev->dev);
@@ -282,7 +285,6 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
{
struct acpi_device *dev;
acpi_handle handle;
- int error = -ENODEV;
if (!device_run_wake(phys_dev))
return -EINVAL;
@@ -302,7 +304,7 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
acpi_disable_wakeup_device_power(dev);
}
- return error;
+ return 0;
}
static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 5d5bdf7..68af94c 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/cpu.h>
#include <linux/pm_runtime.h>
+#include <linux/suspend.h>
#include "pci.h"
struct pci_dynid {
@@ -616,6 +617,21 @@ static int pci_pm_prepare(struct device *dev)
int error = 0;
/*
+ * If a PCI device configured to wake up the system from sleep states
+ * has been suspended at run time and there's a resume request pending
+ * for it, this is equivalent to the device signaling wakeup, so the
+ * system suspend operation should be aborted.
+ */
+ pm_runtime_get_noresume(dev);
+ if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+ pm_wakeup_event(dev, 0);
+
+ if (pm_wakeup_pending()) {
+ pm_runtime_put_sync(dev);
+ return -EBUSY;
+ }
+
+ /*
* PCI devices suspended at run time need to be resumed at this
* point, because in general it is necessary to reconfigure them for
* system suspend. Namely, if the device is supposed to wake up the
@@ -624,7 +640,7 @@ static int pci_pm_prepare(struct device *dev)
* system from the sleep state, we'll have to prevent it from signaling
* wake-up.
*/
- pm_runtime_get_sync(dev);
+ pm_runtime_resume(dev);
if (drv && drv->pm && drv->pm->prepare)
error = drv->pm->prepare(dev);
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 77cb2a1..81525ae 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -55,7 +55,7 @@ enum smbios_attr_enum {
SMBIOS_ATTR_INSTANCE_SHOW,
};
-static mode_t
+static size_t
find_smbios_instance_string(struct pci_dev *pdev, char *buf,
enum smbios_attr_enum attribute)
{
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7bcf12a..1e6be19 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/stat.h>
+#include <linux/export.h>
#include <linux/topology.h>
#include <linux/mm.h>
#include <linux/fs.h>
@@ -172,7 +173,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+ return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X\n",
pci_dev->vendor, pci_dev->device,
pci_dev->subsystem_vendor, pci_dev->subsystem_device,
(u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d549bbc..4c3a9e9 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -77,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
+enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
+
/*
* The default CLS is used if arch didn't set CLS explicitly and not
* all pci devices agree on the same value. Arch can override either
@@ -662,12 +664,11 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
error = platform_pci_set_power_state(dev, state);
if (!error)
pci_update_current_state(dev, state);
- } else {
+ } else
error = -ENODEV;
- /* Fall back to PCI_D0 if native PM is not supported */
- if (!dev->pm_cap)
- dev->current_state = PCI_D0;
- }
+
+ if (error && !dev->pm_cap) /* Fall back to PCI_D0 */
+ dev->current_state = PCI_D0;
return error;
}
@@ -1077,6 +1078,8 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
static int do_pci_enable_device(struct pci_dev *dev, int bars)
{
int err;
+ u16 cmd;
+ u8 pin;
err = pci_set_power_state(dev, PCI_D0);
if (err < 0 && err != -EIO)
@@ -1086,6 +1089,17 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
return err;
pci_fixup_device(pci_fixup_enable, dev);
+ if (dev->msi_enabled || dev->msix_enabled)
+ return 0;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin) {
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ if (cmd & PCI_COMMAND_INTX_DISABLE)
+ pci_write_config_word(dev, PCI_COMMAND,
+ cmd & ~PCI_COMMAND_INTX_DISABLE);
+ }
+
return 0;
}
@@ -1124,7 +1138,11 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
if (atomic_add_return(1, &dev->enable_cnt) > 1)
return 0; /* already enabled */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ /* only skip sriov related */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+ if (dev->resource[i].flags & flags)
+ bars |= (1 << i);
+ for (i = PCI_BRIDGE_RESOURCES; i < DEVICE_COUNT_RESOURCE; i++)
if (dev->resource[i].flags & flags)
bars |= (1 << i);
@@ -1405,13 +1423,16 @@ bool pci_check_pme_status(struct pci_dev *dev)
/**
* pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set.
* @dev: Device to handle.
- * @ign: Ignored.
+ * @pme_poll_reset: Whether or not to reset the device's pme_poll flag.
*
* Check if @dev has generated PME and queue a resume request for it in that
* case.
*/
-static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
+static int pci_pme_wakeup(struct pci_dev *dev, void *pme_poll_reset)
{
+ if (pme_poll_reset && dev->pme_poll)
+ dev->pme_poll = false;
+
if (pci_check_pme_status(dev)) {
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
@@ -1426,7 +1447,7 @@ static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
void pci_pme_wakeup_bus(struct pci_bus *bus)
{
if (bus)
- pci_walk_bus(bus, pci_pme_wakeup, NULL);
+ pci_walk_bus(bus, pci_pme_wakeup, (void *)true);
}
/**
@@ -1444,31 +1465,26 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
static void pci_pme_list_scan(struct work_struct *work)
{
- struct pci_pme_device *pme_dev;
+ struct pci_pme_device *pme_dev, *n;
mutex_lock(&pci_pme_list_mutex);
if (!list_empty(&pci_pme_list)) {
- list_for_each_entry(pme_dev, &pci_pme_list, list)
- pci_pme_wakeup(pme_dev->dev, NULL);
- schedule_delayed_work(&pci_pme_work, msecs_to_jiffies(PME_TIMEOUT));
+ list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
+ if (pme_dev->dev->pme_poll) {
+ pci_pme_wakeup(pme_dev->dev, NULL);
+ } else {
+ list_del(&pme_dev->list);
+ kfree(pme_dev);
+ }
+ }
+ if (!list_empty(&pci_pme_list))
+ schedule_delayed_work(&pci_pme_work,
+ msecs_to_jiffies(PME_TIMEOUT));
}
mutex_unlock(&pci_pme_list_mutex);
}
/**
- * pci_external_pme - is a device an external PCI PME source?
- * @dev: PCI device to check
- *
- */
-
-static bool pci_external_pme(struct pci_dev *dev)
-{
- if (pci_is_pcie(dev) || dev->bus->number == 0)
- return false;
- return true;
-}
-
-/**
* pci_pme_active - enable or disable PCI device's PME# function
* @dev: PCI device to handle.
* @enable: 'true' to enable PME# generation; 'false' to disable it.
@@ -1501,7 +1517,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
hit, and the power savings from the devices will still be a
win. */
- if (pci_external_pme(dev)) {
+ if (dev->pme_poll) {
struct pci_pme_device *pme_dev;
if (enable) {
pme_dev = kmalloc(sizeof(struct pci_pme_device),
@@ -1819,6 +1835,7 @@ void pci_pm_init(struct pci_dev *dev)
(pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
(pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT;
+ dev->pme_poll = true;
/*
* Make device's PM flags reflect the wake-up capability, but
* let the user space enable it to wake up the system as needed.
@@ -1911,10 +1928,6 @@ void pci_enable_ari(struct pci_dev *dev)
if (!pci_is_pcie(dev) || dev->devfn)
return;
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
- if (!pos)
- return;
-
bridge = dev->bus->self;
if (!bridge || !pci_is_pcie(bridge))
return;
@@ -1933,10 +1946,14 @@ void pci_enable_ari(struct pci_dev *dev)
return;
pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl);
- ctrl |= PCI_EXP_DEVCTL2_ARI;
+ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) {
+ ctrl |= PCI_EXP_DEVCTL2_ARI;
+ bridge->ari_enabled = 1;
+ } else {
+ ctrl &= ~PCI_EXP_DEVCTL2_ARI;
+ bridge->ari_enabled = 0;
+ }
pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl);
-
- bridge->ari_enabled = 1;
}
/**
@@ -3191,7 +3208,7 @@ EXPORT_SYMBOL(pcie_get_readrq);
* @rq: maximum memory read count in bytes
* valid values are 128, 256, 512, 1024, 2048, 4096
*
- * If possible sets maximum read byte count
+ * If possible sets maximum memory read request in bytes
*/
int pcie_set_readrq(struct pci_dev *dev, int rq)
{
@@ -3201,8 +3218,6 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
goto out;
- v = (ffs(rq) - 8) << 12;
-
cap = pci_pcie_cap(dev);
if (!cap)
goto out;
@@ -3210,11 +3225,27 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
if (err)
goto out;
+ /*
+ * If using the "performance" PCIe config, we clamp the
+ * read rq size to the max packet size to prevent the
+ * host bridge generating requests larger than we can
+ * cope with
+ */
+ if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
+ int mps = pcie_get_mps(dev);
+
+ if (mps < 0)
+ return mps;
+ if (mps < rq)
+ rq = mps;
+ }
+
+ v = (ffs(rq) - 8) << 12;
if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
ctl &= ~PCI_EXP_DEVCTL_READRQ;
ctl |= v;
- err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl);
+ err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
}
out:
@@ -3223,6 +3254,67 @@ out:
EXPORT_SYMBOL(pcie_set_readrq);
/**
+ * pcie_get_mps - get PCI Express maximum payload size
+ * @dev: PCI device to query
+ *
+ * Returns maximum payload size in bytes
+ * or appropriate error value.
+ */
+int pcie_get_mps(struct pci_dev *dev)
+{
+ int ret, cap;
+ u16 ctl;
+
+ cap = pci_pcie_cap(dev);
+ if (!cap)
+ return -EINVAL;
+
+ ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+ if (!ret)
+ ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+
+ return ret;
+}
+
+/**
+ * pcie_set_mps - set PCI Express maximum payload size
+ * @dev: PCI device to query
+ * @mps: maximum payload size in bytes
+ * valid values are 128, 256, 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum payload size
+ */
+int pcie_set_mps(struct pci_dev *dev, int mps)
+{
+ int cap, err = -EINVAL;
+ u16 ctl, v;
+
+ if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
+ goto out;
+
+ v = ffs(mps) - 8;
+ if (v > dev->pcie_mpss)
+ goto out;
+ v <<= 5;
+
+ cap = pci_pcie_cap(dev);
+ if (!cap)
+ goto out;
+
+ err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+ if (err)
+ goto out;
+
+ if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
+ ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
+ ctl |= v;
+ err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+out:
+ return err;
+}
+
+/**
* pci_select_bars - Make BAR mask from the type of resource
* @dev: the PCI device for which BAR mask is made
* @flags: resource type mask to be selected
@@ -3505,6 +3597,14 @@ static int __init pci_setup(char *str)
pci_hotplug_io_size = memparse(str + 9, &str);
} else if (!strncmp(str, "hpmemsize=", 10)) {
pci_hotplug_mem_size = memparse(str + 10, &str);
+ } else if (!strncmp(str, "pcie_bus_tune_off", 17)) {
+ pcie_bus_config = PCIE_BUS_TUNE_OFF;
+ } else if (!strncmp(str, "pcie_bus_safe", 13)) {
+ pcie_bus_config = PCIE_BUS_SAFE;
+ } else if (!strncmp(str, "pcie_bus_perf", 13)) {
+ pcie_bus_config = PCIE_BUS_PERFORMANCE;
+ } else if (!strncmp(str, "pcie_bus_peer2peer", 18)) {
+ pcie_bus_config = PCIE_BUS_PEER2PEER;
} else {
printk(KERN_ERR "PCI: Unknown option `%s'\n",
str);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 3a39bf1..b74084e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -186,8 +186,6 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
return NULL;
}
-struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
-
/* PCI slot sysfs helper code */
#define to_pci_slot(s) container_of(s, struct pci_slot, kobj)
@@ -285,6 +283,8 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
#endif /* CONFIG_PCI_IOV */
+extern unsigned long pci_cardbus_resource_alignment(struct resource *);
+
static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
struct resource *res)
{
@@ -294,6 +294,8 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
return pci_sriov_resource_alignment(dev, resno);
#endif
+ if (dev->class >> 8 == PCI_CLASS_BRIDGE_CARDBUS)
+ return pci_cardbus_resource_alignment(res);
return resource_alignment(res);
}
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 43421fb..ee82c55 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -24,6 +24,7 @@
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/kfifo.h>
#include "aerdrv.h"
static int forceload;
@@ -445,8 +446,7 @@ static struct pcie_port_service_driver *find_aer_service(struct pci_dev *dev)
return drv;
}
-static pci_ers_result_t reset_link(struct pcie_device *aerdev,
- struct pci_dev *dev)
+static pci_ers_result_t reset_link(struct pci_dev *dev)
{
struct pci_dev *udev;
pci_ers_result_t status;
@@ -486,7 +486,6 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,
/**
* do_recovery - handle nonfatal/fatal error recovery process
- * @aerdev: pointer to a pcie_device data structure of root port
* @dev: pointer to a pci_dev data structure of agent detecting an error
* @severity: error severity type
*
@@ -494,8 +493,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,
* error detected message to all downstream drivers within a hierarchy in
* question and return the returned code.
*/
-static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev,
- int severity)
+static void do_recovery(struct pci_dev *dev, int severity)
{
pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
enum pci_channel_state state;
@@ -511,7 +509,7 @@ static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev,
report_error_detected);
if (severity == AER_FATAL) {
- result = reset_link(aerdev, dev);
+ result = reset_link(dev);
if (result != PCI_ERS_RESULT_RECOVERED)
goto failed;
}
@@ -576,9 +574,74 @@ static void handle_error_source(struct pcie_device *aerdev,
pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
info->status);
} else
- do_recovery(aerdev, dev, info->severity);
+ do_recovery(dev, info->severity);
}
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+static void aer_recover_work_func(struct work_struct *work);
+
+#define AER_RECOVER_RING_ORDER 4
+#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)
+
+struct aer_recover_entry
+{
+ u8 bus;
+ u8 devfn;
+ u16 domain;
+ int severity;
+};
+
+static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
+ AER_RECOVER_RING_SIZE);
+/*
+ * Mutual exclusion for writers of aer_recover_ring, reader side don't
+ * need lock, because there is only one reader and lock is not needed
+ * between reader and writer.
+ */
+static DEFINE_SPINLOCK(aer_recover_ring_lock);
+static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
+
+void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
+ int severity)
+{
+ unsigned long flags;
+ struct aer_recover_entry entry = {
+ .bus = bus,
+ .devfn = devfn,
+ .domain = domain,
+ .severity = severity,
+ };
+
+ spin_lock_irqsave(&aer_recover_ring_lock, flags);
+ if (kfifo_put(&aer_recover_ring, &entry))
+ schedule_work(&aer_recover_work);
+ else
+ pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
+ domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
+}
+EXPORT_SYMBOL_GPL(aer_recover_queue);
+
+static void aer_recover_work_func(struct work_struct *work)
+{
+ struct aer_recover_entry entry;
+ struct pci_dev *pdev;
+
+ while (kfifo_get(&aer_recover_ring, &entry)) {
+ pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
+ entry.devfn);
+ if (!pdev) {
+ pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
+ entry.domain, entry.bus,
+ PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
+ continue;
+ }
+ do_recovery(pdev, entry.severity);
+ pci_dev_put(pdev);
+ }
+}
+#endif
+
/**
* get_device_error_info - read error status from dev and store it to info
* @dev: pointer to the device expected to have a error record
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index b07a42e..3ea5173 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -204,7 +204,7 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
}
#ifdef CONFIG_ACPI_APEI_PCIEAER
-static int cper_severity_to_aer(int cper_severity)
+int cper_severity_to_aer(int cper_severity)
{
switch (cper_severity) {
case CPER_SEV_RECOVERABLE:
@@ -215,6 +215,7 @@ static int cper_severity_to_aer(int cper_severity)
return AER_CORRECTABLE;
}
}
+EXPORT_SYMBOL_GPL(cper_severity_to_aer);
void cper_print_aer(const char *prefix, int cper_severity,
struct aer_capability_regs *aer)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 9b9305a..c73ed00 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -967,7 +967,7 @@ static int __init pcie_aspm_disable(char *str)
printk(KERN_INFO "PCIe ASPM is disabled\n");
} else if (!strcmp(str, "force")) {
aspm_force = 1;
- printk(KERN_INFO "PCIe ASPM is forcedly enabled\n");
+ printk(KERN_INFO "PCIe ASPM is forcibly enabled\n");
}
return 1;
}
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 0057344..001f1b7 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -84,6 +84,9 @@ static bool pcie_pme_walk_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
/* Skip PCIe devices in case we started from a root port. */
if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) {
+ if (dev->pme_poll)
+ dev->pme_poll = false;
+
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
ret = true;
@@ -142,6 +145,9 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
/* First, check if the PME is from the root port itself. */
if (port->devfn == devfn && port->bus->number == busnr) {
+ if (port->pme_poll)
+ port->pme_poll = false;
+
if (pci_check_pme_status(port)) {
pm_request_resume(&port->dev);
found = true;
@@ -187,6 +193,9 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
/* The device is there, but we have to check its PME status. */
found = pci_check_pme_status(dev);
if (found) {
+ if (dev->pme_poll)
+ dev->pme_poll = false;
+
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
}
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index e0610bd..7e41b70 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -151,7 +151,6 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
static void pcie_portdrv_remove(struct pci_dev *dev)
{
pcie_port_device_remove(dev);
- pci_disable_device(dev);
}
static int error_detected_iter(struct device *device, void *data)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0d5d0bf..bc92c47 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -52,6 +52,7 @@ static void release_pcibus_dev(struct device *dev)
if (pci_bus->bridge)
put_device(pci_bus->bridge);
pci_bus_remove_resources(pci_bus);
+ pci_release_bus_of_node(pci_bus);
kfree(pci_bus);
}
@@ -67,21 +68,6 @@ static int __init pcibus_class_init(void)
}
postcore_initcall(pcibus_class_init);
-/*
- * Translate the low bits of the PCI base
- * to the resource type
- */
-static inline unsigned int pci_calc_resource_flags(unsigned int flags)
-{
- if (flags & PCI_BASE_ADDRESS_SPACE_IO)
- return IORESOURCE_IO;
-
- if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
- return IORESOURCE_MEM | IORESOURCE_PREFETCH;
-
- return IORESOURCE_MEM;
-}
-
static u64 pci_size(u64 base, u64 maxbase, u64 mask)
{
u64 size = mask & maxbase; /* Find the significant bits */
@@ -100,18 +86,39 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)
return size;
}
-static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
+static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
{
+ u32 mem_type;
+ unsigned long flags;
+
if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
- res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
- return pci_bar_io;
+ flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
+ flags |= IORESOURCE_IO;
+ return flags;
}
- res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
+ flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
+ flags |= IORESOURCE_MEM;
+ if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ flags |= IORESOURCE_PREFETCH;
- if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
- return pci_bar_mem64;
- return pci_bar_mem32;
+ mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+ switch (mem_type) {
+ case PCI_BASE_ADDRESS_MEM_TYPE_32:
+ break;
+ case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+ dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+ break;
+ case PCI_BASE_ADDRESS_MEM_TYPE_64:
+ flags |= IORESOURCE_MEM_64;
+ break;
+ default:
+ dev_warn(&dev->dev,
+ "mem unknown type %x treated as 32-bit BAR\n",
+ mem_type);
+ break;
+ }
+ return flags;
}
/**
@@ -164,22 +171,25 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
l = 0;
if (type == pci_bar_unknown) {
- type = decode_bar(res, l);
- res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
- if (type == pci_bar_io) {
+ res->flags = decode_bar(dev, l);
+ res->flags |= IORESOURCE_SIZEALIGN;
+ if (res->flags & IORESOURCE_IO) {
l &= PCI_BASE_ADDRESS_IO_MASK;
+ sz &= PCI_BASE_ADDRESS_IO_MASK;
mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT;
} else {
l &= PCI_BASE_ADDRESS_MEM_MASK;
+ sz &= PCI_BASE_ADDRESS_MEM_MASK;
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
}
} else {
res->flags |= (l & IORESOURCE_ROM_ENABLE);
l &= PCI_ROM_ADDRESS_MASK;
+ sz &= PCI_ROM_ADDRESS_MASK;
mask = (u32)PCI_ROM_ADDRESS_MASK;
}
- if (type == pci_bar_mem64) {
+ if (res->flags & IORESOURCE_MEM_64) {
u64 l64 = l;
u64 sz64 = sz;
u64 mask64 = mask | (u64)~0 << 32;
@@ -203,7 +213,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
goto fail;
}
- res->flags |= IORESOURCE_MEM_64;
if ((sizeof(resource_size_t) < 8) && l) {
/* Address above 32-bit boundary; disable the BAR */
pci_write_config_dword(dev, pos, 0);
@@ -229,7 +238,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
}
out:
- return (type == pci_bar_mem64) ? 1 : 0;
+ return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
fail:
res->flags = 0;
goto out;
@@ -283,10 +292,6 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
if (!res->end)
res->end = limit + 0xfff;
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
- } else {
- dev_printk(KERN_DEBUG, &dev->dev,
- " bridge window [io %#06lx-%#06lx] (disabled)\n",
- base, limit);
}
}
@@ -307,10 +312,6 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
res->start = base;
res->end = limit + 0xfffff;
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
- } else {
- dev_printk(KERN_DEBUG, &dev->dev,
- " bridge window [mem %#010lx-%#010lx] (disabled)\n",
- base, limit + 0xfffff);
}
}
@@ -358,10 +359,6 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
res->start = base;
res->end = limit + 0xfffff;
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
- } else {
- dev_printk(KERN_DEBUG, &dev->dev,
- " bridge window [mem %#010lx-%#010lx pref] (disabled)\n",
- base, limit + 0xfffff);
}
}
@@ -588,7 +585,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->self = bridge;
child->bridge = get_device(&bridge->dev);
-
+ pci_set_bus_of_node(child);
pci_set_bus_speed(child);
/* Set up default resource pointers and names.. */
@@ -731,12 +728,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
pci_write_config_word(dev, PCI_STATUS, 0xffff);
/* Prevent assigning a bus number that already exists.
- * This can happen when a bridge is hot-plugged */
- if (pci_find_bus(pci_domain_nr(bus), max+1))
- goto out;
- child = pci_add_new_bus(bus, dev, ++max);
- if (!child)
- goto out;
+ * This can happen when a bridge is hot-plugged, so in
+ * this case we only re-scan this bus. */
+ child = pci_find_bus(pci_domain_nr(bus), max+1);
+ if (!child) {
+ child = pci_add_new_bus(bus, dev, ++max);
+ if (!child)
+ goto out;
+ }
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->secondary) << 8)
@@ -867,6 +866,8 @@ void set_pcie_port_type(struct pci_dev *pdev)
pdev->pcie_cap = pos;
pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
+ pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
+ pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
}
void set_pcie_hotplug_bridge(struct pci_dev *pdev)
@@ -1045,6 +1046,7 @@ static void pci_release_dev(struct device *dev)
pci_dev = to_pci_dev(dev);
pci_release_capabilities(pci_dev);
+ pci_release_of_node(pci_dev);
kfree(pci_dev);
}
@@ -1164,6 +1166,8 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;
+ pci_set_of_node(dev);
+
if (pci_setup_device(dev)) {
kfree(dev);
return NULL;
@@ -1334,6 +1338,157 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
return nr;
}
+static int pcie_find_smpss(struct pci_dev *dev, void *data)
+{
+ u8 *smpss = data;
+
+ if (!pci_is_pcie(dev))
+ return 0;
+
+ /* For PCIE hotplug enabled slots not connected directly to a
+ * PCI-E root port, there can be problems when hotplugging
+ * devices. This is due to the possibility of hotplugging a
+ * device into the fabric with a smaller MPS that the devices
+ * currently running have configured. Modifying the MPS on the
+ * running devices could cause a fatal bus error due to an
+ * incoming frame being larger than the newly configured MPS.
+ * To work around this, the MPS for the entire fabric must be
+ * set to the minimum size. Any devices hotplugged into this
+ * fabric will have the minimum MPS set. If the PCI hotplug
+ * slot is directly connected to the root port and there are not
+ * other devices on the fabric (which seems to be the most
+ * common case), then this is not an issue and MPS discovery
+ * will occur as normal.
+ */
+ if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) ||
+ (dev->bus->self &&
+ dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT)))
+ *smpss = 0;
+
+ if (*smpss > dev->pcie_mpss)
+ *smpss = dev->pcie_mpss;
+
+ return 0;
+}
+
+static void pcie_write_mps(struct pci_dev *dev, int mps)
+{
+ int rc;
+
+ if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
+ mps = 128 << dev->pcie_mpss;
+
+ if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && dev->bus->self)
+ /* For "Performance", the assumption is made that
+ * downstream communication will never be larger than
+ * the MRRS. So, the MPS only needs to be configured
+ * for the upstream communication. This being the case,
+ * walk from the top down and set the MPS of the child
+ * to that of the parent bus.
+ *
+ * Configure the device MPS with the smaller of the
+ * device MPSS or the bridge MPS (which is assumed to be
+ * properly configured at this point to the largest
+ * allowable MPS based on its parent bus).
+ */
+ mps = min(mps, pcie_get_mps(dev->bus->self));
+ }
+
+ rc = pcie_set_mps(dev, mps);
+ if (rc)
+ dev_err(&dev->dev, "Failed attempting to set the MPS\n");
+}
+
+static void pcie_write_mrrs(struct pci_dev *dev)
+{
+ int rc, mrrs;
+
+ /* In the "safe" case, do not configure the MRRS. There appear to be
+ * issues with setting MRRS to 0 on a number of devices.
+ */
+ if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
+ return;
+
+ /* For Max performance, the MRRS must be set to the largest supported
+ * value. However, it cannot be configured larger than the MPS the
+ * device or the bus can support. This should already be properly
+ * configured by a prior call to pcie_write_mps.
+ */
+ mrrs = pcie_get_mps(dev);
+
+ /* MRRS is a R/W register. Invalid values can be written, but a
+ * subsequent read will verify if the value is acceptable or not.
+ * If the MRRS value provided is not acceptable (e.g., too large),
+ * shrink the value until it is acceptable to the HW.
+ */
+ while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
+ rc = pcie_set_readrq(dev, mrrs);
+ if (!rc)
+ break;
+
+ dev_warn(&dev->dev, "Failed attempting to set the MRRS\n");
+ mrrs /= 2;
+ }
+
+ if (mrrs < 128)
+ dev_err(&dev->dev, "MRRS was unable to be configured with a "
+ "safe value. If problems are experienced, try running "
+ "with pci=pcie_bus_safe.\n");
+}
+
+static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
+{
+ int mps, orig_mps;
+
+ if (!pci_is_pcie(dev))
+ return 0;
+
+ mps = 128 << *(u8 *)data;
+ orig_mps = pcie_get_mps(dev);
+
+ pcie_write_mps(dev, mps);
+ pcie_write_mrrs(dev);
+
+ dev_info(&dev->dev, "PCI-E Max Payload Size set to %4d/%4d (was %4d), "
+ "Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss,
+ orig_mps, pcie_get_readrq(dev));
+
+ return 0;
+}
+
+/* pcie_bus_configure_settings requires that pci_walk_bus work in a top-down,
+ * parents then children fashion. If this changes, then this code will not
+ * work as designed.
+ */
+void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
+{
+ u8 smpss;
+
+ if (!pci_is_pcie(bus->self))
+ return;
+
+ if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
+ return;
+
+ /* FIXME - Peer to peer DMA is possible, though the endpoint would need
+ * to be aware to the MPS of the destination. To work around this,
+ * simply force the MPS of the entire system to the smallest possible.
+ */
+ if (pcie_bus_config == PCIE_BUS_PEER2PEER)
+ smpss = 0;
+
+ if (pcie_bus_config == PCIE_BUS_SAFE) {
+ smpss = mpss;
+
+ pcie_find_smpss(bus->self, &smpss);
+ pci_walk_bus(bus, pcie_find_smpss, &smpss);
+ }
+
+ pcie_bus_configure_set(bus->self, &smpss);
+ pci_walk_bus(bus, pcie_bus_configure_set, &smpss);
+}
+EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
+
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
{
unsigned int devfn, pass, max = bus->secondary;
@@ -1416,6 +1571,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
goto dev_reg_err;
b->bridge = get_device(dev);
device_enable_async_suspend(b->bridge);
+ pci_set_bus_of_node(b);
if (!parent)
set_dev_node(b->bridge, pcibus_to_node(b));
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index f097df2..93be760 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -25,6 +26,7 @@
#include <linux/dmi.h>
#include <linux/pci-aspm.h>
#include <linux/ioport.h>
+#include <linux/mm.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -351,6 +353,25 @@ static void __devinit quirk_citrine(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine);
+/* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */
+static void quirk_extend_bar_to_page(struct pci_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+ struct resource *r = &dev->resource[i];
+
+ if (r->flags & IORESOURCE_MEM && resource_size(r) < PAGE_SIZE) {
+ r->end = PAGE_SIZE - 1;
+ r->start = 0;
+ r->flags |= IORESOURCE_UNSET;
+ dev_info(&dev->dev, "expanded BAR %d to page size: %pR\n",
+ i, r);
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, 0x034a, quirk_extend_bar_to_page);
+
/*
* S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
* If it's needed, re-allocate the region.
@@ -367,19 +388,52 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
+static void quirk_io(struct pci_dev *dev, int pos, unsigned size,
+ const char *name)
+{
+ u32 region;
+ struct pci_bus_region bus_region;
+ struct resource *res = dev->resource + pos;
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (pos << 2), &region);
+
+ if (!region)
+ return;
+
+ res->name = pci_name(dev);
+ res->flags = region & ~PCI_BASE_ADDRESS_IO_MASK;
+ res->flags |=
+ (IORESOURCE_IO | IORESOURCE_PCI_FIXED | IORESOURCE_SIZEALIGN);
+ region &= ~(size - 1);
+
+ /* Convert from PCI bus to resource space */
+ bus_region.start = region;
+ bus_region.end = region + size - 1;
+ pcibios_bus_to_resource(dev, res, &bus_region);
+
+ dev_info(&dev->dev, FW_BUG "%s quirk: reg 0x%x: %pR\n",
+ name, PCI_BASE_ADDRESS_0 + (pos << 2), res);
+}
+
/*
* Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
* ver. 1.33 20070103) don't set the correct ISA PCI region header info.
* BAR0 should be 8 bytes; instead, it may be set to something like 8k
* (which conflicts w/ BAR1's memory range).
+ *
+ * CS553x's ISA PCI BARs may also be read-only (ref:
+ * https://bugzilla.kernel.org/show_bug.cgi?id=85991 - Comment #4 forward).
*/
static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
{
+ static char *name = "CS5536 ISA bridge";
+
if (pci_resource_len(dev, 0) != 8) {
- struct resource *res = &dev->resource[0];
- res->end = res->start + 8 - 1;
- dev_info(&dev->dev, "CS5536 ISA bridge bug detected "
- "(incorrect header); workaround applied.\n");
+ quirk_io(dev, 0, 8, name); /* SMB */
+ quirk_io(dev, 1, 256, name); /* GPIO */
+ quirk_io(dev, 2, 64, name); /* MFGPT */
+ dev_info(&dev->dev, "%s bug detected (incorrect header); workaround applied\n",
+ name);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
@@ -1887,6 +1941,15 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
+static void quirk_f0_vpd_link(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) != PCI_CLASS_NETWORK_ETHERNET ||
+ !dev->multifunction || !PCI_FUNC(dev->devfn))
+ return;
+ dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_f0_vpd_link);
+
static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
{
u16 command, pmcsr;
@@ -2793,7 +2856,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
#endif /*CONFIG_MMC_RICOH_MMC*/
-#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+#ifdef CONFIG_DMAR_TABLE
#define VTUNCERRMSK_REG 0x1ac
#define VTD_MSK_SPEC_ERRORS (1 << 31)
/*
@@ -2821,12 +2884,96 @@ static void __devinit fixup_ti816x_class(struct pci_dev* dev)
{
/* TI 816x devices do not have class code set when in PCIe boot mode */
if (dev->class == PCI_CLASS_NOT_DEFINED) {
- dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
- dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8;
+ dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n",
+ PCI_CLASS_NOT_DEFINED, dev->class);
}
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class);
+/* Some PCIe devices do not work reliably with the claimed maximum
+ * payload size supported.
+ */
+static void __devinit fixup_mpss_256(struct pci_dev *dev)
+{
+ dev->pcie_mpss = 1; /* 256 bytes */
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0, fixup_mpss_256);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1, fixup_mpss_256);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000B, fixup_mpss_256);
+
+/* Intel 5000 and 5100 Memory controllers have an errata with read completion
+ * coalescing (which is enabled by default on some BIOSes) and MPS of 256B.
+ * Since there is no way of knowing what the PCIE MPS on each fabric will be
+ * until all of the devices are discovered and buses walked, read completion
+ * coalescing must be disabled. Unfortunately, it cannot be re-enabled because
+ * it is possible to hotplug a device with MPS of 256B.
+ */
+static void __devinit quirk_intel_mc_errata(struct pci_dev *dev)
+{
+ int err;
+ u16 rcc;
+
+ if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
+ return;
+
+ /* Intel errata specifies bits to change but does not say what they are.
+ * Keeping them magical until such time as the registers and values can
+ * be explained.
+ */
+ err = pci_read_config_word(dev, 0x48, &rcc);
+ if (err) {
+ dev_err(&dev->dev, "Error attempting to read the read "
+ "completion coalescing register.\n");
+ return;
+ }
+
+ if (!(rcc & (1 << 10)))
+ return;
+
+ rcc &= ~(1 << 10);
+
+ err = pci_write_config_word(dev, 0x48, rcc);
+ if (err) {
+ dev_err(&dev->dev, "Error attempting to write the read "
+ "completion coalescing register.\n");
+ return;
+ }
+
+ pr_info_once("Read completion coalescing disabled due to hardware "
+ "errata relating to 256B MPS.\n");
+}
+/* Intel 5000 series memory controllers and ports 2-7 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25c0, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25d0, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25d4, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25d8, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e2, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e3, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e4, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e5, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e6, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25f7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25f8, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25f9, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25fa, quirk_intel_mc_errata);
+/* Intel 5100 series memory controllers and ports 2-7 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65c0, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e2, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e3, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e4, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e5, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e6, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f8, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
+
/*
* Some BIOS implementations leave the Intel GPU interrupts enabled,
* even though no one is handling them (f.e. i915 driver is never loaded).
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 36864a9..e31659c 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -7,6 +7,7 @@
* PCI ROM access routines
*/
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/pci.h>
#include <linux/slab.h>
@@ -68,6 +69,7 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
{
void __iomem *image;
int last_image;
+ unsigned length;
image = rom;
do {
@@ -90,9 +92,9 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
if (readb(pds + 3) != 'R')
break;
last_image = readb(pds + 21) & 0x80;
- /* this length is reliable */
- image += readw(pds + 16) * 512;
- } while (!last_image);
+ length = readw(pds + 16);
+ image += length * 512;
+ } while (length && !last_image);
/* never return a size larger than the PCI resource window */
/* there are known ROMs that get the size wrong */
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 49e0323..9d932f4 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -125,18 +125,18 @@ static inline void reset_resource(struct resource *res)
}
/**
- * adjust_resources_sorted() - satisfy any additional resource requests
+ * reassign_resources_sorted() - satisfy any additional resource requests
*
- * @add_head : head of the list tracking requests requiring additional
+ * @realloc_head : head of the list tracking requests requiring additional
* resources
* @head : head of the list tracking requests with allocated
* resources
*
- * Walk through each element of the add_head and try to procure
+ * Walk through each element of the realloc_head and try to procure
* additional resources for the element, provided the element
* is in the head list.
*/
-static void adjust_resources_sorted(struct resource_list_x *add_head,
+static void reassign_resources_sorted(struct resource_list_x *realloc_head,
struct resource_list *head)
{
struct resource *res;
@@ -145,8 +145,8 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
resource_size_t add_size;
int idx;
- prev = add_head;
- for (list = add_head->next; list;) {
+ prev = realloc_head;
+ for (list = realloc_head->next; list;) {
res = list->res;
/* skip resource that has been reset */
if (!res->flags)
@@ -164,6 +164,7 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
idx = res - &list->dev->resource[0];
add_size=list->add_size;
if (!resource_size(res)) {
+ res->start = list->start;
res->end = res->start + add_size - 1;
if(pci_assign_resource(list->dev, idx))
reset_resource(res);
@@ -217,16 +218,16 @@ static void assign_requested_resources_sorted(struct resource_list *head,
}
static void __assign_resources_sorted(struct resource_list *head,
- struct resource_list_x *add_head,
+ struct resource_list_x *realloc_head,
struct resource_list_x *fail_head)
{
/* Satisfy the must-have resource requests */
assign_requested_resources_sorted(head, fail_head);
- /* Try to satisfy any additional nice-to-have resource
+ /* Try to satisfy any additional optional resource
requests */
- if (add_head)
- adjust_resources_sorted(add_head, head);
+ if (realloc_head)
+ reassign_resources_sorted(realloc_head, head);
free_list(resource_list, head);
}
@@ -242,7 +243,7 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
}
static void pbus_assign_resources_sorted(const struct pci_bus *bus,
- struct resource_list_x *add_head,
+ struct resource_list_x *realloc_head,
struct resource_list_x *fail_head)
{
struct pci_dev *dev;
@@ -252,7 +253,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
list_for_each_entry(dev, &bus->devices, bus_list)
__dev_sort_resources(dev, &head);
- __assign_resources_sorted(&head, add_head, fail_head);
+ __assign_resources_sorted(&head, realloc_head, fail_head);
}
void pci_setup_cardbus(struct pci_bus *bus)
@@ -343,7 +344,6 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
/* Clear upper 16 bits of I/O base/limit. */
io_upper16 = 0;
l = 0x00f0;
- dev_info(&bridge->dev, " bridge window [io disabled]\n");
}
/* Temporarily disable the I/O range before updating PCI_IO_BASE. */
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
@@ -369,7 +369,6 @@ static void pci_setup_bridge_mmio(struct pci_bus *bus)
dev_info(&bridge->dev, " bridge window %pR\n", res);
} else {
l = 0x0000fff0;
- dev_info(&bridge->dev, " bridge window [mem disabled]\n");
}
pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
}
@@ -400,7 +399,6 @@ static void pci_setup_bridge_mmio_pref(struct pci_bus *bus)
dev_info(&bridge->dev, " bridge window %pR\n", res);
} else {
l = 0x0000fff0;
- dev_info(&bridge->dev, " bridge window [mem pref disabled]\n");
}
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
@@ -428,7 +426,7 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
}
-static void pci_setup_bridge(struct pci_bus *bus)
+void pci_setup_bridge(struct pci_bus *bus)
{
unsigned long type = IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_PREFETCH;
@@ -550,13 +548,13 @@ static resource_size_t calculate_memsize(resource_size_t size,
return size;
}
-static resource_size_t get_res_add_size(struct resource_list_x *add_head,
+static resource_size_t get_res_add_size(struct resource_list_x *realloc_head,
struct resource *res)
{
struct resource_list_x *list;
- /* check if it is in add_head list */
- for (list = add_head->next; list && list->res != res;
+ /* check if it is in realloc_head list */
+ for (list = realloc_head->next; list && list->res != res;
list = list->next);
if (list)
return list->add_size;
@@ -570,7 +568,7 @@ static resource_size_t get_res_add_size(struct resource_list_x *add_head,
* @bus : the bus
* @min_size : the minimum io window that must to be allocated
* @add_size : additional optional io window
- * @add_head : track the additional io window on this list
+ * @realloc_head : track the additional io window on this list
*
* Sizing the IO windows of the PCI-PCI bridge is trivial,
* since these windows have 4K granularity and the IO ranges
@@ -578,7 +576,7 @@ static resource_size_t get_res_add_size(struct resource_list_x *add_head,
* We must be careful with the ISA aliasing though.
*/
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
- resource_size_t add_size, struct resource_list_x *add_head)
+ resource_size_t add_size, struct resource_list_x *realloc_head)
{
struct pci_dev *dev;
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
@@ -605,15 +603,15 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
else
size1 += r_size;
- if (add_head)
- children_add_size += get_res_add_size(add_head, r);
+ if (realloc_head)
+ children_add_size += get_res_add_size(realloc_head, r);
}
}
size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), 4096);
if (children_add_size > add_size)
add_size = children_add_size;
- size1 = (!add_head || (add_head && !add_size)) ? size0 :
+ size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
calculate_iosize(size, min_size, add_size + size1,
resource_size(b_res), 4096);
if (!size0 && !size1) {
@@ -628,8 +626,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
b_res->start = 4096;
b_res->end = b_res->start + size0 - 1;
b_res->flags |= IORESOURCE_STARTALIGN;
- if (size1 > size0 && add_head)
- add_to_list(add_head, bus->self, b_res, size1-size0, 4096);
+ if (size1 > size0 && realloc_head)
+ add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
}
/**
@@ -638,7 +636,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
* @bus : the bus
* @min_size : the minimum memory window that must to be allocated
* @add_size : additional optional memory window
- * @add_head : track the additional memory window on this list
+ * @realloc_head : track the additional memory window on this list
*
* Calculate the size of the bus and minimal alignment which
* guarantees that all child resources fit in this size.
@@ -646,7 +644,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
unsigned long type, resource_size_t min_size,
resource_size_t add_size,
- struct resource_list_x *add_head)
+ struct resource_list_x *realloc_head)
{
struct pci_dev *dev;
resource_size_t min_align, align, size, size0, size1;
@@ -676,6 +674,16 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (r->parent || (r->flags & mask) != type)
continue;
r_size = resource_size(r);
+#ifdef CONFIG_PCI_IOV
+ /* put SRIOV requested res to the optional list */
+ if (realloc_head && i >= PCI_IOV_RESOURCES &&
+ i <= PCI_IOV_RESOURCE_END) {
+ r->end = r->start - 1;
+ add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */);
+ children_add_size += r_size;
+ continue;
+ }
+#endif
/* For bridges size != alignment */
align = pci_resource_alignment(dev, r);
order = __ffs(align) - 20;
@@ -697,8 +705,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
max_order = order;
mem64_mask &= r->flags & IORESOURCE_MEM_64;
- if (add_head)
- children_add_size += get_res_add_size(add_head, r);
+ if (realloc_head)
+ children_add_size += get_res_add_size(realloc_head, r);
}
}
align = 0;
@@ -717,7 +725,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
if (children_add_size > add_size)
add_size = children_add_size;
- size1 = (!add_head || (add_head && !add_size)) ? size0 :
+ size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
calculate_memsize(size, min_size, add_size,
resource_size(b_res), min_align);
if (!size0 && !size1) {
@@ -731,12 +739,22 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
b_res->start = min_align;
b_res->end = size0 + min_align - 1;
b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
- if (size1 > size0 && add_head)
- add_to_list(add_head, bus->self, b_res, size1-size0, min_align);
+ if (size1 > size0 && realloc_head)
+ add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
return 1;
}
-static void pci_bus_size_cardbus(struct pci_bus *bus)
+unsigned long pci_cardbus_resource_alignment(struct resource *res)
+{
+ if (res->flags & IORESOURCE_IO)
+ return pci_cardbus_io_size;
+ if (res->flags & IORESOURCE_MEM)
+ return pci_cardbus_mem_size;
+ return 0;
+}
+
+static void pci_bus_size_cardbus(struct pci_bus *bus,
+ struct resource_list_x *realloc_head)
{
struct pci_dev *bridge = bus->self;
struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
@@ -747,12 +765,14 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
* a fixed amount of bus space for CardBus bridges.
*/
b_res[0].start = 0;
- b_res[0].end = pci_cardbus_io_size - 1;
b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+ if (realloc_head)
+ add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */);
b_res[1].start = 0;
- b_res[1].end = pci_cardbus_io_size - 1;
b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+ if (realloc_head)
+ add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */);
/*
* Check whether prefetchable memory is supported
@@ -772,21 +792,31 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
*/
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
b_res[2].start = 0;
- b_res[2].end = pci_cardbus_mem_size - 1;
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
+ if (realloc_head)
+ add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */);
b_res[3].start = 0;
- b_res[3].end = pci_cardbus_mem_size - 1;
b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+ if (realloc_head)
+ add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */);
} else {
b_res[3].start = 0;
- b_res[3].end = pci_cardbus_mem_size * 2 - 1;
b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+ if (realloc_head)
+ add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */);
}
+
+ /* set the size of the resource to zero, so that the resource does not
+ * get assigned during required-resource allocation cycle but gets assigned
+ * during the optional-resource allocation cycle.
+ */
+ b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1;
+ b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0;
}
void __ref __pci_bus_size_bridges(struct pci_bus *bus,
- struct resource_list_x *add_head)
+ struct resource_list_x *realloc_head)
{
struct pci_dev *dev;
unsigned long mask, prefmask;
@@ -799,12 +829,12 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
switch (dev->class >> 8) {
case PCI_CLASS_BRIDGE_CARDBUS:
- pci_bus_size_cardbus(b);
+ pci_bus_size_cardbus(b, realloc_head);
break;
case PCI_CLASS_BRIDGE_PCI:
default:
- __pci_bus_size_bridges(b, add_head);
+ __pci_bus_size_bridges(b, realloc_head);
break;
}
}
@@ -828,7 +858,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
* Follow thru
*/
default:
- pbus_size_io(bus, 0, additional_io_size, add_head);
+ pbus_size_io(bus, 0, additional_io_size, realloc_head);
/* If the bridge supports prefetchable range, size it
separately. If it doesn't, or its prefetchable window
has already been allocated by arch code, try
@@ -836,11 +866,11 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
resources. */
mask = IORESOURCE_MEM;
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
- if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head))
+ if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, realloc_head))
mask = prefmask; /* Success, size non-prefetch only. */
else
additional_mem_size += additional_mem_size;
- pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head);
+ pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, realloc_head);
break;
}
}
@@ -852,20 +882,20 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
EXPORT_SYMBOL(pci_bus_size_bridges);
static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
- struct resource_list_x *add_head,
+ struct resource_list_x *realloc_head,
struct resource_list_x *fail_head)
{
struct pci_bus *b;
struct pci_dev *dev;
- pbus_assign_resources_sorted(bus, add_head, fail_head);
+ pbus_assign_resources_sorted(bus, realloc_head, fail_head);
list_for_each_entry(dev, &bus->devices, bus_list) {
b = dev->subordinate;
if (!b)
continue;
- __pci_bus_assign_resources(b, add_head, fail_head);
+ __pci_bus_assign_resources(b, realloc_head, fail_head);
switch (dev->class >> 8) {
case PCI_CLASS_BRIDGE_PCI:
@@ -1075,7 +1105,7 @@ void __init
pci_assign_unassigned_resources(void)
{
struct pci_bus *bus;
- struct resource_list_x add_list; /* list of resources that
+ struct resource_list_x realloc_list; /* list of resources that
want additional resources */
int tried_times = 0;
enum release_type rel_type = leaf_only;
@@ -1088,7 +1118,7 @@ pci_assign_unassigned_resources(void)
head.next = NULL;
- add_list.next = NULL;
+ realloc_list.next = NULL;
pci_try_num = max_depth + 1;
printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
@@ -1098,12 +1128,12 @@ again:
/* Depth first, calculate sizes and alignments of all
subordinate buses. */
list_for_each_entry(bus, &pci_root_buses, node)
- __pci_bus_size_bridges(bus, &add_list);
+ __pci_bus_size_bridges(bus, &realloc_list);
/* Depth last, allocate resources and update the hardware. */
list_for_each_entry(bus, &pci_root_buses, node)
- __pci_bus_assign_resources(bus, &add_list, &head);
- BUG_ON(add_list.next);
+ __pci_bus_assign_resources(bus, &realloc_list, &head);
+ BUG_ON(realloc_list.next);
tried_times++;
/* any device complain? */
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
index eec9738..eb219a1 100644
--- a/drivers/pci/setup-irq.c
+++ b/drivers/pci/setup-irq.c
@@ -21,7 +21,7 @@
static void __init
pdev_fixup_irq(struct pci_dev *dev,
u8 (*swizzle)(struct pci_dev *, u8 *),
- int (*map_irq)(struct pci_dev *, u8, u8))
+ int (*map_irq)(const struct pci_dev *, u8, u8))
{
u8 pin, slot;
int irq = 0;
@@ -56,7 +56,7 @@ pdev_fixup_irq(struct pci_dev *dev,
void __init
pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
- int (*map_irq)(struct pci_dev *, u8, u8))
+ int (*map_irq)(const struct pci_dev *, u8, u8))
{
struct pci_dev *dev = NULL;
for_each_pci_dev(dev)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index e426149..41f08e5 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -74,8 +75,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
resno, new, check);
}
- if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
- (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+ if (res->flags & IORESOURCE_MEM_64) {
new = region.start >> 16 >> 16;
pci_write_config_dword(dev, reg + 4, new);
pci_read_config_dword(dev, reg + 4, &check);
@@ -158,7 +158,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
return ret;
}
-static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
+static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
int resno, resource_size_t size)
{
struct resource *root, *conflict;
@@ -188,7 +188,8 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
return ret;
}
-static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align)
+static int _pci_assign_resource(struct pci_dev *dev, int resno,
+ resource_size_t size, resource_size_t min_align)
{
struct resource *res = dev->resource + resno;
struct pci_bus *bus;
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 968cfea..ac6412f 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -7,6 +7,7 @@
#include <linux/kobject.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/err.h>
#include "pci.h"
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index a5a5ca1..39b7907 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -6,6 +6,7 @@
*/
#include <linux/pci.h>
+#include <linux/export.h>
int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt)
{
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index d4e7a10..90832a9 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -16,7 +16,7 @@
#include <xen/interface/io/pciif.h>
#include <asm/xen/pci.h>
#include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/time.h>
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index cb0ff91..4902206 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -99,9 +99,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
int vcc = cf->board->vcc_pin;
*sp = SS_DETECT | SS_3VCARD;
- if (!rdy || gpio_get_value(cf->board->irq_pin))
+ if (!rdy || gpio_get_value(rdy))
*sp |= SS_READY;
- if (!vcc || gpio_get_value(cf->board->vcc_pin))
+ if (!vcc || gpio_get_value(vcc))
*sp |= SS_POWERON;
} else
*sp = 0;
@@ -283,8 +283,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
}
/* reserve chip-select regions */
- if (!request_mem_region(io->start, io->end + 1 - io->start,
- driver_name)) {
+ if (!request_mem_region(io->start, resource_size(io), driver_name)) {
status = -ENXIO;
goto fail1;
}
@@ -308,7 +307,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
return 0;
fail2:
- release_mem_region(io->start, io->end + 1 - io->start);
+ release_mem_region(io->start, resource_size(io));
fail1:
if (cf->socket.io_offset)
iounmap((void __iomem *) cf->socket.io_offset);
@@ -339,7 +338,7 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
struct resource *io = cf->socket.io[0].res;
pcmcia_unregister_socket(&cf->socket);
- release_mem_region(io->start, io->end + 1 - io->start);
+ release_mem_region(io->start, resource_size(io));
iounmap((void __iomem *) cf->socket.io_offset);
if (board->irq_pin) {
free_irq(board->irq_pin, cf);
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index 01757f1..3e49df6 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -24,6 +24,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/slab.h>
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 6defd4a..06ad3e5 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -209,9 +209,9 @@ static int __devinit electra_cf_probe(struct platform_device *ofdev)
cf->ofdev = ofdev;
cf->mem_phys = mem.start;
- cf->mem_size = PAGE_ALIGN(mem.end - mem.start);
+ cf->mem_size = PAGE_ALIGN(resource_size(&mem));
cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
- cf->io_size = PAGE_ALIGN(io.end - io.start);
+ cf->io_size = PAGE_ALIGN(resource_size(&io));
area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
if (area == NULL)
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c
index 4c3e94c..22a75e6 100644
--- a/drivers/pcmcia/pxa2xx_balloon3.c
+++ b/drivers/pcmcia/pxa2xx_balloon3.c
@@ -97,28 +97,18 @@ static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
- __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG |
+ __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG +
((state->flags & SS_RESET) ?
BALLOON3_FPGA_SETnCLR : 0));
return 0;
}
-static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level balloon3_pcmcia_ops = {
.owner = THIS_MODULE,
.hw_init = balloon3_pcmcia_hw_init,
.hw_shutdown = balloon3_pcmcia_hw_shutdown,
.socket_state = balloon3_pcmcia_socket_state,
.configure_socket = balloon3_pcmcia_configure_socket,
- .socket_init = balloon3_pcmcia_socket_init,
- .socket_suspend = balloon3_pcmcia_socket_suspend,
.first = 0,
.nr = 1,
};
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 2c54054..a87e272 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -231,6 +231,7 @@ void pxa2xx_configure_sockets(struct device *dev)
__raw_writel(mecr, MECR);
}
+EXPORT_SYMBOL(pxa2xx_configure_sockets);
static const char *skt_names[] = {
"PCMCIA socket 0",
diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c
index 05913d0..0b4f946 100644
--- a/drivers/pcmcia/pxa2xx_cm_x255.c
+++ b/drivers/pcmcia/pxa2xx_cm_x255.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/export.h>
#include <asm/mach-types.h>
@@ -102,23 +103,12 @@ static int cmx255_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void cmx255_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void cmx255_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
-
static struct pcmcia_low_level cmx255_pcmcia_ops __initdata = {
.owner = THIS_MODULE,
.hw_init = cmx255_pcmcia_hw_init,
.hw_shutdown = cmx255_pcmcia_shutdown,
.socket_state = cmx255_pcmcia_socket_state,
.configure_socket = cmx255_pcmcia_configure_socket,
- .socket_init = cmx255_pcmcia_socket_init,
- .socket_suspend = cmx255_pcmcia_socket_suspend,
.nr = 1,
};
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index 5662646..923f315 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/export.h>
#include <asm/mach-types.h>
@@ -82,23 +83,12 @@ static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
-
static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
.owner = THIS_MODULE,
.hw_init = cmx270_pcmcia_hw_init,
.hw_shutdown = cmx270_pcmcia_shutdown,
.socket_state = cmx270_pcmcia_socket_state,
.configure_socket = cmx270_pcmcia_configure_socket,
- .socket_init = cmx270_pcmcia_socket_init,
- .socket_suspend = cmx270_pcmcia_socket_suspend,
.nr = 1,
};
diff --git a/drivers/pcmcia/pxa2xx_cm_x2xx.c b/drivers/pcmcia/pxa2xx_cm_x2xx.c
index 4f09506..6e7dcfd 100644
--- a/drivers/pcmcia/pxa2xx_cm_x2xx.c
+++ b/drivers/pcmcia/pxa2xx_cm_x2xx.c
@@ -12,9 +12,8 @@
#include <linux/module.h>
-#include <asm/system.h>
#include <asm/mach-types.h>
-#include <mach/system.h>
+#include <mach/hardware.h>
int cmx255_pcmcia_init(void);
int cmx270_pcmcia_init(void);
diff --git a/drivers/pcmcia/pxa2xx_colibri.c b/drivers/pcmcia/pxa2xx_colibri.c
index 443cb7f..c6dec57 100644
--- a/drivers/pcmcia/pxa2xx_colibri.c
+++ b/drivers/pcmcia/pxa2xx_colibri.c
@@ -116,14 +116,6 @@ colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void colibri_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void colibri_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level colibri_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -135,9 +127,6 @@ static struct pcmcia_low_level colibri_pcmcia_ops = {
.socket_state = colibri_pcmcia_socket_state,
.configure_socket = colibri_pcmcia_configure_socket,
-
- .socket_init = colibri_pcmcia_socket_init,
- .socket_suspend = colibri_pcmcia_socket_suspend,
};
static struct platform_device *colibri_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 92016fe..aded706c 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -128,22 +128,12 @@ static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return ret;
}
-static void mst_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
.owner = THIS_MODULE,
.hw_init = mst_pcmcia_hw_init,
.hw_shutdown = mst_pcmcia_hw_shutdown,
.socket_state = mst_pcmcia_socket_state,
.configure_socket = mst_pcmcia_configure_socket,
- .socket_init = mst_pcmcia_socket_init,
- .socket_suspend = mst_pcmcia_socket_suspend,
.nr = 2,
};
diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c
index 69f7367..d589ad1 100644
--- a/drivers/pcmcia/pxa2xx_palmld.c
+++ b/drivers/pcmcia/pxa2xx_palmld.c
@@ -65,14 +65,6 @@ static int palmld_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void palmld_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level palmld_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -84,9 +76,6 @@ static struct pcmcia_low_level palmld_pcmcia_ops = {
.socket_state = palmld_pcmcia_socket_state,
.configure_socket = palmld_pcmcia_configure_socket,
-
- .socket_init = palmld_pcmcia_socket_init,
- .socket_suspend = palmld_pcmcia_socket_suspend,
};
static struct platform_device *palmld_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c
index d0ad6a7..9c6a04b 100644
--- a/drivers/pcmcia/pxa2xx_palmtc.c
+++ b/drivers/pcmcia/pxa2xx_palmtc.c
@@ -117,14 +117,6 @@ static int palmtc_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return ret;
}
-static void palmtc_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmtc_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level palmtc_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -136,9 +128,6 @@ static struct pcmcia_low_level palmtc_pcmcia_ops = {
.socket_state = palmtc_pcmcia_socket_state,
.configure_socket = palmtc_pcmcia_configure_socket,
-
- .socket_init = palmtc_pcmcia_socket_init,
- .socket_suspend = palmtc_pcmcia_socket_suspend,
};
static struct platform_device *palmtc_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c
index 1a25804..80645a6 100644
--- a/drivers/pcmcia/pxa2xx_palmtx.c
+++ b/drivers/pcmcia/pxa2xx_palmtx.c
@@ -67,14 +67,6 @@ palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void palmtx_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmtx_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level palmtx_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -86,9 +78,6 @@ static struct pcmcia_low_level palmtx_pcmcia_ops = {
.socket_state = palmtx_pcmcia_socket_state,
.configure_socket = palmtx_pcmcia_configure_socket,
-
- .socket_init = palmtx_pcmcia_socket_init,
- .socket_suspend = palmtx_pcmcia_socket_suspend,
};
static struct platform_device *palmtx_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 097fa00..b938163 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -48,9 +48,6 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
- if (platform_scoop_config->pcmcia_init)
- platform_scoop_config->pcmcia_init();
-
/* Register interrupts */
if (SCOOP_DEV[skt->nr].cd_irq >= 0) {
struct pcmcia_irqs cd_irq;
diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c
index d08802f..9396222 100644
--- a/drivers/pcmcia/pxa2xx_stargate2.c
+++ b/drivers/pcmcia/pxa2xx_stargate2.c
@@ -28,7 +28,6 @@
#include "soc_common.h"
-#define SG2_S0_BUFF_CTL 120
#define SG2_S0_POWER_CTL 108
#define SG2_S0_GPIO_RESET 82
#define SG2_S0_GPIO_DETECT 53
@@ -38,6 +37,11 @@ static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" },
};
+static struct gpio sg2_pcmcia_gpios[] = {
+ { SG2_S0_GPIO_RESET, GPIOF_OUT_INIT_HIGH, "PCMCIA Reset" },
+ { SG2_S0_POWER_CTL, GPIOF_OUT_INIT_HIGH, "PCMCIA Power Ctrl" },
+};
+
static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
skt->socket.pci_irq = IRQ_GPIO(SG2_S0_GPIO_READY);
@@ -122,37 +126,23 @@ static int __init sg2_pcmcia_init(void)
if (!sg2_pcmcia_device)
return -ENOMEM;
- ret = gpio_request(SG2_S0_BUFF_CTL, "SG2 CF buff ctl");
+ ret = gpio_request_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
if (ret)
goto error_put_platform_device;
- ret = gpio_request(SG2_S0_POWER_CTL, "SG2 CF power ctl");
- if (ret)
- goto error_free_gpio_buff_ctl;
- ret = gpio_request(SG2_S0_GPIO_RESET, "SG2 CF reset");
- if (ret)
- goto error_free_gpio_power_ctl;
- /* Set gpio directions */
- gpio_direction_output(SG2_S0_BUFF_CTL, 0);
- gpio_direction_output(SG2_S0_POWER_CTL, 1);
- gpio_direction_output(SG2_S0_GPIO_RESET, 1);
ret = platform_device_add_data(sg2_pcmcia_device,
&sg2_pcmcia_ops,
sizeof(sg2_pcmcia_ops));
if (ret)
- goto error_free_gpio_reset;
+ goto error_free_gpios;
ret = platform_device_add(sg2_pcmcia_device);
if (ret)
- goto error_free_gpio_reset;
+ goto error_free_gpios;
return 0;
-error_free_gpio_reset:
- gpio_free(SG2_S0_GPIO_RESET);
-error_free_gpio_power_ctl:
- gpio_free(SG2_S0_POWER_CTL);
-error_free_gpio_buff_ctl:
- gpio_free(SG2_S0_BUFF_CTL);
+error_free_gpios:
+ gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
error_put_platform_device:
platform_device_put(sg2_pcmcia_device);
@@ -162,9 +152,7 @@ error_put_platform_device:
static void __exit sg2_pcmcia_exit(void)
{
platform_device_unregister(sg2_pcmcia_device);
- gpio_free(SG2_S0_BUFF_CTL);
- gpio_free(SG2_S0_POWER_CTL);
- gpio_free(SG2_S0_GPIO_RESET);
+ gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
}
fs_initcall(sg2_pcmcia_init);
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
index b829e65..57ddb96 100644
--- a/drivers/pcmcia/pxa2xx_trizeps4.c
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -55,10 +55,6 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
}
skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY);
break;
-
-#ifndef CONFIG_MACH_TRIZEPS_CONXS
- case 1:
-#endif
default:
break;
}
diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c
index a51f207..1064b1c 100644
--- a/drivers/pcmcia/pxa2xx_viper.c
+++ b/drivers/pcmcia/pxa2xx_viper.c
@@ -136,22 +136,12 @@ static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void viper_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level viper_pcmcia_ops = {
.owner = THIS_MODULE,
.hw_init = viper_pcmcia_hw_init,
.hw_shutdown = viper_pcmcia_hw_shutdown,
.socket_state = viper_pcmcia_socket_state,
.configure_socket = viper_pcmcia_configure_socket,
- .socket_init = viper_pcmcia_socket_init,
- .socket_suspend = viper_pcmcia_socket_suspend,
.nr = 1,
};
diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c
index e956f65..66ab92c 100644
--- a/drivers/pcmcia/pxa2xx_vpac270.c
+++ b/drivers/pcmcia/pxa2xx_vpac270.c
@@ -17,7 +17,7 @@
#include <asm/mach-types.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <mach/vpac270.h>
#include "soc_common.h"
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 523eb69..f53c237 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -135,7 +135,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
try = res->end + 1;
if ((*base == 0) || (*base == try)) {
if (adjust_resource(s->io[i].res, res->start,
- res->end - res->start + num + 1))
+ resource_size(res) + num))
continue;
*base = try;
s->io[i].InUse += num;
@@ -147,8 +147,8 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
try = res->start - num;
if ((*base == 0) || (*base == try)) {
if (adjust_resource(s->io[i].res,
- res->start - num,
- res->end - res->start + num + 1))
+ res->start - num,
+ resource_size(res) + num))
continue;
*base = try;
s->io[i].InUse += num;
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index b187555..9da9656 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -770,7 +770,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
res->end + num);
if (!ret) {
ret = adjust_resource(s->io[i].res, res->start,
- res->end - res->start + num + 1);
+ resource_size(res) + num);
if (ret)
continue;
*base = try;
@@ -788,8 +788,8 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
res->end);
if (!ret) {
ret = adjust_resource(s->io[i].res,
- res->start - num,
- res->end - res->start + num + 1);
+ res->start - num,
+ resource_size(res) + num);
if (ret)
continue;
*base = try;
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index c998f7a..0fac965 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -15,10 +15,6 @@
#include <mach/simpad.h>
#include "sa1100_generic.h"
-extern long get_cs3_shadow(void);
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);
-
static struct pcmcia_irqs irqs[] = {
{ 1, IRQ_GPIO_CF_CD, "CF_CD" },
};
@@ -26,7 +22,7 @@ static struct pcmcia_irqs irqs[] = {
static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
skt->socket.pci_irq = IRQ_GPIO_CF_IRQ;
@@ -38,8 +34,8 @@ static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF bus: */
- //set_cs3_bit(PCMCIA_BUFF_DIS);
- clear_cs3_bit(PCMCIA_RESET);
+ /*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
+ simpad_clear_cs3_bit(PCMCIA_RESET);
}
static void
@@ -47,15 +43,16 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
unsigned long levels = GPLR;
- long cs3reg = get_cs3_shadow();
+ long cs3reg = simpad_get_cs3_ro();
state->detect=((levels & GPIO_CF_CD)==0)?1:0;
state->ready=(levels & GPIO_CF_IRQ)?1:0;
- state->bvd1=1; /* Not available on Simpad. */
- state->bvd2=1; /* Not available on Simpad. */
+ state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */
+ state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */
state->wrprot=0; /* Not available on Simpad. */
-
- if((cs3reg & 0x0c) == 0x0c) {
+
+ if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
+ (PCMCIA_VS1|PCMCIA_VS2)) {
state->vs_3v=0;
state->vs_Xv=0;
} else {
@@ -75,23 +72,23 @@ simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
/* Murphy: see table of MIC2562a-1 */
switch (state->Vcc) {
case 0:
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
break;
case 33:
- clear_cs3_bit(VCC_3V_EN|EN1);
- set_cs3_bit(VCC_5V_EN|EN0);
+ simpad_clear_cs3_bit(VCC_3V_EN|EN1);
+ simpad_set_cs3_bit(VCC_5V_EN|EN0);
break;
case 50:
- clear_cs3_bit(VCC_5V_EN|EN1);
- set_cs3_bit(VCC_3V_EN|EN0);
+ simpad_clear_cs3_bit(VCC_5V_EN|EN1);
+ simpad_set_cs3_bit(VCC_3V_EN|EN0);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__func__, state->Vcc);
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
local_irq_restore(flags);
return -1;
}
@@ -110,7 +107,7 @@ static void simpad_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
{
soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
- set_cs3_bit(PCMCIA_RESET);
+ simpad_set_cs3_bit(PCMCIA_RESET);
}
static struct pcmcia_low_level simpad_pcmcia_ops = {
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 768f957..a0a9c2a 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -186,8 +186,8 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
debug(skt, 2, "initializing socket\n");
-
- skt->ops->socket_init(skt);
+ if (skt->ops->socket_init)
+ skt->ops->socket_init(skt);
return 0;
}
@@ -207,7 +207,8 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
debug(skt, 2, "suspending socket\n");
- skt->ops->socket_suspend(skt);
+ if (skt->ops->socket_suspend)
+ skt->ops->socket_suspend(skt);
return 0;
}
diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h
index 615a45a..582688f 100644
--- a/drivers/pcmcia/topic.h
+++ b/drivers/pcmcia/topic.h
@@ -104,6 +104,9 @@
#define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */
#define TOPIC_EXCA_IFC_33V_ENA 0x01
+#define TOPIC_PCI_CFG_PPBCN 0x3e /* 16-bit */
+#define TOPIC_PCI_CFG_PPBCN_WBEN 0x0400
+
static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
@@ -138,6 +141,7 @@ static int topic97_override(struct yenta_socket *socket)
static int topic95_override(struct yenta_socket *socket)
{
u8 fctrl;
+ u16 ppbcn;
/* enable 3.3V support for 16bit cards */
fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL);
@@ -146,6 +150,18 @@ static int topic95_override(struct yenta_socket *socket)
/* tell yenta to use exca registers to power 16bit cards */
socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF;
+ /* Disable write buffers to prevent lockups under load with numerous
+ Cardbus cards, observed on Tecra 500CDT and reported elsewhere on the
+ net. This is not a power-on default according to the datasheet
+ but some BIOSes seem to set it. */
+ if (pci_read_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, &ppbcn) == 0
+ && socket->dev->revision <= 7
+ && (ppbcn & TOPIC_PCI_CFG_PPBCN_WBEN)) {
+ ppbcn &= ~TOPIC_PCI_CFG_PPBCN_WBEN;
+ pci_write_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, ppbcn);
+ dev_info(&socket->dev->dev, "Disabled ToPIC95 Cardbus write buffers.\n");
+ }
+
return 0;
}
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 45e0191..7f43cf8 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -31,9 +31,6 @@ config ACER_WMI
wireless radio and bluetooth control, and on some laptops,
exposes the mail LED and LCD backlight.
- For more information about this driver see
- <file:Documentation/laptops/acer-wmi.txt>
-
If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
here.
@@ -64,15 +61,18 @@ config ASUS_LAPTOP
depends on INPUT
depends on RFKILL || RFKILL = n
select INPUT_SPARSEKMAP
+ select INPUT_POLLDEV
---help---
- This is the new Linux driver for Asus laptops. It may also support some
- MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
- standard ACPI events and input events. It also adds
- support for video output switching, LCD backlight control, Bluetooth and
- Wlan control, and most importantly, allows you to blink those fancy LEDs.
+ This is a driver for Asus laptops, Lenovo SL and the Pegatron
+ Lucid tablet. It may also support some MEDION, JVC or VICTOR
+ laptops. It makes all the extra buttons generate standard
+ ACPI events and input events, and on the Lucid the built-in
+ accelerometer appears as an input device. It also adds
+ support for video output switching, LCD backlight control,
+ Bluetooth and Wlan control, and most importantly, allows you
+ to blink those fancy LEDs.
- For more information and a userspace daemon for handling the extra
- buttons see <http://acpi4asus.sf.net>.
+ For more information see <http://acpi4asus.sf.net>.
If you have an ACPI-compatible ASUS laptop, say Y or M here.
@@ -83,8 +83,10 @@ config DELL_LAPTOP
depends on EXPERIMENTAL
depends on BACKLIGHT_CLASS_DEVICE
depends on RFKILL || RFKILL = n
- depends on POWER_SUPPLY
depends on SERIO_I8042
+ select POWER_SUPPLY
+ select LEDS_CLASS
+ select NEW_LEDS
default n
---help---
This driver adds support for rfkill and backlight control to Dell
@@ -164,7 +166,7 @@ config HP_ACCEL
Support for a led indicating disk protection will be provided as
hp::hddprotect. For more information on the feature, refer to
- Documentation/hwmon/lis3lv02d.
+ Documentation/misc-devices/lis3lv02d.
To compile this driver as a module, choose M here: the module will
be called hp_accel.
@@ -769,4 +771,12 @@ config INTEL_OAKTRAIL
enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
here; it will only load on supported platforms.
+config SAMSUNG_Q10
+ tristate "Samsung Q10 Extras"
+ depends on SERIO_I8042
+ select BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This driver provides support for backlight control on Samsung Q10
+ and related laptops, including Dell Latitude X200.
+
endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index afc1f83..293a320 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
+obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 202b567..7d47434 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -99,6 +99,7 @@ enum acer_wmi_event_ids {
static const struct key_entry acer_wmi_keymap[] = {
{KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
{KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
+ {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */
{KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
{KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
{KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
@@ -190,6 +191,7 @@ enum interface_flags {
ACER_AMW0,
ACER_AMW0_V2,
ACER_WMID,
+ ACER_WMID_v2,
};
#define ACER_DEFAULT_WIRELESS 0
@@ -205,6 +207,7 @@ static int threeg = -1;
static int force_series;
static bool ec_raw_mode;
static bool has_type_aa;
+static u16 commun_func_bitmap;
module_param(mailled, int, 0444);
module_param(brightness, int, 0444);
@@ -906,6 +909,174 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
return WMI_execute_u32(method_id, (u32)value, NULL);
}
+static acpi_status wmid3_get_device_status(u32 *value, u16 device)
+{
+ struct wmid3_gds_return_value return_value;
+ acpi_status status;
+ union acpi_object *obj;
+ struct wmid3_gds_input_param params = {
+ .function_num = 0x1,
+ .hotkey_number = 0x01,
+ .devices = device,
+ };
+ struct acpi_buffer input = {
+ sizeof(struct wmid3_gds_input_param),
+ &params
+ };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 8) {
+ pr_warn("Unknown buffer length %d\n", obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
+ device,
+ return_value.error_code,
+ return_value.ec_return_value);
+ else
+ *value = !!(return_value.devices & device);
+
+ return status;
+}
+
+static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
+{
+ u16 device;
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ device = ACER_WMID3_GDS_WIRELESS;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ device = ACER_WMID3_GDS_BLUETOOTH;
+ break;
+ case ACER_CAP_THREEG:
+ device = ACER_WMID3_GDS_THREEG;
+ break;
+ default:
+ return AE_ERROR;
+ }
+ return wmid3_get_device_status(value, device);
+}
+
+static acpi_status wmid3_set_device_status(u32 value, u16 device)
+{
+ struct wmid3_gds_return_value return_value;
+ acpi_status status;
+ union acpi_object *obj;
+ u16 devices;
+ struct wmid3_gds_input_param params = {
+ .function_num = 0x1,
+ .hotkey_number = 0x01,
+ .devices = commun_func_bitmap,
+ };
+ struct acpi_buffer input = {
+ sizeof(struct wmid3_gds_input_param),
+ &params
+ };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 8) {
+ pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ if (return_value.error_code || return_value.ec_return_value) {
+ pr_warning("Get Current Device Status failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+ return status;
+ }
+
+ devices = return_value.devices;
+ params.function_num = 0x2;
+ params.hotkey_number = 0x01;
+ params.devices = (value) ? (devices | device) : (devices & ~device);
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output2.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 4) {
+ pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ pr_warning("Set Device Status failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+
+ return status;
+}
+
+static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
+{
+ u16 device;
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ device = ACER_WMID3_GDS_WIRELESS;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ device = ACER_WMID3_GDS_BLUETOOTH;
+ break;
+ case ACER_CAP_THREEG:
+ device = ACER_WMID3_GDS_THREEG;
+ break;
+ default:
+ return AE_ERROR;
+ }
+ return wmid3_set_device_status(value, device);
+}
+
static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
{
struct hotkey_function_type_aa *type_aa;
@@ -919,6 +1090,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
pr_info("Function bitmap for Communication Button: 0x%x\n",
type_aa->commun_func_bitmap);
+ commun_func_bitmap = type_aa->commun_func_bitmap;
if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
interface->capability |= ACER_CAP_WIRELESS;
@@ -951,17 +1123,13 @@ static acpi_status WMID_set_capabilities(void)
return AE_ERROR;
}
- dmi_walk(type_aa_dmi_decode, NULL);
- if (!has_type_aa) {
+ pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
+ if (devices & 0x07)
interface->capability |= ACER_CAP_WIRELESS;
- if (devices & 0x40)
- interface->capability |= ACER_CAP_THREEG;
- if (devices & 0x10)
- interface->capability |= ACER_CAP_BLUETOOTH;
- }
-
- /* WMID always provides brightness methods */
- interface->capability |= ACER_CAP_BRIGHTNESS;
+ if (devices & 0x40)
+ interface->capability |= ACER_CAP_THREEG;
+ if (devices & 0x10)
+ interface->capability |= ACER_CAP_BLUETOOTH;
if (!(devices & 0x20))
max_brightness = 0x9;
@@ -974,6 +1142,10 @@ static struct wmi_interface wmid_interface = {
.type = ACER_WMID,
};
+static struct wmi_interface wmid_v2_interface = {
+ .type = ACER_WMID_v2,
+};
+
/*
* Generic Device (interface-independent)
*/
@@ -994,6 +1166,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
case ACER_WMID:
status = WMID_get_u32(value, cap, interface);
break;
+ case ACER_WMID_v2:
+ if (cap & (ACER_CAP_WIRELESS |
+ ACER_CAP_BLUETOOTH |
+ ACER_CAP_THREEG))
+ status = wmid_v2_get_u32(value, cap);
+ else if (wmi_has_guid(WMID_GUID2))
+ status = WMID_get_u32(value, cap, interface);
+ break;
}
return status;
@@ -1027,6 +1207,13 @@ static acpi_status set_u32(u32 value, u32 cap)
}
case ACER_WMID:
return WMID_set_u32(value, cap, interface);
+ case ACER_WMID_v2:
+ if (cap & (ACER_CAP_WIRELESS |
+ ACER_CAP_BLUETOOTH |
+ ACER_CAP_THREEG))
+ return wmid_v2_set_u32(value, cap);
+ else if (wmi_has_guid(WMID_GUID2))
+ return WMID_set_u32(value, cap, interface);
default:
return AE_BAD_PARAMETER;
}
@@ -1133,186 +1320,6 @@ static void acer_backlight_exit(void)
backlight_device_unregister(acer_backlight_device);
}
-static acpi_status wmid3_get_device_status(u32 *value, u16 device)
-{
- struct wmid3_gds_return_value return_value;
- acpi_status status;
- union acpi_object *obj;
- struct wmid3_gds_input_param params = {
- .function_num = 0x1,
- .hotkey_number = 0x01,
- .devices = device,
- };
- struct acpi_buffer input = {
- sizeof(struct wmid3_gds_input_param),
- &params
- };
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-
- status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
- if (ACPI_FAILURE(status))
- return status;
-
- obj = output.pointer;
-
- if (!obj)
- return AE_ERROR;
- else if (obj->type != ACPI_TYPE_BUFFER) {
- kfree(obj);
- return AE_ERROR;
- }
- if (obj->buffer.length != 8) {
- pr_warn("Unknown buffer length %d\n", obj->buffer.length);
- kfree(obj);
- return AE_ERROR;
- }
-
- return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
- kfree(obj);
-
- if (return_value.error_code || return_value.ec_return_value)
- pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
- return_value.error_code,
- return_value.ec_return_value);
- else
- *value = !!(return_value.devices & device);
-
- return status;
-}
-
-static acpi_status get_device_status(u32 *value, u32 cap)
-{
- if (wmi_has_guid(WMID_GUID3)) {
- u16 device;
-
- switch (cap) {
- case ACER_CAP_WIRELESS:
- device = ACER_WMID3_GDS_WIRELESS;
- break;
- case ACER_CAP_BLUETOOTH:
- device = ACER_WMID3_GDS_BLUETOOTH;
- break;
- case ACER_CAP_THREEG:
- device = ACER_WMID3_GDS_THREEG;
- break;
- default:
- return AE_ERROR;
- }
- return wmid3_get_device_status(value, device);
-
- } else {
- return get_u32(value, cap);
- }
-}
-
-static acpi_status wmid3_set_device_status(u32 value, u16 device)
-{
- struct wmid3_gds_return_value return_value;
- acpi_status status;
- union acpi_object *obj;
- u16 devices;
- struct wmid3_gds_input_param params = {
- .function_num = 0x1,
- .hotkey_number = 0x01,
- .devices = ACER_WMID3_GDS_WIRELESS |
- ACER_WMID3_GDS_THREEG |
- ACER_WMID3_GDS_WIMAX |
- ACER_WMID3_GDS_BLUETOOTH,
- };
- struct acpi_buffer input = {
- sizeof(struct wmid3_gds_input_param),
- &params
- };
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
-
- status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
- if (ACPI_FAILURE(status))
- return status;
-
- obj = output.pointer;
-
- if (!obj)
- return AE_ERROR;
- else if (obj->type != ACPI_TYPE_BUFFER) {
- kfree(obj);
- return AE_ERROR;
- }
- if (obj->buffer.length != 8) {
- pr_warning("Unknown buffer length %d\n", obj->buffer.length);
- kfree(obj);
- return AE_ERROR;
- }
-
- return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
- kfree(obj);
-
- if (return_value.error_code || return_value.ec_return_value) {
- pr_warning("Get Current Device Status failed: "
- "0x%x - 0x%x\n", return_value.error_code,
- return_value.ec_return_value);
- return status;
- }
-
- devices = return_value.devices;
- params.function_num = 0x2;
- params.hotkey_number = 0x01;
- params.devices = (value) ? (devices | device) : (devices & ~device);
-
- status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
- if (ACPI_FAILURE(status))
- return status;
-
- obj = output2.pointer;
-
- if (!obj)
- return AE_ERROR;
- else if (obj->type != ACPI_TYPE_BUFFER) {
- kfree(obj);
- return AE_ERROR;
- }
- if (obj->buffer.length != 4) {
- pr_warning("Unknown buffer length %d\n", obj->buffer.length);
- kfree(obj);
- return AE_ERROR;
- }
-
- return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
- kfree(obj);
-
- if (return_value.error_code || return_value.ec_return_value)
- pr_warning("Set Device Status failed: "
- "0x%x - 0x%x\n", return_value.error_code,
- return_value.ec_return_value);
-
- return status;
-}
-
-static acpi_status set_device_status(u32 value, u32 cap)
-{
- if (wmi_has_guid(WMID_GUID3)) {
- u16 device;
-
- switch (cap) {
- case ACER_CAP_WIRELESS:
- device = ACER_WMID3_GDS_WIRELESS;
- break;
- case ACER_CAP_BLUETOOTH:
- device = ACER_WMID3_GDS_BLUETOOTH;
- break;
- case ACER_CAP_THREEG:
- device = ACER_WMID3_GDS_THREEG;
- break;
- default:
- return AE_ERROR;
- }
- return wmid3_set_device_status(value, device);
-
- } else {
- return set_u32(value, cap);
- }
-}
-
/*
* Rfkill devices
*/
@@ -1340,8 +1347,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
}
if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
- status = wmid3_get_device_status(&state,
- ACER_WMID3_GDS_THREEG);
+ status = get_u32(&state, ACER_WMID3_GDS_THREEG);
if (ACPI_SUCCESS(status))
rfkill_set_sw_state(threeg_rfkill, !state);
}
@@ -1355,7 +1361,7 @@ static int acer_rfkill_set(void *data, bool blocked)
u32 cap = (unsigned long)data;
if (rfkill_inited) {
- status = set_device_status(!blocked, cap);
+ status = set_u32(!blocked, cap);
if (ACPI_FAILURE(status))
return -ENODEV;
}
@@ -1382,7 +1388,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
if (!rfkill_dev)
return ERR_PTR(-ENOMEM);
- status = get_device_status(&state, cap);
+ status = get_u32(&state, cap);
err = rfkill_register(rfkill_dev);
if (err) {
@@ -1483,11 +1489,10 @@ static ssize_t show_bool_threeg(struct device *dev,
{
u32 result; \
acpi_status status;
- if (wmi_has_guid(WMID_GUID3))
- status = wmid3_get_device_status(&result,
- ACER_WMID3_GDS_THREEG);
- else
- status = get_u32(&result, ACER_CAP_THREEG);
+
+ pr_info("This threeg sysfs will be removed in 2012"
+ " - used by: %s\n", current->comm);
+ status = get_u32(&result, ACER_CAP_THREEG);
if (ACPI_SUCCESS(status))
return sprintf(buf, "%u\n", result);
return sprintf(buf, "Read error\n");
@@ -1498,8 +1503,10 @@ static ssize_t set_bool_threeg(struct device *dev,
{
u32 tmp = simple_strtoul(buf, NULL, 10);
acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
- if (ACPI_FAILURE(status))
- return -EINVAL;
+ pr_info("This threeg sysfs will be removed in 2012"
+ " - used by: %s\n", current->comm);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
return count;
}
static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
@@ -1508,6 +1515,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ pr_info("This interface sysfs will be removed in 2012"
+ " - used by: %s\n", current->comm);
switch (interface->type) {
case ACER_AMW0:
return sprintf(buf, "AMW0\n");
@@ -1515,6 +1524,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "AMW0 v2\n");
case ACER_WMID:
return sprintf(buf, "WMID\n");
+ case ACER_WMID_v2:
+ return sprintf(buf, "WMID v2\n");
default:
return sprintf(buf, "Error!\n");
}
@@ -1934,12 +1945,20 @@ static int __init acer_wmi_init(void)
if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
interface = &wmid_interface;
+ if (wmi_has_guid(WMID_GUID3))
+ interface = &wmid_v2_interface;
+
+ if (interface)
+ dmi_walk(type_aa_dmi_decode, NULL);
+
if (wmi_has_guid(WMID_GUID2) && interface) {
- if (ACPI_FAILURE(WMID_set_capabilities())) {
+ if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
pr_err("Unable to detect available WMID devices\n");
return -ENODEV;
}
- } else if (!wmi_has_guid(WMID_GUID2) && interface) {
+ /* WMID always provides brightness methods */
+ interface->capability |= ACER_CAP_BRIGHTNESS;
+ } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
pr_err("No WMID device detection method found\n");
return -ENODEV;
}
@@ -1963,7 +1982,7 @@ static int __init acer_wmi_init(void)
set_quirks();
- if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
+ if (acpi_video_backlight_support()) {
interface->capability &= ~ACER_CAP_BRIGHTNESS;
pr_info("Brightness must be controlled by "
"generic video driver\n");
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index fca3489..760c6d7 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -182,6 +182,7 @@ static const struct bios_settings_t bios_tbl[] = {
{"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
+ {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
/* Acer 531 */
{"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
/* Gateway */
@@ -703,15 +704,15 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Feuerer");
MODULE_DESCRIPTION("Aspire One temperature and fan driver");
MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
-MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:");
-MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
module_init(acerhdf_init);
module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index f0bf9c2..3a09460 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
* Copyright (C) 2006-2007 Corentin Chary
+ * Copyright (C) 2011 Wind River Systems
*
* 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
@@ -48,6 +49,7 @@
#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/input-polldev.h>
#include <linux/rfkill.h>
#include <linux/slab.h>
#include <linux/dmi.h>
@@ -70,11 +72,10 @@ MODULE_LICENSE("GPL");
* WAPF defines the behavior of the Fn+Fx wlan key
* The significance of values is yet to be found, but
* most of the time:
- * 0x0 will do nothing
- * 0x1 will allow to control the device with Fn+Fx key.
- * 0x4 will send an ACPI event (0x88) while pressing the Fn+Fx key
- * 0x5 like 0x1 or 0x4
- * So, if something doesn't work as you want, just try other values =)
+ * Bit | Bluetooth | WLAN
+ * 0 | Hardware | Hardware
+ * 1 | Hardware | Software
+ * 4 | Software | Software
*/
static uint wapf = 1;
module_param(wapf, uint, 0444);
@@ -84,26 +85,32 @@ static int wlan_status = 1;
static int bluetooth_status = 1;
static int wimax_status = -1;
static int wwan_status = -1;
+static int als_status;
module_param(wlan_status, int, 0444);
MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
module_param(bluetooth_status, int, 0444);
MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
module_param(wimax_status, int, 0444);
MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
module_param(wwan_status, int, 0444);
MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
+
+module_param(als_status, int, 0444);
+MODULE_PARM_DESC(als_status, "Set the ALS status on boot "
+ "(0 = disabled, 1 = enabled). "
+ "default is 0");
/*
* Some events we use, same for all Asus
@@ -174,6 +181,29 @@ MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
#define METHOD_KBD_LIGHT_SET "SLKB"
#define METHOD_KBD_LIGHT_GET "GLKB"
+/* For Pegatron Lucid tablet */
+#define DEVICE_NAME_PEGA "Lucid"
+
+#define METHOD_PEGA_ENABLE "ENPR"
+#define METHOD_PEGA_DISABLE "DAPR"
+#define PEGA_WLAN 0x00
+#define PEGA_BLUETOOTH 0x01
+#define PEGA_WWAN 0x02
+#define PEGA_ALS 0x04
+#define PEGA_ALS_POWER 0x05
+
+#define METHOD_PEGA_READ "RDLN"
+#define PEGA_READ_ALS_H 0x02
+#define PEGA_READ_ALS_L 0x03
+
+#define PEGA_ACCEL_NAME "pega_accel"
+#define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer"
+#define METHOD_XLRX "XLRX"
+#define METHOD_XLRY "XLRY"
+#define METHOD_XLRZ "XLRZ"
+#define PEGA_ACC_CLAMP 512 /* 1G accel is reported as ~256, so clamp to 2G */
+#define PEGA_ACC_RETRIES 3
+
/*
* Define a specific led structure to keep the main structure clean
*/
@@ -186,6 +216,15 @@ struct asus_led {
};
/*
+ * Same thing for rfkill
+ */
+struct asus_pega_rfkill {
+ int control_id; /* type of control. Maps to PEGA_* values */
+ struct rfkill *rfkill;
+ struct asus_laptop *asus;
+};
+
+/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
@@ -199,6 +238,7 @@ struct asus_laptop {
struct input_dev *inputdev;
struct key_entry *keymap;
+ struct input_polled_dev *pega_accel_poll;
struct asus_led mled;
struct asus_led tled;
@@ -210,9 +250,18 @@ struct asus_laptop {
int wireless_status;
bool have_rsts;
+ bool is_pega_lucid;
+ bool pega_acc_live;
+ int pega_acc_x;
+ int pega_acc_y;
+ int pega_acc_z;
struct rfkill *gps_rfkill;
+ struct asus_pega_rfkill wlanrfk;
+ struct asus_pega_rfkill btrfk;
+ struct asus_pega_rfkill wwanrfk;
+
acpi_handle handle; /* the handle of the hotk device */
u32 ledd_status; /* status of the LED display */
u8 light_level; /* light sensor level */
@@ -324,6 +373,127 @@ static int acpi_check_handle(acpi_handle handle, const char *method,
return 0;
}
+static bool asus_check_pega_lucid(struct asus_laptop *asus)
+{
+ return !strcmp(asus->name, DEVICE_NAME_PEGA) &&
+ !acpi_check_handle(asus->handle, METHOD_PEGA_ENABLE, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_PEGA_DISABLE, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_PEGA_READ, NULL);
+}
+
+static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable)
+{
+ char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE;
+ return write_acpi_int(asus->handle, method, unit);
+}
+
+static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method)
+{
+ int i, delta;
+ unsigned long long val;
+ for (i = 0; i < PEGA_ACC_RETRIES; i++) {
+ acpi_evaluate_integer(asus->handle, method, NULL, &val);
+
+ /* The output is noisy. From reading the ASL
+ * dissassembly, timeout errors are returned with 1's
+ * in the high word, and the lack of locking around
+ * thei hi/lo byte reads means that a transition
+ * between (for example) -1 and 0 could be read as
+ * 0xff00 or 0x00ff. */
+ delta = abs(curr - (short)val);
+ if (delta < 128 && !(val & ~0xffff))
+ break;
+ }
+ return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP);
+}
+
+static void pega_accel_poll(struct input_polled_dev *ipd)
+{
+ struct device *parent = ipd->input->dev.parent;
+ struct asus_laptop *asus = dev_get_drvdata(parent);
+
+ /* In some cases, the very first call to poll causes a
+ * recursive fault under the polldev worker. This is
+ * apparently related to very early userspace access to the
+ * device, and perhaps a firmware bug. Fake the first report. */
+ if (!asus->pega_acc_live) {
+ asus->pega_acc_live = true;
+ input_report_abs(ipd->input, ABS_X, 0);
+ input_report_abs(ipd->input, ABS_Y, 0);
+ input_report_abs(ipd->input, ABS_Z, 0);
+ input_sync(ipd->input);
+ return;
+ }
+
+ asus->pega_acc_x = pega_acc_axis(asus, asus->pega_acc_x, METHOD_XLRX);
+ asus->pega_acc_y = pega_acc_axis(asus, asus->pega_acc_y, METHOD_XLRY);
+ asus->pega_acc_z = pega_acc_axis(asus, asus->pega_acc_z, METHOD_XLRZ);
+
+ /* Note transform, convert to "right/up/out" in the native
+ * landscape orientation (i.e. the vector is the direction of
+ * "real up" in the device's cartiesian coordinates). */
+ input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x);
+ input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y);
+ input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z);
+ input_sync(ipd->input);
+}
+
+static void pega_accel_exit(struct asus_laptop *asus)
+{
+ if (asus->pega_accel_poll) {
+ input_unregister_polled_device(asus->pega_accel_poll);
+ input_free_polled_device(asus->pega_accel_poll);
+ }
+ asus->pega_accel_poll = NULL;
+}
+
+static int pega_accel_init(struct asus_laptop *asus)
+{
+ int err;
+ struct input_polled_dev *ipd;
+
+ if (!asus->is_pega_lucid)
+ return -ENODEV;
+
+ if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) ||
+ acpi_check_handle(asus->handle, METHOD_XLRY, NULL) ||
+ acpi_check_handle(asus->handle, METHOD_XLRZ, NULL))
+ return -ENODEV;
+
+ ipd = input_allocate_polled_device();
+ if (!ipd)
+ return -ENOMEM;
+
+ ipd->poll = pega_accel_poll;
+ ipd->poll_interval = 125;
+ ipd->poll_interval_min = 50;
+ ipd->poll_interval_max = 2000;
+
+ ipd->input->name = PEGA_ACCEL_DESC;
+ ipd->input->phys = PEGA_ACCEL_NAME "/input0";
+ ipd->input->dev.parent = &asus->platform_device->dev;
+ ipd->input->id.bustype = BUS_HOST;
+
+ set_bit(EV_ABS, ipd->input->evbit);
+ input_set_abs_params(ipd->input, ABS_X,
+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
+ input_set_abs_params(ipd->input, ABS_Y,
+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
+ input_set_abs_params(ipd->input, ABS_Z,
+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
+
+ err = input_register_polled_device(ipd);
+ if (err)
+ goto exit;
+
+ asus->pega_accel_poll = ipd;
+ return 0;
+
+exit:
+ input_free_polled_device(ipd);
+ return err;
+}
+
/* Generic LED function */
static int asus_led_set(struct asus_laptop *asus, const char *method,
int value)
@@ -431,17 +601,17 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
static void asus_led_exit(struct asus_laptop *asus)
{
- if (asus->mled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->mled.led.dev))
led_classdev_unregister(&asus->mled.led);
- if (asus->tled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->tled.led.dev))
led_classdev_unregister(&asus->tled.led);
- if (asus->pled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->pled.led.dev))
led_classdev_unregister(&asus->pled.led);
- if (asus->rled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->rled.led.dev))
led_classdev_unregister(&asus->rled.led);
- if (asus->gled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->gled.led.dev))
led_classdev_unregister(&asus->gled.led);
- if (asus->kled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->kled.led.dev))
led_classdev_unregister(&asus->kled.led);
if (asus->led_workqueue) {
destroy_workqueue(asus->led_workqueue);
@@ -475,6 +645,13 @@ static int asus_led_init(struct asus_laptop *asus)
int r;
/*
+ * The Pegatron Lucid has no physical leds, but all methods are
+ * available in the DSDT...
+ */
+ if (asus->is_pega_lucid)
+ return 0;
+
+ /*
* Functions that actually update the LED's are called from a
* workqueue. By doing this as separate work rather than when the LED
* subsystem asks, we avoid messing with the Asus ACPI stuff during a
@@ -910,8 +1087,18 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
*/
static void asus_als_switch(struct asus_laptop *asus, int value)
{
- if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value))
- pr_warn("Error setting light sensor switch\n");
+ int ret;
+
+ if (asus->is_pega_lucid) {
+ ret = asus_pega_lucid_set(asus, PEGA_ALS, value);
+ if (!ret)
+ ret = asus_pega_lucid_set(asus, PEGA_ALS_POWER, value);
+ } else {
+ ret = write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value);
+ }
+ if (ret)
+ pr_warning("Error setting light sensor switch\n");
+
asus->light_switch = value;
}
@@ -967,6 +1154,35 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
return rv;
}
+static int pega_int_read(struct asus_laptop *asus, int arg, int *result)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ int err = write_acpi_int_ret(asus->handle, METHOD_PEGA_READ, arg,
+ &buffer);
+ if (!err) {
+ union acpi_object *obj = buffer.pointer;
+ if (obj && obj->type == ACPI_TYPE_INTEGER)
+ *result = obj->integer.value;
+ else
+ err = -EIO;
+ }
+ return err;
+}
+
+static ssize_t show_lsvalue(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+ int err, hi, lo;
+
+ err = pega_int_read(asus, PEGA_READ_ALS_H, &hi);
+ if (!err)
+ err = pega_int_read(asus, PEGA_READ_ALS_L, &lo);
+ if (!err)
+ return sprintf(buf, "%d\n", 10 * hi + lo);
+ return err;
+}
+
/*
* GPS
*/
@@ -1065,6 +1281,86 @@ static int asus_rfkill_init(struct asus_laptop *asus)
return result;
}
+static int pega_rfkill_set(void *data, bool blocked)
+{
+ struct asus_pega_rfkill *pega_rfk = data;
+
+ int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
+ pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);
+
+ return ret;
+}
+
+static const struct rfkill_ops pega_rfkill_ops = {
+ .set_block = pega_rfkill_set,
+};
+
+static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
+{
+ pr_warn("Terminating %d\n", pega_rfk->control_id);
+ if (pega_rfk->rfkill) {
+ rfkill_unregister(pega_rfk->rfkill);
+ rfkill_destroy(pega_rfk->rfkill);
+ pega_rfk->rfkill = NULL;
+ }
+}
+
+static void pega_rfkill_exit(struct asus_laptop *asus)
+{
+ pega_rfkill_terminate(&asus->wwanrfk);
+ pega_rfkill_terminate(&asus->btrfk);
+ pega_rfkill_terminate(&asus->wlanrfk);
+}
+
+static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
+ const char *name, int controlid, int rfkill_type)
+{
+ int result;
+
+ pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
+ pega_rfk->control_id = controlid;
+ pega_rfk->asus = asus;
+ pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
+ rfkill_type, &pega_rfkill_ops, pega_rfk);
+ if (!pega_rfk->rfkill)
+ return -EINVAL;
+
+ result = rfkill_register(pega_rfk->rfkill);
+ if (result) {
+ rfkill_destroy(pega_rfk->rfkill);
+ pega_rfk->rfkill = NULL;
+ }
+
+ return result;
+}
+
+static int pega_rfkill_init(struct asus_laptop *asus)
+{
+ int ret = 0;
+
+ if(!asus->is_pega_lucid)
+ return -ENODEV;
+
+ ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
+ if(ret)
+ return ret;
+ ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
+ if(ret)
+ goto err_btrfk;
+ ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
+ if(ret)
+ goto err_wwanrfk;
+
+ pr_warn("Pega rfkill init succeeded\n");
+ return 0;
+err_wwanrfk:
+ pega_rfkill_terminate(&asus->btrfk);
+err_btrfk:
+ pega_rfkill_terminate(&asus->wlanrfk);
+
+ return ret;
+}
+
/*
* Input device (i.e. hotkeys)
*/
@@ -1144,6 +1440,14 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
}
return ;
}
+
+ /* Accelerometer "coarse orientation change" event */
+ if (asus->pega_accel_poll && event == 0xEA) {
+ kobject_uevent(&asus->pega_accel_poll->input->dev.kobj,
+ KOBJ_CHANGE);
+ return ;
+ }
+
asus_input_notify(asus, event);
}
@@ -1155,6 +1459,7 @@ static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
+static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL);
static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
@@ -1167,6 +1472,7 @@ static struct attribute *asus_attributes[] = {
&dev_attr_wwan.attr,
&dev_attr_display.attr,
&dev_attr_ledd.attr,
+ &dev_attr_ls_value.attr,
&dev_attr_ls_level.attr,
&dev_attr_ls_switch.attr,
&dev_attr_gps.attr,
@@ -1183,6 +1489,19 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
acpi_handle handle = asus->handle;
bool supported;
+ if (asus->is_pega_lucid) {
+ /* no ls_level interface on the Lucid */
+ if (attr == &dev_attr_ls_switch.attr)
+ supported = true;
+ else if (attr == &dev_attr_ls_level.attr)
+ supported = false;
+ else
+ goto normal;
+
+ return supported;
+ }
+
+normal:
if (attr == &dev_attr_wlan.attr) {
supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
@@ -1205,8 +1524,9 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
} else if (attr == &dev_attr_ls_switch.attr ||
attr == &dev_attr_ls_level.attr) {
supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
- !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
-
+ !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
+ } else if (attr == &dev_attr_ls_value.attr) {
+ supported = asus->is_pega_lucid;
} else if (attr == &dev_attr_gps.attr) {
supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
!acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
@@ -1261,7 +1581,7 @@ static struct platform_driver platform_driver = {
.driver = {
.name = ASUS_LAPTOP_FILE,
.owner = THIS_MODULE,
- }
+ },
};
/*
@@ -1380,11 +1700,13 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus->ledd_status = 0xFFF;
/* Set initial values of light sensor and level */
- asus->light_switch = 0; /* Default to light sensor disabled */
+ asus->light_switch = !!als_status;
asus->light_level = 5; /* level 5 for sensor sensitivity */
- if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
+ if (asus->is_pega_lucid) {
+ asus_als_switch(asus, asus->light_switch);
+ } else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
asus_als_switch(asus, asus->light_switch);
asus_als_level(asus, asus->light_level);
}
@@ -1431,9 +1753,10 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
goto fail_platform;
/*
- * Register the platform device first. It is used as a parent for the
- * sub-devices below.
+ * Need platform type detection first, then the platform
+ * device. It is used as a parent for the sub-devices below.
*/
+ asus->is_pega_lucid = asus_check_pega_lucid(asus);
result = asus_platform_init(asus);
if (result)
goto fail_platform;
@@ -1457,9 +1780,21 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
if (result)
goto fail_rfkill;
+ result = pega_accel_init(asus);
+ if (result && result != -ENODEV)
+ goto fail_pega_accel;
+
+ result = pega_rfkill_init(asus);
+ if (result && result != -ENODEV)
+ goto fail_pega_rfkill;
+
asus_device_present = true;
return 0;
+fail_pega_rfkill:
+ pega_accel_exit(asus);
+fail_pega_accel:
+ asus_rfkill_exit(asus);
fail_rfkill:
asus_led_exit(asus);
fail_led:
@@ -1483,6 +1818,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
asus_rfkill_exit(asus);
asus_led_exit(asus);
asus_input_exit(asus);
+ pega_accel_exit(asus);
+ pega_rfkill_exit(asus);
asus_platform_exit(asus);
kfree(asus->name);
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 9827fe9..ec5b17f 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -38,6 +38,24 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
+/*
+ * WAPF defines the behavior of the Fn+Fx wlan key
+ * The significance of values is yet to be found, but
+ * most of the time:
+ * Bit | Bluetooth | WLAN
+ * 0 | Hardware | Hardware
+ * 1 | Hardware | Software
+ * 4 | Software | Software
+ */
+static uint wapf;
+module_param(wapf, uint, 0444);
+MODULE_PARM_DESC(wapf, "WAPF value");
+
+static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
+{
+ driver->wapf = wapf;
+}
+
static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
@@ -53,16 +71,16 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x51, { KEY_WWW } },
{ KE_KEY, 0x55, { KEY_CALC } },
{ KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */
- { KE_KEY, 0x5D, { KEY_WLAN } },
- { KE_KEY, 0x5E, { KEY_WLAN } },
- { KE_KEY, 0x5F, { KEY_WLAN } },
+ { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
+ { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
+ { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */
{ KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
- { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
{ KE_KEY, 0x7D, { KEY_BLUETOOTH } },
+ { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
{ KE_KEY, 0x82, { KEY_CAMERA } },
{ KE_KEY, 0x88, { KEY_RFKILL } },
{ KE_KEY, 0x8A, { KEY_PROG1 } },
@@ -85,6 +103,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
.keymap = asus_nb_wmi_keymap,
.input_name = "Asus WMI hotkeys",
.input_phys = ASUS_NB_WMI_FILE "/input0",
+ .quirks = asus_nb_wmi_quirks,
};
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index e1678b9..26fba2d 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -44,6 +44,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h>
+#include <linux/thermal.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -66,6 +67,8 @@ MODULE_LICENSE("GPL");
#define NOTIFY_BRNUP_MAX 0x1f
#define NOTIFY_BRNDOWN_MIN 0x20
#define NOTIFY_BRNDOWN_MAX 0x2e
+#define NOTIFY_KBD_BRTUP 0xc4
+#define NOTIFY_KBD_BRTDWN 0xc5
/* WMI Methods */
#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */
@@ -93,6 +96,7 @@ MODULE_LICENSE("GPL");
/* Wireless */
#define ASUS_WMI_DEVID_HW_SWITCH 0x00010001
#define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002
+#define ASUS_WMI_DEVID_CWAP 0x00010003
#define ASUS_WMI_DEVID_WLAN 0x00010011
#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013
#define ASUS_WMI_DEVID_GPS 0x00010015
@@ -102,6 +106,12 @@ MODULE_LICENSE("GPL");
/* Leds */
/* 0x000200XX and 0x000400XX */
+#define ASUS_WMI_DEVID_LED1 0x00020011
+#define ASUS_WMI_DEVID_LED2 0x00020012
+#define ASUS_WMI_DEVID_LED3 0x00020013
+#define ASUS_WMI_DEVID_LED4 0x00020014
+#define ASUS_WMI_DEVID_LED5 0x00020015
+#define ASUS_WMI_DEVID_LED6 0x00020016
/* Backlight and Brightness */
#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011
@@ -174,13 +184,18 @@ struct asus_wmi {
struct led_classdev tpd_led;
int tpd_led_wk;
+ struct led_classdev kbd_led;
+ int kbd_led_wk;
struct workqueue_struct *led_workqueue;
struct work_struct tpd_led_work;
+ struct work_struct kbd_led_work;
struct asus_rfkill wlan;
struct asus_rfkill bluetooth;
struct asus_rfkill wimax;
struct asus_rfkill wwan3g;
+ struct asus_rfkill gps;
+ struct asus_rfkill uwb;
struct hotplug_slot *hotplug_slot;
struct mutex hotplug_lock;
@@ -205,6 +220,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
asus->inputdev->phys = asus->driver->input_phys;
asus->inputdev->id.bustype = BUS_HOST;
asus->inputdev->dev.parent = &asus->platform_device->dev;
+ set_bit(EV_REP, asus->inputdev->evbit);
err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
if (err)
@@ -359,40 +375,134 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
return read_tpd_led_state(asus);
}
-static int asus_wmi_led_init(struct asus_wmi *asus)
+static void kbd_led_update(struct work_struct *work)
{
- int rv;
+ int ctrl_param = 0;
+ struct asus_wmi *asus;
- if (read_tpd_led_state(asus) < 0)
- return 0;
+ asus = container_of(work, struct asus_wmi, kbd_led_work);
- asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
- if (!asus->led_workqueue)
- return -ENOMEM;
- INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+ /*
+ * bits 0-2: level
+ * bit 7: light on/off
+ */
+ if (asus->kbd_led_wk > 0)
+ ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
- asus->tpd_led.name = "asus::touchpad";
- asus->tpd_led.brightness_set = tpd_led_set;
- asus->tpd_led.brightness_get = tpd_led_get;
- asus->tpd_led.max_brightness = 1;
+ asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
+}
- rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
- if (rv) {
- destroy_workqueue(asus->led_workqueue);
- return rv;
+static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
+{
+ int retval;
+
+ /*
+ * bits 0-2: level
+ * bit 7: light on/off
+ * bit 8-10: environment (0: dark, 1: normal, 2: light)
+ * bit 17: status unknown
+ */
+ retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,
+ 0xFFFF);
+
+ /* Unknown status is considered as off */
+ if (retval == 0x8000)
+ retval = 0;
+
+ if (retval >= 0) {
+ if (level)
+ *level = retval & 0x80 ? retval & 0x7F : 0;
+ if (env)
+ *env = (retval >> 8) & 0x7F;
+ retval = 0;
}
- return 0;
+ return retval;
+}
+
+static void kbd_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct asus_wmi *asus;
+
+ asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+
+ if (value > asus->kbd_led.max_brightness)
+ value = asus->kbd_led.max_brightness;
+ else if (value < 0)
+ value = 0;
+
+ asus->kbd_led_wk = value;
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+ struct asus_wmi *asus;
+ int retval, value;
+
+ asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+
+ retval = kbd_led_read(asus, &value, NULL);
+
+ if (retval < 0)
+ return retval;
+
+ return value;
}
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
- if (asus->tpd_led.dev)
+ if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
+ led_classdev_unregister(&asus->kbd_led);
+ if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
led_classdev_unregister(&asus->tpd_led);
if (asus->led_workqueue)
destroy_workqueue(asus->led_workqueue);
}
+static int asus_wmi_led_init(struct asus_wmi *asus)
+{
+ int rv = 0;
+
+ asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+ if (!asus->led_workqueue)
+ return -ENOMEM;
+
+ if (read_tpd_led_state(asus) >= 0) {
+ INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+
+ asus->tpd_led.name = "asus::touchpad";
+ asus->tpd_led.brightness_set = tpd_led_set;
+ asus->tpd_led.brightness_get = tpd_led_get;
+ asus->tpd_led.max_brightness = 1;
+
+ rv = led_classdev_register(&asus->platform_device->dev,
+ &asus->tpd_led);
+ if (rv)
+ goto error;
+ }
+
+ if (kbd_led_read(asus, NULL, NULL) >= 0) {
+ INIT_WORK(&asus->kbd_led_work, kbd_led_update);
+
+ asus->kbd_led.name = "asus::kbd_backlight";
+ asus->kbd_led.brightness_set = kbd_led_set;
+ asus->kbd_led.brightness_get = kbd_led_get;
+ asus->kbd_led.max_brightness = 3;
+
+ rv = led_classdev_register(&asus->platform_device->dev,
+ &asus->kbd_led);
+ }
+
+error:
+ if (rv)
+ asus_wmi_led_exit(asus);
+
+ return rv;
+}
+
+
/*
* PCI hotplug (for wlan rfkill)
*/
@@ -729,6 +839,16 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
rfkill_destroy(asus->wwan3g.rfkill);
asus->wwan3g.rfkill = NULL;
}
+ if (asus->gps.rfkill) {
+ rfkill_unregister(asus->gps.rfkill);
+ rfkill_destroy(asus->gps.rfkill);
+ asus->gps.rfkill = NULL;
+ }
+ if (asus->uwb.rfkill) {
+ rfkill_unregister(asus->uwb.rfkill);
+ rfkill_destroy(asus->uwb.rfkill);
+ asus->uwb.rfkill = NULL;
+ }
}
static int asus_wmi_rfkill_init(struct asus_wmi *asus)
@@ -763,6 +883,18 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
if (result && result != -ENODEV)
goto exit;
+ result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
+ RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
+
+ if (result && result != -ENODEV)
+ goto exit;
+
+ result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
+ RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
+
+ if (result && result != -ENODEV)
+ goto exit;
+
if (!asus->driver->hotplug_wireless)
goto exit;
@@ -825,7 +957,26 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
return sprintf(buf, "%d\n", value);
}
+static ssize_t asus_hwmon_temp1(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+ u32 value;
+ int err;
+
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
+
+ if (err < 0)
+ return err;
+
+ value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
+
+ return sprintf(buf, "%d\n", value);
+}
+
static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0);
static ssize_t
show_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -836,12 +987,13 @@ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_name.dev_attr.attr,
NULL
};
static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
- struct attribute *attr, int idx)
+ struct attribute *attr, int idx)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct platform_device *pdev = to_platform_device(dev->parent);
@@ -852,12 +1004,14 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
dev_id = ASUS_WMI_DEVID_FAN_CTRL;
+ else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr)
+ dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
if (dev_id != -1) {
int err = asus_wmi_get_devstate(asus, dev_id, &value);
if (err < 0)
- return err;
+ return 0; /* can't return negative here */
}
if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
@@ -872,6 +1026,10 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
|| (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
ok = false;
+ } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
+ /* If value is zero, something is clearly wrong */
+ if (value == 0)
+ ok = false;
}
return ok ? attr->mode : 0;
@@ -1061,6 +1219,8 @@ static void asus_wmi_notify(u32 value, void *context)
acpi_status status;
int code;
int orig_code;
+ unsigned int key_value = 1;
+ bool autorelease = 1;
status = wmi_get_event_data(value, &response);
if (status != AE_OK) {
@@ -1076,6 +1236,13 @@ static void asus_wmi_notify(u32 value, void *context)
code = obj->integer.value;
orig_code = code;
+ if (asus->driver->key_filter) {
+ asus->driver->key_filter(asus->driver, &code, &key_value,
+ &autorelease);
+ if (code == ASUS_WMI_KEY_IGNORE)
+ goto exit;
+ }
+
if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
code = NOTIFY_BRNUP_MIN;
else if (code >= NOTIFY_BRNDOWN_MIN &&
@@ -1085,7 +1252,8 @@ static void asus_wmi_notify(u32 value, void *context)
if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
if (!acpi_video_backlight_support())
asus_wmi_backlight_notify(asus, orig_code);
- } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
+ } else if (!sparse_keymap_report_event(asus->inputdev, code,
+ key_value, autorelease))
pr_info("Unknown key %x pressed\n", code);
exit:
@@ -1239,7 +1407,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
/* We don't know yet what to do with this version... */
if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
- pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
+ pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF);
asus->spec = rv;
}
@@ -1263,13 +1431,14 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
*/
if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
asus->dsts_id = ASUS_WMI_METHODID_DSTS;
- else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
+ else
asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
- if (!asus->dsts_id) {
- pr_err("Can't find DSTS");
- return -ENODEV;
- }
+ /* CWAP allow to define the behavior of the Fn+F2 key,
+ * this method doesn't seems to be present on Eee PCs */
+ if (asus->driver->wapf >= 0)
+ asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
+ asus->driver->wapf, NULL);
return asus_wmi_sysfs_init(asus->platform_device);
}
@@ -1573,6 +1742,14 @@ static int asus_hotk_restore(struct device *device)
bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
}
+ if (asus->gps.rfkill) {
+ bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
+ rfkill_set_sw_state(asus->gps.rfkill, bl);
+ }
+ if (asus->uwb.rfkill) {
+ bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
+ rfkill_set_sw_state(asus->uwb.rfkill, bl);
+ }
return 0;
}
@@ -1609,7 +1786,7 @@ static int asus_wmi_probe(struct platform_device *pdev)
static bool used;
-int asus_wmi_register_driver(struct asus_wmi_driver *driver)
+int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
{
struct platform_driver *platform_driver;
struct platform_device *platform_device;
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
index c044522..8147c10 100644
--- a/drivers/platform/x86/asus-wmi.h
+++ b/drivers/platform/x86/asus-wmi.h
@@ -29,12 +29,15 @@
#include <linux/platform_device.h>
+#define ASUS_WMI_KEY_IGNORE (-1)
+
struct module;
struct key_entry;
struct asus_wmi;
struct asus_wmi_driver {
bool hotplug_wireless;
+ int wapf;
const char *name;
struct module *owner;
@@ -44,6 +47,10 @@ struct asus_wmi_driver {
const struct key_entry *keymap;
const char *input_name;
const char *input_phys;
+ /* Returns new code, value, and autorelease values in arguments.
+ * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
+ void (*key_filter) (struct asus_wmi_driver *driver, int *code,
+ unsigned int *value, bool *autorelease);
int (*probe) (struct platform_device *device);
void (*quirks) (struct asus_wmi_driver *driver);
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 8877b83..ba3638e 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -1046,7 +1046,14 @@ static int __devinit compal_probe(struct platform_device *pdev)
/* Power supply */
initialize_power_supply_data(data);
- power_supply_register(&compal_device->dev, &data->psy);
+ err = power_supply_register(&compal_device->dev, &data->psy);
+ if (err < 0) {
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&pdev->dev.kobj,
+ &compal_attribute_group);
+ kfree(data);
+ return err;
+ }
platform_set_drvdata(pdev, data);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index e39ab1d..e57f5de 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -60,6 +60,22 @@ struct calling_interface_structure {
struct calling_interface_token tokens[];
} __packed;
+struct quirk_entry {
+ u8 touchpad_led;
+};
+
+static struct quirk_entry *quirks;
+
+static struct quirk_entry quirk_dell_vostro_v130 = {
+ .touchpad_led = 1,
+};
+
+static int dmi_matched(const struct dmi_system_id *dmi)
+{
+ quirks = dmi->driver_data;
+ return 1;
+}
+
static int da_command_address;
static int da_command_code;
static int da_num_tokens;
@@ -149,8 +165,56 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = {
{}
};
+static struct dmi_system_id __devinitdata dell_quirks[] = {
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Vostro V130",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Vostro V131",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Vostro 3555",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Inspiron N311z",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Inspiron M5110",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+ { }
+};
+
static struct calling_interface_buffer *buffer;
-static struct page *bufferpage;
static DEFINE_MUTEX(buffer_mutex);
static int hwswitch_state;
@@ -552,6 +616,45 @@ static const struct backlight_ops dell_ops = {
.update_status = dell_send_intensity,
};
+static void touchpad_led_on(void)
+{
+ int command = 0x97;
+ char data = 1;
+ i8042_command(&data, command | 1 << 12);
+}
+
+static void touchpad_led_off(void)
+{
+ int command = 0x97;
+ char data = 2;
+ i8042_command(&data, command | 1 << 12);
+}
+
+static void touchpad_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value > 0)
+ touchpad_led_on();
+ else
+ touchpad_led_off();
+}
+
+static struct led_classdev touchpad_led = {
+ .name = "dell-laptop::touchpad",
+ .brightness_set = touchpad_led_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+};
+
+static int __devinit touchpad_led_init(struct device *dev)
+{
+ return led_classdev_register(dev, &touchpad_led);
+}
+
+static void touchpad_led_exit(void)
+{
+ led_classdev_unregister(&touchpad_led);
+}
+
static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
@@ -584,6 +687,10 @@ static int __init dell_init(void)
if (!dmi_check_system(dell_device_table))
return -ENODEV;
+ quirks = NULL;
+ /* find if this machine support other functions */
+ dmi_check_system(dell_quirks);
+
dmi_walk(find_tokens, NULL);
if (!da_tokens) {
@@ -607,12 +714,10 @@ static int __init dell_init(void)
* Allocate buffer below 4GB for SMI data--only 32-bit physical addr
* is passed to SMI handler.
*/
- bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32);
+ buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
- if (!bufferpage)
+ if (!buffer)
goto fail_buffer;
- buffer = page_address(bufferpage);
- mutex_init(&buffer_mutex);
ret = dell_setup_rfkill();
@@ -627,6 +732,9 @@ static int __init dell_init(void)
goto fail_filter;
}
+ if (quirks && quirks->touchpad_led)
+ touchpad_led_init(&platform_device->dev);
+
dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
if (dell_laptop_dir != NULL)
debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
@@ -678,7 +786,7 @@ fail_backlight:
fail_filter:
dell_cleanup_rfkill();
fail_rfkill:
- free_page((unsigned long)bufferpage);
+ free_page((unsigned long)buffer);
fail_buffer:
platform_device_del(platform_device);
fail_platform_device2:
@@ -693,6 +801,8 @@ fail_platform_driver:
static void __exit dell_exit(void)
{
debugfs_remove_recursive(dell_laptop_dir);
+ if (quirks && quirks->touchpad_led)
+ touchpad_led_exit();
i8042_remove_filter(dell_laptop_i8042_filter);
cancel_delayed_work_sync(&dell_rfkill_work);
backlight_device_unregister(dell_backlight_device);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index ce79082..fa9a217 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -54,6 +54,8 @@ MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
*/
static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
+ { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
+
{ KE_KEY, 0xe045, { KEY_PROG1 } },
{ KE_KEY, 0xe009, { KEY_EJECTCD } },
@@ -85,6 +87,11 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
{ KE_IGNORE, 0xe013, { KEY_RESERVED } },
{ KE_IGNORE, 0xe020, { KEY_MUTE } },
+
+ /* Shortcut and audio panel keys */
+ { KE_IGNORE, 0xe025, { KEY_RESERVED } },
+ { KE_IGNORE, 0xe026, { KEY_RESERVED } },
+
{ KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
{ KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
{ KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
@@ -92,6 +99,9 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
{ KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
{ KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
{ KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+ { KE_IGNORE, 0xe0f7, { KEY_MUTE } },
+ { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
+ { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
{ KE_END, 0 }
};
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 1c45d92..ea44abd 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -568,7 +568,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
static void eeepc_led_exit(struct eeepc_laptop *eeepc)
{
- if (eeepc->tpd_led.dev)
+ if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
led_classdev_unregister(&eeepc->tpd_led);
if (eeepc->led_workqueue)
destroy_workqueue(eeepc->led_workqueue);
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 4aa867a..9f6e643 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -56,6 +56,11 @@ MODULE_PARM_DESC(hotplug_wireless,
"If your laptop needs that, please report to "
"acpi4asus-user@lists.sourceforge.net.");
+/* Values for T101MT "Home" key */
+#define HOME_PRESS 0xe4
+#define HOME_HOLD 0xea
+#define HOME_RELEASE 0xe5
+
static const struct key_entry eeepc_wmi_keymap[] = {
/* Sleep already handled via generic ACPI code */
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
@@ -71,6 +76,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
{ KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
{ KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
+ { KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */
{ KE_KEY, 0xe8, { KEY_SCREENLOCK } },
{ KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
{ KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
@@ -81,6 +87,25 @@ static const struct key_entry eeepc_wmi_keymap[] = {
{ KE_END, 0},
};
+static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
+ unsigned int *value, bool *autorelease)
+{
+ switch (*code) {
+ case HOME_PRESS:
+ *value = 1;
+ *autorelease = 0;
+ break;
+ case HOME_HOLD:
+ *code = ASUS_WMI_KEY_IGNORE;
+ break;
+ case HOME_RELEASE:
+ *code = HOME_PRESS;
+ *value = 0;
+ *autorelease = 0;
+ break;
+ }
+}
+
static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
void *context, void **retval)
{
@@ -141,6 +166,7 @@ static void eeepc_dmi_check(struct asus_wmi_driver *driver)
static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
{
driver->hotplug_wireless = hotplug_wireless;
+ driver->wapf = -1;
eeepc_dmi_check(driver);
}
@@ -151,6 +177,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
.keymap = eeepc_wmi_keymap,
.input_name = "Eee PC WMI hotkeys",
.input_phys = EEEPC_WMI_FILE "/input0",
+ .key_filter = eeepc_wmi_key_filter,
.probe = eeepc_wmi_probe,
.quirks = eeepc_wmi_quirks,
};
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 1b52d00..be6b648 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -76,6 +76,8 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
/* For automatic insertion of the module */
static struct acpi_device_id lis3lv02d_device_ids[] = {
{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+ {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */
+ {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
@@ -209,6 +211,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
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),
+ AXIS_DMI_MATCH("NC854xx", "HP EliteBook 854", y_inverted),
+ AXIS_DMI_MATCH("NC273xx", "HP EliteBook 273", y_inverted),
/* Intel-based HP Pavilion dv5 */
AXIS_DMI_MATCH2("HPDV5_I",
PRODUCT_NAME, "HP Pavilion dv5",
@@ -227,7 +231,13 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
+ AXIS_DMI_MATCH("HPB655x", "HP ProBook 655", xy_swap_inverted),
AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
+ AXIS_DMI_MATCH("HPB63xx", "HP ProBook 63", xy_swap),
+ AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap),
+ AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
+ AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
+ AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted),
{ NULL, }
/* Laptop models without axis info (yet):
* "NC6910" "HP Compaq 6910"
@@ -320,7 +330,7 @@ static int lis3lv02d_add(struct acpi_device *device)
INIT_WORK(&hpled_led.work, delayed_set_status_worker);
ret = led_classdev_register(NULL, &hpled_led.led_classdev);
if (ret) {
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);
flush_work(&hpled_led.work);
return ret;
@@ -334,7 +344,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
if (!device)
return -EINVAL;
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);
led_classdev_unregister(&hpled_led.led_classdev);
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
index 811d436..2704386 100644
--- a/drivers/platform/x86/ibm_rtl.c
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -255,7 +255,7 @@ static int __init ibm_rtl_init(void) {
if (force)
pr_warn("module loaded by force\n");
/* first ensure that we are running on IBM HW */
- else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
+ else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table))
return -ENODEV;
/* Get the address for the Extended BIOS Data Area */
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index bfdda33..04a6928 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -32,16 +32,53 @@
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#define IDEAPAD_RFKILL_DEV_NUM (3)
+#define CFG_BT_BIT (16)
+#define CFG_3G_BIT (17)
+#define CFG_WIFI_BIT (18)
+#define CFG_CAMERA_BIT (19)
+
+enum {
+ VPCCMD_R_VPC1 = 0x10,
+ VPCCMD_R_BL_MAX,
+ VPCCMD_R_BL,
+ VPCCMD_W_BL,
+ VPCCMD_R_WIFI,
+ VPCCMD_W_WIFI,
+ VPCCMD_R_BT,
+ VPCCMD_W_BT,
+ VPCCMD_R_BL_POWER,
+ VPCCMD_R_NOVO,
+ VPCCMD_R_VPC2,
+ VPCCMD_R_TOUCHPAD,
+ VPCCMD_W_TOUCHPAD,
+ VPCCMD_R_CAMERA,
+ VPCCMD_W_CAMERA,
+ VPCCMD_R_3G,
+ VPCCMD_W_3G,
+ VPCCMD_R_ODD, /* 0x21 */
+ VPCCMD_R_RF = 0x23,
+ VPCCMD_W_RF,
+ VPCCMD_W_BL_POWER = 0x33,
+};
+
struct ideapad_private {
struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
struct platform_device *platform_device;
struct input_dev *inputdev;
+ struct backlight_device *blightdev;
+ struct dentry *debug;
+ unsigned long cfg;
};
static acpi_handle ideapad_handle;
+static struct ideapad_private *ideapad_priv;
static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -155,7 +192,147 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
}
/*
- * camera power
+ * debugfs
+ */
+#define DEBUGFS_EVENT_LEN (4096)
+static int debugfs_status_show(struct seq_file *s, void *data)
+{
+ unsigned long value;
+
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value))
+ seq_printf(s, "Backlight max:\t%lu\n", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value))
+ seq_printf(s, "Backlight now:\t%lu\n", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value))
+ seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
+ seq_printf(s, "=====================\n");
+
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value))
+ seq_printf(s, "Radio status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value))
+ seq_printf(s, "Wifi status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value))
+ seq_printf(s, "BT status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value))
+ seq_printf(s, "3G status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ seq_printf(s, "=====================\n");
+
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value))
+ seq_printf(s, "Touchpad status:%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value))
+ seq_printf(s, "Camera status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+
+ return 0;
+}
+
+static int debugfs_status_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, debugfs_status_show, NULL);
+}
+
+static const struct file_operations debugfs_status_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_status_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int debugfs_cfg_show(struct seq_file *s, void *data)
+{
+ if (!ideapad_priv) {
+ seq_printf(s, "cfg: N/A\n");
+ } else {
+ seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
+ ideapad_priv->cfg);
+ if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "Bluetooth ");
+ if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "3G ");
+ if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "Wireless ");
+ if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "Camera ");
+ seq_printf(s, "\nGraphic: ");
+ switch ((ideapad_priv->cfg)&0x700) {
+ case 0x100:
+ seq_printf(s, "Intel");
+ break;
+ case 0x200:
+ seq_printf(s, "ATI");
+ break;
+ case 0x300:
+ seq_printf(s, "Nvidia");
+ break;
+ case 0x400:
+ seq_printf(s, "Intel and ATI");
+ break;
+ case 0x500:
+ seq_printf(s, "Intel and Nvidia");
+ break;
+ }
+ seq_printf(s, "\n");
+ }
+ return 0;
+}
+
+static int debugfs_cfg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, debugfs_cfg_show, NULL);
+}
+
+static const struct file_operations debugfs_cfg_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_cfg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __devinit ideapad_debugfs_init(struct ideapad_private *priv)
+{
+ struct dentry *node;
+
+ priv->debug = debugfs_create_dir("ideapad", NULL);
+ if (priv->debug == NULL) {
+ pr_err("failed to create debugfs directory");
+ goto errout;
+ }
+
+ node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL,
+ &debugfs_cfg_fops);
+ if (!node) {
+ pr_err("failed to create cfg in debugfs");
+ goto errout;
+ }
+
+ node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL,
+ &debugfs_status_fops);
+ if (!node) {
+ pr_err("failed to create event in debugfs");
+ goto errout;
+ }
+
+ return 0;
+
+errout:
+ return -ENOMEM;
+}
+
+static void ideapad_debugfs_exit(struct ideapad_private *priv)
+{
+ debugfs_remove_recursive(priv->debug);
+ priv->debug = NULL;
+}
+
+/*
+ * sysfs
*/
static ssize_t show_ideapad_cam(struct device *dev,
struct device_attribute *attr,
@@ -163,7 +340,7 @@ static ssize_t show_ideapad_cam(struct device *dev,
{
unsigned long result;
- if (read_ec_data(ideapad_handle, 0x1D, &result))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result))
return sprintf(buf, "-1\n");
return sprintf(buf, "%lu\n", result);
}
@@ -178,7 +355,7 @@ static ssize_t store_ideapad_cam(struct device *dev,
return 0;
if (sscanf(buf, "%i", &state) != 1)
return -EINVAL;
- ret = write_ec_cmd(ideapad_handle, 0x1E, state);
+ ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);
if (ret < 0)
return ret;
return count;
@@ -186,6 +363,32 @@ static ssize_t store_ideapad_cam(struct device *dev,
static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
+static struct attribute *ideapad_attributes[] = {
+ &dev_attr_camera_power.attr,
+ NULL
+};
+
+static mode_t ideapad_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int idx)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct ideapad_private *priv = dev_get_drvdata(dev);
+ bool supported;
+
+ if (attr == &dev_attr_camera_power.attr)
+ supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
+ else
+ supported = true;
+
+ return supported ? attr->mode : 0;
+}
+
+static struct attribute_group ideapad_attribute_group = {
+ .is_visible = ideapad_is_visible,
+ .attrs = ideapad_attributes
+};
+
/*
* Rfkill
*/
@@ -197,14 +400,15 @@ struct ideapad_rfk_data {
};
const struct ideapad_rfk_data ideapad_rfk_data[] = {
- { "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN },
- { "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH },
- { "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN },
+ { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
+ { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
+ { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
};
static int ideapad_rfk_set(void *data, bool blocked)
{
- unsigned long opcode = (unsigned long)data;
+ unsigned long dev = (unsigned long)data;
+ int opcode = ideapad_rfk_data[dev].opcode;
return write_ec_cmd(ideapad_handle, opcode, !blocked);
}
@@ -213,13 +417,12 @@ static struct rfkill_ops ideapad_rfk_ops = {
.set_block = ideapad_rfk_set,
};
-static void ideapad_sync_rfk_state(struct acpi_device *adevice)
+static void ideapad_sync_rfk_state(struct ideapad_private *priv)
{
- struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
unsigned long hw_blocked;
int i;
- if (read_ec_data(ideapad_handle, 0x23, &hw_blocked))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked))
return;
hw_blocked = !hw_blocked;
@@ -265,8 +468,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
return 0;
}
-static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
- int dev)
+static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
{
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
@@ -280,15 +482,6 @@ static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
/*
* Platform device
*/
-static struct attribute *ideapad_attributes[] = {
- &dev_attr_camera_power.attr,
- NULL
-};
-
-static struct attribute_group ideapad_attribute_group = {
- .attrs = ideapad_attributes
-};
-
static int __devinit ideapad_platform_init(struct ideapad_private *priv)
{
int result;
@@ -326,8 +519,10 @@ static void ideapad_platform_exit(struct ideapad_private *priv)
* input device
*/
static const struct key_entry ideapad_keymap[] = {
- { KE_KEY, 0x06, { KEY_SWITCHVIDEOMODE } },
- { KE_KEY, 0x0D, { KEY_WLAN } },
+ { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 13, { KEY_WLAN } },
+ { KE_KEY, 16, { KEY_PROG1 } },
+ { KE_KEY, 17, { KEY_PROG2 } },
{ KE_END, 0 },
};
@@ -369,7 +564,7 @@ err_free_dev:
return error;
}
-static void __devexit ideapad_input_exit(struct ideapad_private *priv)
+static void ideapad_input_exit(struct ideapad_private *priv)
{
sparse_keymap_free(priv->inputdev);
input_unregister_device(priv->inputdev);
@@ -382,6 +577,113 @@ static void ideapad_input_report(struct ideapad_private *priv,
sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
}
+static void ideapad_input_novokey(struct ideapad_private *priv)
+{
+ unsigned long long_pressed;
+
+ if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed))
+ return;
+ if (long_pressed)
+ ideapad_input_report(priv, 17);
+ else
+ ideapad_input_report(priv, 16);
+}
+
+/*
+ * backlight
+ */
+static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
+{
+ unsigned long now;
+
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
+ return -EIO;
+ return now;
+}
+
+static int ideapad_backlight_update_status(struct backlight_device *blightdev)
+{
+ if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL,
+ blightdev->props.brightness))
+ return -EIO;
+ if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER,
+ blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
+ return -EIO;
+
+ return 0;
+}
+
+static const struct backlight_ops ideapad_backlight_ops = {
+ .get_brightness = ideapad_backlight_get_brightness,
+ .update_status = ideapad_backlight_update_status,
+};
+
+static int ideapad_backlight_init(struct ideapad_private *priv)
+{
+ struct backlight_device *blightdev;
+ struct backlight_properties props;
+ unsigned long max, now, power;
+
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max))
+ return -EIO;
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
+ return -EIO;
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
+ return -EIO;
+
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.max_brightness = max;
+ props.type = BACKLIGHT_PLATFORM;
+ blightdev = backlight_device_register("ideapad",
+ &priv->platform_device->dev,
+ priv,
+ &ideapad_backlight_ops,
+ &props);
+ if (IS_ERR(blightdev)) {
+ pr_err("Could not register backlight device\n");
+ return PTR_ERR(blightdev);
+ }
+
+ priv->blightdev = blightdev;
+ blightdev->props.brightness = now;
+ blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+ backlight_update_status(blightdev);
+
+ return 0;
+}
+
+static void ideapad_backlight_exit(struct ideapad_private *priv)
+{
+ if (priv->blightdev)
+ backlight_device_unregister(priv->blightdev);
+ priv->blightdev = NULL;
+}
+
+static void ideapad_backlight_notify_power(struct ideapad_private *priv)
+{
+ unsigned long power;
+ struct backlight_device *blightdev = priv->blightdev;
+
+ if (!blightdev)
+ return;
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
+ return;
+ blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
+static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
+{
+ unsigned long now;
+
+ /* if we control brightness via acpi video driver */
+ if (priv->blightdev == NULL) {
+ read_ec_data(ideapad_handle, VPCCMD_R_BL, &now);
+ return;
+ }
+
+ backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
+}
+
/*
* module init/exit
*/
@@ -393,37 +695,56 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
{
- int ret, i, cfg;
+ int ret, i;
+ unsigned long cfg;
struct ideapad_private *priv;
- if (read_method_int(adevice->handle, "_CFG", &cfg))
+ if (read_method_int(adevice->handle, "_CFG", (int *)&cfg))
return -ENODEV;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
dev_set_drvdata(&adevice->dev, priv);
+ ideapad_priv = priv;
ideapad_handle = adevice->handle;
+ priv->cfg = cfg;
ret = ideapad_platform_init(priv);
if (ret)
goto platform_failed;
+ ret = ideapad_debugfs_init(priv);
+ if (ret)
+ goto debugfs_failed;
+
ret = ideapad_input_init(priv);
if (ret)
goto input_failed;
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
- if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
+ if (test_bit(ideapad_rfk_data[i].cfgbit, &cfg))
ideapad_register_rfkill(adevice, i);
else
priv->rfk[i] = NULL;
}
- ideapad_sync_rfk_state(adevice);
+ ideapad_sync_rfk_state(priv);
+
+ if (!acpi_video_backlight_support()) {
+ ret = ideapad_backlight_init(priv);
+ if (ret && ret != -ENODEV)
+ goto backlight_failed;
+ }
return 0;
+backlight_failed:
+ for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
+ ideapad_unregister_rfkill(adevice, i);
+ ideapad_input_exit(priv);
input_failed:
+ ideapad_debugfs_exit(priv);
+debugfs_failed:
ideapad_platform_exit(priv);
platform_failed:
kfree(priv);
@@ -435,9 +756,11 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
int i;
+ ideapad_backlight_exit(priv);
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
ideapad_unregister_rfkill(adevice, i);
ideapad_input_exit(priv);
+ ideapad_debugfs_exit(priv);
ideapad_platform_exit(priv);
dev_set_drvdata(&adevice->dev, NULL);
kfree(priv);
@@ -451,20 +774,30 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
acpi_handle handle = adevice->handle;
unsigned long vpc1, vpc2, vpc_bit;
- if (read_ec_data(handle, 0x10, &vpc1))
+ if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
return;
- if (read_ec_data(handle, 0x1A, &vpc2))
+ if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
return;
vpc1 = (vpc2 << 8) | vpc1;
for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
if (test_bit(vpc_bit, &vpc1)) {
- if (vpc_bit == 9)
- ideapad_sync_rfk_state(adevice);
- else if (vpc_bit == 4)
- read_ec_data(handle, 0x12, &vpc2);
- else
+ switch (vpc_bit) {
+ case 9:
+ ideapad_sync_rfk_state(priv);
+ break;
+ case 4:
+ ideapad_backlight_notify_brightness(priv);
+ break;
+ case 3:
+ ideapad_input_novokey(priv);
+ break;
+ case 2:
+ ideapad_backlight_notify_power(priv);
+ break;
+ default:
ideapad_input_report(priv, vpc_bit);
+ }
}
}
}
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index e66bbba..b46ec11 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -404,7 +404,7 @@ static void ips_cpu_raise(struct ips_driver *ips)
thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8);
- turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
+ turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
turbo_override &= ~TURBO_TDP_MASK;
@@ -439,7 +439,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
thm_writew(THM_MPCPC, (new_limit * 10) / 8);
- turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
+ turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
turbo_override &= ~TURBO_TDP_MASK;
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index 809adea..abddc83 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -477,6 +477,8 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
return AE_ERROR;
}
+ return AE_OK;
+
aux1_not_found:
if (status == AE_NOT_FOUND)
return AE_OK;
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 3a57832..ccd7b1f 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -493,20 +493,30 @@ static int mid_thermal_probe(struct platform_device *pdev)
/* Register each sensor with the generic thermal framework*/
for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+ struct thermal_device_info *td_info = initialize_sensor(i);
+
+ if (!td_info) {
+ ret = -ENOMEM;
+ goto err;
+ }
pinfo->tzd[i] = thermal_zone_device_register(name[i],
- 0, initialize_sensor(i), &tzd_ops, 0, 0, 0, 0);
- if (IS_ERR(pinfo->tzd[i]))
- goto reg_fail;
+ 0, td_info, &tzd_ops, 0, 0, 0, 0);
+ if (IS_ERR(pinfo->tzd[i])) {
+ kfree(td_info);
+ ret = PTR_ERR(pinfo->tzd[i]);
+ goto err;
+ }
}
pinfo->pdev = pdev;
platform_set_drvdata(pdev, pinfo);
return 0;
-reg_fail:
- ret = PTR_ERR(pinfo->tzd[i]);
- while (--i >= 0)
+err:
+ while (--i >= 0) {
+ kfree(pinfo->tzd[i]->devdata);
thermal_zone_device_unregister(pinfo->tzd[i]);
+ }
configure_adc(0);
kfree(pinfo);
return ret;
@@ -524,8 +534,10 @@ static int mid_thermal_remove(struct platform_device *pdev)
int i;
struct platform_info *pinfo = platform_get_drvdata(pdev);
- for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
+ for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+ kfree(pinfo->tzd[i]->devdata);
thermal_zone_device_unregister(pinfo->tzd[i]);
+ }
kfree(pinfo);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/platform/x86/intel_rar_register.c b/drivers/platform/x86/intel_rar_register.c
index bde47e9..c8a6aed 100644
--- a/drivers/platform/x86/intel_rar_register.c
+++ b/drivers/platform/x86/intel_rar_register.c
@@ -637,15 +637,13 @@ end_function:
return error;
}
-const struct pci_device_id rar_pci_id_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(rar_pci_id_tbl) = {
{ PCI_VDEVICE(INTEL, 0x4110) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
-const struct pci_device_id *my_id_table = rar_pci_id_tbl;
-
/* field for registering driver to PCI device */
static struct pci_driver rar_pci_driver = {
.name = "rar_register_driver",
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 940accb..48870e5 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -24,6 +24,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/sfi.h>
+#include <linux/module.h>
#include <asm/mrst.h>
#include <asm/intel_scu_ipc.h>
@@ -725,7 +726,7 @@ static void ipc_remove(struct pci_dev *pdev)
intel_scu_devices_destroy();
}
-static const struct pci_device_id pci_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
{ 0,}
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
index b93a032..2d0f913 100644
--- a/drivers/platform/x86/intel_scu_ipcutil.c
+++ b/drivers/platform/x86/intel_scu_ipcutil.c
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <asm/intel_scu_ipc.h>
-static u32 major;
+static int major;
#define MAX_FW_SIZE 264192
@@ -117,7 +117,11 @@ static const struct file_operations scu_ipc_fops = {
static int __init ipc_module_init(void)
{
- return register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
+ major = register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
+ if (major < 0)
+ return major;
+
+ return 0;
}
static void __exit ipc_module_exit(void)
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 3ff629d..f204643 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -538,6 +538,15 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
},
.callback = dmi_check_cb
},
+ {
+ .ident = "MSI U270",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "Micro-Star International Co., Ltd."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "U270 series"),
+ },
+ .callback = dmi_check_cb
+ },
{ }
};
@@ -996,3 +1005,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*");
MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*");
MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*");
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index c832e33..b96766b 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -28,6 +28,7 @@
#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/slab.h>
+#include <linux/module.h>
MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver");
@@ -175,7 +176,7 @@ static void msi_wmi_notify(u32 value, void *context)
pr_debug("Suppressed key event 0x%X - "
"Last press was %lld us ago\n",
key->code, ktime_to_us(diff));
- return;
+ goto msi_wmi_notify_exit;
}
last_pressed[key->code - SCANCODE_BASE] = cur;
@@ -194,6 +195,8 @@ static void msi_wmi_notify(u32 value, void *context)
pr_info("Unknown key pressed - %x\n", eventcode);
} else
pr_info("Unknown event received\n");
+
+msi_wmi_notify_exit:
kfree(response.pointer);
}
@@ -272,6 +275,7 @@ static int __init msi_wmi_init(void)
err_free_backlight:
backlight_device_unregister(backlight);
err_free_input:
+ sparse_keymap_free(msi_wmi_input_dev);
input_unregister_device(msi_wmi_input_dev);
err_uninstall_notifier:
wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index ec85987..64e1f2d 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -21,6 +21,8 @@
#include <linux/dmi.h>
#include <linux/platform_device.h>
#include <linux/rfkill.h>
+#include <linux/acpi.h>
+#include <linux/efi.h>
/*
* This driver is needed because a number of Samsung laptops do not hook
@@ -226,6 +228,8 @@ static struct backlight_device *backlight_device;
static struct mutex sabi_mutex;
static struct platform_device *sdev;
static struct rfkill *rfk;
+static bool handle_backlight;
+static bool has_stepping_quirk;
static int force;
module_param(force, bool, 0);
@@ -382,6 +386,17 @@ static void set_brightness(u8 user_brightness)
{
u8 user_level = user_brightness + sabi_config->min_brightness;
+ if (has_stepping_quirk && user_level != 0) {
+ /*
+ * short circuit if the specified level is what's already set
+ * to prevent the screen from flickering needlessly
+ */
+ if (user_brightness == read_brightness())
+ return;
+
+ sabi_set_command(sabi_config->commands.set_brightness, 0);
+ }
+
sabi_set_command(sabi_config->commands.set_brightness, user_level);
}
@@ -390,6 +405,40 @@ static int get_brightness(struct backlight_device *bd)
return (int)read_brightness();
}
+static void check_for_stepping_quirk(void)
+{
+ u8 initial_level;
+ u8 check_level;
+ u8 orig_level = read_brightness();
+
+ /*
+ * Some laptops exhibit the strange behaviour of stepping toward
+ * (rather than setting) the brightness except when changing to/from
+ * brightness level 0. This behaviour is checked for here and worked
+ * around in set_brightness.
+ */
+
+ if (orig_level == 0)
+ set_brightness(1);
+
+ initial_level = read_brightness();
+
+ if (initial_level <= 2)
+ check_level = initial_level + 2;
+ else
+ check_level = initial_level - 2;
+
+ has_stepping_quirk = false;
+ set_brightness(check_level);
+
+ if (read_brightness() != check_level) {
+ has_stepping_quirk = true;
+ pr_info("enabled workaround for brightness stepping quirk\n");
+ }
+
+ set_brightness(orig_level);
+}
+
static int update_status(struct backlight_device *bd)
{
set_brightness(bd->props.brightness);
@@ -494,216 +543,34 @@ static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
get_performance_level, set_performance_level);
-static int __init dmi_check_cb(const struct dmi_system_id *id)
-{
- pr_info("found laptop model '%s'\n",
- id->ident);
- return 1;
-}
-
static struct dmi_system_id __initdata samsung_dmi_table[] = {
{
- .ident = "N128",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
- DMI_MATCH(DMI_BOARD_NAME, "N128"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "N130",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
- DMI_MATCH(DMI_BOARD_NAME, "N130"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "X125",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
- DMI_MATCH(DMI_BOARD_NAME, "X125"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "X120/X170",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
- DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "NC10",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
- DMI_MATCH(DMI_BOARD_NAME, "NC10"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "NP-Q45",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
- DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "X360",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
- DMI_MATCH(DMI_BOARD_NAME, "X360"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R410 Plus",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
- DMI_MATCH(DMI_BOARD_NAME, "R460"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R518",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
- DMI_MATCH(DMI_BOARD_NAME, "R518"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R519/R719",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
- DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "N150/N210/N220",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
- DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
},
- .callback = dmi_check_cb,
},
{
- .ident = "N150/N210/N220/N230",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
- DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
},
- .callback = dmi_check_cb,
},
{
- .ident = "N150P/N210P/N220P",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
- DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R700",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
- DMI_MATCH(DMI_BOARD_NAME, "SR700"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R530/R730",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
- DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "NF110/NF210/NF310",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
- DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
},
- .callback = dmi_check_cb,
},
{
- .ident = "N145P/N250P/N260P",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
- DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R70/R71",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
- DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "P460",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
- DMI_MATCH(DMI_BOARD_NAME, "P460"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "X520",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
- DMI_MATCH(DMI_BOARD_NAME, "X520"),
- },
- .callback = dmi_check_cb,
- },
- {
- .ident = "R528/R728",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
- DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
},
- .callback = dmi_check_cb,
},
{ },
};
@@ -737,14 +604,25 @@ static int __init samsung_init(void)
int loca;
int retval;
+ if (efi_enabled(EFI_BOOT))
+ return -ENODEV;
+
mutex_init(&sabi_mutex);
+ handle_backlight = true;
+
+#ifdef CONFIG_ACPI
+ /* Don't handle backlight here if the acpi video already handle it */
+ if (acpi_video_backlight_support())
+ handle_backlight = false;
+#endif
if (!force && !dmi_check_system(samsung_dmi_table))
return -ENODEV;
f0000_segment = ioremap_nocache(0xf0000, 0xffff);
if (!f0000_segment) {
- pr_err("Can't map the segment at 0xf0000\n");
+ if (debug || force)
+ pr_err("Can't map the segment at 0xf0000\n");
return -EINVAL;
}
@@ -757,7 +635,8 @@ static int __init samsung_init(void)
}
if (loca == 0xffff) {
- pr_err("This computer does not support SABI\n");
+ if (debug || force)
+ pr_err("This computer does not support SABI\n");
goto error_no_signature;
}
@@ -795,7 +674,8 @@ static int __init samsung_init(void)
printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
- test_backlight();
+ if (handle_backlight)
+ test_backlight();
test_wireless();
retval = sabi_get_command(sabi_config->commands.get_brightness,
@@ -813,11 +693,24 @@ static int __init samsung_init(void)
}
}
+ /* Check for stepping quirk */
+ if (handle_backlight)
+ check_for_stepping_quirk();
+
+#ifdef CONFIG_ACPI
+ /* Only log that if we are really on a sabi platform */
+ if (acpi_video_backlight_support())
+ pr_info("Backlight controlled by ACPI video driver\n");
+#endif
+
/* knock up a platform device to hang stuff off of */
sdev = platform_device_register_simple("samsung", -1, NULL, 0);
if (IS_ERR(sdev))
goto error_no_platform;
+ if (!handle_backlight)
+ goto skip_backlight;
+
/* create a backlight device to talk to this one */
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_PLATFORM;
@@ -833,6 +726,7 @@ static int __init samsung_init(void)
backlight_device->props.power = FB_BLANK_UNBLANK;
backlight_update_status(backlight_device);
+skip_backlight:
retval = init_wireless(sdev);
if (retval)
goto error_no_rfk;
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 35dae41..40c4705 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -3281,7 +3281,7 @@ static int sony_pic_add(struct acpi_device *device)
/* request IRQ */
list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
- IRQF_DISABLED, "sony-laptop", &spic_dev)) {
+ 0, "sony-laptop", &spic_dev)) {
dprintk("IRQ: %d - triggering: %d - "
"polarity: %d - shr: %d\n",
irq->irq.interrupts[0],
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index aaba423..2a8d6aa 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3186,8 +3186,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
/* (assignments unknown, please report if found) */
+ KEY_UNKNOWN, KEY_UNKNOWN,
+
+ /*
+ * The mic mute button only sends 0x1a. It does not
+ * automatically mute the mic or change the mute light.
+ */
+ KEY_MICMUTE, /* 0x1a: Mic mute (since ?400 or so) */
+
+ /* (assignments unknown, please report if found) */
KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
- KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+ KEY_UNKNOWN,
},
};
@@ -3396,7 +3405,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
/* Do not issue duplicate brightness change events to
* userspace. tpacpi_detect_brightness_capabilities() must have
* been called before this point */
- if (tp_features.bright_acpimode && acpi_video_backlight_support()) {
+ if (acpi_video_backlight_support()) {
pr_info("This ThinkPad has standard ACPI backlight "
"brightness control, supported by the ACPI "
"video driver\n");
@@ -3998,7 +4007,7 @@ static void bluetooth_shutdown(void)
pr_notice("failed to save bluetooth state to NVRAM\n");
else
vdbg_printk(TPACPI_DBG_RFKILL,
- "bluestooth state saved to NVRAM\n");
+ "bluetooth state saved to NVRAM\n");
}
static void bluetooth_exit(void)
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 4c20447..d528daa 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -41,6 +41,7 @@ static const struct key_entry topstar_keymap[] = {
{ KE_KEY, 0x8c, { KEY_MEDIA } },
/* Known non hotkey events don't handled or that we don't care yet */
+ { KE_IGNORE, 0x82, }, /* backlight event */
{ KE_IGNORE, 0x8e, },
{ KE_IGNORE, 0x8f, },
{ KE_IGNORE, 0x90, },
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index cb009b2..dcdc1f4 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -47,7 +47,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/backlight.h>
-#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
@@ -63,11 +62,7 @@ MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
MODULE_LICENSE("GPL");
/* Toshiba ACPI method paths */
-#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
-#define TOSH_INTERFACE_1 "\\_SB_.VALD"
-#define TOSH_INTERFACE_2 "\\_SB_.VALZ"
#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
-#define GHCI_METHOD ".GHCI"
/* Toshiba HCI interface definitions
*
@@ -111,6 +106,26 @@ MODULE_LICENSE("GPL");
#define HCI_WIRELESS_BT_ATTACH 0x40
#define HCI_WIRELESS_BT_POWER 0x80
+struct toshiba_acpi_dev {
+ struct acpi_device *acpi_dev;
+ const char *method_hci;
+ struct rfkill *bt_rfk;
+ struct input_dev *hotkey_dev;
+ struct backlight_device *backlight_dev;
+ struct led_classdev led_dev;
+
+ int force_fan;
+ int last_key_event;
+ int key_event_valid;
+
+ int illumination_supported:1;
+ int video_supported:1;
+ int fan_supported:1;
+ int system_event_supported:1;
+
+ struct mutex mutex;
+};
+
static const struct acpi_device_id toshiba_device_ids[] = {
{"TOS6200", 0},
{"TOS6208", 0},
@@ -119,7 +134,7 @@ static const struct acpi_device_id toshiba_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
-static const struct key_entry toshiba_acpi_keymap[] __initconst = {
+static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
{ KE_KEY, 0x101, { KEY_MUTE } },
{ KE_KEY, 0x102, { KEY_ZOOMOUT } },
{ KE_KEY, 0x103, { KEY_ZOOMIN } },
@@ -155,15 +170,6 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value)
/* acpi interface wrappers
*/
-static int is_valid_acpi_path(const char *methodName)
-{
- acpi_handle handle;
- acpi_status status;
-
- status = acpi_get_handle(NULL, (char *)methodName, &handle);
- return !ACPI_FAILURE(status);
-}
-
static int write_acpi_int(const char *methodName, int val)
{
struct acpi_object_list params;
@@ -176,32 +182,14 @@ static int write_acpi_int(const char *methodName, int val)
in_objs[0].integer.value = val;
status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
- return (status == AE_OK);
-}
-
-#if 0
-static int read_acpi_int(const char *methodName, int *pVal)
-{
- struct acpi_buffer results;
- union acpi_object out_objs[1];
- acpi_status status;
-
- results.length = sizeof(out_objs);
- results.pointer = out_objs;
-
- status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
- *pVal = out_objs[0].integer.value;
-
- return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
+ return (status == AE_OK) ? 0 : -EIO;
}
-#endif
-
-static const char *method_hci /*= 0*/ ;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
-static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+static acpi_status hci_raw(struct toshiba_acpi_dev *dev,
+ const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
{
struct acpi_object_list params;
union acpi_object in_objs[HCI_WORDS];
@@ -220,7 +208,8 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(NULL, (char *)method_hci, &params,
+ status = acpi_evaluate_object(dev->acpi_dev->handle,
+ (char *)dev->method_hci, &params,
&results);
if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
for (i = 0; i < out_objs->package.count; ++i) {
@@ -237,85 +226,79 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
* may be useful (such as "not supported").
*/
-static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
+static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 in1, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
+static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 *out1, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*out1 = out[2];
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result)
+static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 in1, u32 in2, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
+static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 *out1, u32 *out2, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*out1 = out[2];
*out2 = out[3];
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-struct toshiba_acpi_dev {
- struct platform_device *p_dev;
- struct rfkill *bt_rfk;
- struct input_dev *hotkey_dev;
- int illumination_installed;
- acpi_handle handle;
-
- const char *bt_name;
-
- struct mutex mutex;
-};
-
/* Illumination support */
-static int toshiba_illumination_available(void)
+static int toshiba_illumination_available(struct toshiba_acpi_dev *dev)
{
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
in[0] = 0xf100;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("Illumination device not available\n");
return 0;
}
in[0] = 0xf400;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
return 1;
}
static void toshiba_illumination_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, led_dev);
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
/* First request : initialize communication. */
in[0] = 0xf100;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("Illumination device not available\n");
return;
@@ -326,7 +309,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
in[0] = 0xf400;
in[1] = 0x14e;
in[2] = 1;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("ACPI call for illumination failed\n");
return;
@@ -336,7 +319,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
in[0] = 0xf400;
in[1] = 0x14e;
in[2] = 0;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("ACPI call for illumination failed.\n");
return;
@@ -347,11 +330,13 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
in[0] = 0xf200;
in[1] = 0;
in[2] = 0;
- hci_raw(in, out);
+ hci_raw(dev, in, out);
}
static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, led_dev);
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
@@ -359,7 +344,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
/* First request : initialize communication. */
in[0] = 0xf100;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("Illumination device not available\n");
return LED_OFF;
@@ -368,7 +353,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
/* Check the illumination */
in[0] = 0xf300;
in[1] = 0x14e;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("ACPI call for illumination failed.\n");
return LED_OFF;
@@ -380,46 +365,35 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
in[0] = 0xf200;
in[1] = 0;
in[2] = 0;
- hci_raw(in, out);
+ hci_raw(dev, in, out);
return result;
}
-static struct led_classdev toshiba_led = {
- .name = "toshiba::illumination",
- .max_brightness = 1,
- .brightness_set = toshiba_illumination_set,
- .brightness_get = toshiba_illumination_get,
-};
-
-static struct toshiba_acpi_dev toshiba_acpi = {
- .bt_name = "Toshiba Bluetooth",
-};
-
/* Bluetooth rfkill handlers */
-static u32 hci_get_bt_present(bool *present)
+static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
{
u32 hci_result;
u32 value, value2;
value = 0;
value2 = 0;
- hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+ hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
if (hci_result == HCI_SUCCESS)
*present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
return hci_result;
}
-static u32 hci_get_radio_state(bool *radio_state)
+static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
{
u32 hci_result;
u32 value, value2;
value = 0;
value2 = 0x0001;
- hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+ hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
*radio_state = value & HCI_WIRELESS_KILL_SWITCH;
return hci_result;
@@ -436,8 +410,8 @@ static int bt_rfkill_set_block(void *data, bool blocked)
value = (blocked == false);
mutex_lock(&dev->mutex);
- if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) {
- err = -EBUSY;
+ if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) {
+ err = -EIO;
goto out;
}
@@ -446,11 +420,11 @@ static int bt_rfkill_set_block(void *data, bool blocked)
goto out;
}
- hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
- hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
+ hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
+ hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
- err = -EBUSY;
+ err = -EIO;
else
err = 0;
out:
@@ -467,7 +441,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
mutex_lock(&dev->mutex);
- hci_result = hci_get_radio_state(&value);
+ hci_result = hci_get_radio_state(dev, &value);
if (hci_result != HCI_SUCCESS) {
/* Can't do anything useful */
mutex_unlock(&dev->mutex);
@@ -488,63 +462,64 @@ static const struct rfkill_ops toshiba_rfk_ops = {
};
static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
-static struct backlight_device *toshiba_backlight_device;
-static int force_fan;
-static int last_key_event;
-static int key_event_valid;
static int get_lcd(struct backlight_device *bd)
{
+ struct toshiba_acpi_dev *dev = bl_get_data(bd);
u32 hci_result;
u32 value;
- hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS)
return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
- } else
- return -EFAULT;
+
+ return -EIO;
}
static int lcd_proc_show(struct seq_file *m, void *v)
{
- int value = get_lcd(NULL);
+ struct toshiba_acpi_dev *dev = m->private;
+ int value;
+ if (!dev->backlight_dev)
+ return -ENODEV;
+
+ value = get_lcd(dev->backlight_dev);
if (value >= 0) {
seq_printf(m, "brightness: %d\n", value);
seq_printf(m, "brightness_levels: %d\n",
HCI_LCD_BRIGHTNESS_LEVELS);
- } else {
- pr_err("Error reading LCD brightness\n");
+ return 0;
}
- return 0;
+ pr_err("Error reading LCD brightness\n");
+ return -EIO;
}
static int lcd_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, lcd_proc_show, NULL);
+ return single_open(file, lcd_proc_show, PDE(inode)->data);
}
-static int set_lcd(int value)
+static int set_lcd(struct toshiba_acpi_dev *dev, int value)
{
u32 hci_result;
value = value << HCI_LCD_BRIGHTNESS_SHIFT;
- hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
- if (hci_result != HCI_SUCCESS)
- return -EFAULT;
-
- return 0;
+ hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
+ return hci_result == HCI_SUCCESS ? 0 : -EIO;
}
static int set_lcd_status(struct backlight_device *bd)
{
- return set_lcd(bd->props.brightness);
+ struct toshiba_acpi_dev *dev = bl_get_data(bd);
+ return set_lcd(dev, bd->props.brightness);
}
static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char cmd[42];
size_t len;
int value;
@@ -557,7 +532,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
if (sscanf(cmd, " brightness : %i", &value) == 1 &&
value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
- ret = set_lcd(value);
+ ret = set_lcd(dev, value);
if (ret == 0)
ret = count;
} else {
@@ -575,41 +550,49 @@ static const struct file_operations lcd_proc_fops = {
.write = lcd_proc_write,
};
-static int video_proc_show(struct seq_file *m, void *v)
+static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status)
{
u32 hci_result;
+
+ hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result);
+ return hci_result == HCI_SUCCESS ? 0 : -EIO;
+}
+
+static int video_proc_show(struct seq_file *m, void *v)
+{
+ struct toshiba_acpi_dev *dev = m->private;
u32 value;
+ int ret;
- hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ ret = get_video_status(dev, &value);
+ if (!ret) {
int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
seq_printf(m, "lcd_out: %d\n", is_lcd);
seq_printf(m, "crt_out: %d\n", is_crt);
seq_printf(m, "tv_out: %d\n", is_tv);
- } else {
- pr_err("Error reading video out status\n");
}
- return 0;
+ return ret;
}
static int video_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, video_proc_show, NULL);
+ return single_open(file, video_proc_show, PDE(inode)->data);
}
static ssize_t video_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char *cmd, *buffer;
+ int ret;
int value;
int remain = count;
int lcd_out = -1;
int crt_out = -1;
int tv_out = -1;
- u32 hci_result;
u32 video_out;
cmd = kmalloc(count + 1, GFP_KERNEL);
@@ -644,8 +627,8 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
kfree(cmd);
- hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ ret = get_video_status(dev, &video_out);
+ if (!ret) {
unsigned int new_video_out = video_out;
if (lcd_out != -1)
_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
@@ -656,12 +639,10 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
/* To avoid unnecessary video disruption, only write the new
* video setting if something changed. */
if (new_video_out != video_out)
- write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
- } else {
- return -EFAULT;
+ ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
}
- return count;
+ return ret ? ret : count;
}
static const struct file_operations video_proc_fops = {
@@ -673,30 +654,38 @@ static const struct file_operations video_proc_fops = {
.write = video_proc_write,
};
-static int fan_proc_show(struct seq_file *m, void *v)
+static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status)
{
u32 hci_result;
+
+ hci_read1(dev, HCI_FAN, status, &hci_result);
+ return hci_result == HCI_SUCCESS ? 0 : -EIO;
+}
+
+static int fan_proc_show(struct seq_file *m, void *v)
+{
+ struct toshiba_acpi_dev *dev = m->private;
+ int ret;
u32 value;
- hci_read1(HCI_FAN, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ ret = get_fan_status(dev, &value);
+ if (!ret) {
seq_printf(m, "running: %d\n", (value > 0));
- seq_printf(m, "force_on: %d\n", force_fan);
- } else {
- pr_err("Error reading fan status\n");
+ seq_printf(m, "force_on: %d\n", dev->force_fan);
}
- return 0;
+ return ret;
}
static int fan_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, fan_proc_show, NULL);
+ return single_open(file, fan_proc_show, PDE(inode)->data);
}
static ssize_t fan_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char cmd[42];
size_t len;
int value;
@@ -709,11 +698,11 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf,
if (sscanf(cmd, " force_on : %i", &value) == 1 &&
value >= 0 && value <= 1) {
- hci_write1(HCI_FAN, value, &hci_result);
+ hci_write1(dev, HCI_FAN, value, &hci_result);
if (hci_result != HCI_SUCCESS)
- return -EFAULT;
+ return -EIO;
else
- force_fan = value;
+ dev->force_fan = value;
} else {
return -EINVAL;
}
@@ -732,42 +721,43 @@ static const struct file_operations fan_proc_fops = {
static int keys_proc_show(struct seq_file *m, void *v)
{
+ struct toshiba_acpi_dev *dev = m->private;
u32 hci_result;
u32 value;
- if (!key_event_valid) {
- hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+ if (!dev->key_event_valid && dev->system_event_supported) {
+ hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
if (hci_result == HCI_SUCCESS) {
- key_event_valid = 1;
- last_key_event = value;
+ dev->key_event_valid = 1;
+ dev->last_key_event = value;
} else if (hci_result == HCI_EMPTY) {
/* better luck next time */
} else if (hci_result == HCI_NOT_SUPPORTED) {
/* This is a workaround for an unresolved issue on
* some machines where system events sporadically
* become disabled. */
- hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
pr_notice("Re-enabled hotkeys\n");
} else {
pr_err("Error reading hotkey status\n");
- goto end;
+ return -EIO;
}
}
- seq_printf(m, "hotkey_ready: %d\n", key_event_valid);
- seq_printf(m, "hotkey: 0x%04x\n", last_key_event);
-end:
+ seq_printf(m, "hotkey_ready: %d\n", dev->key_event_valid);
+ seq_printf(m, "hotkey: 0x%04x\n", dev->last_key_event);
return 0;
}
static int keys_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, keys_proc_show, NULL);
+ return single_open(file, keys_proc_show, PDE(inode)->data);
}
static ssize_t keys_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char cmd[42];
size_t len;
int value;
@@ -778,7 +768,7 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf,
cmd[len] = '\0';
if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
- key_event_valid = 0;
+ dev->key_event_valid = 0;
} else {
return -EINVAL;
}
@@ -820,21 +810,35 @@ static const struct file_operations version_proc_fops = {
#define PROC_TOSHIBA "toshiba"
-static void __init create_toshiba_proc_entries(void)
+static void __devinit
+create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
{
- proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops);
- proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops);
- proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops);
- proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops);
- proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops);
+ if (dev->backlight_dev)
+ proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &lcd_proc_fops, dev);
+ if (dev->video_supported)
+ proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &video_proc_fops, dev);
+ if (dev->fan_supported)
+ proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &fan_proc_fops, dev);
+ if (dev->hotkey_dev)
+ proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &keys_proc_fops, dev);
+ proc_create_data("version", S_IRUGO, toshiba_proc_dir,
+ &version_proc_fops, dev);
}
-static void remove_toshiba_proc_entries(void)
+static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
{
- remove_proc_entry("lcd", toshiba_proc_dir);
- remove_proc_entry("video", toshiba_proc_dir);
- remove_proc_entry("fan", toshiba_proc_dir);
- remove_proc_entry("keys", toshiba_proc_dir);
+ if (dev->backlight_dev)
+ remove_proc_entry("lcd", toshiba_proc_dir);
+ if (dev->video_supported)
+ remove_proc_entry("video", toshiba_proc_dir);
+ if (dev->fan_supported)
+ remove_proc_entry("fan", toshiba_proc_dir);
+ if (dev->hotkey_dev)
+ remove_proc_entry("keys", toshiba_proc_dir);
remove_proc_entry("version", toshiba_proc_dir);
}
@@ -843,224 +847,266 @@ static const struct backlight_ops toshiba_backlight_data = {
.update_status = set_lcd_status,
};
-static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
-{
- u32 hci_result, value;
-
- if (event != 0x80)
- return;
- do {
- hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
- if (value == 0x100)
- continue;
- /* act on key press; ignore key release */
- if (value & 0x80)
- continue;
-
- if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
- value, 1, true)) {
- pr_info("Unknown key %x\n",
- value);
- }
- } else if (hci_result == HCI_NOT_SUPPORTED) {
- /* This is a workaround for an unresolved issue on
- * some machines where system events sporadically
- * become disabled. */
- hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
- pr_notice("Re-enabled hotkeys\n");
- }
- } while (hci_result != HCI_EMPTY);
-}
-
-static int __init toshiba_acpi_setup_keyboard(char *device)
+static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
{
acpi_status status;
int error;
- status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
- if (ACPI_FAILURE(status)) {
- pr_info("Unable to get notification device\n");
- return -ENODEV;
- }
-
- toshiba_acpi.hotkey_dev = input_allocate_device();
- if (!toshiba_acpi.hotkey_dev) {
+ dev->hotkey_dev = input_allocate_device();
+ if (!dev->hotkey_dev) {
pr_info("Unable to register input device\n");
return -ENOMEM;
}
- toshiba_acpi.hotkey_dev->name = "Toshiba input device";
- toshiba_acpi.hotkey_dev->phys = device;
- toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
+ dev->hotkey_dev->name = "Toshiba input device";
+ dev->hotkey_dev->phys = "toshiba_acpi/input0";
+ dev->hotkey_dev->id.bustype = BUS_HOST;
- error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
- toshiba_acpi_keymap, NULL);
+ error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL);
if (error)
goto err_free_dev;
- status = acpi_install_notify_handler(toshiba_acpi.handle,
- ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
- if (ACPI_FAILURE(status)) {
- pr_info("Unable to install hotkey notification\n");
- error = -ENODEV;
- goto err_free_keymap;
- }
-
- status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
+ status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
if (ACPI_FAILURE(status)) {
pr_info("Unable to enable hotkeys\n");
error = -ENODEV;
- goto err_remove_notify;
+ goto err_free_keymap;
}
- error = input_register_device(toshiba_acpi.hotkey_dev);
+ error = input_register_device(dev->hotkey_dev);
if (error) {
pr_info("Unable to register input device\n");
- goto err_remove_notify;
+ goto err_free_keymap;
}
return 0;
- err_remove_notify:
- acpi_remove_notify_handler(toshiba_acpi.handle,
- ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
err_free_keymap:
- sparse_keymap_free(toshiba_acpi.hotkey_dev);
+ sparse_keymap_free(dev->hotkey_dev);
err_free_dev:
- input_free_device(toshiba_acpi.hotkey_dev);
- toshiba_acpi.hotkey_dev = NULL;
+ input_free_device(dev->hotkey_dev);
+ dev->hotkey_dev = NULL;
return error;
}
-static void toshiba_acpi_exit(void)
+static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
{
- if (toshiba_acpi.hotkey_dev) {
- acpi_remove_notify_handler(toshiba_acpi.handle,
- ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
- sparse_keymap_free(toshiba_acpi.hotkey_dev);
- input_unregister_device(toshiba_acpi.hotkey_dev);
+ struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+
+ remove_toshiba_proc_entries(dev);
+
+ if (dev->hotkey_dev) {
+ input_unregister_device(dev->hotkey_dev);
+ sparse_keymap_free(dev->hotkey_dev);
}
- if (toshiba_acpi.bt_rfk) {
- rfkill_unregister(toshiba_acpi.bt_rfk);
- rfkill_destroy(toshiba_acpi.bt_rfk);
+ if (dev->bt_rfk) {
+ rfkill_unregister(dev->bt_rfk);
+ rfkill_destroy(dev->bt_rfk);
}
- if (toshiba_backlight_device)
- backlight_device_unregister(toshiba_backlight_device);
+ if (dev->backlight_dev)
+ backlight_device_unregister(dev->backlight_dev);
- remove_toshiba_proc_entries();
+ if (dev->illumination_supported)
+ led_classdev_unregister(&dev->led_dev);
- if (toshiba_proc_dir)
- remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ kfree(dev);
+
+ return 0;
+}
- if (toshiba_acpi.illumination_installed)
- led_classdev_unregister(&toshiba_led);
+static const char * __devinit find_hci_method(acpi_handle handle)
+{
+ acpi_status status;
+ acpi_handle hci_handle;
- platform_device_unregister(toshiba_acpi.p_dev);
+ status = acpi_get_handle(handle, "GHCI", &hci_handle);
+ if (ACPI_SUCCESS(status))
+ return "GHCI";
- return;
+ status = acpi_get_handle(handle, "SPFC", &hci_handle);
+ if (ACPI_SUCCESS(status))
+ return "SPFC";
+
+ return NULL;
}
-static int __init toshiba_acpi_init(void)
+static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
{
+ struct toshiba_acpi_dev *dev;
+ const char *hci_method;
u32 hci_result;
+ u32 dummy;
bool bt_present;
int ret = 0;
struct backlight_properties props;
- if (acpi_disabled)
- return -ENODEV;
-
- /* simple device detection: look for HCI method */
- if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
- method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
- if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
- pr_info("Unable to activate hotkeys\n");
- } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
- method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
- if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
- pr_info("Unable to activate hotkeys\n");
- } else
- return -ENODEV;
-
pr_info("Toshiba Laptop ACPI Extras version %s\n",
TOSHIBA_ACPI_VERSION);
- pr_info(" HCI method: %s\n", method_hci);
-
- mutex_init(&toshiba_acpi.mutex);
-
- toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi",
- -1, NULL, 0);
- if (IS_ERR(toshiba_acpi.p_dev)) {
- ret = PTR_ERR(toshiba_acpi.p_dev);
- pr_err("unable to register platform device\n");
- toshiba_acpi.p_dev = NULL;
- toshiba_acpi_exit();
- return ret;
+
+ hci_method = find_hci_method(acpi_dev->handle);
+ if (!hci_method) {
+ pr_err("HCI interface not found\n");
+ return -ENODEV;
}
- force_fan = 0;
- key_event_valid = 0;
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ dev->acpi_dev = acpi_dev;
+ dev->method_hci = hci_method;
+ acpi_dev->driver_data = dev;
- /* enable event fifo */
- hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+ if (toshiba_acpi_setup_keyboard(dev))
+ pr_info("Unable to activate hotkeys\n");
- toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
- if (!toshiba_proc_dir) {
- toshiba_acpi_exit();
- return -ENODEV;
- } else {
- create_toshiba_proc_entries();
- }
+ mutex_init(&dev->mutex);
+
+ /* enable event fifo */
+ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
+ if (hci_result == HCI_SUCCESS)
+ dev->system_event_supported = 1;
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
- toshiba_backlight_device = backlight_device_register("toshiba",
- &toshiba_acpi.p_dev->dev,
- NULL,
- &toshiba_backlight_data,
- &props);
- if (IS_ERR(toshiba_backlight_device)) {
- ret = PTR_ERR(toshiba_backlight_device);
+ dev->backlight_dev = backlight_device_register("toshiba",
+ &acpi_dev->dev,
+ dev,
+ &toshiba_backlight_data,
+ &props);
+ if (IS_ERR(dev->backlight_dev)) {
+ ret = PTR_ERR(dev->backlight_dev);
pr_err("Could not register toshiba backlight device\n");
- toshiba_backlight_device = NULL;
- toshiba_acpi_exit();
- return ret;
+ dev->backlight_dev = NULL;
+ goto error;
}
+ dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev);
/* Register rfkill switch for Bluetooth */
- if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
- toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name,
- &toshiba_acpi.p_dev->dev,
- RFKILL_TYPE_BLUETOOTH,
- &toshiba_rfk_ops,
- &toshiba_acpi);
- if (!toshiba_acpi.bt_rfk) {
+ if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) {
+ dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth",
+ &acpi_dev->dev,
+ RFKILL_TYPE_BLUETOOTH,
+ &toshiba_rfk_ops,
+ dev);
+ if (!dev->bt_rfk) {
pr_err("unable to allocate rfkill device\n");
- toshiba_acpi_exit();
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto error;
}
- ret = rfkill_register(toshiba_acpi.bt_rfk);
+ ret = rfkill_register(dev->bt_rfk);
if (ret) {
pr_err("unable to register rfkill device\n");
- rfkill_destroy(toshiba_acpi.bt_rfk);
- toshiba_acpi_exit();
- return ret;
+ rfkill_destroy(dev->bt_rfk);
+ goto error;
}
}
- toshiba_acpi.illumination_installed = 0;
- if (toshiba_illumination_available()) {
- if (!led_classdev_register(&(toshiba_acpi.p_dev->dev),
- &toshiba_led))
- toshiba_acpi.illumination_installed = 1;
+ if (toshiba_illumination_available(dev)) {
+ dev->led_dev.name = "toshiba::illumination";
+ dev->led_dev.max_brightness = 1;
+ dev->led_dev.brightness_set = toshiba_illumination_set;
+ dev->led_dev.brightness_get = toshiba_illumination_get;
+ if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev))
+ dev->illumination_supported = 1;
}
+ /* Determine whether or not BIOS supports fan and video interfaces */
+
+ ret = get_video_status(dev, &dummy);
+ dev->video_supported = !ret;
+
+ ret = get_fan_status(dev, &dummy);
+ dev->fan_supported = !ret;
+
+ create_toshiba_proc_entries(dev);
+
return 0;
+
+error:
+ toshiba_acpi_remove(acpi_dev, 0);
+ return ret;
+}
+
+static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
+{
+ struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+ u32 hci_result, value;
+ int retries = 3;
+
+ if (!dev->system_event_supported || event != 0x80)
+ return;
+
+ do {
+ hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
+ switch (hci_result) {
+ case HCI_SUCCESS:
+ if (value == 0x100)
+ continue;
+ /* act on key press; ignore key release */
+ if (value & 0x80)
+ continue;
+
+ if (!sparse_keymap_report_event(dev->hotkey_dev,
+ value, 1, true)) {
+ pr_info("Unknown key %x\n",
+ value);
+ }
+ break;
+ case HCI_NOT_SUPPORTED:
+ /* This is a workaround for an unresolved issue on
+ * some machines where system events sporadically
+ * become disabled. */
+ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
+ pr_notice("Re-enabled hotkeys\n");
+ /* fall through */
+ default:
+ retries--;
+ break;
+ }
+ } while (retries && hci_result != HCI_EMPTY);
+}
+
+
+static struct acpi_driver toshiba_acpi_driver = {
+ .name = "Toshiba ACPI driver",
+ .owner = THIS_MODULE,
+ .ids = toshiba_device_ids,
+ .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+ .ops = {
+ .add = toshiba_acpi_add,
+ .remove = toshiba_acpi_remove,
+ .notify = toshiba_acpi_notify,
+ },
+};
+
+static int __init toshiba_acpi_init(void)
+{
+ int ret;
+
+ toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
+ if (!toshiba_proc_dir) {
+ pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
+ return -ENODEV;
+ }
+
+ ret = acpi_bus_register_driver(&toshiba_acpi_driver);
+ if (ret) {
+ pr_err("Failed to register ACPI driver: %d\n", ret);
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ }
+
+ return ret;
+}
+
+static void __exit toshiba_acpi_exit(void)
+{
+ acpi_bus_unregister_driver(&toshiba_acpi_driver);
+ if (toshiba_proc_dir)
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
}
module_init(toshiba_acpi_init);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 9b88be4..a134c26 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -36,6 +36,7 @@
#include <linux/list.h>
#include <linux/acpi.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 8ac530a..291906e 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/export.h>
#include <linux/acpi.h>
#include <linux/pnp.h>
#include <linux/slab.h>
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 100e4d9..5be4a39 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -511,9 +511,6 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
int i;
unsigned char map = 0, flags;
- if (p->channel_count == 0)
- return;
-
for (i = 0; i < p->channel_count; i++)
map |= 1 << p->channels[i];
@@ -529,9 +526,6 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
pnp_irq_mask_t map;
unsigned char flags;
- if (p->interrupt_count == 0)
- return;
-
bitmap_zero(map.bits, PNP_IRQ_NR);
for (i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i])
@@ -549,9 +543,6 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
pnp_irq_mask_t map;
unsigned char flags;
- if (p->interrupt_count == 0)
- return;
-
bitmap_zero(map.bits, PNP_IRQ_NR);
for (i = 0; i < p->interrupt_count; i++) {
if (p->interrupts[i]) {
@@ -574,9 +565,6 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
{
unsigned char flags = 0;
- if (io->address_length == 0)
- return;
-
if (io->io_decode == ACPI_DECODE_16)
flags = IORESOURCE_IO_16BIT_ADDR;
pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
@@ -587,9 +575,6 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
unsigned int option_flags,
struct acpi_resource_fixed_io *io)
{
- if (io->address_length == 0)
- return;
-
pnp_register_port_resource(dev, option_flags, io->address, io->address,
0, io->address_length, IORESOURCE_IO_FIXED);
}
@@ -600,9 +585,6 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
{
unsigned char flags = 0;
- if (p->address_length == 0)
- return;
-
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
@@ -615,9 +597,6 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
{
unsigned char flags = 0;
- if (p->address_length == 0)
- return;
-
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
@@ -630,9 +609,6 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
{
unsigned char flags = 0;
- if (p->address_length == 0)
- return;
-
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->address, p->address,
@@ -654,9 +630,6 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
return;
}
- if (p->address_length == 0)
- return;
-
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
@@ -676,9 +649,6 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
struct acpi_resource_extended_address64 *p = &r->data.ext_address64;
unsigned char flags = 0;
- if (p->address_length == 0)
- return;
-
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
@@ -1018,7 +988,7 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
io->minimum = p->start;
io->maximum = p->end;
io->alignment = 0; /* Correct? */
- io->address_length = p->end - p->start + 1;
+ io->address_length = resource_size(p);
} else {
io->minimum = 0;
io->address_length = 0;
@@ -1036,7 +1006,7 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
if (pnp_resource_enabled(p)) {
fixed_io->address = p->start;
- fixed_io->address_length = p->end - p->start + 1;
+ fixed_io->address_length = resource_size(p);
} else {
fixed_io->address = 0;
fixed_io->address_length = 0;
@@ -1059,7 +1029,7 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
memory24->minimum = p->start;
memory24->maximum = p->end;
memory24->alignment = 0;
- memory24->address_length = p->end - p->start + 1;
+ memory24->address_length = resource_size(p);
} else {
memory24->minimum = 0;
memory24->address_length = 0;
@@ -1083,7 +1053,7 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
memory32->minimum = p->start;
memory32->maximum = p->end;
memory32->alignment = 0;
- memory32->address_length = p->end - p->start + 1;
+ memory32->address_length = resource_size(p);
} else {
memory32->minimum = 0;
memory32->alignment = 0;
@@ -1106,7 +1076,7 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
p->flags & IORESOURCE_MEM_WRITEABLE ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
fixed_memory32->address = p->start;
- fixed_memory32->address_length = p->end - p->start + 1;
+ fixed_memory32->address_length = resource_size(p);
} else {
fixed_memory32->address = 0;
fixed_memory32->address_length = 0;
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index cb1f47b..cca2f9f 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -505,7 +505,7 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -529,7 +529,7 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -559,7 +559,7 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -617,7 +617,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -636,11 +636,11 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
struct resource *res)
{
unsigned long base = res->start;
- unsigned long len = res->end - res->start + 1;
+ unsigned long len = resource_size(res);
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
index 8520a7f..445197d 100644
--- a/drivers/pps/clients/Kconfig
+++ b/drivers/pps/clients/Kconfig
@@ -29,4 +29,13 @@ config PPS_CLIENT_PARPORT
If you say yes here you get support for a PPS source connected
with the interrupt pin of your parallel port.
+config PPS_CLIENT_GPIO
+ tristate "PPS client using GPIO"
+ depends on PPS && GENERIC_HARDIRQS
+ help
+ If you say yes here you get support for a PPS source using
+ GPIO. To be useful you must also register a platform device
+ specifying the GPIO pin and other options, usually in your board
+ setup.
+
endif
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
index 4feb7e9..a461d15 100644
--- a/drivers/pps/clients/Makefile
+++ b/drivers/pps/clients/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o
obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o
obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o
+obj-$(CONFIG_PPS_CLIENT_GPIO) += pps-gpio.o
ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c
index 82583b0..436b4e4 100644
--- a/drivers/pps/clients/pps-ktimer.c
+++ b/drivers/pps/clients/pps-ktimer.c
@@ -52,17 +52,6 @@ static void pps_ktimer_event(unsigned long ptr)
}
/*
- * The echo function
- */
-
-static void pps_ktimer_echo(struct pps_device *pps, int event, void *data)
-{
- dev_info(pps->dev, "echo %s %s\n",
- event & PPS_CAPTUREASSERT ? "assert" : "",
- event & PPS_CAPTURECLEAR ? "clear" : "");
-}
-
-/*
* The PPS info struct
*/
@@ -72,7 +61,6 @@ static struct pps_source_info pps_ktimer_info = {
.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
PPS_ECHOASSERT |
PPS_CANWAIT | PPS_TSFMT_TSPEC,
- .echo = pps_ktimer_echo,
.owner = THIS_MODULE,
};
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c
index 79451f2..60cee9e 100644
--- a/drivers/pps/clients/pps-ldisc.c
+++ b/drivers/pps/clients/pps-ldisc.c
@@ -31,7 +31,7 @@
static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status,
struct pps_event_time *ts)
{
- struct pps_device *pps = (struct pps_device *)tty->disc_data;
+ struct pps_device *pps = pps_lookup_dev(tty);
BUG_ON(pps == NULL);
@@ -67,9 +67,9 @@ static int pps_tty_open(struct tty_struct *tty)
pr_err("cannot register PPS source \"%s\"\n", info.path);
return -ENOMEM;
}
- tty->disc_data = pps;
+ pps->lookup_cookie = tty;
- /* Should open N_TTY ldisc too */
+ /* Now open the base class N_TTY ldisc */
ret = alias_n_tty_open(tty);
if (ret < 0) {
pr_err("cannot open tty ldisc \"%s\"\n", info.path);
@@ -81,7 +81,6 @@ static int pps_tty_open(struct tty_struct *tty)
return 0;
err_unregister:
- tty->disc_data = NULL;
pps_unregister_source(pps);
return ret;
}
@@ -90,11 +89,10 @@ static void (*alias_n_tty_close)(struct tty_struct *tty);
static void pps_tty_close(struct tty_struct *tty)
{
- struct pps_device *pps = (struct pps_device *)tty->disc_data;
+ struct pps_device *pps = pps_lookup_dev(tty);
alias_n_tty_close(tty);
- tty->disc_data = NULL;
dev_info(pps->dev, "removed\n");
pps_unregister_source(pps);
}
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index c571d6d..e1b4705 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -133,14 +133,6 @@ out_both:
return;
}
-/* the PPS echo function */
-static void pps_echo(struct pps_device *pps, int event, void *data)
-{
- dev_info(pps->dev, "echo %s %s\n",
- event & PPS_CAPTUREASSERT ? "assert" : "",
- event & PPS_CAPTURECLEAR ? "clear" : "");
-}
-
static void parport_attach(struct parport *port)
{
struct pps_client_pp *device;
@@ -151,7 +143,6 @@ static void parport_attach(struct parport *port)
PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
PPS_ECHOASSERT | PPS_ECHOCLEAR | \
PPS_CANWAIT | PPS_TSFMT_TSPEC,
- .echo = pps_echo,
.owner = THIS_MODULE,
.dev = NULL
};
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index a4e8eb9..f197e8e 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -52,6 +52,14 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
ts->sec += offset->sec;
}
+static void pps_echo_client_default(struct pps_device *pps, int event,
+ void *data)
+{
+ dev_info(pps->dev, "echo %s %s\n",
+ event & PPS_CAPTUREASSERT ? "assert" : "",
+ event & PPS_CAPTURECLEAR ? "clear" : "");
+}
+
/*
* Exported functions
*/
@@ -80,13 +88,6 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
err = -EINVAL;
goto pps_register_source_exit;
}
- if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 &&
- info->echo == NULL) {
- pr_err("%s: echo function is not defined\n",
- info->name);
- err = -EINVAL;
- goto pps_register_source_exit;
- }
if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
pr_err("%s: unspecified time format\n",
info->name);
@@ -108,6 +109,11 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
pps->params.mode = default_params;
pps->info = *info;
+ /* check for default echo function */
+ if ((pps->info.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) &&
+ pps->info.echo == NULL)
+ pps->info.echo = pps_echo_client_default;
+
init_waitqueue_head(&pps->queue);
spin_lock_init(&pps->lock);
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 2baadd2..e83669f 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -247,12 +247,15 @@ static int pps_cdev_open(struct inode *inode, struct file *file)
struct pps_device *pps = container_of(inode->i_cdev,
struct pps_device, cdev);
file->private_data = pps;
-
+ kobject_get(&pps->dev->kobj);
return 0;
}
static int pps_cdev_release(struct inode *inode, struct file *file)
{
+ struct pps_device *pps = container_of(inode->i_cdev,
+ struct pps_device, cdev);
+ kobject_put(&pps->dev->kobj);
return 0;
}
@@ -274,8 +277,10 @@ static void pps_device_destruct(struct device *dev)
{
struct pps_device *pps = dev_get_drvdata(dev);
- /* release id here to protect others from using it while it's
- * still in use */
+ cdev_del(&pps->cdev);
+
+ /* Now we can release the ID for re-use */
+ pr_debug("deallocating pps%d\n", pps->id);
mutex_lock(&pps_idr_lock);
idr_remove(&pps_idr, pps->id);
mutex_unlock(&pps_idr_lock);
@@ -330,6 +335,7 @@ int pps_register_cdev(struct pps_device *pps)
if (IS_ERR(pps->dev))
goto del_cdev;
+ /* Override the release function with our own */
pps->dev->release = pps_device_destruct;
pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
@@ -350,11 +356,44 @@ free_idr:
void pps_unregister_cdev(struct pps_device *pps)
{
+ pr_debug("unregistering pps%d\n", pps->id);
+ pps->lookup_cookie = NULL;
device_destroy(pps_class, pps->dev->devt);
- cdev_del(&pps->cdev);
}
/*
+ * Look up a pps device by magic cookie.
+ * The cookie is usually a pointer to some enclosing device, but this
+ * code doesn't care; you should never be dereferencing it.
+ *
+ * This is a bit of a kludge that is currently used only by the PPS
+ * serial line discipline. It may need to be tweaked when a second user
+ * is found.
+ *
+ * There is no function interface for setting the lookup_cookie field.
+ * It's initialized to NULL when the pps device is created, and if a
+ * client wants to use it, just fill it in afterward.
+ *
+ * The cookie is automatically set to NULL in pps_unregister_source()
+ * so that it will not be used again, even if the pps device cannot
+ * be removed from the idr due to pending references holding the minor
+ * number in use.
+ */
+struct pps_device *pps_lookup_dev(void const *cookie)
+{
+ struct pps_device *pps;
+ unsigned id;
+
+ rcu_read_lock();
+ idr_for_each_entry(&pps_idr, pps, id)
+ if (cookie == pps->lookup_cookie)
+ break;
+ rcu_read_unlock();
+ return pps;
+}
+EXPORT_SYMBOL(pps_lookup_dev);
+
+/*
* Module stuff
*/
diff --git a/drivers/ps3/ps3-vuart.c b/drivers/ps3/ps3-vuart.c
index d9fb729..fb73008 100644
--- a/drivers/ps3/ps3-vuart.c
+++ b/drivers/ps3/ps3-vuart.c
@@ -952,7 +952,7 @@ static int ps3_vuart_bus_interrupt_get(void)
}
result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
- IRQF_DISABLED, "vuart", &vuart_bus_priv);
+ 0, "vuart", &vuart_bus_priv);
if (result) {
pr_debug("%s:%d: request_irq failed (%d)\n",
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
index af0afa1..8c3f5ad 100644
--- a/drivers/ps3/ps3stor_lib.c
+++ b/drivers/ps3/ps3stor_lib.c
@@ -19,6 +19,7 @@
*/
#include <linux/dma-mapping.h>
+#include <linux/module.h>
#include <asm/lv1call.h>
#include <asm/ps3stor.h>
@@ -166,7 +167,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
goto fail_close_device;
}
- error = request_irq(dev->irq, handler, IRQF_DISABLED,
+ error = request_irq(dev->irq, handler, 0,
dev->sbd.core.driver->name, dev);
if (error) {
dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
index 4742258..0e41737 100644
--- a/drivers/ps3/sys-manager-core.c
+++ b/drivers/ps3/sys-manager-core.c
@@ -19,6 +19,7 @@
*/
#include <linux/kernel.h>
+#include <linux/export.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
index 070211a..bc87192 100644
--- a/drivers/rapidio/Kconfig
+++ b/drivers/rapidio/Kconfig
@@ -1,6 +1,8 @@
#
# RapidIO configuration
#
+source "drivers/rapidio/devices/Kconfig"
+
config RAPIDIO_DISC_TIMEOUT
int "Discovery timeout duration (seconds)"
depends on RAPIDIO
@@ -20,8 +22,6 @@ config RAPIDIO_ENABLE_RX_TX_PORTS
ports for Input/Output direction to allow other traffic
than Maintenance transfers.
-source "drivers/rapidio/switches/Kconfig"
-
config RAPIDIO_DEBUG
bool "RapidIO subsystem debug messages"
depends on RAPIDIO
@@ -32,3 +32,5 @@ config RAPIDIO_DEBUG
going on.
If you are unsure about this, say N here.
+
+source "drivers/rapidio/switches/Kconfig"
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
index 89b8eca..ec3fb81 100644
--- a/drivers/rapidio/Makefile
+++ b/drivers/rapidio/Makefile
@@ -4,5 +4,6 @@
obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
obj-$(CONFIG_RAPIDIO) += switches/
+obj-$(CONFIG_RAPIDIO) += devices/
subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index ebe77dd..2bebd79 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -516,7 +516,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
return rdev;
cleanup:
- if (rio_is_switch(rdev))
+ if (rswitch)
kfree(rswitch->route_table);
kfree(rdev);
@@ -923,7 +923,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
* rio_enum_complete- Tests if enumeration of a network is complete
* @port: Master port to send transaction
*
- * Tests the Component Tag CSR for non-zero value (enumeration
+ * Tests the PGCCSR discovered bit for non-zero value (enumeration
* complete flag). Return %1 if enumeration is complete or %0 if
* enumeration is incomplete.
*/
@@ -933,7 +933,7 @@ static int rio_enum_complete(struct rio_mport *port)
rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
&regval);
- return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
+ return (regval & RIO_PORT_GEN_DISCOVERED) ? 1 : 0;
}
/**
diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c
index 043ee31..809b7a3 100644
--- a/drivers/rapidio/switches/idt_gen2.c
+++ b/drivers/rapidio/switches/idt_gen2.c
@@ -10,6 +10,7 @@
* option) any later version.
*/
+#include <linux/stat.h>
#include <linux/rio.h>
#include <linux/rio_drv.h>
#include <linux/rio_ids.h>
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 86b6f1c..65894f0 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -11,7 +11,6 @@
#define KMSG_COMPONENT "dasd"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -22,6 +21,9 @@
#include <linux/hdreg.h>
#include <linux/async.h>
#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -45,6 +47,7 @@
* SECTION: exported variables of dasd.c
*/
debug_info_t *dasd_debug_area;
+static struct dentry *dasd_debugfs_root_entry;
struct dasd_discipline *dasd_diag_discipline_pointer;
void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
@@ -71,6 +74,8 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
static void dasd_device_timeout(unsigned long);
static void dasd_block_timeout(unsigned long);
static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *);
+static void dasd_profile_init(struct dasd_profile *, struct dentry *);
+static void dasd_profile_exit(struct dasd_profile *);
/*
* SECTION: Operations on the device structure.
@@ -121,7 +126,7 @@ struct dasd_device *dasd_alloc_device(void)
device->state = DASD_STATE_NEW;
device->target = DASD_STATE_NEW;
mutex_init(&device->state_mutex);
-
+ spin_lock_init(&device->profile.lock);
return device;
}
@@ -159,6 +164,7 @@ struct dasd_block *dasd_alloc_block(void)
init_timer(&block->timer);
block->timer.function = dasd_block_timeout;
block->timer.data = (unsigned long) block;
+ spin_lock_init(&block->profile.lock);
return block;
}
@@ -222,19 +228,44 @@ static int dasd_state_known_to_new(struct dasd_device *device)
return 0;
}
+static struct dentry *dasd_debugfs_setup(const char *name,
+ struct dentry *base_dentry)
+{
+ struct dentry *pde;
+
+ if (!base_dentry)
+ return NULL;
+ pde = debugfs_create_dir(name, base_dentry);
+ if (!pde || IS_ERR(pde))
+ return NULL;
+ return pde;
+}
+
/*
* Request the irq line for the device.
*/
static int dasd_state_known_to_basic(struct dasd_device *device)
{
+ struct dasd_block *block = device->block;
int rc;
/* Allocate and register gendisk structure. */
- if (device->block) {
- rc = dasd_gendisk_alloc(device->block);
+ if (block) {
+ rc = dasd_gendisk_alloc(block);
if (rc)
return rc;
- }
+ block->debugfs_dentry =
+ dasd_debugfs_setup(block->gdp->disk_name,
+ dasd_debugfs_root_entry);
+ dasd_profile_init(&block->profile, block->debugfs_dentry);
+ if (dasd_global_profile_level == DASD_PROFILE_ON)
+ dasd_profile_on(&device->block->profile);
+ }
+ device->debugfs_dentry =
+ dasd_debugfs_setup(dev_name(&device->cdev->dev),
+ dasd_debugfs_root_entry);
+ dasd_profile_init(&device->profile, device->debugfs_dentry);
+
/* register 'device' debug area, used for all DBF_DEV_XXX calls */
device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1,
8 * sizeof(long));
@@ -253,6 +284,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
{
int rc;
if (device->block) {
+ dasd_profile_exit(&device->block->profile);
+ if (device->block->debugfs_dentry)
+ debugfs_remove(device->block->debugfs_dentry);
dasd_gendisk_free(device->block);
dasd_block_clear_timer(device->block);
}
@@ -260,6 +294,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
if (rc)
return rc;
dasd_device_clear_timer(device);
+ dasd_profile_exit(&device->profile);
+ if (device->debugfs_dentry)
+ debugfs_remove(device->debugfs_dentry);
DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
if (device->debug_area != NULL) {
@@ -609,21 +646,13 @@ void dasd_enable_device(struct dasd_device *device)
/*
* SECTION: device operation (interrupt handler, start i/o, term i/o ...)
*/
-#ifdef CONFIG_DASD_PROFILE
-struct dasd_profile_info_t dasd_global_profile;
-unsigned int dasd_profile_level = DASD_PROFILE_OFF;
+unsigned int dasd_global_profile_level = DASD_PROFILE_OFF;
-/*
- * Increments counter in global and local profiling structures.
- */
-#define dasd_profile_counter(value, counter, block) \
-{ \
- int index; \
- for (index = 0; index < 31 && value >> (2+index); index++); \
- dasd_global_profile.counter[index]++; \
- block->profile.counter[index]++; \
-}
+#ifdef CONFIG_DASD_PROFILE
+struct dasd_profile_info dasd_global_profile_data;
+static struct dentry *dasd_global_profile_dentry;
+static struct dentry *dasd_debugfs_global_entry;
/*
* Add profiling information for cqr before execution.
@@ -634,30 +663,121 @@ static void dasd_profile_start(struct dasd_block *block,
{
struct list_head *l;
unsigned int counter;
-
- if (dasd_profile_level != DASD_PROFILE_ON)
- return;
+ struct dasd_device *device;
/* count the length of the chanq for statistics */
counter = 0;
- list_for_each(l, &block->ccw_queue)
- if (++counter >= 31)
- break;
- dasd_global_profile.dasd_io_nr_req[counter]++;
- block->profile.dasd_io_nr_req[counter]++;
+ if (dasd_global_profile_level || block->profile.data)
+ list_for_each(l, &block->ccw_queue)
+ if (++counter >= 31)
+ break;
+
+ if (dasd_global_profile_level) {
+ dasd_global_profile_data.dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ dasd_global_profile_data.dasd_read_nr_req[counter]++;
+ }
+
+ spin_lock(&block->profile.lock);
+ if (block->profile.data)
+ block->profile.data->dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ block->profile.data->dasd_read_nr_req[counter]++;
+ spin_unlock(&block->profile.lock);
+
+ /*
+ * We count the request for the start device, even though it may run on
+ * some other device due to error recovery. This way we make sure that
+ * we count each request only once.
+ */
+ device = cqr->startdev;
+ if (device->profile.data) {
+ counter = 1; /* request is not yet queued on the start device */
+ list_for_each(l, &device->ccw_queue)
+ if (++counter >= 31)
+ break;
+ }
+ spin_lock(&device->profile.lock);
+ if (device->profile.data) {
+ device->profile.data->dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ device->profile.data->dasd_read_nr_req[counter]++;
+ }
+ spin_unlock(&device->profile.lock);
}
/*
* Add profiling information for cqr after execution.
*/
+
+#define dasd_profile_counter(value, index) \
+{ \
+ for (index = 0; index < 31 && value >> (2+index); index++) \
+ ; \
+}
+
+static void dasd_profile_end_add_data(struct dasd_profile_info *data,
+ int is_alias,
+ int is_tpm,
+ int is_read,
+ long sectors,
+ int sectors_ind,
+ int tottime_ind,
+ int tottimeps_ind,
+ int strtime_ind,
+ int irqtime_ind,
+ int irqtimeps_ind,
+ int endtime_ind)
+{
+ /* in case of an overflow, reset the whole profile */
+ if (data->dasd_io_reqs == UINT_MAX) {
+ memset(data, 0, sizeof(*data));
+ getnstimeofday(&data->starttod);
+ }
+ data->dasd_io_reqs++;
+ data->dasd_io_sects += sectors;
+ if (is_alias)
+ data->dasd_io_alias++;
+ if (is_tpm)
+ data->dasd_io_tpm++;
+
+ data->dasd_io_secs[sectors_ind]++;
+ data->dasd_io_times[tottime_ind]++;
+ data->dasd_io_timps[tottimeps_ind]++;
+ data->dasd_io_time1[strtime_ind]++;
+ data->dasd_io_time2[irqtime_ind]++;
+ data->dasd_io_time2ps[irqtimeps_ind]++;
+ data->dasd_io_time3[endtime_ind]++;
+
+ if (is_read) {
+ data->dasd_read_reqs++;
+ data->dasd_read_sects += sectors;
+ if (is_alias)
+ data->dasd_read_alias++;
+ if (is_tpm)
+ data->dasd_read_tpm++;
+ data->dasd_read_secs[sectors_ind]++;
+ data->dasd_read_times[tottime_ind]++;
+ data->dasd_read_time1[strtime_ind]++;
+ data->dasd_read_time2[irqtime_ind]++;
+ data->dasd_read_time3[endtime_ind]++;
+ }
+}
+
static void dasd_profile_end(struct dasd_block *block,
struct dasd_ccw_req *cqr,
struct request *req)
{
long strtime, irqtime, endtime, tottime; /* in microseconds */
long tottimeps, sectors;
+ struct dasd_device *device;
+ int sectors_ind, tottime_ind, tottimeps_ind, strtime_ind;
+ int irqtime_ind, irqtimeps_ind, endtime_ind;
- if (dasd_profile_level != DASD_PROFILE_ON)
+ device = cqr->startdev;
+ if (!(dasd_global_profile_level ||
+ block->profile.data ||
+ device->profile.data))
return;
sectors = blk_rq_sectors(req);
@@ -672,29 +792,392 @@ static void dasd_profile_end(struct dasd_block *block,
tottime = ((cqr->endclk - cqr->buildclk) >> 12);
tottimeps = tottime / sectors;
- if (!dasd_global_profile.dasd_io_reqs)
- memset(&dasd_global_profile, 0,
- sizeof(struct dasd_profile_info_t));
- dasd_global_profile.dasd_io_reqs++;
- dasd_global_profile.dasd_io_sects += sectors;
-
- if (!block->profile.dasd_io_reqs)
- memset(&block->profile, 0,
- sizeof(struct dasd_profile_info_t));
- block->profile.dasd_io_reqs++;
- block->profile.dasd_io_sects += sectors;
-
- dasd_profile_counter(sectors, dasd_io_secs, block);
- dasd_profile_counter(tottime, dasd_io_times, block);
- dasd_profile_counter(tottimeps, dasd_io_timps, block);
- dasd_profile_counter(strtime, dasd_io_time1, block);
- dasd_profile_counter(irqtime, dasd_io_time2, block);
- dasd_profile_counter(irqtime / sectors, dasd_io_time2ps, block);
- dasd_profile_counter(endtime, dasd_io_time3, block);
+ dasd_profile_counter(sectors, sectors_ind);
+ dasd_profile_counter(tottime, tottime_ind);
+ dasd_profile_counter(tottimeps, tottimeps_ind);
+ dasd_profile_counter(strtime, strtime_ind);
+ dasd_profile_counter(irqtime, irqtime_ind);
+ dasd_profile_counter(irqtime / sectors, irqtimeps_ind);
+ dasd_profile_counter(endtime, endtime_ind);
+
+ if (dasd_global_profile_level) {
+ dasd_profile_end_add_data(&dasd_global_profile_data,
+ cqr->startdev != block->base,
+ cqr->cpmode == 1,
+ rq_data_dir(req) == READ,
+ sectors, sectors_ind, tottime_ind,
+ tottimeps_ind, strtime_ind,
+ irqtime_ind, irqtimeps_ind,
+ endtime_ind);
+ }
+
+ spin_lock(&block->profile.lock);
+ if (block->profile.data)
+ dasd_profile_end_add_data(block->profile.data,
+ cqr->startdev != block->base,
+ cqr->cpmode == 1,
+ rq_data_dir(req) == READ,
+ sectors, sectors_ind, tottime_ind,
+ tottimeps_ind, strtime_ind,
+ irqtime_ind, irqtimeps_ind,
+ endtime_ind);
+ spin_unlock(&block->profile.lock);
+
+ spin_lock(&device->profile.lock);
+ if (device->profile.data)
+ dasd_profile_end_add_data(device->profile.data,
+ cqr->startdev != block->base,
+ cqr->cpmode == 1,
+ rq_data_dir(req) == READ,
+ sectors, sectors_ind, tottime_ind,
+ tottimeps_ind, strtime_ind,
+ irqtime_ind, irqtimeps_ind,
+ endtime_ind);
+ spin_unlock(&device->profile.lock);
+}
+
+void dasd_profile_reset(struct dasd_profile *profile)
+{
+ struct dasd_profile_info *data;
+
+ spin_lock_bh(&profile->lock);
+ data = profile->data;
+ if (!data) {
+ spin_unlock_bh(&profile->lock);
+ return;
+ }
+ memset(data, 0, sizeof(*data));
+ getnstimeofday(&data->starttod);
+ spin_unlock_bh(&profile->lock);
+}
+
+void dasd_global_profile_reset(void)
+{
+ memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data));
+ getnstimeofday(&dasd_global_profile_data.starttod);
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+ struct dasd_profile_info *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ spin_lock_bh(&profile->lock);
+ if (profile->data) {
+ spin_unlock_bh(&profile->lock);
+ kfree(data);
+ return 0;
+ }
+ getnstimeofday(&data->starttod);
+ profile->data = data;
+ spin_unlock_bh(&profile->lock);
+ return 0;
+}
+
+void dasd_profile_off(struct dasd_profile *profile)
+{
+ spin_lock_bh(&profile->lock);
+ kfree(profile->data);
+ profile->data = NULL;
+ spin_unlock_bh(&profile->lock);
+}
+
+char *dasd_get_user_string(const char __user *user_buf, size_t user_len)
+{
+ char *buffer;
+
+ buffer = vmalloc(user_len + 1);
+ if (buffer == NULL)
+ return ERR_PTR(-ENOMEM);
+ if (copy_from_user(buffer, user_buf, user_len) != 0) {
+ vfree(buffer);
+ return ERR_PTR(-EFAULT);
+ }
+ /* got the string, now strip linefeed. */
+ if (buffer[user_len - 1] == '\n')
+ buffer[user_len - 1] = 0;
+ else
+ buffer[user_len] = 0;
+ return buffer;
+}
+
+static ssize_t dasd_stats_write(struct file *file,
+ const char __user *user_buf,
+ size_t user_len, loff_t *pos)
+{
+ char *buffer, *str;
+ int rc;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct dasd_profile *prof = m->private;
+
+ if (user_len > 65536)
+ user_len = 65536;
+ buffer = dasd_get_user_string(user_buf, user_len);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+
+ str = skip_spaces(buffer);
+ rc = user_len;
+ if (strncmp(str, "reset", 5) == 0) {
+ dasd_profile_reset(prof);
+ } else if (strncmp(str, "on", 2) == 0) {
+ rc = dasd_profile_on(prof);
+ if (!rc)
+ rc = user_len;
+ } else if (strncmp(str, "off", 3) == 0) {
+ dasd_profile_off(prof);
+ } else
+ rc = -EINVAL;
+ vfree(buffer);
+ return rc;
+}
+
+static void dasd_stats_array(struct seq_file *m, unsigned int *array)
+{
+ int i;
+
+ for (i = 0; i < 32; i++)
+ seq_printf(m, "%u ", array[i]);
+ seq_putc(m, '\n');
+}
+
+static void dasd_stats_seq_print(struct seq_file *m,
+ struct dasd_profile_info *data)
+{
+ seq_printf(m, "start_time %ld.%09ld\n",
+ data->starttod.tv_sec, data->starttod.tv_nsec);
+ seq_printf(m, "total_requests %u\n", data->dasd_io_reqs);
+ seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
+ seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
+ seq_printf(m, "total_hpf %u\n", data->dasd_io_tpm);
+ seq_printf(m, "histogram_sectors ");
+ dasd_stats_array(m, data->dasd_io_secs);
+ seq_printf(m, "histogram_io_times ");
+ dasd_stats_array(m, data->dasd_io_times);
+ seq_printf(m, "histogram_io_times_weighted ");
+ dasd_stats_array(m, data->dasd_io_timps);
+ seq_printf(m, "histogram_time_build_to_ssch ");
+ dasd_stats_array(m, data->dasd_io_time1);
+ seq_printf(m, "histogram_time_ssch_to_irq ");
+ dasd_stats_array(m, data->dasd_io_time2);
+ seq_printf(m, "histogram_time_ssch_to_irq_weighted ");
+ dasd_stats_array(m, data->dasd_io_time2ps);
+ seq_printf(m, "histogram_time_irq_to_end ");
+ dasd_stats_array(m, data->dasd_io_time3);
+ seq_printf(m, "histogram_ccw_queue_length ");
+ dasd_stats_array(m, data->dasd_io_nr_req);
+ seq_printf(m, "total_read_requests %u\n", data->dasd_read_reqs);
+ seq_printf(m, "total_read_sectors %u\n", data->dasd_read_sects);
+ seq_printf(m, "total_read_pav %u\n", data->dasd_read_alias);
+ seq_printf(m, "total_read_hpf %u\n", data->dasd_read_tpm);
+ seq_printf(m, "histogram_read_sectors ");
+ dasd_stats_array(m, data->dasd_read_secs);
+ seq_printf(m, "histogram_read_times ");
+ dasd_stats_array(m, data->dasd_read_times);
+ seq_printf(m, "histogram_read_time_build_to_ssch ");
+ dasd_stats_array(m, data->dasd_read_time1);
+ seq_printf(m, "histogram_read_time_ssch_to_irq ");
+ dasd_stats_array(m, data->dasd_read_time2);
+ seq_printf(m, "histogram_read_time_irq_to_end ");
+ dasd_stats_array(m, data->dasd_read_time3);
+ seq_printf(m, "histogram_read_ccw_queue_length ");
+ dasd_stats_array(m, data->dasd_read_nr_req);
+}
+
+static int dasd_stats_show(struct seq_file *m, void *v)
+{
+ struct dasd_profile *profile;
+ struct dasd_profile_info *data;
+
+ profile = m->private;
+ spin_lock_bh(&profile->lock);
+ data = profile->data;
+ if (!data) {
+ spin_unlock_bh(&profile->lock);
+ seq_printf(m, "disabled\n");
+ return 0;
+ }
+ dasd_stats_seq_print(m, data);
+ spin_unlock_bh(&profile->lock);
+ return 0;
+}
+
+static int dasd_stats_open(struct inode *inode, struct file *file)
+{
+ struct dasd_profile *profile = inode->i_private;
+ return single_open(file, dasd_stats_show, profile);
+}
+
+static const struct file_operations dasd_stats_raw_fops = {
+ .owner = THIS_MODULE,
+ .open = dasd_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = dasd_stats_write,
+};
+
+static ssize_t dasd_stats_global_write(struct file *file,
+ const char __user *user_buf,
+ size_t user_len, loff_t *pos)
+{
+ char *buffer, *str;
+ ssize_t rc;
+
+ if (user_len > 65536)
+ user_len = 65536;
+ buffer = dasd_get_user_string(user_buf, user_len);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+ str = skip_spaces(buffer);
+ rc = user_len;
+ if (strncmp(str, "reset", 5) == 0) {
+ dasd_global_profile_reset();
+ } else if (strncmp(str, "on", 2) == 0) {
+ dasd_global_profile_reset();
+ dasd_global_profile_level = DASD_PROFILE_GLOBAL_ONLY;
+ } else if (strncmp(str, "off", 3) == 0) {
+ dasd_global_profile_level = DASD_PROFILE_OFF;
+ } else
+ rc = -EINVAL;
+ vfree(buffer);
+ return rc;
+}
+
+static int dasd_stats_global_show(struct seq_file *m, void *v)
+{
+ if (!dasd_global_profile_level) {
+ seq_printf(m, "disabled\n");
+ return 0;
+ }
+ dasd_stats_seq_print(m, &dasd_global_profile_data);
+ return 0;
+}
+
+static int dasd_stats_global_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dasd_stats_global_show, NULL);
+}
+
+static const struct file_operations dasd_stats_global_fops = {
+ .owner = THIS_MODULE,
+ .open = dasd_stats_global_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = dasd_stats_global_write,
+};
+
+static void dasd_profile_init(struct dasd_profile *profile,
+ struct dentry *base_dentry)
+{
+ mode_t mode;
+ struct dentry *pde;
+
+ if (!base_dentry)
+ return;
+ profile->dentry = NULL;
+ profile->data = NULL;
+ mode = (S_IRUSR | S_IWUSR | S_IFREG);
+ pde = debugfs_create_file("statistics", mode, base_dentry,
+ profile, &dasd_stats_raw_fops);
+ if (pde && !IS_ERR(pde))
+ profile->dentry = pde;
+ return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+ dasd_profile_off(profile);
+ if (profile->dentry) {
+ debugfs_remove(profile->dentry);
+ profile->dentry = NULL;
+ }
+}
+
+static void dasd_statistics_removeroot(void)
+{
+ dasd_global_profile_level = DASD_PROFILE_OFF;
+ if (dasd_global_profile_dentry) {
+ debugfs_remove(dasd_global_profile_dentry);
+ dasd_global_profile_dentry = NULL;
+ }
+ if (dasd_debugfs_global_entry)
+ debugfs_remove(dasd_debugfs_global_entry);
+ if (dasd_debugfs_root_entry)
+ debugfs_remove(dasd_debugfs_root_entry);
+}
+
+static void dasd_statistics_createroot(void)
+{
+ mode_t mode;
+ struct dentry *pde;
+
+ dasd_debugfs_root_entry = NULL;
+ dasd_debugfs_global_entry = NULL;
+ dasd_global_profile_dentry = NULL;
+ pde = debugfs_create_dir("dasd", NULL);
+ if (!pde || IS_ERR(pde))
+ goto error;
+ dasd_debugfs_root_entry = pde;
+ pde = debugfs_create_dir("global", dasd_debugfs_root_entry);
+ if (!pde || IS_ERR(pde))
+ goto error;
+ dasd_debugfs_global_entry = pde;
+
+ mode = (S_IRUSR | S_IWUSR | S_IFREG);
+ pde = debugfs_create_file("statistics", mode, dasd_debugfs_global_entry,
+ NULL, &dasd_stats_global_fops);
+ if (!pde || IS_ERR(pde))
+ goto error;
+ dasd_global_profile_dentry = pde;
+ return;
+
+error:
+ DBF_EVENT(DBF_ERR, "%s",
+ "Creation of the dasd debugfs interface failed");
+ dasd_statistics_removeroot();
+ return;
}
+
#else
#define dasd_profile_start(block, cqr, req) do {} while (0)
#define dasd_profile_end(block, cqr, req) do {} while (0)
+
+static void dasd_statistics_createroot(void)
+{
+ return;
+}
+
+static void dasd_statistics_removeroot(void)
+{
+ return;
+}
+
+int dasd_stats_generic_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "Statistics are not activated in this kernel\n");
+ return 0;
+}
+
+static void dasd_profile_init(struct dasd_profile *profile,
+ struct dentry *base_dentry)
+{
+ return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+ return;
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+ return 0;
+}
+
#endif /* CONFIG_DASD_PROFILE */
/*
@@ -1110,7 +1593,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
unsigned long long now;
int expires;
- kstat_cpu(smp_processor_id()).irqs[IOINT_DAS]++;
if (IS_ERR(irb)) {
switch (PTR_ERR(irb)) {
case -EIO:
@@ -1577,13 +2059,14 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr)
/*
* Wakeup helper for the 'sleep_on' functions.
*/
-static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
+void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
{
spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev));
cqr->callback_data = DASD_SLEEPON_END_TAG;
spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev));
wake_up(&generic_waitq);
}
+EXPORT_SYMBOL_GPL(dasd_wakeup_cb);
static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
{
@@ -1683,7 +2166,9 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
} else
wait_event(generic_waitq, !(device->stopped));
- cqr->callback = dasd_wakeup_cb;
+ if (!cqr->callback)
+ cqr->callback = dasd_wakeup_cb;
+
cqr->callback_data = DASD_SLEEPON_START_TAG;
dasd_add_request_tail(cqr);
if (interruptible) {
@@ -1779,7 +2264,11 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
cqr->callback = dasd_wakeup_cb;
cqr->callback_data = DASD_SLEEPON_START_TAG;
cqr->status = DASD_CQR_QUEUED;
- list_add(&cqr->devlist, &device->ccw_queue);
+ /*
+ * add new request as second
+ * first the terminated cqr needs to be finished
+ */
+ list_add(&cqr->devlist, device->ccw_queue.next);
/* let the bh start the request to keep them in order */
dasd_schedule_device_bh(device);
@@ -2441,6 +2930,7 @@ dasd_exit(void)
debug_unregister(dasd_debug_area);
dasd_debug_area = NULL;
}
+ dasd_statistics_removeroot();
}
/*
@@ -2799,6 +3289,9 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
if (IS_ERR(device))
return PTR_ERR(device);
+ /* mark device as suspended */
+ set_bit(DASD_FLAG_SUSPENDED, &device->flags);
+
if (device->discipline->freeze)
rc = device->discipline->freeze(device);
@@ -2873,6 +3366,7 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
if (device->block)
dasd_schedule_block_bh(device->block);
+ clear_bit(DASD_FLAG_SUSPENDED, &device->flags);
dasd_put_device(device);
return 0;
}
@@ -2992,6 +3486,8 @@ static int __init dasd_init(void)
dasd_diag_discipline_pointer = NULL;
+ dasd_statistics_createroot();
+
rc = dasd_devmap_init();
if (rc)
goto failed;
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index cc2dd7f..fe9dacc 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -844,6 +844,30 @@ static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device,
set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
}
+/*
+ * Wakeup helper for read_conf
+ * if the cqr is not done and needs some error recovery
+ * the buffer has to be re-initialized with the EBCDIC "V1.0"
+ * to show support for virtual device SNEQ
+ */
+static void read_conf_cb(struct dasd_ccw_req *cqr, void *data)
+{
+ struct ccw1 *ccw;
+ __u8 *rcd_buffer;
+
+ if (cqr->status != DASD_CQR_DONE) {
+ ccw = cqr->cpaddr;
+ rcd_buffer = (__u8 *)((addr_t) ccw->cda);
+ memset(rcd_buffer, 0, sizeof(*rcd_buffer));
+
+ rcd_buffer[0] = 0xE5;
+ rcd_buffer[1] = 0xF1;
+ rcd_buffer[2] = 0x4B;
+ rcd_buffer[3] = 0xF0;
+ }
+ dasd_wakeup_cb(cqr, data);
+}
+
static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
struct dasd_ccw_req *cqr,
__u8 *rcd_buffer,
@@ -863,6 +887,7 @@ static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
cqr->retries = 5;
+ cqr->callback = read_conf_cb;
rc = dasd_sleep_on_immediatly(cqr);
return rc;
}
@@ -900,6 +925,7 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
goto out_error;
}
dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm);
+ cqr->callback = read_conf_cb;
ret = dasd_sleep_on(cqr);
/*
* on success we update the user input parms
@@ -1075,6 +1101,12 @@ static void do_path_verification_work(struct work_struct *work)
data = container_of(work, struct path_verification_work_data, worker);
device = data->device;
+ /* delay path verification until device was resumed */
+ if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
+ schedule_work(work);
+ return;
+ }
+
opm = 0;
npm = 0;
ppm = 0;
@@ -1461,6 +1493,15 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
"Read device characteristic failed, rc=%d", rc);
goto out_err3;
}
+
+ if ((device->features & DASD_FEATURE_USERAW) &&
+ !(private->rdc_data.facilities.RT_in_LR)) {
+ dev_err(&device->cdev->dev, "The storage server does not "
+ "support raw-track access\n");
+ rc = -EINVAL;
+ goto out_err3;
+ }
+
/* find the valid cylinder size */
if (private->rdc_data.no_cyl == LV_COMPAT_CYL &&
private->rdc_data.long_no_cyl)
@@ -2012,9 +2053,13 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
/* first of all check for state change pending interrupt */
mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
if ((scsw_dstat(&irb->scsw) & mask) == mask) {
- /* for alias only and not in offline processing*/
+ /*
+ * for alias only, not in offline processing
+ * and only if not suspended
+ */
if (!device->block && private->lcu &&
- !test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+ !test_bit(DASD_FLAG_OFFLINE, &device->flags) &&
+ !test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
/*
* the state change could be caused by an alias
* reassignment remove device from alias handling
@@ -2341,7 +2386,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
new_track = 1;
end_idaw = 0;
len_to_track_end = 0;
- idaw_dst = 0;
+ idaw_dst = NULL;
idaw_len = 0;
rq_for_each_segment(bv, req, iter) {
dst = page_address(bv->bv_page) + bv->bv_offset;
@@ -2403,7 +2448,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
if (end_idaw) {
idaws = idal_create_words(idaws, idaw_dst,
idaw_len);
- idaw_dst = 0;
+ idaw_dst = NULL;
idaw_len = 0;
end_idaw = 0;
}
@@ -3989,6 +4034,7 @@ static struct ccw_driver dasd_eckd_driver = {
.thaw = dasd_generic_restore_device,
.restore = dasd_generic_restore_device,
.uc_handler = dasd_generic_uc_handler,
+ .int_class = IOINT_DAS,
};
/*
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 77f778b..16c5208 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -21,7 +21,7 @@
#include <linux/slab.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/ebcdic.h>
#include "dasd_int.h"
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 4b71b11..a62a753 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -79,6 +79,7 @@ static struct ccw_driver dasd_fba_driver = {
.freeze = dasd_generic_pm_freeze,
.thaw = dasd_generic_restore_device,
.restore = dasd_generic_restore_device,
+ .int_class = IOINT_DAS,
};
static void
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1e4f2c..afe8c33 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -382,6 +382,41 @@ struct dasd_path {
__u8 npm;
};
+struct dasd_profile_info {
+ /* legacy part of profile data, as in dasd_profile_info_t */
+ unsigned int dasd_io_reqs; /* number of requests processed */
+ unsigned int dasd_io_sects; /* number of sectors processed */
+ unsigned int dasd_io_secs[32]; /* histogram of request's sizes */
+ unsigned int dasd_io_times[32]; /* histogram of requests's times */
+ unsigned int dasd_io_timps[32]; /* h. of requests's times per sector */
+ unsigned int dasd_io_time1[32]; /* hist. of time from build to start */
+ unsigned int dasd_io_time2[32]; /* hist. of time from start to irq */
+ unsigned int dasd_io_time2ps[32]; /* hist. of time from start to irq */
+ unsigned int dasd_io_time3[32]; /* hist. of time from irq to end */
+ unsigned int dasd_io_nr_req[32]; /* hist. of # of requests in chanq */
+
+ /* new data */
+ struct timespec starttod; /* time of start or last reset */
+ unsigned int dasd_io_alias; /* requests using an alias */
+ unsigned int dasd_io_tpm; /* requests using transport mode */
+ unsigned int dasd_read_reqs; /* total number of read requests */
+ unsigned int dasd_read_sects; /* total number read sectors */
+ unsigned int dasd_read_alias; /* read request using an alias */
+ unsigned int dasd_read_tpm; /* read requests in transport mode */
+ unsigned int dasd_read_secs[32]; /* histogram of request's sizes */
+ unsigned int dasd_read_times[32]; /* histogram of requests's times */
+ unsigned int dasd_read_time1[32]; /* hist. time from build to start */
+ unsigned int dasd_read_time2[32]; /* hist. of time from start to irq */
+ unsigned int dasd_read_time3[32]; /* hist. of time from irq to end */
+ unsigned int dasd_read_nr_req[32]; /* hist. of # of requests in chanq */
+};
+
+struct dasd_profile {
+ struct dentry *dentry;
+ struct dasd_profile_info *data;
+ spinlock_t lock;
+};
+
struct dasd_device {
/* Block device stuff. */
struct dasd_block *block;
@@ -431,6 +466,9 @@ struct dasd_device {
/* default expiration time in s */
unsigned long default_expires;
+
+ struct dentry *debugfs_dentry;
+ struct dasd_profile profile;
};
struct dasd_block {
@@ -453,9 +491,8 @@ struct dasd_block {
struct tasklet_struct tasklet;
struct timer_list timer;
-#ifdef CONFIG_DASD_PROFILE
- struct dasd_profile_info_t profile;
-#endif
+ struct dentry *debugfs_dentry;
+ struct dasd_profile profile;
};
@@ -479,6 +516,7 @@ struct dasd_block {
*/
#define DASD_FLAG_IS_RESERVED 7 /* The device is reserved */
#define DASD_FLAG_LOCK_STOLEN 8 /* The device lock was stolen */
+#define DASD_FLAG_SUSPENDED 9 /* The device was suspended */
void dasd_put_device_wake(struct dasd_device *);
@@ -589,12 +627,13 @@ dasd_check_blocksize(int bsize)
}
/* externals in dasd.c */
-#define DASD_PROFILE_ON 1
-#define DASD_PROFILE_OFF 0
+#define DASD_PROFILE_OFF 0
+#define DASD_PROFILE_ON 1
+#define DASD_PROFILE_GLOBAL_ONLY 2
extern debug_info_t *dasd_debug_area;
-extern struct dasd_profile_info_t dasd_global_profile;
-extern unsigned int dasd_profile_level;
+extern struct dasd_profile_info dasd_global_profile_data;
+extern unsigned int dasd_global_profile_level;
extern const struct block_device_operations dasd_device_operations;
extern struct kmem_cache *dasd_page_cache;
@@ -605,6 +644,7 @@ struct dasd_ccw_req *
dasd_smalloc_request(int , int, int, struct dasd_device *);
void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
+void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
static inline int
dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, struct dasd_device *device)
@@ -662,6 +702,11 @@ void dasd_device_remove_stop_bits(struct dasd_device *, int);
int dasd_device_is_ro(struct dasd_device *);
+void dasd_profile_reset(struct dasd_profile *);
+int dasd_profile_on(struct dasd_profile *);
+void dasd_profile_off(struct dasd_profile *);
+void dasd_global_profile_reset(void);
+char *dasd_get_user_string(const char __user *, size_t);
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 9caeaea5..792c69e 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -240,7 +240,7 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
*/
static int dasd_ioctl_reset_profile(struct dasd_block *block)
{
- memset(&block->profile, 0, sizeof(struct dasd_profile_info_t));
+ dasd_profile_reset(&block->profile);
return 0;
}
@@ -249,12 +249,46 @@ static int dasd_ioctl_reset_profile(struct dasd_block *block)
*/
static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
{
- if (dasd_profile_level == DASD_PROFILE_OFF)
- return -EIO;
- if (copy_to_user(argp, &block->profile,
- sizeof(struct dasd_profile_info_t)))
- return -EFAULT;
- return 0;
+ struct dasd_profile_info_t *data;
+ int rc = 0;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock_bh(&block->profile.lock);
+ if (block->profile.data) {
+ data->dasd_io_reqs = block->profile.data->dasd_io_reqs;
+ data->dasd_io_sects = block->profile.data->dasd_io_sects;
+ memcpy(data->dasd_io_secs, block->profile.data->dasd_io_secs,
+ sizeof(data->dasd_io_secs));
+ memcpy(data->dasd_io_times, block->profile.data->dasd_io_times,
+ sizeof(data->dasd_io_times));
+ memcpy(data->dasd_io_timps, block->profile.data->dasd_io_timps,
+ sizeof(data->dasd_io_timps));
+ memcpy(data->dasd_io_time1, block->profile.data->dasd_io_time1,
+ sizeof(data->dasd_io_time1));
+ memcpy(data->dasd_io_time2, block->profile.data->dasd_io_time2,
+ sizeof(data->dasd_io_time2));
+ memcpy(data->dasd_io_time2ps,
+ block->profile.data->dasd_io_time2ps,
+ sizeof(data->dasd_io_time2ps));
+ memcpy(data->dasd_io_time3, block->profile.data->dasd_io_time3,
+ sizeof(data->dasd_io_time3));
+ memcpy(data->dasd_io_nr_req,
+ block->profile.data->dasd_io_nr_req,
+ sizeof(data->dasd_io_nr_req));
+ spin_unlock_bh(&block->profile.lock);
+ } else {
+ spin_unlock_bh(&block->profile.lock);
+ rc = -EIO;
+ goto out;
+ }
+ if (copy_to_user(argp, data, sizeof(*data)))
+ rc = -EFAULT;
+out:
+ kfree(data);
+ return rc;
}
#else
static int dasd_ioctl_reset_profile(struct dasd_block *block)
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index c4a6a31..e12989f 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -32,28 +32,6 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
static struct proc_dir_entry *dasd_devices_entry = NULL;
static struct proc_dir_entry *dasd_statistics_entry = NULL;
-#ifdef CONFIG_DASD_PROFILE
-static char *
-dasd_get_user_string(const char __user *user_buf, size_t user_len)
-{
- char *buffer;
-
- buffer = kmalloc(user_len + 1, GFP_KERNEL);
- if (buffer == NULL)
- return ERR_PTR(-ENOMEM);
- if (copy_from_user(buffer, user_buf, user_len) != 0) {
- kfree(buffer);
- return ERR_PTR(-EFAULT);
- }
- /* got the string, now strip linefeed. */
- if (buffer[user_len - 1] == '\n')
- buffer[user_len - 1] = 0;
- else
- buffer[user_len] = 0;
- return buffer;
-}
-#endif /* CONFIG_DASD_PROFILE */
-
static int
dasd_devices_show(struct seq_file *m, void *v)
{
@@ -167,6 +145,55 @@ static const struct file_operations dasd_devices_file_ops = {
};
#ifdef CONFIG_DASD_PROFILE
+static int dasd_stats_all_block_on(void)
+{
+ int i, rc;
+ struct dasd_device *device;
+
+ rc = 0;
+ for (i = 0; i < dasd_max_devindex; ++i) {
+ device = dasd_device_from_devindex(i);
+ if (IS_ERR(device))
+ continue;
+ if (device->block)
+ rc = dasd_profile_on(&device->block->profile);
+ dasd_put_device(device);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+static void dasd_stats_all_block_off(void)
+{
+ int i;
+ struct dasd_device *device;
+
+ for (i = 0; i < dasd_max_devindex; ++i) {
+ device = dasd_device_from_devindex(i);
+ if (IS_ERR(device))
+ continue;
+ if (device->block)
+ dasd_profile_off(&device->block->profile);
+ dasd_put_device(device);
+ }
+}
+
+static void dasd_stats_all_block_reset(void)
+{
+ int i;
+ struct dasd_device *device;
+
+ for (i = 0; i < dasd_max_devindex; ++i) {
+ device = dasd_device_from_devindex(i);
+ if (IS_ERR(device))
+ continue;
+ if (device->block)
+ dasd_profile_reset(&device->block->profile);
+ dasd_put_device(device);
+ }
+}
+
static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor)
{
int i;
@@ -183,18 +210,18 @@ static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int f
static int dasd_stats_proc_show(struct seq_file *m, void *v)
{
#ifdef CONFIG_DASD_PROFILE
- struct dasd_profile_info_t *prof;
+ struct dasd_profile_info *prof;
int factor;
/* check for active profiling */
- if (dasd_profile_level == DASD_PROFILE_OFF) {
+ if (!dasd_global_profile_level) {
seq_printf(m, "Statistics are off - they might be "
"switched on using 'echo set on > "
"/proc/dasd/statistics'\n");
return 0;
}
+ prof = &dasd_global_profile_data;
- prof = &dasd_global_profile;
/* prevent counter 'overflow' on output */
for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
factor *= 10);
@@ -245,6 +272,7 @@ static ssize_t dasd_stats_proc_write(struct file *file,
{
#ifdef CONFIG_DASD_PROFILE
char *buffer, *str;
+ int rc;
if (user_len > 65536)
user_len = 65536;
@@ -259,32 +287,40 @@ static ssize_t dasd_stats_proc_write(struct file *file,
str = skip_spaces(str + 4);
if (strcmp(str, "on") == 0) {
/* switch on statistics profiling */
- dasd_profile_level = DASD_PROFILE_ON;
+ rc = dasd_stats_all_block_on();
+ if (rc) {
+ dasd_stats_all_block_off();
+ goto out_error;
+ }
+ dasd_global_profile_reset();
+ dasd_global_profile_level = DASD_PROFILE_ON;
pr_info("The statistics feature has been switched "
"on\n");
} else if (strcmp(str, "off") == 0) {
/* switch off and reset statistics profiling */
- memset(&dasd_global_profile,
- 0, sizeof (struct dasd_profile_info_t));
- dasd_profile_level = DASD_PROFILE_OFF;
+ dasd_global_profile_level = DASD_PROFILE_OFF;
+ dasd_global_profile_reset();
+ dasd_stats_all_block_off();
pr_info("The statistics feature has been switched "
"off\n");
} else
- goto out_error;
+ goto out_parse_error;
} else if (strncmp(str, "reset", 5) == 0) {
/* reset the statistics */
- memset(&dasd_global_profile, 0,
- sizeof (struct dasd_profile_info_t));
+ dasd_global_profile_reset();
+ dasd_stats_all_block_reset();
pr_info("The statistics have been reset\n");
} else
- goto out_error;
- kfree(buffer);
+ goto out_parse_error;
+ vfree(buffer);
return user_len;
-out_error:
+out_parse_error:
+ rc = -EINVAL;
pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
str);
- kfree(buffer);
- return -EINVAL;
+out_error:
+ vfree(buffer);
+ return rc;
#else
pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
return user_len;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 9b43ae9..a5a55da 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -27,7 +27,7 @@
static int dcssblk_open(struct block_device *bdev, fmode_t mode);
static int dcssblk_release(struct gendisk *disk, fmode_t mode);
-static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static void dcssblk_make_request(struct request_queue *q, struct bio *bio);
static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
void **kaddr, unsigned long *pfn);
@@ -814,7 +814,7 @@ out:
return rc;
}
-static int
+static void
dcssblk_make_request(struct request_queue *q, struct bio *bio)
{
struct dcssblk_dev_info *dev_info;
@@ -871,10 +871,9 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
bytes_done += bvec->bv_len;
}
bio_endio(bio, 0);
- return 0;
+ return;
fail:
bio_io_error(bio);
- return 0;
}
static int
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 1f6a4d8..98f3e4a 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -181,7 +181,7 @@ static unsigned long xpram_highest_page_index(void)
/*
* Block device make request function.
*/
-static int xpram_make_request(struct request_queue *q, struct bio *bio)
+static void xpram_make_request(struct request_queue *q, struct bio *bio)
{
xpram_device_t *xdev = bio->bi_bdev->bd_disk->private_data;
struct bio_vec *bvec;
@@ -221,10 +221,9 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio)
}
set_bit(BIO_UPTODATE, &bio->bi_flags);
bio_endio(bio, 0);
- return 0;
+ return;
fail:
bio_io_error(bio);
- return 0;
}
static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index a4f117d..2c9a776 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -116,9 +116,6 @@ config S390_TAPE
called tape390 and include all selected interfaces and
hardware drivers.
-comment "S/390 tape interface support"
- depends on S390_TAPE
-
comment "S/390 tape hardware support"
depends on S390_TAPE
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 694464c..2c8d79c 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -9,7 +9,6 @@
* Dan Morrison, IBM Corporation <dmorriso@cse.buffalo.edu>
*/
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
@@ -362,7 +361,6 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
int cstat, dstat;
int count;
- kstat_cpu(smp_processor_id()).irqs[IOINT_C15]++;
raw = dev_get_drvdata(&cdev->dev);
req = (struct raw3215_req *) intparm;
cstat = irb->scsw.cmd.cstat;
@@ -776,6 +774,7 @@ static struct ccw_driver raw3215_ccw_driver = {
.freeze = &raw3215_pm_stop,
.thaw = &raw3215_pm_start,
.restore = &raw3215_pm_start,
+ .int_class = IOINT_C15,
};
#ifdef CONFIG_TN3215_CONSOLE
@@ -994,12 +993,26 @@ static int tty3215_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
struct raw3215_info *raw;
+ int i, written;
if (!tty)
return 0;
raw = (struct raw3215_info *) tty->driver_data;
- raw3215_write(raw, buf, count);
- return count;
+ written = count;
+ while (count > 0) {
+ for (i = 0; i < count; i++)
+ if (buf[i] == '\t' || buf[i] == '\n')
+ break;
+ raw3215_write(raw, buf, i);
+ count -= i;
+ buf += i;
+ if (count > 0) {
+ raw3215_putchar(raw, *buf);
+ count--;
+ buf++;
+ }
+ }
+ return written;
}
/*
@@ -1147,7 +1160,7 @@ static int __init tty3215_init(void)
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
- driver->init_termios.c_oflag = ONLCR | XTABS;
+ driver->init_termios.c_oflag = ONLCR;
driver->init_termios.c_lflag = ISIG;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &tty3215_ops);
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 2150824..9117045 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -11,10 +11,11 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/compat.h>
+#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/types.h>
-#include <linux/compat.h>
#include <asm/compat.h>
#include <asm/ccwdev.h>
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 810ac38..e5cb924 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -7,7 +7,6 @@
* Copyright IBM Corp. 2003, 2009
*/
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -330,7 +329,6 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
struct raw3270_request *rq;
int rc;
- kstat_cpu(smp_processor_id()).irqs[IOINT_C70]++;
rp = dev_get_drvdata(&cdev->dev);
if (!rp)
return;
@@ -1398,6 +1396,7 @@ static struct ccw_driver raw3270_ccw_driver = {
.freeze = &raw3270_pm_stop,
.thaw = &raw3270_pm_start,
.restore = &raw3270_pm_start,
+ .int_class = IOINT_C70,
};
static int
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
index 7ad30e7..5f9f929 100644
--- a/drivers/s390/char/sclp_async.c
+++ b/drivers/s390/char/sclp_async.c
@@ -82,12 +82,9 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write,
return -EFAULT;
} else {
len = *count;
- rc = copy_from_user(buf, buffer, sizeof(buf));
- if (rc != 0)
- return -EFAULT;
- buf[sizeof(buf) - 1] = '\0';
- if (strict_strtoul(buf, 0, &val) != 0)
- return -EINVAL;
+ rc = kstrtoul_from_user(buffer, len, 0, &val);
+ if (rc)
+ return rc;
if (val != 0 && val != 1)
return -EINVAL;
callhome_enabled = val;
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index a0ce2a9..a56a15e 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -61,8 +61,8 @@ static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
rc = sclp_service_call(cmd, sccb);
if (rc)
goto out;
- __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
- PSW_MASK_WAIT | PSW_DEFAULT_KEY);
+ __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA |
+ PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT);
local_irq_disable();
out:
/* Contents of the sccb might have changed. */
@@ -383,8 +383,10 @@ static int sclp_attach_storage(u8 id)
switch (sccb->header.response_code) {
case 0x0020:
set_bit(id, sclp_storage_ids);
- for (i = 0; i < sccb->assigned; i++)
- sclp_unassign_storage(sccb->entries[i] >> 16);
+ for (i = 0; i < sccb->assigned; i++) {
+ if (sccb->entries[i])
+ sclp_unassign_storage(sccb->entries[i] >> 16);
+ }
break;
default:
rc = -EIO;
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c
index 4a51e3f..bd1b9c9 100644
--- a/drivers/s390/char/sclp_cpi_sys.c
+++ b/drivers/s390/char/sclp_cpi_sys.c
@@ -21,6 +21,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/completion.h>
+#include <linux/export.h>
#include <asm/ebcdic.h>
#include <asm/sclp.h>
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 05909a7..87fc0ac 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -13,7 +13,7 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/reboot.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/ptrace.h>
#include <asm/sigp.h>
#include <asm/smp.h>
@@ -30,7 +30,8 @@ static void do_machine_quiesce(void)
psw_t quiesce_psw;
smp_send_stop();
- quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+ quiesce_psw.mask =
+ PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_WAIT;
quiesce_psw.addr = 0xfff;
__load_psw(quiesce_psw);
}
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 9eff2df..934ef33 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1330,6 +1330,7 @@ static struct ccw_driver tape_34xx_driver = {
.set_online = tape_34xx_online,
.set_offline = tape_generic_offline,
.freeze = tape_generic_pm_suspend,
+ .int_class = IOINT_TAP,
};
static int
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index a7d5707..49c6aab 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1762,6 +1762,7 @@ static struct ccw_driver tape_3590_driver = {
.set_offline = tape_generic_offline,
.set_online = tape_3590_online,
.freeze = tape_generic_pm_suspend,
+ .int_class = IOINT_TAP,
};
/*
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 7978a0a..b3a3e8e 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -14,7 +14,6 @@
#define KMSG_COMPONENT "tape"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/init.h> // for kernel parameters
#include <linux/kmod.h> // for requesting modules
@@ -1115,7 +1114,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
struct tape_request *request;
int rc;
- kstat_cpu(smp_processor_id()).irqs[IOINT_TAP]++;
device = dev_get_drvdata(&cdev->dev);
if (device == NULL) {
return;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 84e569c..89c03e6 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <asm/compat.h>
#include <asm/cpcmd.h>
#include <asm/debug.h>
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index c837d74..524d988 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -21,7 +21,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <asm/cpcmd.h>
#include <asm/debug.h>
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index f6b00c3..85f4a9a 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -11,9 +11,9 @@
#define KMSG_COMPONENT "vmur"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/cdev.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/cio.h>
@@ -74,6 +74,7 @@ static struct ccw_driver ur_driver = {
.set_online = ur_set_online,
.set_offline = ur_set_offline,
.freeze = ur_pm_suspend,
+ .int_class = IOINT_VMR,
};
static DEFINE_MUTEX(vmur_mutex);
@@ -305,7 +306,6 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
{
struct urdev *urd;
- kstat_cpu(smp_processor_id()).irqs[IOINT_VMR]++;
TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
irb->scsw.cmd.count);
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 12ef912..11312f4 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -258,13 +258,13 @@ static int vmwdt_suspend(void)
if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) {
pr_err("The system cannot be suspended while the watchdog"
" is in use\n");
- return NOTIFY_BAD;
+ return notifier_from_errno(-EBUSY);
}
if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) {
clear_bit(VMWDT_OPEN, &vmwdt_is_open);
pr_err("The system cannot be suspended while the watchdog"
" is running\n");
- return NOTIFY_BAD;
+ return notifier_from_errno(-EBUSY);
}
return NOTIFY_DONE;
}
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 3b94044..1b6d924 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/debugfs.h>
+#include <linux/module.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h>
#include <asm/sclp.h>
@@ -142,22 +143,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
return memcpy_hsa(dest, src, count, TO_KERNEL);
}
-static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
-{
- static char buf[4096];
- int offs = 0, size;
-
- while (offs < count) {
- size = min(sizeof(buf), count - offs);
- if (memcpy_real(buf, (void *) src + offs, size))
- return -EFAULT;
- if (copy_to_user(dest + offs, buf, size))
- return -EFAULT;
- offs += size;
- }
- return 0;
-}
-
static int __init init_cpu_info(enum arch_id arch)
{
struct save_area *sa;
@@ -346,8 +331,8 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
/* Copy from real mem */
size = count - mem_offs - hdr_count;
- rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
- size);
+ rc = copy_to_user_real(buf + hdr_count + mem_offs,
+ (void *) mem_start + mem_offs, size);
if (rc)
goto fail;
@@ -656,6 +641,8 @@ static int __init zcore_init(void)
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
return -ENODATA;
+ if (OLDMEM_BASE)
+ return -ENODATA;
zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));
debug_register_view(zcore_dbf, &debug_sprintf_view);
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 76058a5..08c6603 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -335,10 +335,9 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
return -EINVAL;
if (user_len > 65536)
user_len = 65536;
- buf = vmalloc (user_len + 1); /* maybe better use the stack? */
+ buf = vzalloc(user_len + 1); /* maybe better use the stack? */
if (buf == NULL)
return -ENOMEM;
- memset(buf, 0, user_len + 1);
if (strncpy_from_user (buf, user_buf, user_len) < 0) {
rc = -EFAULT;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index cda9bd6..4f1989d 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -29,31 +29,20 @@
/* a device matches a driver if all its slave devices match the same
* entry of the driver */
-static int
-ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
+static int ccwgroup_bus_match(struct device *dev, struct device_driver * drv)
{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(drv);
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(drv);
if (gdev->creator_id == gdrv->driver_id)
return 1;
return 0;
}
-static int
-ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env)
-{
- /* TODO */
- return 0;
-}
static struct bus_type ccwgroup_bus_type;
-static void
-__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
+static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
{
int i;
char str[8];
@@ -63,7 +52,6 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
sysfs_remove_link(&gdev->dev.kobj, str);
sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device");
}
-
}
/*
@@ -87,12 +75,87 @@ static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
}
}
+static int ccwgroup_set_online(struct ccwgroup_device *gdev)
+{
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+ int ret = 0;
+
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
+ return -EAGAIN;
+ if (gdev->state == CCWGROUP_ONLINE)
+ goto out;
+ if (gdrv->set_online)
+ ret = gdrv->set_online(gdev);
+ if (ret)
+ goto out;
+
+ gdev->state = CCWGROUP_ONLINE;
+out:
+ atomic_set(&gdev->onoff, 0);
+ return ret;
+}
+
+static int ccwgroup_set_offline(struct ccwgroup_device *gdev)
+{
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+ int ret = 0;
+
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
+ return -EAGAIN;
+ if (gdev->state == CCWGROUP_OFFLINE)
+ goto out;
+ if (gdrv->set_offline)
+ ret = gdrv->set_offline(gdev);
+ if (ret)
+ goto out;
+
+ gdev->state = CCWGROUP_OFFLINE;
+out:
+ atomic_set(&gdev->onoff, 0);
+ return ret;
+}
+
static ssize_t ccwgroup_online_store(struct device *dev,
struct device_attribute *attr,
- const char *buf, size_t count);
+ const char *buf, size_t count)
+{
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
+ unsigned long value;
+ int ret;
+
+ if (!dev->driver)
+ return -EINVAL;
+ if (!try_module_get(gdrv->driver.owner))
+ return -EINVAL;
+
+ ret = strict_strtoul(buf, 0, &value);
+ if (ret)
+ goto out;
+
+ if (value == 1)
+ ret = ccwgroup_set_online(gdev);
+ else if (value == 0)
+ ret = ccwgroup_set_offline(gdev);
+ else
+ ret = -EINVAL;
+out:
+ module_put(gdrv->driver.owner);
+ return (ret == 0) ? count : ret;
+}
+
static ssize_t ccwgroup_online_show(struct device *dev,
struct device_attribute *attr,
- char *buf);
+ char *buf)
+{
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ int online;
+
+ online = (gdev->state == CCWGROUP_ONLINE) ? 1 : 0;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", online);
+}
+
/*
* Provide an 'ungroup' attribute so the user can remove group devices no
* longer needed or accidentially created. Saves memory :)
@@ -110,14 +173,13 @@ static void ccwgroup_ungroup_callback(struct device *dev)
mutex_unlock(&gdev->reg_mutex);
}
-static ssize_t
-ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t ccwgroup_ungroup_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct ccwgroup_device *gdev;
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
int rc;
- gdev = to_ccwgroupdev(dev);
-
/* Prevent concurrent online/offline processing and ungrouping. */
if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
return -EAGAIN;
@@ -138,7 +200,6 @@ out:
}
return count;
}
-
static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store);
static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
@@ -155,21 +216,19 @@ static const struct attribute_group *ccwgroup_attr_groups[] = {
NULL,
};
-static void
-ccwgroup_release (struct device *dev)
+static void ccwgroup_release(struct device *dev)
{
kfree(to_ccwgroupdev(dev));
}
-static int
-__ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
+static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
{
char str[8];
int i, rc;
for (i = 0; i < gdev->count; i++) {
- rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj, &gdev->dev.kobj,
- "group_device");
+ rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj,
+ &gdev->dev.kobj, "group_device");
if (rc) {
for (--i; i >= 0; i--)
sysfs_remove_link(&gdev->cdev[i]->dev.kobj,
@@ -179,8 +238,8 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
}
for (i = 0; i < gdev->count; i++) {
sprintf(str, "cdev%d", i);
- rc = sysfs_create_link(&gdev->dev.kobj, &gdev->cdev[i]->dev.kobj,
- str);
+ rc = sysfs_create_link(&gdev->dev.kobj,
+ &gdev->cdev[i]->dev.kobj, str);
if (rc) {
for (--i; i >= 0; i--) {
sprintf(str, "cdev%d", i);
@@ -317,14 +376,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
rc = device_add(&gdev->dev);
if (rc)
goto error;
- get_device(&gdev->dev);
rc = __ccwgroup_create_symlinks(gdev);
- if (!rc) {
- mutex_unlock(&gdev->reg_mutex);
- put_device(&gdev->dev);
- return 0;
+ if (rc) {
+ device_del(&gdev->dev);
+ goto error;
}
- device_unregister(&gdev->dev);
+ mutex_unlock(&gdev->reg_mutex);
+ return 0;
error:
for (i = 0; i < num_devices; i++)
if (gdev->cdev[i]) {
@@ -342,7 +400,15 @@ error:
EXPORT_SYMBOL(ccwgroup_create_from_string);
static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
- void *data);
+ void *data)
+{
+ struct device *dev = data;
+
+ if (action == BUS_NOTIFY_UNBIND_DRIVER)
+ device_schedule_callback(dev, ccwgroup_ungroup_callback);
+
+ return NOTIFY_OK;
+}
static struct notifier_block ccwgroup_nb = {
.notifier_call = ccwgroup_notifier
@@ -374,128 +440,21 @@ module_exit(cleanup_ccwgroup);
/************************** driver stuff ******************************/
-static int
-ccwgroup_set_online(struct ccwgroup_device *gdev)
-{
- struct ccwgroup_driver *gdrv;
- int ret;
-
- if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
- return -EAGAIN;
- if (gdev->state == CCWGROUP_ONLINE) {
- ret = 0;
- goto out;
- }
- if (!gdev->dev.driver) {
- ret = -EINVAL;
- goto out;
- }
- gdrv = to_ccwgroupdrv (gdev->dev.driver);
- if ((ret = gdrv->set_online ? gdrv->set_online(gdev) : 0))
- goto out;
-
- gdev->state = CCWGROUP_ONLINE;
- out:
- atomic_set(&gdev->onoff, 0);
- return ret;
-}
-
-static int
-ccwgroup_set_offline(struct ccwgroup_device *gdev)
-{
- struct ccwgroup_driver *gdrv;
- int ret;
-
- if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
- return -EAGAIN;
- if (gdev->state == CCWGROUP_OFFLINE) {
- ret = 0;
- goto out;
- }
- if (!gdev->dev.driver) {
- ret = -EINVAL;
- goto out;
- }
- gdrv = to_ccwgroupdrv (gdev->dev.driver);
- if ((ret = gdrv->set_offline ? gdrv->set_offline(gdev) : 0))
- goto out;
-
- gdev->state = CCWGROUP_OFFLINE;
- out:
- atomic_set(&gdev->onoff, 0);
- return ret;
-}
-
-static ssize_t
-ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
- unsigned long value;
- int ret;
-
- if (!dev->driver)
- return -EINVAL;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
- if (!try_module_get(gdrv->driver.owner))
- return -EINVAL;
-
- ret = strict_strtoul(buf, 0, &value);
- if (ret)
- goto out;
-
- if (value == 1)
- ret = ccwgroup_set_online(gdev);
- else if (value == 0)
- ret = ccwgroup_set_offline(gdev);
- else
- ret = -EINVAL;
-out:
- module_put(gdrv->driver.owner);
- return (ret == 0) ? count : ret;
-}
-
-static ssize_t
-ccwgroup_online_show (struct device *dev, struct device_attribute *attr, char *buf)
+static int ccwgroup_probe(struct device *dev)
{
- int online;
-
- online = (to_ccwgroupdev(dev)->state == CCWGROUP_ONLINE);
-
- return sprintf(buf, online ? "1\n" : "0\n");
-}
-
-static int
-ccwgroup_probe (struct device *dev)
-{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
-
- int ret;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
- ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
- return ret;
+ return gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
}
-static int
-ccwgroup_remove (struct device *dev)
+static int ccwgroup_remove(struct device *dev)
{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
if (!dev->driver)
return 0;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
if (gdrv->remove)
gdrv->remove(gdev);
@@ -504,15 +463,11 @@ ccwgroup_remove (struct device *dev)
static void ccwgroup_shutdown(struct device *dev)
{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
if (!dev->driver)
return;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
if (gdrv->shutdown)
gdrv->shutdown(gdev);
}
@@ -588,26 +543,12 @@ static const struct dev_pm_ops ccwgroup_pm_ops = {
static struct bus_type ccwgroup_bus_type = {
.name = "ccwgroup",
.match = ccwgroup_bus_match,
- .uevent = ccwgroup_uevent,
.probe = ccwgroup_probe,
.remove = ccwgroup_remove,
.shutdown = ccwgroup_shutdown,
.pm = &ccwgroup_pm_ops,
};
-
-static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
- void *data)
-{
- struct device *dev = data;
-
- if (action == BUS_NOTIFY_UNBIND_DRIVER)
- device_schedule_callback(dev, ccwgroup_ungroup_callback);
-
- return NOTIFY_OK;
-}
-
-
/**
* ccwgroup_driver_register() - register a ccw group driver
* @cdriver: driver to be registered
@@ -621,9 +562,9 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
return driver_register(&cdriver->driver);
}
+EXPORT_SYMBOL(ccwgroup_driver_register);
-static int
-__ccwgroup_match_all(struct device *dev, void *data)
+static int __ccwgroup_match_all(struct device *dev, void *data)
{
return 1;
}
@@ -654,6 +595,7 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver)
put_driver(&cdriver->driver);
driver_unregister(&cdriver->driver);
}
+EXPORT_SYMBOL(ccwgroup_driver_unregister);
/**
* ccwgroup_probe_ccwdev() - probe function for slave devices
@@ -668,6 +610,7 @@ int ccwgroup_probe_ccwdev(struct ccw_device *cdev)
{
return 0;
}
+EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
/**
* ccwgroup_remove_ccwdev() - remove function for slave devices
@@ -704,9 +647,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
/* Release ccwgroup device reference for local processing. */
put_device(&gdev->dev);
}
-
-MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(ccwgroup_driver_register);
-EXPORT_SYMBOL(ccwgroup_driver_unregister);
-EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c
index d15f8b4..5156264 100644
--- a/drivers/s390/cio/ccwreq.c
+++ b/drivers/s390/cio/ccwreq.c
@@ -1,10 +1,13 @@
/*
* Handling of internal CCW device requests.
*
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2009, 2011
* Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
*/
+#define KMSG_COMPONENT "cio"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/types.h>
#include <linux/err.h>
#include <asm/ccwdev.h>
@@ -323,7 +326,21 @@ void ccw_request_timeout(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_request *req = &cdev->private->req;
- int rc;
+ int rc = -ENODEV, chp;
+
+ if (cio_update_schib(sch))
+ goto err;
+
+ for (chp = 0; chp < 8; chp++) {
+ if ((0x80 >> chp) & sch->schib.pmcw.lpum)
+ pr_warning("%s: No interrupt was received within %lus "
+ "(CS=%02x, DS=%02x, CHPID=%x.%02x)\n",
+ dev_name(&cdev->dev), req->timeout / HZ,
+ scsw_cstat(&sch->schib.scsw),
+ scsw_dstat(&sch->schib.scsw),
+ sch->schid.cssid,
+ sch->schib.pmcw.chpid[chp]);
+ }
if (!ccwreq_next_path(cdev)) {
/* set the final return code for this request */
@@ -342,7 +359,7 @@ err:
* ccw_request_notoper - notoper handler for I/O request procedure
* @cdev: ccw device
*
- * Handle timeout during I/O request procedure.
+ * Handle notoper during I/O request procedure.
*/
void ccw_request_notoper(struct ccw_device *cdev)
{
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 2d32233..e792436 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -10,6 +10,8 @@
#include <linux/bug.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
+#include <linux/export.h>
+#include <linux/sched.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/wait.h>
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 75c3f1f..a84631a 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -529,10 +529,7 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
int chsc_chp_vary(struct chp_id chpid, int on)
{
struct channel_path *chp = chpid_to_chp(chpid);
- struct chp_link link;
- memset(&link, 0, sizeof(struct chp_link));
- link.chpid = chpid;
/* Wait until previous actions have settled. */
css_wait_for_slow_path();
/*
@@ -542,10 +539,10 @@ int chsc_chp_vary(struct chp_id chpid, int on)
/* Try to update the channel path descritor. */
chsc_determine_base_channel_path_desc(chpid, &chp->desc);
for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
- __s390_vary_chpid_on, &link);
+ __s390_vary_chpid_on, &chpid);
} else
for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
- NULL, &link);
+ NULL, &chpid);
return 0;
}
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index ec76029..8f9a1a3 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -1,7 +1,7 @@
/*
* Driver for s390 chsc subchannels
*
- * Copyright IBM Corp. 2008, 2009
+ * Copyright IBM Corp. 2008, 2011
*
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
*
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
+#include <linux/kernel_stat.h>
#include <asm/compat.h>
#include <asm/cio.h>
@@ -57,6 +58,8 @@ static void chsc_subchannel_irq(struct subchannel *sch)
CHSC_LOG(4, "irb");
CHSC_LOG_HEX(4, irb, sizeof(*irb));
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++;
+
/* Copy irb to provided request and set done. */
if (!request) {
CHSC_MSG(0, "Interrupt on sch 0.%x.%04x with no request\n",
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index cbde448..dc67c39 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -622,6 +622,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
if (!sch) {
/* Clear pending interrupt condition. */
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
tsch(tpi_info->schid, irb);
continue;
}
@@ -634,7 +635,10 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
/* Call interrupt handler if there is one. */
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
- }
+ else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+ } else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
spin_unlock(sch->lock);
/*
* Are more interrupts pending?
@@ -654,8 +658,8 @@ static struct io_subchannel_private console_priv;
static int console_subchannel_in_use;
/*
- * Use tpi to get a pending interrupt, call the interrupt handler and
- * return a pointer to the subchannel structure.
+ * Use cio_tpi to get a pending interrupt and call the interrupt handler.
+ * Return non-zero if an interrupt was processed, zero otherwise.
*/
static int cio_tpi(void)
{
@@ -667,14 +671,23 @@ static int cio_tpi(void)
tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
if (tpi(NULL) != 1)
return 0;
+ kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
+ if (tpi_info->adapter_IO) {
+ do_adapter_IO(tpi_info->isc);
+ return 1;
+ }
irb = (struct irb *)&S390_lowcore.irb;
/* Store interrupt response block to lowcore. */
- if (tsch(tpi_info->schid, irb) != 0)
+ if (tsch(tpi_info->schid, irb) != 0) {
/* Not status pending or not operational. */
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
return 1;
+ }
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
- if (!sch)
+ if (!sch) {
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
return 1;
+ }
irq_context = in_interrupt();
if (!irq_context)
local_bh_disable();
@@ -683,6 +696,8 @@ static int cio_tpi(void)
memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
+ else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
spin_unlock(sch->lock);
irq_exit();
if (!irq_context)
@@ -1054,7 +1069,7 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
{
struct subchannel_id schid;
- s390_reset_system();
+ s390_reset_system(NULL, NULL);
if (reipl_find_schid(devid, &schid) != 0)
panic("IPL Device not found\n");
do_reipl_asm(*((__u32*)&schid));
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 155a82b..4a1ff5c 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -68,8 +68,13 @@ struct schib {
__u8 mda[4]; /* model dependent area */
} __attribute__ ((packed,aligned(4)));
+/*
+ * When rescheduled, todo's with higher values will overwrite those
+ * with lower values.
+ */
enum sch_todo {
SCH_TODO_NOTHING,
+ SCH_TODO_EVAL,
SCH_TODO_UNREG,
};
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c47b25f..21908e6 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -195,51 +195,6 @@ void css_sch_device_unregister(struct subchannel *sch)
}
EXPORT_SYMBOL_GPL(css_sch_device_unregister);
-static void css_sch_todo(struct work_struct *work)
-{
- struct subchannel *sch;
- enum sch_todo todo;
-
- sch = container_of(work, struct subchannel, todo_work);
- /* Find out todo. */
- spin_lock_irq(sch->lock);
- todo = sch->todo;
- CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid,
- sch->schid.sch_no, todo);
- sch->todo = SCH_TODO_NOTHING;
- spin_unlock_irq(sch->lock);
- /* Perform todo. */
- if (todo == SCH_TODO_UNREG)
- css_sch_device_unregister(sch);
- /* Release workqueue ref. */
- put_device(&sch->dev);
-}
-
-/**
- * css_sched_sch_todo - schedule a subchannel operation
- * @sch: subchannel
- * @todo: todo
- *
- * Schedule the operation identified by @todo to be performed on the slow path
- * workqueue. Do nothing if another operation with higher priority is already
- * scheduled. Needs to be called with subchannel lock held.
- */
-void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo)
-{
- CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n",
- sch->schid.ssid, sch->schid.sch_no, todo);
- if (sch->todo >= todo)
- return;
- /* Get workqueue ref. */
- if (!get_device(&sch->dev))
- return;
- sch->todo = todo;
- if (!queue_work(cio_work_q, &sch->todo_work)) {
- /* Already queued, release workqueue ref. */
- put_device(&sch->dev);
- }
-}
-
static void ssd_from_pmcw(struct chsc_ssd_info *ssd, struct pmcw *pmcw)
{
int i;
@@ -466,6 +421,65 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow)
css_schedule_eval(schid);
}
+/**
+ * css_sched_sch_todo - schedule a subchannel operation
+ * @sch: subchannel
+ * @todo: todo
+ *
+ * Schedule the operation identified by @todo to be performed on the slow path
+ * workqueue. Do nothing if another operation with higher priority is already
+ * scheduled. Needs to be called with subchannel lock held.
+ */
+void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo)
+{
+ CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n",
+ sch->schid.ssid, sch->schid.sch_no, todo);
+ if (sch->todo >= todo)
+ return;
+ /* Get workqueue ref. */
+ if (!get_device(&sch->dev))
+ return;
+ sch->todo = todo;
+ if (!queue_work(cio_work_q, &sch->todo_work)) {
+ /* Already queued, release workqueue ref. */
+ put_device(&sch->dev);
+ }
+}
+
+static void css_sch_todo(struct work_struct *work)
+{
+ struct subchannel *sch;
+ enum sch_todo todo;
+ int ret;
+
+ sch = container_of(work, struct subchannel, todo_work);
+ /* Find out todo. */
+ spin_lock_irq(sch->lock);
+ todo = sch->todo;
+ CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid,
+ sch->schid.sch_no, todo);
+ sch->todo = SCH_TODO_NOTHING;
+ spin_unlock_irq(sch->lock);
+ /* Perform todo. */
+ switch (todo) {
+ case SCH_TODO_NOTHING:
+ break;
+ case SCH_TODO_EVAL:
+ ret = css_evaluate_known_subchannel(sch, 1);
+ if (ret == -EAGAIN) {
+ spin_lock_irq(sch->lock);
+ css_sched_sch_todo(sch, todo);
+ spin_unlock_irq(sch->lock);
+ }
+ break;
+ case SCH_TODO_UNREG:
+ css_sch_device_unregister(sch);
+ break;
+ }
+ /* Release workqueue ref. */
+ put_device(&sch->dev);
+}
+
static struct idset *slow_subchannel_set;
static spinlock_t slow_subchannel_lock;
static wait_queue_head_t css_eval_wq;
@@ -814,8 +828,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
mutex_unlock(&css->mutex);
continue;
}
- if (__chsc_do_secm(css, 0))
- ret = NOTIFY_BAD;
+ ret = __chsc_do_secm(css, 0);
+ ret = notifier_from_errno(ret);
mutex_unlock(&css->mutex);
}
break;
@@ -831,8 +845,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
mutex_unlock(&css->mutex);
continue;
}
- if (__chsc_do_secm(css, 1))
- ret = NOTIFY_BAD;
+ ret = __chsc_do_secm(css, 1);
+ ret = notifier_from_errno(ret);
mutex_unlock(&css->mutex);
}
/* search for subchannels, which appeared during hibernation */
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 80ebddd..33bb4d8 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -133,6 +133,8 @@ struct channel_subsystem {
extern struct channel_subsystem *channel_subsystems[];
+void channel_subsystem_reinit(void);
+
/* Helper functions to build lists for the slow path. */
void css_schedule_eval(struct subchannel_id schid);
void css_schedule_eval_all(void);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 8e04c00..4726985 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -21,6 +21,7 @@
#include <linux/device.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
+#include <linux/kernel_stat.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -747,6 +748,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
struct ccw_device *cdev)
{
cdev->private->cdev = cdev;
+ cdev->private->int_class = IOINT_CIO;
atomic_set(&cdev->private->onoff, 0);
cdev->dev.parent = &sch->dev;
cdev->dev.release = ccw_device_release;
@@ -1010,6 +1012,8 @@ static void io_subchannel_irq(struct subchannel *sch)
CIO_TRACE_EVENT(6, dev_name(&sch->dev));
if (cdev)
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
+ else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
}
void io_subchannel_init_config(struct subchannel *sch)
@@ -1621,6 +1625,7 @@ ccw_device_probe_console(void)
memset(&console_private, 0, sizeof(struct ccw_device_private));
console_cdev.private = &console_private;
console_private.cdev = &console_cdev;
+ console_private.int_class = IOINT_CIO;
ret = ccw_device_console_enable(&console_cdev, sch);
if (ret) {
cio_release_console();
@@ -1702,11 +1707,18 @@ ccw_device_probe (struct device *dev)
int ret;
cdev->drv = cdrv; /* to let the driver call _set_online */
+ /* Note: we interpret class 0 in this context as an uninitialized
+ * field since it translates to a non-I/O interrupt class. */
+ if (cdrv->int_class != 0)
+ cdev->private->int_class = cdrv->int_class;
+ else
+ cdev->private->int_class = IOINT_CIO;
ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
if (ret) {
cdev->drv = NULL;
+ cdev->private->int_class = IOINT_CIO;
return ret;
}
@@ -1740,6 +1752,7 @@ ccw_device_remove (struct device *dev)
}
ccw_device_set_timeout(cdev, 0);
cdev->drv = NULL;
+ cdev->private->int_class = IOINT_CIO;
return 0;
}
@@ -1855,9 +1868,9 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev)
*/
cdev->private->flags.resuming = 1;
cdev->private->path_new_mask = LPM_ANYPATH;
- css_schedule_eval(sch->schid);
+ css_sched_sch_todo(sch, SCH_TODO_EVAL);
spin_unlock_irq(sch->lock);
- css_complete_work();
+ css_wait_for_slow_path();
/* cdev may have been moved to a different subchannel. */
sch = to_subchannel(cdev->dev.parent);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 7e297c7..179824b 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -2,9 +2,10 @@
#define S390_DEVICE_H
#include <asm/ccwdev.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/wait.h>
#include <linux/notifier.h>
+#include <linux/kernel_stat.h>
#include "io_sch.h"
/*
@@ -56,7 +57,17 @@ extern fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS];
static inline void
dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event)
{
- dev_jumptable[cdev->private->state][dev_event](cdev, dev_event);
+ int state = cdev->private->state;
+
+ if (dev_event == DEV_EVENT_INTERRUPT) {
+ if (state == DEV_STATE_ONLINE)
+ kstat_cpu(smp_processor_id()).
+ irqs[cdev->private->int_class]++;
+ else if (state != DEV_STATE_CMFCHANGE &&
+ state != DEV_STATE_CMFUPDATE)
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+ }
+ dev_jumptable[state][dev_event](cdev, dev_event);
}
/*
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 52c233f..1b85351 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -496,8 +496,26 @@ static void ccw_device_reset_path_events(struct ccw_device *cdev)
cdev->private->pgid_reset_mask = 0;
}
-void
-ccw_device_verify_done(struct ccw_device *cdev, int err)
+static void create_fake_irb(struct irb *irb, int type)
+{
+ memset(irb, 0, sizeof(*irb));
+ if (type == FAKE_CMD_IRB) {
+ struct cmd_scsw *scsw = &irb->scsw.cmd;
+ scsw->cc = 1;
+ scsw->fctl = SCSW_FCTL_START_FUNC;
+ scsw->actl = SCSW_ACTL_START_PEND;
+ scsw->stctl = SCSW_STCTL_STATUS_PEND;
+ } else if (type == FAKE_TM_IRB) {
+ struct tm_scsw *scsw = &irb->scsw.tm;
+ scsw->x = 1;
+ scsw->cc = 1;
+ scsw->fctl = SCSW_FCTL_START_FUNC;
+ scsw->actl = SCSW_ACTL_START_PEND;
+ scsw->stctl = SCSW_STCTL_STATUS_PEND;
+ }
+}
+
+void ccw_device_verify_done(struct ccw_device *cdev, int err)
{
struct subchannel *sch;
@@ -520,12 +538,8 @@ callback:
ccw_device_done(cdev, DEV_STATE_ONLINE);
/* Deliver fake irb to device driver, if needed. */
if (cdev->private->flags.fake_irb) {
- memset(&cdev->private->irb, 0, sizeof(struct irb));
- cdev->private->irb.scsw.cmd.cc = 1;
- cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC;
- cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND;
- cdev->private->irb.scsw.cmd.stctl =
- SCSW_STCTL_STATUS_PEND;
+ create_fake_irb(&cdev->private->irb,
+ cdev->private->flags.fake_irb);
cdev->private->flags.fake_irb = 0;
if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index f98698d..ec7fb6d 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -198,7 +198,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
if (cdev->private->state == DEV_STATE_VERIFY) {
/* Remember to fake irb when finished. */
if (!cdev->private->flags.fake_irb) {
- cdev->private->flags.fake_irb = 1;
+ cdev->private->flags.fake_irb = FAKE_CMD_IRB;
cdev->private->intparm = intparm;
return 0;
} else
@@ -213,9 +213,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
ret = cio_set_options (sch, flags);
if (ret)
return ret;
- /* Adjust requested path mask to excluded varied off paths. */
+ /* Adjust requested path mask to exclude unusable paths. */
if (lpm) {
- lpm &= sch->opm;
+ lpm &= sch->lpm;
if (lpm == 0)
return -EACCES;
}
@@ -605,11 +605,21 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
sch = to_subchannel(cdev->dev.parent);
if (!sch->schib.pmcw.ena)
return -EINVAL;
+ if (cdev->private->state == DEV_STATE_VERIFY) {
+ /* Remember to fake irb when finished. */
+ if (!cdev->private->flags.fake_irb) {
+ cdev->private->flags.fake_irb = FAKE_TM_IRB;
+ cdev->private->intparm = intparm;
+ return 0;
+ } else
+ /* There's already a fake I/O around. */
+ return -EBUSY;
+ }
if (cdev->private->state != DEV_STATE_ONLINE)
return -EIO;
- /* Adjust requested path mask to excluded varied off paths. */
+ /* Adjust requested path mask to exclude unusable paths. */
if (lpm) {
- lpm &= sch->opm;
+ lpm &= sch->lpm;
if (lpm == 0)
return -EACCES;
}
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index ba31ad8..76253df 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <asm/schid.h>
#include <asm/ccwdev.h>
+#include <asm/irq.h>
#include "css.h"
#include "orb.h"
@@ -110,6 +111,9 @@ enum cdev_todo {
CDEV_TODO_UNREG_EVAL,
};
+#define FAKE_CMD_IRB 1
+#define FAKE_TM_IRB 2
+
struct ccw_device_private {
struct ccw_device *cdev;
struct subchannel *sch;
@@ -137,7 +141,7 @@ struct ccw_device_private {
unsigned int doverify:1; /* delayed path verification */
unsigned int donotify:1; /* call notify function */
unsigned int recog_done:1; /* dev. recog. complete */
- unsigned int fake_irb:1; /* deliver faked irb */
+ unsigned int fake_irb:2; /* deliver faked irb */
unsigned int resuming:1; /* recognition while resume */
unsigned int pgroup:1; /* pathgroup is set up */
unsigned int mpath:1; /* multipathing is set up */
@@ -157,6 +161,7 @@ struct ccw_device_private {
struct list_head cmb_list; /* list of measured devices */
u64 cmb_start_time; /* clock value of cmb reset */
void *cmb_wait; /* deferred cmb enable/disable */
+ enum interruption_class int_class;
};
static inline int rsch(struct subchannel_id schid)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 7bc643f..b962ffb 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -14,16 +14,10 @@
#include "chsc.h"
#define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */
+#define QDIO_BUSY_BIT_RETRY_DELAY 10 /* 10 milliseconds */
+#define QDIO_BUSY_BIT_RETRIES 1000 /* = 10s retry time */
#define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */
-/*
- * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait
- * till next initiative to give transmitted skbs back to the stack is too long.
- * Therefore polling is started in case of multicast queue is filled more
- * than 50 percent.
- */
-#define QDIO_IQDIO_POLL_LVL 65 /* HS multicast queue */
-
enum qdio_irq_states {
QDIO_IRQ_STATE_INACTIVE,
QDIO_IRQ_STATE_ESTABLISHED,
@@ -42,6 +36,7 @@ enum qdio_irq_states {
#define SLSB_STATE_NOT_INIT 0x0
#define SLSB_STATE_EMPTY 0x1
#define SLSB_STATE_PRIMED 0x2
+#define SLSB_STATE_PENDING 0x3
#define SLSB_STATE_HALTED 0xe
#define SLSB_STATE_ERROR 0xf
#define SLSB_TYPE_INPUT 0x0
@@ -65,6 +60,8 @@ enum qdio_irq_states {
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_NOT_INIT) /* 0xa0 */
#define SLSB_P_OUTPUT_EMPTY \
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_EMPTY) /* 0xa1 */
+#define SLSB_P_OUTPUT_PENDING \
+ (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_PENDING) /* 0xa3 */
#define SLSB_CU_OUTPUT_PRIMED \
(SLSB_OWNER_CU | SLSB_TYPE_OUTPUT | SLSB_STATE_PRIMED) /* 0x62 */
#define SLSB_P_OUTPUT_HALTED \
@@ -82,19 +79,11 @@ enum qdio_irq_states {
#define CHSC_FLAG_QDIO_CAPABILITY 0x80
#define CHSC_FLAG_VALIDITY 0x40
-/* qdio adapter-characteristics-1 flag */
-#define AC1_SIGA_INPUT_NEEDED 0x40 /* process input queues */
-#define AC1_SIGA_OUTPUT_NEEDED 0x20 /* process output queues */
-#define AC1_SIGA_SYNC_NEEDED 0x10 /* ask hypervisor to sync */
-#define AC1_AUTOMATIC_SYNC_ON_THININT 0x08 /* set by hypervisor */
-#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI 0x04 /* set by hypervisor */
-#define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */
-#define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */
-
/* SIGA flags */
#define QDIO_SIGA_WRITE 0x00
#define QDIO_SIGA_READ 0x01
#define QDIO_SIGA_SYNC 0x02
+#define QDIO_SIGA_WRITEQ 0x04
#define QDIO_SIGA_QEBSM_FLAG 0x80
#ifdef CONFIG_64BIT
@@ -251,6 +240,12 @@ struct qdio_input_q {
struct qdio_output_q {
/* PCIs are enabled for the queue */
int pci_out_enabled;
+ /* cq: use asynchronous output buffers */
+ int use_cq;
+ /* cq: aobs used for particual SBAL */
+ struct qaob **aobs;
+ /* cq: sbal state related to asynchronous operation */
+ struct qdio_outbuf_state *sbal_state;
/* timer to check for more outbound work */
struct timer_list timer;
/* used SBALs before tasklet schedule */
@@ -287,6 +282,9 @@ struct qdio_q {
/* error condition during a data transfer */
unsigned int qdio_error;
+ /* last scan of the queue */
+ u64 timestamp;
+
struct tasklet_struct tasklet;
struct qdio_queue_perf_stat q_stats;
@@ -420,20 +418,7 @@ static inline int multicast_outbound(struct qdio_q *q)
#define queue_irqs_disabled(q) \
(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
-#define TIQDIO_SHARED_IND 63
-
-/* device state change indicators */
-struct indicator_t {
- u32 ind; /* u32 because of compare-and-swap performance */
- atomic_t count; /* use count, 0 or 1 for non-shared indicators */
-};
-
-extern struct indicator_t *q_indicators;
-
-static inline int shared_ind(u32 *dsci)
-{
- return dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
-}
+extern u64 last_ai_time;
/* prototypes for thin interrupt */
void qdio_setup_thinint(struct qdio_irq *irq_ptr);
@@ -446,6 +431,8 @@ int tiqdio_allocate_memory(void);
void tiqdio_free_memory(void);
int tiqdio_register_thinints(void);
void tiqdio_unregister_thinints(void);
+void clear_nonshared_ind(struct qdio_irq *);
+int test_nonshared_ind(struct qdio_irq *);
/* prototypes for setup */
void qdio_inbound_processing(unsigned long data);
@@ -467,6 +454,9 @@ int qdio_setup_create_sysfs(struct ccw_device *cdev);
void qdio_setup_destroy_sysfs(struct ccw_device *cdev);
int qdio_setup_init(void);
void qdio_setup_exit(void);
+int qdio_enable_async_operation(struct qdio_output_q *q);
+void qdio_disable_async_operation(struct qdio_output_q *q);
+struct qaob *qdio_allocate_aob(void);
int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state);
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index f8b03a6..29021f4 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -7,6 +7,8 @@
*/
#include <linux/seq_file.h>
#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/export.h>
#include <asm/debug.h>
#include "qdio_debug.h"
#include "qdio.h"
@@ -54,15 +56,17 @@ static int qstat_show(struct seq_file *m, void *v)
if (!q)
return 0;
- seq_printf(m, "DSCI: %d nr_used: %d\n",
- *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
- seq_printf(m, "ftc: %d last_move: %d\n",
+ seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n",
+ q->timestamp, last_ai_time);
+ seq_printf(m, "nr_used: %d ftc: %d last_move: %d\n",
+ atomic_read(&q->nr_buf_used),
q->first_to_check, q->last_move);
if (q->is_input_q) {
seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
q->u.in.polling, q->u.in.ack_start,
q->u.in.ack_count);
- seq_printf(m, "IRQs disabled: %u\n",
+ seq_printf(m, "DSCI: %d IRQs disabled: %u\n",
+ *(u32 *)q->irq_ptr->dsci,
test_bit(QDIO_QUEUE_IRQS_DISABLED,
&q->u.in.queue_irq_state));
}
@@ -76,6 +80,9 @@ static int qstat_show(struct seq_file *m, void *v)
case SLSB_P_OUTPUT_NOT_INIT:
seq_printf(m, "N");
break;
+ case SLSB_P_OUTPUT_PENDING:
+ seq_printf(m, "P");
+ break;
case SLSB_P_INPUT_PRIMED:
case SLSB_CU_OUTPUT_PRIMED:
seq_printf(m, "+");
@@ -188,19 +195,13 @@ static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
struct qdio_irq *irq_ptr = seq->private;
struct qdio_q *q;
unsigned long val;
- char buf[8];
int ret, i;
if (!irq_ptr)
return 0;
- if (count >= sizeof(buf))
- return -EINVAL;
- if (copy_from_user(&buf, ubuf, count))
- return -EFAULT;
- buf[count] = 0;
-
- ret = strict_strtoul(buf, 10, &val);
- if (ret < 0)
+
+ ret = kstrtoul_from_user(ubuf, count, 10, &val);
+ if (ret)
return ret;
switch (val) {
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 570d4da..770a740 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -14,8 +14,8 @@
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/gfp.h>
-#include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/io.h>
+#include <linux/atomic.h>
#include <asm/debug.h>
#include <asm/qdio.h>
@@ -77,11 +77,13 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
* Note: For IQDC unicast queues only the highest priority queue is processed.
*/
static inline int do_siga_output(unsigned long schid, unsigned long mask,
- unsigned int *bb, unsigned int fc)
+ unsigned int *bb, unsigned int fc,
+ unsigned long aob)
{
register unsigned long __fc asm("0") = fc;
register unsigned long __schid asm("1") = schid;
register unsigned long __mask asm("2") = mask;
+ register unsigned long __aob asm("3") = aob;
int cc = QDIO_ERROR_SIGA_ACCESS_EXCEPTION;
asm volatile(
@@ -90,7 +92,8 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask,
" srl %0,28\n"
"1:\n"
EX_TABLE(0b, 1b)
- : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask)
+ : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask),
+ "+d" (__aob)
: : "cc", "memory");
*bb = ((unsigned int) __fc) >> 31;
return cc;
@@ -101,9 +104,12 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
/* all done or next buffer state different */
if (ccq == 0 || ccq == 32)
return 0;
- /* not all buffers processed */
- if (ccq == 96 || ccq == 97)
+ /* no buffer processed */
+ if (ccq == 97)
return 1;
+ /* not all buffers processed */
+ if (ccq == 96)
+ return 2;
/* notify devices immediately */
DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq);
return -EIO;
@@ -123,10 +129,8 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
int start, int count, int auto_ack)
{
+ int rc, tmp_count = count, tmp_start = start, nr = q->nr, retried = 0;
unsigned int ccq = 0;
- int tmp_count = count, tmp_start = start;
- int nr = q->nr;
- int rc;
BUG_ON(!q->irq_ptr->sch_token);
qperf_inc(q, eqbs);
@@ -137,29 +141,34 @@ again:
ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count,
auto_ack);
rc = qdio_check_ccq(q, ccq);
-
- /* At least one buffer was processed, return and extract the remaining
- * buffers later.
- */
- if ((ccq == 96) && (count != tmp_count)) {
- qperf_inc(q, eqbs_partial);
- return (count - tmp_count);
- }
+ if (!rc)
+ return count - tmp_count;
if (rc == 1) {
DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq);
goto again;
}
- if (rc < 0) {
- DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
- DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
- q->handler(q->irq_ptr->cdev,
- QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
- 0, -1, -1, q->irq_ptr->int_parm);
- return 0;
+ if (rc == 2) {
+ BUG_ON(tmp_count == count);
+ qperf_inc(q, eqbs_partial);
+ DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x",
+ tmp_count);
+ /*
+ * Retry once, if that fails bail out and process the
+ * extracted buffers before trying again.
+ */
+ if (!retried++)
+ goto again;
+ else
+ return count - tmp_count;
}
- return count - tmp_count;
+
+ DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
+ DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
+ return 0;
}
/**
@@ -192,27 +201,28 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
again:
ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count);
rc = qdio_check_ccq(q, ccq);
- if (rc == 1) {
+ if (!rc) {
+ WARN_ON(tmp_count);
+ return count - tmp_count;
+ }
+
+ if (rc == 1 || rc == 2) {
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq);
qperf_inc(q, sqbs_partial);
goto again;
}
- if (rc < 0) {
- DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
- DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
- q->handler(q->irq_ptr->cdev,
- QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
- 0, -1, -1, q->irq_ptr->int_parm);
- return 0;
- }
- WARN_ON(tmp_count);
- return count - tmp_count;
+
+ DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
+ DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
+ return 0;
}
/* returns number of examined buffers and their common state in *state */
static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
unsigned char *state, unsigned int count,
- int auto_ack)
+ int auto_ack, int merge_pending)
{
unsigned char __state = 0;
int i;
@@ -224,9 +234,14 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
return qdio_do_eqbs(q, state, bufnr, count, auto_ack);
for (i = 0; i < count; i++) {
- if (!__state)
+ if (!__state) {
__state = q->slsb.val[bufnr];
- else if (q->slsb.val[bufnr] != __state)
+ if (merge_pending && __state == SLSB_P_OUTPUT_PENDING)
+ __state = SLSB_P_OUTPUT_EMPTY;
+ } else if (merge_pending) {
+ if ((q->slsb.val[bufnr] & __state) != __state)
+ break;
+ } else if (q->slsb.val[bufnr] != __state)
break;
bufnr = next_buf(bufnr);
}
@@ -237,7 +252,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
static inline int get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state, int auto_ack)
{
- return get_buf_states(q, bufnr, state, 1, auto_ack);
+ return get_buf_states(q, bufnr, state, 1, auto_ack, 0);
}
/* wrap-around safe setting of slsb states, returns number of changed buffers */
@@ -266,7 +281,7 @@ static inline int set_buf_state(struct qdio_q *q, int bufnr,
}
/* set slsb states to initial state */
-void qdio_init_buf_states(struct qdio_irq *irq_ptr)
+static void qdio_init_buf_states(struct qdio_irq *irq_ptr)
{
struct qdio_q *q;
int i;
@@ -308,23 +323,33 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
return qdio_siga_sync(q, q->mask, 0);
}
-static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit)
+static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
+ unsigned long aob)
{
unsigned long schid = *((u32 *) &q->irq_ptr->schid);
unsigned int fc = QDIO_SIGA_WRITE;
u64 start_time = 0;
- int cc;
+ int retries = 0, cc;
+ unsigned long laob = 0;
+
+ if (q->u.out.use_cq && aob != 0) {
+ fc = QDIO_SIGA_WRITEQ;
+ laob = aob;
+ }
if (is_qebsm(q)) {
schid = q->irq_ptr->sch_token;
fc |= QDIO_SIGA_QEBSM_FLAG;
}
again:
- cc = do_siga_output(schid, q->mask, busy_bit, fc);
+ WARN_ON_ONCE((aob && queue_type(q) != QDIO_IQDIO_QFMT) ||
+ (aob && fc != QDIO_SIGA_WRITEQ));
+ cc = do_siga_output(schid, q->mask, busy_bit, fc, laob);
/* hipersocket busy condition */
if (unlikely(*busy_bit)) {
WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2);
+ retries++;
if (!start_time) {
start_time = get_clock();
@@ -333,6 +358,11 @@ again:
if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE)
goto again;
}
+ if (retries) {
+ DBF_DEV_EVENT(DBF_WARN, q->irq_ptr,
+ "%4x cc2 BB1:%1d", SCH_NO(q), q->nr);
+ DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "count:%u", retries);
+ }
return cc;
}
@@ -373,7 +403,7 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
{
if (need_siga_sync(q))
qdio_siga_sync_q(q);
- return get_buf_states(q, bufnr, state, 1, 0);
+ return get_buf_states(q, bufnr, state, 1, 0, 0);
}
static inline void qdio_stop_polling(struct qdio_q *q)
@@ -420,7 +450,7 @@ static void process_buffer_error(struct qdio_q *q, int count)
qperf_inc(q, target_full);
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
q->first_to_check);
- return;
+ goto set;
}
DBF_ERROR("%4x BUF ERROR", SCH_NO(q));
@@ -430,6 +460,7 @@ static void process_buffer_error(struct qdio_q *q, int count)
q->sbal[q->first_to_check]->element[14].sflags,
q->sbal[q->first_to_check]->element[15].sflags);
+set:
/*
* Interrupts may be avoided as long as the error is present
* so change the buffer state immediately to avoid starvation.
@@ -487,6 +518,8 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state = 0;
+ q->timestamp = get_clock_fast();
+
/*
* Don't check 128 buffers, as otherwise qdio_inbound_q_moved
* would return 0.
@@ -501,7 +534,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
* No siga sync here, as a PCI or we after a thin interrupt
* already sync'ed the queues.
*/
- count = get_buf_states(q, q->first_to_check, &state, count, 1);
+ count = get_buf_states(q, q->first_to_check, &state, count, 1, 0);
if (!count)
goto out;
@@ -584,6 +617,107 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
return 0;
}
+static inline int contains_aobs(struct qdio_q *q)
+{
+ return !q->is_input_q && q->u.out.use_cq;
+}
+
+static inline void qdio_trace_aob(struct qdio_irq *irq, struct qdio_q *q,
+ int i, struct qaob *aob)
+{
+ int tmp;
+
+ DBF_DEV_EVENT(DBF_INFO, irq, "AOB%d:%lx", i,
+ (unsigned long) virt_to_phys(aob));
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES00:%lx",
+ (unsigned long) aob->res0[0]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES01:%lx",
+ (unsigned long) aob->res0[1]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES02:%lx",
+ (unsigned long) aob->res0[2]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES03:%lx",
+ (unsigned long) aob->res0[3]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES04:%lx",
+ (unsigned long) aob->res0[4]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES05:%lx",
+ (unsigned long) aob->res0[5]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES1:%x", aob->res1);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES2:%x", aob->res2);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES3:%x", aob->res3);
+ DBF_DEV_EVENT(DBF_INFO, irq, "AORC:%u", aob->aorc);
+ DBF_DEV_EVENT(DBF_INFO, irq, "FLAGS:%u", aob->flags);
+ DBF_DEV_EVENT(DBF_INFO, irq, "CBTBS:%u", aob->cbtbs);
+ DBF_DEV_EVENT(DBF_INFO, irq, "SBC:%u", aob->sb_count);
+ for (tmp = 0; tmp < QDIO_MAX_ELEMENTS_PER_BUFFER; ++tmp) {
+ DBF_DEV_EVENT(DBF_INFO, irq, "SBA%d:%lx", tmp,
+ (unsigned long) aob->sba[tmp]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "rSBA%d:%lx", tmp,
+ (unsigned long) q->sbal[i]->element[tmp].addr);
+ DBF_DEV_EVENT(DBF_INFO, irq, "DC%d:%u", tmp, aob->dcount[tmp]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "rDC%d:%u", tmp,
+ q->sbal[i]->element[tmp].length);
+ }
+ DBF_DEV_EVENT(DBF_INFO, irq, "USER0:%lx", (unsigned long) aob->user0);
+ for (tmp = 0; tmp < 2; ++tmp) {
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES4%d:%lx", tmp,
+ (unsigned long) aob->res4[tmp]);
+ }
+ DBF_DEV_EVENT(DBF_INFO, irq, "USER1:%lx", (unsigned long) aob->user1);
+ DBF_DEV_EVENT(DBF_INFO, irq, "USER2:%lx", (unsigned long) aob->user2);
+}
+
+static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count)
+{
+ unsigned char state = 0;
+ int j, b = start;
+
+ if (!contains_aobs(q))
+ return;
+
+ for (j = 0; j < count; ++j) {
+ get_buf_state(q, b, &state, 0);
+ if (state == SLSB_P_OUTPUT_PENDING) {
+ struct qaob *aob = q->u.out.aobs[b];
+ if (aob == NULL)
+ continue;
+
+ BUG_ON(q->u.out.sbal_state == NULL);
+ q->u.out.sbal_state[b].flags |=
+ QDIO_OUTBUF_STATE_FLAG_PENDING;
+ q->u.out.aobs[b] = NULL;
+ } else if (state == SLSB_P_OUTPUT_EMPTY) {
+ BUG_ON(q->u.out.sbal_state == NULL);
+ q->u.out.sbal_state[b].aob = NULL;
+ }
+ b = next_buf(b);
+ }
+}
+
+static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
+ int bufnr)
+{
+ unsigned long phys_aob = 0;
+
+ if (!q->use_cq)
+ goto out;
+
+ if (!q->aobs[bufnr]) {
+ struct qaob *aob = qdio_allocate_aob();
+ q->aobs[bufnr] = aob;
+ }
+ if (q->aobs[bufnr]) {
+ BUG_ON(q->sbal_state == NULL);
+ q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE;
+ q->sbal_state[bufnr].aob = q->aobs[bufnr];
+ q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user;
+ phys_aob = virt_to_phys(q->aobs[bufnr]);
+ BUG_ON(phys_aob & 0xFF);
+ }
+
+out:
+ return phys_aob;
+}
+
static void qdio_kick_handler(struct qdio_q *q)
{
int start = q->first_to_kick;
@@ -604,6 +738,8 @@ static void qdio_kick_handler(struct qdio_q *q)
start, count);
}
+ qdio_handle_aobs(q, start, count);
+
q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
q->irq_ptr->int_parm);
@@ -653,6 +789,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state = 0;
+ q->timestamp = get_clock_fast();
+
if (need_siga_sync(q))
if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
!pci_out_supported(q)) ||
@@ -666,23 +804,26 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
*/
count = min(atomic_read(&q->nr_buf_used), QDIO_MAX_BUFFERS_MASK);
stop = add_buf(q->first_to_check, count);
-
if (q->first_to_check == stop)
- return q->first_to_check;
+ goto out;
- count = get_buf_states(q, q->first_to_check, &state, count, 0);
+ count = get_buf_states(q, q->first_to_check, &state, count, 0, 1);
if (!count)
- return q->first_to_check;
+ goto out;
switch (state) {
+ case SLSB_P_OUTPUT_PENDING:
+ BUG();
case SLSB_P_OUTPUT_EMPTY:
/* the adapter got it */
- DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %02x", q->nr, count);
+ DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
+ "out empty:%1d %02x", q->nr, count);
atomic_sub(count, &q->nr_buf_used);
q->first_to_check = add_buf(q->first_to_check, count);
if (q->irq_ptr->perf_stat_enabled)
account_sbals(q, count);
+
break;
case SLSB_P_OUTPUT_ERROR:
process_buffer_error(q, count);
@@ -695,7 +836,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
/* the adapter has not fetched the output yet */
if (q->irq_ptr->perf_stat_enabled)
q->q_stats.nr_sbal_nop++;
- DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", q->nr);
+ DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d",
+ q->nr);
break;
case SLSB_P_OUTPUT_NOT_INIT:
case SLSB_P_OUTPUT_HALTED:
@@ -703,6 +845,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
default:
BUG();
}
+
+out:
return q->first_to_check;
}
@@ -726,24 +870,29 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q)
return 0;
}
-static int qdio_kick_outbound_q(struct qdio_q *q)
+static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob)
{
+ int retries = 0, cc;
unsigned int busy_bit;
- int cc;
if (!need_siga_out(q))
return 0;
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
+retry:
qperf_inc(q, siga_write);
- cc = qdio_siga_output(q, &busy_bit);
+ cc = qdio_siga_output(q, &busy_bit, aob);
switch (cc) {
case 0:
break;
case 2:
if (busy_bit) {
- DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr);
+ while (++retries < QDIO_BUSY_BIT_RETRIES) {
+ mdelay(QDIO_BUSY_BIT_RETRY_DELAY);
+ goto retry;
+ }
+ DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr);
cc |= QDIO_ERROR_SIGA_BUSY;
} else
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr);
@@ -753,6 +902,10 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc);
break;
}
+ if (retries) {
+ DBF_ERROR("%4x cc2 BB2:%1d", SCH_NO(q), q->nr);
+ DBF_ERROR("count:%u", retries);
+ }
return cc;
}
@@ -768,21 +921,13 @@ static void __qdio_outbound_processing(struct qdio_q *q)
if (!pci_out_supported(q) && !qdio_outbound_q_done(q))
goto sched;
- /* bail out for HiperSockets unicast queues */
- if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q))
- return;
-
- if ((queue_type(q) == QDIO_IQDIO_QFMT) &&
- (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL)
- goto sched;
-
if (q->u.out.pci_out_enabled)
return;
/*
* Now we know that queue type is either qeth without pci enabled
- * or HiperSockets multicast. Make sure buffer switch from PRIMED to
- * EMPTY is noticed and outbound_handler is called after some time.
+ * or HiperSockets. Make sure buffer switch from PRIMED to EMPTY
+ * is noticed and outbound_handler is called after some time.
*/
if (qdio_outbound_q_done(q))
del_timer(&q->u.out.timer);
@@ -906,8 +1051,9 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
}
q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
q->irq_ptr->int_parm);
- } else
+ } else {
tasklet_schedule(&q->tasklet);
+ }
}
if (!pci_out_supported(q))
@@ -927,6 +1073,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
struct qdio_q *q;
+ int count;
DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no);
DBF_ERROR("intp :%lx", intparm);
@@ -940,8 +1087,10 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
dump_stack();
goto no_handler;
}
+
+ count = sub_buf(q->first_to_check, q->first_to_kick);
q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
- 0, -1, -1, irq_ptr->int_parm);
+ q->nr, q->first_to_kick, count, irq_ptr->int_parm);
no_handler:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
}
@@ -980,7 +1129,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
return;
}
- kstat_cpu(smp_processor_id()).irqs[IOINT_QDI]++;
if (irq_ptr->perf_stat_enabled)
irq_ptr->perf_stat.qdio_int++;
@@ -1221,6 +1369,26 @@ out_err:
}
EXPORT_SYMBOL_GPL(qdio_allocate);
+static void qdio_detect_hsicq(struct qdio_irq *irq_ptr)
+{
+ struct qdio_q *q = irq_ptr->input_qs[0];
+ int i, use_cq = 0;
+
+ if (irq_ptr->nr_input_qs > 1 && queue_type(q) == QDIO_IQDIO_QFMT)
+ use_cq = 1;
+
+ for_each_output_queue(irq_ptr, q, i) {
+ if (use_cq) {
+ if (qdio_enable_async_operation(&q->u.out) < 0) {
+ use_cq = 0;
+ continue;
+ }
+ } else
+ qdio_disable_async_operation(&q->u.out);
+ }
+ DBF_EVENT("use_cq:%d", use_cq);
+}
+
/**
* qdio_establish - establish queues on a qdio subchannel
* @init_data: initialization data
@@ -1286,6 +1454,8 @@ int qdio_establish(struct qdio_initialize *init_data)
qdio_setup_ssqd_info(irq_ptr);
DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac);
+ qdio_detect_hsicq(irq_ptr);
+
/* qebsm is now setup if available, initialize buffer states */
qdio_init_buf_states(irq_ptr);
@@ -1427,12 +1597,9 @@ set:
used = atomic_add_return(count, &q->nr_buf_used) - count;
BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q);
- /* no need to signal as long as the adapter had free buffers */
- if (used)
- return 0;
-
if (need_siga_in(q))
return qdio_siga_input(q);
+
return 0;
}
@@ -1465,17 +1632,21 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
q->u.out.pci_out_enabled = 0;
if (queue_type(q) == QDIO_IQDIO_QFMT) {
- /* One SIGA-W per buffer required for unicast HiperSockets. */
+ unsigned long phys_aob = 0;
+
+ /* One SIGA-W per buffer required for unicast HSI */
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
- rc = qdio_kick_outbound_q(q);
+ phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
+
+ rc = qdio_kick_outbound_q(q, phys_aob);
} else if (need_siga_sync(q)) {
rc = qdio_siga_sync_q(q);
} else {
/* try to fast requeue buffers */
get_buf_state(q, prev_buf(bufnr), &state, 0);
if (state != SLSB_CU_OUTPUT_PRIMED)
- rc = qdio_kick_outbound_q(q);
+ rc = qdio_kick_outbound_q(q, 0);
else
qperf_inc(q, fast_requeue);
}
@@ -1503,6 +1674,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
{
struct qdio_irq *irq_ptr;
+
if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
return -EINVAL;
@@ -1547,9 +1719,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
WARN_ON(queue_irqs_enabled(q));
- if (!shared_ind(q->irq_ptr->dsci))
- xchg(q->irq_ptr->dsci, 0);
-
+ clear_nonshared_ind(irq_ptr);
qdio_stop_polling(q);
clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
@@ -1557,7 +1727,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
* We need to check again to not lose initiative after
* resetting the ACK state.
*/
- if (!shared_ind(q->irq_ptr->dsci) && *q->irq_ptr->dsci)
+ if (test_nonshared_ind(irq_ptr))
goto rescan;
if (!qdio_inbound_q_done(q))
goto rescan;
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 89107d0..2acc01f 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -8,6 +8,7 @@
*/
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <asm/qdio.h>
#include "cio.h"
@@ -19,6 +20,22 @@
#include "qdio_debug.h"
static struct kmem_cache *qdio_q_cache;
+static struct kmem_cache *qdio_aob_cache;
+
+struct qaob *qdio_allocate_aob()
+{
+ struct qaob *aob;
+
+ aob = kmem_cache_zalloc(qdio_aob_cache, GFP_ATOMIC);
+ return aob;
+}
+EXPORT_SYMBOL_GPL(qdio_allocate_aob);
+
+void qdio_release_aob(struct qaob *aob)
+{
+ kmem_cache_free(qdio_aob_cache, aob);
+}
+EXPORT_SYMBOL_GPL(qdio_release_aob);
/*
* qebsm is only available under 64bit but the adapter sets the feature
@@ -154,29 +171,36 @@ static void setup_queues(struct qdio_irq *irq_ptr,
struct qdio_q *q;
void **input_sbal_array = qdio_init->input_sbal_addr_array;
void **output_sbal_array = qdio_init->output_sbal_addr_array;
+ struct qdio_outbuf_state *output_sbal_state_array =
+ qdio_init->output_sbal_state_array;
int i;
for_each_input_queue(irq_ptr, q, i) {
- DBF_EVENT("in-q:%1d", i);
+ DBF_EVENT("inq:%1d", i);
setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
q->is_input_q = 1;
- q->u.in.queue_start_poll = qdio_init->queue_start_poll;
+ q->u.in.queue_start_poll = qdio_init->queue_start_poll[i];
+
setup_storage_lists(q, irq_ptr, input_sbal_array, i);
input_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
- if (is_thinint_irq(irq_ptr))
+ if (is_thinint_irq(irq_ptr)) {
tasklet_init(&q->tasklet, tiqdio_inbound_processing,
(unsigned long) q);
- else
+ } else {
tasklet_init(&q->tasklet, qdio_inbound_processing,
(unsigned long) q);
+ }
}
for_each_output_queue(irq_ptr, q, i) {
DBF_EVENT("outq:%1d", i);
setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i);
+ q->u.out.sbal_state = output_sbal_state_array;
+ output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q;
+
q->is_input_q = 0;
q->u.out.scan_threshold = qdio_init->scan_threshold;
setup_storage_lists(q, irq_ptr, output_sbal_array, i);
@@ -311,6 +335,19 @@ void qdio_release_memory(struct qdio_irq *irq_ptr)
for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) {
q = irq_ptr->output_qs[i];
if (q) {
+ if (q->u.out.use_cq) {
+ int n;
+
+ for (n = 0; n < QDIO_MAX_BUFFERS_PER_Q; ++n) {
+ struct qaob *aob = q->u.out.aobs[n];
+ if (aob) {
+ qdio_release_aob(aob);
+ q->u.out.aobs[n] = NULL;
+ }
+ }
+
+ qdio_disable_async_operation(&q->u.out);
+ }
free_page((unsigned long) q->slib);
kmem_cache_free(qdio_q_cache, q);
}
@@ -345,6 +382,7 @@ static void setup_qdr(struct qdio_irq *irq_ptr,
int i;
irq_ptr->qdr->qfmt = qdio_init->q_format;
+ irq_ptr->qdr->ac = qdio_init->qdr_ac;
irq_ptr->qdr->iqdcnt = qdio_init->no_input_qs;
irq_ptr->qdr->oqdcnt = qdio_init->no_output_qs;
irq_ptr->qdr->iqdsz = sizeof(struct qdesfmt0) / 4; /* size in words */
@@ -465,23 +503,60 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
printk(KERN_INFO "%s", s);
}
+int qdio_enable_async_operation(struct qdio_output_q *outq)
+{
+ outq->aobs = kzalloc(sizeof(struct qaob *) * QDIO_MAX_BUFFERS_PER_Q,
+ GFP_ATOMIC);
+ if (!outq->aobs) {
+ outq->use_cq = 0;
+ return -ENOMEM;
+ }
+ outq->use_cq = 1;
+ return 0;
+}
+
+void qdio_disable_async_operation(struct qdio_output_q *q)
+{
+ kfree(q->aobs);
+ q->aobs = NULL;
+ q->use_cq = 0;
+}
+
int __init qdio_setup_init(void)
{
+ int rc;
+
qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q),
256, 0, NULL);
if (!qdio_q_cache)
return -ENOMEM;
+ qdio_aob_cache = kmem_cache_create("qdio_aob",
+ sizeof(struct qaob),
+ sizeof(struct qaob),
+ 0,
+ NULL);
+ if (!qdio_aob_cache) {
+ rc = -ENOMEM;
+ goto free_qdio_q_cache;
+ }
+
/* Check for OSA/FCP thin interrupts (bit 67). */
DBF_EVENT("thinint:%1d",
(css_general_characteristics.aif_osa) ? 1 : 0);
/* Check for QEBSM support in general (bit 58). */
DBF_EVENT("cssQEBSM:%1d", (qebsm_possible()) ? 1 : 0);
- return 0;
+ rc = 0;
+out:
+ return rc;
+free_qdio_q_cache:
+ kmem_cache_destroy(qdio_q_cache);
+ goto out;
}
void qdio_setup_exit(void)
{
+ kmem_cache_destroy(qdio_aob_cache);
kmem_cache_destroy(qdio_q_cache);
}
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 68be6e1..011eade 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -9,7 +9,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/debug.h>
#include <asm/qdio.h>
#include <asm/airq.h>
@@ -26,17 +26,24 @@
*/
#define TIQDIO_NR_NONSHARED_IND 63
#define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1)
+#define TIQDIO_SHARED_IND 63
+
+/* device state change indicators */
+struct indicator_t {
+ u32 ind; /* u32 because of compare-and-swap performance */
+ atomic_t count; /* use count, 0 or 1 for non-shared indicators */
+};
/* list of thin interrupt input queues */
static LIST_HEAD(tiq_list);
-DEFINE_MUTEX(tiq_list_lock);
+static DEFINE_MUTEX(tiq_list_lock);
/* adapter local summary indicator */
static u8 *tiqdio_alsi;
-struct indicator_t *q_indicators;
+static struct indicator_t *q_indicators;
-static u64 last_ai_time;
+u64 last_ai_time;
/* returns addr for the device state change indicator */
static u32 *get_indicator(void)
@@ -67,12 +74,9 @@ static void put_indicator(u32 *addr)
void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
{
- struct qdio_q *q;
- int i;
-
mutex_lock(&tiq_list_lock);
- for_each_input_queue(irq_ptr, q, i)
- list_add_rcu(&q->entry, &tiq_list);
+ BUG_ON(irq_ptr->nr_input_qs < 1);
+ list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
mutex_unlock(&tiq_list_lock);
xchg(irq_ptr->dsci, 1 << 7);
}
@@ -80,19 +84,54 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
{
struct qdio_q *q;
- int i;
- for (i = 0; i < irq_ptr->nr_input_qs; i++) {
- q = irq_ptr->input_qs[i];
- /* if establish triggered an error */
- if (!q || !q->entry.prev || !q->entry.next)
- continue;
+ BUG_ON(irq_ptr->nr_input_qs < 1);
+ q = irq_ptr->input_qs[0];
+ /* if establish triggered an error */
+ if (!q || !q->entry.prev || !q->entry.next)
+ return;
- mutex_lock(&tiq_list_lock);
- list_del_rcu(&q->entry);
- mutex_unlock(&tiq_list_lock);
- synchronize_rcu();
- }
+ mutex_lock(&tiq_list_lock);
+ list_del_rcu(&q->entry);
+ mutex_unlock(&tiq_list_lock);
+ synchronize_rcu();
+}
+
+static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)
+{
+ return irq_ptr->nr_input_qs > 1;
+}
+
+static inline int references_shared_dsci(struct qdio_irq *irq_ptr)
+{
+ return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+}
+
+static inline int shared_ind(struct qdio_irq *irq_ptr)
+{
+ return references_shared_dsci(irq_ptr) ||
+ has_multiple_inq_on_dsci(irq_ptr);
+}
+
+void clear_nonshared_ind(struct qdio_irq *irq_ptr)
+{
+ if (!is_thinint_irq(irq_ptr))
+ return;
+ if (shared_ind(irq_ptr))
+ return;
+ xchg(irq_ptr->dsci, 0);
+}
+
+int test_nonshared_ind(struct qdio_irq *irq_ptr)
+{
+ if (!is_thinint_irq(irq_ptr))
+ return 0;
+ if (shared_ind(irq_ptr))
+ return 0;
+ if (*irq_ptr->dsci)
+ return 1;
+ else
+ return 0;
}
static inline u32 clear_shared_ind(void)
@@ -102,6 +141,40 @@ static inline u32 clear_shared_ind(void)
return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
}
+static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
+{
+ struct qdio_q *q;
+ int i;
+
+ for_each_input_queue(irq, q, i) {
+ if (!references_shared_dsci(irq) &&
+ has_multiple_inq_on_dsci(irq))
+ xchg(q->irq_ptr->dsci, 0);
+
+ if (q->u.in.queue_start_poll) {
+ /* skip if polling is enabled or already in work */
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state)) {
+ qperf_inc(q, int_discarded);
+ continue;
+ }
+
+ /* avoid dsci clear here, done after processing */
+ q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+ q->irq_ptr->int_parm);
+ } else {
+ if (!shared_ind(q->irq_ptr))
+ xchg(q->irq_ptr->dsci, 0);
+
+ /*
+ * Call inbound processing but not directly
+ * since that could starve other thinint queues.
+ */
+ tasklet_schedule(&q->tasklet);
+ }
+ }
+}
+
/**
* tiqdio_thinint_handler - thin interrupt handler for qdio
* @alsi: pointer to adapter local summary indicator
@@ -120,35 +193,18 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
/* check for work on all inbound thinint queues */
list_for_each_entry_rcu(q, &tiq_list, entry) {
+ struct qdio_irq *irq;
/* only process queues from changed sets */
- if (unlikely(shared_ind(q->irq_ptr->dsci))) {
+ irq = q->irq_ptr;
+ if (unlikely(references_shared_dsci(irq))) {
if (!si_used)
continue;
- } else if (!*q->irq_ptr->dsci)
+ } else if (!*irq->dsci)
continue;
- if (q->u.in.queue_start_poll) {
- /* skip if polling is enabled or already in work */
- if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
- &q->u.in.queue_irq_state)) {
- qperf_inc(q, int_discarded);
- continue;
- }
+ tiqdio_call_inq_handlers(irq);
- /* avoid dsci clear here, done after processing */
- q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
- q->irq_ptr->int_parm);
- } else {
- /* only clear it if the indicator is non-shared */
- if (!shared_ind(q->irq_ptr->dsci))
- xchg(q->irq_ptr->dsci, 0);
- /*
- * Call inbound processing but not directly
- * since that could starve other thinint queues.
- */
- tasklet_schedule(&q->tasklet);
- }
qperf_inc(q, adapter_int);
}
rcu_read_unlock();
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 16e4a25..96bbe9d 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -6,6 +6,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com>
+ * Holger Dengler <hd@linux.vnet.ibm.com>
*
* Adjunct processor bus.
*
@@ -40,7 +41,7 @@
#include <linux/mutex.h>
#include <asm/reset.h>
#include <asm/airq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/isc.h>
#include <linux/hrtimer.h>
@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
}
#endif
-static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
- int *support)
+#ifdef CONFIG_64BIT
+static inline struct ap_queue_status
+__ap_query_functions(ap_qid_t qid, unsigned int *functions)
{
register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
- register struct ap_queue_status reg1 asm ("1");
- register unsigned long reg2 asm ("2") = 0UL;
+ register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
+ register unsigned long reg2 asm ("2");
asm volatile(
".long 0xb2af0000\n"
- "0: la %1,0\n"
- "1:\n"
- EX_TABLE(0b, 1b)
- : "+d" (reg0), "=d" (reg1), "=d" (reg2)
+ "0:\n"
+ EX_TABLE(0b, 0b)
+ : "+d" (reg0), "+d" (reg1), "=d" (reg2)
:
: "cc");
- if (reg2 & 0x6000000000000000ULL)
- *support = 1;
- else
- *support = 0;
-
+ *functions = (unsigned int)(reg2 >> 32);
return reg1;
}
+#endif
/**
- * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
- * support.
+ * ap_query_functions(): Query supported functions.
* @qid: The AP queue number
+ * @functions: Pointer to functions field.
*
- * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ * Returns
+ * 0 on success.
+ * -ENODEV if queue not valid.
+ * -EBUSY if device busy.
+ * -EINVAL if query function is not supported
*/
-int ap_4096_commands_available(ap_qid_t qid)
+static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
{
+#ifdef CONFIG_64BIT
struct ap_queue_status status;
- int i, support = 0;
- status = __ap_4096_commands_available(qid, &support);
+ int i;
+ status = __ap_query_functions(qid, functions);
for (i = 0; i < AP_MAX_RESET; i++) {
+ if (ap_queue_status_invalid_test(&status))
+ return -ENODEV;
+
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
- return support;
+ return 0;
case AP_RESPONSE_RESET_IN_PROGRESS:
case AP_RESPONSE_BUSY:
break;
@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid)
case AP_RESPONSE_DECONFIGURED:
case AP_RESPONSE_CHECKSTOPPED:
case AP_RESPONSE_INVALID_ADDRESS:
- return 0;
+ return -ENODEV;
case AP_RESPONSE_OTHERWISE_CHANGED:
break;
default:
@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid)
}
if (i < AP_MAX_RESET - 1) {
udelay(5);
- status = __ap_4096_commands_available(qid, &support);
+ status = __ap_query_functions(qid, functions);
}
}
- return support;
+ return -EBUSY;
+#else
+ return -EINVAL;
+#endif
+}
+
+/**
+ * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
+ * support.
+ * @qid: The AP queue number
+ *
+ * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ */
+int ap_4096_commands_available(ap_qid_t qid)
+{
+ unsigned int functions;
+
+ if (ap_query_functions(qid, &functions))
+ return 0;
+
+ return test_ap_facility(functions, 1) &&
+ test_ap_facility(functions, 2);
}
EXPORT_SYMBOL(ap_4096_commands_available);
@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused)
struct device *dev;
ap_qid_t qid;
int queue_depth, device_type;
+ unsigned int device_functions;
int rc, i;
if (ap_select_domain() != 0)
@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->list);
setup_timer(&ap_dev->timeout, ap_request_timeout,
(unsigned long) ap_dev);
- if (device_type == 0) {
+ switch (device_type) {
+ case 0:
if (ap_probe_device_type(ap_dev)) {
kfree(ap_dev);
continue;
}
- }
- else
+ break;
+ case 10:
+ if (ap_query_functions(qid, &device_functions)) {
+ kfree(ap_dev);
+ continue;
+ }
+ if (test_ap_facility(device_functions, 3))
+ ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
+ else if (test_ap_facility(device_functions, 4))
+ ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
+ else {
+ kfree(ap_dev);
+ continue;
+ }
+ break;
+ default:
ap_dev->device_type = device_type;
+ }
ap_dev->device.bus = &ap_bus_type;
ap_dev->device.parent = ap_root_device;
@@ -1227,18 +1271,16 @@ ap_config_timeout(unsigned long ptr)
}
/**
- * ap_schedule_poll_timer(): Schedule poll timer.
+ * __ap_schedule_poll_timer(): Schedule poll timer.
*
* Set up the timer to run the poll tasklet
*/
-static inline void ap_schedule_poll_timer(void)
+static inline void __ap_schedule_poll_timer(void)
{
ktime_t hr_time;
spin_lock_bh(&ap_poll_timer_lock);
- if (ap_using_interrupts() || ap_suspend_flag)
- goto out;
- if (hrtimer_is_queued(&ap_poll_timer))
+ if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
goto out;
if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
hr_time = ktime_set(0, poll_timeout);
@@ -1250,6 +1292,18 @@ out:
}
/**
+ * ap_schedule_poll_timer(): Schedule poll timer.
+ *
+ * Set up the timer to run the poll tasklet
+ */
+static inline void ap_schedule_poll_timer(void)
+{
+ if (ap_using_interrupts())
+ return;
+ __ap_schedule_poll_timer();
+}
+
+/**
* ap_poll_read(): Receive pending reply messages from an AP device.
* @ap_dev: pointer to the AP device
* @flags: pointer to control flags, bit 2^0 is set if another poll is
@@ -1330,8 +1384,9 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
*flags |= 1;
*flags |= 2;
break;
- case AP_RESPONSE_Q_FULL:
case AP_RESPONSE_RESET_IN_PROGRESS:
+ __ap_schedule_poll_timer();
+ case AP_RESPONSE_Q_FULL:
*flags |= 2;
break;
case AP_RESPONSE_MESSAGE_TOO_BIG:
@@ -1497,6 +1552,8 @@ static void ap_reset(struct ap_device *ap_dev)
rc = ap_init_queue(ap_dev->qid);
if (rc == -ENODEV)
ap_dev->unregistered = 1;
+ else
+ __ap_schedule_poll_timer();
}
static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 08b9738..d960a63 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -6,6 +6,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com>
+ * Holger Dengler <hd@linux.vnet.ibm.com>
*
* Adjunct processor bus header file.
*
@@ -72,7 +73,26 @@ struct ap_queue_status {
unsigned int int_enabled : 1;
unsigned int response_code : 8;
unsigned int pad2 : 16;
-};
+} __packed;
+
+#define AP_QUEUE_STATUS_INVALID \
+ { 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
+
+static inline
+int ap_queue_status_invalid_test(struct ap_queue_status *status)
+{
+ struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
+ return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
+}
+
+#define MAX_AP_FACILITY 31
+
+static inline int test_ap_facility(unsigned int function, unsigned int nr)
+{
+ if (nr > MAX_AP_FACILITY)
+ return 0;
+ return function & (unsigned int)(0x80000000 >> nr);
+}
#define AP_RESPONSE_NORMAL 0x00
#define AP_RESPONSE_Q_NOT_AVAIL 0x01
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 8e65447..88ad33e 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -36,7 +36,7 @@
#include <linux/seq_file.h>
#include <linux/compat.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <linux/hw_random.h>
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 2176d00..da171b5 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_mono.c b/drivers/s390/crypto/zcrypt_mono.c
index 44253fd..eb313c3 100644
--- a/drivers/s390/crypto/zcrypt_mono.c
+++ b/drivers/s390/crypto/zcrypt_mono.c
@@ -32,7 +32,7 @@
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 1afb69c..d84816f 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index aa4c050..bdbdbe1 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -30,7 +30,7 @@
#include <linux/init.h>
#include <linux/gfp.h>
#include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 4f85eb7..dd47378 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -31,7 +31,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 481037d..b1e8f6c 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -20,6 +20,7 @@
#include <linux/virtio_console.h>
#include <linux/interrupt.h>
#include <linux/virtio_ring.h>
+#include <linux/export.h>
#include <linux/pfn.h>
#include <asm/io.h>
#include <asm/kvm_para.h>
@@ -33,7 +34,7 @@
* The pointer to our (page) of device descriptions.
*/
static void *kvm_devices;
-struct work_struct hotplug_work;
+static struct work_struct hotplug_work;
struct kvm_device {
struct virtio_device vdev;
@@ -334,10 +335,10 @@ static void scan_devices(void)
*/
static int match_desc(struct device *dev, void *data)
{
- if ((ulong)to_kvmdev(dev_to_virtio(dev))->desc == (ulong)data)
- return 1;
+ struct virtio_device *vdev = dev_to_virtio(dev);
+ struct kvm_device *kdev = to_kvmdev(vdev);
- return 0;
+ return kdev->desc == data;
}
/*
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index fa80ba1..9b66d2d 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -4,7 +4,7 @@ menu "S/390 network device drivers"
config LCS
def_tristate m
prompt "Lan Channel Station Interface"
- depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
+ depends on CCW && NETDEVICES && (ETHERNET || TR || FDDI)
help
Select this option if you want to use LCS networking on IBM System z.
This device driver supports Token Ring (IEEE 802.5),
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index f1fa248..b41fae3 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -63,7 +63,6 @@
#define KMSG_COMPONENT "claw"
-#include <linux/kernel_stat.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
#include <asm/debug.h>
@@ -291,6 +290,7 @@ static struct ccw_driver claw_ccw_driver = {
.ids = claw_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
+ .int_class = IOINT_CLW,
};
static ssize_t
@@ -645,7 +645,6 @@ claw_irq_handler(struct ccw_device *cdev,
struct claw_env *p_env;
struct chbk *p_ch_r=NULL;
- kstat_cpu(smp_processor_id()).irqs[IOINT_CLW]++;
CLAW_DBF_TEXT(4, trace, "clawirq");
/* Bypass all 'unsolicited interrupts' */
privptr = dev_get_drvdata(&cdev->dev);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 426787e..5cb93a8 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -24,7 +24,6 @@
#define KMSG_COMPONENT "ctcm"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -1203,7 +1202,6 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
int cstat;
int dstat;
- kstat_cpu(smp_processor_id()).irqs[IOINT_CTC]++;
CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
"Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev));
@@ -1769,6 +1767,7 @@ static struct ccw_driver ctcm_ccw_driver = {
.ids = ctcm_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
+ .int_class = IOINT_CTC,
};
static struct ccwgroup_driver ctcm_group_driver = {
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index 5336120..1fa07b0 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -12,6 +12,7 @@
#ifndef _CTC_MPC_H_
#define _CTC_MPC_H_
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include "fsm.h"
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
index 8305319..650aec1 100644
--- a/drivers/s390/net/ctcm_sysfs.c
+++ b/drivers/s390/net/ctcm_sysfs.c
@@ -159,7 +159,7 @@ static ssize_t ctcm_proto_store(struct device *dev,
return count;
}
-const char *ctcm_type[] = {
+static const char *ctcm_type[] = {
"not a channel",
"CTC/A",
"FICON channel",
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index 1e8b235..a4510cf 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -8,7 +8,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/**
* Define this to get debugging messages.
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index c3b8064..863fc21 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -26,7 +26,6 @@
#define KMSG_COMPONENT "lcs"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/if.h>
#include <linux/netdevice.h>
@@ -51,7 +50,7 @@
#include "lcs.h"
-#if !defined(CONFIG_NET_ETHERNET) && \
+#if !defined(CONFIG_ETHERNET) && \
!defined(CONFIG_TR) && !defined(CONFIG_FDDI)
#error Cannot compile lcs.c without some net devices switched on.
#endif
@@ -1399,7 +1398,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
int rc, index;
int cstat, dstat;
- kstat_cpu(smp_processor_id()).irqs[IOINT_LCS]++;
if (lcs_check_irb_error(cdev, irb))
return;
@@ -1636,7 +1634,7 @@ lcs_startlan_auto(struct lcs_card *card)
int rc;
LCS_DBF_TEXT(2, trace, "strtauto");
-#ifdef CONFIG_NET_ETHERNET
+#ifdef CONFIG_ETHERNET
card->lan_type = LCS_FRAME_TYPE_ENET;
rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP);
if (rc == 0)
@@ -1972,7 +1970,7 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
-const char *lcs_type[] = {
+static const char *lcs_type[] = {
"not a channel",
"2216 parallel",
"2216 channel",
@@ -2122,7 +2120,7 @@ static const struct net_device_ops lcs_mc_netdev_ops = {
.ndo_stop = lcs_stop_device,
.ndo_get_stats = lcs_getstats,
.ndo_start_xmit = lcs_start_xmit,
- .ndo_set_multicast_list = lcs_set_multicast_list,
+ .ndo_set_rx_mode = lcs_set_multicast_list,
};
static int
@@ -2168,7 +2166,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
goto netdev_out;
}
switch (card->lan_type) {
-#ifdef CONFIG_NET_ETHERNET
+#ifdef CONFIG_ETHERNET
case LCS_FRAME_TYPE_ENET:
card->lan_type_trans = eth_type_trans;
dev = alloc_etherdev(0);
@@ -2399,6 +2397,7 @@ static struct ccw_driver lcs_ccw_driver = {
.ids = lcs_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
+ .int_class = IOINT_LCS,
};
/**
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3251333..b6a6356 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1994,6 +1994,8 @@ static struct net_device *netiucv_init_netdevice(char *username)
netiucv_setup_netdevice);
if (!dev)
return NULL;
+ if (dev_alloc_name(dev, dev->name) < 0)
+ goto out_netdev;
privptr = netdev_priv(dev);
privptr->fsm = init_fsm("netiucvdev", dev_state_names,
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d3cee33..4abc79d 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -110,6 +110,10 @@ struct qeth_perf_stats {
unsigned int sc_dp_p;
unsigned int sc_p_dp;
+ /* qdio_cq_handler: number of times called, time spent in */
+ __u64 cq_start_time;
+ unsigned int cq_cnt;
+ unsigned int cq_time;
/* qdio_input_handler: number of times called, time spent in */
__u64 inbound_start_time;
unsigned int inbound_cnt;
@@ -213,6 +217,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
*/
#define QETH_TX_TIMEOUT 100 * HZ
#define QETH_RCD_TIMEOUT 60 * HZ
+#define QETH_RECLAIM_WORK_TIME HZ
#define QETH_HEADER_SIZE 32
#define QETH_MAX_PORTNO 15
@@ -231,7 +236,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
#define QETH_IN_BUF_COUNT_MAX 128
#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
- ((card)->qdio.in_buf_pool.buf_count / 2)
+ ((card)->qdio.in_buf_pool.buf_count / 2)
/* buffers we have to be behind before we get a PCI */
#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
@@ -260,6 +265,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
/* large receive scatter gather copy break */
#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+#define QETH_RX_PULL_LEN 256
struct qeth_hdr_layer3 {
__u8 id;
@@ -375,6 +381,21 @@ enum qeth_qdio_buffer_states {
* outbound: filled by driver; owned by hardware in order to be sent
*/
QETH_QDIO_BUF_PRIMED,
+ /*
+ * inbound: not applicable
+ * outbound: identified to be pending in TPQ
+ */
+ QETH_QDIO_BUF_PENDING,
+ /*
+ * inbound: not applicable
+ * outbound: found in completion queue
+ */
+ QETH_QDIO_BUF_IN_CQ,
+ /*
+ * inbound: not applicable
+ * outbound: handled via transfer pending / completion queue
+ */
+ QETH_QDIO_BUF_HANDLED_DELAYED,
};
enum qeth_qdio_info_states {
@@ -399,6 +420,7 @@ struct qeth_qdio_buffer {
struct qdio_buffer *buffer;
/* the buffer pool entry currently associated to this buffer */
struct qeth_buffer_pool_entry *pool_entry;
+ struct sk_buff *rx_skb;
};
struct qeth_qdio_q {
@@ -412,8 +434,11 @@ struct qeth_qdio_out_buffer {
atomic_t state;
int next_element_to_fill;
struct sk_buff_head skb_list;
- struct list_head ctx_list;
int is_header[16];
+
+ struct qaob *aob;
+ struct qeth_qdio_out_q *q;
+ struct qeth_qdio_out_buffer *next_pending;
};
struct qeth_card;
@@ -426,7 +451,8 @@ enum qeth_out_q_states {
struct qeth_qdio_out_q {
struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
- struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+ struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
+ struct qdio_outbuf_state *bufstates; /* convenience pointer */
int queue_no;
struct qeth_card *card;
atomic_t state;
@@ -447,7 +473,9 @@ struct qeth_qdio_out_q {
struct qeth_qdio_info {
atomic_t state;
/* input */
+ int no_in_queues;
struct qeth_qdio_q *in_q;
+ struct qeth_qdio_q *c_q;
struct qeth_qdio_buffer_pool in_buf_pool;
struct qeth_qdio_buffer_pool init_pool;
int in_buf_size;
@@ -455,6 +483,7 @@ struct qeth_qdio_info {
/* output */
int no_out_queues;
struct qeth_qdio_out_q **out_qs;
+ struct qdio_outbuf_state *out_bufstates;
/* priority queueing */
int do_prio_queueing;
@@ -526,6 +555,12 @@ enum qeth_cmd_buffer_state {
BUF_STATE_PROCESSED,
};
+enum qeth_cq {
+ QETH_CQ_DISABLED = 0,
+ QETH_CQ_ENABLED = 1,
+ QETH_CQ_NOTAVAILABLE = 2,
+};
+
struct qeth_ipato {
int enabled;
int invert4;
@@ -650,6 +685,8 @@ struct qeth_card_options {
int rx_sg_cb;
enum qeth_ipa_isolation_modes isolation;
int sniffer;
+ enum qeth_cq cq;
+ char hsuid[9];
};
/*
@@ -720,7 +757,7 @@ struct qeth_card {
wait_queue_head_t wait_q;
spinlock_t vlanlock;
spinlock_t mclock;
- struct vlan_group *vlangrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct list_head vid_list;
struct list_head mc_list;
struct work_struct kernel_thread_starter;
@@ -747,6 +784,8 @@ struct qeth_card {
struct mutex discipline_mutex;
struct napi_struct napi;
struct qeth_rx rx;
+ struct delayed_work buffer_reclaim_work;
+ int reclaim_index;
};
struct qeth_card_list_struct {
@@ -812,6 +851,7 @@ int qeth_core_create_device_attributes(struct device *);
void qeth_core_remove_device_attributes(struct device *);
int qeth_core_create_osn_attributes(struct device *);
void qeth_core_remove_osn_attributes(struct device *);
+void qeth_buffer_reclaim_work(struct work_struct *);
/* exports for qeth discipline device drivers */
extern struct qeth_card_list_struct qeth_core_card_list;
@@ -840,7 +880,7 @@ int qeth_check_qdio_errors(struct qeth_card *, struct qdio_buffer *,
unsigned int, const char *);
void qeth_queue_input_buffer(struct qeth_card *, int);
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
- struct qdio_buffer *, struct qdio_buffer_element **, int *,
+ struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **);
void qeth_schedule_recovery(struct qeth_card *);
void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
@@ -887,6 +927,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
int qeth_set_access_ctrl_online(struct qeth_card *card);
int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
+int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index dd08f7b..55f6488 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -21,6 +21,7 @@
#include <linux/mii.h>
#include <linux/kthread.h>
#include <linux/slab.h>
+#include <net/iucv/af_iucv.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
@@ -44,6 +45,7 @@ struct qeth_card_list_struct qeth_core_card_list;
EXPORT_SYMBOL_GPL(qeth_core_card_list);
struct kmem_cache *qeth_core_header_cache;
EXPORT_SYMBOL_GPL(qeth_core_header_cache);
+static struct kmem_cache *qeth_qdio_outbuf_cache;
static struct device *qeth_core_root_dev;
static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY;
@@ -56,6 +58,14 @@ static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32);
static void qeth_free_buffer_pool(struct qeth_card *);
static int qeth_qdio_establish(struct qeth_card *);
+static void qeth_free_qdio_buffers(struct qeth_card *);
+static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ enum iucv_tx_notify notification);
+static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ enum qeth_qdio_buffer_states newbufstate);
static inline const char *qeth_get_cardname(struct qeth_card *card)
@@ -199,7 +209,7 @@ static int qeth_alloc_buffer_pool(struct qeth_card *card)
QETH_CARD_TEXT(card, 5, "alocpool");
for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
- pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+ pool_entry = kzalloc(sizeof(*pool_entry), GFP_KERNEL);
if (!pool_entry) {
qeth_free_buffer_pool(card);
return -ENOMEM;
@@ -239,6 +249,196 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
}
EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
+static inline int qeth_cq_init(struct qeth_card *card)
+{
+ int rc;
+
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ QETH_DBF_TEXT(SETUP, 2, "cqinit");
+ memset(card->qdio.c_q->qdio_bufs, 0,
+ QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+ card->qdio.c_q->next_buf_to_init = 127;
+ rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT,
+ card->qdio.no_in_queues - 1, 0,
+ 127);
+ if (rc) {
+ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+ goto out;
+ }
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+static inline int qeth_alloc_cq(struct qeth_card *card)
+{
+ int rc;
+
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ int i;
+ struct qdio_outbuf_state *outbuf_states;
+
+ QETH_DBF_TEXT(SETUP, 2, "cqon");
+ card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q),
+ GFP_KERNEL);
+ if (!card->qdio.c_q) {
+ rc = -1;
+ goto kmsg_out;
+ }
+ QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *));
+
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
+ card->qdio.c_q->bufs[i].buffer =
+ &card->qdio.c_q->qdio_bufs[i];
+ }
+
+ card->qdio.no_in_queues = 2;
+
+ card->qdio.out_bufstates = (struct qdio_outbuf_state *)
+ kzalloc(card->qdio.no_out_queues *
+ QDIO_MAX_BUFFERS_PER_Q *
+ sizeof(struct qdio_outbuf_state), GFP_KERNEL);
+ outbuf_states = card->qdio.out_bufstates;
+ if (outbuf_states == NULL) {
+ rc = -1;
+ goto free_cq_out;
+ }
+ for (i = 0; i < card->qdio.no_out_queues; ++i) {
+ card->qdio.out_qs[i]->bufstates = outbuf_states;
+ outbuf_states += QDIO_MAX_BUFFERS_PER_Q;
+ }
+ } else {
+ QETH_DBF_TEXT(SETUP, 2, "nocq");
+ card->qdio.c_q = NULL;
+ card->qdio.no_in_queues = 1;
+ }
+ QETH_DBF_TEXT_(SETUP, 2, "iqc%d", card->qdio.no_in_queues);
+ rc = 0;
+out:
+ return rc;
+free_cq_out:
+ kfree(card->qdio.c_q);
+ card->qdio.c_q = NULL;
+kmsg_out:
+ dev_err(&card->gdev->dev, "Failed to create completion queue\n");
+ goto out;
+}
+
+static inline void qeth_free_cq(struct qeth_card *card)
+{
+ if (card->qdio.c_q) {
+ --card->qdio.no_in_queues;
+ kfree(card->qdio.c_q);
+ card->qdio.c_q = NULL;
+ }
+ kfree(card->qdio.out_bufstates);
+ card->qdio.out_bufstates = NULL;
+}
+
+static inline enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
+ int delayed) {
+ enum iucv_tx_notify n;
+
+ switch (sbalf15) {
+ case 0:
+ n = delayed ? TX_NOTIFY_DELAYED_OK : TX_NOTIFY_OK;
+ break;
+ case 4:
+ case 16:
+ case 17:
+ case 18:
+ n = delayed ? TX_NOTIFY_DELAYED_UNREACHABLE :
+ TX_NOTIFY_UNREACHABLE;
+ break;
+ default:
+ n = delayed ? TX_NOTIFY_DELAYED_GENERALERROR :
+ TX_NOTIFY_GENERALERROR;
+ break;
+ }
+
+ return n;
+}
+
+static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
+ int bidx, int forced_cleanup)
+{
+ if (q->bufs[bidx]->next_pending != NULL) {
+ struct qeth_qdio_out_buffer *head = q->bufs[bidx];
+ struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending;
+
+ while (c) {
+ if (forced_cleanup ||
+ atomic_read(&c->state) ==
+ QETH_QDIO_BUF_HANDLED_DELAYED) {
+ struct qeth_qdio_out_buffer *f = c;
+ QETH_CARD_TEXT(f->q->card, 5, "fp");
+ QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f);
+ /* release here to avoid interleaving between
+ outbound tasklet and inbound tasklet
+ regarding notifications and lifecycle */
+ qeth_release_skbs(c);
+
+ c = f->next_pending;
+ BUG_ON(head->next_pending != f);
+ head->next_pending = c;
+ kmem_cache_free(qeth_qdio_outbuf_cache, f);
+ } else {
+ head = c;
+ c = c->next_pending;
+ }
+
+ }
+ }
+}
+
+
+static inline void qeth_qdio_handle_aob(struct qeth_card *card,
+ unsigned long phys_aob_addr) {
+ struct qaob *aob;
+ struct qeth_qdio_out_buffer *buffer;
+ enum iucv_tx_notify notification;
+
+ aob = (struct qaob *) phys_to_virt(phys_aob_addr);
+ QETH_CARD_TEXT(card, 5, "haob");
+ QETH_CARD_TEXT_(card, 5, "%lx", phys_aob_addr);
+ buffer = (struct qeth_qdio_out_buffer *) aob->user1;
+ QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
+
+ BUG_ON(buffer == NULL);
+
+ if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
+ QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
+ notification = TX_NOTIFY_OK;
+ } else {
+ BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
+
+ atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
+ notification = TX_NOTIFY_DELAYED_OK;
+ }
+
+ if (aob->aorc != 0) {
+ QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
+ notification = qeth_compute_cq_notification(aob->aorc, 1);
+ }
+ qeth_notify_skbs(buffer->q, buffer, notification);
+
+ buffer->aob = NULL;
+ qeth_clear_output_buffer(buffer->q, buffer,
+ QETH_QDIO_BUF_HANDLED_DELAYED);
+ /* from here on: do not touch buffer anymore */
+ qdio_release_aob(aob);
+}
+
+static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue)
+{
+ return card->options.cq == QETH_CQ_ENABLED &&
+ card->qdio.c_q != NULL &&
+ queue != 0 &&
+ queue == card->qdio.no_in_queues - 1;
+}
+
+
static int qeth_issue_next_read(struct qeth_card *card)
{
int rc;
@@ -589,7 +789,7 @@ static int qeth_setup_channel(struct qeth_channel *channel)
QETH_DBF_TEXT(SETUP, 2, "setupch");
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
channel->iob[cnt].data =
- kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+ kzalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
if (channel->iob[cnt].data == NULL)
break;
channel->iob[cnt].state = BUF_STATE_FREE;
@@ -883,22 +1083,60 @@ out:
return;
}
-static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
- struct qeth_qdio_out_buffer *buf)
+static void qeth_notify_skbs(struct qeth_qdio_out_q *q,
+ struct qeth_qdio_out_buffer *buf,
+ enum iucv_tx_notify notification)
{
- int i;
struct sk_buff *skb;
- /* is PCI flag set on buffer? */
- if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
- atomic_dec(&queue->set_pci_flags_count);
+ if (skb_queue_empty(&buf->skb_list))
+ goto out;
+ skb = skb_peek(&buf->skb_list);
+ while (skb) {
+ QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification);
+ QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb);
+ if (skb->protocol == ETH_P_AF_IUCV) {
+ if (skb->sk) {
+ struct iucv_sock *iucv = iucv_sk(skb->sk);
+ iucv->sk_txnotify(skb, notification);
+ }
+ }
+ if (skb_queue_is_last(&buf->skb_list, skb))
+ skb = NULL;
+ else
+ skb = skb_queue_next(&buf->skb_list, skb);
+ }
+out:
+ return;
+}
+
+static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
+{
+ struct sk_buff *skb;
skb = skb_dequeue(&buf->skb_list);
while (skb) {
+ QETH_CARD_TEXT(buf->q->card, 5, "skbr");
+ QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb);
atomic_dec(&skb->users);
dev_kfree_skb_any(skb);
skb = skb_dequeue(&buf->skb_list);
}
+}
+
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ enum qeth_qdio_buffer_states newbufstate)
+{
+ int i;
+
+ /* is PCI flag set on buffer? */
+ if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
+ atomic_dec(&queue->set_pci_flags_count);
+
+ if (newbufstate == QETH_QDIO_BUF_EMPTY) {
+ qeth_release_skbs(buf);
+ }
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
if (buf->buffer->element[i].addr && buf->is_header[i])
kmem_cache_free(qeth_core_header_cache,
@@ -912,21 +1150,36 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
buf->buffer->element[15].eflags = 0;
buf->buffer->element[15].sflags = 0;
buf->next_element_to_fill = 0;
- atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+ atomic_set(&buf->state, newbufstate);
+}
+
+static void qeth_clear_outq_buffers(struct qeth_qdio_out_q *q, int free)
+{
+ int j;
+
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+ if (!q->bufs[j])
+ continue;
+ qeth_cleanup_handled_pending(q, j, free);
+ qeth_clear_output_buffer(q, q->bufs[j], QETH_QDIO_BUF_EMPTY);
+ if (free) {
+ kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]);
+ q->bufs[j] = NULL;
+ }
+ }
}
void qeth_clear_qdio_buffers(struct qeth_card *card)
{
- int i, j;
+ int i;
QETH_CARD_TEXT(card, 2, "clearqdbf");
/* clear outbound buffers to free skbs */
- for (i = 0; i < card->qdio.no_out_queues; ++i)
+ for (i = 0; i < card->qdio.no_out_queues; ++i) {
if (card->qdio.out_qs[i]) {
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
- qeth_clear_output_buffer(card->qdio.out_qs[i],
- &card->qdio.out_qs[i]->bufs[j]);
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 0);
}
+ }
}
EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers);
@@ -950,6 +1203,11 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
QETH_QDIO_UNINITIALIZED)
return;
+
+ qeth_free_cq(card);
+ cancel_delayed_work_sync(&card->buffer_reclaim_work);
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+ kfree_skb(card->qdio.in_q->bufs[j].rx_skb);
kfree(card->qdio.in_q);
card->qdio.in_q = NULL;
/* inbound buffer pool */
@@ -957,9 +1215,7 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
/* free outbound qdio_qs */
if (card->qdio.out_qs) {
for (i = 0; i < card->qdio.no_out_queues; ++i) {
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
- qeth_clear_output_buffer(card->qdio.out_qs[i],
- &card->qdio.out_qs[i]->bufs[j]);
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
kfree(card->qdio.out_qs[i]);
}
kfree(card->qdio.out_qs);
@@ -995,27 +1251,29 @@ static void qeth_get_channel_path_desc(struct qeth_card *card)
ccwdev = card->data.ccwdev;
chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
if (chp_dsc != NULL) {
- /* CHPP field bit 6 == 1 -> single queue */
- if ((chp_dsc->chpp & 0x02) == 0x02) {
- if ((atomic_read(&card->qdio.state) !=
- QETH_QDIO_UNINITIALIZED) &&
- (card->qdio.no_out_queues == 4))
- /* change from 4 to 1 outbound queues */
- qeth_free_qdio_buffers(card);
- card->qdio.no_out_queues = 1;
- if (card->qdio.default_out_queue != 0)
- dev_info(&card->gdev->dev,
+ if (card->info.type != QETH_CARD_TYPE_IQD) {
+ /* CHPP field bit 6 == 1 -> single queue */
+ if ((chp_dsc->chpp & 0x02) == 0x02) {
+ if ((atomic_read(&card->qdio.state) !=
+ QETH_QDIO_UNINITIALIZED) &&
+ (card->qdio.no_out_queues == 4))
+ /* change from 4 to 1 outbound queues */
+ qeth_free_qdio_buffers(card);
+ card->qdio.no_out_queues = 1;
+ if (card->qdio.default_out_queue != 0)
+ dev_info(&card->gdev->dev,
"Priority Queueing not supported\n");
- card->qdio.default_out_queue = 0;
- } else {
- if ((atomic_read(&card->qdio.state) !=
- QETH_QDIO_UNINITIALIZED) &&
- (card->qdio.no_out_queues == 1)) {
- /* change from 1 to 4 outbound queues */
- qeth_free_qdio_buffers(card);
- card->qdio.default_out_queue = 2;
+ card->qdio.default_out_queue = 0;
+ } else {
+ if ((atomic_read(&card->qdio.state) !=
+ QETH_QDIO_UNINITIALIZED) &&
+ (card->qdio.no_out_queues == 1)) {
+ /* change from 1 to 4 outbound queues */
+ qeth_free_qdio_buffers(card);
+ card->qdio.default_out_queue = 2;
+ }
+ card->qdio.no_out_queues = 4;
}
- card->qdio.no_out_queues = 4;
}
card->info.func_level = 0x4100 + chp_dsc->desc;
kfree(chp_dsc);
@@ -1051,6 +1309,7 @@ static void qeth_set_intial_options(struct qeth_card *card)
card->options.performance_stats = 0;
card->options.rx_sg_cb = QETH_RX_SG_CB;
card->options.isolation = ISOLATION_MODE_NONE;
+ card->options.cq = QETH_CQ_DISABLED;
}
static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
@@ -1097,7 +1356,6 @@ static int qeth_setup_card(struct qeth_card *card)
card->dev = NULL;
spin_lock_init(&card->vlanlock);
spin_lock_init(&card->mclock);
- card->vlangrp = NULL;
spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock);
@@ -1120,6 +1378,7 @@ static int qeth_setup_card(struct qeth_card *card)
card->ipato.invert6 = 0;
/* init QDIO stuff */
qeth_init_qdio_info(card);
+ INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
return 0;
}
@@ -1141,7 +1400,7 @@ static struct qeth_card *qeth_alloc_card(void)
if (!card)
goto out;
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_KERNEL);
if (!card->ip_tbd_list) {
QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
goto out_card;
@@ -1181,6 +1440,7 @@ static int qeth_determine_card_type(struct qeth_card *card)
card->info.type = known_devices[i][QETH_DEV_MODEL_IND];
card->qdio.no_out_queues =
known_devices[i][QETH_QUEUE_NO_IND];
+ card->qdio.no_in_queues = 1;
card->info.is_multicast_different =
known_devices[i][QETH_MULTICAST_IND];
qeth_get_channel_path_desc(card);
@@ -2028,6 +2288,37 @@ static int qeth_ulp_setup(struct qeth_card *card)
return rc;
}
+static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
+{
+ int rc;
+ struct qeth_qdio_out_buffer *newbuf;
+
+ rc = 0;
+ newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, GFP_ATOMIC);
+ if (!newbuf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ newbuf->buffer = &q->qdio_bufs[bidx];
+ skb_queue_head_init(&newbuf->skb_list);
+ lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
+ newbuf->q = q;
+ newbuf->aob = NULL;
+ newbuf->next_pending = q->bufs[bidx];
+ atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY);
+ q->bufs[bidx] = newbuf;
+ if (q->bufstates) {
+ q->bufstates[bidx].user = newbuf;
+ QETH_CARD_TEXT_(q->card, 2, "nbs%d", bidx);
+ QETH_CARD_TEXT_(q->card, 2, "%lx", (long) newbuf);
+ QETH_CARD_TEXT_(q->card, 2, "%lx",
+ (long) newbuf->next_pending);
+ }
+out:
+ return rc;
+}
+
+
static int qeth_alloc_qdio_buffers(struct qeth_card *card)
{
int i, j;
@@ -2038,52 +2329,63 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
return 0;
- card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
- GFP_KERNEL);
+ card->qdio.in_q = kzalloc(sizeof(struct qeth_qdio_q),
+ GFP_KERNEL);
if (!card->qdio.in_q)
goto out_nomem;
QETH_DBF_TEXT(SETUP, 2, "inq");
QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
/* give inbound qeth_qdio_buffers their qdio_buffers */
- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
card->qdio.in_q->bufs[i].buffer =
&card->qdio.in_q->qdio_bufs[i];
+ card->qdio.in_q->bufs[i].rx_skb = NULL;
+ }
/* inbound buffer pool */
if (qeth_alloc_buffer_pool(card))
goto out_freeinq;
+
/* outbound */
card->qdio.out_qs =
- kmalloc(card->qdio.no_out_queues *
+ kzalloc(card->qdio.no_out_queues *
sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
if (!card->qdio.out_qs)
goto out_freepool;
for (i = 0; i < card->qdio.no_out_queues; ++i) {
- card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+ card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q),
GFP_KERNEL);
if (!card->qdio.out_qs[i])
goto out_freeoutq;
QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *));
- memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
card->qdio.out_qs[i]->queue_no = i;
/* give outbound qeth_qdio_buffers their qdio_buffers */
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
- card->qdio.out_qs[i]->bufs[j].buffer =
- &card->qdio.out_qs[i]->qdio_bufs[j];
- skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
- skb_list);
- lockdep_set_class(
- &card->qdio.out_qs[i]->bufs[j].skb_list.lock,
- &qdio_out_skb_queue_key);
- INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+ BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+ if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
+ goto out_freeoutqbufs;
}
}
+
+ /* completion */
+ if (qeth_alloc_cq(card))
+ goto out_freeoutq;
+
return 0;
+out_freeoutqbufs:
+ while (j > 0) {
+ --j;
+ kmem_cache_free(qeth_qdio_outbuf_cache,
+ card->qdio.out_qs[i]->bufs[j]);
+ card->qdio.out_qs[i]->bufs[j] = NULL;
+ }
out_freeoutq:
- while (i > 0)
+ while (i > 0) {
kfree(card->qdio.out_qs[--i]);
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
+ }
kfree(card->qdio.out_qs);
card->qdio.out_qs = NULL;
out_freepool:
@@ -2354,6 +2656,12 @@ static int qeth_init_input_buffer(struct qeth_card *card,
struct qeth_buffer_pool_entry *pool_entry;
int i;
+ if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
+ buf->rx_skb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+ if (!buf->rx_skb)
+ return 1;
+ }
+
pool_entry = qeth_find_free_buffer_pool_entry(card);
if (!pool_entry)
return 1;
@@ -2400,13 +2708,21 @@ int qeth_init_qdio_queues(struct qeth_card *card)
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
return rc;
}
+
+ /* completion */
+ rc = qeth_cq_init(card);
+ if (rc) {
+ return rc;
+ }
+
/* outbound queue */
for (i = 0; i < card->qdio.no_out_queues; ++i) {
memset(card->qdio.out_qs[i]->qdio_bufs, 0,
QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
qeth_clear_output_buffer(card->qdio.out_qs[i],
- &card->qdio.out_qs[i]->bufs[j]);
+ card->qdio.out_qs[i]->bufs[j],
+ QETH_QDIO_BUF_EMPTY);
}
card->qdio.out_qs[i]->card = card;
card->qdio.out_qs[i]->next_buf_to_fill = 0;
@@ -2735,9 +3051,19 @@ int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf,
}
EXPORT_SYMBOL_GPL(qeth_check_qdio_errors);
+void qeth_buffer_reclaim_work(struct work_struct *work)
+{
+ struct qeth_card *card = container_of(work, struct qeth_card,
+ buffer_reclaim_work.work);
+
+ QETH_CARD_TEXT_(card, 2, "brw:%x", card->reclaim_index);
+ qeth_queue_input_buffer(card, card->reclaim_index);
+}
+
void qeth_queue_input_buffer(struct qeth_card *card, int index)
{
struct qeth_qdio_q *queue = card->qdio.in_q;
+ struct list_head *lh;
int count;
int i;
int rc;
@@ -2769,6 +3095,20 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
atomic_add_unless(&card->force_alloc_skb, -1, 0);
}
+ if (!count) {
+ i = 0;
+ list_for_each(lh, &card->qdio.in_buf_pool.entry_list)
+ i++;
+ if (i == card->qdio.in_buf_pool.buf_count) {
+ QETH_CARD_TEXT(card, 2, "qsarbw");
+ card->reclaim_index = index;
+ schedule_delayed_work(
+ &card->buffer_reclaim_work,
+ QETH_RECLAIM_WORK_TIME);
+ }
+ return;
+ }
+
/*
* according to old code it should be avoided to requeue all
* 128 buffers in order to benefit from PCI avoidance.
@@ -2788,8 +3128,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
qeth_get_micros() -
card->perf_stats.inbound_do_qdio_start_time;
if (rc) {
- dev_warn(&card->gdev->dev,
- "QDIO reported an error, rc=%i\n", rc);
QETH_CARD_TEXT(card, 2, "qinberr");
}
queue->next_buf_to_init = (queue->next_buf_to_init + count) %
@@ -2863,12 +3201,12 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
queue->card->perf_stats.sc_p_dp++;
queue->do_pack = 0;
/* flush packing buffers */
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
if ((atomic_read(&buffer->state) ==
QETH_QDIO_BUF_EMPTY) &&
(buffer->next_element_to_fill > 0)) {
atomic_set(&buffer->state,
- QETH_QDIO_BUF_PRIMED);
+ QETH_QDIO_BUF_PRIMED);
flush_count++;
queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) %
@@ -2879,6 +3217,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
return flush_count;
}
+
/*
* Called to flush a packing buffer if no more pci flags are on the queue.
* Checks if there is a packing buffer and prepares it to be flushed.
@@ -2888,7 +3227,7 @@ static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
{
struct qeth_qdio_out_buffer *buffer;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
(buffer->next_element_to_fill > 0)) {
/* it's a packing buffer */
@@ -2909,10 +3248,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
unsigned int qdio_flags;
for (i = index; i < index + count; ++i) {
- buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+ int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+ buf = queue->bufs[bidx];
buf->buffer->element[buf->next_element_to_fill - 1].eflags |=
SBAL_EFLAGS_LAST_ENTRY;
+ if (queue->bufstates)
+ queue->bufstates[bidx].user = buf;
+
if (queue->card->info.type == QETH_CARD_TYPE_IQD)
continue;
@@ -2964,6 +3307,9 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
if (rc == QDIO_ERROR_SIGA_TARGET)
return;
QETH_CARD_TEXT(queue->card, 2, "flushbuf");
+ QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no);
+ QETH_CARD_TEXT_(queue->card, 2, " idx%d", index);
+ QETH_CARD_TEXT_(queue->card, 2, " c%d", count);
QETH_CARD_TEXT_(queue->card, 2, " err%d", rc);
/* this must not happen under normal circumstances. if it
@@ -3025,14 +3371,120 @@ void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
}
EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
+int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
+{
+ int rc;
+
+ if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
+ rc = -1;
+ goto out;
+ } else {
+ if (card->options.cq == cq) {
+ rc = 0;
+ goto out;
+ }
+
+ if (card->state != CARD_STATE_DOWN &&
+ card->state != CARD_STATE_RECOVER) {
+ rc = -1;
+ goto out;
+ }
+
+ qeth_free_qdio_buffers(card);
+ card->options.cq = cq;
+ rc = 0;
+ }
+out:
+ return rc;
+
+}
+EXPORT_SYMBOL_GPL(qeth_configure_cq);
+
+
+static void qeth_qdio_cq_handler(struct qeth_card *card,
+ unsigned int qdio_err,
+ unsigned int queue, int first_element, int count) {
+ struct qeth_qdio_q *cq = card->qdio.c_q;
+ int i;
+ int rc;
+
+ if (!qeth_is_cq(card, queue))
+ goto out;
+
+ QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element);
+ QETH_CARD_TEXT_(card, 5, "qcqhc%d", count);
+ QETH_CARD_TEXT_(card, 5, "qcqherr%d", qdio_err);
+
+ if (qdio_err) {
+ netif_stop_queue(card->dev);
+ qeth_schedule_recovery(card);
+ goto out;
+ }
+
+ if (card->options.performance_stats) {
+ card->perf_stats.cq_cnt++;
+ card->perf_stats.cq_start_time = qeth_get_micros();
+ }
+
+ for (i = first_element; i < first_element + count; ++i) {
+ int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+ struct qdio_buffer *buffer = &cq->qdio_bufs[bidx];
+ int e;
+
+ e = 0;
+ while (buffer->element[e].addr) {
+ unsigned long phys_aob_addr;
+
+ phys_aob_addr = (unsigned long) buffer->element[e].addr;
+ qeth_qdio_handle_aob(card, phys_aob_addr);
+ buffer->element[e].addr = NULL;
+ buffer->element[e].eflags = 0;
+ buffer->element[e].sflags = 0;
+ buffer->element[e].length = 0;
+
+ ++e;
+ }
+
+ buffer->element[15].eflags = 0;
+ buffer->element[15].sflags = 0;
+ }
+ rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, queue,
+ card->qdio.c_q->next_buf_to_init,
+ count);
+ if (rc) {
+ dev_warn(&card->gdev->dev,
+ "QDIO reported an error, rc=%i\n", rc);
+ QETH_CARD_TEXT(card, 2, "qcqherr");
+ }
+ card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+ + count) % QDIO_MAX_BUFFERS_PER_Q;
+
+ netif_wake_queue(card->dev);
+
+ if (card->options.performance_stats) {
+ int delta_t = qeth_get_micros();
+ delta_t -= card->perf_stats.cq_start_time;
+ card->perf_stats.cq_time += delta_t;
+ }
+out:
+ return;
+}
+
void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
- unsigned int queue, int first_element, int count,
+ unsigned int queue, int first_elem, int count,
unsigned long card_ptr)
{
struct qeth_card *card = (struct qeth_card *)card_ptr;
- if (qdio_err)
+ QETH_CARD_TEXT_(card, 2, "qihq%d", queue);
+ QETH_CARD_TEXT_(card, 2, "qiec%d", qdio_err);
+
+ if (qeth_is_cq(card, queue))
+ qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count);
+ else if (qdio_err)
qeth_schedule_recovery(card);
+
+
}
EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
@@ -3058,9 +3510,45 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
qeth_get_micros();
}
for (i = first_element; i < (first_element + count); ++i) {
- buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+ int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+ buffer = queue->bufs[bidx];
qeth_handle_send_error(card, buffer, qdio_error);
- qeth_clear_output_buffer(queue, buffer);
+
+ if (queue->bufstates &&
+ (queue->bufstates[bidx].flags &
+ QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
+ BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+
+ if (atomic_cmpxchg(&buffer->state,
+ QETH_QDIO_BUF_PRIMED,
+ QETH_QDIO_BUF_PENDING) ==
+ QETH_QDIO_BUF_PRIMED) {
+ qeth_notify_skbs(queue, buffer,
+ TX_NOTIFY_PENDING);
+ }
+ buffer->aob = queue->bufstates[bidx].aob;
+ QETH_CARD_TEXT_(queue->card, 5, "pel%d", bidx);
+ QETH_CARD_TEXT(queue->card, 5, "aob");
+ QETH_CARD_TEXT_(queue->card, 5, "%lx",
+ virt_to_phys(buffer->aob));
+ BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q);
+ if (qeth_init_qdio_out_buf(queue, bidx)) {
+ QETH_CARD_TEXT(card, 2, "outofbuf");
+ qeth_schedule_recovery(card);
+ }
+ } else {
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ enum iucv_tx_notify n;
+
+ n = qeth_compute_cq_notification(
+ buffer->buffer->element[15].sflags, 0);
+ qeth_notify_skbs(queue, buffer, n);
+ }
+
+ qeth_clear_output_buffer(queue, buffer,
+ QETH_QDIO_BUF_EMPTY);
+ }
+ qeth_cleanup_handled_pending(queue, bidx, 0);
}
atomic_sub(count, &queue->used_buffers);
/* check if we need to do something on this outbound queue */
@@ -3205,7 +3693,8 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
frag = &skb_shinfo(skb)->frags[cnt];
- buffer->element[element].addr = (char *)page_to_phys(frag->page)
+ buffer->element[element].addr = (char *)
+ page_to_phys(skb_frag_page(frag))
+ frag->page_offset;
buffer->element[element].length = frag->size;
buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG;
@@ -3292,7 +3781,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
/* ... now we've got the queue */
index = queue->next_buf_to_fill;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
/*
* check if buffer is empty to make sure that we do not 'overtake'
* ourselves and try to fill a buffer that is already primed
@@ -3326,7 +3815,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
start_index = queue->next_buf_to_fill;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
/*
* check if buffer is empty to make sure that we do not 'overtake'
* ourselves and try to fill a buffer that is already primed
@@ -3348,7 +3837,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) %
QDIO_MAX_BUFFERS_PER_Q;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
/* we did a step forward, so check buffer state
* again */
if (atomic_read(&buffer->state) !=
@@ -3833,7 +4322,7 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata)
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
struct qeth_snmp_ureq *ureq;
- int req_len;
+ unsigned int req_len;
struct qeth_arp_query_info qinfo = {0, };
int rc = 0;
@@ -3849,6 +4338,10 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata)
/* skip 4 bytes (data_len struct member) to get req_len */
if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
return -EFAULT;
+ if (req_len > (QETH_BUFSIZE - IPA_PDU_HEADER_SIZE -
+ sizeof(struct qeth_ipacmd_hdr) -
+ sizeof(struct qeth_ipacmd_setadpparms_hdr)))
+ return -EINVAL;
ureq = memdup_user(udata, req_len + sizeof(struct qeth_snmp_ureq_hdr));
if (IS_ERR(ureq)) {
QETH_CARD_TEXT(card, 2, "snmpnome");
@@ -3926,6 +4419,20 @@ static void qeth_determine_capabilities(struct qeth_card *card)
if (rc)
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
+ QETH_DBF_TEXT_(SETUP, 2, "qfmt%d", card->ssqd.qfmt);
+ QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac1);
+ QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac3);
+ QETH_DBF_TEXT_(SETUP, 2, "icnt%d", card->ssqd.icnt);
+ if (!((card->ssqd.qfmt != QDIO_IQDIO_QFMT) ||
+ ((card->ssqd.qdioac1 & CHSC_AC1_INITIATE_INPUTQ) == 0) ||
+ ((card->ssqd.qdioac3 & CHSC_AC3_FORMAT2_CQ_AVAILABLE) == 0))) {
+ dev_info(&card->gdev->dev,
+ "Completion Queueing supported\n");
+ } else {
+ card->options.cq = QETH_CQ_NOTAVAILABLE;
+ }
+
+
out_offline:
if (ddev_offline == 1)
ccw_device_set_offline(ddev);
@@ -3933,11 +4440,30 @@ out:
return;
}
+static inline void qeth_qdio_establish_cq(struct qeth_card *card,
+ struct qdio_buffer **in_sbal_ptrs,
+ void (**queue_start_poll) (struct ccw_device *, int, unsigned long)) {
+ int i;
+
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ int offset = QDIO_MAX_BUFFERS_PER_Q *
+ (card->qdio.no_in_queues - 1);
+ i = QDIO_MAX_BUFFERS_PER_Q * (card->qdio.no_in_queues - 1);
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
+ in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
+ virt_to_phys(card->qdio.c_q->bufs[i].buffer);
+ }
+
+ queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
+ }
+}
+
static int qeth_qdio_establish(struct qeth_card *card)
{
struct qdio_initialize init_data;
char *qib_param_field;
struct qdio_buffer **in_sbal_ptrs;
+ void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
struct qdio_buffer **out_sbal_ptrs;
int i, j, k;
int rc = 0;
@@ -3946,34 +4472,48 @@ static int qeth_qdio_establish(struct qeth_card *card)
qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
GFP_KERNEL);
- if (!qib_param_field)
- return -ENOMEM;
+ if (!qib_param_field) {
+ rc = -ENOMEM;
+ goto out_free_nothing;
+ }
qeth_create_qib_param_field(card, qib_param_field);
qeth_create_qib_param_field_blkt(card, qib_param_field);
- in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+ in_sbal_ptrs = kzalloc(card->qdio.no_in_queues *
+ QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
GFP_KERNEL);
if (!in_sbal_ptrs) {
- kfree(qib_param_field);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_free_qib_param;
}
- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
in_sbal_ptrs[i] = (struct qdio_buffer *)
virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+ }
+
+ queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues,
+ GFP_KERNEL);
+ if (!queue_start_poll) {
+ rc = -ENOMEM;
+ goto out_free_in_sbals;
+ }
+ for (i = 0; i < card->qdio.no_in_queues; ++i)
+ queue_start_poll[i] = card->discipline.start_poll;
+
+ qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
out_sbal_ptrs =
- kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+ kzalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
sizeof(void *), GFP_KERNEL);
if (!out_sbal_ptrs) {
- kfree(in_sbal_ptrs);
- kfree(qib_param_field);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_free_queue_start_poll;
}
for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
- card->qdio.out_qs[i]->bufs[j].buffer);
+ card->qdio.out_qs[i]->bufs[j]->buffer);
}
memset(&init_data, 0, sizeof(struct qdio_initialize));
@@ -3981,14 +4521,15 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.q_format = qeth_get_qdio_q_format(card);
init_data.qib_param_field_format = 0;
init_data.qib_param_field = qib_param_field;
- init_data.no_input_qs = 1;
+ init_data.no_input_qs = card->qdio.no_in_queues;
init_data.no_output_qs = card->qdio.no_out_queues;
init_data.input_handler = card->discipline.input_handler;
init_data.output_handler = card->discipline.output_handler;
- init_data.queue_start_poll = card->discipline.start_poll;
+ init_data.queue_start_poll = queue_start_poll;
init_data.int_parm = (unsigned long) card;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+ init_data.output_sbal_state_array = card->qdio.out_bufstates;
init_data.scan_threshold =
(card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
@@ -4005,10 +4546,26 @@ static int qeth_qdio_establish(struct qeth_card *card)
qdio_free(CARD_DDEV(card));
}
}
+
+ switch (card->options.cq) {
+ case QETH_CQ_ENABLED:
+ dev_info(&card->gdev->dev, "Completion Queue support enabled");
+ break;
+ case QETH_CQ_DISABLED:
+ dev_info(&card->gdev->dev, "Completion Queue support disabled");
+ break;
+ default:
+ break;
+ }
out:
kfree(out_sbal_ptrs);
+out_free_queue_start_poll:
+ kfree(queue_start_poll);
+out_free_in_sbals:
kfree(in_sbal_ptrs);
+out_free_qib_param:
kfree(qib_param_field);
+out_free_nothing:
return rc;
}
@@ -4145,29 +4702,36 @@ out:
}
EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
-static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
+static inline int qeth_create_skb_frag(struct qeth_qdio_buffer *qethbuffer,
+ struct qdio_buffer_element *element,
struct sk_buff **pskb, int offset, int *pfrag, int data_len)
{
struct page *page = virt_to_page(element->addr);
if (*pskb == NULL) {
- /* the upper protocol layers assume that there is data in the
- * skb itself. Copy a small amount (64 bytes) to make them
- * happy. */
- *pskb = dev_alloc_skb(64 + ETH_HLEN);
- if (!(*pskb))
- return -ENOMEM;
+ if (qethbuffer->rx_skb) {
+ /* only if qeth_card.options.cq == QETH_CQ_ENABLED */
+ *pskb = qethbuffer->rx_skb;
+ qethbuffer->rx_skb = NULL;
+ } else {
+ *pskb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+ if (!(*pskb))
+ return -ENOMEM;
+ }
+
skb_reserve(*pskb, ETH_HLEN);
- if (data_len <= 64) {
+ if (data_len <= QETH_RX_PULL_LEN) {
memcpy(skb_put(*pskb, data_len), element->addr + offset,
data_len);
} else {
get_page(page);
- memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
- skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
- data_len - 64);
- (*pskb)->data_len += data_len - 64;
- (*pskb)->len += data_len - 64;
- (*pskb)->truesize += data_len - 64;
+ memcpy(skb_put(*pskb, QETH_RX_PULL_LEN),
+ element->addr + offset, QETH_RX_PULL_LEN);
+ skb_fill_page_desc(*pskb, *pfrag, page,
+ offset + QETH_RX_PULL_LEN,
+ data_len - QETH_RX_PULL_LEN);
+ (*pskb)->data_len += data_len - QETH_RX_PULL_LEN;
+ (*pskb)->len += data_len - QETH_RX_PULL_LEN;
+ (*pskb)->truesize += data_len - QETH_RX_PULL_LEN;
(*pfrag)++;
}
} else {
@@ -4178,15 +4742,18 @@ static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
(*pskb)->truesize += data_len;
(*pfrag)++;
}
+
+
return 0;
}
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
- struct qdio_buffer *buffer,
+ struct qeth_qdio_buffer *qethbuffer,
struct qdio_buffer_element **__element, int *__offset,
struct qeth_hdr **hdr)
{
struct qdio_buffer_element *element = *__element;
+ struct qdio_buffer *buffer = qethbuffer->buffer;
int offset = *__offset;
struct sk_buff *skb = NULL;
int skb_len = 0;
@@ -4231,9 +4798,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
if (!skb_len)
return NULL;
- if ((skb_len >= card->options.rx_sg_cb) &&
- (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
- (!atomic_read(&card->force_alloc_skb))) {
+ if (((skb_len >= card->options.rx_sg_cb) &&
+ (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+ (!atomic_read(&card->force_alloc_skb))) ||
+ (card->options.cq == QETH_CQ_ENABLED)) {
use_rx_sg = 1;
} else {
skb = dev_alloc_skb(skb_len + headroom);
@@ -4248,8 +4816,8 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
data_len = min(skb_len, (int)(element->length - offset));
if (data_len) {
if (use_rx_sg) {
- if (qeth_create_skb_frag(element, &skb, offset,
- &frag, data_len))
+ if (qeth_create_skb_frag(qethbuffer, element,
+ &skb, offset, &frag, data_len))
goto no_mem;
} else {
memcpy(skb_put(skb, data_len), data_ptr,
@@ -4651,6 +5219,8 @@ static struct {
{"tx do_QDIO count"},
{"tx csum"},
{"tx lin"},
+ {"cq handler count"},
+ {"cq handler time"}
};
int qeth_core_get_sset_count(struct net_device *dev, int stringset)
@@ -4709,6 +5279,8 @@ void qeth_core_get_ethtool_stats(struct net_device *dev,
data[32] = card->perf_stats.outbound_do_qdio_cnt;
data[33] = card->perf_stats.tx_csum;
data[34] = card->perf_stats.tx_lin;
+ data[35] = card->perf_stats.cq_cnt;
+ data[36] = card->perf_stats.cq_time;
}
EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
@@ -4867,7 +5439,16 @@ static int __init qeth_core_init(void)
goto slab_err;
}
+ qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf",
+ sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL);
+ if (!qeth_qdio_outbuf_cache) {
+ rc = -ENOMEM;
+ goto cqslab_err;
+ }
+
return 0;
+cqslab_err:
+ kmem_cache_destroy(qeth_core_header_cache);
slab_err:
root_device_unregister(qeth_core_root_dev);
register_err:
@@ -4892,6 +5473,7 @@ static void __exit qeth_core_exit(void)
&driver_attr_group);
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
ccw_driver_unregister(&qeth_ccw_driver);
+ kmem_cache_destroy(qeth_qdio_outbuf_cache);
kmem_cache_destroy(qeth_core_header_cache);
qeth_unregister_dbf_views();
pr_info("core functions removed\n");
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index b70b47f..a21ae3d 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -409,7 +409,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
BUG_ON(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
- card->qdio.in_q->bufs[card->rx.b_index].buffer,
+ &card->qdio.in_q->bufs[card->rx.b_index],
&card->rx.b_element, &card->rx.e_offset, &hdr);
if (!skb) {
*done = 1;
@@ -925,7 +925,7 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l2_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qeth_l2_set_multicast_list,
+ .ndo_set_rx_mode = qeth_l2_set_multicast_list,
.ndo_do_ioctl = qeth_l2_do_ioctl,
.ndo_set_mac_address = qeth_l2_set_mac_address,
.ndo_change_mtu = qeth_change_mtu,
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
index 14a43ae..e367315 100644
--- a/drivers/s390/net/qeth_l3.h
+++ b/drivers/s390/net/qeth_l3.h
@@ -63,5 +63,9 @@ int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
const u8 *);
int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions);
+int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *);
+int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *);
+void qeth_l3_set_ip_addr_list(struct qeth_card *);
#endif /* __QETH_L3_H__ */
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index e2c9ac5..4d5307d 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/bitops.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@@ -23,10 +24,12 @@
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/arp.h>
#include <net/ip6_checksum.h>
+#include <net/iucv/af_iucv.h>
#include "qeth_l3.h"
@@ -265,7 +268,7 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
}
}
-static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
{
unsigned long flags;
int rc = 0;
@@ -284,7 +287,7 @@ static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
return rc;
}
-static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
{
unsigned long flags;
int rc = 0;
@@ -303,7 +306,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
}
-static struct qeth_ipaddr *qeth_l3_get_addr_buffer(
+struct qeth_ipaddr *qeth_l3_get_addr_buffer(
enum qeth_prot_versions prot)
{
struct qeth_ipaddr *addr;
@@ -419,7 +422,7 @@ again:
list_splice(&fail_list, &card->ip_list);
}
-static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
+void qeth_l3_set_ip_addr_list(struct qeth_card *card)
{
struct list_head *tbd_list;
struct qeth_ipaddr *todo, *addr;
@@ -436,7 +439,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
spin_lock_irqsave(&card->ip_lock, flags);
tbd_list = card->ip_tbd_list;
- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+ card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
if (!card->ip_tbd_list) {
QETH_CARD_TEXT(card, 0, "silnomem");
card->ip_tbd_list = tbd_list;
@@ -1412,7 +1415,7 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card)
return 0;
}
-int qeth_l3_set_rx_csum(struct qeth_card *card, int on)
+static int qeth_l3_set_rx_csum(struct qeth_card *card, int on)
{
int rc = 0;
@@ -1696,16 +1699,18 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
static void qeth_l3_add_vlan_mc(struct qeth_card *card)
{
struct in_device *in_dev;
- struct vlan_group *vg;
- int i;
+ u16 vid;
QETH_CARD_TEXT(card, 4, "addmcvl");
- if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+ if (!qeth_is_supported(card, IPA_FULL_VLAN))
return;
- vg = card->vlangrp;
- for (i = 0; i < VLAN_N_VID; i++) {
- struct net_device *netdev = vlan_group_get_device(vg, i);
+ for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+ struct net_device *netdev;
+
+ rcu_read_lock();
+ netdev = __vlan_find_dev_deep(card->dev, vid);
+ rcu_read_unlock();
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
continue;
@@ -1759,16 +1764,16 @@ static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
{
struct inet6_dev *in_dev;
- struct vlan_group *vg;
- int i;
+ u16 vid;
QETH_CARD_TEXT(card, 4, "admc6vl");
- if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+ if (!qeth_is_supported(card, IPA_FULL_VLAN))
return;
- vg = card->vlangrp;
- for (i = 0; i < VLAN_N_VID; i++) {
- struct net_device *netdev = vlan_group_get_device(vg, i);
+ for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+ struct net_device *netdev;
+
+ netdev = __vlan_find_dev_deep(card->dev, vid);
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
continue;
@@ -1806,10 +1811,12 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
struct in_device *in_dev;
struct in_ifaddr *ifa;
struct qeth_ipaddr *addr;
+ struct net_device *netdev;
QETH_CARD_TEXT(card, 4, "frvaddr4");
- in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid));
+ netdev = __vlan_find_dev_deep(card->dev, vid);
+ in_dev = in_dev_get(netdev);
if (!in_dev)
return;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
@@ -1832,10 +1839,12 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
struct inet6_dev *in6_dev;
struct inet6_ifaddr *ifa;
struct qeth_ipaddr *addr;
+ struct net_device *netdev;
QETH_CARD_TEXT(card, 4, "frvaddr6");
- in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+ netdev = __vlan_find_dev_deep(card->dev, vid);
+ in6_dev = in6_dev_get(netdev);
if (!in6_dev)
return;
list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
@@ -1856,26 +1865,15 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
unsigned short vid)
{
- if (!card->vlangrp)
- return;
qeth_l3_free_vlan_addresses4(card, vid);
qeth_l3_free_vlan_addresses6(card, vid);
}
-static void qeth_l3_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
+static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct qeth_card *card = dev->ml_priv;
- unsigned long flags;
-
- QETH_CARD_TEXT(card, 4, "vlanreg");
- spin_lock_irqsave(&card->vlanlock, flags);
- card->vlangrp = grp;
- spin_unlock_irqrestore(&card->vlanlock, flags);
-}
-static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
-{
+ set_bit(vid, card->active_vlans);
return;
}
@@ -1892,7 +1890,7 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
spin_lock_irqsave(&card->vlanlock, flags);
/* unregister IP addresses of vlan device */
qeth_l3_free_vlan_addresses(card, vid);
- vlan_group_set_device(card->vlangrp, vid, NULL);
+ clear_bit(vid, card->active_vlans);
spin_unlock_irqrestore(&card->vlanlock, flags);
qeth_l3_set_multicast_list(card->dev);
}
@@ -1996,12 +1994,13 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
__u16 vlan_tag = 0;
int is_vlan;
unsigned int len;
+ __u16 magic;
*done = 0;
BUG_ON(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
- card->qdio.in_q->bufs[card->rx.b_index].buffer,
+ &card->qdio.in_q->bufs[card->rx.b_index],
&card->rx.b_element, &card->rx.e_offset, &hdr);
if (!skb) {
*done = 1;
@@ -2010,14 +2009,26 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
skb->dev = card->dev;
switch (hdr->hdr.l3.id) {
case QETH_HEADER_TYPE_LAYER3:
- is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
+ magic = *(__u16 *)skb->data;
+ if ((card->info.type == QETH_CARD_TYPE_IQD) &&
+ (magic == ETH_P_AF_IUCV)) {
+ skb->protocol = ETH_P_AF_IUCV;
+ skb->pkt_type = PACKET_HOST;
+ skb->mac_header = NET_SKB_PAD;
+ skb->dev = card->dev;
+ len = skb->len;
+ card->dev->header_ops->create(skb, card->dev, 0,
+ card->dev->dev_addr, "FAKELL",
+ card->dev->addr_len);
+ netif_receive_skb(skb);
+ } else {
+ is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
&vlan_tag);
- len = skb->len;
- if (is_vlan && !card->options.sniffer)
- vlan_gro_receive(&card->napi, card->vlangrp,
- vlan_tag, skb);
- else
+ len = skb->len;
+ if (is_vlan && !card->options.sniffer)
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
napi_gro_receive(&card->napi, skb);
+ }
break;
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
skb->pkt_type = PACKET_HOST;
@@ -2118,15 +2129,15 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev,
struct qeth_card *card)
{
int rc = 0;
- struct vlan_group *vg;
- int i;
+ u16 vid;
- vg = card->vlangrp;
- if (!vg)
- return rc;
+ for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+ struct net_device *netdev;
- for (i = 0; i < VLAN_N_VID; i++) {
- if (vlan_group_get_device(vg, i) == dev) {
+ rcu_read_lock();
+ netdev = __vlan_find_dev_deep(dev, vid);
+ rcu_read_unlock();
+ if (netdev == dev) {
rc = QETH_VLAN_CARD;
break;
}
@@ -2745,11 +2756,13 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
struct neighbour *n = NULL;
struct dst_entry *dst;
+ rcu_read_lock();
dst = skb_dst(skb);
if (dst)
n = dst_get_neighbour(dst);
if (n) {
cast_type = n->type;
+ rcu_read_unlock();
if ((cast_type == RTN_BROADCAST) ||
(cast_type == RTN_MULTICAST) ||
(cast_type == RTN_ANYCAST))
@@ -2757,6 +2770,8 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
else
return RTN_UNSPEC;
}
+ rcu_read_unlock();
+
/* try something else */
if (skb->protocol == ETH_P_IPV6)
return (skb_network_header(skb)[24] == 0xff) ?
@@ -2789,6 +2804,30 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
return cast_type;
}
+static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
+ struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+ char daddr[16];
+ struct af_iucv_trans_hdr *iucv_hdr;
+
+ skb_pull(skb, 14);
+ card->dev->header_ops->create(skb, card->dev, 0,
+ card->dev->dev_addr, card->dev->dev_addr,
+ card->dev->addr_len);
+ skb_pull(skb, 14);
+ iucv_hdr = (struct af_iucv_trans_hdr *)skb->data;
+ memset(hdr, 0, sizeof(struct qeth_hdr));
+ hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+ hdr->hdr.l3.ext_flags = 0;
+ hdr->hdr.l3.length = skb->len;
+ hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
+ memset(daddr, 0, sizeof(daddr));
+ daddr[0] = 0xfe;
+ daddr[1] = 0x80;
+ memcpy(&daddr[8], iucv_hdr->destUserID, 8);
+ memcpy(hdr->hdr.l3.dest_addr, daddr, 16);
+}
+
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
@@ -2803,7 +2842,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
* before we're going to overwrite this location with next hop ip.
* v6 uses passthrough, v4 sets the tag in the QDIO header.
*/
- if (card->vlangrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
else
@@ -2812,6 +2851,8 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+
+ rcu_read_lock();
dst = skb_dst(skb);
if (dst)
n = dst_get_neighbour(dst);
@@ -2858,6 +2899,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
}
}
+ rcu_read_unlock();
}
static inline void qeth_l3_hdr_csum(struct qeth_card *card,
@@ -2941,8 +2983,11 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
int data_offset = -1;
int nr_frags;
- if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) ||
- card->options.sniffer)
+ if (((card->info.type == QETH_CARD_TYPE_IQD) &&
+ (((card->options.cq != QETH_CQ_ENABLED) && !ipv) ||
+ ((card->options.cq == QETH_CQ_ENABLED) &&
+ (skb->protocol != ETH_P_AF_IUCV)))) ||
+ card->options.sniffer)
goto tx_drop;
if ((card->state != CARD_STATE_UP) || !card->lan_online) {
@@ -2964,7 +3009,10 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
(skb_shinfo(skb)->nr_frags == 0)) {
new_skb = skb;
- data_offset = ETH_HLEN;
+ if (new_skb->protocol == ETH_P_AF_IUCV)
+ data_offset = 0;
+ else
+ data_offset = ETH_HLEN;
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
if (!hdr)
goto tx_drop;
@@ -2988,8 +3036,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_pull(new_skb, ETH_HLEN);
}
- if (ipv != 4 && card->vlangrp &&
- vlan_tx_tag_present(new_skb)) {
+ if (ipv != 4 && vlan_tx_tag_present(new_skb)) {
skb_push(new_skb, VLAN_HLEN);
skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
skb_copy_to_linear_data_offset(new_skb, 4,
@@ -2999,7 +3046,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
tag = (u16 *)(new_skb->data + 12);
*tag = __constant_htons(ETH_P_8021Q);
*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
- new_skb->vlan_tci = 0;
}
}
@@ -3031,9 +3077,13 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
qeth_l3_fill_header(card, hdr, new_skb, ipv,
cast_type);
} else {
- qeth_l3_fill_header(card, hdr, new_skb, ipv,
- cast_type);
- hdr->hdr.l3.length = new_skb->len - data_offset;
+ if (new_skb->protocol == ETH_P_AF_IUCV)
+ qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb);
+ else {
+ qeth_l3_fill_header(card, hdr, new_skb, ipv,
+ cast_type);
+ hdr->hdr.l3.length = new_skb->len - data_offset;
+ }
}
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -3232,15 +3282,14 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qeth_l3_set_multicast_list,
- .ndo_do_ioctl = qeth_l3_do_ioctl,
- .ndo_change_mtu = qeth_change_mtu,
- .ndo_fix_features = qeth_l3_fix_features,
- .ndo_set_features = qeth_l3_set_features,
- .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_set_rx_mode = qeth_l3_set_multicast_list,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_fix_features = qeth_l3_fix_features,
+ .ndo_set_features = qeth_l3_set_features,
.ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
- .ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_tx_timeout = qeth_tx_timeout,
};
static const struct net_device_ops qeth_l3_osa_netdev_ops = {
@@ -3249,15 +3298,14 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qeth_l3_set_multicast_list,
- .ndo_do_ioctl = qeth_l3_do_ioctl,
- .ndo_change_mtu = qeth_change_mtu,
- .ndo_fix_features = qeth_l3_fix_features,
- .ndo_set_features = qeth_l3_set_features,
- .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_set_rx_mode = qeth_l3_set_multicast_list,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_fix_features = qeth_l3_fix_features,
+ .ndo_set_features = qeth_l3_set_features,
.ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
- .ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_tx_timeout = qeth_tx_timeout,
.ndo_neigh_setup = qeth_l3_neigh_setup,
};
@@ -3298,6 +3346,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->flags |= IFF_NOARP;
card->dev->netdev_ops = &qeth_l3_netdev_ops;
qeth_l3_iqd_read_initial_mac(card);
+ if (card->options.hsuid[0])
+ memcpy(card->dev->perm_addr, card->options.hsuid, 9);
} else
return -ENODEV;
@@ -3668,7 +3718,6 @@ static int qeth_l3_ip6_event(struct notifier_block *this,
struct qeth_ipaddr *addr;
struct qeth_card *card;
-
card = qeth_l3_get_card_from_dev(dev);
if (!card)
return NOTIFY_DONE;
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index cd99210..d979bb2 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -9,7 +9,7 @@
*/
#include <linux/slab.h>
-
+#include <asm/ebcdic.h>
#include "qeth_l3.h"
#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
@@ -308,6 +308,8 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
+ if (card->options.cq == QETH_CQ_ENABLED)
+ return -EPERM;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
@@ -333,10 +335,10 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
QETH_IN_BUF_COUNT_MAX)
qeth_realloc_buffer_pool(card,
QETH_IN_BUF_COUNT_MAX);
- break;
} else
rc = -EPERM;
- default: /* fall through */
+ break;
+ default:
rc = -EINVAL;
}
out:
@@ -347,6 +349,111 @@ out:
static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
qeth_l3_dev_sniffer_store);
+
+static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ char tmp_hsuid[9];
+
+ if (!card)
+ return -EINVAL;
+
+ if (card->info.type != QETH_CARD_TYPE_IQD)
+ return -EPERM;
+
+ if (card->state == CARD_STATE_DOWN)
+ return -EPERM;
+
+ memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
+ EBCASC(tmp_hsuid, 8);
+ return sprintf(buf, "%s\n", tmp_hsuid);
+}
+
+static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ struct qeth_ipaddr *addr;
+ char *tmp;
+ int i;
+
+ if (!card)
+ return -EINVAL;
+
+ if (card->info.type != QETH_CARD_TYPE_IQD)
+ return -EPERM;
+ if (card->state != CARD_STATE_DOWN &&
+ card->state != CARD_STATE_RECOVER)
+ return -EPERM;
+ if (card->options.sniffer)
+ return -EPERM;
+ if (card->options.cq == QETH_CQ_NOTAVAILABLE)
+ return -EPERM;
+
+ tmp = strsep((char **)&buf, "\n");
+ if (strlen(tmp) > 8)
+ return -EINVAL;
+
+ if (card->options.hsuid[0]) {
+ /* delete old ip address */
+ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+ if (addr != NULL) {
+ addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
+ addr->u.a6.addr.s6_addr32[1] = 0x00000000;
+ for (i = 8; i < 16; i++)
+ addr->u.a6.addr.s6_addr[i] =
+ card->options.hsuid[i - 8];
+ addr->u.a6.pfxlen = 0;
+ addr->type = QETH_IP_TYPE_NORMAL;
+ } else
+ return -ENOMEM;
+ if (!qeth_l3_delete_ip(card, addr))
+ kfree(addr);
+ qeth_l3_set_ip_addr_list(card);
+ }
+
+ if (strlen(tmp) == 0) {
+ /* delete ip address only */
+ card->options.hsuid[0] = '\0';
+ if (card->dev)
+ memcpy(card->dev->perm_addr, card->options.hsuid, 9);
+ qeth_configure_cq(card, QETH_CQ_DISABLED);
+ return count;
+ }
+
+ if (qeth_configure_cq(card, QETH_CQ_ENABLED))
+ return -EPERM;
+
+ for (i = 0; i < 8; i++)
+ card->options.hsuid[i] = ' ';
+ card->options.hsuid[8] = '\0';
+ strncpy(card->options.hsuid, tmp, strlen(tmp));
+ ASCEBC(card->options.hsuid, 8);
+ if (card->dev)
+ memcpy(card->dev->perm_addr, card->options.hsuid, 9);
+
+ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+ if (addr != NULL) {
+ addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
+ addr->u.a6.addr.s6_addr32[1] = 0x00000000;
+ for (i = 8; i < 16; i++)
+ addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8];
+ addr->u.a6.pfxlen = 0;
+ addr->type = QETH_IP_TYPE_NORMAL;
+ } else
+ return -ENOMEM;
+ if (!qeth_l3_add_ip(card, addr))
+ kfree(addr);
+ qeth_l3_set_ip_addr_list(card);
+
+ return count;
+}
+
+static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
+ qeth_l3_dev_hsuid_store);
+
+
static struct attribute *qeth_l3_device_attrs[] = {
&dev_attr_route4.attr,
&dev_attr_route6.attr,
@@ -354,6 +461,7 @@ static struct attribute *qeth_l3_device_attrs[] = {
&dev_attr_broadcast_mode.attr,
&dev_attr_canonical_macaddr.attr,
&dev_attr_sniffer.attr,
+ &dev_attr_hsuid.attr,
NULL,
};
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index fc669c0..3743ac9 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -32,6 +32,7 @@
#include <linux/miscdevice.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "zfcp_ext.h"
#include "zfcp_fc.h"
#include "zfcp_reqlist.h"
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index de1bcfa..79a6afe 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -9,6 +9,7 @@
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/module.h>
#include "zfcp_ext.h"
#include "zfcp_reqlist.h"
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 8b18dc0..79b9848 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -9,6 +9,7 @@
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <asm/debug.h>
@@ -164,6 +165,42 @@ void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req)
}
/**
+ * zfcp_dbf_hba_def_err - trace event for deferred error messages
+ * @adapter: pointer to struct zfcp_adapter
+ * @req_id: request id which caused the deferred error message
+ * @scount: number of sbals incl. the signaling sbal
+ * @pl: array of all involved sbals
+ */
+void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
+ void **pl)
+{
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_pay *payload = &dbf->pay_buf;
+ unsigned long flags;
+ u16 length;
+
+ if (!pl)
+ return;
+
+ spin_lock_irqsave(&dbf->pay_lock, flags);
+ memset(payload, 0, sizeof(*payload));
+
+ memcpy(payload->area, "def_err", 7);
+ payload->fsf_req_id = req_id;
+ payload->counter = 0;
+ length = min((u16)sizeof(struct qdio_buffer),
+ (u16)ZFCP_DBF_PAY_MAX_REC);
+
+ while (payload->counter < scount && (char *)pl[payload->counter]) {
+ memcpy(payload->data, (char *)pl[payload->counter], length);
+ debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
+ payload->counter++;
+ }
+
+ spin_unlock_irqrestore(&dbf->pay_lock, flags);
+}
+
+/**
* zfcp_dbf_hba_basic - trace event for basic adapter events
* @adapter: pointer to struct zfcp_adapter
*/
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index ebbf760..f172b84 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -72,6 +72,7 @@ struct zfcp_reqlist;
#define ZFCP_STATUS_COMMON_NOESC 0x00200000
/* adapter status */
+#define ZFCP_STATUS_ADAPTER_MB_ACT 0x00000001
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
@@ -316,4 +317,10 @@ struct zfcp_fsf_req {
void (*handler)(struct zfcp_fsf_req *);
};
+static inline
+int zfcp_adapter_multi_buffer_active(struct zfcp_adapter *adapter)
+{
+ return atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_MB_ACT;
+}
+
#endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 3ad6399..ef9e502 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -53,6 +53,7 @@ extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ceb7f7c..8bfd579 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -951,39 +951,47 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
struct scatterlist *sg_resp)
{
struct zfcp_adapter *adapter = req->adapter;
+ struct zfcp_qdio *qdio = adapter->qdio;
+ struct fsf_qtcb *qtcb = req->qtcb;
u32 feat = adapter->adapter_features;
- int bytes;
- if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
- if (!zfcp_qdio_sg_one_sbale(sg_req) ||
- !zfcp_qdio_sg_one_sbale(sg_resp))
- return -EOPNOTSUPP;
+ if (zfcp_adapter_multi_buffer_active(adapter)) {
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
+ return -EIO;
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
+ return -EIO;
- zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
- sg_req, sg_resp);
+ zfcp_qdio_set_data_div(qdio, &req->qdio_req,
+ zfcp_qdio_sbale_count(sg_req));
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
+ zfcp_qdio_set_scount(qdio, &req->qdio_req);
return 0;
}
/* use single, unchained SBAL if it can hold the request */
if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
- zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
+ zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
sg_req, sg_resp);
return 0;
}
- bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req);
- if (bytes <= 0)
+ if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
+ return -EOPNOTSUPP;
+
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
return -EIO;
- zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
- req->qtcb->bottom.support.req_buf_length = bytes;
- zfcp_qdio_skip_to_last_sbale(&req->qdio_req);
- bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
- sg_resp);
- req->qtcb->bottom.support.resp_buf_length = bytes;
- if (bytes <= 0)
+ qtcb->bottom.support.req_buf_length = zfcp_qdio_real_bytes(sg_req);
+
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
+ zfcp_qdio_skip_to_last_sbale(qdio, &req->qdio_req);
+
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
return -EIO;
- zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
+
+ qtcb->bottom.support.resp_buf_length = zfcp_qdio_real_bytes(sg_resp);
+
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
return 0;
}
@@ -1134,7 +1142,8 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
- zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
+ if (!zfcp_adapter_multi_buffer_active(adapter))
+ zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
@@ -2184,7 +2193,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
struct zfcp_fsf_req *req;
struct fcp_cmnd *fcp_cmnd;
u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
- int real_bytes, retval = -EIO, dix_bytes = 0;
+ int retval = -EIO;
struct scsi_device *sdev = scsi_cmnd->device;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -2229,7 +2238,8 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF;
}
- zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
+ if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
+ goto failed_scsi_cmnd;
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
@@ -2237,18 +2247,22 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
if (scsi_prot_sg_count(scsi_cmnd)) {
zfcp_qdio_set_data_div(qdio, &req->qdio_req,
scsi_prot_sg_count(scsi_cmnd));
- dix_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
+ retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
+ scsi_prot_sglist(scsi_cmnd));
+ if (retval)
+ goto failed_scsi_cmnd;
+ io->prot_data_length = zfcp_qdio_real_bytes(
scsi_prot_sglist(scsi_cmnd));
- io->prot_data_length = dix_bytes;
}
- real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
- scsi_sglist(scsi_cmnd));
-
- if (unlikely(real_bytes < 0) || unlikely(dix_bytes < 0))
+ retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
+ scsi_sglist(scsi_cmnd));
+ if (unlikely(retval))
goto failed_scsi_cmnd;
zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
+ if (zfcp_adapter_multi_buffer_active(adapter))
+ zfcp_qdio_set_scount(qdio, &req->qdio_req);
retval = zfcp_fsf_req_send(req);
if (unlikely(retval))
@@ -2350,7 +2364,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_qdio *qdio = adapter->qdio;
struct zfcp_fsf_req *req = NULL;
struct fsf_qtcb_bottom_support *bottom;
- int retval = -EIO, bytes;
+ int retval = -EIO;
u8 direction;
if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
@@ -2383,13 +2397,17 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
bottom->option = fsf_cfdc->option;
- bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
+ retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
- if (bytes != ZFCP_CFDC_MAX_SIZE) {
+ if (retval ||
+ (zfcp_qdio_real_bytes(fsf_cfdc->sg) != ZFCP_CFDC_MAX_SIZE)) {
zfcp_fsf_req_free(req);
+ retval = -EIO;
goto out;
}
- zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
+ if (zfcp_adapter_multi_buffer_active(adapter))
+ zfcp_qdio_set_scount(qdio, &req->qdio_req);
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index f3922a8..52c6b59 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -10,11 +10,16 @@
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/slab.h>
+#include <linux/module.h>
#include "zfcp_ext.h"
#include "zfcp_qdio.h"
#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
+static bool enable_multibuffer;
+module_param_named(datarouter, enable_multibuffer, bool, 0400);
+MODULE_PARM_DESC(datarouter, "Enable hardware data router support");
+
static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
{
int pos;
@@ -37,8 +42,11 @@ static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
- if (qdio_err & QDIO_ERROR_SLSB_STATE)
+ if (qdio_err & QDIO_ERROR_SLSB_STATE) {
zfcp_qdio_siosl(adapter);
+ zfcp_erp_adapter_shutdown(adapter, 0, id);
+ return;
+ }
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
ZFCP_STATUS_COMMON_ERP_FAILED, id);
@@ -93,9 +101,31 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
unsigned long parm)
{
struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
- int sbal_idx, sbal_no;
+ struct zfcp_adapter *adapter = qdio->adapter;
+ int sbal_no, sbal_idx;
if (unlikely(qdio_err)) {
+ if (zfcp_adapter_multi_buffer_active(adapter)) {
+ void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
+ struct qdio_buffer_element *sbale;
+ u64 req_id;
+ u8 scount;
+
+ memset(pl, 0,
+ ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
+ sbale = qdio->res_q[idx]->element;
+ req_id = (u64) sbale->addr;
+ scount = min(sbale->scount + 1,
+ ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
+ /* incl. signaling SBAL */
+
+ for (sbal_no = 0; sbal_no < scount; sbal_no++) {
+ sbal_idx = (idx + sbal_no) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ pl[sbal_no] = qdio->res_q[sbal_idx];
+ }
+ zfcp_dbf_hba_def_err(adapter, req_id, scount, pl);
+ }
zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
return;
}
@@ -155,7 +185,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
static struct qdio_buffer_element *
zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
{
- if (q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL)
+ if (q_req->sbale_curr == qdio->max_sbale_per_sbal - 1)
return zfcp_qdio_sbal_chain(qdio, q_req);
q_req->sbale_curr++;
return zfcp_qdio_sbale_curr(qdio, q_req);
@@ -167,13 +197,12 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
* @q_req: pointer to struct zfcp_qdio_req
* @sg: scatter-gather list
* @max_sbals: upper bound for number of SBALs to be used
- * Returns: number of bytes, or error (negativ)
+ * Returns: zero or -EINVAL on error
*/
int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
struct scatterlist *sg)
{
struct qdio_buffer_element *sbale;
- int bytes = 0;
/* set storage-block type for this request */
sbale = zfcp_qdio_sbale_req(qdio, q_req);
@@ -187,14 +216,10 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
q_req->sbal_number);
return -EINVAL;
}
-
sbale->addr = sg_virt(sg);
sbale->length = sg->length;
-
- bytes += sg->length;
}
-
- return bytes;
+ return 0;
}
static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
@@ -279,6 +304,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
ASCEBC(id->adapter_name, 8);
id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
+ if (enable_multibuffer)
+ id->qdr_ac |= QDR_AC_MULTI_BUFFER_ENABLE;
id->no_input_qs = 1;
id->no_output_qs = 1;
id->input_handler = zfcp_qdio_int_resp;
@@ -374,6 +401,17 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
&qdio->adapter->status);
+ if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
+ qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
+ } else {
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
+ qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
+ }
+
+ qdio->max_sbale_per_req =
+ ZFCP_QDIO_MAX_SBALS_PER_REQ * qdio->max_sbale_per_sbal
+ - 2;
if (qdio_activate(cdev))
goto failed_qdio;
@@ -393,6 +431,11 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
+ if (adapter->scsi_host) {
+ adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
+ adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
+ }
+
return 0;
failed_qdio:
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h
index 54e22ac..8ac7f53 100644
--- a/drivers/s390/scsi/zfcp_qdio.h
+++ b/drivers/s390/scsi/zfcp_qdio.h
@@ -13,20 +13,9 @@
#define ZFCP_QDIO_SBALE_LEN PAGE_SIZE
-/* DMQ bug workaround: don't use last SBALE */
-#define ZFCP_QDIO_MAX_SBALES_PER_SBAL (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
-
-/* index of last SBALE (with respect to DMQ bug workaround) */
-#define ZFCP_QDIO_LAST_SBALE_PER_SBAL (ZFCP_QDIO_MAX_SBALES_PER_SBAL - 1)
-
/* Max SBALS for chaining */
#define ZFCP_QDIO_MAX_SBALS_PER_REQ 36
-/* max. number of (data buffer) SBALEs in largest SBAL chain
- * request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */
-#define ZFCP_QDIO_MAX_SBALES_PER_REQ \
- (ZFCP_QDIO_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2)
-
/**
* struct zfcp_qdio - basic qdio data structure
* @res_q: response queue
@@ -53,6 +42,8 @@ struct zfcp_qdio {
atomic_t req_q_full;
wait_queue_head_t req_q_wq;
struct zfcp_adapter *adapter;
+ u16 max_sbale_per_sbal;
+ u16 max_sbale_per_req;
};
/**
@@ -155,7 +146,7 @@ void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
{
struct qdio_buffer_element *sbale;
- BUG_ON(q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL);
+ BUG_ON(q_req->sbale_curr == qdio->max_sbale_per_sbal - 1);
q_req->sbale_curr++;
sbale = zfcp_qdio_sbale_curr(qdio, q_req);
sbale->addr = data;
@@ -195,9 +186,10 @@ int zfcp_qdio_sg_one_sbale(struct scatterlist *sg)
* @q_req: The current zfcp_qdio_req
*/
static inline
-void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio_req *q_req)
+void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio *qdio,
+ struct zfcp_qdio_req *q_req)
{
- q_req->sbale_curr = ZFCP_QDIO_LAST_SBALE_PER_SBAL;
+ q_req->sbale_curr = qdio->max_sbale_per_sbal - 1;
}
/**
@@ -228,8 +220,52 @@ void zfcp_qdio_set_data_div(struct zfcp_qdio *qdio,
{
struct qdio_buffer_element *sbale;
- sbale = &qdio->req_q[q_req->sbal_first]->element[0];
+ sbale = qdio->req_q[q_req->sbal_first]->element;
sbale->length = count;
}
+/**
+ * zfcp_qdio_sbale_count - count sbale used
+ * @sg: pointer to struct scatterlist
+ */
+static inline
+unsigned int zfcp_qdio_sbale_count(struct scatterlist *sg)
+{
+ unsigned int count = 0;
+
+ for (; sg; sg = sg_next(sg))
+ count++;
+
+ return count;
+}
+
+/**
+ * zfcp_qdio_real_bytes - count bytes used
+ * @sg: pointer to struct scatterlist
+ */
+static inline
+unsigned int zfcp_qdio_real_bytes(struct scatterlist *sg)
+{
+ unsigned int real_bytes = 0;
+
+ for (; sg; sg = sg_next(sg))
+ real_bytes += sg->length;
+
+ return real_bytes;
+}
+
+/**
+ * zfcp_qdio_set_scount - set SBAL count value
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: The current zfcp_qdio_req
+ */
+static inline
+void zfcp_qdio_set_scount(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
+{
+ struct qdio_buffer_element *sbale;
+
+ sbale = qdio->req_q[q_req->sbal_first]->element;
+ sbale->scount = q_req->sbal_number - 1;
+}
+
#endif /* ZFCP_QDIO_H */
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 3a417df..7b35364 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -3,17 +3,18 @@
*
* Interface to Linux SCSI midlayer.
*
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2013
*/
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <scsi/fc/fc_fcp.h>
#include <scsi/scsi_eh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "zfcp_ext.h"
#include "zfcp_dbf.h"
#include "zfcp_fc.h"
@@ -24,11 +25,8 @@ module_param_named(queue_depth, default_depth, uint, 0600);
MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices");
static bool enable_dif;
-
-#ifdef CONFIG_ZFCP_DIF
-module_param_named(dif, enable_dif, bool, 0600);
+module_param_named(dif, enable_dif, bool, 0400);
MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support");
-#endif
static bool allow_lun_scan = 1;
module_param(allow_lun_scan, bool, 0600);
@@ -313,8 +311,12 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.proc_name = "zfcp",
.can_queue = 4096,
.this_id = -1,
- .sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ,
- .max_sectors = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8),
+ .sg_tablesize = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
+ * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2),
+ /* GCD, adjusted later */
+ .max_sectors = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
+ * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
+ /* GCD, adjusted later */
.dma_boundary = ZFCP_QDIO_SBALE_LEN - 1,
.cmd_per_lun = 1,
.use_clustering = 1,
@@ -672,9 +674,9 @@ void zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
mask |= SHOST_DIX_TYPE1_PROTECTION;
scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
- shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
- shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
- shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2;
+ shost->sg_prot_tablesize = adapter->qdio->max_sbale_per_req / 2;
+ shost->sg_tablesize = adapter->qdio->max_sbale_per_req / 2;
+ shost->max_sectors = shost->sg_tablesize * 8;
}
scsi_host_set_prot(shost, mask);
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 160e751..0787b97 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -452,6 +452,9 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op,
if (!tp)
return;
+ INIT_LIST_HEAD(&tp->bp_list);
+ INIT_LIST_HEAD(&tp->glob_list);
+
tp->client = bbc_i2c_attach(bp, op);
if (!tp->client) {
kfree(tp);
@@ -497,6 +500,9 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op,
if (!fp)
return;
+ INIT_LIST_HEAD(&fp->bp_list);
+ INIT_LIST_HEAD(&fp->glob_list);
+
fp->client = bbc_i2c_attach(bp, op);
if (!fp->client) {
kfree(fp);
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 5f94d22..7179f72 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -233,13 +233,9 @@ int bbc_i2c_write_buf(struct bbc_i2c_client *client,
int ret = 0;
while (len > 0) {
- int err = bbc_i2c_writeb(client, *buf, off);
-
- if (err < 0) {
- ret = err;
+ ret = bbc_i2c_writeb(client, *buf, off);
+ if (ret < 0)
break;
- }
-
len--;
buf++;
off++;
@@ -253,11 +249,9 @@ int bbc_i2c_read_buf(struct bbc_i2c_client *client,
int ret = 0;
while (len > 0) {
- int err = bbc_i2c_readb(client, buf, off);
- if (err < 0) {
- ret = err;
+ ret = bbc_i2c_readb(client, buf, off);
+ if (ret < 0)
break;
- }
len--;
buf++;
off++;
@@ -307,13 +301,18 @@ static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, in
if (!bp)
return NULL;
+ INIT_LIST_HEAD(&bp->temps);
+ INIT_LIST_HEAD(&bp->fans);
+
bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
if (!bp->i2c_control_regs)
goto fail;
- bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
- if (!bp->i2c_bussel_reg)
- goto fail;
+ if (op->num_resources == 2) {
+ bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
+ if (!bp->i2c_bussel_reg)
+ goto fail;
+ }
bp->waiting = 0;
init_waitqueue_head(&bp->wq);
@@ -422,17 +421,6 @@ static struct platform_driver bbc_i2c_driver = {
.remove = __devexit_p(bbc_i2c_remove),
};
-static int __init bbc_i2c_init(void)
-{
- return platform_driver_register(&bbc_i2c_driver);
-}
-
-static void __exit bbc_i2c_exit(void)
-{
- platform_driver_unregister(&bbc_i2c_driver);
-}
-
-module_init(bbc_i2c_init);
-module_exit(bbc_i2c_exit);
+module_platform_driver(bbc_i2c_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 740da446..4b99397 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -16,7 +16,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h> /* put_/get_user */
#include <asm/io.h>
@@ -275,15 +275,4 @@ static struct platform_driver d7s_driver = {
.remove = __devexit_p(d7s_remove),
};
-static int __init d7s_init(void)
-{
- return platform_driver_register(&d7s_driver);
-}
-
-static void __exit d7s_exit(void)
-{
- platform_driver_unregister(&d7s_driver);
-}
-
-module_init(d7s_init);
-module_exit(d7s_exit);
+module_platform_driver(d7s_driver);
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index be7b4e5..339fd6f 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -1138,16 +1138,6 @@ static struct platform_driver envctrl_driver = {
.remove = __devexit_p(envctrl_remove),
};
-static int __init envctrl_init(void)
-{
- return platform_driver_register(&envctrl_driver);
-}
-
-static void __exit envctrl_exit(void)
-{
- platform_driver_unregister(&envctrl_driver);
-}
+module_platform_driver(envctrl_driver);
-module_init(envctrl_init);
-module_exit(envctrl_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 73dd4e7..826157f 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -216,16 +216,6 @@ static struct platform_driver flash_driver = {
.remove = __devexit_p(flash_remove),
};
-static int __init flash_init(void)
-{
- return platform_driver_register(&flash_driver);
-}
-
-static void __exit flash_cleanup(void)
-{
- platform_driver_unregister(&flash_driver);
-}
+module_platform_driver(flash_driver);
-module_init(flash_init);
-module_exit(flash_cleanup);
MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index ebce963..0b31658 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -435,16 +435,6 @@ static struct platform_driver uctrl_driver = {
};
-static int __init uctrl_init(void)
-{
- return platform_driver_register(&uctrl_driver);
-}
-
-static void __exit uctrl_exit(void)
-{
- platform_driver_unregister(&uctrl_driver);
-}
+module_platform_driver(uctrl_driver);
-module_init(uctrl_init);
-module_exit(uctrl_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 0619957..409f580 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -34,6 +34,7 @@
#include <linux/blkdev.h>
#include <asm/uaccess.h>
#include <linux/highmem.h> /* For flush_kernel_dcache_page */
+#include <linux/module.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 8a0b330..1254431 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -508,7 +508,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
goto cleanup;
}
- if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
+ if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) ||
+ (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) {
rcode = -EINVAL;
goto cleanup;
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index c7b6fed..2e658d2 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -771,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{
struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
}
@@ -895,16 +897,17 @@ static ssize_t aac_show_serial_number(struct device *device,
int len = 0;
if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
- len = snprintf(buf, PAGE_SIZE, "%06X\n",
+ len = snprintf(buf, 16, "%06X\n",
le32_to_cpu(dev->adapter_info.serial[0]));
if (len &&
!memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)-len],
buf, len-1))
- len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+ len = snprintf(buf, 16, "%.*s\n",
(int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
dev->supplement_adapter_info.MfgPcbaSerialNo);
- return len;
+
+ return min(len, 16);
}
static ssize_t aac_show_max_channel(struct device *device,
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index c204946..957595a 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -37,7 +37,6 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/completion.h>
#include <linux/time.h>
#include <linux/interrupt.h>
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 5e6620f..6739069 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -31,8 +31,7 @@ config AIC79XX_CMDS_PER_DEVICE
on some devices. The upper bound is 253. 0 disables tagged queueing.
Per device tag depth can be controlled via the kernel command line
- "tag_info" option. See drivers/scsi/aic7xxx/README.aic79xx
- for details.
+ "tag_info" option. See Documentation/scsi/aic79xx.txt for details.
config AIC79XX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 88da670..55ac55e 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -36,8 +36,7 @@ config AIC7XXX_CMDS_PER_DEVICE
on some devices. The upper bound is 253. 0 disables tagged queueing.
Per device tag depth can be controlled via the kernel command line
- "tag_info" option. See drivers/scsi/aic7xxx/README.aic7xxx
- for details.
+ "tag_info" option. See Documentation/scsi/aic7xxx.txt for details.
config AIC7XXX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
index 67eeba3..a16a77c 100644
--- a/drivers/scsi/aic94xx/aic94xx_dump.c
+++ b/drivers/scsi/aic94xx/aic94xx_dump.c
@@ -29,7 +29,7 @@
*
*/
-#include "linux/pci.h"
+#include <linux/pci.h>
#include "aic94xx.h"
#include "aic94xx_reg.h"
#include "aic94xx_reg_def.h"
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 2959327..fdac7c2 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -906,6 +906,7 @@ int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
switch (func) {
case PHY_FUNC_CLEAR_ERROR_LOG:
+ case PHY_FUNC_GET_EVENTS:
return -ENOSYS;
case PHY_FUNC_SET_LINK_RATE:
rates = arg;
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index 532d212..393e7ce 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
- memcpy(&resp->ending_fis[0], r+16, 24);
+ memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE);
ts->buf_valid_size = sizeof(*resp);
}
}
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index b8a82f2..cdb1536 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -660,6 +660,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
spin_lock(&phba->ctrl.mbox_lock);
ctrl = &phba->ctrl;
wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ memset(wrb, 0, sizeof(*wrb));
req = embedded_payload(wrb);
ctxt = &req->context;
@@ -868,3 +869,22 @@ error:
beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
return status;
}
+
+int beiscsi_cmd_reset_function(struct beiscsi_hba *phba)
+{
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_post_sgl_pages_req *req = embedded_payload(wrb);
+ int status;
+
+ spin_lock(&ctrl->mbox_lock);
+
+ req = embedded_payload(wrb);
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+ status = be_mbox_notify_wait(phba);
+
+ spin_unlock(&ctrl->mbox_lock);
+ return status;
+}
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 497eb29..8b40a5b 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -561,6 +561,8 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem, u32 page_offset,
u32 num_pages);
+int beiscsi_cmd_reset_function(struct beiscsi_hba *phba);
+
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
struct be_queue_info *wrbq);
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 3cad106..8b002f6 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -177,9 +177,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct beiscsi_conn *beiscsi_conn = conn->dd_data;
- struct Scsi_Host *shost =
- (struct Scsi_Host *)iscsi_session_to_shost(cls_session);
- struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
struct beiscsi_endpoint *beiscsi_ep;
struct iscsi_endpoint *ep;
@@ -290,7 +289,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
int beiscsi_get_host_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf)
{
- struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
int status = 0;
SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param);
@@ -733,3 +732,56 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
}
+
+mode_t be2iscsi_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index ff60b7f..4a1f2e3 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -26,6 +26,8 @@
#define BE2_IPV4 0x1
#define BE2_IPV6 0x10
+mode_t be2iscsi_attr_is_visible(int param_type, int param);
+
void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_offload_params *params);
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 94b9a07..b9ee9f3 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/semaphore.h>
#include <linux/iscsi_boot_sysfs.h>
+#include <linux/module.h>
#include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h>
@@ -215,73 +216,62 @@ unlock:
static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
{
struct beiscsi_hba *phba = data;
+ struct mgmt_session_info *boot_sess = &phba->boot_sess;
+ struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
char *str = buf;
int rc;
switch (type) {
case ISCSI_BOOT_TGT_NAME:
rc = sprintf(buf, "%.*s\n",
- (int)strlen(phba->boot_sess.target_name),
- (char *)&phba->boot_sess.target_name);
+ (int)strlen(boot_sess->target_name),
+ (char *)&boot_sess->target_name);
break;
case ISCSI_BOOT_TGT_IP_ADDR:
- if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1)
+ if (boot_conn->dest_ipaddr.ip_type == 0x1)
rc = sprintf(buf, "%pI4\n",
- (char *)&phba->boot_sess.conn_list[0].
- dest_ipaddr.ip_address);
+ (char *)&boot_conn->dest_ipaddr.ip_address);
else
rc = sprintf(str, "%pI6\n",
- (char *)&phba->boot_sess.conn_list[0].
- dest_ipaddr.ip_address);
+ (char *)&boot_conn->dest_ipaddr.ip_address);
break;
case ISCSI_BOOT_TGT_PORT:
- rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0].
- dest_port);
+ rc = sprintf(str, "%d\n", boot_conn->dest_port);
break;
case ISCSI_BOOT_TGT_CHAP_NAME:
rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_chap_name_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_chap_name);
+ boot_conn->negotiated_login_options.auth_data.chap.
+ target_chap_name_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.target_chap_name);
break;
case ISCSI_BOOT_TGT_CHAP_SECRET:
rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_secret_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_secret);
-
+ boot_conn->negotiated_login_options.auth_data.chap.
+ target_secret_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.target_secret);
break;
case ISCSI_BOOT_TGT_REV_CHAP_NAME:
rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_chap_name_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_chap_name);
-
+ boot_conn->negotiated_login_options.auth_data.chap.
+ intr_chap_name_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.intr_chap_name);
break;
case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
- rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_secret_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_secret);
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->negotiated_login_options.auth_data.chap.
+ intr_secret_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.intr_secret);
break;
case ISCSI_BOOT_TGT_FLAGS:
- rc = sprintf(str, "2\n");
+ rc = sprintf(str, "2\n");
break;
case ISCSI_BOOT_TGT_NIC_ASSOC:
- rc = sprintf(str, "0\n");
+ rc = sprintf(str, "0\n");
break;
default:
rc = -ENOSYS;
@@ -315,10 +305,10 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
switch (type) {
case ISCSI_BOOT_ETH_FLAGS:
- rc = sprintf(str, "2\n");
+ rc = sprintf(str, "2\n");
break;
case ISCSI_BOOT_ETH_INDEX:
- rc = sprintf(str, "0\n");
+ rc = sprintf(str, "0\n");
break;
case ISCSI_BOOT_ETH_MAC:
rc = beiscsi_get_macaddr(buf, phba);
@@ -391,40 +381,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
return rc;
}
-static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
-{
- struct iscsi_boot_kobj *boot_kobj;
-
- phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
- if (!phba->boot_kset)
- return -ENOMEM;
-
- /* get boot info using mgmt cmd */
- boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
- beiscsi_show_boot_tgt_info,
- beiscsi_tgt_get_attr_visibility);
- if (!boot_kobj)
- goto free_kset;
-
- boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
- beiscsi_show_boot_ini_info,
- beiscsi_ini_get_attr_visibility);
- if (!boot_kobj)
- goto free_kset;
-
- boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
- beiscsi_show_boot_eth_info,
- beiscsi_eth_get_attr_visibility);
- if (!boot_kobj)
- goto free_kset;
- return 0;
-
-free_kset:
- if (phba->boot_kset)
- iscsi_boot_destroy_kset(phba->boot_kset);
- return -ENOMEM;
-}
-
/*------------------- PCI Driver operations and data ----------------- */
static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
@@ -468,7 +424,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
"iscsi_host_alloc failed\n");
return NULL;
}
- shost->dma_boundary = pcidev->dma_mask;
shost->max_id = BE2_MAX_SESSIONS;
shost->max_channel = 0;
shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
@@ -483,14 +438,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
if (iscsi_host_add(shost, &phba->pcidev->dev))
goto free_devices;
- if (beiscsi_setup_boot_info(phba))
- /*
- * log error but continue, because we may not be using
- * iscsi boot.
- */
- shost_printk(KERN_ERR, phba->shost, "Could not set up "
- "iSCSI boot info.");
-
return phba;
free_devices:
@@ -875,33 +822,47 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
int ret, msix_vec, i, j;
- char desc[32];
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
if (phba->msix_enabled) {
for (i = 0; i < phba->num_cpus; i++) {
- sprintf(desc, "beiscsi_msix_%04x", i);
+ phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME,
+ GFP_KERNEL);
+ if (!phba->msi_name[i]) {
+ ret = -ENOMEM;
+ goto free_msix_irqs;
+ }
+
+ sprintf(phba->msi_name[i], "beiscsi_%02x_%02x",
+ phba->shost->host_no, i);
msix_vec = phba->msix_entries[i].vector;
- ret = request_irq(msix_vec, be_isr_msix, 0, desc,
+ ret = request_irq(msix_vec, be_isr_msix, 0,
+ phba->msi_name[i],
&phwi_context->be_eq[i]);
if (ret) {
shost_printk(KERN_ERR, phba->shost,
"beiscsi_init_irqs-Failed to"
"register msix for i = %d\n", i);
- if (!i)
- return ret;
+ kfree(phba->msi_name[i]);
goto free_msix_irqs;
}
}
+ phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL);
+ if (!phba->msi_name[i]) {
+ ret = -ENOMEM;
+ goto free_msix_irqs;
+ }
+ sprintf(phba->msi_name[i], "beiscsi_mcc_%02x",
+ phba->shost->host_no);
msix_vec = phba->msix_entries[i].vector;
- ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc",
+ ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i],
&phwi_context->be_eq[i]);
if (ret) {
shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
"Failed to register beiscsi_msix_mcc\n");
- i++;
+ kfree(phba->msi_name[i]);
goto free_msix_irqs;
}
@@ -916,8 +877,11 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
}
return 0;
free_msix_irqs:
- for (j = i - 1; j == 0; j++)
+ for (j = i - 1; j >= 0; j--) {
+ kfree(phba->msi_name[j]);
+ msix_vec = phba->msix_entries[j].vector;
free_irq(msix_vec, &phwi_context->be_eq[j]);
+ }
return ret;
}
@@ -1159,7 +1123,12 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
& SOL_STS_MASK) >> 8);
flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
& SOL_FLAGS_MASK) >> 24) | 0x80;
+ if (!task->sc) {
+ if (io_task->scsi_cmnd)
+ scsi_dma_unmap(io_task->scsi_cmnd);
+ return;
+ }
task->sc->result = (DID_OK << 16) | status;
if (rsp != ISCSI_STATUS_CMD_COMPLETED) {
task->sc->result = DID_ERROR << 16;
@@ -3511,6 +3480,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
unsigned int tag, wrb_num;
unsigned short status, extd_status;
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+ int ret = -ENOMEM;
tag = beiscsi_get_boot_target(phba);
if (!tag) {
@@ -3535,8 +3505,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
boot_resp = embedded_payload(wrb);
if (boot_resp->boot_session_handle < 0) {
- printk(KERN_ERR "No Boot Session for this pci_func,"
- "session Hndl = %d\n", boot_resp->boot_session_handle);
+ shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
return -ENXIO;
}
@@ -3574,14 +3543,70 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
wrb = queue_get_wrb(mccq, wrb_num);
free_mcc_tag(&phba->ctrl, tag);
session_resp = nonemb_cmd.va ;
+
memcpy(&phba->boot_sess, &session_resp->session_info,
sizeof(struct mgmt_session_info));
- pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
- nonemb_cmd.va, nonemb_cmd.dma);
- return 0;
+ ret = 0;
+
boot_freemem:
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
+ return ret;
+}
+
+static void beiscsi_boot_release(void *data)
+{
+ struct beiscsi_hba *phba = data;
+
+ scsi_host_put(phba->shost);
+}
+
+static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+{
+ struct iscsi_boot_kobj *boot_kobj;
+
+ /* get boot info using mgmt cmd */
+ if (beiscsi_get_boot_info(phba))
+ /* Try to see if we can carry on without this */
+ return 0;
+
+ phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+ if (!phba->boot_kset)
+ return -ENOMEM;
+
+ /* get a ref because the show function will ref the phba */
+ if (!scsi_host_get(phba->shost))
+ goto free_kset;
+ boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+ beiscsi_show_boot_tgt_info,
+ beiscsi_tgt_get_attr_visibility,
+ beiscsi_boot_release);
+ if (!boot_kobj)
+ goto put_shost;
+
+ if (!scsi_host_get(phba->shost))
+ goto free_kset;
+ boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+ beiscsi_show_boot_ini_info,
+ beiscsi_ini_get_attr_visibility,
+ beiscsi_boot_release);
+ if (!boot_kobj)
+ goto put_shost;
+
+ if (!scsi_host_get(phba->shost))
+ goto free_kset;
+ boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+ beiscsi_show_boot_eth_info,
+ beiscsi_eth_get_attr_visibility,
+ beiscsi_boot_release);
+ if (!boot_kobj)
+ goto put_shost;
+ return 0;
+
+put_shost:
+ scsi_host_put(phba->shost);
+free_kset:
+ iscsi_boot_destroy_kset(phba->boot_kset);
return -ENOMEM;
}
@@ -3963,11 +3988,10 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
}
memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
dw[offsetof(struct amap_pdu_data_out, lun) / 32],
- io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+ &io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
- cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
- lun[0]));
+ cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
io_task->pwrb_handle->wrb_index);
@@ -4025,11 +4049,11 @@ static int beiscsi_mtask(struct iscsi_task *task)
TGT_DM_CMD);
AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
pwrb, 0);
- AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+ AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
} else {
AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
INI_RD_CMD);
- AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
+ AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
}
hwi_write_buffer(pwrb, task);
break;
@@ -4100,9 +4124,8 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
}
-static void beiscsi_remove(struct pci_dev *pcidev)
+static void beiscsi_quiesce(struct beiscsi_hba *phba)
{
- struct beiscsi_hba *phba = NULL;
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
struct be_eq_obj *pbe_eq;
@@ -4110,12 +4133,6 @@ static void beiscsi_remove(struct pci_dev *pcidev)
u8 *real_offset = 0;
u32 value = 0;
- phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
- if (!phba) {
- dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n");
- return;
- }
-
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
hwi_disable_intr(phba);
@@ -4123,6 +4140,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
for (i = 0; i <= phba->num_cpus; i++) {
msix_vec = phba->msix_entries[i].vector;
free_irq(msix_vec, &phwi_context->be_eq[i]);
+ kfree(phba->msi_name[i]);
}
} else
if (phba->pcidev->irq)
@@ -4150,11 +4168,40 @@ static void beiscsi_remove(struct pci_dev *pcidev)
phba->ctrl.mbox_mem_alloced.size,
phba->ctrl.mbox_mem_alloced.va,
phba->ctrl.mbox_mem_alloced.dma);
- if (phba->boot_kset)
- iscsi_boot_destroy_kset(phba->boot_kset);
+}
+
+static void beiscsi_remove(struct pci_dev *pcidev)
+{
+
+ struct beiscsi_hba *phba = NULL;
+
+ phba = pci_get_drvdata(pcidev);
+ if (!phba) {
+ dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n");
+ return;
+ }
+
+ beiscsi_quiesce(phba);
+ iscsi_boot_destroy_kset(phba->boot_kset);
iscsi_host_remove(phba->shost);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
+ pci_disable_device(pcidev);
+}
+
+static void beiscsi_shutdown(struct pci_dev *pcidev)
+{
+
+ struct beiscsi_hba *phba = NULL;
+
+ phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
+ if (!phba) {
+ dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n");
+ return;
+ }
+
+ beiscsi_quiesce(phba);
+ pci_disable_device(pcidev);
}
static void beiscsi_msix_enable(struct beiscsi_hba *phba)
@@ -4234,7 +4281,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
gcrashmode++;
shost_printk(KERN_ERR, phba->shost,
"Loading Driver in crashdump mode\n");
- ret = beiscsi_pci_soft_reset(phba);
+ ret = beiscsi_cmd_reset_function(phba);
if (ret) {
shost_printk(KERN_ERR, phba->shost,
"Reset Failed. Aborting Crashdump\n");
@@ -4310,11 +4357,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
goto free_blkenbld;
}
hwi_enable_intr(phba);
- ret = beiscsi_get_boot_info(phba);
- if (ret < 0) {
- shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
- "No Boot Devices !!!!!\n");
- }
+
+ if (beiscsi_setup_boot_info(phba))
+ /*
+ * log error but continue, because we may not be using
+ * iscsi boot.
+ */
+ shost_printk(KERN_ERR, phba->shost, "Could not set up "
+ "iSCSI boot info.");
+
SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
return 0;
@@ -4346,9 +4397,9 @@ free_port:
hba_free:
if (phba->msix_enabled)
pci_disable_msix(phba->pcidev);
- iscsi_host_remove(phba->shost);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
+ pci_set_drvdata(pcidev, NULL);
disable_pci:
pci_disable_device(pcidev);
return ret;
@@ -4359,37 +4410,12 @@ struct iscsi_transport beiscsi_iscsi_transport = {
.name = DRV_NAME,
.caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_ERL |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME,
.create_session = beiscsi_session_create,
.destroy_session = beiscsi_session_destroy,
.create_conn = beiscsi_conn_create,
.bind_conn = beiscsi_conn_bind,
.destroy_conn = iscsi_conn_teardown,
+ .attr_is_visible = be2iscsi_attr_is_visible,
.set_param = beiscsi_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_session_param = iscsi_session_get_param,
@@ -4413,6 +4439,7 @@ static struct pci_driver beiscsi_pci_driver = {
.name = DRV_NAME,
.probe = beiscsi_dev_probe,
.remove = beiscsi_remove,
+ .shutdown = beiscsi_shutdown,
.id_table = beiscsi_pci_id_table
};
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 081c171..b4a06d5 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -34,7 +34,7 @@
#include "be.h"
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "2.103.298.0"
+#define BUILD_STR "4.1.239.0"
#define BE_NAME "ServerEngines BladeEngine2" \
"Linux iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@@ -162,6 +162,8 @@ do { \
#define PAGES_REQUIRED(x) \
((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE))
+#define BEISCSI_MSI_NAME 20 /* size of msi_name string */
+
enum be_mem_enum {
HWI_MEM_ADDN_CONTEXT,
HWI_MEM_WRB,
@@ -287,6 +289,7 @@ struct beiscsi_hba {
unsigned int num_cpus;
unsigned int nxt_cqid;
struct msix_entry msix_entries[MAX_CPUS + 1];
+ char *msi_name[MAX_CPUS + 1];
bool msix_enabled;
struct be_mem_descriptor *init_mem;
@@ -397,7 +400,7 @@ struct amap_pdu_data_out {
};
struct be_cmd_bhs {
- struct iscsi_cmd iscsi_hdr;
+ struct iscsi_scsi_req iscsi_hdr;
unsigned char pad1[16];
struct pdu_data_out iscsi_data_pdu;
unsigned char pad2[BE_SENSE_INFO_SIZE -
@@ -428,7 +431,7 @@ struct be_nonio_bhs {
};
struct be_status_bhs {
- struct iscsi_cmd iscsi_hdr;
+ struct iscsi_scsi_req iscsi_hdr;
unsigned char pad1[16];
/**
* The plus 2 below is to hold the sense info length that gets
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index 97a61b4..e1f1e34 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -19,6 +19,23 @@ struct b577xx_doorbell_hdr {
/*
* doorbell message sent to the chip
*/
+struct b577xx_doorbell {
+#if defined(__BIG_ENDIAN)
+ u16 zero_fill2;
+ u8 zero_fill1;
+ struct b577xx_doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct b577xx_doorbell_hdr header;
+ u8 zero_fill1;
+ u16 zero_fill2;
+#endif
+};
+
+
+
+/*
+ * doorbell message sent to the chip
+ */
struct b577xx_doorbell_set_prod {
#if defined(__BIG_ENDIAN)
u16 prod;
@@ -39,106 +56,63 @@ struct regpair {
/*
- * Fixed size structure in order to plant it in Union structure
+ * ABTS info $$KEEP_ENDIANNESS$$
*/
-struct fcoe_abts_rsp_union {
- u32 r_ctl;
- u32 abts_rsp_payload[7];
+struct fcoe_abts_info {
+ __le16 aborted_task_id;
+ __le16 reserved0;
+ __le32 reserved1;
};
/*
- * 4 regs size
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
*/
-struct fcoe_bd_ctx {
- u32 buf_addr_hi;
- u32 buf_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 rsrv0;
- u16 buf_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 buf_len;
- u16 rsrv0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 rsrv1;
- u16 flags;
-#elif defined(__LITTLE_ENDIAN)
- u16 flags;
- u16 rsrv1;
-#endif
+struct fcoe_abts_rsp_union {
+ u8 r_ctl;
+ u8 rsrv[3];
+ __le32 abts_rsp_payload[7];
};
-struct fcoe_cleanup_flow_info {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 task_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 task_id;
- u16 reserved1;
-#endif
- u32 reserved2[7];
+/*
+ * 4 regs size $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_bd_ctx {
+ __le32 buf_addr_hi;
+ __le32 buf_addr_lo;
+ __le16 buf_len;
+ __le16 rsrv0;
+ __le16 flags;
+ __le16 rsrv1;
};
-struct fcoe_fcp_cmd_payload {
- u32 opaque[8];
-};
-
-struct fcoe_fc_hdr {
-#if defined(__BIG_ENDIAN)
- u8 cs_ctl;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 cs_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 r_ctl;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 r_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 seq_id;
- u8 df_ctl;
- u16 seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 seq_cnt;
- u8 df_ctl;
- u8 seq_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 type;
- u8 f_ctl[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 f_ctl[3];
- u8 type;
-#endif
- u32 parameters;
-#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#endif
+/*
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cached_sge_ctx {
+ struct regpair cur_buf_addr;
+ __le16 cur_buf_rem;
+ __le16 second_buf_rem;
+ struct regpair second_buf_addr;
};
-struct fcoe_fc_frame {
- struct fcoe_fc_hdr fc_hdr;
- u32 reserved0[2];
-};
-union fcoe_cmd_flow_info {
- struct fcoe_fcp_cmd_payload fcp_cmd_payload;
- struct fcoe_fc_frame mp_fc_frame;
+/*
+ * Cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cleanup_info {
+ __le16 cleaned_task_id;
+ __le16 rolled_tx_seq_cnt;
+ __le32 rolled_tx_data_offset;
};
-
+/*
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
+ */
struct fcoe_fcp_rsp_flags {
u8 flags;
#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
@@ -155,95 +129,168 @@ struct fcoe_fcp_rsp_flags {
#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
};
-
+/*
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
+ */
struct fcoe_fcp_rsp_payload {
struct regpair reserved0;
- u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
- u16 retry_delay_timer;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u8 scsi_status_code;
-#elif defined(__LITTLE_ENDIAN)
+ __le32 fcp_resid;
u8 scsi_status_code;
struct fcoe_fcp_rsp_flags fcp_flags;
- u16 retry_delay_timer;
-#endif
- u32 fcp_rsp_len;
- u32 fcp_sns_len;
+ __le16 retry_delay_timer;
+ __le32 fcp_rsp_len;
+ __le32 fcp_sns_len;
};
-
/*
* Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
*/
struct fcoe_fcp_rsp_union {
struct fcoe_fcp_rsp_payload payload;
struct regpair reserved0;
};
+/*
+ * FC header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_hdr {
+ u8 s_id[3];
+ u8 cs_ctl;
+ u8 d_id[3];
+ u8 r_ctl;
+ __le16 seq_cnt;
+ u8 df_ctl;
+ u8 seq_id;
+ u8 f_ctl[3];
+ u8 type;
+ __le32 parameters;
+ __le16 rx_id;
+ __le16 ox_id;
+};
-struct fcoe_fcp_xfr_rdy_payload {
- u32 burst_len;
- u32 data_ro;
+/*
+ * FC header union $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mp_rsp_union {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 mp_payload_len;
+ __le32 rsrv;
};
-struct fcoe_read_flow_info {
- struct fcoe_fc_hdr fc_data_in_hdr;
- u32 reserved[2];
+/*
+ * Completion information $$KEEP_ENDIANNESS$$
+ */
+union fcoe_comp_flow_info {
+ struct fcoe_fcp_rsp_union fcp_rsp;
+ struct fcoe_abts_rsp_union abts_rsp;
+ struct fcoe_mp_rsp_union mp_rsp;
+ __le32 opaque[8];
};
-struct fcoe_write_flow_info {
- struct fcoe_fc_hdr fc_data_out_hdr;
- struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
+
+/*
+ * External ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_abts_info {
+ __le32 rsrv0[6];
+ struct fcoe_abts_info ctx;
};
-union fcoe_rsp_flow_info {
- struct fcoe_fcp_rsp_union fcp_rsp;
- struct fcoe_abts_rsp_union abts_rsp;
+
+/*
+ * External cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_cleanup_info {
+ __le32 rsrv0[6];
+ struct fcoe_cleanup_info ctx;
};
+
/*
- * 32 bytes used for general purposes
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
*/
-union fcoe_general_task_ctx {
- union fcoe_cmd_flow_info cmd_info;
- struct fcoe_read_flow_info read_info;
- struct fcoe_write_flow_info write_info;
- union fcoe_rsp_flow_info rsp_info;
- struct fcoe_cleanup_flow_info cleanup_info;
- u32 comp_info[8];
+struct fcoe_fw_tx_seq_ctx {
+ __le32 data_offset;
+ __le16 seq_cnt;
+ __le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+ __le32 rsrv0[6];
+ struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+ struct regpair cur_sge_addr;
+ __le16 cur_sge_off;
+ u8 cur_sge_idx;
+ u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+ struct fcoe_mul_sges_ctx mul_sgl;
+ struct regpair rsrv0;
};
/*
- * FCoE KCQ CQE parameters
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+ __le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+ __le32 burst_len;
+ __le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
*/
union fcoe_kcqe_params {
- u32 reserved0[4];
+ __le32 reserved0[4];
};
/*
- * FCoE KCQ CQE
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_kcqe {
- u32 fcoe_conn_id;
- u32 completion_status;
- u32 fcoe_conn_context_id;
+ __le32 fcoe_conn_id;
+ __le32 completion_status;
+ __le32 fcoe_conn_context_id;
union fcoe_kcqe_params params;
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
- u8 op_code;
- u16 qe_self_seq;
-#elif defined(__LITTLE_ENDIAN)
- u16 qe_self_seq;
+ __le16 qe_self_seq;
u8 op_code;
u8 flags;
#define FCOE_KCQE_RESERVED0 (0x7<<0)
@@ -254,23 +301,14 @@ struct fcoe_kcqe {
#define FCOE_KCQE_LAYER_CODE_SHIFT 4
#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
-#endif
};
+
+
/*
- * FCoE KWQE header
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_header {
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
- u8 op_code;
-#elif defined(__LITTLE_ENDIAN)
u8 op_code;
u8 flags;
#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
@@ -279,50 +317,23 @@ struct fcoe_kwqe_header {
#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-#endif
};
/*
- * FCoE firmware init request 1
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init1 {
-#if defined(__BIG_ENDIAN)
+ __le16 num_tasks;
struct fcoe_kwqe_header hdr;
- u16 num_tasks;
-#elif defined(__LITTLE_ENDIAN)
- u16 num_tasks;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 task_list_pbl_addr_lo;
- u32 task_list_pbl_addr_hi;
- u32 dummy_buffer_addr_lo;
- u32 dummy_buffer_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rq_num_wqes;
- u16 sq_num_wqes;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_num_wqes;
- u16 rq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 cq_num_wqes;
- u16 rq_buffer_log_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_buffer_log_size;
- u16 cq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
- u8 num_sessions_log;
- u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
- u16 mtu;
+ __le32 task_list_pbl_addr_lo;
+ __le32 task_list_pbl_addr_hi;
+ __le32 dummy_buffer_addr_lo;
+ __le32 dummy_buffer_addr_hi;
+ __le16 sq_num_wqes;
+ __le16 rq_num_wqes;
+ __le16 rq_buffer_log_size;
+ __le16 cq_num_wqes;
+ __le16 mtu;
u8 num_sessions_log;
u8 flags;
#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
@@ -331,113 +342,73 @@ struct fcoe_kwqe_init1 {
#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-#endif
};
/*
- * FCoE firmware init request 2
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init2 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ u8 hsi_major_version;
+ u8 hsi_minor_version;
struct fcoe_kwqe_header hdr;
-#endif
- u32 hash_tbl_pbl_addr_lo;
- u32 hash_tbl_pbl_addr_hi;
- u32 t2_hash_tbl_addr_lo;
- u32 t2_hash_tbl_addr_hi;
- u32 t2_ptr_hash_tbl_addr_lo;
- u32 t2_ptr_hash_tbl_addr_hi;
- u32 free_list_count;
+ __le32 hash_tbl_pbl_addr_lo;
+ __le32 hash_tbl_pbl_addr_hi;
+ __le32 t2_hash_tbl_addr_lo;
+ __le32 t2_hash_tbl_addr_hi;
+ __le32 t2_ptr_hash_tbl_addr_lo;
+ __le32 t2_ptr_hash_tbl_addr_hi;
+ __le32 free_list_count;
};
/*
- * FCoE firmware init request 3
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u32 error_bit_map_lo;
- u32 error_bit_map_hi;
-#if defined(__BIG_ENDIAN)
- u8 reserved21[3];
- u8 cached_session_enable;
-#elif defined(__LITTLE_ENDIAN)
- u8 cached_session_enable;
+ __le32 error_bit_map_lo;
+ __le32 error_bit_map_hi;
+ u8 perf_config;
u8 reserved21[3];
-#endif
- u32 reserved2[4];
+ __le32 reserved2[4];
};
/*
- * FCoE connection offload request 1
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
+ __le16 fcoe_conn_id;
struct fcoe_kwqe_header hdr;
- u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 fcoe_conn_id;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 sq_addr_lo;
- u32 sq_addr_hi;
- u32 rq_pbl_addr_lo;
- u32 rq_pbl_addr_hi;
- u32 rq_first_pbe_addr_lo;
- u32 rq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 rq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_prod;
- u16 reserved0;
-#endif
+ __le32 sq_addr_lo;
+ __le32 sq_addr_hi;
+ __le32 rq_pbl_addr_lo;
+ __le32 rq_pbl_addr_hi;
+ __le32 rq_first_pbe_addr_lo;
+ __le32 rq_first_pbe_addr_hi;
+ __le16 rq_prod;
+ __le16 reserved0;
};
/*
- * FCoE connection offload request 2
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload2 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_max_fc_pay_len;
+ __le16 tx_max_fc_pay_len;
struct fcoe_kwqe_header hdr;
-#endif
- u32 cq_addr_lo;
- u32 cq_addr_hi;
- u32 xferq_addr_lo;
- u32 xferq_addr_hi;
- u32 conn_db_addr_lo;
- u32 conn_db_addr_hi;
- u32 reserved1;
+ __le32 cq_addr_lo;
+ __le32 cq_addr_hi;
+ __le32 xferq_addr_lo;
+ __le32 xferq_addr_hi;
+ __le32 conn_db_addr_lo;
+ __le32 conn_db_addr_hi;
+ __le32 reserved1;
};
/*
- * FCoE connection offload request 3
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
- u16 vlan_tag;
+ __le16 vlan_tag;
#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
@@ -445,34 +416,8 @@ struct fcoe_kwqe_conn_offload3 {
#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
struct fcoe_kwqe_header hdr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 tx_max_conc_seqs_c3;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 s_id[3];
u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
u8 flags;
#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
@@ -491,79 +436,44 @@ struct fcoe_kwqe_conn_offload3 {
#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-#endif
- u32 reserved;
- u32 confq_first_pbe_addr_lo;
- u32 confq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 tx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 rx_open_seqs_exch_c3;
- u8 rx_max_conc_seqs_c3;
- u16 rx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_total_conc_seqs;
+ __le32 reserved;
+ __le32 confq_first_pbe_addr_lo;
+ __le32 confq_first_pbe_addr_hi;
+ __le16 tx_total_conc_seqs;
+ __le16 rx_max_fc_pay_len;
+ __le16 rx_total_conc_seqs;
u8 rx_max_conc_seqs_c3;
u8 rx_open_seqs_exch_c3;
-#endif
};
/*
- * FCoE connection offload request 4
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u8 reserved2;
- u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
u8 e_d_tov_timer_val;
u8 reserved2;
struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u8 dst_mac_addr_hi16[2];
-#endif
- u8 dst_mac_addr_lo32[4];
- u32 lcq_addr_lo;
- u32 lcq_addr_hi;
- u32 confq_pbl_base_addr_lo;
- u32 confq_pbl_base_addr_hi;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u8 dst_mac_addr_hi[2];
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ __le32 lcq_addr_lo;
+ __le32 lcq_addr_hi;
+ __le32 confq_pbl_base_addr_lo;
+ __le32 confq_pbl_base_addr_hi;
};
/*
- * FCoE connection enable request
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_enable_disable {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
u16 vlan_tag;
#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
@@ -571,82 +481,52 @@ struct fcoe_kwqe_conn_enable_disable {
#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-#endif
- u8 dst_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 dst_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u16 reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ u8 dst_mac_addr_hi[2];
+ __le16 reserved1;
u8 s_id[3];
u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved3;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
u8 reserved3;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved4;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved4;
};
/*
- * FCoE connection destroy request
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved1[5];
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved1[5];
};
/*
- * FCoe destroy request
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u32 reserved1[7];
+ __le32 reserved1[7];
};
/*
- * FCoe statistics request
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_stat {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 stat_params_addr_lo;
- u32 stat_params_addr_hi;
- u32 reserved1[5];
+ __le32 stat_params_addr_lo;
+ __le32 stat_params_addr_hi;
+ __le32 reserved1[5];
};
/*
- * FCoE KWQ WQE
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
*/
union fcoe_kwqe {
struct fcoe_kwqe_init1 init1;
@@ -662,19 +542,42 @@ union fcoe_kwqe {
struct fcoe_kwqe_stat statistics;
};
-struct fcoe_mul_sges_ctx {
- struct regpair cur_sge_addr;
-#if defined(__BIG_ENDIAN)
- u8 sgl_size;
- u8 cur_sge_idx;
- u16 cur_sge_off;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_sge_off;
- u8 cur_sge_idx;
- u8 sgl_size;
-#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+ struct fcoe_cached_sge_ctx cached_sge;
+ struct fcoe_ext_mul_sges_ctx sgl;
+ __le32 opaque[5];
};
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
struct fcoe_s_stat_ctx {
u8 flags;
#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
@@ -693,51 +596,34 @@ struct fcoe_s_stat_ctx {
#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
};
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
- u16 low_seq_cnt;
- struct fcoe_s_stat_ctx s_stat;
- u8 seq_id;
-#elif defined(__LITTLE_ENDIAN)
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
u8 seq_id;
struct fcoe_s_stat_ctx s_stat;
- u16 low_seq_cnt;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 err_seq_cnt;
- u16 high_seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 high_seq_cnt;
- u16 err_seq_cnt;
-#endif
- u32 low_exp_ro;
- u32 high_exp_ro;
+ __le16 seq_cnt;
+ __le32 low_exp_ro;
+ __le32 high_exp_ro;
};
-struct fcoe_single_sge_ctx {
- struct regpair cur_buf_addr;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 cur_buf_rem;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_buf_rem;
- u16 reserved0;
-#endif
-};
-
-union fcoe_sgl_ctx {
- struct fcoe_single_sge_ctx single_sge;
- struct fcoe_mul_sges_ctx mul_sges;
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+ struct fcoe_read_flow_info read_info;
+ union fcoe_comp_flow_info comp_info;
+ __le32 opaque[8];
};
/*
- * FCoE SQ element
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_sqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_SQE_TASK_ID (0x7FFF<<0)
#define FCOE_SQE_TASK_ID_SHIFT 0
#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
@@ -746,135 +632,141 @@ struct fcoe_sqe {
-struct fcoe_task_ctx_entry_tx_only {
- union fcoe_sgl_ctx sgl_ctx;
+/*
+ * 14 regs $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_only {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0;
};
-struct fcoe_task_ctx_entry_txwr_rxrd {
-#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+ struct fcoe_fc_frame tx_frame;
+ struct fcoe_fcp_cmd_payload fcp_cmd;
+ struct fcoe_ext_cleanup_info cleanup;
+ struct fcoe_ext_abts_info abts;
+ struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+ __le32 opaque[8];
+};
+
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u16 verify_tx_seq;
-#endif
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+ __le16 rsrv3;
+ __le32 verify_tx_seq;
};
/*
- * Common section. Both TX and RX processing might write and read from it in
- * different flows
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
*/
-struct fcoe_task_ctx_entry_tx_rx_cmn {
- u32 data_2_trns;
- union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
- u16 tx_low_seq_cnt;
- struct fcoe_s_stat_ctx tx_s_stat;
- u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_seq_id;
- struct fcoe_s_stat_ctx tx_s_stat;
- u16 tx_low_seq_cnt;
-#endif
- u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
-};
-
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
- u16 rx_id;
-#endif
+struct fcoe_tce_tx_wr_rx_rd {
+ union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
};
-struct fcoe_task_ctx_entry_rx_only {
- struct fcoe_seq_ctx seq_ctx;
- struct fcoe_seq_ctx ooo_seq_ctx;
- u32 rsrv3;
- union fcoe_sgl_ctx sgl_ctx;
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+ __le32 data_2_trns;
+ __le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+ __le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+ __le16 rx_id;
+ struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+ struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+ struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+ struct fcoe_rx_seq_ctx rx_seq_ctx;
+ union fcoe_rx_wr_union_ctx union_ctx;
};
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
struct fcoe_task_ctx_entry {
- struct fcoe_task_ctx_entry_tx_only tx_wr_only;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr_only;
- u32 reserved[4];
+ struct fcoe_tce_tx_only txwr_only;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr_only;
};
+
+
+
+
+
+
+
+
/*
- * FCoE XFRQ element
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_xfrqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
#define FCOE_XFRQE_TASK_ID_SHIFT 0
#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
@@ -883,22 +775,31 @@ struct fcoe_xfrqe {
/*
- * FCoE CONFQ element
+ * fcoe rx doorbell message sent to the chip $$KEEP_ENDIANNESS$$
+ */
+struct b577xx_fcoe_rx_doorbell {
+ struct b577xx_doorbell_hdr hdr;
+ u8 params;
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM (0x1F<<0)
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT 0
+#define B577XX_FCOE_RX_DOORBELL_OPCODE (0x7<<5)
+#define B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT 5
+ __le16 doorbell_cq_cons;
+};
+
+
+/*
+ * FCoE CONFQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_confqe {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#endif
- u32 param;
+ __le16 ox_id;
+ __le16 rx_id;
+ __le32 param;
};
/*
- * FCoE connection data base
+ * FCoE conection data base
*/
struct fcoe_conn_db {
#if defined(__BIG_ENDIAN)
@@ -914,10 +815,10 @@ struct fcoe_conn_db {
/*
- * FCoE CQ element
+ * FCoE CQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_CQE_CQE_INFO (0x3FFF<<0)
#define FCOE_CQE_CQE_INFO_SHIFT 0
#define FCOE_CQE_CQE_TYPE (0x1<<14)
@@ -928,61 +829,46 @@ struct fcoe_cqe {
/*
- * FCoE error/warning resporting entry
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_partial_err_report_entry {
+ __le32 err_warn_bitmap_lo;
+ __le32 err_warn_bitmap_hi;
+ __le32 tx_buf_off;
+ __le32 rx_buf_off;
+};
+
+/*
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
*/
struct fcoe_err_report_entry {
- u32 err_warn_bitmap_lo;
- u32 err_warn_bitmap_hi;
- u32 tx_buf_off;
- u32 rx_buf_off;
+ struct fcoe_partial_err_report_entry data;
struct fcoe_fc_hdr fc_hdr;
};
/*
- * FCoE hash table entry (32 bytes)
+ * FCoE hash table entry (32 bytes) $$KEEP_ENDIANNESS$$
*/
struct fcoe_hash_table_entry {
-#if defined(__BIG_ENDIAN)
- u8 d_id_0;
- u8 s_id_2;
- u8 s_id_1;
- u8 s_id_0;
-#elif defined(__LITTLE_ENDIAN)
u8 s_id_0;
u8 s_id_1;
u8 s_id_2;
u8 d_id_0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 dst_mac_addr_hi;
- u8 d_id_2;
- u8 d_id_1;
-#elif defined(__LITTLE_ENDIAN)
u8 d_id_1;
u8 d_id_2;
- u16 dst_mac_addr_hi;
-#endif
- u32 dst_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 vlan_id;
- u16 src_mac_addr_hi;
-#elif defined(__LITTLE_ENDIAN)
- u16 src_mac_addr_hi;
- u16 vlan_id;
-#endif
- u32 src_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 vlan_flag;
-#elif defined(__LITTLE_ENDIAN)
+ __le16 dst_mac_addr_hi;
+ __le16 dst_mac_addr_mid;
+ __le16 dst_mac_addr_lo;
+ __le16 src_mac_addr_hi;
+ __le16 vlan_id;
+ __le16 src_mac_addr_lo;
+ __le16 src_mac_addr_mid;
u8 vlan_flag;
u8 reserved0;
- u16 reserved1;
-#endif
- u32 reserved2;
- u32 field_id;
+ __le16 reserved1;
+ __le32 reserved2;
+ __le32 field_id;
#define FCOE_HASH_TABLE_ENTRY_CID (0xFFFFFF<<0)
#define FCOE_HASH_TABLE_ENTRY_CID_SHIFT 0
#define FCOE_HASH_TABLE_ENTRY_RESERVED3 (0x7F<<24)
@@ -991,11 +877,27 @@ struct fcoe_hash_table_entry {
#define FCOE_HASH_TABLE_ENTRY_VALID_SHIFT 31
};
+
/*
- * FCoE pending work request CQE
+ * FCoE LCQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_lcqe {
+ __le32 wqe;
+#define FCOE_LCQE_TASK_ID (0xFFFF<<0)
+#define FCOE_LCQE_TASK_ID_SHIFT 0
+#define FCOE_LCQE_LCQE_TYPE (0xFF<<16)
+#define FCOE_LCQE_LCQE_TYPE_SHIFT 16
+#define FCOE_LCQE_RESERVED (0xFF<<24)
+#define FCOE_LCQE_RESERVED_SHIFT 24
+};
+
+
+
+/*
+ * FCoE pending work request CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_pend_wq_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_PEND_WQ_CQE_TASK_ID (0x3FFF<<0)
#define FCOE_PEND_WQ_CQE_TASK_ID_SHIFT 0
#define FCOE_PEND_WQ_CQE_CQE_TYPE (0x1<<14)
@@ -1006,53 +908,61 @@ struct fcoe_pend_wq_cqe {
/*
- * FCoE RX statistics parameters section#0
+ * FCoE RX statistics parameters section#0 $$KEEP_ENDIANNESS$$
*/
struct fcoe_rx_stat_params_section0 {
- u32 fcoe_ver_cnt;
- u32 fcoe_rx_pkt_cnt;
- u32 fcoe_rx_byte_cnt;
- u32 fcoe_rx_drop_pkt_cnt;
+ __le32 fcoe_rx_pkt_cnt;
+ __le32 fcoe_rx_byte_cnt;
};
/*
- * FCoE RX statistics parameters section#1
+ * FCoE RX statistics parameters section#1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_rx_stat_params_section1 {
- u32 fc_crc_cnt;
- u32 eofa_del_cnt;
- u32 miss_frame_cnt;
- u32 seq_timeout_cnt;
- u32 drop_seq_cnt;
- u32 fcoe_rx_drop_pkt_cnt;
- u32 fcp_rx_pkt_cnt;
- u32 reserved0;
+ __le32 fcoe_ver_cnt;
+ __le32 fcoe_rx_drop_pkt_cnt;
+};
+
+
+/*
+ * FCoE RX statistics parameters section#2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_stat_params_section2 {
+ __le32 fc_crc_cnt;
+ __le32 eofa_del_cnt;
+ __le32 miss_frame_cnt;
+ __le32 seq_timeout_cnt;
+ __le32 drop_seq_cnt;
+ __le32 fcoe_rx_drop_pkt_cnt;
+ __le32 fcp_rx_pkt_cnt;
+ __le32 reserved0;
};
/*
- * FCoE TX statistics parameters
+ * FCoE TX statistics parameters $$KEEP_ENDIANNESS$$
*/
struct fcoe_tx_stat_params {
- u32 fcoe_tx_pkt_cnt;
- u32 fcoe_tx_byte_cnt;
- u32 fcp_tx_pkt_cnt;
- u32 reserved0;
+ __le32 fcoe_tx_pkt_cnt;
+ __le32 fcoe_tx_byte_cnt;
+ __le32 fcp_tx_pkt_cnt;
+ __le32 reserved0;
};
/*
- * FCoE statistics parameters
+ * FCoE statistics parameters $$KEEP_ENDIANNESS$$
*/
struct fcoe_statistics_params {
struct fcoe_tx_stat_params tx_stat;
struct fcoe_rx_stat_params_section0 rx_stat0;
struct fcoe_rx_stat_params_section1 rx_stat1;
+ struct fcoe_rx_stat_params_section2 rx_stat2;
};
/*
- * FCoE t2 hash table entry (64 bytes)
+ * FCoE t2 hash table entry (64 bytes) $$KEEP_ENDIANNESS$$
*/
struct fcoe_t2_hash_table_entry {
struct fcoe_hash_table_entry data;
@@ -1060,11 +970,13 @@ struct fcoe_t2_hash_table_entry {
struct regpair reserved0[3];
};
+
+
/*
- * FCoE unsolicited CQE
+ * FCoE unsolicited CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_unsolicited_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_UNSOLICITED_CQE_SUBTYPE (0x3<<0)
#define FCOE_UNSOLICITED_CQE_SUBTYPE_SHIFT 0
#define FCOE_UNSOLICITED_CQE_PKT_LEN (0xFFF<<2)
@@ -1075,6 +987,4 @@ struct fcoe_unsolicited_cqe {
#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT_SHIFT 15
};
-
-
#endif /* __57XX_FCOE_HSI_LINUX_LE__ */
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
index 6a38080..cfcad8b 100644
--- a/drivers/scsi/bnx2fc/Kconfig
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -2,7 +2,8 @@ config SCSI_BNX2X_FCOE
tristate "Broadcom NetXtreme II FCoE support"
depends on PCI
select NETDEVICES
- select NETDEV_1000
+ select ETHERNET
+ select NET_VENDOR_BROADCOM
select LIBFC
select LIBFCOE
select CNIC
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 856fcbf..049ea90 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -2,7 +2,7 @@
#define _BNX2FC_H_
/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
*
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom Corporation
*
* 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
@@ -58,11 +58,11 @@
#include "57xx_hsi_bnx2fc.h"
#include "bnx2fc_debug.h"
-#include "../../net/cnic_if.h"
+#include "../../net/ethernet/broadcom/cnic_if.h"
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "1.0.1"
+#define BNX2FC_VERSION "1.0.9"
#define PFX "bnx2fc: "
@@ -81,7 +81,7 @@
#define BNX2FC_RQ_WQES_MAX 16
#define BNX2FC_CQ_WQES_MAX (BNX2FC_SQ_WQES_MAX + BNX2FC_RQ_WQES_MAX)
-#define BNX2FC_NUM_MAX_SESS 128
+#define BNX2FC_NUM_MAX_SESS 1024
#define BNX2FC_NUM_MAX_SESS_LOG (ilog2(BNX2FC_NUM_MAX_SESS))
#define BNX2FC_MAX_OUTSTANDING_CMNDS 2048
@@ -141,6 +141,13 @@
#define BNX2FC_RNID_HBA 0x7
+#define SRR_RETRY_COUNT 5
+#define REC_RETRY_COUNT 1
+#define BNX2FC_NUM_ERR_BITS 63
+
+#define BNX2FC_RELOGIN_WAIT_TIME 200
+#define BNX2FC_RELOGIN_WAIT_CNT 10
+
/* bnx2fc driver uses only one instance of fcoe_percpu_s */
extern struct fcoe_percpu_s bnx2fc_global;
@@ -153,18 +160,13 @@ struct bnx2fc_percpu_s {
};
struct bnx2fc_hba {
- struct list_head link;
+ struct list_head list;
struct cnic_dev *cnic;
struct pci_dev *pcidev;
- struct net_device *netdev;
struct net_device *phys_dev;
unsigned long reg_with_cnic;
#define BNX2FC_CNIC_REGISTERED 1
- struct packet_type fcoe_packet_type;
- struct packet_type fip_packet_type;
struct bnx2fc_cmd_mgr *cmd_mgr;
- struct workqueue_struct *timer_work_queue;
- struct kref kref;
spinlock_t hba_lock;
struct mutex hba_mutex;
unsigned long adapter_state;
@@ -172,15 +174,9 @@ struct bnx2fc_hba {
#define ADAPTER_STATE_GOING_DOWN 1
#define ADAPTER_STATE_LINK_DOWN 2
#define ADAPTER_STATE_READY 3
- u32 flags;
- unsigned long init_done;
- #define BNX2FC_FW_INIT_DONE 0
- #define BNX2FC_CTLR_INIT_DONE 1
- #define BNX2FC_CREATE_DONE 2
- struct fcoe_ctlr ctlr;
- struct list_head vports;
- u8 vlan_enabled;
- int vlan_id;
+ unsigned long flags;
+ #define BNX2FC_FLAG_FW_INIT_DONE 0
+ #define BNX2FC_FLAG_DESTROY_CMPL 1
u32 next_conn_id;
struct fcoe_task_ctx_entry **task_ctx;
dma_addr_t *task_ctx_dma;
@@ -199,38 +195,42 @@ struct bnx2fc_hba {
char *dummy_buffer;
dma_addr_t dummy_buf_dma;
+ /* Active list of offloaded sessions */
+ struct bnx2fc_rport **tgt_ofld_list;
+
+ /* statistics */
struct fcoe_statistics_params *stats_buffer;
dma_addr_t stats_buf_dma;
-
- /*
- * PCI related info.
- */
- u16 pci_did;
- u16 pci_vid;
- u16 pci_sdid;
- u16 pci_svid;
- u16 pci_func;
- u16 pci_devno;
-
- struct task_struct *l2_thread;
-
- /* linkdown handling */
- wait_queue_head_t shutdown_wait;
- int wait_for_link_down;
+ struct completion stat_req_done;
/*destroy handling */
struct timer_list destroy_timer;
wait_queue_head_t destroy_wait;
- /* Active list of offloaded sessions */
- struct bnx2fc_rport *tgt_ofld_list[BNX2FC_NUM_MAX_SESS];
+ /* linkdown handling */
+ wait_queue_head_t shutdown_wait;
+ int wait_for_link_down;
int num_ofld_sess;
+ struct list_head vports;
+};
- /* statistics */
- struct completion stat_req_done;
+struct bnx2fc_interface {
+ struct list_head list;
+ unsigned long if_flags;
+ #define BNX2FC_CTLR_INIT_DONE 0
+ struct bnx2fc_hba *hba;
+ struct net_device *netdev;
+ struct packet_type fcoe_packet_type;
+ struct packet_type fip_packet_type;
+ struct workqueue_struct *timer_work_queue;
+ struct kref kref;
+ struct fcoe_ctlr ctlr;
+ u8 vlan_enabled;
+ int vlan_id;
+ bool enabled;
};
-#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_hba, ctlr)
+#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_interface, ctlr)
struct bnx2fc_lport {
struct list_head list;
@@ -252,9 +252,11 @@ struct bnx2fc_rport {
struct fc_rport_priv *rdata;
void __iomem *ctx_base;
#define DPM_TRIGER_TYPE 0x40
+ u32 io_timeout;
u32 fcoe_conn_id;
u32 context_id;
u32 sid;
+ int dev_type;
unsigned long flags;
#define BNX2FC_FLAG_SESSION_READY 0x1
@@ -262,14 +264,18 @@ struct bnx2fc_rport {
#define BNX2FC_FLAG_DISABLED 0x3
#define BNX2FC_FLAG_DESTROYED 0x4
#define BNX2FC_FLAG_OFLD_REQ_CMPL 0x5
-#define BNX2FC_FLAG_DESTROY_CMPL 0x6
-#define BNX2FC_FLAG_CTX_ALLOC_FAILURE 0x7
-#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x8
-#define BNX2FC_FLAG_EXPL_LOGO 0x9
+#define BNX2FC_FLAG_CTX_ALLOC_FAILURE 0x6
+#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x7
+#define BNX2FC_FLAG_EXPL_LOGO 0x8
+ u8 src_addr[ETH_ALEN];
u32 max_sqes;
u32 max_rqes;
u32 max_cqes;
+ atomic_t free_sqes;
+
+ struct b577xx_doorbell_set_prod sq_db;
+ struct b577xx_fcoe_rx_doorbell rx_db;
struct fcoe_sqe *sq;
dma_addr_t sq_dma;
@@ -279,7 +285,7 @@ struct bnx2fc_rport {
struct fcoe_cqe *cq;
dma_addr_t cq_dma;
- u32 cq_cons_idx;
+ u16 cq_cons_idx;
u8 cq_curr_toggle_bit;
u32 cq_mem_size;
@@ -322,12 +328,9 @@ struct bnx2fc_rport {
spinlock_t cq_lock;
atomic_t num_active_ios;
u32 flush_in_prog;
- unsigned long work_time_slice;
unsigned long timestamp;
struct list_head free_task_list;
struct bnx2fc_cmd *pending_queue[BNX2FC_SQ_WQES_MAX+1];
- atomic_t pi;
- atomic_t ci;
struct list_head active_cmd_queue;
struct list_head els_queue;
struct list_head io_retire_queue;
@@ -362,6 +365,8 @@ struct bnx2fc_els_cb_arg {
struct bnx2fc_cmd *aborted_io_req;
struct bnx2fc_cmd *io_req;
u16 l2_oxid;
+ u32 offset;
+ enum fc_rctl r_ctl;
};
/* bnx2fc command structure */
@@ -375,6 +380,7 @@ struct bnx2fc_cmd {
#define BNX2FC_ABTS 3
#define BNX2FC_ELS 4
#define BNX2FC_CLEANUP 5
+#define BNX2FC_SEQ_CLEANUP 6
u8 io_req_flags;
struct kref refcount;
struct fcoe_port *port;
@@ -388,6 +394,7 @@ struct bnx2fc_cmd {
struct completion tm_done;
int wait_for_comp;
u16 xid;
+ struct fcoe_err_report_entry err_entry;
struct fcoe_task_ctx_entry *task;
struct io_bdt *bd_tbl;
struct fcp_rsp *rsp;
@@ -404,6 +411,12 @@ struct bnx2fc_cmd {
#define BNX2FC_FLAG_IO_COMPL 0x9
#define BNX2FC_FLAG_ELS_DONE 0xa
#define BNX2FC_FLAG_ELS_TIMEOUT 0xb
+#define BNX2FC_FLAG_CMD_LOST 0xc
+#define BNX2FC_FLAG_SRR_SENT 0xd
+ u8 rec_retry;
+ u8 srr_retry;
+ u32 srr_offset;
+ u8 srr_rctl;
u32 fcp_resid;
u32 fcp_rsp_len;
u32 fcp_sns_len;
@@ -434,6 +447,7 @@ struct bnx2fc_unsol_els {
+struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt);
struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type);
void bnx2fc_cmd_release(struct kref *ref);
int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd);
@@ -471,6 +485,10 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req);
void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
u16 orig_xid);
+void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnup_req,
+ struct fcoe_task_ctx_entry *task,
+ struct bnx2fc_cmd *orig_io_req,
+ u32 offset);
void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task);
void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
@@ -511,6 +529,7 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
struct fc_frame *,
void *),
void *arg, u32 timeout);
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt);
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
@@ -519,5 +538,13 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
unsigned char *buf,
u32 frame_len, u16 l2_oxid);
int bnx2fc_send_stat_req(struct bnx2fc_hba *hba);
+int bnx2fc_post_io_req(struct bnx2fc_rport *tgt, struct bnx2fc_cmd *io_req);
+int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req);
+int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl);
+void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnup_req,
+ struct fcoe_task_ctx_entry *task,
+ u8 rx_state);
+int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset,
+ enum fc_rctl r_ctl);
#endif
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index fe77691..399cda0 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -5,6 +5,12 @@
* This file defines HSI constants for the FCoE flows
*/
+/* Current FCoE HSI version number composed of two fields (16 bit) */
+/* Implies on a change broken previous HSI */
+#define FCOE_HSI_MAJOR_VERSION (1)
+/* Implies on a change which does not broken previous HSI */
+#define FCOE_HSI_MINOR_VERSION (1)
+
/* KWQ/KCQ FCoE layer code */
#define FCOE_KWQE_LAYER_CODE (7)
@@ -40,21 +46,62 @@
#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3)
#define FCOE_KCQE_COMPLETION_STATUS_CTX_FREE_FAILURE (0x4)
#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR (0x5)
+#define FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION (0x6)
+
+/* CQE type */
+#define FCOE_PENDING_CQE_TYPE 0
+#define FCOE_UNSOLIC_CQE_TYPE 1
/* Unsolicited CQE type */
#define FCOE_UNSOLICITED_FRAME_CQE_TYPE 0
#define FCOE_ERROR_DETECTION_CQE_TYPE 1
#define FCOE_WARNING_DETECTION_CQE_TYPE 2
+/* E_D_TOV timer resolution in ms */
+#define FCOE_E_D_TOV_TIMER_RESOLUTION_MS (20)
+
+/* E_D_TOV timer resolution for SDM (4 micro) */
+#define FCOE_E_D_TOV_SDM_TIMER_RESOLUTION \
+ (FCOE_E_D_TOV_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* REC timer resolution in ms */
+#define FCOE_REC_TIMER_RESOLUTION_MS (20)
+
+/* REC timer resolution for SDM (4 micro) */
+#define FCOE_REC_SDM_TIMER_RESOLUTION (FCOE_REC_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* E_D_TOV timer default wraparound value (2 sec) in 20 ms resolution */
+#define FCOE_E_D_TOV_DEFAULT_WRAPAROUND_VAL \
+ (2000 / FCOE_E_D_TOV_TIMER_RESOLUTION_MS)
+
+/* REC_TOV timer default wraparound value (3 sec) in 20 ms resolution */
+#define FCOE_REC_TOV_DEFAULT_WRAPAROUND_VAL \
+ (3000 / FCOE_REC_TIMER_RESOLUTION_MS)
+
+#define FCOE_NUM_OF_TIMER_TASKS (8 * 1024)
+
+#define FCOE_NUM_OF_CACHED_TASKS_TIMER (8)
+
/* Task context constants */
+/******** Remove FCP_CMD write tce sleep ***********************/
+/* In case timer services are required then shall be updated by Xstorm after
+ * start processing the task. In case no timer facilities are required then the
+ * driver would initialize the state to this value
+ *
+#define FCOE_TASK_TX_STATE_NORMAL 0
+ * After driver has initialize the task in case timer services required *
+#define FCOE_TASK_TX_STATE_INIT 1
+******** Remove FCP_CMD write tce sleep ***********************/
/* After driver has initialize the task in case timer services required */
#define FCOE_TASK_TX_STATE_INIT 0
/* In case timer services are required then shall be updated by Xstorm after
* start processing the task. In case no timer facilities are required then the
- * driver would initialize the state to this value */
+ * driver would initialize the state to this value
+ */
#define FCOE_TASK_TX_STATE_NORMAL 1
/* Task is under abort procedure. Updated in order to stop processing of
- * pending WQEs on this task */
+ * pending WQEs on this task
+ */
#define FCOE_TASK_TX_STATE_ABORT 2
/* For E_D_T_TOV timer expiration in Xstorm (Class 2 only) */
#define FCOE_TASK_TX_STATE_ERROR 3
@@ -66,17 +113,8 @@
#define FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP 6
/* For sequence cleanup request task */
#define FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP 7
-/* Mark task as aborted and indicate that ABTS was not transmitted */
-#define FCOE_TASK_TX_STATE_BEFORE_ABTS_TX 8
-/* Mark task as aborted and indicate that ABTS was transmitted */
-#define FCOE_TASK_TX_STATE_AFTER_ABTS_TX 9
/* For completion the ABTS task. */
-#define FCOE_TASK_TX_STATE_ABTS_TX_COMPLETED 10
-/* Mark task as aborted and indicate that Exchange cleanup was not transmitted
- */
-#define FCOE_TASK_TX_STATE_BEFORE_EXCHANGE_CLEANUP_TX 11
-/* Mark task as aborted and indicate that Exchange cleanup was transmitted */
-#define FCOE_TASK_TX_STATE_AFTER_EXCHANGE_CLEANUP_TX 12
+#define FCOE_TASK_TX_STATE_ABTS_TX 8
#define FCOE_TASK_RX_STATE_NORMAL 0
#define FCOE_TASK_RX_STATE_COMPLETED 1
@@ -86,25 +124,25 @@
#define FCOE_TASK_RX_STATE_WARNING 3
/* For E_D_T_TOV timer expiration in Ustorm */
#define FCOE_TASK_RX_STATE_ERROR 4
-/* ABTS ACC arrived wait for local completion to finally complete the task. */
-#define FCOE_TASK_RX_STATE_ABTS_ACC_ARRIVED 5
-/* local completion arrived wait for ABTS ACC to finally complete the task. */
-#define FCOE_TASK_RX_STATE_ABTS_LOCAL_COMP_ARRIVED 6
+/* FW only: First visit at rx-path, part of the abts round trip */
+#define FCOE_TASK_RX_STATE_ABTS_IN_PROCESS 5
+/* FW only: Second visit at rx-path, after ABTS frame transmitted */
+#define FCOE_TASK_RX_STATE_ABTS_TRANSMITTED 6
/* Special completion indication in case of task was aborted. */
#define FCOE_TASK_RX_STATE_ABTS_COMPLETED 7
-/* Special completion indication in case of task was cleaned. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED 8
-/* Special completion indication (in task requested the exchange cleanup) in
- * case cleaned task is in non-valid. */
-#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED 9
+/* FW only: First visit at rx-path, part of the cleanup round trip */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_IN_PROCESS 8
+/* FW only: Special completion indication in case of task was cleaned. */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED 9
+/* Not in used: Special completion indication (in task requested the exchange
+ * cleanup) in case cleaned task is in non-valid.
+ */
+#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED 10
/* Special completion indication (in task requested the sequence cleanup) in
- * case cleaned task was already returned to normal. */
-#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP 10
-/* Exchange cleanup arrived wait until xfer will be handled to finally
- * complete the task. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_ARRIVED 11
-/* Xfer handled, wait for exchange cleanup to finally complete the task. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_HANDLED_XFER 12
+ * case cleaned task was already returned to normal.
+ */
+#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP 11
+
#define FCOE_TASK_TYPE_WRITE 0
#define FCOE_TASK_TYPE_READ 1
@@ -120,11 +158,40 @@
#define FCOE_TASK_CLASS_TYPE_3 0
#define FCOE_TASK_CLASS_TYPE_2 1
+/* FCoE/FC packet fields */
+#define FCOE_ETH_TYPE 0x8906
+
+/* FCoE maximum elements in hash table */
+#define FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW 8
+
+/* FCoE half of the elements in hash table */
+#define FCOE_HALF_ELEMENTS_IN_HASH_TABLE_ROW \
+ (FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW / 2)
+
+/* FcoE number of cached T2 entries */
+#define T_FCOE_NUMBER_OF_CACHED_T2_ENTRIES (4)
+
+/* FCoE maximum elements in hash table */
+#define FCOE_HASH_TBL_CHUNK_SIZE 16384
+
/* Everest FCoE connection type */
#define B577XX_FCOE_CONNECTION_TYPE 4
-/* Error codes for Error Reporting in fast path flows */
-/* XFER error codes */
+/* FCoE number of rows (in log). This number derives
+ * from the maximum connections supported which is 2048.
+ * TBA: Need a different constant for E2
+ */
+#define FCOE_MAX_NUM_SESSIONS_LOG 11
+
+#define FC_ABTS_REPLY_MAX_PAYLOAD_LEN 12
+
+/* Error codes for Error Reporting in slow path flows */
+#define FCOE_SLOW_PATH_ERROR_CODE_TOO_MANY_FUNCS 0
+#define FCOE_SLOW_PATH_ERROR_CODE_NO_LICENSE 1
+
+/* Error codes for Error Reporting in fast path flows
+ * XFER error codes
+ */
#define FCOE_ERROR_CODE_XFER_OOO_RO 0
#define FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED 1
#define FCOE_ERROR_CODE_XFER_NULL_BURST_LEN 2
@@ -155,17 +222,17 @@
#define FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET 23
#define FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET 24
#define FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET 25
-#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET 26
-#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ 27
+#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET 26
+#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ 27
#define FCOE_ERROR_CODE_DATA_FCTL 28
/* Middle path error codes */
-#define FCOE_ERROR_CODE_MIDPATH_TYPE_NOT_ELS 29
+#define FCOE_ERROR_CODE_MIDPATH_INVALID_TYPE 29
#define FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET 30
#define FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET 31
#define FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET 32
#define FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET 33
-#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_FCTL 34
+#define FCOE_ERROR_CODE_MIDPATH_REPLY_FCTL 34
#define FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY 35
#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL 36
@@ -173,7 +240,7 @@
#define FCOE_ERROR_CODE_ABTS_REPLY_F_CTL 37
#define FCOE_ERROR_CODE_ABTS_REPLY_DDF_RCTL_FIELD 38
#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_BLS_RCTL 39
-#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL 40
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL 40
#define FCOE_ERROR_CODE_ABTS_REPLY_RCTL_GENERAL_MISMATCH 41
/* Common error codes */
@@ -185,7 +252,7 @@
#define FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES 47
#define FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR 48
#define FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG 49
-#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED 50
+#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED 50
/* Unsolicited Rx error codes */
#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_ELS 51
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h
index 7f6aff6..3416d9a 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h
@@ -21,21 +21,21 @@ extern unsigned int bnx2fc_debug_level;
#define BNX2FC_ELS_DBG(fmt, arg...) \
BNX2FC_CHK_LOGGING(LOG_ELS, \
- printk(KERN_ALERT PFX fmt, ##arg))
+ printk(KERN_INFO PFX fmt, ##arg))
#define BNX2FC_MISC_DBG(fmt, arg...) \
BNX2FC_CHK_LOGGING(LOG_MISC, \
- printk(KERN_ALERT PFX fmt, ##arg))
+ printk(KERN_INFO PFX fmt, ##arg))
#define BNX2FC_IO_DBG(io_req, fmt, arg...) \
do { \
if (!io_req || !io_req->port || !io_req->port->lport || \
!io_req->port->lport->host) \
BNX2FC_CHK_LOGGING(LOG_IO, \
- printk(KERN_ALERT PFX "NULL " fmt, ##arg)); \
+ printk(KERN_INFO PFX "NULL " fmt, ##arg)); \
else \
BNX2FC_CHK_LOGGING(LOG_IO, \
- shost_printk(KERN_ALERT, \
+ shost_printk(KERN_INFO, \
(io_req)->port->lport->host, \
PFX "xid:0x%x " fmt, \
(io_req)->xid, ##arg)); \
@@ -46,10 +46,10 @@ extern unsigned int bnx2fc_debug_level;
if (!tgt || !tgt->port || !tgt->port->lport || \
!tgt->port->lport->host || !tgt->rport) \
BNX2FC_CHK_LOGGING(LOG_TGT, \
- printk(KERN_ALERT PFX "NULL " fmt, ##arg)); \
+ printk(KERN_INFO PFX "NULL " fmt, ##arg)); \
else \
BNX2FC_CHK_LOGGING(LOG_TGT, \
- shost_printk(KERN_ALERT, \
+ shost_printk(KERN_INFO, \
(tgt)->port->lport->host, \
PFX "port:%x " fmt, \
(tgt)->rport->port_id, ##arg)); \
@@ -60,10 +60,10 @@ extern unsigned int bnx2fc_debug_level;
do { \
if (!lport || !lport->host) \
BNX2FC_CHK_LOGGING(LOG_HBA, \
- printk(KERN_ALERT PFX "NULL " fmt, ##arg)); \
+ printk(KERN_INFO PFX "NULL " fmt, ##arg)); \
else \
BNX2FC_CHK_LOGGING(LOG_HBA, \
- shost_printk(KERN_ALERT, lport->host, \
+ shost_printk(KERN_INFO, lport->host, \
PFX fmt, ##arg)); \
} while (0)
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index 52c3584..ce0ce3e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -3,7 +3,7 @@
* This file contains helper routines that handle ELS requests
* and responses.
*
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom Corporation
*
* 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
@@ -83,7 +83,7 @@ int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
rrq.rrq_cmd = ELS_RRQ;
hton24(rrq.rrq_s_id, sid);
rrq.rrq_ox_id = htons(aborted_io_req->xid);
- rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
+ rrq.rrq_rx_id = htons(aborted_io_req->task->rxwr_txrd.var_ctx.rx_id);
retry_rrq:
rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
@@ -253,13 +253,420 @@ int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
return rc;
}
+void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+ struct bnx2fc_mp_req *mp_req;
+ struct fc_frame_header *fc_hdr, *fh;
+ struct bnx2fc_cmd *srr_req;
+ struct bnx2fc_cmd *orig_io_req;
+ struct fc_frame *fp;
+ unsigned char *buf;
+ void *resp_buf;
+ u32 resp_len, hdr_len;
+ u8 opcode;
+ int rc = 0;
+
+ orig_io_req = cb_arg->aborted_io_req;
+ srr_req = cb_arg->io_req;
+ if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &srr_req->req_flags)) {
+ /* SRR timedout */
+ BNX2FC_IO_DBG(srr_req, "srr timed out, abort "
+ "orig_io - 0x%x\n",
+ orig_io_req->xid);
+ rc = bnx2fc_initiate_abts(srr_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
+ "failed. issue cleanup\n");
+ bnx2fc_initiate_cleanup(srr_req);
+ }
+ if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
+ test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+ BNX2FC_IO_DBG(srr_req, "srr_compl:xid 0x%x flags = %lx",
+ orig_io_req->xid, orig_io_req->req_flags);
+ goto srr_compl_done;
+ }
+ orig_io_req->srr_retry++;
+ if (orig_io_req->srr_retry <= SRR_RETRY_COUNT) {
+ struct bnx2fc_rport *tgt = orig_io_req->tgt;
+ spin_unlock_bh(&tgt->tgt_lock);
+ rc = bnx2fc_send_srr(orig_io_req,
+ orig_io_req->srr_offset,
+ orig_io_req->srr_rctl);
+ spin_lock_bh(&tgt->tgt_lock);
+ if (!rc)
+ goto srr_compl_done;
+ }
+
+ rc = bnx2fc_initiate_abts(orig_io_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
+ "failed xid = 0x%x. issue cleanup\n",
+ orig_io_req->xid);
+ bnx2fc_initiate_cleanup(orig_io_req);
+ }
+ goto srr_compl_done;
+ }
+ if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
+ test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+ BNX2FC_IO_DBG(srr_req, "srr_compl:xid - 0x%x flags = %lx",
+ orig_io_req->xid, orig_io_req->req_flags);
+ goto srr_compl_done;
+ }
+ mp_req = &(srr_req->mp_req);
+ fc_hdr = &(mp_req->resp_fc_hdr);
+ resp_len = mp_req->resp_len;
+ resp_buf = mp_req->resp_buf;
+
+ hdr_len = sizeof(*fc_hdr);
+ buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+ if (!buf) {
+ printk(KERN_ERR PFX "srr buf: mem alloc failure\n");
+ goto srr_compl_done;
+ }
+ memcpy(buf, fc_hdr, hdr_len);
+ memcpy(buf + hdr_len, resp_buf, resp_len);
+
+ fp = fc_frame_alloc(NULL, resp_len);
+ if (!fp) {
+ printk(KERN_ERR PFX "fc_frame_alloc failure\n");
+ goto free_buf;
+ }
+
+ fh = (struct fc_frame_header *) fc_frame_header_get(fp);
+ /* Copy FC Frame header and payload into the frame */
+ memcpy(fh, buf, hdr_len + resp_len);
+
+ opcode = fc_frame_payload_op(fp);
+ switch (opcode) {
+ case ELS_LS_ACC:
+ BNX2FC_IO_DBG(srr_req, "SRR success\n");
+ break;
+ case ELS_LS_RJT:
+ BNX2FC_IO_DBG(srr_req, "SRR rejected\n");
+ rc = bnx2fc_initiate_abts(orig_io_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
+ "failed xid = 0x%x. issue cleanup\n",
+ orig_io_req->xid);
+ bnx2fc_initiate_cleanup(orig_io_req);
+ }
+ break;
+ default:
+ BNX2FC_IO_DBG(srr_req, "srr compl - invalid opcode = %d\n",
+ opcode);
+ break;
+ }
+ fc_frame_free(fp);
+free_buf:
+ kfree(buf);
+srr_compl_done:
+ kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+}
+
+void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+ struct bnx2fc_cmd *orig_io_req, *new_io_req;
+ struct bnx2fc_cmd *rec_req;
+ struct bnx2fc_mp_req *mp_req;
+ struct fc_frame_header *fc_hdr, *fh;
+ struct fc_els_ls_rjt *rjt;
+ struct fc_els_rec_acc *acc;
+ struct bnx2fc_rport *tgt;
+ struct fcoe_err_report_entry *err_entry;
+ struct scsi_cmnd *sc_cmd;
+ enum fc_rctl r_ctl;
+ unsigned char *buf;
+ void *resp_buf;
+ struct fc_frame *fp;
+ u8 opcode;
+ u32 offset;
+ u32 e_stat;
+ u32 resp_len, hdr_len;
+ int rc = 0;
+ bool send_seq_clnp = false;
+ bool abort_io = false;
+
+ BNX2FC_MISC_DBG("Entered rec_compl callback\n");
+ rec_req = cb_arg->io_req;
+ orig_io_req = cb_arg->aborted_io_req;
+ BNX2FC_IO_DBG(rec_req, "rec_compl: orig xid = 0x%x", orig_io_req->xid);
+ tgt = orig_io_req->tgt;
+
+ /* Handle REC timeout case */
+ if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rec_req->req_flags)) {
+ BNX2FC_IO_DBG(rec_req, "timed out, abort "
+ "orig_io - 0x%x\n",
+ orig_io_req->xid);
+ /* els req is timed out. send abts for els */
+ rc = bnx2fc_initiate_abts(rec_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
+ "failed. issue cleanup\n");
+ bnx2fc_initiate_cleanup(rec_req);
+ }
+ orig_io_req->rec_retry++;
+ /* REC timedout. send ABTS to the orig IO req */
+ if (orig_io_req->rec_retry <= REC_RETRY_COUNT) {
+ spin_unlock_bh(&tgt->tgt_lock);
+ rc = bnx2fc_send_rec(orig_io_req);
+ spin_lock_bh(&tgt->tgt_lock);
+ if (!rc)
+ goto rec_compl_done;
+ }
+ rc = bnx2fc_initiate_abts(orig_io_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
+ "failed xid = 0x%x. issue cleanup\n",
+ orig_io_req->xid);
+ bnx2fc_initiate_cleanup(orig_io_req);
+ }
+ goto rec_compl_done;
+ }
+
+ if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
+ BNX2FC_IO_DBG(rec_req, "completed"
+ "orig_io - 0x%x\n",
+ orig_io_req->xid);
+ goto rec_compl_done;
+ }
+ if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+ BNX2FC_IO_DBG(rec_req, "abts in prog "
+ "orig_io - 0x%x\n",
+ orig_io_req->xid);
+ goto rec_compl_done;
+ }
+
+ mp_req = &(rec_req->mp_req);
+ fc_hdr = &(mp_req->resp_fc_hdr);
+ resp_len = mp_req->resp_len;
+ acc = resp_buf = mp_req->resp_buf;
+
+ hdr_len = sizeof(*fc_hdr);
+
+ buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+ if (!buf) {
+ printk(KERN_ERR PFX "rec buf: mem alloc failure\n");
+ goto rec_compl_done;
+ }
+ memcpy(buf, fc_hdr, hdr_len);
+ memcpy(buf + hdr_len, resp_buf, resp_len);
+
+ fp = fc_frame_alloc(NULL, resp_len);
+ if (!fp) {
+ printk(KERN_ERR PFX "fc_frame_alloc failure\n");
+ goto free_buf;
+ }
+
+ fh = (struct fc_frame_header *) fc_frame_header_get(fp);
+ /* Copy FC Frame header and payload into the frame */
+ memcpy(fh, buf, hdr_len + resp_len);
+
+ opcode = fc_frame_payload_op(fp);
+ if (opcode == ELS_LS_RJT) {
+ BNX2FC_IO_DBG(rec_req, "opcode is RJT\n");
+ rjt = fc_frame_payload_get(fp, sizeof(*rjt));
+ if ((rjt->er_reason == ELS_RJT_LOGIC ||
+ rjt->er_reason == ELS_RJT_UNAB) &&
+ rjt->er_explan == ELS_EXPL_OXID_RXID) {
+ BNX2FC_IO_DBG(rec_req, "handle CMD LOST case\n");
+ new_io_req = bnx2fc_cmd_alloc(tgt);
+ if (!new_io_req)
+ goto abort_io;
+ new_io_req->sc_cmd = orig_io_req->sc_cmd;
+ /* cleanup orig_io_req that is with the FW */
+ set_bit(BNX2FC_FLAG_CMD_LOST,
+ &orig_io_req->req_flags);
+ bnx2fc_initiate_cleanup(orig_io_req);
+ /* Post a new IO req with the same sc_cmd */
+ BNX2FC_IO_DBG(rec_req, "Post IO request again\n");
+ spin_unlock_bh(&tgt->tgt_lock);
+ rc = bnx2fc_post_io_req(tgt, new_io_req);
+ spin_lock_bh(&tgt->tgt_lock);
+ if (!rc)
+ goto free_frame;
+ BNX2FC_IO_DBG(rec_req, "REC: io post err\n");
+ }
+abort_io:
+ rc = bnx2fc_initiate_abts(orig_io_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
+ "failed. issue cleanup\n");
+ bnx2fc_initiate_cleanup(orig_io_req);
+ }
+ } else if (opcode == ELS_LS_ACC) {
+ /* REVISIT: Check if the exchange is already aborted */
+ offset = ntohl(acc->reca_fc4value);
+ e_stat = ntohl(acc->reca_e_stat);
+ if (e_stat & ESB_ST_SEQ_INIT) {
+ BNX2FC_IO_DBG(rec_req, "target has the seq init\n");
+ goto free_frame;
+ }
+ BNX2FC_IO_DBG(rec_req, "e_stat = 0x%x, offset = 0x%x\n",
+ e_stat, offset);
+ /* Seq initiative is with us */
+ err_entry = (struct fcoe_err_report_entry *)
+ &orig_io_req->err_entry;
+ sc_cmd = orig_io_req->sc_cmd;
+ if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
+ /* SCSI WRITE command */
+ if (offset == orig_io_req->data_xfer_len) {
+ BNX2FC_IO_DBG(rec_req, "WRITE - resp lost\n");
+ /* FCP_RSP lost */
+ r_ctl = FC_RCTL_DD_CMD_STATUS;
+ offset = 0;
+ } else {
+ /* start transmitting from offset */
+ BNX2FC_IO_DBG(rec_req, "XFER_RDY/DATA lost\n");
+ send_seq_clnp = true;
+ r_ctl = FC_RCTL_DD_DATA_DESC;
+ if (bnx2fc_initiate_seq_cleanup(orig_io_req,
+ offset, r_ctl))
+ abort_io = true;
+ /* XFER_RDY */
+ }
+ } else {
+ /* SCSI READ command */
+ if (err_entry->data.rx_buf_off ==
+ orig_io_req->data_xfer_len) {
+ /* FCP_RSP lost */
+ BNX2FC_IO_DBG(rec_req, "READ - resp lost\n");
+ r_ctl = FC_RCTL_DD_CMD_STATUS;
+ offset = 0;
+ } else {
+ /* request retransmission from this offset */
+ send_seq_clnp = true;
+ offset = err_entry->data.rx_buf_off;
+ BNX2FC_IO_DBG(rec_req, "RD DATA lost\n");
+ /* FCP_DATA lost */
+ r_ctl = FC_RCTL_DD_SOL_DATA;
+ if (bnx2fc_initiate_seq_cleanup(orig_io_req,
+ offset, r_ctl))
+ abort_io = true;
+ }
+ }
+ if (abort_io) {
+ rc = bnx2fc_initiate_abts(orig_io_req);
+ if (rc != SUCCESS) {
+ BNX2FC_IO_DBG(rec_req, "rec_compl:initiate_abts"
+ " failed. issue cleanup\n");
+ bnx2fc_initiate_cleanup(orig_io_req);
+ }
+ } else if (!send_seq_clnp) {
+ BNX2FC_IO_DBG(rec_req, "Send SRR - FCP_RSP\n");
+ spin_unlock_bh(&tgt->tgt_lock);
+ rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
+ spin_lock_bh(&tgt->tgt_lock);
+
+ if (rc) {
+ BNX2FC_IO_DBG(rec_req, "Unable to send SRR"
+ " IO will abort\n");
+ }
+ }
+ }
+free_frame:
+ fc_frame_free(fp);
+free_buf:
+ kfree(buf);
+rec_compl_done:
+ kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+ kfree(cb_arg);
+}
+
+int bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req)
+{
+ struct fc_els_rec rec;
+ struct bnx2fc_rport *tgt = orig_io_req->tgt;
+ struct fc_lport *lport = tgt->rdata->local_port;
+ struct bnx2fc_els_cb_arg *cb_arg = NULL;
+ u32 sid = tgt->sid;
+ u32 r_a_tov = lport->r_a_tov;
+ int rc;
+
+ BNX2FC_IO_DBG(orig_io_req, "Sending REC\n");
+ memset(&rec, 0, sizeof(rec));
+
+ cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+ if (!cb_arg) {
+ printk(KERN_ERR PFX "Unable to allocate cb_arg for REC\n");
+ rc = -ENOMEM;
+ goto rec_err;
+ }
+ kref_get(&orig_io_req->refcount);
+
+ cb_arg->aborted_io_req = orig_io_req;
+
+ rec.rec_cmd = ELS_REC;
+ hton24(rec.rec_s_id, sid);
+ rec.rec_ox_id = htons(orig_io_req->xid);
+ rec.rec_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
+
+ rc = bnx2fc_initiate_els(tgt, ELS_REC, &rec, sizeof(rec),
+ bnx2fc_rec_compl, cb_arg,
+ r_a_tov);
+rec_err:
+ if (rc) {
+ BNX2FC_IO_DBG(orig_io_req, "REC failed - release\n");
+ spin_lock_bh(&tgt->tgt_lock);
+ kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+ spin_unlock_bh(&tgt->tgt_lock);
+ kfree(cb_arg);
+ }
+ return rc;
+}
+
+int bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl)
+{
+ struct fcp_srr srr;
+ struct bnx2fc_rport *tgt = orig_io_req->tgt;
+ struct fc_lport *lport = tgt->rdata->local_port;
+ struct bnx2fc_els_cb_arg *cb_arg = NULL;
+ u32 r_a_tov = lport->r_a_tov;
+ int rc;
+
+ BNX2FC_IO_DBG(orig_io_req, "Sending SRR\n");
+ memset(&srr, 0, sizeof(srr));
+
+ cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+ if (!cb_arg) {
+ printk(KERN_ERR PFX "Unable to allocate cb_arg for SRR\n");
+ rc = -ENOMEM;
+ goto srr_err;
+ }
+ kref_get(&orig_io_req->refcount);
+
+ cb_arg->aborted_io_req = orig_io_req;
+
+ srr.srr_op = ELS_SRR;
+ srr.srr_ox_id = htons(orig_io_req->xid);
+ srr.srr_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
+ srr.srr_rel_off = htonl(offset);
+ srr.srr_r_ctl = r_ctl;
+ orig_io_req->srr_offset = offset;
+ orig_io_req->srr_rctl = r_ctl;
+
+ rc = bnx2fc_initiate_els(tgt, ELS_SRR, &srr, sizeof(srr),
+ bnx2fc_srr_compl, cb_arg,
+ r_a_tov);
+srr_err:
+ if (rc) {
+ BNX2FC_IO_DBG(orig_io_req, "SRR failed - release\n");
+ spin_lock_bh(&tgt->tgt_lock);
+ kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+ spin_unlock_bh(&tgt->tgt_lock);
+ kfree(cb_arg);
+ } else
+ set_bit(BNX2FC_FLAG_SRR_SENT, &orig_io_req->req_flags);
+
+ return rc;
+}
+
static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
void *data, u32 data_len,
void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
{
struct fcoe_port *port = tgt->port;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
struct fc_rport *rport = tgt->rport;
struct fc_lport *lport = port->lport;
struct bnx2fc_cmd *els_req;
@@ -274,12 +681,12 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
rc = fc_remote_port_chkready(rport);
if (rc) {
- printk(KERN_ALERT PFX "els 0x%x: rport not ready\n", op);
+ printk(KERN_ERR PFX "els 0x%x: rport not ready\n", op);
rc = -EINVAL;
goto els_err;
}
if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
- printk(KERN_ALERT PFX "els 0x%x: link is not ready\n", op);
+ printk(KERN_ERR PFX "els 0x%x: link is not ready\n", op);
rc = -EINVAL;
goto els_err;
}
@@ -305,7 +712,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
rc = bnx2fc_init_mp_req(els_req);
if (rc == FAILED) {
- printk(KERN_ALERT PFX "ELS MP request init failed\n");
+ printk(KERN_ERR PFX "ELS MP request init failed\n");
spin_lock_bh(&tgt->tgt_lock);
kref_put(&els_req->refcount, bnx2fc_cmd_release);
spin_unlock_bh(&tgt->tgt_lock);
@@ -324,7 +731,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
memcpy(mp_req->req_buf, data, data_len);
} else {
- printk(KERN_ALERT PFX "Invalid ELS op 0x%x\n", op);
+ printk(KERN_ERR PFX "Invalid ELS op 0x%x\n", op);
els_req->cb_func = NULL;
els_req->cb_arg = NULL;
spin_lock_bh(&tgt->tgt_lock);
@@ -342,9 +749,14 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
did = tgt->rport->port_id;
sid = tgt->sid;
- __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
- FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
- FC_FC_SEQ_INIT, 0);
+ if (op == ELS_SRR)
+ __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS4_REQ, did, sid,
+ FC_TYPE_FCP, FC_FC_FIRST_SEQ |
+ FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
+ else
+ __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
+ FC_TYPE_ELS, FC_FC_FIRST_SEQ |
+ FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
/* Obtain exchange id */
xid = els_req->xid;
@@ -352,7 +764,8 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
index = xid % BNX2FC_TASKS_PER_PAGE;
/* Initialize task context for this IO request */
- task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[task_idx];
task = &(task_page[index]);
bnx2fc_init_mp_task(els_req, task);
@@ -417,12 +830,13 @@ void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
hdr = (u64 *)fc_hdr;
temp_hdr = (u64 *)
- &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
hdr[2] = cpu_to_be64(temp_hdr[2]);
- mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+ mp_req->resp_len =
+ task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
/* Parse ELS response */
if ((els_req->cb_func) && (els_req->cb_arg)) {
@@ -495,8 +909,8 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
void *arg, u32 timeout)
{
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
- struct fcoe_ctlr *fip = &hba->ctlr;
+ struct bnx2fc_interface *interface = port->priv;
+ struct fcoe_ctlr *fip = &interface->ctlr;
struct fc_frame_header *fh = fc_frame_header_get(fp);
switch (op) {
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index bdf62a5..b215f32 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -3,7 +3,7 @@
* cnic modules to create FCoE instances, send/receive non-offloaded
* FIP/FCoE packets, listen to link events etc.
*
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom Corporation
*
* 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
@@ -15,13 +15,14 @@
#include "bnx2fc.h"
static struct list_head adapter_list;
+static struct list_head if_list;
static u32 adapter_count;
static DEFINE_MUTEX(bnx2fc_dev_lock);
DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
#define DRV_MODULE_NAME "bnx2fc"
#define DRV_MODULE_VERSION BNX2FC_VERSION
-#define DRV_MODULE_RELDATE "Mar 17, 2011"
+#define DRV_MODULE_RELDATE "Oct 21, 2011"
static char version[] __devinitdata =
@@ -55,33 +56,36 @@ static struct scsi_host_template bnx2fc_shost_template;
static struct fc_function_template bnx2fc_transport_function;
static struct fc_function_template bnx2fc_vport_xport_function;
static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
+static void __bnx2fc_destroy(struct bnx2fc_interface *interface);
static int bnx2fc_destroy(struct net_device *net_device);
static int bnx2fc_enable(struct net_device *netdev);
static int bnx2fc_disable(struct net_device *netdev);
static void bnx2fc_recv_frame(struct sk_buff *skb);
-static void bnx2fc_start_disc(struct bnx2fc_hba *hba);
+static void bnx2fc_start_disc(struct bnx2fc_interface *interface);
static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
-static int bnx2fc_net_config(struct fc_lport *lp);
static int bnx2fc_lport_config(struct fc_lport *lport);
static int bnx2fc_em_config(struct fc_lport *lport);
static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba);
static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba);
static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
-static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
struct device *parent, int npiv);
static void bnx2fc_destroy_work(struct work_struct *work);
static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
+static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
+ *phys_dev);
+static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface);
static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);
static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba);
static void bnx2fc_port_shutdown(struct fc_lport *lport);
-static void bnx2fc_stop(struct bnx2fc_hba *hba);
+static void bnx2fc_stop(struct bnx2fc_interface *interface);
static int __init bnx2fc_mod_init(void);
static void __exit bnx2fc_mod_exit(void);
@@ -95,6 +99,25 @@ static struct notifier_block bnx2fc_cpu_notifier = {
.notifier_call = bnx2fc_cpu_callback,
};
+static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport)
+{
+ return ((struct bnx2fc_interface *)
+ ((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
+}
+
+/**
+ * bnx2fc_get_lesb() - Fill the FCoE Link Error Status Block
+ * @lport: the local port
+ * @fc_lesb: the link error status block
+ */
+static void bnx2fc_get_lesb(struct fc_lport *lport,
+ struct fc_els_lesb *fc_lesb)
+{
+ struct net_device *netdev = bnx2fc_netdev(lport);
+
+ __fcoe_get_lesb(lport, fc_lesb, netdev);
+}
+
static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
{
struct fcoe_percpu_s *bg;
@@ -142,7 +165,8 @@ static void bnx2fc_abort_io(struct fc_lport *lport)
static void bnx2fc_cleanup(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct bnx2fc_rport *tgt;
int i;
@@ -219,7 +243,8 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
struct fcoe_crc_eof *cp;
struct sk_buff *skb;
struct fc_frame_header *fh;
- struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
+ struct bnx2fc_hba *hba;
struct fcoe_port *port;
struct fcoe_hdr *hp;
struct bnx2fc_rport *tgt;
@@ -230,7 +255,8 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
int wlen, rc = 0;
port = (struct fcoe_port *)lport_priv(lport);
- hba = port->priv;
+ interface = port->priv;
+ hba = interface->hba;
fh = fc_frame_header_get(fp);
@@ -242,12 +268,12 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
}
if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
- if (!hba->ctlr.sel_fcf) {
+ if (!interface->ctlr.sel_fcf) {
BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n");
kfree_skb(skb);
return -EINVAL;
}
- if (fcoe_ctlr_els_send(&hba->ctlr, lport, skb))
+ if (fcoe_ctlr_els_send(&interface->ctlr, lport, skb))
return 0;
}
@@ -296,7 +322,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
return -ENOMEM;
}
frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
- cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+ cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
+ frag->page_offset;
} else {
cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -316,19 +342,19 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
skb_reset_network_header(skb);
skb->mac_len = elen;
skb->protocol = htons(ETH_P_FCOE);
- skb->dev = hba->netdev;
+ skb->dev = interface->netdev;
/* fill up mac and fcoe headers */
eh = eth_hdr(skb);
eh->h_proto = htons(ETH_P_FCOE);
- if (hba->ctlr.map_dest)
+ if (interface->ctlr.map_dest)
fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
else
/* insert GW address */
- memcpy(eh->h_dest, hba->ctlr.dest_addr, ETH_ALEN);
+ memcpy(eh->h_dest, interface->ctlr.dest_addr, ETH_ALEN);
- if (unlikely(hba->ctlr.flogi_oxid != FC_XID_UNKNOWN))
- memcpy(eh->h_source, hba->ctlr.ctl_src_addr, ETH_ALEN);
+ if (unlikely(interface->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+ memcpy(eh->h_source, interface->ctlr.ctl_src_addr, ETH_ALEN);
else
memcpy(eh->h_source, port->data_src_addr, ETH_ALEN);
@@ -377,22 +403,30 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct net_device *olddev)
{
struct fc_lport *lport;
- struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
struct fc_frame_header *fh;
struct fcoe_rcv_info *fr;
struct fcoe_percpu_s *bg;
+ struct sk_buff *tmp_skb;
unsigned short oxid;
- hba = container_of(ptype, struct bnx2fc_hba, fcoe_packet_type);
- lport = hba->ctlr.lp;
+ interface = container_of(ptype, struct bnx2fc_interface,
+ fcoe_packet_type);
+ lport = interface->ctlr.lp;
if (unlikely(lport == NULL)) {
- printk(KERN_ALERT PFX "bnx2fc_rcv: lport is NULL\n");
+ printk(KERN_ERR PFX "bnx2fc_rcv: lport is NULL\n");
goto err;
}
+ tmp_skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!tmp_skb)
+ goto err;
+
+ skb = tmp_skb;
+
if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
- printk(KERN_ALERT PFX "bnx2fc_rcv: Wrong FC type frame\n");
+ printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n");
goto err;
}
@@ -411,7 +445,6 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
fr = fcoe_dev_from_skb(skb);
fr->fr_dev = lport;
- fr->ptype = ptype;
bg = &bnx2fc_global;
spin_lock_bh(&bg->fcoe_rx_list.lock);
@@ -469,7 +502,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
fr = fcoe_dev_from_skb(skb);
lport = fr->fr_dev;
if (unlikely(lport == NULL)) {
- printk(KERN_ALERT PFX "Invalid lport struct\n");
+ printk(KERN_ERR PFX "Invalid lport struct\n");
kfree_skb(skb);
return;
}
@@ -539,6 +572,14 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
break;
}
}
+
+ if (fh->fh_r_ctl == FC_RCTL_BA_ABTS) {
+ /* Drop incoming ABTS */
+ put_cpu();
+ kfree_skb(skb);
+ return;
+ }
+
if (le32_to_cpu(fr_crc(fp)) !=
~crc32(~0, skb->data, fr_len)) {
if (stats->InvalidCRCCount < 5)
@@ -594,7 +635,8 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
struct fc_host_statistics *bnx2fc_stats;
struct fc_lport *lport = shost_priv(shost);
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct fcoe_statistics_params *fw_stats;
int rc = 0;
@@ -612,7 +654,7 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
return bnx2fc_stats;
}
- bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat1.fc_crc_cnt;
+ bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat2.fc_crc_cnt;
bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
@@ -631,7 +673,7 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
{
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
struct Scsi_Host *shost = lport->host;
int rc = 0;
@@ -654,7 +696,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s",
BNX2FC_NAME, BNX2FC_VERSION,
- hba->netdev->name);
+ interface->netdev->name);
return 0;
}
@@ -662,11 +704,11 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
static void bnx2fc_link_speed_update(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
- struct net_device *netdev = hba->netdev;
+ struct bnx2fc_interface *interface = port->priv;
+ struct net_device *netdev = interface->netdev;
struct ethtool_cmd ecmd;
- if (!dev_ethtool_get_settings(netdev, &ecmd)) {
+ if (!__ethtool_get_settings(netdev, &ecmd)) {
lport->link_supported_speeds &=
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
@@ -679,6 +721,9 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport)
case SPEED_1000:
lport->link_speed = FC_PORTSPEED_1GBIT;
break;
+ case SPEED_2500:
+ lport->link_speed = FC_PORTSPEED_2GBIT;
+ break;
case SPEED_10000:
lport->link_speed = FC_PORTSPEED_10GBIT;
break;
@@ -688,7 +733,8 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport)
static int bnx2fc_link_ok(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct net_device *dev = hba->phys_dev;
int rc = 0;
@@ -710,20 +756,22 @@ static int bnx2fc_link_ok(struct fc_lport *lport)
*/
void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
{
- if (test_bit(__LINK_STATE_NOCARRIER, &hba->netdev->state))
+ if (test_bit(__LINK_STATE_NOCARRIER, &hba->phys_dev->state))
set_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
else
clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
}
-static int bnx2fc_net_config(struct fc_lport *lport)
+static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev)
{
struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
struct fcoe_port *port;
u64 wwnn, wwpn;
port = lport_priv(lport);
- hba = port->priv;
+ interface = port->priv;
+ hba = interface->hba;
/* require support for get_pauseparam ethtool op. */
if (!hba->phys_dev->ethtool_ops ||
@@ -740,11 +788,16 @@ static int bnx2fc_net_config(struct fc_lport *lport)
bnx2fc_link_speed_update(lport);
if (!lport->vport) {
- wwnn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 1, 0);
+ if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
+ wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr,
+ 1, 0);
BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn);
fc_set_wwnn(lport, wwnn);
- wwpn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 2, 0);
+ if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
+ wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr,
+ 2, 0);
+
BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn);
fc_set_wwpn(lport, wwpn);
}
@@ -756,9 +809,9 @@ static void bnx2fc_destroy_timer(unsigned long data)
{
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)data;
- BNX2FC_HBA_DBG(hba->ctlr.lp, "ERROR:bnx2fc_destroy_timer - "
- "Destroy compl not received!!\n");
- hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+ printk(KERN_ERR PFX "ERROR:bnx2fc_destroy_timer - "
+ "Destroy compl not received!!\n");
+ set_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
wake_up_interruptible(&hba->destroy_wait);
}
@@ -767,73 +820,85 @@ static void bnx2fc_destroy_timer(unsigned long data)
*
* @context: adapter structure pointer
* @event: event type
+ * @vlan_id: vlan id - associated vlan id with this event
*
* Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
- * NETDEV_CHANGE_MTU events
+ * NETDEV_CHANGE_MTU events. Handle NETDEV_UNREGISTER only for vlans.
*/
-static void bnx2fc_indicate_netevent(void *context, unsigned long event)
+static void bnx2fc_indicate_netevent(void *context, unsigned long event,
+ u16 vlan_id)
{
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
- struct fc_lport *lport = hba->ctlr.lp;
+ struct fc_lport *lport;
struct fc_lport *vport;
+ struct bnx2fc_interface *interface, *tmp;
+ int wait_for_upload = 0;
u32 link_possible = 1;
- if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
- BNX2FC_MISC_DBG("driver not ready. event=%s %ld\n",
- hba->netdev->name, event);
+ if (vlan_id != 0 && event != NETDEV_UNREGISTER)
return;
- }
-
- /*
- * ASSUMPTION:
- * indicate_netevent cannot be called from cnic unless bnx2fc
- * does register_device
- */
- BUG_ON(!lport);
-
- BNX2FC_HBA_DBG(lport, "enter netevent handler - event=%s %ld\n",
- hba->netdev->name, event);
switch (event) {
case NETDEV_UP:
- BNX2FC_HBA_DBG(lport, "Port up, adapter_state = %ld\n",
- hba->adapter_state);
if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
printk(KERN_ERR "indicate_netevent: "\
- "adapter is not UP!!\n");
+ "hba is not UP!!\n");
break;
case NETDEV_DOWN:
- BNX2FC_HBA_DBG(lport, "Port down\n");
clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
link_possible = 0;
break;
case NETDEV_GOING_DOWN:
- BNX2FC_HBA_DBG(lport, "Port going down\n");
set_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
link_possible = 0;
break;
case NETDEV_CHANGE:
- BNX2FC_HBA_DBG(lport, "NETDEV_CHANGE\n");
break;
+ case NETDEV_UNREGISTER:
+ if (!vlan_id)
+ return;
+ mutex_lock(&bnx2fc_dev_lock);
+ list_for_each_entry_safe(interface, tmp, &if_list, list) {
+ if (interface->hba == hba &&
+ interface->vlan_id == (vlan_id & VLAN_VID_MASK))
+ __bnx2fc_destroy(interface);
+ }
+ mutex_unlock(&bnx2fc_dev_lock);
+ return;
+
default:
printk(KERN_ERR PFX "Unkonwn netevent %ld", event);
return;
}
- bnx2fc_link_speed_update(lport);
-
- if (link_possible && !bnx2fc_link_ok(lport)) {
- printk(KERN_ERR "indicate_netevent: call ctlr_link_up\n");
- fcoe_ctlr_link_up(&hba->ctlr);
- } else {
- printk(KERN_ERR "indicate_netevent: call ctlr_link_down\n");
- if (fcoe_ctlr_link_down(&hba->ctlr)) {
- clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+ mutex_lock(&bnx2fc_dev_lock);
+ list_for_each_entry(interface, &if_list, list) {
+
+ if (interface->hba != hba)
+ continue;
+
+ lport = interface->ctlr.lp;
+ BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n",
+ interface->netdev->name, event);
+
+ bnx2fc_link_speed_update(lport);
+
+ if (link_possible && !bnx2fc_link_ok(lport)) {
+ /* Reset max recv frame size to default */
+ fc_set_mfs(lport, BNX2FC_MFS);
+ /*
+ * ctlr link up will only be handled during
+ * enable to avoid sending discovery solicitation
+ * on a stale vlan
+ */
+ if (interface->enabled)
+ fcoe_ctlr_link_up(&interface->ctlr);
+ } else if (fcoe_ctlr_link_down(&interface->ctlr)) {
mutex_lock(&lport->lp_mutex);
list_for_each_entry(vport, &lport->vports, list)
fc_host_port_type(vport->host) =
@@ -844,24 +909,26 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event)
get_cpu())->LinkFailureCount++;
put_cpu();
fcoe_clean_pending_queue(lport);
+ wait_for_upload = 1;
+ }
+ }
+ mutex_unlock(&bnx2fc_dev_lock);
- init_waitqueue_head(&hba->shutdown_wait);
- BNX2FC_HBA_DBG(lport, "indicate_netevent "
- "num_ofld_sess = %d\n",
- hba->num_ofld_sess);
- hba->wait_for_link_down = 1;
- BNX2FC_HBA_DBG(lport, "waiting for uploads to "
- "compl proc = %s\n",
- current->comm);
- wait_event_interruptible(hba->shutdown_wait,
- (hba->num_ofld_sess == 0));
- BNX2FC_HBA_DBG(lport, "wakeup - num_ofld_sess = %d\n",
+ if (wait_for_upload) {
+ clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+ init_waitqueue_head(&hba->shutdown_wait);
+ BNX2FC_MISC_DBG("indicate_netevent "
+ "num_ofld_sess = %d\n",
hba->num_ofld_sess);
- hba->wait_for_link_down = 0;
+ hba->wait_for_link_down = 1;
+ wait_event_interruptible(hba->shutdown_wait,
+ (hba->num_ofld_sess == 0));
+ BNX2FC_MISC_DBG("wakeup - num_ofld_sess = %d\n",
+ hba->num_ofld_sess);
+ hba->wait_for_link_down = 0;
- if (signal_pending(current))
- flush_signals(current);
- }
+ if (signal_pending(current))
+ flush_signals(current);
}
}
@@ -880,23 +947,12 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
static int bnx2fc_em_config(struct fc_lport *lport)
{
- struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
-
if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, FCOE_MIN_XID,
FCOE_MAX_XID, NULL)) {
printk(KERN_ERR PFX "em_config:fc_exch_mgr_alloc failed\n");
return -ENOMEM;
}
- hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
- BNX2FC_MAX_XID);
-
- if (!hba->cmd_mgr) {
- printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
- fc_exch_mgr_free(lport);
- return -ENOMEM;
- }
return 0;
}
@@ -909,11 +965,8 @@ static int bnx2fc_lport_config(struct fc_lport *lport)
lport->e_d_tov = 2 * 1000;
lport->r_a_tov = 10 * 1000;
- /* REVISIT: enable when supporting tape devices
lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
- */
- lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS);
lport->does_npiv = 1;
memset(&lport->rnid_gen, 0, sizeof(struct fc_els_rnid_gen));
@@ -943,9 +996,10 @@ static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype,
struct net_device *orig_dev)
{
- struct bnx2fc_hba *hba;
- hba = container_of(ptype, struct bnx2fc_hba, fip_packet_type);
- fcoe_ctlr_recv(&hba->ctlr, skb);
+ struct bnx2fc_interface *interface;
+ interface = container_of(ptype, struct bnx2fc_interface,
+ fip_packet_type);
+ fcoe_ctlr_recv(&interface->ctlr, skb);
return 0;
}
@@ -996,18 +1050,31 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost);
struct fcoe_port *port = lport_priv(n_port);
- struct bnx2fc_hba *hba = port->priv;
- struct net_device *netdev = hba->netdev;
+ struct bnx2fc_interface *interface = port->priv;
+ struct net_device *netdev = interface->netdev;
struct fc_lport *vn_port;
+ int rc;
+ char buf[32];
- if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+ rc = fcoe_validate_vport_create(vport);
+ if (rc) {
+ fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
+ printk(KERN_ERR PFX "Failed to create vport, "
+ "WWPN (0x%s) already exists\n",
+ buf);
+ return rc;
+ }
+
+ if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) {
printk(KERN_ERR PFX "vn ports cannot be created on"
- "this hba\n");
+ "this interface\n");
return -EIO;
}
+ rtnl_lock();
mutex_lock(&bnx2fc_dev_lock);
- vn_port = bnx2fc_if_create(hba, &vport->dev, 1);
+ vn_port = bnx2fc_if_create(interface, &vport->dev, 1);
mutex_unlock(&bnx2fc_dev_lock);
+ rtnl_unlock();
if (IS_ERR(vn_port)) {
printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
@@ -1026,16 +1093,46 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
return 0;
}
+static void bnx2fc_free_vport(struct bnx2fc_hba *hba, struct fc_lport *lport)
+{
+ struct bnx2fc_lport *blport, *tmp;
+
+ spin_lock_bh(&hba->hba_lock);
+ list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
+ if (blport->lport == lport) {
+ list_del(&blport->list);
+ kfree(blport);
+ }
+ }
+ spin_unlock_bh(&hba->hba_lock);
+}
+
static int bnx2fc_vport_destroy(struct fc_vport *vport)
{
struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost);
struct fc_lport *vn_port = vport->dd_data;
struct fcoe_port *port = lport_priv(vn_port);
+ struct bnx2fc_interface *interface = port->priv;
+ struct fc_lport *v_port;
+ bool found = false;
mutex_lock(&n_port->lp_mutex);
+ list_for_each_entry(v_port, &n_port->vports, list)
+ if (v_port->vport == vport) {
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ mutex_unlock(&n_port->lp_mutex);
+ return -ENOENT;
+ }
list_del(&vn_port->list);
mutex_unlock(&n_port->lp_mutex);
+ bnx2fc_free_vport(interface->hba, port->lport);
+ bnx2fc_port_shutdown(port->lport);
+ bnx2fc_interface_put(interface);
queue_work(bnx2fc_wq, &port->destroy_work);
return 0;
}
@@ -1056,10 +1153,10 @@ static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable)
}
-static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
+static int bnx2fc_interface_setup(struct bnx2fc_interface *interface)
{
- struct net_device *netdev = hba->netdev;
- struct net_device *physdev = hba->phys_dev;
+ struct net_device *netdev = interface->netdev;
+ struct net_device *physdev = interface->hba->phys_dev;
struct netdev_hw_addr *ha;
int sel_san_mac = 0;
@@ -1074,7 +1171,8 @@ static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
(is_valid_ether_addr(ha->addr))) {
- memcpy(hba->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+ memcpy(interface->ctlr.ctl_src_addr, ha->addr,
+ ETH_ALEN);
sel_san_mac = 1;
BNX2FC_MISC_DBG("Found SAN MAC\n");
}
@@ -1084,15 +1182,15 @@ static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
if (!sel_san_mac)
return -ENODEV;
- hba->fip_packet_type.func = bnx2fc_fip_recv;
- hba->fip_packet_type.type = htons(ETH_P_FIP);
- hba->fip_packet_type.dev = netdev;
- dev_add_pack(&hba->fip_packet_type);
+ interface->fip_packet_type.func = bnx2fc_fip_recv;
+ interface->fip_packet_type.type = htons(ETH_P_FIP);
+ interface->fip_packet_type.dev = netdev;
+ dev_add_pack(&interface->fip_packet_type);
- hba->fcoe_packet_type.func = bnx2fc_rcv;
- hba->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
- hba->fcoe_packet_type.dev = netdev;
- dev_add_pack(&hba->fcoe_packet_type);
+ interface->fcoe_packet_type.func = bnx2fc_rcv;
+ interface->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+ interface->fcoe_packet_type.dev = netdev;
+ dev_add_pack(&interface->fcoe_packet_type);
return 0;
}
@@ -1128,53 +1226,54 @@ static void bnx2fc_release_transport(void)
static void bnx2fc_interface_release(struct kref *kref)
{
- struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
struct net_device *netdev;
- struct net_device *phys_dev;
- hba = container_of(kref, struct bnx2fc_hba, kref);
+ interface = container_of(kref, struct bnx2fc_interface, kref);
BNX2FC_MISC_DBG("Interface is being released\n");
- netdev = hba->netdev;
- phys_dev = hba->phys_dev;
+ netdev = interface->netdev;
/* tear-down FIP controller */
- if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done))
- fcoe_ctlr_destroy(&hba->ctlr);
+ if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags))
+ fcoe_ctlr_destroy(&interface->ctlr);
+
+ kfree(interface);
- /* Free the command manager */
- if (hba->cmd_mgr) {
- bnx2fc_cmd_mgr_free(hba->cmd_mgr);
- hba->cmd_mgr = NULL;
- }
dev_put(netdev);
module_put(THIS_MODULE);
}
-static inline void bnx2fc_interface_get(struct bnx2fc_hba *hba)
+static inline void bnx2fc_interface_get(struct bnx2fc_interface *interface)
{
- kref_get(&hba->kref);
+ kref_get(&interface->kref);
}
-static inline void bnx2fc_interface_put(struct bnx2fc_hba *hba)
+static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface)
{
- kref_put(&hba->kref, bnx2fc_interface_release);
+ kref_put(&interface->kref, bnx2fc_interface_release);
}
-static void bnx2fc_interface_destroy(struct bnx2fc_hba *hba)
+static void bnx2fc_hba_destroy(struct bnx2fc_hba *hba)
{
+ /* Free the command manager */
+ if (hba->cmd_mgr) {
+ bnx2fc_cmd_mgr_free(hba->cmd_mgr);
+ hba->cmd_mgr = NULL;
+ }
+ kfree(hba->tgt_ofld_list);
bnx2fc_unbind_pcidev(hba);
kfree(hba);
}
/**
- * bnx2fc_interface_create - create a new fcoe instance
+ * bnx2fc_hba_create - create a new bnx2fc hba
*
* @cnic: pointer to cnic device
*
- * Creates a new FCoE instance on the given device which include allocating
- * hba structure, scsi_host and lport structures.
+ * Creates a new FCoE hba on the given device.
+ *
*/
-static struct bnx2fc_hba *bnx2fc_interface_create(struct cnic_dev *cnic)
+static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
{
struct bnx2fc_hba *hba;
int rc;
@@ -1189,65 +1288,83 @@ static struct bnx2fc_hba *bnx2fc_interface_create(struct cnic_dev *cnic)
hba->cnic = cnic;
rc = bnx2fc_bind_pcidev(hba);
- if (rc)
+ if (rc) {
+ printk(KERN_ERR PFX "create_adapter: bind error\n");
goto bind_err;
+ }
hba->phys_dev = cnic->netdev;
- /* will get overwritten after we do vlan discovery */
- hba->netdev = hba->phys_dev;
+ hba->next_conn_id = 0;
+
+ hba->tgt_ofld_list =
+ kzalloc(sizeof(struct bnx2fc_rport *) * BNX2FC_NUM_MAX_SESS,
+ GFP_KERNEL);
+ if (!hba->tgt_ofld_list) {
+ printk(KERN_ERR PFX "Unable to allocate tgt offload list\n");
+ goto tgtofld_err;
+ }
+
+ hba->num_ofld_sess = 0;
+
+ hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
+ BNX2FC_MAX_XID);
+ if (!hba->cmd_mgr) {
+ printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
+ goto cmgr_err;
+ }
init_waitqueue_head(&hba->shutdown_wait);
init_waitqueue_head(&hba->destroy_wait);
+ INIT_LIST_HEAD(&hba->vports);
return hba;
+
+cmgr_err:
+ kfree(hba->tgt_ofld_list);
+tgtofld_err:
+ bnx2fc_unbind_pcidev(hba);
bind_err:
- printk(KERN_ERR PFX "create_interface: bind error\n");
kfree(hba);
return NULL;
}
-static int bnx2fc_interface_setup(struct bnx2fc_hba *hba,
- enum fip_state fip_mode)
+struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,
+ struct net_device *netdev,
+ enum fip_state fip_mode)
{
+ struct bnx2fc_interface *interface;
int rc = 0;
- struct net_device *netdev = hba->netdev;
- struct fcoe_ctlr *fip = &hba->ctlr;
+ interface = kzalloc(sizeof(*interface), GFP_KERNEL);
+ if (!interface) {
+ printk(KERN_ERR PFX "Unable to allocate interface structure\n");
+ return NULL;
+ }
dev_hold(netdev);
- kref_init(&hba->kref);
-
- hba->flags = 0;
+ kref_init(&interface->kref);
+ interface->hba = hba;
+ interface->netdev = netdev;
/* Initialize FIP */
- memset(fip, 0, sizeof(*fip));
- fcoe_ctlr_init(fip, fip_mode);
- hba->ctlr.send = bnx2fc_fip_send;
- hba->ctlr.update_mac = bnx2fc_update_src_mac;
- hba->ctlr.get_src_addr = bnx2fc_get_src_mac;
- set_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done);
-
- INIT_LIST_HEAD(&hba->vports);
- rc = bnx2fc_netdev_setup(hba);
- if (rc)
- goto setup_err;
-
- hba->next_conn_id = 0;
+ fcoe_ctlr_init(&interface->ctlr, fip_mode);
+ interface->ctlr.send = bnx2fc_fip_send;
+ interface->ctlr.update_mac = bnx2fc_update_src_mac;
+ interface->ctlr.get_src_addr = bnx2fc_get_src_mac;
+ set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags);
- memset(hba->tgt_ofld_list, 0, sizeof(hba->tgt_ofld_list));
- hba->num_ofld_sess = 0;
-
- return 0;
+ rc = bnx2fc_interface_setup(interface);
+ if (!rc)
+ return interface;
-setup_err:
- fcoe_ctlr_destroy(&hba->ctlr);
+ fcoe_ctlr_destroy(&interface->ctlr);
dev_put(netdev);
- bnx2fc_interface_put(hba);
- return rc;
+ kfree(interface);
+ return NULL;
}
/**
* bnx2fc_if_create - Create FCoE instance on a given interface
*
- * @hba: FCoE interface to create a local port on
+ * @interface: FCoE interface to create a local port on
* @parent: Device pointer to be the parent in sysfs for the SCSI host
* @npiv: Indicates if the port is vport or not
*
@@ -1255,7 +1372,7 @@ setup_err:
*
* Returns: Allocated fc_lport or an error pointer
*/
-static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
struct device *parent, int npiv)
{
struct fc_lport *lport, *n_port;
@@ -1263,11 +1380,12 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
struct Scsi_Host *shost;
struct fc_vport *vport = dev_to_vport(parent);
struct bnx2fc_lport *blport;
+ struct bnx2fc_hba *hba;
int rc = 0;
blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL);
if (!blport) {
- BNX2FC_HBA_DBG(hba->ctlr.lp, "Unable to alloc bnx2fc_lport\n");
+ BNX2FC_HBA_DBG(interface->ctlr.lp, "Unable to alloc blport\n");
return NULL;
}
@@ -1284,7 +1402,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
shost = lport->host;
port = lport_priv(lport);
port->lport = lport;
- port->priv = hba;
+ port->priv = interface;
INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
/* Configure fcoe_port */
@@ -1299,7 +1417,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
fc_set_wwpn(lport, vport->port_name);
}
/* Configure netdev and networking properties of the lport */
- rc = bnx2fc_net_config(lport);
+ rc = bnx2fc_net_config(lport, interface->netdev);
if (rc) {
printk(KERN_ERR PFX "Error on bnx2fc_net_config\n");
goto lp_config_err;
@@ -1308,7 +1426,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
rc = bnx2fc_shost_config(lport, parent);
if (rc) {
printk(KERN_ERR PFX "Couldnt configure shost for %s\n",
- hba->netdev->name);
+ interface->netdev->name);
goto lp_config_err;
}
@@ -1334,8 +1452,9 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
goto shost_err;
}
- bnx2fc_interface_get(hba);
+ bnx2fc_interface_get(interface);
+ hba = interface->hba;
spin_lock_bh(&hba->hba_lock);
blport->lport = lport;
list_add_tail(&blport->list, &hba->vports);
@@ -1352,27 +1471,34 @@ free_blport:
return NULL;
}
-static void bnx2fc_netdev_cleanup(struct bnx2fc_hba *hba)
+static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface)
{
/* Dont listen for Ethernet packets anymore */
- __dev_remove_pack(&hba->fcoe_packet_type);
- __dev_remove_pack(&hba->fip_packet_type);
+ __dev_remove_pack(&interface->fcoe_packet_type);
+ __dev_remove_pack(&interface->fip_packet_type);
synchronize_net();
}
-static void bnx2fc_if_destroy(struct fc_lport *lport)
+static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface)
{
+ struct fc_lport *lport = interface->ctlr.lp;
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
- struct bnx2fc_lport *blport, *tmp;
+ struct bnx2fc_hba *hba = interface->hba;
- BNX2FC_HBA_DBG(hba->ctlr.lp, "ENTERED bnx2fc_if_destroy\n");
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
/* Free existing transmit skbs */
fcoe_clean_pending_queue(lport);
+ bnx2fc_net_cleanup(interface);
+
+ bnx2fc_free_vport(hba, lport);
+}
+
+static void bnx2fc_if_destroy(struct fc_lport *lport)
+{
+
/* Free queued packets for the receive thread */
bnx2fc_clean_rx_queue(lport);
@@ -1389,19 +1515,20 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
/* Free memory used by statistical counters */
fc_lport_free_stats(lport);
- spin_lock_bh(&hba->hba_lock);
- list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
- if (blport->lport == lport) {
- list_del(&blport->list);
- kfree(blport);
- }
- }
- spin_unlock_bh(&hba->hba_lock);
-
/* Release Scsi_Host */
scsi_host_put(lport->host);
+}
- bnx2fc_interface_put(hba);
+static void __bnx2fc_destroy(struct bnx2fc_interface *interface)
+{
+ struct fc_lport *lport = interface->ctlr.lp;
+ struct fcoe_port *port = lport_priv(lport);
+
+ bnx2fc_interface_cleanup(interface);
+ bnx2fc_stop(interface);
+ list_del(&interface->list);
+ bnx2fc_interface_put(interface);
+ queue_work(bnx2fc_wq, &port->destroy_work);
}
/**
@@ -1416,46 +1543,23 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
*/
static int bnx2fc_destroy(struct net_device *netdev)
{
- struct bnx2fc_hba *hba = NULL;
- struct net_device *phys_dev;
+ struct bnx2fc_interface *interface = NULL;
int rc = 0;
rtnl_lock();
-
mutex_lock(&bnx2fc_dev_lock);
- /* obtain physical netdev */
- if (netdev->priv_flags & IFF_802_1Q_VLAN)
- phys_dev = vlan_dev_real_dev(netdev);
- else {
- printk(KERN_ERR PFX "Not a vlan device\n");
- rc = -ENODEV;
- goto netdev_err;
- }
- hba = bnx2fc_hba_lookup(phys_dev);
- if (!hba || !hba->ctlr.lp) {
+ interface = bnx2fc_interface_lookup(netdev);
+ if (!interface || !interface->ctlr.lp) {
rc = -ENODEV;
- printk(KERN_ERR PFX "bnx2fc_destroy: hba or lport not found\n");
+ printk(KERN_ERR PFX "bnx2fc_destroy: interface or lport not found\n");
goto netdev_err;
}
- if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
- printk(KERN_ERR PFX "bnx2fc_destroy: Create not called\n");
- goto netdev_err;
- }
-
- bnx2fc_netdev_cleanup(hba);
-
- bnx2fc_stop(hba);
-
- bnx2fc_if_destroy(hba->ctlr.lp);
- destroy_workqueue(hba->timer_work_queue);
+ destroy_workqueue(interface->timer_work_queue);
+ __bnx2fc_destroy(interface);
- if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
- bnx2fc_fw_destroy(hba);
-
- clear_bit(BNX2FC_CREATE_DONE, &hba->init_done);
netdev_err:
mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock();
@@ -1472,12 +1576,7 @@ static void bnx2fc_destroy_work(struct work_struct *work)
BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
- bnx2fc_port_shutdown(lport);
- rtnl_lock();
- mutex_lock(&bnx2fc_dev_lock);
bnx2fc_if_destroy(lport);
- mutex_unlock(&bnx2fc_dev_lock);
- rtnl_unlock();
}
static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba)
@@ -1547,28 +1646,27 @@ static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
static void bnx2fc_ulp_start(void *handle)
{
struct bnx2fc_hba *hba = handle;
- struct fc_lport *lport = hba->ctlr.lp;
+ struct bnx2fc_interface *interface;
+ struct fc_lport *lport;
- BNX2FC_MISC_DBG("Entered %s\n", __func__);
mutex_lock(&bnx2fc_dev_lock);
- if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
- goto start_disc;
-
- if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done))
+ if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags))
bnx2fc_fw_init(hba);
-start_disc:
- mutex_unlock(&bnx2fc_dev_lock);
-
BNX2FC_MISC_DBG("bnx2fc started.\n");
- /* Kick off Fabric discovery*/
- if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
- printk(KERN_ERR PFX "ulp_init: start discovery\n");
- lport->tt.frame_send = bnx2fc_xmit;
- bnx2fc_start_disc(hba);
+ list_for_each_entry(interface, &if_list, list) {
+ if (interface->hba == hba) {
+ lport = interface->ctlr.lp;
+ /* Kick off Fabric discovery*/
+ printk(KERN_ERR PFX "ulp_init: start discovery\n");
+ lport->tt.frame_send = bnx2fc_xmit;
+ bnx2fc_start_disc(interface);
+ }
}
+
+ mutex_unlock(&bnx2fc_dev_lock);
}
static void bnx2fc_port_shutdown(struct fc_lport *lport)
@@ -1578,37 +1676,25 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport)
fc_lport_destroy(lport);
}
-static void bnx2fc_stop(struct bnx2fc_hba *hba)
+static void bnx2fc_stop(struct bnx2fc_interface *interface)
{
struct fc_lport *lport;
struct fc_lport *vport;
- BNX2FC_MISC_DBG("ENTERED %s - init_done = %ld\n", __func__,
- hba->init_done);
- if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done) &&
- test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
- lport = hba->ctlr.lp;
- bnx2fc_port_shutdown(lport);
- BNX2FC_HBA_DBG(lport, "bnx2fc_stop: waiting for %d "
- "offloaded sessions\n",
- hba->num_ofld_sess);
- wait_event_interruptible(hba->shutdown_wait,
- (hba->num_ofld_sess == 0));
- mutex_lock(&lport->lp_mutex);
- list_for_each_entry(vport, &lport->vports, list)
- fc_host_port_type(vport->host) = FC_PORTTYPE_UNKNOWN;
- mutex_unlock(&lport->lp_mutex);
- fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
- fcoe_ctlr_link_down(&hba->ctlr);
- fcoe_clean_pending_queue(lport);
-
- mutex_lock(&hba->hba_mutex);
- clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
- clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+ if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags))
+ return;
- clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
- mutex_unlock(&hba->hba_mutex);
- }
+ lport = interface->ctlr.lp;
+ bnx2fc_port_shutdown(lport);
+
+ mutex_lock(&lport->lp_mutex);
+ list_for_each_entry(vport, &lport->vports, list)
+ fc_host_port_type(vport->host) =
+ FC_PORTTYPE_UNKNOWN;
+ mutex_unlock(&lport->lp_mutex);
+ fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+ fcoe_ctlr_link_down(&interface->ctlr);
+ fcoe_clean_pending_queue(lport);
}
static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
@@ -1647,8 +1733,7 @@ static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
}
- /* Mark HBA to indicate that the FW INIT is done */
- set_bit(BNX2FC_FW_INIT_DONE, &hba->init_done);
+ set_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags);
return 0;
err_unbind:
@@ -1659,7 +1744,7 @@ err_out:
static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
{
- if (test_and_clear_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+ if (test_and_clear_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags)) {
if (bnx2fc_send_fw_fcoe_destroy_msg(hba) == 0) {
init_timer(&hba->destroy_timer);
hba->destroy_timer.expires = BNX2FC_FW_TIMEOUT +
@@ -1668,8 +1753,9 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
hba->destroy_timer.data = (unsigned long)hba;
add_timer(&hba->destroy_timer);
wait_event_interruptible(hba->destroy_wait,
- (hba->flags &
- BNX2FC_FLAG_DESTROY_CMPL));
+ test_bit(BNX2FC_FLAG_DESTROY_CMPL,
+ &hba->flags));
+ clear_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
/* This should never happen */
if (signal_pending(current))
flush_signals(current);
@@ -1690,45 +1776,67 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
*/
static void bnx2fc_ulp_stop(void *handle)
{
- struct bnx2fc_hba *hba = (struct bnx2fc_hba *)handle;
+ struct bnx2fc_hba *hba = handle;
+ struct bnx2fc_interface *interface;
printk(KERN_ERR "ULP_STOP\n");
mutex_lock(&bnx2fc_dev_lock);
- bnx2fc_stop(hba);
+ if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags))
+ goto exit;
+ list_for_each_entry(interface, &if_list, list) {
+ if (interface->hba == hba)
+ bnx2fc_stop(interface);
+ }
+ BUG_ON(hba->num_ofld_sess != 0);
+
+ mutex_lock(&hba->hba_mutex);
+ clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+ clear_bit(ADAPTER_STATE_GOING_DOWN,
+ &hba->adapter_state);
+
+ clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+ mutex_unlock(&hba->hba_mutex);
+
bnx2fc_fw_destroy(hba);
+exit:
mutex_unlock(&bnx2fc_dev_lock);
}
-static void bnx2fc_start_disc(struct bnx2fc_hba *hba)
+static void bnx2fc_start_disc(struct bnx2fc_interface *interface)
{
struct fc_lport *lport;
int wait_cnt = 0;
BNX2FC_MISC_DBG("Entered %s\n", __func__);
/* Kick off FIP/FLOGI */
- if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+ if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) {
printk(KERN_ERR PFX "Init not done yet\n");
return;
}
- lport = hba->ctlr.lp;
+ lport = interface->ctlr.lp;
BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n");
- if (!bnx2fc_link_ok(lport)) {
+ if (!bnx2fc_link_ok(lport) && interface->enabled) {
BNX2FC_HBA_DBG(lport, "ctlr_link_up\n");
- fcoe_ctlr_link_up(&hba->ctlr);
+ fcoe_ctlr_link_up(&interface->ctlr);
fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
- set_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+ set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state);
}
/* wait for the FCF to be selected before issuing FLOGI */
- while (!hba->ctlr.sel_fcf) {
+ while (!interface->ctlr.sel_fcf) {
msleep(250);
/* give up after 3 secs */
if (++wait_cnt > 12)
break;
}
+
+ /* Reset max receive frame size to default */
+ if (fc_set_mfs(lport, BNX2FC_MFS))
+ return;
+
fc_lport_init(lport);
fc_fabric_login(lport);
}
@@ -1749,15 +1857,15 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
BNX2FC_MISC_DBG("Entered %s\n", __func__);
/* bnx2fc works only when bnx2x is loaded */
- if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+ if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) ||
+ (dev->max_fcoe_conn == 0)) {
printk(KERN_ERR PFX "bnx2fc FCoE not supported on %s,"
- " flags: %lx\n",
- dev->netdev->name, dev->flags);
+ " flags: %lx fcoe_conn: %d\n",
+ dev->netdev->name, dev->flags, dev->max_fcoe_conn);
return;
}
- /* Configure FCoE interface */
- hba = bnx2fc_interface_create(dev);
+ hba = bnx2fc_hba_create(dev);
if (!hba) {
printk(KERN_ERR PFX "hba initialization failed\n");
return;
@@ -1765,7 +1873,7 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
/* Add HBA to the adapter list */
mutex_lock(&bnx2fc_dev_lock);
- list_add_tail(&hba->link, &adapter_list);
+ list_add_tail(&hba->list, &adapter_list);
adapter_count++;
mutex_unlock(&bnx2fc_dev_lock);
@@ -1773,7 +1881,7 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
rc = dev->register_device(dev, CNIC_ULP_FCOE,
(void *) hba);
if (rc)
- printk(KERN_ALERT PFX "register_device failed, rc = %d\n", rc);
+ printk(KERN_ERR PFX "register_device failed, rc = %d\n", rc);
else
set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
}
@@ -1781,52 +1889,22 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
static int bnx2fc_disable(struct net_device *netdev)
{
- struct bnx2fc_hba *hba;
- struct net_device *phys_dev;
- struct ethtool_drvinfo drvinfo;
+ struct bnx2fc_interface *interface;
int rc = 0;
rtnl_lock();
-
mutex_lock(&bnx2fc_dev_lock);
- /* obtain physical netdev */
- if (netdev->priv_flags & IFF_802_1Q_VLAN)
- phys_dev = vlan_dev_real_dev(netdev);
- else {
- printk(KERN_ERR PFX "Not a vlan device\n");
- rc = -ENODEV;
- goto nodev;
- }
-
- /* verify if the physical device is a netxtreme2 device */
- if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
- memset(&drvinfo, 0, sizeof(drvinfo));
- phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
- if (strcmp(drvinfo.driver, "bnx2x")) {
- printk(KERN_ERR PFX "Not a netxtreme2 device\n");
- rc = -ENODEV;
- goto nodev;
- }
- } else {
- printk(KERN_ERR PFX "unable to obtain drv_info\n");
- rc = -ENODEV;
- goto nodev;
- }
-
- printk(KERN_ERR PFX "phys_dev is netxtreme2 device\n");
-
- /* obtain hba and initialize rest of the structure */
- hba = bnx2fc_hba_lookup(phys_dev);
- if (!hba || !hba->ctlr.lp) {
+ interface = bnx2fc_interface_lookup(netdev);
+ if (!interface || !interface->ctlr.lp) {
rc = -ENODEV;
- printk(KERN_ERR PFX "bnx2fc_disable: hba or lport not found\n");
+ printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n");
} else {
- fcoe_ctlr_link_down(&hba->ctlr);
- fcoe_clean_pending_queue(hba->ctlr.lp);
+ interface->enabled = false;
+ fcoe_ctlr_link_down(&interface->ctlr);
+ fcoe_clean_pending_queue(interface->ctlr.lp);
}
-nodev:
mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock();
return rc;
@@ -1835,48 +1913,21 @@ nodev:
static int bnx2fc_enable(struct net_device *netdev)
{
- struct bnx2fc_hba *hba;
- struct net_device *phys_dev;
- struct ethtool_drvinfo drvinfo;
+ struct bnx2fc_interface *interface;
int rc = 0;
rtnl_lock();
-
- BNX2FC_MISC_DBG("Entered %s\n", __func__);
mutex_lock(&bnx2fc_dev_lock);
- /* obtain physical netdev */
- if (netdev->priv_flags & IFF_802_1Q_VLAN)
- phys_dev = vlan_dev_real_dev(netdev);
- else {
- printk(KERN_ERR PFX "Not a vlan device\n");
- rc = -ENODEV;
- goto nodev;
- }
- /* verify if the physical device is a netxtreme2 device */
- if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
- memset(&drvinfo, 0, sizeof(drvinfo));
- phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
- if (strcmp(drvinfo.driver, "bnx2x")) {
- printk(KERN_ERR PFX "Not a netxtreme2 device\n");
- rc = -ENODEV;
- goto nodev;
- }
- } else {
- printk(KERN_ERR PFX "unable to obtain drv_info\n");
+ interface = bnx2fc_interface_lookup(netdev);
+ if (!interface || !interface->ctlr.lp) {
rc = -ENODEV;
- goto nodev;
+ printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n");
+ } else if (!bnx2fc_link_ok(interface->ctlr.lp)) {
+ fcoe_ctlr_link_up(&interface->ctlr);
+ interface->enabled = true;
}
- /* obtain hba and initialize rest of the structure */
- hba = bnx2fc_hba_lookup(phys_dev);
- if (!hba || !hba->ctlr.lp) {
- rc = -ENODEV;
- printk(KERN_ERR PFX "bnx2fc_enable: hba or lport not found\n");
- } else if (!bnx2fc_link_ok(hba->ctlr.lp))
- fcoe_ctlr_link_up(&hba->ctlr);
-
-nodev:
mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock();
return rc;
@@ -1894,6 +1945,7 @@ nodev:
*/
static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
{
+ struct bnx2fc_interface *interface;
struct bnx2fc_hba *hba;
struct net_device *phys_dev;
struct fc_lport *lport;
@@ -1929,7 +1981,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
memset(&drvinfo, 0, sizeof(drvinfo));
phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
- if (strcmp(drvinfo.driver, "bnx2x")) {
+ if (strncmp(drvinfo.driver, "bnx2x", strlen("bnx2x"))) {
printk(KERN_ERR PFX "Not a netxtreme2 device\n");
rc = -EINVAL;
goto netdev_err;
@@ -1940,7 +1992,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
goto netdev_err;
}
- /* obtain hba and initialize rest of the structure */
+ /* obtain interface and initialize rest of the structure */
hba = bnx2fc_hba_lookup(phys_dev);
if (!hba) {
rc = -ENODEV;
@@ -1948,67 +2000,68 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
goto netdev_err;
}
- if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
- rc = bnx2fc_fw_init(hba);
- if (rc)
- goto netdev_err;
- }
-
- if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+ if (bnx2fc_interface_lookup(netdev)) {
rc = -EEXIST;
goto netdev_err;
}
- /* update netdev with vlan netdev */
- hba->netdev = netdev;
- hba->vlan_id = vlan_id;
- hba->vlan_enabled = 1;
-
- rc = bnx2fc_interface_setup(hba, fip_mode);
- if (rc) {
- printk(KERN_ERR PFX "bnx2fc_interface_setup failed\n");
+ interface = bnx2fc_interface_create(hba, netdev, fip_mode);
+ if (!interface) {
+ printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
goto ifput_err;
}
- hba->timer_work_queue =
+ interface->vlan_id = vlan_id;
+ interface->vlan_enabled = 1;
+
+ interface->timer_work_queue =
create_singlethread_workqueue("bnx2fc_timer_wq");
- if (!hba->timer_work_queue) {
+ if (!interface->timer_work_queue) {
printk(KERN_ERR PFX "ulp_init could not create timer_wq\n");
rc = -EINVAL;
goto ifput_err;
}
- lport = bnx2fc_if_create(hba, &hba->pcidev->dev, 0);
+ lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
if (!lport) {
printk(KERN_ERR PFX "Failed to create interface (%s)\n",
netdev->name);
- bnx2fc_netdev_cleanup(hba);
rc = -EINVAL;
goto if_create_err;
}
+ /* Add interface to if_list */
+ list_add_tail(&interface->list, &if_list);
+
lport->boot_time = jiffies;
/* Make this master N_port */
- hba->ctlr.lp = lport;
+ interface->ctlr.lp = lport;
- set_bit(BNX2FC_CREATE_DONE, &hba->init_done);
- printk(KERN_ERR PFX "create: START DISC\n");
- bnx2fc_start_disc(hba);
+ if (!bnx2fc_link_ok(lport)) {
+ fcoe_ctlr_link_up(&interface->ctlr);
+ fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
+ set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state);
+ }
+
+ BNX2FC_HBA_DBG(lport, "create: START DISC\n");
+ bnx2fc_start_disc(interface);
+ interface->enabled = true;
/*
* Release from kref_init in bnx2fc_interface_setup, on success
* lport should be holding a reference taken in bnx2fc_if_create
*/
- bnx2fc_interface_put(hba);
+ bnx2fc_interface_put(interface);
/* put netdev that was held while calling dev_get_by_name */
mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock();
return 0;
if_create_err:
- destroy_workqueue(hba->timer_work_queue);
+ destroy_workqueue(interface->timer_work_queue);
ifput_err:
- bnx2fc_interface_put(hba);
+ bnx2fc_net_cleanup(interface);
+ bnx2fc_interface_put(interface);
netdev_err:
module_put(THIS_MODULE);
mod_err:
@@ -2018,7 +2071,7 @@ mod_err:
}
/**
- * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc adapter instance
+ * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance
*
* @cnic: Pointer to cnic device instance
*
@@ -2038,19 +2091,30 @@ static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic)
return NULL;
}
-static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev)
+static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
+ *netdev)
+{
+ struct bnx2fc_interface *interface;
+
+ /* Called with bnx2fc_dev_lock held */
+ list_for_each_entry(interface, &if_list, list) {
+ if (interface->netdev == netdev)
+ return interface;
+ }
+ return NULL;
+}
+
+static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device
+ *phys_dev)
{
- struct list_head *list;
- struct list_head *temp;
struct bnx2fc_hba *hba;
/* Called with bnx2fc_dev_lock held */
- list_for_each_safe(list, temp, &adapter_list) {
- hba = (struct bnx2fc_hba *)list;
+ list_for_each_entry(hba, &adapter_list, list) {
if (hba->phys_dev == phys_dev)
return hba;
}
- printk(KERN_ERR PFX "hba_lookup: hba NULL\n");
+ printk(KERN_ERR PFX "adapter_lookup: hba NULL\n");
return NULL;
}
@@ -2062,6 +2126,7 @@ static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev)
static void bnx2fc_ulp_exit(struct cnic_dev *dev)
{
struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface, *tmp;
BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n");
@@ -2080,21 +2145,20 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
return;
}
- list_del_init(&hba->link);
+ list_del_init(&hba->list);
adapter_count--;
- if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+ list_for_each_entry_safe(interface, tmp, &if_list, list)
/* destroy not called yet, move to quiesced list */
- bnx2fc_netdev_cleanup(hba);
- bnx2fc_if_destroy(hba->ctlr.lp);
- }
+ if (interface->hba == hba)
+ __bnx2fc_destroy(interface);
mutex_unlock(&bnx2fc_dev_lock);
bnx2fc_ulp_stop(hba);
/* unregister cnic device */
if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
- bnx2fc_interface_destroy(hba);
+ bnx2fc_hba_destroy(hba);
}
/**
@@ -2156,7 +2220,7 @@ static void bnx2fc_percpu_thread_create(unsigned int cpu)
(void *)p,
"bnx2fc_thread/%d", cpu);
/* bind thread to the cpu */
- if (likely(!IS_ERR(p->iothread))) {
+ if (likely(!IS_ERR(thread))) {
kthread_bind(thread, cpu);
p->iothread = thread;
wake_up_process(thread);
@@ -2168,7 +2232,6 @@ static void bnx2fc_percpu_thread_destroy(unsigned int cpu)
struct bnx2fc_percpu_s *p;
struct task_struct *thread;
struct bnx2fc_work *work, *tmp;
- LIST_HEAD(work_list);
BNX2FC_MISC_DBG("destroying io thread for CPU %d\n", cpu);
@@ -2180,7 +2243,7 @@ static void bnx2fc_percpu_thread_destroy(unsigned int cpu)
/* Free all work in the list */
- list_for_each_entry_safe(work, tmp, &work_list, list) {
+ list_for_each_entry_safe(work, tmp, &p->work_list, list) {
list_del_init(&work->list);
bnx2fc_process_cq_compl(work->tgt, work->wqe);
kfree(work);
@@ -2250,6 +2313,7 @@ static int __init bnx2fc_mod_init(void)
}
INIT_LIST_HEAD(&adapter_list);
+ INIT_LIST_HEAD(&if_list);
mutex_init(&bnx2fc_dev_lock);
adapter_count = 0;
@@ -2327,16 +2391,17 @@ static void __exit bnx2fc_mod_exit(void)
mutex_unlock(&bnx2fc_dev_lock);
/* Unregister with cnic */
- list_for_each_entry_safe(hba, next, &to_be_deleted, link) {
- list_del_init(&hba->link);
- printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p, kref = %d\n",
- hba, atomic_read(&hba->kref.refcount));
+ list_for_each_entry_safe(hba, next, &to_be_deleted, list) {
+ list_del_init(&hba->list);
+ printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p\n",
+ hba);
bnx2fc_ulp_stop(hba);
/* unregister cnic device */
if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED,
&hba->reg_with_cnic))
- hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
- bnx2fc_interface_destroy(hba);
+ hba->cnic->unregister_device(hba->cnic,
+ CNIC_ULP_FCOE);
+ bnx2fc_hba_destroy(hba);
}
cnic_unregister_driver(CNIC_ULP_FCOE);
@@ -2411,6 +2476,7 @@ static struct fc_function_template bnx2fc_transport_function = {
.vport_create = bnx2fc_vport_create,
.vport_delete = bnx2fc_vport_destroy,
.vport_disable = bnx2fc_vport_disable,
+ .bsg_request = fc_lport_bsg_request,
};
static struct fc_function_template bnx2fc_vport_xport_function = {
@@ -2444,6 +2510,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = {
.get_fc_host_stats = fc_get_host_stats,
.issue_fc_host_lip = bnx2fc_fcoe_reset,
.terminate_rport_io = fc_rport_terminate_io,
+ .bsg_request = fc_lport_bsg_request,
};
/**
@@ -2473,6 +2540,7 @@ static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
.elsct_send = bnx2fc_elsct_send,
.fcp_abort_io = bnx2fc_abort_io,
.fcp_cleanup = bnx2fc_cleanup,
+ .get_lesb = bnx2fc_get_lesb,
.rport_event_callback = bnx2fc_rport_event_handler,
};
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 78baa46..1923a25 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -2,7 +2,7 @@
* This file contains the code that low level functions that interact
* with 57712 FCoE firmware.
*
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom Corporation
*
* 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
@@ -23,7 +23,7 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
struct fcoe_kcqe *ofld_kcqe);
static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code);
static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
- struct fcoe_kcqe *conn_destroy);
+ struct fcoe_kcqe *destroy_kcqe);
int bnx2fc_send_stat_req(struct bnx2fc_hba *hba)
{
@@ -67,7 +67,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
int rc = 0;
if (!hba->cnic) {
- printk(KERN_ALERT PFX "hba->cnic NULL during fcoe fw init\n");
+ printk(KERN_ERR PFX "hba->cnic NULL during fcoe fw init\n");
return -ENODEV;
}
@@ -100,6 +100,10 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
fcoe_init2.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+ fcoe_init2.hsi_major_version = FCOE_HSI_MAJOR_VERSION;
+ fcoe_init2.hsi_minor_version = FCOE_HSI_MINOR_VERSION;
+
+
fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
((u64) hba->hash_tbl_pbl_dma >> 32);
@@ -122,6 +126,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
fcoe_init3.error_bit_map_lo = 0xffffffff;
fcoe_init3.error_bit_map_hi = 0xffffffff;
+ fcoe_init3.perf_config = 1;
kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
@@ -161,7 +166,8 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
struct bnx2fc_rport *tgt)
{
struct fc_lport *lport = port->lport;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct kwqe *kwqe_arr[4];
struct fcoe_kwqe_conn_offload1 ofld_req1;
struct fcoe_kwqe_conn_offload2 ofld_req2;
@@ -223,7 +229,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
ofld_req3.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- ofld_req3.vlan_tag = hba->vlan_id <<
+ ofld_req3.vlan_tag = interface->vlan_id <<
FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT;
ofld_req3.vlan_tag |= 3 << FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT;
@@ -273,8 +279,20 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
ofld_req3.flags |= (((rdata->sp_features & FC_SP_FT_SEQC) ? 1 : 0) <<
FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT);
+ /*
+ * Info from PRLI response, this info is used for sequence level error
+ * recovery support
+ */
+ if (tgt->dev_type == TYPE_TAPE) {
+ ofld_req3.flags |= 1 <<
+ FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT;
+ ofld_req3.flags |= (((rdata->flags & FC_RP_FLAGS_REC_SUPPORTED)
+ ? 1 : 0) <<
+ FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT);
+ }
+
/* vlan flag */
- ofld_req3.flags |= (hba->vlan_enabled <<
+ ofld_req3.flags |= (interface->vlan_enabled <<
FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
/* C2_VALID and ACK flags are not set as they are not suppported */
@@ -289,19 +307,20 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
ofld_req4.e_d_tov_timer_val = lport->e_d_tov / 20;
- ofld_req4.src_mac_addr_lo32[0] = port->data_src_addr[5];
+ ofld_req4.src_mac_addr_lo[0] = port->data_src_addr[5];
/* local mac */
- ofld_req4.src_mac_addr_lo32[1] = port->data_src_addr[4];
- ofld_req4.src_mac_addr_lo32[2] = port->data_src_addr[3];
- ofld_req4.src_mac_addr_lo32[3] = port->data_src_addr[2];
- ofld_req4.src_mac_addr_hi16[0] = port->data_src_addr[1];
- ofld_req4.src_mac_addr_hi16[1] = port->data_src_addr[0];
- ofld_req4.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- ofld_req4.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- ofld_req4.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- ofld_req4.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- ofld_req4.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- ofld_req4.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ ofld_req4.src_mac_addr_lo[1] = port->data_src_addr[4];
+ ofld_req4.src_mac_addr_mid[0] = port->data_src_addr[3];
+ ofld_req4.src_mac_addr_mid[1] = port->data_src_addr[2];
+ ofld_req4.src_mac_addr_hi[0] = port->data_src_addr[1];
+ ofld_req4.src_mac_addr_hi[1] = port->data_src_addr[0];
+ ofld_req4.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5];
+ /* fcf mac */
+ ofld_req4.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4];
+ ofld_req4.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3];
+ ofld_req4.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2];
+ ofld_req4.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1];
+ ofld_req4.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0];
ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
@@ -331,7 +350,8 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
struct bnx2fc_rport *tgt)
{
struct kwqe *kwqe_arr[2];
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct fcoe_kwqe_conn_enable_disable enbl_req;
struct fc_lport *lport = port->lport;
struct fc_rport *rport = tgt->rport;
@@ -345,20 +365,21 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
enbl_req.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- enbl_req.src_mac_addr_lo32[0] = port->data_src_addr[5];
+ enbl_req.src_mac_addr_lo[0] = port->data_src_addr[5];
/* local mac */
- enbl_req.src_mac_addr_lo32[1] = port->data_src_addr[4];
- enbl_req.src_mac_addr_lo32[2] = port->data_src_addr[3];
- enbl_req.src_mac_addr_lo32[3] = port->data_src_addr[2];
- enbl_req.src_mac_addr_hi16[0] = port->data_src_addr[1];
- enbl_req.src_mac_addr_hi16[1] = port->data_src_addr[0];
-
- enbl_req.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- enbl_req.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- enbl_req.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- enbl_req.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- enbl_req.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- enbl_req.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ enbl_req.src_mac_addr_lo[1] = port->data_src_addr[4];
+ enbl_req.src_mac_addr_mid[0] = port->data_src_addr[3];
+ enbl_req.src_mac_addr_mid[1] = port->data_src_addr[2];
+ enbl_req.src_mac_addr_hi[0] = port->data_src_addr[1];
+ enbl_req.src_mac_addr_hi[1] = port->data_src_addr[0];
+ memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN);
+
+ enbl_req.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5];
+ enbl_req.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4];
+ enbl_req.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3];
+ enbl_req.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2];
+ enbl_req.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1];
+ enbl_req.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0];
port_id = fc_host_port_id(lport->host);
if (port_id != tgt->sid) {
@@ -374,10 +395,10 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
enbl_req.d_id[0] = (port_id & 0x000000FF);
enbl_req.d_id[1] = (port_id & 0x0000FF00) >> 8;
enbl_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
- enbl_req.vlan_tag = hba->vlan_id <<
+ enbl_req.vlan_tag = interface->vlan_id <<
FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
enbl_req.vlan_tag |= 3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
- enbl_req.vlan_flag = hba->vlan_enabled;
+ enbl_req.vlan_flag = interface->vlan_enabled;
enbl_req.context_id = tgt->context_id;
enbl_req.conn_id = tgt->fcoe_conn_id;
@@ -397,7 +418,8 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
int bnx2fc_send_session_disable_req(struct fcoe_port *port,
struct bnx2fc_rport *tgt)
{
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct fcoe_kwqe_conn_enable_disable disable_req;
struct kwqe *kwqe_arr[2];
struct fc_rport *rport = tgt->rport;
@@ -411,18 +433,19 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port,
disable_req.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- disable_req.src_mac_addr_lo32[0] = port->data_src_addr[5];
- disable_req.src_mac_addr_lo32[2] = port->data_src_addr[3];
- disable_req.src_mac_addr_lo32[3] = port->data_src_addr[2];
- disable_req.src_mac_addr_hi16[0] = port->data_src_addr[1];
- disable_req.src_mac_addr_hi16[1] = port->data_src_addr[0];
+ disable_req.src_mac_addr_lo[0] = tgt->src_addr[5];
+ disable_req.src_mac_addr_lo[1] = tgt->src_addr[4];
+ disable_req.src_mac_addr_mid[0] = tgt->src_addr[3];
+ disable_req.src_mac_addr_mid[1] = tgt->src_addr[2];
+ disable_req.src_mac_addr_hi[0] = tgt->src_addr[1];
+ disable_req.src_mac_addr_hi[1] = tgt->src_addr[0];
- disable_req.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- disable_req.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- disable_req.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- disable_req.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- disable_req.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- disable_req.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ disable_req.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5];
+ disable_req.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4];
+ disable_req.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3];
+ disable_req.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2];
+ disable_req.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1];
+ disable_req.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0];
port_id = tgt->sid;
disable_req.s_id[0] = (port_id & 0x000000FF);
@@ -436,11 +459,11 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port,
disable_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
disable_req.context_id = tgt->context_id;
disable_req.conn_id = tgt->fcoe_conn_id;
- disable_req.vlan_tag = hba->vlan_id <<
+ disable_req.vlan_tag = interface->vlan_id <<
FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
disable_req.vlan_tag |=
3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
- disable_req.vlan_flag = hba->vlan_enabled;
+ disable_req.vlan_flag = interface->vlan_enabled;
kwqe_arr[0] = (struct kwqe *) &disable_req;
@@ -519,7 +542,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
{
struct fcoe_port *port = tgt->port;
struct fc_lport *lport = port->lport;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
struct bnx2fc_unsol_els *unsol_els;
struct fc_frame_header *fh;
struct fc_frame *fp;
@@ -580,7 +603,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
fr_eof(fp) = FC_EOF_T;
fr_crc(fp) = cpu_to_le32(~crc);
unsol_els->lport = lport;
- unsol_els->hba = hba;
+ unsol_els->hba = interface->hba;
unsol_els->fp = fp;
INIT_WORK(&unsol_els->unsol_els_work, bnx2fc_unsol_els_work);
queue_work(bnx2fc_wq, &unsol_els->unsol_els_work);
@@ -602,9 +625,12 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
u32 frame_len, len;
struct bnx2fc_cmd *io_req = NULL;
struct fcoe_task_ctx_entry *task, *task_page;
- struct bnx2fc_hba *hba = tgt->port->priv;
+ struct bnx2fc_interface *interface = tgt->port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
int task_idx, index;
int rc = 0;
+ u64 err_warn_bit_map;
+ u8 err_warn = 0xff;
BNX2FC_TGT_DBG(tgt, "Entered UNSOL COMPLETION wqe = 0x%x\n", wqe);
@@ -662,44 +688,48 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
xid = err_entry->fc_hdr.ox_id;
BNX2FC_TGT_DBG(tgt, "Unsol Error Frame OX_ID = 0x%x\n", xid);
BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x\n",
- err_entry->err_warn_bitmap_hi,
- err_entry->err_warn_bitmap_lo);
+ err_entry->data.err_warn_bitmap_hi,
+ err_entry->data.err_warn_bitmap_lo);
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
- err_entry->tx_buf_off, err_entry->rx_buf_off);
+ err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
- bnx2fc_return_rqe(tgt, 1);
if (xid > BNX2FC_MAX_XID) {
BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n",
xid);
- spin_unlock_bh(&tgt->tgt_lock);
- break;
+ goto ret_err_rqe;
}
task_idx = xid / BNX2FC_TASKS_PER_PAGE;
index = xid % BNX2FC_TASKS_PER_PAGE;
task_page = (struct fcoe_task_ctx_entry *)
- hba->task_ctx[task_idx];
+ hba->task_ctx[task_idx];
task = &(task_page[index]);
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
- if (!io_req) {
- spin_unlock_bh(&tgt->tgt_lock);
- break;
- }
+ if (!io_req)
+ goto ret_err_rqe;
if (io_req->cmd_type != BNX2FC_SCSI_CMD) {
printk(KERN_ERR PFX "err_warn: Not a SCSI cmd\n");
- spin_unlock_bh(&tgt->tgt_lock);
- break;
+ goto ret_err_rqe;
}
if (test_and_clear_bit(BNX2FC_FLAG_IO_CLEANUP,
&io_req->req_flags)) {
BNX2FC_IO_DBG(io_req, "unsol_err: cleanup in "
"progress.. ignore unsol err\n");
- spin_unlock_bh(&tgt->tgt_lock);
- break;
+ goto ret_err_rqe;
+ }
+
+ err_warn_bit_map = (u64)
+ ((u64)err_entry->data.err_warn_bitmap_hi << 32) |
+ (u64)err_entry->data.err_warn_bitmap_lo;
+ for (i = 0; i < BNX2FC_NUM_ERR_BITS; i++) {
+ if (err_warn_bit_map & (u64)((u64)1 << i)) {
+ err_warn = i;
+ break;
+ }
}
/*
@@ -709,26 +739,61 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
* logging out the target, when the ABTS eventually
* times out.
*/
- if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
- &io_req->req_flags)) {
- /*
- * Cancel the timeout_work, as we received IO
- * completion with FW error.
- */
- if (cancel_delayed_work(&io_req->timeout_work))
- kref_put(&io_req->refcount,
- bnx2fc_cmd_release); /* timer hold */
-
- rc = bnx2fc_initiate_abts(io_req);
- if (rc != SUCCESS) {
- BNX2FC_IO_DBG(io_req, "err_warn: initiate_abts "
- "failed. issue cleanup\n");
- rc = bnx2fc_initiate_cleanup(io_req);
- BUG_ON(rc);
- }
- } else
+ if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
printk(KERN_ERR PFX "err_warn: io_req (0x%x) already "
"in ABTS processing\n", xid);
+ goto ret_err_rqe;
+ }
+ BNX2FC_TGT_DBG(tgt, "err = 0x%x\n", err_warn);
+ if (tgt->dev_type != TYPE_TAPE)
+ goto skip_rec;
+ switch (err_warn) {
+ case FCOE_ERROR_CODE_REC_TOV_TIMER_EXPIRATION:
+ case FCOE_ERROR_CODE_DATA_OOO_RO:
+ case FCOE_ERROR_CODE_COMMON_INCORRECT_SEQ_CNT:
+ case FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET:
+ case FCOE_ERROR_CODE_FCP_RSP_OPENED_SEQ:
+ case FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET:
+ BNX2FC_TGT_DBG(tgt, "REC TOV popped for xid - 0x%x\n",
+ xid);
+ memset(&io_req->err_entry, 0,
+ sizeof(struct fcoe_err_report_entry));
+ memcpy(&io_req->err_entry, err_entry,
+ sizeof(struct fcoe_err_report_entry));
+ if (!test_bit(BNX2FC_FLAG_SRR_SENT,
+ &io_req->req_flags)) {
+ spin_unlock_bh(&tgt->tgt_lock);
+ rc = bnx2fc_send_rec(io_req);
+ spin_lock_bh(&tgt->tgt_lock);
+
+ if (rc)
+ goto skip_rec;
+ } else
+ printk(KERN_ERR PFX "SRR in progress\n");
+ goto ret_err_rqe;
+ break;
+ default:
+ break;
+ }
+
+skip_rec:
+ set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags);
+ /*
+ * Cancel the timeout_work, as we received IO
+ * completion with FW error.
+ */
+ if (cancel_delayed_work(&io_req->timeout_work))
+ kref_put(&io_req->refcount, bnx2fc_cmd_release);
+
+ rc = bnx2fc_initiate_abts(io_req);
+ if (rc != SUCCESS) {
+ printk(KERN_ERR PFX "err_warn: initiate_abts "
+ "failed xid = 0x%x. issue cleanup\n",
+ io_req->xid);
+ bnx2fc_initiate_cleanup(io_req);
+ }
+ret_err_rqe:
+ bnx2fc_return_rqe(tgt, 1);
spin_unlock_bh(&tgt->tgt_lock);
break;
@@ -744,11 +809,52 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
xid = cpu_to_be16(err_entry->fc_hdr.ox_id);
BNX2FC_TGT_DBG(tgt, "Unsol Warning Frame OX_ID = 0x%x\n", xid);
BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x",
- err_entry->err_warn_bitmap_hi,
- err_entry->err_warn_bitmap_lo);
+ err_entry->data.err_warn_bitmap_hi,
+ err_entry->data.err_warn_bitmap_lo);
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
- err_entry->tx_buf_off, err_entry->rx_buf_off);
+ err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
+
+ if (xid > BNX2FC_MAX_XID) {
+ BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n", xid);
+ goto ret_warn_rqe;
+ }
+ err_warn_bit_map = (u64)
+ ((u64)err_entry->data.err_warn_bitmap_hi << 32) |
+ (u64)err_entry->data.err_warn_bitmap_lo;
+ for (i = 0; i < BNX2FC_NUM_ERR_BITS; i++) {
+ if (err_warn_bit_map & (u64) (1 << i)) {
+ err_warn = i;
+ break;
+ }
+ }
+ BNX2FC_TGT_DBG(tgt, "warn = 0x%x\n", err_warn);
+
+ task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+ index = xid % BNX2FC_TASKS_PER_PAGE;
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[task_idx];
+ task = &(task_page[index]);
+ io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
+ if (!io_req)
+ goto ret_warn_rqe;
+
+ if (io_req->cmd_type != BNX2FC_SCSI_CMD) {
+ printk(KERN_ERR PFX "err_warn: Not a SCSI cmd\n");
+ goto ret_warn_rqe;
+ }
+
+ memset(&io_req->err_entry, 0,
+ sizeof(struct fcoe_err_report_entry));
+ memcpy(&io_req->err_entry, err_entry,
+ sizeof(struct fcoe_err_report_entry));
+
+ if (err_warn == FCOE_ERROR_CODE_REC_TOV_TIMER_EXPIRATION)
+ /* REC_TOV is not a warning code */
+ BUG_ON(1);
+ else
+ BNX2FC_TGT_DBG(tgt, "Unsolicited warning\n");
+ret_warn_rqe:
bnx2fc_return_rqe(tgt, 1);
spin_unlock_bh(&tgt->tgt_lock);
break;
@@ -764,7 +870,8 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
struct fcoe_task_ctx_entry *task;
struct fcoe_task_ctx_entry *task_page;
struct fcoe_port *port = tgt->port;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct bnx2fc_cmd *io_req;
int task_idx, index;
u16 xid;
@@ -775,7 +882,7 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
spin_lock_bh(&tgt->tgt_lock);
xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
if (xid >= BNX2FC_MAX_TASKS) {
- printk(KERN_ALERT PFX "ERROR:xid out of range\n");
+ printk(KERN_ERR PFX "ERROR:xid out of range\n");
spin_unlock_bh(&tgt->tgt_lock);
return;
}
@@ -784,9 +891,9 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
task = &(task_page[index]);
- num_rq = ((task->rx_wr_tx_rd.rx_flags &
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE) >>
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT);
+ num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
@@ -799,22 +906,19 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
/* Timestamp IO completion time */
cmd_type = io_req->cmd_type;
- /* optimized completion path */
- if (cmd_type == BNX2FC_SCSI_CMD) {
- rx_state = ((task->rx_wr_tx_rd.rx_flags &
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE) >>
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT);
+ rx_state = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT);
+ /* Process other IO completion types */
+ switch (cmd_type) {
+ case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
spin_unlock_bh(&tgt->tgt_lock);
return;
}
- }
- /* Process other IO completion types */
- switch (cmd_type) {
- case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
bnx2fc_process_abts_compl(io_req, task, num_rq);
else if (rx_state ==
@@ -841,8 +945,16 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
break;
case BNX2FC_ELS:
- BNX2FC_IO_DBG(io_req, "cq_compl - call process_els_compl\n");
- bnx2fc_process_els_compl(io_req, task, num_rq);
+ if (rx_state == FCOE_TASK_RX_STATE_COMPLETED)
+ bnx2fc_process_els_compl(io_req, task, num_rq);
+ else if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
+ bnx2fc_process_abts_compl(io_req, task, num_rq);
+ else if (rx_state ==
+ FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED)
+ bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+ else
+ printk(KERN_ERR PFX "Invalid rx state = %d\n",
+ rx_state);
break;
case BNX2FC_CLEANUP:
@@ -850,6 +962,13 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
kref_put(&io_req->refcount, bnx2fc_cmd_release);
break;
+ case BNX2FC_SEQ_CLEANUP:
+ BNX2FC_IO_DBG(io_req, "cq_compl(0x%x) - seq cleanup resp\n",
+ io_req->xid);
+ bnx2fc_process_seq_cleanup_compl(io_req, task, rx_state);
+ kref_put(&io_req->refcount, bnx2fc_cmd_release);
+ break;
+
default:
printk(KERN_ERR PFX "Invalid cmd_type %d\n", cmd_type);
break;
@@ -857,6 +976,20 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
spin_unlock_bh(&tgt->tgt_lock);
}
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt)
+{
+ struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
+ u32 msg;
+
+ wmb();
+ rx_db->doorbell_cq_cons = tgt->cq_cons_idx | (tgt->cq_curr_toggle_bit <<
+ FCOE_CQE_TOGGLE_BIT_SHIFT);
+ msg = *((u32 *)rx_db);
+ writel(cpu_to_le32(msg), tgt->ctx_base);
+ mmiowb();
+
+}
+
struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
{
struct bnx2fc_work *work;
@@ -875,8 +1008,9 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
struct fcoe_cqe *cq;
u32 cq_cons;
struct fcoe_cqe *cqe;
+ u32 num_free_sqes = 0;
+ u32 num_cqes = 0;
u16 wqe;
- bool more_cqes_found = false;
/*
* cq_lock is a low contention lock used to protect
@@ -894,62 +1028,56 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
cq_cons = tgt->cq_cons_idx;
cqe = &cq[cq_cons];
- do {
- more_cqes_found ^= true;
-
- while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
- (tgt->cq_curr_toggle_bit <<
- FCOE_CQE_TOGGLE_BIT_SHIFT)) {
+ while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
+ (tgt->cq_curr_toggle_bit <<
+ FCOE_CQE_TOGGLE_BIT_SHIFT)) {
- /* new entry on the cq */
- if (wqe & FCOE_CQE_CQE_TYPE) {
- /* Unsolicited event notification */
- bnx2fc_process_unsol_compl(tgt, wqe);
- } else {
- struct bnx2fc_work *work = NULL;
- struct bnx2fc_percpu_s *fps = NULL;
- unsigned int cpu = wqe % num_possible_cpus();
-
- fps = &per_cpu(bnx2fc_percpu, cpu);
- spin_lock_bh(&fps->fp_work_lock);
- if (unlikely(!fps->iothread))
- goto unlock;
-
- work = bnx2fc_alloc_work(tgt, wqe);
- if (work)
- list_add_tail(&work->list,
- &fps->work_list);
+ /* new entry on the cq */
+ if (wqe & FCOE_CQE_CQE_TYPE) {
+ /* Unsolicited event notification */
+ bnx2fc_process_unsol_compl(tgt, wqe);
+ } else {
+ /* Pending work request completion */
+ struct bnx2fc_work *work = NULL;
+ struct bnx2fc_percpu_s *fps = NULL;
+ unsigned int cpu = wqe % num_possible_cpus();
+
+ fps = &per_cpu(bnx2fc_percpu, cpu);
+ spin_lock_bh(&fps->fp_work_lock);
+ if (unlikely(!fps->iothread))
+ goto unlock;
+
+ work = bnx2fc_alloc_work(tgt, wqe);
+ if (work)
+ list_add_tail(&work->list,
+ &fps->work_list);
unlock:
- spin_unlock_bh(&fps->fp_work_lock);
-
- /* Pending work request completion */
- if (fps->iothread && work)
- wake_up_process(fps->iothread);
- else
- bnx2fc_process_cq_compl(tgt, wqe);
- }
- cqe++;
- tgt->cq_cons_idx++;
-
- if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
- tgt->cq_cons_idx = 0;
- cqe = cq;
- tgt->cq_curr_toggle_bit =
- 1 - tgt->cq_curr_toggle_bit;
- }
+ spin_unlock_bh(&fps->fp_work_lock);
+
+ /* Pending work request completion */
+ if (fps->iothread && work)
+ wake_up_process(fps->iothread);
+ else
+ bnx2fc_process_cq_compl(tgt, wqe);
+ num_free_sqes++;
}
- /* Re-arm CQ */
- if (more_cqes_found) {
- tgt->conn_db->cq_arm.lo = -1;
- wmb();
+ cqe++;
+ tgt->cq_cons_idx++;
+ num_cqes++;
+
+ if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
+ tgt->cq_cons_idx = 0;
+ cqe = cq;
+ tgt->cq_curr_toggle_bit =
+ 1 - tgt->cq_curr_toggle_bit;
}
- } while (more_cqes_found);
-
- /*
- * Commit tgt->cq_cons_idx change to the memory
- * spin_lock implies full memory barrier, no need to smp_wmb
- */
-
+ }
+ if (num_cqes) {
+ /* Arm CQ only if doorbell is mapped */
+ if (tgt->ctx_base)
+ bnx2fc_arm_cq(tgt);
+ atomic_add(num_free_sqes, &tgt->free_sqes);
+ }
spin_unlock_bh(&tgt->cq_lock);
return 0;
}
@@ -969,7 +1097,7 @@ static void bnx2fc_fastpath_notification(struct bnx2fc_hba *hba,
struct bnx2fc_rport *tgt = hba->tgt_ofld_list[conn_id];
if (!tgt) {
- printk(KERN_ALERT PFX "conn_id 0x%x not valid\n", conn_id);
+ printk(KERN_ERR PFX "conn_id 0x%x not valid\n", conn_id);
return;
}
@@ -990,6 +1118,7 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
{
struct bnx2fc_rport *tgt;
struct fcoe_port *port;
+ struct bnx2fc_interface *interface;
u32 conn_id;
u32 context_id;
int rc;
@@ -1004,8 +1133,9 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
BNX2FC_TGT_DBG(tgt, "Entered ofld compl - context_id = 0x%x\n",
ofld_kcqe->fcoe_conn_context_id);
port = tgt->port;
- if (hba != tgt->port->priv) {
- printk(KERN_ALERT PFX "ERROR:ofld_cmpl: HBA mis-match\n");
+ interface = tgt->port->priv;
+ if (hba != interface->hba) {
+ printk(KERN_ERR PFX "ERROR:ofld_cmpl: HBA mis-match\n");
goto ofld_cmpl_err;
}
/*
@@ -1026,7 +1156,7 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
/* now enable the session */
rc = bnx2fc_send_session_enable_req(port, tgt);
if (rc) {
- printk(KERN_ALERT PFX "enable session failed\n");
+ printk(KERN_ERR PFX "enable session failed\n");
goto ofld_cmpl_err;
}
}
@@ -1049,6 +1179,7 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
struct fcoe_kcqe *ofld_kcqe)
{
struct bnx2fc_rport *tgt;
+ struct bnx2fc_interface *interface;
u32 conn_id;
u32 context_id;
@@ -1056,7 +1187,7 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
conn_id = ofld_kcqe->fcoe_conn_id;
tgt = hba->tgt_ofld_list[conn_id];
if (!tgt) {
- printk(KERN_ALERT PFX "ERROR:enbl_cmpl: No pending ofld req\n");
+ printk(KERN_ERR PFX "ERROR:enbl_cmpl: No pending ofld req\n");
return;
}
@@ -1068,16 +1199,17 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
* and enable
*/
if (tgt->context_id != context_id) {
- printk(KERN_ALERT PFX "context id mis-match\n");
+ printk(KERN_ERR PFX "context id mis-match\n");
return;
}
- if (hba != tgt->port->priv) {
- printk(KERN_ALERT PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
+ interface = tgt->port->priv;
+ if (hba != interface->hba) {
+ printk(KERN_ERR PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
goto enbl_cmpl_err;
}
- if (ofld_kcqe->completion_status) {
+ if (ofld_kcqe->completion_status)
goto enbl_cmpl_err;
- } else {
+ else {
/* enable successful - rport ready for issuing IOs */
set_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
@@ -1100,14 +1232,14 @@ static void bnx2fc_process_conn_disable_cmpl(struct bnx2fc_hba *hba,
conn_id = disable_kcqe->fcoe_conn_id;
tgt = hba->tgt_ofld_list[conn_id];
if (!tgt) {
- printk(KERN_ALERT PFX "ERROR: disable_cmpl: No disable req\n");
+ printk(KERN_ERR PFX "ERROR: disable_cmpl: No disable req\n");
return;
}
BNX2FC_TGT_DBG(tgt, PFX "disable_cmpl: conn_id %d\n", conn_id);
if (disable_kcqe->completion_status) {
- printk(KERN_ALERT PFX "ERROR: Disable failed with cmpl status %d\n",
+ printk(KERN_ERR PFX "Disable failed with cmpl status %d\n",
disable_kcqe->completion_status);
return;
} else {
@@ -1129,14 +1261,14 @@ static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
conn_id = destroy_kcqe->fcoe_conn_id;
tgt = hba->tgt_ofld_list[conn_id];
if (!tgt) {
- printk(KERN_ALERT PFX "destroy_cmpl: No destroy req\n");
+ printk(KERN_ERR PFX "destroy_cmpl: No destroy req\n");
return;
}
BNX2FC_TGT_DBG(tgt, "destroy_cmpl: conn_id %d\n", conn_id);
if (destroy_kcqe->completion_status) {
- printk(KERN_ALERT PFX "Destroy conn failed, cmpl status %d\n",
+ printk(KERN_ERR PFX "Destroy conn failed, cmpl status %d\n",
destroy_kcqe->completion_status);
return;
} else {
@@ -1163,7 +1295,12 @@ static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code)
case FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR:
printk(KERN_ERR PFX "init_failure due to NIC error\n");
break;
-
+ case FCOE_KCQE_COMPLETION_STATUS_ERROR:
+ printk(KERN_ERR PFX "init failure due to compl status err\n");
+ break;
+ case FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION:
+ printk(KERN_ERR PFX "init failure due to HSI mismatch\n");
+ break;
default:
printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
}
@@ -1222,7 +1359,7 @@ void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
} else {
printk(KERN_ERR PFX "DESTROY success\n");
}
- hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+ set_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
wake_up_interruptible(&hba->destroy_wait);
break;
@@ -1244,7 +1381,7 @@ void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
case FCOE_KCQE_OPCODE_FCOE_ERROR:
/* fall thru */
default:
- printk(KERN_ALERT PFX "unknown opcode 0x%x\n",
+ printk(KERN_ERR PFX "unknown opcode 0x%x\n",
kcqe->op_code);
}
}
@@ -1269,21 +1406,14 @@ void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid)
void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt)
{
- struct b577xx_doorbell_set_prod ev_doorbell;
+ struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
u32 msg;
wmb();
-
- memset(&ev_doorbell, 0, sizeof(struct b577xx_doorbell_set_prod));
- ev_doorbell.header.header = B577XX_DOORBELL_HDR_DB_TYPE;
-
- ev_doorbell.prod = tgt->sq_prod_idx |
+ sq_db->prod = tgt->sq_prod_idx |
(tgt->sq_curr_toggle_bit << 15);
- ev_doorbell.header.header |= B577XX_FCOE_CONNECTION_TYPE <<
- B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
- msg = *((u32 *)&ev_doorbell);
+ msg = *((u32 *)sq_db);
writel(cpu_to_le32(msg), tgt->ctx_base);
-
mmiowb();
}
@@ -1294,7 +1424,8 @@ int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt)
struct fcoe_port *port = tgt->port;
u32 reg_off;
resource_size_t reg_base;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
reg_base = pci_resource_start(hba->pcidev,
BNX2X_DOORBELL_PCI_BAR);
@@ -1333,6 +1464,96 @@ void bnx2fc_return_rqe(struct bnx2fc_rport *tgt, u8 num_items)
tgt->conn_db->rq_prod = tgt->rq_prod_idx;
}
+void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnp_req,
+ struct fcoe_task_ctx_entry *task,
+ struct bnx2fc_cmd *orig_io_req,
+ u32 offset)
+{
+ struct scsi_cmnd *sc_cmd = orig_io_req->sc_cmd;
+ struct bnx2fc_rport *tgt = seq_clnp_req->tgt;
+ struct bnx2fc_interface *interface = tgt->port->priv;
+ struct fcoe_bd_ctx *bd = orig_io_req->bd_tbl->bd_tbl;
+ struct fcoe_task_ctx_entry *orig_task;
+ struct fcoe_task_ctx_entry *task_page;
+ struct fcoe_ext_mul_sges_ctx *sgl;
+ u8 task_type = FCOE_TASK_TYPE_SEQUENCE_CLEANUP;
+ u8 orig_task_type;
+ u16 orig_xid = orig_io_req->xid;
+ u32 context_id = tgt->context_id;
+ u64 phys_addr = (u64)orig_io_req->bd_tbl->bd_tbl_dma;
+ u32 orig_offset = offset;
+ int bd_count;
+ int orig_task_idx, index;
+ int i;
+
+ memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+ if (sc_cmd->sc_data_direction == DMA_TO_DEVICE)
+ orig_task_type = FCOE_TASK_TYPE_WRITE;
+ else
+ orig_task_type = FCOE_TASK_TYPE_READ;
+
+ /* Tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags =
+ FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
+ task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
+
+ task->txwr_rxrd.union_ctx.cleanup.ctx.rolled_tx_seq_cnt = 0;
+ task->txwr_rxrd.union_ctx.cleanup.ctx.rolled_tx_data_offset = offset;
+
+ bd_count = orig_io_req->bd_tbl->bd_valid;
+
+ /* obtain the appropriate bd entry from relative offset */
+ for (i = 0; i < bd_count; i++) {
+ if (offset < bd[i].buf_len)
+ break;
+ offset -= bd[i].buf_len;
+ }
+ phys_addr += (i * sizeof(struct fcoe_bd_ctx));
+
+ if (orig_task_type == FCOE_TASK_TYPE_WRITE) {
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
+ (u32)phys_addr;
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
+ (u32)((u64)phys_addr >> 32);
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
+ bd_count;
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_off =
+ offset; /* adjusted offset */
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_idx = i;
+ } else {
+ orig_task_idx = orig_xid / BNX2FC_TASKS_PER_PAGE;
+ index = orig_xid % BNX2FC_TASKS_PER_PAGE;
+
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[orig_task_idx];
+ orig_task = &(task_page[index]);
+
+ /* Multiple SGEs were used for this IO */
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)phys_addr;
+ sgl->mul_sgl.cur_sge_addr.hi = (u32)((u64)phys_addr >> 32);
+ sgl->mul_sgl.sgl_size = bd_count;
+ sgl->mul_sgl.cur_sge_off = offset; /*adjusted offset */
+ sgl->mul_sgl.cur_sge_idx = i;
+
+ memset(&task->rxwr_only.rx_seq_ctx, 0,
+ sizeof(struct fcoe_rx_seq_ctx));
+ task->rxwr_only.rx_seq_ctx.low_exp_ro = orig_offset;
+ task->rxwr_only.rx_seq_ctx.high_exp_ro = orig_offset;
+ }
+}
void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
u16 orig_xid)
@@ -1344,18 +1565,31 @@ void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
/* Tx Write Rx Read */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
- /* Common */
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.general.cleanup_info.task_id = orig_xid;
-
-
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ if (tgt->dev_type == TYPE_TAPE)
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_TAPE <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ else
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
+
+ /* Tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags =
+ FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
+
+ /* Rx Read Tx Write */
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
}
void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
@@ -1364,6 +1598,7 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
struct bnx2fc_rport *tgt = io_req->tgt;
struct fc_frame_header *fc_hdr;
+ struct fcoe_ext_mul_sges_ctx *sgl;
u8 task_type = 0;
u64 *hdr;
u64 temp_hdr[3];
@@ -1389,47 +1624,54 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
/* Tx only */
if ((task_type == FCOE_TASK_TYPE_MIDPATH) ||
(task_type == FCOE_TASK_TYPE_UNSOLICITED)) {
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
(u32)mp_req->mp_req_bd_dma;
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
(u32)((u64)mp_req->mp_req_bd_dma >> 32);
- task->tx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
- BNX2FC_IO_DBG(io_req, "init_mp_task - bd_dma = 0x%llx\n",
- (unsigned long long)mp_req->mp_req_bd_dma);
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size = 1;
}
/* Tx Write Rx Read */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_INIT <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
- /* Common */
- task->cmn.data_2_trns = io_req->data_xfer_len;
- context_id = tgt->context_id;
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ if (tgt->dev_type == TYPE_TAPE)
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_TAPE <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ else
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+
+ /* tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_INIT <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
/* Rx Write Tx Read */
+ task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+ /* rx flags */
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+ context_id = tgt->context_id;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
fc_hdr = &(mp_req->req_fc_hdr);
if (task_type == FCOE_TASK_TYPE_MIDPATH) {
fc_hdr->fh_ox_id = cpu_to_be16(io_req->xid);
fc_hdr->fh_rx_id = htons(0xffff);
- task->rx_wr_tx_rd.rx_id = 0xffff;
+ task->rxwr_txrd.var_ctx.rx_id = 0xffff;
} else if (task_type == FCOE_TASK_TYPE_UNSOLICITED) {
fc_hdr->fh_rx_id = cpu_to_be16(io_req->xid);
}
/* Fill FC Header into middle path buffer */
- hdr = (u64 *) &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ hdr = (u64 *) &task->txwr_rxrd.union_ctx.tx_frame.fc_hdr;
memcpy(temp_hdr, fc_hdr, sizeof(temp_hdr));
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
@@ -1437,12 +1679,12 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
/* Rx Only */
if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)mp_req->mp_resp_bd_dma;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)mp_req->mp_resp_bd_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
(u32)((u64)mp_req->mp_resp_bd_dma >> 32);
- task->rx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+ sgl->mul_sgl.sgl_size = 1;
}
}
@@ -1453,6 +1695,9 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
struct io_bdt *bd_tbl = io_req->bd_tbl;
struct bnx2fc_rport *tgt = io_req->tgt;
+ struct fcoe_cached_sge_ctx *cached_sge;
+ struct fcoe_ext_mul_sges_ctx *sgl;
+ int dev_type = tgt->dev_type;
u64 *fcp_cmnd;
u64 tmp_fcp_cmnd[4];
u32 context_id;
@@ -1470,48 +1715,56 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
task_type = FCOE_TASK_TYPE_READ;
/* Tx only */
+ bd_count = bd_tbl->bd_valid;
if (task_type == FCOE_TASK_TYPE_WRITE) {
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)bd_tbl->bd_tbl_dma;
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
- (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
- task->tx_wr_only.sgl_ctx.mul_sges.sgl_size =
- bd_tbl->bd_valid;
+ if ((dev_type == TYPE_DISK) && (bd_count == 1)) {
+ struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+ task->txwr_only.sgl_ctx.cached_sge.cur_buf_addr.lo =
+ fcoe_bd_tbl->buf_addr_lo;
+ task->txwr_only.sgl_ctx.cached_sge.cur_buf_addr.hi =
+ fcoe_bd_tbl->buf_addr_hi;
+ task->txwr_only.sgl_ctx.cached_sge.cur_buf_rem =
+ fcoe_bd_tbl->buf_len;
+
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
+ } else {
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
+ (u32)bd_tbl->bd_tbl_dma;
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
+ (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
+ bd_tbl->bd_valid;
+ }
}
/*Tx Write Rx Read */
/* Init state to NORMAL */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
- /* Common */
- task->cmn.data_2_trns = io_req->data_xfer_len;
- context_id = tgt->context_id;
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
-
- /* Set initiative ownership */
- task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT;
+ task->txwr_rxrd.const_ctx.init_flags |= task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ if (dev_type == TYPE_TAPE) {
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_TAPE <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ io_req->rec_retry = 0;
+ io_req->rec_retry = 0;
+ } else
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ /* tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
/* Set initial seq counter */
- task->cmn.tx_low_seq_cnt = 1;
-
- /* Set state to "waiting for the first packet" */
- task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME;
+ task->txwr_rxrd.union_ctx.tx_seq.ctx.seq_cnt = 1;
/* Fill FCP_CMND IU */
fcp_cmnd = (u64 *)
- task->cmn.general.cmd_info.fcp_cmd_payload.opaque;
+ task->txwr_rxrd.union_ctx.fcp_cmd.opaque;
bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
/* swap fcp_cmnd */
@@ -1523,33 +1776,61 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
}
/* Rx Write Tx Read */
- task->rx_wr_tx_rd.rx_id = 0xffff;
+ task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
- /* Rx Only */
- if (task_type == FCOE_TASK_TYPE_READ) {
+ context_id = tgt->context_id;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
+ /* rx flags */
+ /* Set state to "waiting for the first packet" */
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
- bd_count = bd_tbl->bd_valid;
+ task->rxwr_txrd.var_ctx.rx_id = 0xffff;
+
+ /* Rx Only */
+ cached_sge = &task->rxwr_only.union_ctx.read_info.sgl_ctx.cached_sge;
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
+ bd_count = bd_tbl->bd_valid;
+ if (task_type == FCOE_TASK_TYPE_READ &&
+ dev_type == TYPE_DISK) {
if (bd_count == 1) {
struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.lo =
- fcoe_bd_tbl->buf_addr_lo;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.hi =
- fcoe_bd_tbl->buf_addr_hi;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_rem =
- fcoe_bd_tbl->buf_len;
- task->tx_wr_rx_rd.init_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT;
+ cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
+ } else if (bd_count == 2) {
+ struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+ cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+
+ fcoe_bd_tbl++;
+ cached_sge->second_buf_addr.lo =
+ fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->second_buf_addr.hi =
+ fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->second_buf_rem = fcoe_bd_tbl->buf_len;
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
} else {
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)bd_tbl->bd_tbl_dma;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)bd_tbl->bd_tbl_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
- task->rx_wr_only.sgl_ctx.mul_sges.sgl_size =
- bd_tbl->bd_valid;
+ sgl->mul_sgl.sgl_size = bd_count;
}
+ } else {
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)bd_tbl->bd_tbl_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
+ (u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+ sgl->mul_sgl.sgl_size = bd_count;
}
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index ca4be24..182fcb2 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1,7 +1,7 @@
/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
* IO manager and SCSI IO processing.
*
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom Corporation
*
* 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
@@ -17,9 +17,7 @@
static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
int bd_index);
static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
-static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
-static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
- struct bnx2fc_cmd *io_req);
+static int bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req);
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
@@ -29,10 +27,11 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
unsigned int timer_msec)
{
- struct bnx2fc_hba *hba = io_req->port->priv;
+ struct bnx2fc_interface *interface = io_req->port->priv;
- if (queue_delayed_work(hba->timer_work_queue, &io_req->timeout_work,
- msecs_to_jiffies(timer_msec)))
+ if (queue_delayed_work(interface->timer_work_queue,
+ &io_req->timeout_work,
+ msecs_to_jiffies(timer_msec)))
kref_get(&io_req->refcount);
}
@@ -217,6 +216,11 @@ static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code)
return;
BNX2FC_IO_DBG(io_req, "scsi_done. err_code = 0x%x\n", err_code);
+ if (test_bit(BNX2FC_FLAG_CMD_LOST, &io_req->req_flags)) {
+ /* Do not call scsi done for this IO */
+ return;
+ }
+
bnx2fc_unmap_sg_list(io_req);
io_req->sc_cmd = NULL;
if (!sc_cmd) {
@@ -419,12 +423,13 @@ free_cmgr:
struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
{
struct fcoe_port *port = tgt->port;
- struct bnx2fc_hba *hba = port->priv;
- struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_cmd_mgr *cmd_mgr = interface->hba->cmd_mgr;
struct bnx2fc_cmd *io_req;
struct list_head *listp;
struct io_bdt *bd_tbl;
int index = RESERVE_FREE_LIST_INDEX;
+ u32 free_sqes;
u32 max_sqes;
u16 xid;
@@ -445,8 +450,10 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
* cmgr lock
*/
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+ free_sqes = atomic_read(&tgt->free_sqes);
if ((list_empty(&(cmd_mgr->free_list[index]))) ||
- (tgt->num_active_ios.counter >= max_sqes)) {
+ (tgt->num_active_ios.counter >= max_sqes) ||
+ (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
"ios(%d):sqes(%d)\n",
tgt->num_active_ios.counter, tgt->max_sqes);
@@ -463,6 +470,7 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
xid = io_req->xid;
cmd_mgr->cmds[xid] = io_req;
atomic_inc(&tgt->num_active_ios);
+ atomic_dec(&tgt->free_sqes);
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
INIT_LIST_HEAD(&io_req->link);
@@ -481,14 +489,16 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
kref_init(&io_req->refcount);
return io_req;
}
-static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
+
+struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
{
struct fcoe_port *port = tgt->port;
- struct bnx2fc_hba *hba = port->priv;
- struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_cmd_mgr *cmd_mgr = interface->hba->cmd_mgr;
struct bnx2fc_cmd *io_req;
struct list_head *listp;
struct io_bdt *bd_tbl;
+ u32 free_sqes;
u32 max_sqes;
u16 xid;
int index = get_cpu();
@@ -499,8 +509,10 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
* cmgr lock
*/
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+ free_sqes = atomic_read(&tgt->free_sqes);
if ((list_empty(&cmd_mgr->free_list[index])) ||
- (tgt->num_active_ios.counter >= max_sqes)) {
+ (tgt->num_active_ios.counter >= max_sqes) ||
+ (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
put_cpu();
return NULL;
@@ -513,6 +525,7 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
xid = io_req->xid;
cmd_mgr->cmds[xid] = io_req;
atomic_inc(&tgt->num_active_ios);
+ atomic_dec(&tgt->free_sqes);
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
put_cpu();
@@ -562,7 +575,8 @@ void bnx2fc_cmd_release(struct kref *ref)
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
{
struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
- struct bnx2fc_hba *hba = io_req->port->priv;
+ struct bnx2fc_interface *interface = io_req->port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
size_t sz = sizeof(struct fcoe_bd_ctx);
/* clear tm flags */
@@ -598,7 +612,8 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
struct bnx2fc_mp_req *mp_req;
struct fcoe_bd_ctx *mp_req_bd;
struct fcoe_bd_ctx *mp_resp_bd;
- struct bnx2fc_hba *hba = io_req->port->priv;
+ struct bnx2fc_interface *interface = io_req->port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
dma_addr_t addr;
size_t sz;
@@ -674,7 +689,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
struct fc_rport_libfc_priv *rp = rport->dd_data;
struct fcoe_port *port;
- struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
struct bnx2fc_rport *tgt;
struct bnx2fc_cmd *io_req;
struct bnx2fc_mp_req *tm_req;
@@ -691,10 +706,10 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
lport = shost_priv(host);
port = lport_priv(lport);
- hba = port->priv;
+ interface = port->priv;
if (rport == NULL) {
- printk(KERN_ALERT PFX "device_reset: rport is NULL\n");
+ printk(KERN_ERR PFX "device_reset: rport is NULL\n");
rc = FAILED;
goto tmf_err;
}
@@ -737,7 +752,9 @@ retry_tmf:
rc = bnx2fc_init_mp_req(io_req);
if (rc == FAILED) {
printk(KERN_ERR PFX "Task mgmt MP request init failed\n");
+ spin_lock_bh(&tgt->tgt_lock);
kref_put(&io_req->refcount, bnx2fc_cmd_release);
+ spin_unlock_bh(&tgt->tgt_lock);
goto tmf_err;
}
@@ -766,7 +783,8 @@ retry_tmf:
index = xid % BNX2FC_TASKS_PER_PAGE;
/* Initialize task context for this IO request */
- task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[task_idx];
task = &(task_page[index]);
bnx2fc_init_mp_task(io_req, task);
@@ -798,10 +816,10 @@ retry_tmf:
spin_unlock_bh(&tgt->tgt_lock);
if (!rc) {
- printk(KERN_ERR PFX "task mgmt command failed...\n");
+ BNX2FC_TGT_DBG(tgt, "task mgmt command failed...\n");
rc = FAILED;
} else {
- printk(KERN_ERR PFX "task mgmt command success...\n");
+ BNX2FC_TGT_DBG(tgt, "task mgmt command success...\n");
rc = SUCCESS;
}
tmf_err:
@@ -814,7 +832,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
struct bnx2fc_rport *tgt = io_req->tgt;
struct fc_rport *rport = tgt->rport;
struct fc_rport_priv *rdata = tgt->rdata;
- struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
struct fcoe_port *port;
struct bnx2fc_cmd *abts_io_req;
struct fcoe_task_ctx_entry *task;
@@ -831,7 +849,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_abts\n");
port = io_req->port;
- hba = port->priv;
+ interface = port->priv;
lport = port->lport;
if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
@@ -841,7 +859,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
}
if (rport == NULL) {
- printk(KERN_ALERT PFX "initiate_abts: rport is NULL\n");
+ printk(KERN_ERR PFX "initiate_abts: rport is NULL\n");
rc = FAILED;
goto abts_err;
}
@@ -873,7 +891,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
/* Obtain oxid and rxid for the original exchange to be aborted */
fc_hdr->fh_ox_id = htons(io_req->xid);
- fc_hdr->fh_rx_id = htons(io_req->task->rx_wr_tx_rd.rx_id);
+ fc_hdr->fh_rx_id = htons(io_req->task->rxwr_txrd.var_ctx.rx_id);
sid = tgt->sid;
did = rport->port_id;
@@ -888,7 +906,8 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
index = xid % BNX2FC_TASKS_PER_PAGE;
/* Initialize task context for this IO request */
- task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[task_idx];
task = &(task_page[index]);
bnx2fc_init_mp_task(abts_io_req, task);
@@ -916,11 +935,81 @@ abts_err:
return rc;
}
+int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset,
+ enum fc_rctl r_ctl)
+{
+ struct fc_lport *lport;
+ struct bnx2fc_rport *tgt = orig_io_req->tgt;
+ struct bnx2fc_interface *interface;
+ struct fcoe_port *port;
+ struct bnx2fc_cmd *seq_clnp_req;
+ struct fcoe_task_ctx_entry *task;
+ struct fcoe_task_ctx_entry *task_page;
+ struct bnx2fc_els_cb_arg *cb_arg = NULL;
+ int task_idx, index;
+ u16 xid;
+ int rc = 0;
+
+ BNX2FC_IO_DBG(orig_io_req, "bnx2fc_initiate_seq_cleanup xid = 0x%x\n",
+ orig_io_req->xid);
+ kref_get(&orig_io_req->refcount);
+
+ port = orig_io_req->port;
+ interface = port->priv;
+ lport = port->lport;
+
+ cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+ if (!cb_arg) {
+ printk(KERN_ERR PFX "Unable to alloc cb_arg for seq clnup\n");
+ rc = -ENOMEM;
+ goto cleanup_err;
+ }
+
+ seq_clnp_req = bnx2fc_elstm_alloc(tgt, BNX2FC_SEQ_CLEANUP);
+ if (!seq_clnp_req) {
+ printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
+ rc = -ENOMEM;
+ kfree(cb_arg);
+ goto cleanup_err;
+ }
+ /* Initialize rest of io_req fields */
+ seq_clnp_req->sc_cmd = NULL;
+ seq_clnp_req->port = port;
+ seq_clnp_req->tgt = tgt;
+ seq_clnp_req->data_xfer_len = 0; /* No data transfer for cleanup */
+
+ xid = seq_clnp_req->xid;
+
+ task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+ index = xid % BNX2FC_TASKS_PER_PAGE;
+
+ /* Initialize task context for this IO request */
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[task_idx];
+ task = &(task_page[index]);
+ cb_arg->aborted_io_req = orig_io_req;
+ cb_arg->io_req = seq_clnp_req;
+ cb_arg->r_ctl = r_ctl;
+ cb_arg->offset = offset;
+ seq_clnp_req->cb_arg = cb_arg;
+
+ printk(KERN_ERR PFX "call init_seq_cleanup_task\n");
+ bnx2fc_init_seq_cleanup_task(seq_clnp_req, task, orig_io_req, offset);
+
+ /* Obtain free SQ entry */
+ bnx2fc_add_2_sq(tgt, xid);
+
+ /* Ring doorbell */
+ bnx2fc_ring_doorbell(tgt);
+cleanup_err:
+ return rc;
+}
+
int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
{
struct fc_lport *lport;
struct bnx2fc_rport *tgt = io_req->tgt;
- struct bnx2fc_hba *hba;
+ struct bnx2fc_interface *interface;
struct fcoe_port *port;
struct bnx2fc_cmd *cleanup_io_req;
struct fcoe_task_ctx_entry *task;
@@ -933,7 +1022,7 @@ int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_cleanup\n");
port = io_req->port;
- hba = port->priv;
+ interface = port->priv;
lport = port->lport;
cleanup_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_CLEANUP);
@@ -955,7 +1044,8 @@ int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
index = xid % BNX2FC_TASKS_PER_PAGE;
/* Initialize task context for this IO request */
- task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+ task_page = (struct fcoe_task_ctx_entry *)
+ interface->hba->task_ctx[task_idx];
task = &(task_page[index]);
orig_xid = io_req->xid;
@@ -1013,7 +1103,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
struct fc_rport_libfc_priv *rp = rport->dd_data;
struct bnx2fc_cmd *io_req;
struct fc_lport *lport;
+ struct fc_rport_priv *rdata;
struct bnx2fc_rport *tgt;
+ int logo_issued;
+ int wait_cnt = 0;
int rc = FAILED;
@@ -1023,7 +1116,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
lport = shost_priv(sc_cmd->device->host);
if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
- printk(KERN_ALERT PFX "eh_abort: link not ready\n");
+ printk(KERN_ERR PFX "eh_abort: link not ready\n");
return rc;
}
@@ -1054,7 +1147,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
* io_req is no longer in the active_q.
*/
if (tgt->flush_in_prog) {
- printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+ printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
"flush in progress\n", io_req->xid);
kref_put(&io_req->refcount, bnx2fc_cmd_release);
spin_unlock_bh(&tgt->tgt_lock);
@@ -1062,7 +1155,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
}
if (io_req->on_active_queue == 0) {
- printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+ printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
"not on active_q\n", io_req->xid);
/*
* This condition can happen only due to the FW bug,
@@ -1100,10 +1193,42 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
rc = bnx2fc_initiate_abts(io_req);
} else {
- printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+ printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
"already in abts processing\n", io_req->xid);
+ if (cancel_delayed_work(&io_req->timeout_work))
+ kref_put(&io_req->refcount,
+ bnx2fc_cmd_release); /* drop timer hold */
+ bnx2fc_initiate_cleanup(io_req);
+
+ spin_unlock_bh(&tgt->tgt_lock);
+
+ wait_for_completion(&io_req->tm_done);
+
+ spin_lock_bh(&tgt->tgt_lock);
+ io_req->wait_for_comp = 0;
+ rdata = io_req->tgt->rdata;
+ logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
+ &tgt->flags);
kref_put(&io_req->refcount, bnx2fc_cmd_release);
spin_unlock_bh(&tgt->tgt_lock);
+
+ if (!logo_issued) {
+ BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
+ tgt->flags);
+ mutex_lock(&lport->disc.disc_mutex);
+ lport->tt.rport_logoff(rdata);
+ mutex_unlock(&lport->disc.disc_mutex);
+ do {
+ msleep(BNX2FC_RELOGIN_WAIT_TIME);
+ /*
+ * If session not recovered, let SCSI-ml
+ * escalate error recovery.
+ */
+ if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT)
+ return FAILED;
+ } while (!test_bit(BNX2FC_FLAG_SESSION_READY,
+ &tgt->flags));
+ }
return SUCCESS;
}
if (rc == FAILED) {
@@ -1141,6 +1266,41 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
return rc;
}
+void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnp_req,
+ struct fcoe_task_ctx_entry *task,
+ u8 rx_state)
+{
+ struct bnx2fc_els_cb_arg *cb_arg = seq_clnp_req->cb_arg;
+ struct bnx2fc_cmd *orig_io_req = cb_arg->aborted_io_req;
+ u32 offset = cb_arg->offset;
+ enum fc_rctl r_ctl = cb_arg->r_ctl;
+ int rc = 0;
+ struct bnx2fc_rport *tgt = orig_io_req->tgt;
+
+ BNX2FC_IO_DBG(orig_io_req, "Entered process_cleanup_compl xid = 0x%x"
+ "cmd_type = %d\n",
+ seq_clnp_req->xid, seq_clnp_req->cmd_type);
+
+ if (rx_state == FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP) {
+ printk(KERN_ERR PFX "seq cleanup ignored - xid = 0x%x\n",
+ seq_clnp_req->xid);
+ goto free_cb_arg;
+ }
+
+ spin_unlock_bh(&tgt->tgt_lock);
+ rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
+ spin_lock_bh(&tgt->tgt_lock);
+
+ if (rc)
+ printk(KERN_ERR PFX "clnup_compl: Unable to send SRR"
+ " IO will abort\n");
+ seq_clnp_req->cb_arg = NULL;
+ kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+free_cb_arg:
+ kfree(cb_arg);
+ return;
+}
+
void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
u8 num_rq)
@@ -1150,6 +1310,8 @@ void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
io_req->refcount.refcount.counter, io_req->cmd_type);
bnx2fc_scsi_done(io_req, DID_ERROR);
kref_put(&io_req->refcount, bnx2fc_cmd_release);
+ if (io_req->wait_for_comp)
+ complete(&io_req->tm_done);
}
void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
@@ -1189,7 +1351,7 @@ void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
kref_put(&io_req->refcount,
bnx2fc_cmd_release); /* drop timer hold */
- r_ctl = task->cmn.general.rsp_info.abts_rsp.r_ctl;
+ r_ctl = (u8)task->rxwr_only.union_ctx.comp_info.abts_rsp.r_ctl;
switch (r_ctl) {
case FC_RCTL_BA_ACC:
@@ -1344,12 +1506,13 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
fc_hdr = &(tm_req->resp_fc_hdr);
hdr = (u64 *)fc_hdr;
temp_hdr = (u64 *)
- &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
hdr[2] = cpu_to_be64(temp_hdr[2]);
- tm_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+ tm_req->resp_len =
+ task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
rsp_buf = tm_req->resp_buf;
@@ -1369,7 +1532,7 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
fc_hdr->fh_r_ctl);
}
if (!sc_cmd->SCp.ptr) {
- printk(KERN_ALERT PFX "tm_compl: SCp.ptr is NULL\n");
+ printk(KERN_ERR PFX "tm_compl: SCp.ptr is NULL\n");
return;
}
switch (io_req->fcp_status) {
@@ -1401,7 +1564,7 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
io_req->on_tmf_queue = 0;
} else {
- printk(KERN_ALERT PFX "Command not on active_cmd_queue!\n");
+ printk(KERN_ERR PFX "Command not on active_cmd_queue!\n");
return;
}
@@ -1442,6 +1605,8 @@ static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
{
+ struct bnx2fc_interface *interface = io_req->port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct scsi_cmnd *sc = io_req->sc_cmd;
struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
struct scatterlist *sg;
@@ -1453,7 +1618,8 @@ static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
u64 addr;
int i;
- sg_count = scsi_dma_map(sc);
+ sg_count = dma_map_sg(&hba->pcidev->dev, scsi_sglist(sc),
+ scsi_sg_count(sc), sc->sc_data_direction);
scsi_for_each_sg(sc, sg, sg_count, i) {
sg_len = sg_dma_len(sg);
addr = sg_dma_address(sg);
@@ -1478,20 +1644,24 @@ static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
return bd_count;
}
-static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req)
+static int bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req)
{
struct scsi_cmnd *sc = io_req->sc_cmd;
struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
int bd_count;
- if (scsi_sg_count(sc))
+ if (scsi_sg_count(sc)) {
bd_count = bnx2fc_map_sg(io_req);
- else {
+ if (bd_count == 0)
+ return -ENOMEM;
+ } else {
bd_count = 0;
bd[0].buf_addr_lo = bd[0].buf_addr_hi = 0;
bd[0].buf_len = bd[0].flags = 0;
}
io_req->bd_tbl->bd_valid = bd_count;
+
+ return 0;
}
static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req)
@@ -1588,7 +1758,7 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
if (rq_buff_len > num_rq * BNX2FC_RQ_BUF_SZ) {
/* Invalid sense sense length. */
- printk(KERN_ALERT PFX "invalid sns length %d\n",
+ printk(KERN_ERR PFX "invalid sns length %d\n",
rq_buff_len);
/* reset rq_buff_len */
rq_buff_len = num_rq * BNX2FC_RQ_BUF_SZ;
@@ -1663,12 +1833,6 @@ int bnx2fc_queuecommand(struct Scsi_Host *host,
tgt = (struct bnx2fc_rport *)&rp[1];
if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
- if (test_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags)) {
- sc_cmd->result = DID_NO_CONNECT << 16;
- sc_cmd->scsi_done(sc_cmd);
- return 0;
-
- }
/*
* Session is not offloaded yet. Let SCSI-ml retry
* the command.
@@ -1724,7 +1888,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
/* Fetch fcp_rsp from task context and perform cmd completion */
fcp_rsp = (struct fcoe_fcp_rsp_payload *)
- &(task->cmn.general.rsp_info.fcp_rsp.payload);
+ &(task->rxwr_only.union_ctx.comp_info.fcp_rsp.payload);
/* parse fcp_rsp and obtain sense data from RQ if available */
bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
@@ -1771,7 +1935,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
scsi_set_resid(sc_cmd, io_req->fcp_resid);
break;
default:
- printk(KERN_ALERT PFX "scsi_cmd_compl: fcp_status = %d\n",
+ printk(KERN_ERR PFX "scsi_cmd_compl: fcp_status = %d\n",
io_req->fcp_status);
break;
}
@@ -1780,14 +1944,15 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
kref_put(&io_req->refcount, bnx2fc_cmd_release);
}
-static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
+int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
struct bnx2fc_cmd *io_req)
{
struct fcoe_task_ctx_entry *task;
struct fcoe_task_ctx_entry *task_page;
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
struct fcoe_port *port = tgt->port;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct fc_lport *lport = port->lport;
struct fcoe_dev_stats *stats;
int task_idx, index;
@@ -1818,7 +1983,13 @@ static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
xid = io_req->xid;
/* Build buffer descriptor list for firmware from sg list */
- bnx2fc_build_bd_list_from_sg(io_req);
+ if (bnx2fc_build_bd_list_from_sg(io_req)) {
+ printk(KERN_ERR PFX "BD list creation failed\n");
+ spin_lock_bh(&tgt->tgt_lock);
+ kref_put(&io_req->refcount, bnx2fc_cmd_release);
+ spin_unlock_bh(&tgt->tgt_lock);
+ return -EAGAIN;
+ }
task_idx = xid / BNX2FC_TASKS_PER_PAGE;
index = xid % BNX2FC_TASKS_PER_PAGE;
@@ -1845,7 +2016,8 @@ static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
}
/* Time IO req */
- bnx2fc_cmd_timer_set(io_req, BNX2FC_IO_TIMEOUT);
+ if (tgt->io_timeout)
+ bnx2fc_cmd_timer_set(io_req, BNX2FC_IO_TIMEOUT);
/* Obtain free SQ entry */
bnx2fc_add_2_sq(tgt, xid);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index a2e3830..c1800b5 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -2,7 +2,7 @@
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2010 Broadcom Corporation
+ * Copyright (c) 2008 - 2011 Broadcom Corporation
*
* 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
@@ -65,7 +65,8 @@ static void bnx2fc_offload_session(struct fcoe_port *port,
{
struct fc_lport *lport = rdata->local_port;
struct fc_rport *rport = rdata->rport;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
int rval;
int i = 0;
@@ -75,7 +76,7 @@ static void bnx2fc_offload_session(struct fcoe_port *port,
if (rval) {
printk(KERN_ERR PFX "Failed to allocate conn id for "
"port_id (%6x)\n", rport->port_id);
- goto ofld_err;
+ goto tgt_init_err;
}
/* Allocate session resources */
@@ -138,11 +139,12 @@ retry_ofld:
ofld_err:
/* couldn't offload the session. log off from this rport */
BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n");
- lport->tt.rport_logoff(rdata);
/* Free session resources */
bnx2fc_free_session_resc(hba, tgt);
+tgt_init_err:
if (tgt->fcoe_conn_id != -1)
bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+ lport->tt.rport_logoff(rdata);
}
void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
@@ -235,7 +237,8 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
static void bnx2fc_upload_session(struct fcoe_port *port,
struct bnx2fc_rport *tgt)
{
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
BNX2FC_TGT_DBG(tgt, "upload_session: active_ios = %d\n",
tgt->num_active_ios.counter);
@@ -314,7 +317,10 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
{
struct fc_rport *rport = rdata->rport;
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
+ struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
+ struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
tgt->rport = rport;
tgt->rdata = rdata;
@@ -335,6 +341,7 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
tgt->max_sqes = BNX2FC_SQ_WQES_MAX;
tgt->max_rqes = BNX2FC_RQ_WQES_MAX;
tgt->max_cqes = BNX2FC_CQ_WQES_MAX;
+ atomic_set(&tgt->free_sqes, BNX2FC_SQ_WQES_MAX);
/* Initialize the toggle bit */
tgt->sq_curr_toggle_bit = 1;
@@ -345,7 +352,25 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
tgt->rq_cons_idx = 0;
atomic_set(&tgt->num_active_ios, 0);
- tgt->work_time_slice = 2;
+ if (rdata->flags & FC_RP_FLAGS_RETRY) {
+ tgt->dev_type = TYPE_TAPE;
+ tgt->io_timeout = 0; /* use default ULP timeout */
+ } else {
+ tgt->dev_type = TYPE_DISK;
+ tgt->io_timeout = BNX2FC_IO_TIMEOUT;
+ }
+
+ /* initialize sq doorbell */
+ sq_db->header.header = B577XX_DOORBELL_HDR_DB_TYPE;
+ sq_db->header.header |= B577XX_FCOE_CONNECTION_TYPE <<
+ B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
+ /* initialize rx doorbell */
+ rx_db->hdr.header = ((0x1 << B577XX_DOORBELL_HDR_RX_SHIFT) |
+ (0x1 << B577XX_DOORBELL_HDR_DB_TYPE_SHIFT) |
+ (B577XX_FCOE_CONNECTION_TYPE <<
+ B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT));
+ rx_db->params = (0x2 << B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT) |
+ (0x3 << B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT);
spin_lock_init(&tgt->tgt_lock);
spin_lock_init(&tgt->cq_lock);
@@ -377,7 +402,8 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
enum fc_rport_event event)
{
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct fc_rport *rport = rdata->rport;
struct fc_rport_libfc_priv *rp;
struct bnx2fc_rport *tgt;
@@ -388,7 +414,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
switch (event) {
case RPORT_EV_READY:
if (!rport) {
- printk(KERN_ALERT PFX "rport is NULL: ERROR!\n");
+ printk(KERN_ERR PFX "rport is NULL: ERROR!\n");
break;
}
@@ -400,7 +426,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
* We should not come here, as lport will
* take care of fabric login
*/
- printk(KERN_ALERT PFX "%x - rport_event_handler ERROR\n",
+ printk(KERN_ERR PFX "%x - rport_event_handler ERROR\n",
rdata->ids.port_id);
break;
}
@@ -468,7 +494,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
break;
if (!rport) {
- printk(KERN_ALERT PFX "%x - rport not created Yet!!\n",
+ printk(KERN_INFO PFX "%x - rport not created Yet!!\n",
port_id);
break;
}
@@ -522,7 +548,8 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
u32 port_id)
{
- struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct bnx2fc_rport *tgt;
struct fc_rport_priv *rdata;
int i;
@@ -537,7 +564,7 @@ struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
"obtained\n");
return tgt;
} else {
- printk(KERN_ERR PFX "rport 0x%x "
+ BNX2FC_TGT_DBG(tgt, "rport 0x%x "
"is in DELETED state\n",
rdata->ids.port_id);
return NULL;
@@ -596,7 +623,6 @@ static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id)
/* called with hba mutex held */
spin_lock_bh(&hba->hba_lock);
hba->tgt_ofld_list[conn_id] = NULL;
- hba->next_conn_id = conn_id;
spin_unlock_bh(&hba->hba_lock);
}
@@ -618,7 +644,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
&tgt->sq_dma, GFP_KERNEL);
if (!tgt->sq) {
- printk(KERN_ALERT PFX "unable to allocate SQ memory %d\n",
+ printk(KERN_ERR PFX "unable to allocate SQ memory %d\n",
tgt->sq_mem_size);
goto mem_alloc_failure;
}
@@ -631,7 +657,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
&tgt->cq_dma, GFP_KERNEL);
if (!tgt->cq) {
- printk(KERN_ALERT PFX "unable to allocate CQ memory %d\n",
+ printk(KERN_ERR PFX "unable to allocate CQ memory %d\n",
tgt->cq_mem_size);
goto mem_alloc_failure;
}
@@ -644,7 +670,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
&tgt->rq_dma, GFP_KERNEL);
if (!tgt->rq) {
- printk(KERN_ALERT PFX "unable to allocate RQ memory %d\n",
+ printk(KERN_ERR PFX "unable to allocate RQ memory %d\n",
tgt->rq_mem_size);
goto mem_alloc_failure;
}
@@ -656,7 +682,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
&tgt->rq_pbl_dma, GFP_KERNEL);
if (!tgt->rq_pbl) {
- printk(KERN_ALERT PFX "unable to allocate RQ PBL %d\n",
+ printk(KERN_ERR PFX "unable to allocate RQ PBL %d\n",
tgt->rq_pbl_size);
goto mem_alloc_failure;
}
@@ -682,7 +708,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
&tgt->xferq_dma, GFP_KERNEL);
if (!tgt->xferq) {
- printk(KERN_ALERT PFX "unable to allocate XFERQ %d\n",
+ printk(KERN_ERR PFX "unable to allocate XFERQ %d\n",
tgt->xferq_mem_size);
goto mem_alloc_failure;
}
@@ -696,7 +722,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->confq = dma_alloc_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
&tgt->confq_dma, GFP_KERNEL);
if (!tgt->confq) {
- printk(KERN_ALERT PFX "unable to allocate CONFQ %d\n",
+ printk(KERN_ERR PFX "unable to allocate CONFQ %d\n",
tgt->confq_mem_size);
goto mem_alloc_failure;
}
@@ -711,7 +737,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->confq_pbl_size,
&tgt->confq_pbl_dma, GFP_KERNEL);
if (!tgt->confq_pbl) {
- printk(KERN_ALERT PFX "unable to allocate CONFQ PBL %d\n",
+ printk(KERN_ERR PFX "unable to allocate CONFQ PBL %d\n",
tgt->confq_pbl_size);
goto mem_alloc_failure;
}
@@ -736,7 +762,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->conn_db_mem_size,
&tgt->conn_db_dma, GFP_KERNEL);
if (!tgt->conn_db) {
- printk(KERN_ALERT PFX "unable to allocate conn_db %d\n",
+ printk(KERN_ERR PFX "unable to allocate conn_db %d\n",
tgt->conn_db_mem_size);
goto mem_alloc_failure;
}
@@ -752,21 +778,17 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
&tgt->lcq_dma, GFP_KERNEL);
if (!tgt->lcq) {
- printk(KERN_ALERT PFX "unable to allocate lcq %d\n",
+ printk(KERN_ERR PFX "unable to allocate lcq %d\n",
tgt->lcq_mem_size);
goto mem_alloc_failure;
}
memset(tgt->lcq, 0, tgt->lcq_mem_size);
- /* Arm CQ */
- tgt->conn_db->cq_arm.lo = -1;
tgt->conn_db->rq_prod = 0x8000;
return 0;
mem_alloc_failure:
- bnx2fc_free_session_resc(hba, tgt);
- bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
return -ENOMEM;
}
@@ -781,12 +803,14 @@ mem_alloc_failure:
static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
struct bnx2fc_rport *tgt)
{
+ void __iomem *ctx_base_ptr;
+
BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
- if (tgt->ctx_base) {
- iounmap(tgt->ctx_base);
- tgt->ctx_base = NULL;
- }
+ spin_lock_bh(&tgt->cq_lock);
+ ctx_base_ptr = tgt->ctx_base;
+ tgt->ctx_base = NULL;
+
/* Free LCQ */
if (tgt->lcq) {
dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
@@ -828,17 +852,19 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
tgt->rq = NULL;
}
/* Free CQ */
- spin_lock_bh(&tgt->cq_lock);
if (tgt->cq) {
dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
tgt->cq, tgt->cq_dma);
tgt->cq = NULL;
}
- spin_unlock_bh(&tgt->cq_lock);
/* Free SQ */
if (tgt->sq) {
dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
tgt->sq, tgt->sq_dma);
tgt->sq = NULL;
}
+ spin_unlock_bh(&tgt->cq_lock);
+
+ if (ctx_base_ptr)
+ iounmap(ctx_base_ptr);
}
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 30e6bdb..57515f1 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,6 +1,6 @@
/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
*
* 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
@@ -125,7 +125,7 @@
/* SQ/RQ/CQ DB structure sizes */
#define ISCSI_SQ_DB_SIZE (16)
-#define ISCSI_RQ_DB_SIZE (16)
+#define ISCSI_RQ_DB_SIZE (64)
#define ISCSI_CQ_DB_SIZE (80)
#define ISCSI_SQN_TO_NOTIFY_NOT_VALID 0xFFFF
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index dad6c8a..72118db 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,6 +1,6 @@
/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
*
* 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
@@ -707,8 +707,10 @@ struct iscsi_kwqe_conn_update {
#define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
#elif defined(__LITTLE_ENDIAN)
u8 conn_flags;
#define ISCSI_KWQE_CONN_UPDATE_HEADER_DIGEST (0x1<<0)
@@ -719,8 +721,10 @@ struct iscsi_kwqe_conn_update {
#define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
u8 reserved2;
u8 max_outstanding_r2ts;
u8 session_error_recovery_level;
diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig
index 45a6154..01cff18 100644
--- a/drivers/scsi/bnx2i/Kconfig
+++ b/drivers/scsi/bnx2i/Kconfig
@@ -4,7 +4,8 @@ config SCSI_BNX2_ISCSI
depends on PCI
select SCSI_ISCSI_ATTRS
select NETDEVICES
- select NETDEV_1000
+ select ETHERNET
+ select NET_VENDOR_BROADCOM
select CNIC
---help---
This driver supports iSCSI offload for the Broadcom NetXtreme II
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 6bdd25a..0bd70e8 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -22,11 +22,14 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/in.h>
#include <linux/kfifo.h>
#include <linux/netdevice.h>
#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -37,7 +40,7 @@
#include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h>
-#include "../../net/cnic_if.h"
+#include "../../net/ethernet/broadcom/cnic_if.h"
#include "57xx_iscsi_hsi.h"
#include "57xx_iscsi_constants.h"
@@ -202,10 +205,13 @@ struct io_bdt {
/**
* bnx2i_cmd - iscsi command structure
*
+ * @hdr: iSCSI header
+ * @conn: iscsi_conn pointer
* @scsi_cmd: SCSI-ML task pointer corresponding to this iscsi cmd
* @sg: SG list
* @io_tbl: buffer descriptor (BD) table
* @bd_tbl_dma: buffer descriptor (BD) table's dma address
+ * @req: bnx2i specific command request struct
*/
struct bnx2i_cmd {
struct iscsi_hdr hdr;
@@ -229,6 +235,7 @@ struct bnx2i_cmd {
* @gen_pdu: login/nopout/logout pdu resources
* @violation_notified: bit mask used to track iscsi error/warning messages
* already printed out
+ * @work_cnt: keeps track of the number of outstanding work
*
* iSCSI connection structure
*/
@@ -252,6 +259,8 @@ struct bnx2i_conn {
*/
struct generic_pdu_resc gen_pdu;
u64 violation_notified;
+
+ atomic_t work_cnt;
};
@@ -478,7 +487,7 @@ struct bnx2i_5771x_cq_db {
struct bnx2i_5771x_sq_rq_db {
u16 prod_idx;
- u8 reserved0[14]; /* Pad structure size to 16 bytes */
+ u8 reserved0[62]; /* Pad structure size to 64 bytes */
};
@@ -661,7 +670,6 @@ enum {
* @hba: adapter to which this connection belongs
* @conn: iscsi connection this EP is linked to
* @cls_ep: associated iSCSI endpoint pointer
- * @sess: iscsi session this EP is linked to
* @cm_sk: cnic sock struct
* @hba_age: age to detect if 'iscsid' issues ep_disconnect()
* after HBA reset is completed by bnx2i/cnic/bnx2
@@ -687,7 +695,7 @@ struct bnx2i_endpoint {
u32 hba_age;
u32 state;
unsigned long timestamp;
- int num_active_cmds;
+ atomic_t num_active_cmds;
u32 ec_shift;
struct qp_info qp;
@@ -700,6 +708,19 @@ struct bnx2i_endpoint {
};
+struct bnx2i_work {
+ struct list_head list;
+ struct iscsi_session *session;
+ struct bnx2i_conn *bnx2i_conn;
+ struct cqe cqe;
+};
+
+struct bnx2i_percpu_s {
+ struct task_struct *iothread;
+ struct list_head work_list;
+ spinlock_t p_work_lock;
+};
+
/* Global variables */
extern unsigned int error_mask1, error_mask2;
@@ -783,7 +804,7 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list(
struct bnx2i_hba *hba, u32 iscsi_cid);
extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep);
-extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
+extern int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep);
@@ -793,4 +814,8 @@ extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn);
extern void bnx2i_print_xmit_pdu_queue(struct bnx2i_conn *conn);
extern void bnx2i_print_recv_state(struct bnx2i_conn *conn);
+extern int bnx2i_percpu_io_thread(void *arg);
+extern int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
+ struct bnx2i_conn *bnx2i_conn,
+ struct cqe *cqe);
#endif
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index ca397f8..1069974 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,6 +1,6 @@
/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -17,6 +17,8 @@
#include <scsi/libiscsi.h>
#include "bnx2i.h"
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
+
/**
* bnx2i_get_cid_num - get cid from ep
* @ep: endpoint pointer
@@ -131,16 +133,16 @@ static void bnx2i_iscsi_license_error(struct bnx2i_hba *hba, u32 error_code)
* the driver. EQ event is generated CQ index is hit or at least 1 CQ is
* outstanding and on chip timer expires
*/
-void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
+int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
{
struct bnx2i_5771x_cq_db *cq_db;
u16 cq_index;
- u16 next_index;
+ u16 next_index = 0;
u32 num_active_cmds;
/* Coalesce CQ entries only on 10G devices */
if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type))
- return;
+ return 0;
/* Do not update CQ DB multiple times before firmware writes
* '0xFFFF' to CQDB->SQN field. Deviation may cause spurious
@@ -150,16 +152,17 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
if (action != CNIC_ARM_CQE_FP)
if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF)
- return;
+ return 0;
if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) {
- num_active_cmds = ep->num_active_cmds;
+ num_active_cmds = atomic_read(&ep->num_active_cmds);
if (num_active_cmds <= event_coal_min)
next_index = 1;
- else
- next_index = event_coal_min +
- ((num_active_cmds - event_coal_min) >>
- ep->ec_shift);
+ else {
+ next_index = num_active_cmds >> ep->ec_shift;
+ if (next_index > num_active_cmds - event_coal_min)
+ next_index = num_active_cmds - event_coal_min;
+ }
if (!next_index)
next_index = 1;
cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1;
@@ -170,6 +173,7 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
cq_db->sqn[0] = cq_index;
}
+ return next_index;
}
@@ -265,7 +269,7 @@ static void bnx2i_ring_sq_dbell(struct bnx2i_conn *bnx2i_conn, int count)
struct bnx2i_5771x_sq_rq_db *sq_db;
struct bnx2i_endpoint *ep = bnx2i_conn->ep;
- ep->num_active_cmds++;
+ atomic_inc(&ep->num_active_cmds);
wmb(); /* flush SQ WQE memory before the doorbell is rung */
if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
sq_db = (struct bnx2i_5771x_sq_rq_db *) ep->qp.sq_pgtbl_virt;
@@ -328,11 +332,11 @@ int bnx2i_send_iscsi_login(struct bnx2i_conn *bnx2i_conn,
{
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_login_request *login_wqe;
- struct iscsi_login *login_hdr;
+ struct iscsi_login_req *login_hdr;
u32 dword;
bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
- login_hdr = (struct iscsi_login *)task->hdr;
+ login_hdr = (struct iscsi_login_req *)task->hdr;
login_wqe = (struct bnx2i_login_request *)
bnx2i_conn->ep->qp.sq_prod_qe;
@@ -430,7 +434,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
default:
tmfabort_wqe->ref_itt = RESERVED_ITT;
}
- memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+ memcpy(scsi_lun, &tmfabort_hdr->lun, sizeof(struct scsi_lun));
tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
@@ -547,7 +551,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
nopout_wqe->op_code = nopout_hdr->opcode;
nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL;
- memcpy(nopout_wqe->lun, nopout_hdr->lun, 8);
+ memcpy(nopout_wqe->lun, &nopout_hdr->lun, 8);
if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
u32 tmp = nopout_wqe->lun[0];
@@ -559,7 +563,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
nopout_wqe->itt = ((u16)task->itt |
(ISCSI_TASK_TYPE_MPATH <<
ISCSI_TMF_REQUEST_TYPE_SHIFT));
- nopout_wqe->ttt = nopout_hdr->ttt;
+ nopout_wqe->ttt = be32_to_cpu(nopout_hdr->ttt);
nopout_wqe->flags = 0;
if (!unsol)
nopout_wqe->flags = ISCSI_NOP_OUT_REQUEST_LOCAL_COMPLETION;
@@ -1334,24 +1338,25 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
/**
* bnx2i_process_scsi_cmd_resp - this function handles scsi cmd completion.
- * @conn: iscsi connection
+ * @session: iscsi session
+ * @bnx2i_conn: bnx2i connection
* @cqe: pointer to newly DMA'ed CQE entry for processing
*
* process SCSI CMD Response CQE & complete the request to SCSI-ML
*/
-static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
- struct bnx2i_conn *bnx2i_conn,
- struct cqe *cqe)
+int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
+ struct bnx2i_conn *bnx2i_conn,
+ struct cqe *cqe)
{
struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
struct bnx2i_cmd_response *resp_cqe;
struct bnx2i_cmd *bnx2i_cmd;
struct iscsi_task *task;
- struct iscsi_cmd_rsp *hdr;
+ struct iscsi_scsi_rsp *hdr;
u32 datalen = 0;
resp_cqe = (struct bnx2i_cmd_response *)cqe;
- spin_lock(&session->lock);
+ spin_lock_bh(&session->lock);
task = iscsi_itt_to_task(conn,
resp_cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
if (!task)
@@ -1374,7 +1379,7 @@ static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
}
bnx2i_iscsi_unmap_sg_list(bnx2i_cmd);
- hdr = (struct iscsi_cmd_rsp *)task->hdr;
+ hdr = (struct iscsi_scsi_rsp *)task->hdr;
resp_cqe = (struct bnx2i_cmd_response *)cqe;
hdr->opcode = resp_cqe->op_code;
hdr->max_cmdsn = cpu_to_be32(resp_cqe->max_cmd_sn);
@@ -1412,7 +1417,7 @@ done:
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr,
conn->data, datalen);
fail:
- spin_unlock(&session->lock);
+ spin_unlock_bh(&session->lock);
return 0;
}
@@ -1714,7 +1719,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
hdr->flags = ISCSI_FLAG_CMD_FINAL;
hdr->itt = task->hdr->itt;
hdr->ttt = cpu_to_be32(nop_in->ttt);
- memcpy(hdr->lun, nop_in->lun, 8);
+ memcpy(&hdr->lun, nop_in->lun, 8);
}
done:
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -1757,7 +1762,7 @@ static void bnx2i_process_async_mesg(struct iscsi_session *session,
resp_hdr->opcode = async_cqe->op_code;
resp_hdr->flags = 0x80;
- memcpy(resp_hdr->lun, async_cqe->lun, 8);
+ memcpy(&resp_hdr->lun, async_cqe->lun, 8);
resp_hdr->exp_cmdsn = cpu_to_be32(async_cqe->exp_cmd_sn);
resp_hdr->max_cmdsn = cpu_to_be32(async_cqe->max_cmd_sn);
@@ -1839,21 +1844,137 @@ static void bnx2i_process_cmd_cleanup_resp(struct iscsi_session *session,
}
+/**
+ * bnx2i_percpu_io_thread - thread per cpu for ios
+ *
+ * @arg: ptr to bnx2i_percpu_info structure
+ */
+int bnx2i_percpu_io_thread(void *arg)
+{
+ struct bnx2i_percpu_s *p = arg;
+ struct bnx2i_work *work, *tmp;
+ LIST_HEAD(work_list);
+
+ set_user_nice(current, -20);
+
+ while (!kthread_should_stop()) {
+ spin_lock_bh(&p->p_work_lock);
+ while (!list_empty(&p->work_list)) {
+ list_splice_init(&p->work_list, &work_list);
+ spin_unlock_bh(&p->p_work_lock);
+
+ list_for_each_entry_safe(work, tmp, &work_list, list) {
+ list_del_init(&work->list);
+ /* work allocated in the bh, freed here */
+ bnx2i_process_scsi_cmd_resp(work->session,
+ work->bnx2i_conn,
+ &work->cqe);
+ atomic_dec(&work->bnx2i_conn->work_cnt);
+ kfree(work);
+ }
+ spin_lock_bh(&p->p_work_lock);
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_bh(&p->p_work_lock);
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+
+ return 0;
+}
+
+
+/**
+ * bnx2i_queue_scsi_cmd_resp - queue cmd completion to the percpu thread
+ * @bnx2i_conn: bnx2i connection
+ *
+ * this function is called by generic KCQ handler to queue all pending cmd
+ * completion CQEs
+ *
+ * The implementation is to queue the cmd response based on the
+ * last recorded command for the given connection. The
+ * cpu_id gets recorded upon task_xmit. No out-of-order completion!
+ */
+static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session,
+ struct bnx2i_conn *bnx2i_conn,
+ struct bnx2i_nop_in_msg *cqe)
+{
+ struct bnx2i_work *bnx2i_work = NULL;
+ struct bnx2i_percpu_s *p = NULL;
+ struct iscsi_task *task;
+ struct scsi_cmnd *sc;
+ int rc = 0;
+ int cpu;
+
+ spin_lock(&session->lock);
+ task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data,
+ cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
+ if (!task || !task->sc) {
+ spin_unlock(&session->lock);
+ return -EINVAL;
+ }
+ sc = task->sc;
+
+ if (!blk_rq_cpu_valid(sc->request))
+ cpu = smp_processor_id();
+ else
+ cpu = sc->request->cpu;
+
+ spin_unlock(&session->lock);
+
+ p = &per_cpu(bnx2i_percpu, cpu);
+ spin_lock(&p->p_work_lock);
+ if (unlikely(!p->iothread)) {
+ rc = -EINVAL;
+ goto err;
+ }
+ /* Alloc and copy to the cqe */
+ bnx2i_work = kzalloc(sizeof(struct bnx2i_work), GFP_ATOMIC);
+ if (bnx2i_work) {
+ INIT_LIST_HEAD(&bnx2i_work->list);
+ bnx2i_work->session = session;
+ bnx2i_work->bnx2i_conn = bnx2i_conn;
+ memcpy(&bnx2i_work->cqe, cqe, sizeof(struct cqe));
+ list_add_tail(&bnx2i_work->list, &p->work_list);
+ atomic_inc(&bnx2i_conn->work_cnt);
+ wake_up_process(p->iothread);
+ spin_unlock(&p->p_work_lock);
+ goto done;
+ } else
+ rc = -ENOMEM;
+err:
+ spin_unlock(&p->p_work_lock);
+ bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, (struct cqe *)cqe);
+done:
+ return rc;
+}
+
/**
* bnx2i_process_new_cqes - process newly DMA'ed CQE's
- * @bnx2i_conn: iscsi connection
+ * @bnx2i_conn: bnx2i connection
*
* this function is called by generic KCQ handler to process all pending CQE's
*/
-static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
+static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
{
struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
struct iscsi_session *session = conn->session;
- struct qp_info *qp = &bnx2i_conn->ep->qp;
+ struct qp_info *qp;
struct bnx2i_nop_in_msg *nopin;
int tgt_async_msg;
+ int cqe_cnt = 0;
+
+ if (bnx2i_conn->ep == NULL)
+ return 0;
+
+ qp = &bnx2i_conn->ep->qp;
+ if (!qp->cq_virt) {
+ printk(KERN_ALERT "bnx2i (%s): cq resr freed in bh execution!",
+ bnx2i_conn->hba->netdev->name);
+ goto out;
+ }
while (1) {
nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe;
if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
@@ -1876,8 +1997,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
switch (nopin->op_code) {
case ISCSI_OP_SCSI_CMD_RSP:
case ISCSI_OP_SCSI_DATA_IN:
- bnx2i_process_scsi_cmd_resp(session, bnx2i_conn,
- qp->cq_cons_qe);
+ /* Run the kthread engine only for data cmds
+ All other cmds will be completed in this bh! */
+ bnx2i_queue_scsi_cmd_resp(session, bnx2i_conn, nopin);
break;
case ISCSI_OP_LOGIN_RSP:
bnx2i_process_login_resp(session, bnx2i_conn,
@@ -1921,13 +2043,21 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
nopin->op_code);
}
- if (!tgt_async_msg)
- bnx2i_conn->ep->num_active_cmds--;
+ if (!tgt_async_msg) {
+ if (!atomic_read(&bnx2i_conn->ep->num_active_cmds))
+ printk(KERN_ALERT "bnx2i (%s): no active cmd! "
+ "op 0x%x\n",
+ bnx2i_conn->hba->netdev->name,
+ nopin->op_code);
+ else
+ atomic_dec(&bnx2i_conn->ep->num_active_cmds);
+ }
cqe_out:
/* clear out in production version only, till beta keep opcode
* field intact, will be helpful in debugging (context dump)
* nopin->op_code = 0;
*/
+ cqe_cnt++;
qp->cqe_exp_seq_sn++;
if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1))
qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN;
@@ -1940,6 +2070,8 @@ cqe_out:
qp->cq_cons_idx++;
}
}
+out:
+ return cqe_cnt;
}
/**
@@ -1955,6 +2087,7 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
{
struct bnx2i_conn *bnx2i_conn;
u32 iscsi_cid;
+ int nxt_idx;
iscsi_cid = new_cqe_kcqe->iscsi_conn_id;
bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid);
@@ -1967,9 +2100,12 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid);
return;
}
+
bnx2i_process_new_cqes(bnx2i_conn);
- bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
- bnx2i_process_new_cqes(bnx2i_conn);
+ nxt_idx = bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep,
+ CNIC_ARM_CQE_FP);
+ if (nxt_idx && nxt_idx == bnx2i_process_new_cqes(bnx2i_conn))
+ bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
}
@@ -2315,7 +2451,7 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
"opcode\n", hba->netdev->name);
else if (ofld_kcqe->completion_status ==
- ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
+ ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
/* error status code valid only for 5771x chipset */
ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
else
@@ -2389,14 +2525,20 @@ static void bnx2i_indicate_kcqe(void *context, struct kcqe *kcqe[],
* bnx2i_indicate_netevent - Generic netdev event handler
* @context: adapter structure pointer
* @event: event type
+ * @vlan_id: vlans id - associated vlan id with this event
*
* Handles four netdev events, NETDEV_UP, NETDEV_DOWN,
* NETDEV_GOING_DOWN and NETDEV_CHANGE
*/
-static void bnx2i_indicate_netevent(void *context, unsigned long event)
+static void bnx2i_indicate_netevent(void *context, unsigned long event,
+ u16 vlan_id)
{
struct bnx2i_hba *hba = context;
+ /* Ignore all netevent coming from vlans */
+ if (vlan_id != 0)
+ return;
+
switch (event) {
case NETDEV_UP:
if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
@@ -2514,7 +2656,7 @@ static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
static int bnx2i_send_nl_mesg(void *context, u32 msg_type,
- char *buf, u16 buflen)
+ char *buf, u16 buflen)
{
struct bnx2i_hba *hba = context;
int rc;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6adbdc3..1a947f1 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
static u32 adapter_count;
#define DRV_MODULE_NAME "bnx2i"
-#define DRV_MODULE_VERSION "2.6.2.3"
-#define DRV_MODULE_RELDATE "Dec 31, 2010"
+#define DRV_MODULE_VERSION "2.7.0.3"
+#define DRV_MODULE_RELDATE "Jun 15, 2011"
static char version[] __devinitdata =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -30,7 +30,7 @@ MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
"Eddie Wai <eddie.wai@broadcom.com>");
MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
- " iSCSI Driver");
+ "/57800/57810/57840 iSCSI Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -40,7 +40,7 @@ unsigned int event_coal_min = 24;
module_param(event_coal_min, int, 0664);
MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands");
-unsigned int event_coal_div = 1;
+unsigned int event_coal_div = 2;
module_param(event_coal_div, int, 0664);
MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor");
@@ -66,6 +66,15 @@ MODULE_PARM_DESC(rq_size, "Configure RQ size");
u64 iscsi_error_mask = 0x00;
+DEFINE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
+
+static int bnx2i_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu);
+/* notification function for CPU hotplug events */
+static struct notifier_block bnx2i_cpu_notifier = {
+ .notifier_call = bnx2i_cpu_callback,
+};
+
/**
* bnx2i_identify_device - identifies NetXtreme II device type
@@ -88,11 +97,20 @@ void bnx2i_identify_device(struct bnx2i_hba *hba)
(hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
- } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57712 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57712E)
+ } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57712 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57712E ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800_VF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810_VF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840_VF)
set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
else
printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
@@ -163,21 +181,14 @@ void bnx2i_start(void *handle)
struct bnx2i_hba *hba = handle;
int i = HZ;
- if (!hba->cnic->max_iscsi_conn) {
- printk(KERN_ALERT "bnx2i: dev %s does not support "
- "iSCSI\n", hba->netdev->name);
+ /*
+ * We should never register devices that don't support iSCSI
+ * (see bnx2i_init_one), so something is wrong if we try to
+ * start a iSCSI adapter on hardware with 0 supported iSCSI
+ * connections
+ */
+ BUG_ON(!hba->cnic->max_iscsi_conn);
- if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
- mutex_lock(&bnx2i_dev_lock);
- list_del_init(&hba->link);
- adapter_count--;
- hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
- clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
- mutex_unlock(&bnx2i_dev_lock);
- bnx2i_free_hba(hba);
- }
- return;
- }
bnx2i_send_fw_iscsi_init_msg(hba);
while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
msleep(BNX2I_INIT_POLL_TIME);
@@ -281,6 +292,13 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
int rc;
mutex_lock(&bnx2i_dev_lock);
+ if (!cnic->max_iscsi_conn) {
+ printk(KERN_ALERT "bnx2i: dev %s does not support "
+ "iSCSI\n", hba->netdev->name);
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
hba->cnic = cnic;
rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba);
if (!rc) {
@@ -298,6 +316,7 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
else
printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc);
+out:
mutex_unlock(&bnx2i_dev_lock);
return rc;
@@ -362,6 +381,91 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
/**
+ * bnx2i_percpu_thread_create - Create a receive thread for an
+ * online CPU
+ *
+ * @cpu: cpu index for the online cpu
+ */
+static void bnx2i_percpu_thread_create(unsigned int cpu)
+{
+ struct bnx2i_percpu_s *p;
+ struct task_struct *thread;
+
+ p = &per_cpu(bnx2i_percpu, cpu);
+
+ thread = kthread_create(bnx2i_percpu_io_thread, (void *)p,
+ "bnx2i_thread/%d", cpu);
+ /* bind thread to the cpu */
+ if (likely(!IS_ERR(thread))) {
+ kthread_bind(thread, cpu);
+ p->iothread = thread;
+ wake_up_process(thread);
+ }
+}
+
+
+static void bnx2i_percpu_thread_destroy(unsigned int cpu)
+{
+ struct bnx2i_percpu_s *p;
+ struct task_struct *thread;
+ struct bnx2i_work *work, *tmp;
+
+ /* Prevent any new work from being queued for this CPU */
+ p = &per_cpu(bnx2i_percpu, cpu);
+ spin_lock_bh(&p->p_work_lock);
+ thread = p->iothread;
+ p->iothread = NULL;
+
+ /* Free all work in the list */
+ list_for_each_entry_safe(work, tmp, &p->work_list, list) {
+ list_del_init(&work->list);
+ bnx2i_process_scsi_cmd_resp(work->session,
+ work->bnx2i_conn, &work->cqe);
+ kfree(work);
+ }
+
+ spin_unlock_bh(&p->p_work_lock);
+ if (thread)
+ kthread_stop(thread);
+}
+
+
+/**
+ * bnx2i_cpu_callback - Handler for CPU hotplug events
+ *
+ * @nfb: The callback data block
+ * @action: The event triggering the callback
+ * @hcpu: The index of the CPU that the event is for
+ *
+ * This creates or destroys per-CPU data for iSCSI
+ *
+ * Returns NOTIFY_OK always.
+ */
+static int bnx2i_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ printk(KERN_INFO "bnx2i: CPU %x online: Create Rx thread\n",
+ cpu);
+ bnx2i_percpu_thread_create(cpu);
+ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ printk(KERN_INFO "CPU %x offline: Remove Rx thread\n", cpu);
+ bnx2i_percpu_thread_destroy(cpu);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+
+/**
* bnx2i_mod_init - module init entry point
*
* initialize any driver wide global data structures such as endpoint pool,
@@ -371,6 +475,8 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
static int __init bnx2i_mod_init(void)
{
int err;
+ unsigned cpu = 0;
+ struct bnx2i_percpu_s *p;
printk(KERN_INFO "%s", version);
@@ -393,6 +499,20 @@ static int __init bnx2i_mod_init(void)
goto unreg_xport;
}
+ /* Create percpu kernel threads to handle iSCSI I/O completions */
+ for_each_possible_cpu(cpu) {
+ p = &per_cpu(bnx2i_percpu, cpu);
+ INIT_LIST_HEAD(&p->work_list);
+ spin_lock_init(&p->p_work_lock);
+ p->iothread = NULL;
+ }
+
+ for_each_online_cpu(cpu)
+ bnx2i_percpu_thread_create(cpu);
+
+ /* Initialize per CPU interrupt thread */
+ register_hotcpu_notifier(&bnx2i_cpu_notifier);
+
return 0;
unreg_xport:
@@ -413,6 +533,7 @@ out:
static void __exit bnx2i_mod_exit(void)
{
struct bnx2i_hba *hba;
+ unsigned cpu = 0;
mutex_lock(&bnx2i_dev_lock);
while (!list_empty(&adapter_list)) {
@@ -430,6 +551,11 @@ static void __exit bnx2i_mod_exit(void)
}
mutex_unlock(&bnx2i_dev_lock);
+ unregister_hotcpu_notifier(&bnx2i_cpu_notifier);
+
+ for_each_online_cpu(cpu)
+ bnx2i_percpu_thread_destroy(cpu);
+
iscsi_unregister_transport(&bnx2i_iscsi_transport);
cnic_unregister_driver(CNIC_ULP_ISCSI);
}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 041928b..d1e6971 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
/*
* bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -27,6 +27,7 @@ static struct scsi_host_template bnx2i_host_template;
*/
static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
static int bnx2i_adapter_ready(struct bnx2i_hba *hba)
{
@@ -1212,9 +1213,10 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
struct bnx2i_conn *bnx2i_conn = conn->dd_data;
struct scsi_cmnd *sc = task->sc;
struct bnx2i_cmd *cmd = task->dd_data;
- struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
+ struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
- if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes)
+ if (atomic_read(&bnx2i_conn->ep->num_active_cmds) + 1 >
+ hba->max_sqes)
return -ENOMEM;
/*
@@ -1354,6 +1356,9 @@ bnx2i_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
bnx2i_conn = conn->dd_data;
bnx2i_conn->cls_conn = cls_conn;
bnx2i_conn->hba = hba;
+
+ atomic_set(&bnx2i_conn->work_cnt, 0);
+
/* 'ep' ptr will be assigned in bind() call */
bnx2i_conn->ep = NULL;
init_completion(&bnx2i_conn->cmd_cleanup_cmpl);
@@ -1457,11 +1462,34 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
struct bnx2i_conn *bnx2i_conn = conn->dd_data;
struct Scsi_Host *shost;
struct bnx2i_hba *hba;
+ struct bnx2i_work *work, *tmp;
+ unsigned cpu = 0;
+ struct bnx2i_percpu_s *p;
shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn));
hba = iscsi_host_priv(shost);
bnx2i_conn_free_login_resources(hba, bnx2i_conn);
+
+ if (atomic_read(&bnx2i_conn->work_cnt)) {
+ for_each_online_cpu(cpu) {
+ p = &per_cpu(bnx2i_percpu, cpu);
+ spin_lock_bh(&p->p_work_lock);
+ list_for_each_entry_safe(work, tmp,
+ &p->work_list, list) {
+ if (work->session == conn->session &&
+ work->bnx2i_conn == bnx2i_conn) {
+ list_del_init(&work->list);
+ kfree(work);
+ if (!atomic_dec_and_test(
+ &bnx2i_conn->work_cnt))
+ break;
+ }
+ }
+ spin_unlock_bh(&p->p_work_lock);
+ }
+ }
+
iscsi_conn_teardown(cls_conn);
}
@@ -1769,7 +1797,7 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
}
bnx2i_ep = ep->dd_data;
- bnx2i_ep->num_active_cmds = 0;
+ atomic_set(&bnx2i_ep->num_active_cmds, 0);
iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
if (iscsi_cid == -1) {
printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
@@ -2149,6 +2177,59 @@ static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params)
return 0;
}
+static mode_t bnx2i_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
/*
* 'Scsi_Host_Template' structure and 'iscsi_tranport' structure template
@@ -2163,9 +2244,9 @@ static struct scsi_host_template bnx2i_host_template = {
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
.change_queue_depth = iscsi_change_queue_depth,
- .can_queue = 1024,
+ .can_queue = 2048,
.max_sectors = 127,
- .cmd_per_lun = 24,
+ .cmd_per_lun = 128,
.this_id = -1,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = ISCSI_MAX_BDS_PER_CMD,
@@ -2179,37 +2260,12 @@ struct iscsi_transport bnx2i_iscsi_transport = {
CAP_MULTI_R2T | CAP_DATADGST |
CAP_DATA_PATH_OFFLOAD |
CAP_TEXT_NEGO,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_ERL |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_NETDEV_NAME,
.create_session = bnx2i_session_create,
.destroy_session = bnx2i_session_destroy,
.create_conn = bnx2i_conn_create,
.bind_conn = bnx2i_conn_bind,
.destroy_conn = bnx2i_conn_destroy,
+ .attr_is_visible = bnx2i_attr_is_visible,
.set_param = iscsi_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_session_param = iscsi_session_get_param,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 9174196..83a77f7 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,6 +1,6 @@
/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2004 - 2010 Broadcom Corporation
+ * Copyright (c) 2004 - 2011 Broadcom Corporation
*
* 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
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild
index 09dbf9e..6f095e2 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb3
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
index 11dff23..6bbc36f 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -2,7 +2,8 @@ config SCSI_CXGB3_ISCSI
tristate "Chelsio T3 iSCSI support"
depends on PCI && INET
select NETDEVICES
- select NETDEV_10000
+ select ETHERNET
+ select NET_VENDOR_CHELSIO
select CHELSIO_T3
select SCSI_ISCSI_ATTRS
---help---
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index 143f268..000294a 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -14,7 +14,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <scsi/scsi_host.h>
@@ -106,25 +105,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
- .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
- ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME |
- ISCSI_HOST_NETDEV_NAME,
+ .attr_is_visible = cxgbi_attr_is_visible,
.get_host_param = cxgbi_get_host_param,
.set_host_param = cxgbi_set_host_param,
/* session management */
@@ -1245,7 +1226,7 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi;
struct ulp_iscsi_info uinfo;
unsigned int pgsz_factor[4];
- int err;
+ int i, err;
if (ddp) {
kref_get(&ddp->refcnt);
@@ -1271,6 +1252,8 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
cxgbi_ddp_page_size_factor(pgsz_factor);
+ for (i = 0; i < 4; i++)
+ uinfo.pgsz_factor[i] = pgsz_factor[i];
uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT);
err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild
index b9f4af7..8290cda 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
index d5302c2..16b2c7d 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -2,7 +2,8 @@ config SCSI_CXGB4_ISCSI
tristate "Chelsio T4 iSCSI support"
depends on PCI && INET
select NETDEVICES
- select NETDEV_10000
+ select ETHERNET
+ select NET_VENDOR_CHELSIO
select CHELSIO_T4
select SCSI_ISCSI_ATTRS
---help---
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index ae13c49..ac7a9b1 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -13,7 +13,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <scsi/scsi_host.h>
@@ -107,25 +106,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
CAP_DATADGST | CAP_DIGEST_OFFLOAD |
CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
- .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
- ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME |
- ISCSI_HOST_NETDEV_NAME,
+ .attr_is_visible = cxgbi_attr_is_visible,
.get_host_param = cxgbi_get_host_param,
.set_host_param = cxgbi_set_host_param,
/* session management */
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index 77ac217..c10f74a 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -25,6 +25,7 @@
#include <net/dst.h>
#include <net/route.h>
#include <linux/inetdevice.h> /* ip_dev_find */
+#include <linux/module.h>
#include <net/tcp.h>
static unsigned int dbg_level;
@@ -1787,7 +1788,7 @@ static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
}
static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
- unsigned int dlen, skb_frag_t *frags,
+ unsigned int dlen, struct page_frag *frags,
int frag_max)
{
unsigned int datalen = dlen;
@@ -1814,7 +1815,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
copy = min(datalen, sglen);
if (i && page == frags[i - 1].page &&
sgoffset + sg->offset ==
- frags[i - 1].page_offset + frags[i - 1].size) {
+ frags[i - 1].offset + frags[i - 1].size) {
frags[i - 1].size += copy;
} else {
if (i >= frag_max) {
@@ -1824,7 +1825,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
}
frags[i].page = page;
- frags[i].page_offset = sg->offset + sgoffset;
+ frags[i].offset = sg->offset + sgoffset;
frags[i].size = copy;
i++;
}
@@ -1944,14 +1945,14 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
if (tdata->nr_frags > MAX_SKB_FRAGS ||
(padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
char *dst = skb->data + task->hdr_len;
- skb_frag_t *frag = tdata->frags;
+ struct page_frag *frag = tdata->frags;
/* data fits in the skb's headroom */
for (i = 0; i < tdata->nr_frags; i++, frag++) {
char *src = kmap_atomic(frag->page,
KM_SOFTIRQ0);
- memcpy(dst, src+frag->page_offset, frag->size);
+ memcpy(dst, src+frag->offset, frag->size);
dst += frag->size;
kunmap_atomic(src, KM_SOFTIRQ0);
}
@@ -1962,11 +1963,13 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
skb_put(skb, count + padlen);
} else {
/* data fit into frag_list */
- for (i = 0; i < tdata->nr_frags; i++)
- get_page(tdata->frags[i].page);
-
- memcpy(skb_shinfo(skb)->frags, tdata->frags,
- sizeof(skb_frag_t) * tdata->nr_frags);
+ for (i = 0; i < tdata->nr_frags; i++) {
+ __skb_fill_page_desc(skb, i,
+ tdata->frags[i].page,
+ tdata->frags[i].offset,
+ tdata->frags[i].size);
+ skb_frag_ref(skb, i);
+ }
skb_shinfo(skb)->nr_frags = tdata->nr_frags;
skb->len += count;
skb->data_len += count;
@@ -2566,6 +2569,62 @@ void cxgbi_iscsi_cleanup(struct iscsi_transport *itp,
}
EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+mode_t cxgbi_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible);
+
static int __init libcxgbi_init_module(void)
{
sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 9267844..20c88279 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -574,7 +574,7 @@ struct cxgbi_endpoint {
#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
struct cxgbi_task_data {
unsigned short nr_frags;
- skb_frag_t frags[MAX_PDU_FRAGS];
+ struct page_frag frags[MAX_PDU_FRAGS];
struct sk_buff *skb;
unsigned int offset;
unsigned int count;
@@ -709,6 +709,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *);
void cxgbi_cleanup_task(struct iscsi_task *task);
+mode_t cxgbi_attr_is_visible(int param_type, int param);
void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
int cxgbi_set_conn_param(struct iscsi_cls_conn *,
enum iscsi_param, char *, int);
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index d973325..23149b9 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -22,6 +22,7 @@
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include <scsi/scsi_dh.h>
#include "../scsi_priv.h"
@@ -60,6 +61,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx)
}
/*
+ * device_handler_match_function - Match a device handler to a device
+ * @sdev - SCSI device to be tested
+ *
+ * Tests @sdev against the match function of all registered device_handler.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match_function(struct scsi_device *sdev)
+{
+ struct scsi_device_handler *tmp_dh, *found_dh = NULL;
+
+ spin_lock(&list_lock);
+ list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
+ if (tmp_dh->match && tmp_dh->match(sdev)) {
+ found_dh = tmp_dh;
+ break;
+ }
+ }
+ spin_unlock(&list_lock);
+ return found_dh;
+}
+
+/*
+ * device_handler_match_devlist - Match a device handler to a device
+ * @sdev - SCSI device to be tested
+ *
+ * Tests @sdev against all device_handler registered in the devlist.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match_devlist(struct scsi_device *sdev)
+{
+ int idx;
+
+ idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
+ SCSI_DEVINFO_DH);
+ return get_device_handler_by_idx(idx);
+}
+
+/*
* device_handler_match - Attach a device handler to a device
* @scsi_dh - The device handler to match against or NULL
* @sdev - SCSI device to be tested against @scsi_dh
@@ -72,12 +113,11 @@ static struct scsi_device_handler *
device_handler_match(struct scsi_device_handler *scsi_dh,
struct scsi_device *sdev)
{
- struct scsi_device_handler *found_dh = NULL;
- int idx;
+ struct scsi_device_handler *found_dh;
- idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
- SCSI_DEVINFO_DH);
- found_dh = get_device_handler_by_idx(idx);
+ found_dh = device_handler_match_function(sdev);
+ if (!found_dh)
+ found_dh = device_handler_match_devlist(sdev);
if (scsi_dh && found_dh != scsi_dh)
found_dh = NULL;
@@ -151,6 +191,10 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
struct scsi_device_handler *scsi_dh;
int err = -EINVAL;
+ if (sdev->sdev_state == SDEV_CANCEL ||
+ sdev->sdev_state == SDEV_DEL)
+ return -ENODEV;
+
if (!sdev->scsi_dh_data) {
/*
* Attach to a device handler
@@ -327,7 +371,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
list_add(&scsi_dh->list, &scsi_dh_list);
spin_unlock(&list_lock);
- for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+ for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
scsi_dev_info_list_add_keyed(0,
scsi_dh->devlist[i].vendor,
scsi_dh->devlist[i].model,
@@ -360,7 +404,7 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
scsi_dh_notifier_remove);
- for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+ for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
scsi_dh->devlist[i].model,
SCSI_DEVINFO_DH);
@@ -476,7 +520,7 @@ int scsi_dh_handler_exist(const char *name)
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
/*
- * scsi_dh_handler_attach - Attach device handler
+ * scsi_dh_attach - Attach device handler
* @sdev - sdev the handler should be attached to
* @name - name of the handler to attach
*/
@@ -506,7 +550,7 @@ int scsi_dh_attach(struct request_queue *q, const char *name)
EXPORT_SYMBOL_GPL(scsi_dh_attach);
/*
- * scsi_dh_handler_detach - Detach device handler
+ * scsi_dh_detach - Detach device handler
* @sdev - sdev the handler should be detached from
*
* This function will detach the device handler only
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 5391e6a..e5a4423 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -21,6 +21,7 @@
*/
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_dh.h>
@@ -128,43 +129,6 @@ static struct request *get_alua_req(struct scsi_device *sdev,
}
/*
- * submit_std_inquiry - Issue a standard INQUIRY command
- * @sdev: sdev the command should be send to
- */
-static int submit_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
-{
- struct request *rq;
- int err = SCSI_DH_RES_TEMP_UNAVAIL;
-
- rq = get_alua_req(sdev, h->inq, ALUA_INQUIRY_SIZE, READ);
- if (!rq)
- goto done;
-
- /* Prepare the command. */
- rq->cmd[0] = INQUIRY;
- rq->cmd[1] = 0;
- rq->cmd[2] = 0;
- rq->cmd[4] = ALUA_INQUIRY_SIZE;
- rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
- rq->sense = h->sense;
- memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
- rq->sense_len = h->senselen = 0;
-
- err = blk_execute_rq(rq->q, NULL, rq, 1);
- if (err == -EIO) {
- sdev_printk(KERN_INFO, sdev,
- "%s: std inquiry failed with %x\n",
- ALUA_DH_NAME, rq->errors);
- h->senselen = rq->sense_len;
- err = SCSI_DH_IO;
- }
- blk_put_request(rq);
-done:
- return err;
-}
-
-/*
* submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
* @sdev: sdev the command should be sent to
*/
@@ -338,23 +302,17 @@ static unsigned submit_stpg(struct alua_dh_data *h)
}
/*
- * alua_std_inquiry - Evaluate standard INQUIRY command
+ * alua_check_tpgs - Evaluate TPGS setting
* @sdev: device to be checked
*
- * Just extract the TPGS setting to find out if ALUA
+ * Examine the TPGS setting of the sdev to find out if ALUA
* is supported.
*/
-static int alua_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h)
{
- int err;
-
- err = submit_std_inquiry(sdev, h);
-
- if (err != SCSI_DH_OK)
- return err;
+ int err = SCSI_DH_OK;
- /* Check TPGS setting */
- h->tpgs = (h->inq[5] >> 4) & 0x3;
+ h->tpgs = scsi_device_tpgs(sdev);
switch (h->tpgs) {
case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
sdev_printk(KERN_INFO, sdev,
@@ -508,27 +466,28 @@ static int alua_check_sense(struct scsi_device *sdev,
* Power On, Reset, or Bus Device Reset, just retry.
*/
return ADD_TO_MLQUEUE;
- if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
+ if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
/*
* ALUA state changed
*/
return ADD_TO_MLQUEUE;
- }
- if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
+ if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07)
/*
* Implicit ALUA state transition failed
*/
return ADD_TO_MLQUEUE;
- }
- if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e) {
+ if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x03)
+ /*
+ * Inquiry data has changed
+ */
+ return ADD_TO_MLQUEUE;
+ if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e)
/*
* REPORTED_LUNS_DATA_HAS_CHANGED is reported
* when switching controllers on targets like
* Intel Multi-Flex. We can just retry.
*/
return ADD_TO_MLQUEUE;
- }
-
break;
}
@@ -547,9 +506,9 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0;
- char *ucp;
+ unsigned char *ucp;
unsigned err;
- unsigned long expiry, interval = 10;
+ unsigned long expiry, interval = 1000;
expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
retry:
@@ -610,7 +569,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
case TPGS_STATE_TRANSITIONING:
if (time_before(jiffies, expiry)) {
/* State transition, retry */
- interval *= 10;
+ interval *= 2;
msleep(interval);
goto retry;
}
@@ -641,7 +600,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
{
int err;
- err = alua_std_inquiry(sdev, h);
+ err = alua_check_tpgs(sdev, h);
if (err != SCSI_DH_OK)
goto out;
@@ -673,11 +632,9 @@ static int alua_activate(struct scsi_device *sdev,
struct alua_dh_data *h = get_alua_data(sdev);
int err = SCSI_DH_OK;
- if (h->group_id != -1) {
- err = alua_rtpg(sdev, h);
- if (err != SCSI_DH_OK)
- goto out;
- }
+ err = alua_rtpg(sdev, h);
+ if (err != SCSI_DH_OK)
+ goto out;
if (h->tpgs & TPGS_MODE_EXPLICIT &&
h->state != TPGS_STATE_OPTIMIZED &&
@@ -719,23 +676,10 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
}
-static const struct scsi_dh_devlist alua_dev_list[] = {
- {"HP", "MSA VOLUME" },
- {"HP", "HSV101" },
- {"HP", "HSV111" },
- {"HP", "HSV200" },
- {"HP", "HSV210" },
- {"HP", "HSV300" },
- {"IBM", "2107900" },
- {"IBM", "2145" },
- {"Pillar", "Axiom" },
- {"Intel", "Multi-Flex"},
- {"NETAPP", "LUN"},
- {"NETAPP", "LUN C-Mode"},
- {"AIX", "NVDISK"},
- {"Promise", "VTrak"},
- {NULL, NULL}
-};
+static bool alua_match(struct scsi_device *sdev)
+{
+ return (scsi_device_tpgs(sdev) != 0);
+}
static int alua_bus_attach(struct scsi_device *sdev);
static void alua_bus_detach(struct scsi_device *sdev);
@@ -743,12 +687,12 @@ static void alua_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler alua_dh = {
.name = ALUA_DH_NAME,
.module = THIS_MODULE,
- .devlist = alua_dev_list,
.attach = alua_bus_attach,
.detach = alua_bus_detach,
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
+ .match = alua_match,
};
/*
@@ -790,6 +734,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+ sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME);
return 0;
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index 48441f6..591186c 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -21,6 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_dh.h>
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index b479f1e..0f86a18 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -22,6 +22,7 @@
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_eh.h>
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index e7fc70d..1d31279 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -1,5 +1,5 @@
/*
- * Engenio/LSI RDAC SCSI Device Handler
+ * LSI/Engenio/NetApp E-Series RDAC SCSI Device Handler
*
* Copyright (C) 2005 Mike Christie. All rights reserved.
* Copyright (C) Chandra Seetharaman, IBM Corp. 2007
@@ -24,6 +24,7 @@
#include <scsi/scsi_dh.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
+#include <linux/module.h>
#define RDAC_NAME "rdac"
#define RDAC_RETRY_COUNT 5
@@ -35,7 +36,7 @@
* mode page were taken from the LSI RDAC 2.4 GPL'd
* driver, and then converted to Linux conventions.
*/
-#define RDAC_QUIESCENCE_TIME 20;
+#define RDAC_QUIESCENCE_TIME 20
/*
* Page Codes
*/
@@ -128,25 +129,7 @@ struct c4_inquiry {
u8 reserved[2];
};
-struct rdac_controller {
- u8 subsys_id[SUBSYS_ID_LEN];
- u8 slot_id[SLOT_ID_LEN];
- int use_ms10;
- struct kref kref;
- struct list_head node; /* list of all controllers */
- union {
- struct rdac_pg_legacy legacy;
- struct rdac_pg_expanded expanded;
- } mode_select;
- u8 index;
- u8 array_name[ARRAY_LABEL_LEN];
- spinlock_t ms_lock;
- int ms_queued;
- struct work_struct ms_work;
- struct scsi_device *ms_sdev;
- struct list_head ms_head;
-};
-
+#define UNIQUE_ID_LEN 16
struct c8_inquiry {
u8 peripheral_info;
u8 page_code; /* 0xC8 */
@@ -159,12 +142,31 @@ struct c8_inquiry {
u8 vol_user_label_len;
u8 vol_user_label[60];
u8 array_uniq_id_len;
- u8 array_unique_id[16];
+ u8 array_unique_id[UNIQUE_ID_LEN];
u8 array_user_label_len;
u8 array_user_label[60];
u8 lun[8];
};
+struct rdac_controller {
+ u8 array_id[UNIQUE_ID_LEN];
+ int use_ms10;
+ struct kref kref;
+ struct list_head node; /* list of all controllers */
+ union {
+ struct rdac_pg_legacy legacy;
+ struct rdac_pg_expanded expanded;
+ } mode_select;
+ u8 index;
+ u8 array_name[ARRAY_LABEL_LEN];
+ struct Scsi_Host *host;
+ spinlock_t ms_lock;
+ int ms_queued;
+ struct work_struct ms_work;
+ struct scsi_device *ms_sdev;
+ struct list_head ms_head;
+};
+
struct c2_inquiry {
u8 peripheral_info;
u8 page_code; /* 0xC2 */
@@ -369,16 +371,17 @@ static void release_controller(struct kref *kref)
kfree(ctlr);
}
-static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id,
- char *array_name)
+static struct rdac_controller *get_controller(int index, char *array_name,
+ u8 *array_id, struct scsi_device *sdev)
{
struct rdac_controller *ctlr, *tmp;
spin_lock(&list_lock);
list_for_each_entry(tmp, &ctlr_list, node) {
- if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) &&
- (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) {
+ if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) &&
+ (tmp->index == index) &&
+ (tmp->host == sdev->host)) {
kref_get(&tmp->kref);
spin_unlock(&list_lock);
return tmp;
@@ -389,16 +392,11 @@ static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id,
goto done;
/* initialize fields of controller */
- memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN);
- memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN);
+ memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN);
+ ctlr->index = index;
+ ctlr->host = sdev->host;
memcpy(ctlr->array_name, array_name, ARRAY_LABEL_LEN);
- /* update the controller index */
- if (slot_id[1] == 0x31)
- ctlr->index = 0;
- else
- ctlr->index = 1;
-
kref_init(&ctlr->kref);
ctlr->use_ms10 = -1;
ctlr->ms_queued = 0;
@@ -444,7 +442,7 @@ done:
}
static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h,
- char *array_name)
+ char *array_name, u8 *array_id)
{
int err, i;
struct c8_inquiry *inqp;
@@ -463,6 +461,8 @@ static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h,
*(array_name+i) = inqp->array_user_label[(2*i)+1];
*(array_name+ARRAY_LABEL_LEN-1) = '\0';
+ memset(array_id, 0, UNIQUE_ID_LEN);
+ memcpy(array_id, inqp->array_unique_id, inqp->array_uniq_id_len);
}
return err;
}
@@ -504,16 +504,20 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
}
static int initialize_controller(struct scsi_device *sdev,
- struct rdac_dh_data *h, char *array_name)
+ struct rdac_dh_data *h, char *array_name, u8 *array_id)
{
- int err;
+ int err, index;
struct c4_inquiry *inqp;
err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c4;
- h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id,
- array_name);
+ /* get the controller index */
+ if (inqp->slot_id[1] == 0x31)
+ index = 0;
+ else
+ index = 1;
+ h->ctlr = get_controller(index, array_name, array_id, sdev);
if (!h->ctlr)
err = SCSI_DH_RES_TEMP_UNAVAIL;
}
@@ -792,6 +796,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
{"IBM", "3526"},
{"SGI", "TP9400"},
{"SGI", "TP9500"},
+ {"SGI", "TP9700"},
{"SGI", "IS"},
{"STK", "OPENstorage D280"},
{"SUN", "CSM200_R"},
@@ -811,6 +816,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
{"SUN", "CSM100_R_FC"},
{"SUN", "STK6580_6780"},
{"SUN", "SUN_6180"},
+ {"SUN", "ArrayStorage"},
{NULL, NULL},
};
@@ -835,6 +841,7 @@ static int rdac_bus_attach(struct scsi_device *sdev)
unsigned long flags;
int err;
char array_name[ARRAY_LABEL_LEN];
+ char array_id[UNIQUE_ID_LEN];
scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
+ sizeof(*h) , GFP_KERNEL);
@@ -849,11 +856,11 @@ static int rdac_bus_attach(struct scsi_device *sdev)
h->lun = UNINITIALIZED_LUN;
h->state = RDAC_STATE_ACTIVE;
- err = get_lun_info(sdev, h, array_name);
+ err = get_lun_info(sdev, h, array_name, array_id);
if (err != SCSI_DH_OK)
goto failed;
- err = initialize_controller(sdev, h, array_name);
+ err = initialize_controller(sdev, h, array_name, array_id);
if (err != SCSI_DH_OK)
goto failed;
@@ -941,7 +948,7 @@ static void __exit rdac_exit(void)
module_init(rdac_init);
module_exit(rdac_exit);
-MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver");
+MODULE_DESCRIPTION("Multipath LSI/Engenio/NetApp E-Series RDAC driver");
MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
MODULE_VERSION("01.00.0000.0000");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index 179ad77..bd9e31e 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -22,7 +22,7 @@
#include <linux/i2o-dev.h>
#include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/*
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index f829adc..8d67467 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -18,7 +18,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -32,6 +31,8 @@
#include <linux/sysfs.h>
#include <linux/ctype.h>
#include <linux/workqueue.h>
+#include <net/dcbnl.h>
+#include <net/dcbevent.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
#include <scsi/scsi_transport.h>
@@ -52,7 +53,7 @@ MODULE_DESCRIPTION("FCoE");
MODULE_LICENSE("GPL v2");
/* Performance tuning parameters for fcoe */
-static unsigned int fcoe_ddp_min;
+static unsigned int fcoe_ddp_min = 4096;
module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \
"Direct Data Placement (DDP).");
@@ -99,8 +100,11 @@ static void fcoe_destroy_work(struct work_struct *);
static int fcoe_ddp_setup(struct fc_lport *, u16, struct scatterlist *,
unsigned int);
static int fcoe_ddp_done(struct fc_lport *, u16);
-
+static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *,
+ unsigned int);
static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
+static int fcoe_dcb_app_notification(struct notifier_block *notifier,
+ ulong event, void *ptr);
static bool fcoe_match(struct net_device *netdev);
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode);
@@ -129,6 +133,11 @@ static struct notifier_block fcoe_cpu_notifier = {
.notifier_call = fcoe_cpu_callback,
};
+/* notification function for DCB events */
+static struct notifier_block dcb_notifier = {
+ .notifier_call = fcoe_dcb_app_notification,
+};
+
static struct scsi_transport_template *fcoe_nport_scsi_transport;
static struct scsi_transport_template *fcoe_vport_scsi_transport;
@@ -137,12 +146,12 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled);
static int fcoe_vport_disable(struct fc_vport *, bool disable);
static void fcoe_set_vport_symbolic_name(struct fc_vport *);
static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
-static int fcoe_validate_vport_create(struct fc_vport *);
static struct libfc_function_template fcoe_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
.ddp_setup = fcoe_ddp_setup,
.ddp_done = fcoe_ddp_done,
+ .ddp_target = fcoe_ddp_target,
.elsct_send = fcoe_elsct_send,
.get_lesb = fcoe_get_lesb,
.lport_set_port_id = fcoe_set_port_id,
@@ -279,6 +288,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
* use the first one for SPMA */
real_dev = (netdev->priv_flags & IFF_802_1Q_VLAN) ?
vlan_dev_real_dev(netdev) : netdev;
+ fcoe->realdev = real_dev;
rcu_read_lock();
for_each_dev_addr(real_dev, ha) {
if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
@@ -429,21 +439,8 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
struct fcoe_ctlr *fip = &fcoe->ctlr;
u8 flogi_maddr[ETH_ALEN];
const struct net_device_ops *ops;
- struct fcoe_port *port = lport_priv(fcoe->ctlr.lp);
-
- FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
-
- /* Logout of the fabric */
- fc_fabric_logoff(fcoe->ctlr.lp);
-
- /* Cleanup the fc_lport */
- fc_lport_destroy(fcoe->ctlr.lp);
-
- /* Stop the transmit retry timer */
- del_timer_sync(&port->timer);
- /* Free existing transmit skbs */
- fcoe_clean_pending_queue(fcoe->ctlr.lp);
+ rtnl_lock();
/*
* Don't listen for Ethernet packets anymore.
@@ -466,9 +463,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
} else
dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
- if (!is_zero_ether_addr(port->data_src_addr))
- dev_uc_del(netdev, port->data_src_addr);
-
/* Tell the LLD we are done w/ FCoE */
ops = netdev->netdev_ops;
if (ops->ndo_fcoe_disable) {
@@ -476,6 +470,10 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
" specific feature for LLD.\n");
}
+
+ rtnl_unlock();
+
+ /* Release the self-reference taken during fcoe_interface_create() */
fcoe_interface_put(fcoe);
}
@@ -501,6 +499,19 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev,
}
/**
+ * fcoe_port_send() - Send an Ethernet-encapsulated FIP/FCoE frame
+ * @port: The FCoE port
+ * @skb: The FIP/FCoE packet to be sent
+ */
+static void fcoe_port_send(struct fcoe_port *port, struct sk_buff *skb)
+{
+ if (port->fcoe_pending_queue.qlen)
+ fcoe_check_wait_queue(port->lport, skb);
+ else if (fcoe_start_io(skb))
+ fcoe_check_wait_queue(port->lport, skb);
+}
+
+/**
* fcoe_fip_send() - Send an Ethernet-encapsulated FIP frame
* @fip: The FCoE controller
* @skb: The FIP packet to be sent
@@ -508,7 +519,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev,
static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
skb->dev = fcoe_from_ctlr(fip)->netdev;
- dev_queue_xmit(skb);
+ fcoe_port_send(lport_priv(fip->lp), skb);
}
/**
@@ -578,23 +589,6 @@ static int fcoe_lport_config(struct fc_lport *lport)
}
/**
- * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
- * @netdev: the associated net device
- * @wwn: the output WWN
- * @type: the type of WWN (WWPN or WWNN)
- *
- * Returns: 0 for success
- */
-static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
-{
- const struct net_device_ops *ops = netdev->netdev_ops;
-
- if (ops->ndo_fcoe_get_wwn)
- return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
- return -EINVAL;
-}
-
-/**
* fcoe_netdev_features_change - Updates the lport's offload flags based
* on the LLD netdev's FCoE feature flags
*/
@@ -859,6 +853,32 @@ skip_oem:
*/
static void fcoe_if_destroy(struct fc_lport *lport)
{
+ struct fcoe_port *port = lport_priv(lport);
+ struct fcoe_interface *fcoe = port->priv;
+ struct net_device *netdev = fcoe->netdev;
+
+ FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
+
+ /* Logout of the fabric */
+ fc_fabric_logoff(lport);
+
+ /* Cleanup the fc_lport */
+ fc_lport_destroy(lport);
+
+ /* Stop the transmit retry timer */
+ del_timer_sync(&port->timer);
+
+ /* Free existing transmit skbs */
+ fcoe_clean_pending_queue(lport);
+
+ rtnl_lock();
+ if (!is_zero_ether_addr(port->data_src_addr))
+ dev_uc_del(netdev, port->data_src_addr);
+ rtnl_unlock();
+
+ /* Release reference held in fcoe_if_create() */
+ fcoe_interface_put(fcoe);
+
/* Free queued packets for the per-CPU receive threads */
fcoe_percpu_clean(lport);
@@ -902,6 +922,28 @@ static int fcoe_ddp_setup(struct fc_lport *lport, u16 xid,
}
/**
+ * fcoe_ddp_target() - Call a LLD's ddp_target through the net device
+ * @lport: The local port to setup DDP for
+ * @xid: The exchange ID for this DDP transfer
+ * @sgl: The scatterlist describing this transfer
+ * @sgc: The number of sg items
+ *
+ * Returns: 0 if the DDP context was not configured
+ */
+static int fcoe_ddp_target(struct fc_lport *lport, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ struct net_device *netdev = fcoe_netdev(lport);
+
+ if (netdev->netdev_ops->ndo_fcoe_ddp_target)
+ return netdev->netdev_ops->ndo_fcoe_ddp_target(netdev, xid,
+ sgl, sgc);
+
+ return 0;
+}
+
+
+/**
* fcoe_ddp_done() - Call a LLD's ddp_done through the net device
* @lport: The local port to complete DDP on
* @xid: The exchange ID for this DDP transfer
@@ -1084,8 +1126,9 @@ static void fcoe_percpu_thread_create(unsigned int cpu)
p = &per_cpu(fcoe_percpu, cpu);
- thread = kthread_create(fcoe_percpu_receive_thread,
- (void *)p, "fcoethread/%d", cpu);
+ thread = kthread_create_on_node(fcoe_percpu_receive_thread,
+ (void *)p, cpu_to_node(cpu),
+ "fcoethread/%d", cpu);
if (likely(!IS_ERR(thread))) {
kthread_bind(thread, cpu);
@@ -1221,6 +1264,26 @@ static int fcoe_cpu_callback(struct notifier_block *nfb,
}
/**
+ * fcoe_select_cpu() - Selects CPU to handle post-processing of incoming
+ * command.
+ *
+ * This routine selects next CPU based on cpumask to distribute
+ * incoming requests in round robin.
+ *
+ * Returns: int CPU number
+ */
+static inline unsigned int fcoe_select_cpu(void)
+{
+ static unsigned int selected_cpu;
+
+ selected_cpu = cpumask_next(selected_cpu, cpu_online_mask);
+ if (selected_cpu >= nr_cpu_ids)
+ selected_cpu = cpumask_first(cpu_online_mask);
+
+ return selected_cpu;
+}
+
+/**
* fcoe_rcv() - Receive packets from a net device
* @skb: The received packet
* @netdev: The net device that the packet was received on
@@ -1286,18 +1349,25 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
fr = fcoe_dev_from_skb(skb);
fr->fr_dev = lport;
- fr->ptype = ptype;
/*
* In case the incoming frame's exchange is originated from
* the initiator, then received frame's exchange id is ANDed
* with fc_cpu_mask bits to get the same cpu on which exchange
- * was originated, otherwise just use the current cpu.
+ * was originated, otherwise select cpu using rx exchange id
+ * or fcoe_select_cpu().
*/
if (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)
cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask;
- else
- cpu = smp_processor_id();
+ else {
+ if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)
+ cpu = fcoe_select_cpu();
+ else
+ cpu = ntohs(fh->fh_rx_id) & fc_cpu_mask;
+ }
+
+ if (cpu >= nr_cpu_ids)
+ goto err;
fps = &per_cpu(fcoe_percpu, cpu);
spin_lock_bh(&fps->fcoe_rx_list.lock);
@@ -1440,7 +1510,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
return -ENOMEM;
}
frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
- cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+ cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
+ frag->page_offset;
} else {
cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -1461,7 +1531,15 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
skb_reset_network_header(skb);
skb->mac_len = elen;
skb->protocol = htons(ETH_P_FCOE);
- skb->dev = fcoe->netdev;
+ skb->priority = port->priority;
+
+ if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN &&
+ fcoe->realdev->features & NETIF_F_HW_VLAN_TX) {
+ skb->vlan_tci = VLAN_TAG_PRESENT |
+ vlan_dev_vlan_id(fcoe->netdev);
+ skb->dev = fcoe->realdev;
+ } else
+ skb->dev = fcoe->netdev;
/* fill up mac and fcoe headers */
eh = eth_hdr(skb);
@@ -1497,11 +1575,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
/* send down to lld */
fr_dev(fp) = lport;
- if (port->fcoe_pending_queue.qlen)
- fcoe_check_wait_queue(lport, skb);
- else if (fcoe_start_io(skb))
- fcoe_check_wait_queue(lport, skb);
-
+ fcoe_port_send(port, skb);
return 0;
}
@@ -1684,6 +1758,7 @@ int fcoe_percpu_receive_thread(void *arg)
*/
static void fcoe_dev_setup(void)
{
+ register_dcbevent_notifier(&dcb_notifier);
register_netdevice_notifier(&fcoe_notifier);
}
@@ -1692,9 +1767,69 @@ static void fcoe_dev_setup(void)
*/
static void fcoe_dev_cleanup(void)
{
+ unregister_dcbevent_notifier(&dcb_notifier);
unregister_netdevice_notifier(&fcoe_notifier);
}
+static struct fcoe_interface *
+fcoe_hostlist_lookup_realdev_port(struct net_device *netdev)
+{
+ struct fcoe_interface *fcoe;
+ struct net_device *real_dev;
+
+ list_for_each_entry(fcoe, &fcoe_hostlist, list) {
+ if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
+ real_dev = vlan_dev_real_dev(fcoe->netdev);
+ else
+ real_dev = fcoe->netdev;
+
+ if (netdev == real_dev)
+ return fcoe;
+ }
+ return NULL;
+}
+
+static int fcoe_dcb_app_notification(struct notifier_block *notifier,
+ ulong event, void *ptr)
+{
+ struct dcb_app_type *entry = ptr;
+ struct fcoe_interface *fcoe;
+ struct net_device *netdev;
+ struct fcoe_port *port;
+ int prio;
+
+ if (entry->app.selector != DCB_APP_IDTYPE_ETHTYPE)
+ return NOTIFY_OK;
+
+ netdev = dev_get_by_index(&init_net, entry->ifindex);
+ if (!netdev)
+ return NOTIFY_OK;
+
+ fcoe = fcoe_hostlist_lookup_realdev_port(netdev);
+ dev_put(netdev);
+ if (!fcoe)
+ return NOTIFY_OK;
+
+ if (entry->dcbx & DCB_CAP_DCBX_VER_CEE)
+ prio = ffs(entry->app.priority) - 1;
+ else
+ prio = entry->app.priority;
+
+ if (prio < 0)
+ return NOTIFY_OK;
+
+ if (entry->app.protocol == ETH_P_FIP ||
+ entry->app.protocol == ETH_P_FCOE)
+ fcoe->ctlr.priority = prio;
+
+ if (entry->app.protocol == ETH_P_FCOE) {
+ port = lport_priv(fcoe->ctlr.lp);
+ port->priority = prio;
+ }
+
+ return NOTIFY_OK;
+}
+
/**
* fcoe_device_notification() - Handler for net device events
* @notifier: The context of the notification
@@ -1749,7 +1884,6 @@ static int fcoe_device_notification(struct notifier_block *notifier,
case NETDEV_UNREGISTER:
list_del(&fcoe->list);
port = lport_priv(fcoe->ctlr.lp);
- fcoe_interface_cleanup(fcoe);
queue_work(fcoe_wq, &port->destroy_work);
goto out;
break;
@@ -1843,22 +1977,22 @@ static int fcoe_destroy(struct net_device *netdev)
{
struct fcoe_interface *fcoe;
struct fc_lport *lport;
+ struct fcoe_port *port;
int rc = 0;
mutex_lock(&fcoe_config_mutex);
rtnl_lock();
fcoe = fcoe_hostlist_lookup_port(netdev);
if (!fcoe) {
- rtnl_unlock();
rc = -ENODEV;
goto out_nodev;
}
lport = fcoe->ctlr.lp;
+ port = lport_priv(lport);
list_del(&fcoe->list);
- fcoe_interface_cleanup(fcoe);
- rtnl_unlock();
- fcoe_if_destroy(lport);
+ queue_work(fcoe_wq, &port->destroy_work);
out_nodev:
+ rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
return rc;
}
@@ -1870,10 +2004,22 @@ out_nodev:
static void fcoe_destroy_work(struct work_struct *work)
{
struct fcoe_port *port;
+ struct fcoe_interface *fcoe;
+ int npiv = 0;
port = container_of(work, struct fcoe_port, destroy_work);
mutex_lock(&fcoe_config_mutex);
+
+ /* set if this is an NPIV port */
+ npiv = port->lport->vport ? 1 : 0;
+
+ fcoe = port->priv;
fcoe_if_destroy(port->lport);
+
+ /* Do not tear down the fcoe interface for NPIV port */
+ if (!npiv)
+ fcoe_interface_cleanup(fcoe);
+
mutex_unlock(&fcoe_config_mutex);
}
@@ -1892,6 +2038,46 @@ static bool fcoe_match(struct net_device *netdev)
}
/**
+ * fcoe_dcb_create() - Initialize DCB attributes and hooks
+ * @netdev: The net_device object of the L2 link that should be queried
+ * @port: The fcoe_port to bind FCoE APP priority with
+ * @
+ */
+static void fcoe_dcb_create(struct fcoe_interface *fcoe)
+{
+#ifdef CONFIG_DCB
+ int dcbx;
+ u8 fup, up;
+ struct net_device *netdev = fcoe->realdev;
+ struct fcoe_port *port = lport_priv(fcoe->ctlr.lp);
+ struct dcb_app app = {
+ .priority = 0,
+ .protocol = ETH_P_FCOE
+ };
+
+ /* setup DCB priority attributes. */
+ if (netdev && netdev->dcbnl_ops && netdev->dcbnl_ops->getdcbx) {
+ dcbx = netdev->dcbnl_ops->getdcbx(netdev);
+
+ if (dcbx & DCB_CAP_DCBX_VER_IEEE) {
+ app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE;
+ up = dcb_ieee_getapp_mask(netdev, &app);
+ app.protocol = ETH_P_FIP;
+ fup = dcb_ieee_getapp_mask(netdev, &app);
+ } else {
+ app.selector = DCB_APP_IDTYPE_ETHTYPE;
+ up = dcb_getapp(netdev, &app);
+ app.protocol = ETH_P_FIP;
+ fup = dcb_getapp(netdev, &app);
+ }
+
+ port->priority = ffs(up) ? ffs(up) - 1 : 0;
+ fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority;
+ }
+#endif
+}
+
+/**
* fcoe_create() - Create a fcoe interface
* @netdev : The net_device object the Ethernet interface to create on
* @fip_mode: The FIP mode for this creation
@@ -1902,7 +2088,7 @@ static bool fcoe_match(struct net_device *netdev)
*/
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
{
- int rc;
+ int rc = 0;
struct fcoe_interface *fcoe;
struct fc_lport *lport;
@@ -1926,13 +2112,17 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
netdev->name);
rc = -EIO;
+ rtnl_unlock();
fcoe_interface_cleanup(fcoe);
- goto out_free;
+ goto out_nortnl;
}
/* Make this the "master" N_Port */
fcoe->ctlr.lp = lport;
+ /* setup DCB priority attributes. */
+ fcoe_dcb_create(fcoe);
+
/* add to lports list */
fcoe_hostlist_add(lport);
@@ -1942,19 +2132,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
if (!fcoe_link_ok(lport))
fcoe_ctlr_link_up(&fcoe->ctlr);
- /*
- * Release from init in fcoe_interface_create(), on success lport
- * should be holding a reference taken in fcoe_if_create().
- */
- fcoe_interface_put(fcoe);
- rtnl_unlock();
- mutex_unlock(&fcoe_config_mutex);
-
- return 0;
-out_free:
- fcoe_interface_put(fcoe);
out_nodev:
rtnl_unlock();
+out_nortnl:
mutex_unlock(&fcoe_config_mutex);
return rc;
}
@@ -1971,7 +2151,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
struct net_device *netdev = fcoe_netdev(lport);
struct ethtool_cmd ecmd;
- if (!dev_ethtool_get_settings(netdev, &ecmd)) {
+ if (!__ethtool_get_settings(netdev, &ecmd)) {
lport->link_supported_speeds &=
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
@@ -2234,7 +2414,6 @@ static void __exit fcoe_exit(void)
list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) {
list_del(&fcoe->list);
port = lport_priv(fcoe->ctlr.lp);
- fcoe_interface_cleanup(fcoe);
queue_work(fcoe_wq, &port->destroy_work);
}
rtnl_unlock();
@@ -2284,14 +2463,11 @@ static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
goto done;
mac = fr_cb(fp)->granted_mac;
- if (is_zero_ether_addr(mac)) {
- /* pre-FIP */
- if (fcoe_ctlr_recv_flogi(fip, lport, fp)) {
- fc_frame_free(fp);
- return;
- }
- }
- fcoe_update_src_mac(lport, mac);
+ /* pre-FIP */
+ if (is_zero_ether_addr(mac))
+ fcoe_ctlr_recv_flogi(fip, lport, fp);
+ if (!is_zero_ether_addr(mac))
+ fcoe_update_src_mac(lport, mac);
done:
fc_lport_flogi_resp(seq, fp, lport);
}
@@ -2373,7 +2549,7 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
rc = fcoe_validate_vport_create(vport);
if (rc) {
- wwn_to_str(vport->port_name, buf, sizeof(buf));
+ fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
printk(KERN_ERR "fcoe: Failed to create vport, "
"WWPN (0x%s) already exists\n",
buf);
@@ -2381,7 +2557,9 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
}
mutex_lock(&fcoe_config_mutex);
+ rtnl_lock();
vn_port = fcoe_if_create(fcoe, &vport->dev, 1);
+ rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
if (IS_ERR(vn_port)) {
@@ -2480,28 +2658,9 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport)
static void fcoe_get_lesb(struct fc_lport *lport,
struct fc_els_lesb *fc_lesb)
{
- unsigned int cpu;
- u32 lfc, vlfc, mdac;
- struct fcoe_dev_stats *devst;
- struct fcoe_fc_els_lesb *lesb;
- struct rtnl_link_stats64 temp;
struct net_device *netdev = fcoe_netdev(lport);
- lfc = 0;
- vlfc = 0;
- mdac = 0;
- lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
- memset(lesb, 0, sizeof(*lesb));
- for_each_possible_cpu(cpu) {
- devst = per_cpu_ptr(lport->dev_stats, cpu);
- lfc += devst->LinkFailureCount;
- vlfc += devst->VLinkFailureCount;
- mdac += devst->MissDiscAdvCount;
- }
- lesb->lesb_link_fail = htonl(lfc);
- lesb->lesb_vlink_fail = htonl(vlfc);
- lesb->lesb_miss_fka = htonl(mdac);
- lesb->lesb_fcs_error = htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
+ __fcoe_get_lesb(lport, fc_lesb, netdev);
}
/**
@@ -2525,49 +2684,3 @@ static void fcoe_set_port_id(struct fc_lport *lport,
if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
}
-
-/**
- * fcoe_validate_vport_create() - Validate a vport before creating it
- * @vport: NPIV port to be created
- *
- * This routine is meant to add validation for a vport before creating it
- * via fcoe_vport_create().
- * Current validations are:
- * - WWPN supplied is unique for given lport
- *
- *
-*/
-static int fcoe_validate_vport_create(struct fc_vport *vport)
-{
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_lport *n_port = shost_priv(shost);
- struct fc_lport *vn_port;
- int rc = 0;
- char buf[32];
-
- mutex_lock(&n_port->lp_mutex);
-
- wwn_to_str(vport->port_name, buf, sizeof(buf));
- /* Check if the wwpn is not same as that of the lport */
- if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
- FCOE_DBG("vport WWPN 0x%s is same as that of the "
- "base port WWPN\n", buf);
- rc = -EINVAL;
- goto out;
- }
-
- /* Check if there is any existing vport with same wwpn */
- list_for_each_entry(vn_port, &n_port->vports, list) {
- if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
- FCOE_DBG("vport with given WWPN 0x%s already "
- "exists\n", buf);
- rc = -EINVAL;
- break;
- }
- }
-
-out:
- mutex_unlock(&n_port->lp_mutex);
-
- return rc;
-}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index c4a9399..6c6884b 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -80,6 +80,7 @@ do { \
struct fcoe_interface {
struct list_head list;
struct net_device *netdev;
+ struct net_device *realdev;
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
struct fcoe_ctlr ctlr;
@@ -99,14 +100,4 @@ static inline struct net_device *fcoe_netdev(const struct fc_lport *lport)
((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
}
-static inline void wwn_to_str(u64 wwn, char *buf, int len)
-{
- u8 wwpn[8];
-
- u64_to_wwn(wwn, wwpn);
- snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
- wwpn[0], wwpn[1], wwpn[2], wwpn[3],
- wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
-}
-
#endif /* _FCOE_H_ */
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index c74c4b8..e7522dc 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -320,6 +320,7 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
skb_put(skb, sizeof(*sol));
skb->protocol = htons(ETH_P_FIP);
+ skb->priority = fip->priority;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
fip->send(fip, skb);
@@ -474,6 +475,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
}
skb_put(skb, len);
skb->protocol = htons(ETH_P_FIP);
+ skb->priority = fip->priority;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
fip->send(fip, skb);
@@ -566,6 +568,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
cap->fip.fip_dl_len = htons(dlen / FIP_BPW);
skb->protocol = htons(ETH_P_FIP);
+ skb->priority = fip->priority;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
return 0;
@@ -1911,6 +1914,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
skb_put(skb, len);
skb->protocol = htons(ETH_P_FIP);
+ skb->priority = fip->priority;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index 41068e8..bd97b22 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -83,6 +83,107 @@ static struct notifier_block libfcoe_notifier = {
.notifier_call = libfcoe_device_notification,
};
+void __fcoe_get_lesb(struct fc_lport *lport,
+ struct fc_els_lesb *fc_lesb,
+ struct net_device *netdev)
+{
+ unsigned int cpu;
+ u32 lfc, vlfc, mdac;
+ struct fcoe_dev_stats *devst;
+ struct fcoe_fc_els_lesb *lesb;
+ struct rtnl_link_stats64 temp;
+
+ lfc = 0;
+ vlfc = 0;
+ mdac = 0;
+ lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
+ memset(lesb, 0, sizeof(*lesb));
+ for_each_possible_cpu(cpu) {
+ devst = per_cpu_ptr(lport->dev_stats, cpu);
+ lfc += devst->LinkFailureCount;
+ vlfc += devst->VLinkFailureCount;
+ mdac += devst->MissDiscAdvCount;
+ }
+ lesb->lesb_link_fail = htonl(lfc);
+ lesb->lesb_vlink_fail = htonl(vlfc);
+ lesb->lesb_miss_fka = htonl(mdac);
+ lesb->lesb_fcs_error =
+ htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
+}
+EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
+
+void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
+{
+ u8 wwpn[8];
+
+ u64_to_wwn(wwn, wwpn);
+ snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
+ wwpn[0], wwpn[1], wwpn[2], wwpn[3],
+ wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
+}
+EXPORT_SYMBOL_GPL(fcoe_wwn_to_str);
+
+/**
+ * fcoe_validate_vport_create() - Validate a vport before creating it
+ * @vport: NPIV port to be created
+ *
+ * This routine is meant to add validation for a vport before creating it
+ * via fcoe_vport_create().
+ * Current validations are:
+ * - WWPN supplied is unique for given lport
+ */
+int fcoe_validate_vport_create(struct fc_vport *vport)
+{
+ struct Scsi_Host *shost = vport_to_shost(vport);
+ struct fc_lport *n_port = shost_priv(shost);
+ struct fc_lport *vn_port;
+ int rc = 0;
+ char buf[32];
+
+ mutex_lock(&n_port->lp_mutex);
+
+ fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
+ /* Check if the wwpn is not same as that of the lport */
+ if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
+ LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the "
+ "base port WWPN\n", buf);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Check if there is any existing vport with same wwpn */
+ list_for_each_entry(vn_port, &n_port->vports, list) {
+ if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
+ LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s "
+ "already exists\n", buf);
+ rc = -EINVAL;
+ break;
+ }
+ }
+out:
+ mutex_unlock(&n_port->lp_mutex);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(fcoe_validate_vport_create);
+
+/**
+ * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
+ * @netdev: the associated net device
+ * @wwn: the output WWN
+ * @type: the type of WWN (WWPN or WWNN)
+ *
+ * Returns: 0 for success
+ */
+int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
+{
+ const struct net_device_ops *ops = netdev->netdev_ops;
+
+ if (ops->ndo_fcoe_get_wwn)
+ return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(fcoe_get_wwn);
+
/**
* fcoe_fc_crc() - Calculates the CRC for a given frame
* @fp: The frame to be checksumed
@@ -105,11 +206,12 @@ u32 fcoe_fc_crc(struct fc_frame *fp)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
frag = &skb_shinfo(skb)->frags[i];
off = frag->page_offset;
- len = frag->size;
+ len = skb_frag_size(frag);
while (len > 0) {
clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
- data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
- KM_SKB_DATA_SOFTIRQ);
+ data = kmap_atomic(
+ skb_frag_page(frag) + (off >> PAGE_SHIFT),
+ KM_SKB_DATA_SOFTIRQ);
crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
off += clen;
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 671cde9..95a5ba2 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -37,7 +37,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.5.0.1"
+#define DRV_VERSION "1.5.0.2"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index bb63f1a..fc98eb6 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -388,17 +388,6 @@ static void fnic_iounmap(struct fnic *fnic)
iounmap(fnic->bar0.vaddr);
}
-/*
- * Allocate element for mempools requiring GFP_DMA flag.
- * Otherwise, checks in kmem_flagcheck() hit BUG_ON().
- */
-static void *fnic_alloc_slab_dma(gfp_t gfp_mask, void *pool_data)
-{
- struct kmem_cache *mem = pool_data;
-
- return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA);
-}
-
/**
* fnic_get_mac() - get assigned data MAC address for FIP code.
* @lport: local port.
@@ -603,14 +592,12 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
if (!fnic->io_req_pool)
goto err_out_free_resources;
- pool = mempool_create(2, fnic_alloc_slab_dma, mempool_free_slab,
- fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
+ pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
if (!pool)
goto err_out_free_ioreq_pool;
fnic->io_sgl_pool[FNIC_SGL_CACHE_DFLT] = pool;
- pool = mempool_create(2, fnic_alloc_slab_dma, mempool_free_slab,
- fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
+ pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
if (!pool)
goto err_out_free_dflt_pool;
fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX] = pool;
@@ -876,7 +863,7 @@ static int __init fnic_init_module(void)
len = sizeof(struct fnic_dflt_sgl_list);
fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create
("fnic_sgl_dflt", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
- SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA,
+ SLAB_HWCACHE_ALIGN,
NULL);
if (!fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]) {
printk(KERN_ERR PFX "failed to create fnic dflt sgl slab\n");
@@ -888,7 +875,7 @@ static int __init fnic_init_module(void)
len = sizeof(struct fnic_sgl_list);
fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create
("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
- SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA,
+ SLAB_HWCACHE_ALIGN,
NULL);
if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) {
printk(KERN_ERR PFX "failed to create fnic max sgl slab\n");
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 538b31c..c40ce52 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -406,7 +406,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
if (sg_count) {
io_req->sgl_list =
mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type],
- GFP_ATOMIC | GFP_DMA);
+ GFP_ATOMIC);
if (!io_req->sgl_list) {
ret = SCSI_MLQUEUE_HOST_BUSY;
scsi_dma_unmap(sc);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 36aca4b..4aabbdc 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -490,7 +490,8 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
evt->hostdata->dev);
if (evt->cmnd_done)
evt->cmnd_done(evt->cmnd);
- } else if (evt->done)
+ } else if (evt->done && evt->crq.format != VIOSRP_MAD_FORMAT &&
+ evt->iu.srp.login_req.opcode != SRP_LOGIN_REQ)
evt->done(evt);
free_event_struct(&evt->hostdata->pool, evt);
spin_lock_irqsave(hostdata->host->host_lock, flags);
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index f48ae01..920c02e 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -104,6 +104,11 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
if (crq->valid & 0x80) {
if (++queue->cur == queue->size)
queue->cur = 0;
+
+ /* Ensure the read of the valid bit occurs before reading any
+ * other bits of the CRQ entry
+ */
+ rmb();
} else
crq = NULL;
spin_unlock_irqrestore(&queue->lock, flags);
@@ -122,6 +127,11 @@ static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
{
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+ /*
+ * Ensure the command buffer is flushed to memory before handing it
+ * over to the VIOS to prevent it from fetching any stale data.
+ */
+ mb();
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
}
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index ef46d83..e7fe9c4 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1094,6 +1094,7 @@ static void isci_host_completion_routine(unsigned long data)
struct isci_request *request;
struct isci_request *next_request;
struct sas_task *task;
+ u16 active;
INIT_LIST_HEAD(&completed_request_list);
INIT_LIST_HEAD(&errored_request_list);
@@ -1184,6 +1185,13 @@ static void isci_host_completion_routine(unsigned long data)
}
}
+ /* the coalesence timeout doubles at each encoding step, so
+ * update it based on the ilog2 value of the outstanding requests
+ */
+ active = isci_tci_active(ihost);
+ writel(SMU_ICC_GEN_VAL(NUMBER, active) |
+ SMU_ICC_GEN_VAL(TIMER, ISCI_COALESCE_BASE + ilog2(active)),
+ &ihost->smu_registers->interrupt_coalesce_control);
}
/**
@@ -1255,6 +1263,10 @@ void isci_host_deinit(struct isci_host *ihost)
{
int i;
+ /* disable output data selects */
+ for (i = 0; i < isci_gpio_count(ihost); i++)
+ writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
+
isci_host_change_state(ihost, isci_stopping);
for (i = 0; i < SCI_MAX_PORTS; i++) {
struct isci_port *iport = &ihost->ports[i];
@@ -1273,6 +1285,12 @@ void isci_host_deinit(struct isci_host *ihost)
spin_unlock_irq(&ihost->scic_lock);
wait_for_stop(ihost);
+
+ /* disable sgpio: where the above wait should give time for the
+ * enclosure to sample the gpios going inactive
+ */
+ writel(0, &ihost->scu_registers->peg0.sgpio.interface_control);
+
sci_controller_reset(ihost);
/* Cancel any/all outstanding port timers */
@@ -1332,7 +1350,7 @@ static void isci_user_parameters_get(struct sci_user_parameters *u)
u->stp_max_occupancy_timeout = stp_max_occ_to;
u->ssp_max_occupancy_timeout = ssp_max_occ_to;
u->no_outbound_task_timeout = no_outbound_task_to;
- u->max_number_concurrent_device_spin_up = max_concurr_spinup;
+ u->max_concurr_spinup = max_concurr_spinup;
}
static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm)
@@ -1474,7 +1492,7 @@ static void sci_controller_ready_state_enter(struct sci_base_state_machine *sm)
struct isci_host *ihost = container_of(sm, typeof(*ihost), sm);
/* set the default interrupt coalescence number and timeout value. */
- sci_controller_set_interrupt_coalescence(ihost, 0x10, 250);
+ sci_controller_set_interrupt_coalescence(ihost, 0, 0);
}
static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm)
@@ -1643,7 +1661,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
/* Default to APC mode. */
- ihost->oem_parameters.controller.max_concurrent_dev_spin_up = 1;
+ ihost->oem_parameters.controller.max_concurr_spin_up = 1;
/* Default to no SSC operation. */
ihost->oem_parameters.controller.do_enable_ssc = false;
@@ -1769,7 +1787,8 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem)
} else
return -EINVAL;
- if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
+ if (oem->controller.max_concurr_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT ||
+ oem->controller.max_concurr_spin_up < 1)
return -EINVAL;
return 0;
@@ -1792,6 +1811,16 @@ static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
return SCI_FAILURE_INVALID_STATE;
}
+static u8 max_spin_up(struct isci_host *ihost)
+{
+ if (ihost->user_parameters.max_concurr_spinup)
+ return min_t(u8, ihost->user_parameters.max_concurr_spinup,
+ MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT);
+ else
+ return min_t(u8, ihost->oem_parameters.controller.max_concurr_spin_up,
+ MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT);
+}
+
static void power_control_timeout(unsigned long data)
{
struct sci_timer *tmr = (struct sci_timer *)data;
@@ -1821,8 +1850,7 @@ static void power_control_timeout(unsigned long data)
if (iphy == NULL)
continue;
- if (ihost->power_control.phys_granted_power >=
- ihost->oem_parameters.controller.max_concurrent_dev_spin_up)
+ if (ihost->power_control.phys_granted_power >= max_spin_up(ihost))
break;
ihost->power_control.requesters[i] = NULL;
@@ -1847,8 +1875,7 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
{
BUG_ON(iphy == NULL);
- if (ihost->power_control.phys_granted_power <
- ihost->oem_parameters.controller.max_concurrent_dev_spin_up) {
+ if (ihost->power_control.phys_granted_power < max_spin_up(ihost)) {
ihost->power_control.phys_granted_power++;
sci_phy_consume_power_handler(iphy);
@@ -2357,6 +2384,12 @@ int isci_host_init(struct isci_host *ihost)
for (i = 0; i < SCI_MAX_PHYS; i++)
isci_phy_init(&ihost->phys[i], ihost, i);
+ /* enable sgpio */
+ writel(1, &ihost->scu_registers->peg0.sgpio.interface_control);
+ for (i = 0; i < isci_gpio_count(ihost); i++)
+ writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
+ writel(0, &ihost->scu_registers->peg0.sgpio.vendor_specific_code);
+
for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
struct isci_remote_device *idev = &ihost->devices[i];
@@ -2752,3 +2785,56 @@ enum sci_task_status sci_controller_start_task(struct isci_host *ihost,
return status;
}
+
+static int sci_write_gpio_tx_gp(struct isci_host *ihost, u8 reg_index, u8 reg_count, u8 *write_data)
+{
+ int d;
+
+ /* no support for TX_GP_CFG */
+ if (reg_index == 0)
+ return -EINVAL;
+
+ for (d = 0; d < isci_gpio_count(ihost); d++) {
+ u32 val = 0x444; /* all ODx.n clear */
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ int bit = (i << 2) + 2;
+
+ bit = try_test_sas_gpio_gp_bit(to_sas_gpio_od(d, i),
+ write_data, reg_index,
+ reg_count);
+ if (bit < 0)
+ break;
+
+ /* if od is set, clear the 'invert' bit */
+ val &= ~(bit << ((i << 2) + 2));
+ }
+
+ if (i < 3)
+ break;
+ writel(val, &ihost->scu_registers->peg0.sgpio.output_data_select[d]);
+ }
+
+ /* unless reg_index is > 1, we should always be able to write at
+ * least one register
+ */
+ return d > 0;
+}
+
+int isci_gpio_write(struct sas_ha_struct *sas_ha, u8 reg_type, u8 reg_index,
+ u8 reg_count, u8 *write_data)
+{
+ struct isci_host *ihost = sas_ha->lldd_ha;
+ int written;
+
+ switch (reg_type) {
+ case SAS_GPIO_REG_TX_GP:
+ written = sci_write_gpio_tx_gp(ihost, reg_index, reg_count, write_data);
+ break;
+ default:
+ written = -EINVAL;
+ }
+
+ return written;
+}
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 062101a..ef84778 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -309,9 +309,8 @@ static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
}
#define for_each_isci_host(id, ihost, pdev) \
- for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
- id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
- ihost = to_pci_info(pdev)->hosts[++id])
+ for (id = 0; id < SCI_MAX_CONTROLLERS && \
+ (ihost = to_pci_info(pdev)->hosts[id]); id++)
static inline enum isci_status isci_host_get_state(struct isci_host *isci_host)
{
@@ -369,6 +368,9 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
#define ISCI_TAG_SEQ(tag) (((tag) >> 12) & (SCI_MAX_SEQ-1))
#define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1))
+/* interrupt coalescing baseline: 9 == 3 to 5us interrupt delay per command */
+#define ISCI_COALESCE_BASE 9
+
/* expander attached sata devices require 3 rnc slots */
static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
{
@@ -437,6 +439,18 @@ static inline bool is_c0(struct pci_dev *pdev)
return false;
}
+/* set hw control for 'activity', even though active enclosures seem to drive
+ * the activity led on their own. Skip setting FSENG control on 'status' due
+ * to unexpected operation and 'error' due to not being a supported automatic
+ * FSENG output
+ */
+#define SGPIO_HW_CONTROL 0x00000443
+
+static inline int isci_gpio_count(struct isci_host *ihost)
+{
+ return ARRAY_SIZE(ihost->scu_registers->peg0.sgpio.output_data_select);
+}
+
void sci_controller_post_request(struct isci_host *ihost,
u32 request);
void sci_controller_release_frame(struct isci_host *ihost,
@@ -539,4 +553,7 @@ void sci_port_configuration_agent_construct(
enum sci_status sci_port_configuration_agent_initialize(
struct isci_host *ihost,
struct sci_port_configuration_agent *port_agent);
+
+int isci_gpio_write(struct sas_ha_struct *, u8 reg_type, u8 reg_index,
+ u8 reg_count, u8 *write_data);
#endif
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 0365d58..3784388 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -59,10 +59,19 @@
#include <linux/firmware.h>
#include <linux/efi.h>
#include <asm/string.h>
+#include <scsi/scsi_host.h>
#include "isci.h"
#include "task.h"
#include "probe_roms.h"
+#define MAJ 1
+#define MIN 0
+#define BUILD 0
+#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
+ __stringify(BUILD)
+
+MODULE_VERSION(DRV_VERSION);
+
static struct scsi_transport_template *isci_transport_template;
static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
@@ -109,10 +118,26 @@ unsigned char phy_gen = 3;
module_param(phy_gen, byte, 0);
MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
-unsigned char max_concurr_spinup = 1;
+unsigned char max_concurr_spinup;
module_param(max_concurr_spinup, byte, 0);
MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
+static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
+ struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ struct isci_host *ihost = container_of(sas_ha, typeof(*ihost), sas_ha);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ihost->id);
+}
+
+static DEVICE_ATTR(isci_id, S_IRUGO, isci_show_id, NULL);
+
+struct device_attribute *isci_host_attrs[] = {
+ &dev_attr_isci_id,
+ NULL
+};
+
static struct scsi_host_template isci_sht = {
.module = THIS_MODULE,
@@ -138,6 +163,7 @@ static struct scsi_host_template isci_sht = {
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+ .shost_attrs = isci_host_attrs,
};
static struct sas_domain_function_template isci_transport_ops = {
@@ -166,6 +192,9 @@ static struct sas_domain_function_template isci_transport_ops = {
/* Phy management */
.lldd_control_phy = isci_phy_control,
+
+ /* GPIO support */
+ .lldd_write_gpio = isci_gpio_write,
};
@@ -232,17 +261,6 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
return 0;
}
-static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
- struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
- struct isci_host *ihost = container_of(sas_ha, typeof(*ihost), sas_ha);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", ihost->id);
-}
-
-static DEVICE_ATTR(isci_id, S_IRUGO, isci_show_id, NULL);
-
static void isci_unregister(struct isci_host *isci_host)
{
struct Scsi_Host *shost;
@@ -251,7 +269,6 @@ static void isci_unregister(struct isci_host *isci_host)
return;
shost = isci_host->shost;
- device_remove_file(&shost->shost_dev, &dev_attr_isci_id);
sas_unregister_ha(&isci_host->sas_ha);
@@ -415,14 +432,8 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
if (err)
goto err_shost_remove;
- err = device_create_file(&shost->shost_dev, &dev_attr_isci_id);
- if (err)
- goto err_unregister_ha;
-
return isci_host;
- err_unregister_ha:
- sas_unregister_ha(&(isci_host->sas_ha));
err_shost_remove:
scsi_remove_host(shost);
err_shost:
@@ -448,7 +459,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
return -ENOMEM;
pci_set_drvdata(pdev, pci_info);
- if (efi_enabled)
+ if (efi_enabled(EFI_RUNTIME_SERVICES))
orom = isci_get_efi_var(pdev);
if (!orom)
@@ -539,7 +550,8 @@ static __init int isci_init(void)
{
int err;
- pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
+ pr_info("%s: Intel(R) C600 SAS Controller Driver - version %s\n",
+ DRV_NAME, DRV_VERSION);
isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
if (!isci_transport_template)
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index 430fc8f..35f50c2 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -708,7 +708,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
__func__,
event_code);
- return SCI_FAILURE;;
+ return SCI_FAILURE;
}
return SCI_SUCCESS;
case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:
@@ -1313,6 +1313,17 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
ret = isci_port_perform_hard_reset(ihost, iport, iphy);
break;
+ case PHY_FUNC_GET_EVENTS: {
+ struct scu_link_layer_registers __iomem *r;
+ struct sas_phy *phy = sas_phy->phy;
+
+ r = iphy->link_layer_registers;
+ phy->running_disparity_error_count = readl(&r->running_disparity_error_count);
+ phy->loss_of_dword_sync_count = readl(&r->loss_of_sync_error_count);
+ phy->phy_reset_problem_count = readl(&r->phy_reset_problem_count);
+ phy->invalid_dword_count = readl(&r->invalid_dword_counter);
+ break;
+ }
default:
dev_dbg(&ihost->pdev->dev,
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 8f6f9b7..ac7f277 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -145,48 +145,15 @@ static void sci_port_bcn_enable(struct isci_port *iport)
}
}
-/* called under sci_lock to stabilize phy:port associations */
-void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport)
-{
- int i;
-
- clear_bit(IPORT_BCN_BLOCKED, &iport->flags);
- wake_up(&ihost->eventq);
-
- if (!test_and_clear_bit(IPORT_BCN_PENDING, &iport->flags))
- return;
-
- for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) {
- struct isci_phy *iphy = iport->phy_table[i];
-
- if (!iphy)
- continue;
-
- ihost->sas_ha.notify_port_event(&iphy->sas_phy,
- PORTE_BROADCAST_RCVD);
- break;
- }
-}
-
static void isci_port_bc_change_received(struct isci_host *ihost,
struct isci_port *iport,
struct isci_phy *iphy)
{
- if (iport && test_bit(IPORT_BCN_BLOCKED, &iport->flags)) {
- dev_dbg(&ihost->pdev->dev,
- "%s: disabled BCN; isci_phy = %p, sas_phy = %p\n",
- __func__, iphy, &iphy->sas_phy);
- set_bit(IPORT_BCN_PENDING, &iport->flags);
- atomic_inc(&iport->event);
- wake_up(&ihost->eventq);
- } else {
- dev_dbg(&ihost->pdev->dev,
- "%s: isci_phy = %p, sas_phy = %p\n",
- __func__, iphy, &iphy->sas_phy);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_phy = %p, sas_phy = %p\n",
+ __func__, iphy, &iphy->sas_phy);
- ihost->sas_ha.notify_port_event(&iphy->sas_phy,
- PORTE_BROADCAST_RCVD);
- }
+ ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD);
sci_port_bcn_enable(iport);
}
@@ -278,9 +245,6 @@ static void isci_port_link_down(struct isci_host *isci_host,
/* check to see if this is the last phy on this port. */
if (isci_phy->sas_phy.port &&
isci_phy->sas_phy.port->num_phys == 1) {
- atomic_inc(&isci_port->event);
- isci_port_bcn_enable(isci_host, isci_port);
-
/* change the state for all devices on this port. The
* next task sent to this device will be returned as
* SAS_TASK_UNDELIVERED, and the scsi mid layer will
@@ -294,8 +258,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
__func__, isci_device);
set_bit(IDEV_GONE, &isci_device->flags);
}
+ isci_port_change_state(isci_port, isci_stopping);
}
- isci_port_change_state(isci_port, isci_stopping);
}
/* Notify libsas of the borken link, this will trigger calls to our
@@ -350,6 +314,34 @@ static void isci_port_stop_complete(struct isci_host *ihost,
dev_dbg(&ihost->pdev->dev, "Port stop complete\n");
}
+
+static bool is_port_ready_state(enum sci_port_states state)
+{
+ switch (state) {
+ case SCI_PORT_READY:
+ case SCI_PORT_SUB_WAITING:
+ case SCI_PORT_SUB_OPERATIONAL:
+ case SCI_PORT_SUB_CONFIGURING:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* flag dummy rnc hanling when exiting a ready state */
+static void port_state_machine_change(struct isci_port *iport,
+ enum sci_port_states state)
+{
+ struct sci_base_state_machine *sm = &iport->sm;
+ enum sci_port_states old_state = sm->current_state_id;
+
+ if (is_port_ready_state(old_state) && !is_port_ready_state(state))
+ iport->ready_exit = true;
+
+ sci_change_state(sm, state);
+ iport->ready_exit = false;
+}
+
/**
* isci_port_hard_reset_complete() - This function is called by the sci core
* when the hard reset complete notification has been received.
@@ -368,6 +360,26 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port,
/* Save the status of the hard reset from the port. */
isci_port->hard_reset_status = completion_status;
+ if (completion_status != SCI_SUCCESS) {
+
+ /* The reset failed. The port state is now SCI_PORT_FAILED. */
+ if (isci_port->active_phy_mask == 0) {
+
+ /* Generate the link down now to the host, since it
+ * was intercepted by the hard reset state machine when
+ * it really happened.
+ */
+ isci_port_link_down(isci_port->isci_host,
+ &isci_port->isci_host->phys[
+ isci_port->last_active_phy],
+ isci_port);
+ }
+ /* Advance the port state so that link state changes will be
+ * noticed.
+ */
+ port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
+
+ }
complete_all(&isci_port->hard_reset_complete);
}
@@ -657,6 +669,8 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
struct isci_host *ihost = iport->owning_controller;
iport->active_phy_mask &= ~(1 << iphy->phy_index);
+ if (!iport->active_phy_mask)
+ iport->last_active_phy = iphy->phy_index;
iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
@@ -683,33 +697,6 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
}
}
-static bool is_port_ready_state(enum sci_port_states state)
-{
- switch (state) {
- case SCI_PORT_READY:
- case SCI_PORT_SUB_WAITING:
- case SCI_PORT_SUB_OPERATIONAL:
- case SCI_PORT_SUB_CONFIGURING:
- return true;
- default:
- return false;
- }
-}
-
-/* flag dummy rnc hanling when exiting a ready state */
-static void port_state_machine_change(struct isci_port *iport,
- enum sci_port_states state)
-{
- struct sci_base_state_machine *sm = &iport->sm;
- enum sci_port_states old_state = sm->current_state_id;
-
- if (is_port_ready_state(old_state) && !is_port_ready_state(state))
- iport->ready_exit = true;
-
- sci_change_state(sm, state);
- iport->ready_exit = false;
-}
-
/**
* sci_port_general_link_up_handler - phy can be assigned to port?
* @sci_port: sci_port object for which has a phy that has gone link up.
@@ -1622,7 +1609,8 @@ void sci_port_construct(struct isci_port *iport, u8 index,
iport->logical_port_index = SCIC_SDS_DUMMY_PORT;
iport->physical_port_index = index;
iport->active_phy_mask = 0;
- iport->ready_exit = false;
+ iport->last_active_phy = 0;
+ iport->ready_exit = false;
iport->owning_controller = ihost;
@@ -1648,7 +1636,6 @@ void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index)
init_completion(&iport->start_complete);
iport->isci_host = ihost;
isci_port_change_state(iport, isci_freed);
- atomic_set(&iport->event, 0);
}
/**
@@ -1676,7 +1663,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
{
unsigned long flags;
enum sci_status status;
- int idx, ret = TMF_RESP_FUNC_COMPLETE;
+ int ret = TMF_RESP_FUNC_COMPLETE;
dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
__func__, iport);
@@ -1697,8 +1684,13 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
"%s: iport = %p; hard reset completion\n",
__func__, iport);
- if (iport->hard_reset_status != SCI_SUCCESS)
+ if (iport->hard_reset_status != SCI_SUCCESS) {
ret = TMF_RESP_FUNC_FAILED;
+
+ dev_err(&ihost->pdev->dev,
+ "%s: iport = %p; hard reset failed (0x%x)\n",
+ __func__, iport, iport->hard_reset_status);
+ }
} else {
ret = TMF_RESP_FUNC_FAILED;
@@ -1718,18 +1710,6 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
"%s: iport = %p; hard reset failed "
"(0x%x) - driving explicit link fail for all phys\n",
__func__, iport, iport->hard_reset_status);
-
- /* Down all phys in the port. */
- spin_lock_irqsave(&ihost->scic_lock, flags);
- for (idx = 0; idx < SCI_MAX_PHYS; ++idx) {
- struct isci_phy *iphy = iport->phy_table[idx];
-
- if (!iphy)
- continue;
- sci_phy_stop(iphy);
- sci_phy_start(iphy);
- }
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
}
return ret;
}
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index b50ecd4..cb5ffbc 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -77,7 +77,6 @@ enum isci_status {
/**
* struct isci_port - isci direct attached sas port object
- * @event: counts bcns and port stop events (for bcn filtering)
* @ready_exit: several states constitute 'ready'. When exiting ready we
* need to take extra port-teardown actions that are
* skipped when exiting to another 'ready' state.
@@ -92,10 +91,6 @@ enum isci_status {
*/
struct isci_port {
enum isci_status status;
- #define IPORT_BCN_BLOCKED 0
- #define IPORT_BCN_PENDING 1
- unsigned long flags;
- atomic_t event;
struct isci_host *isci_host;
struct asd_sas_port sas_port;
struct list_head remote_dev_list;
@@ -109,6 +104,7 @@ struct isci_port {
u8 logical_port_index;
u8 physical_port_index;
u8 active_phy_mask;
+ u8 last_active_phy;
u16 reserved_rni;
u16 reserved_tag;
u32 started_request_count;
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
index dc007e6..2c75248 100644
--- a/drivers/scsi/isci/probe_roms.h
+++ b/drivers/scsi/isci/probe_roms.h
@@ -112,7 +112,7 @@ struct sci_user_parameters {
* This field specifies the maximum number of direct attached devices
* that can have power supplied to them simultaneously.
*/
- u8 max_number_concurrent_device_spin_up;
+ u8 max_concurr_spinup;
/**
* This field specifies the number of seconds to allow a phy to consume
@@ -219,7 +219,7 @@ struct sci_bios_oem_param_block_hdr {
struct sci_oem_params {
struct {
uint8_t mode_type;
- uint8_t max_concurrent_dev_spin_up;
+ uint8_t max_concurr_spin_up;
uint8_t do_enable_ssc;
uint8_t reserved;
} controller;
diff --git a/drivers/scsi/isci/registers.h b/drivers/scsi/isci/registers.h
index 00afc73..eaa541a 100644
--- a/drivers/scsi/isci/registers.h
+++ b/drivers/scsi/isci/registers.h
@@ -875,122 +875,6 @@ struct scu_iit_entry {
#define SCU_PTSxSR_GEN_BIT(name) \
SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name)
-
-/*
- * *****************************************************************************
- * * SGPIO Register shift and mask values
- * ***************************************************************************** */
-#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT (0)
-#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK (0x00000001)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT (1)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK (0x00000002)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK (0x00000004)
-#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT (15)
-#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK (0x00008000)
-#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK (0xFFFF7FF8)
-
-#define SCU_SGICRx_GEN_BIT(name) \
- SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name)
-
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT (0)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK (0x0000000F)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT (4)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK (0x000000F0)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT (8)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK (0x00000F00)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT (12)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK (0x0000F000)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000)
-
-#define SCU_SGPBRx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value)
-
-#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT (0)
-#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK (0x00000003)
-#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT (4)
-#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK (0x00000030)
-#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT (8)
-#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK (0x00000300)
-#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT (12)
-#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK (0x00003000)
-#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSDLRx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value)
-
-#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT (0)
-#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK (0x00000003)
-#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT (4)
-#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK (0x00000030)
-#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT (8)
-#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK (0x00000300)
-#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT (12)
-#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK (0x00003000)
-#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSDURx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value)
-
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT (0)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK (0x00000003)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT (4)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK (0x00000030)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT (8)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK (0x00000300)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT (12)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK (0x00003000)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSIDLRx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value)
-
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT (0)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK (0x00000003)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT (4)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK (0x00000030)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT (8)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK (0x00000300)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT (12)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK (0x00003000)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSIDURx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value)
-
-#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT (0)
-#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK (0x0000000F)
-#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK (0xFFFFFFF0)
-
-#define SCU_SGVSCR_GEN_VAL(value) \
- SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value)
-
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT (0)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK (0x00000003)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT (2)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK (0x00000004)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT (3)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK (0x00000008)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT (4)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK (0x00000030)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT (6)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK (0x00000040)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT (7)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK (0x00000080)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT (8)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK (0x00000300)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT (10)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK (0x00000400)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT (11)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK (0x00000800)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK (0xFFFFF000)
-
-#define SCU_SGODSR_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value)
-
-#define SCU_SGODSR_GEN_BIT(name) \
- SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name)
-
/*
* *****************************************************************************
* * SMU Registers
@@ -1529,10 +1413,12 @@ struct scu_sgpio_registers {
u32 serial_input_upper;
/* 0x0018 SGPIO_SGVSCR */
u32 vendor_specific_code;
+/* 0x001C Reserved */
+ u32 reserved_001c;
/* 0x0020 SGPIO_SGODSR */
- u32 ouput_data_select[8];
+ u32 output_data_select[8];
/* Remainder of memory space 256 bytes */
- u32 reserved_1444_14ff[0x31];
+ u32 reserved_1444_14ff[0x30];
};
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index b6e6368..b207cd3 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -386,6 +386,18 @@ static bool is_remote_device_ready(struct isci_remote_device *idev)
}
}
+/*
+ * called once the remote node context has transisitioned to a ready
+ * state (after suspending RX and/or TX due to early D2H fis)
+ */
+static void atapi_remote_device_resume_done(void *_dev)
+{
+ struct isci_remote_device *idev = _dev;
+ struct isci_request *ireq = idev->working_request;
+
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+}
+
enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
u32 event_code)
{
@@ -432,6 +444,16 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
if (status != SCI_SUCCESS)
return status;
+ if (state == SCI_STP_DEV_ATAPI_ERROR) {
+ /* For ATAPI error state resume the RNC right away. */
+ if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
+ scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
+ return sci_remote_node_context_resume(&idev->rnc,
+ atapi_remote_device_resume_done,
+ idev);
+ }
+ }
+
if (state == SCI_STP_DEV_IDLE) {
/* We pick up suspension events to handle specifically to this
@@ -625,6 +647,7 @@ enum sci_status sci_remote_device_complete_io(struct isci_host *ihost,
case SCI_STP_DEV_CMD:
case SCI_STP_DEV_NCQ:
case SCI_STP_DEV_NCQ_ERROR:
+ case SCI_STP_DEV_ATAPI_ERROR:
status = common_complete_io(iport, idev, ireq);
if (status != SCI_SUCCESS)
break;
@@ -1020,6 +1043,7 @@ static const struct sci_base_state sci_remote_device_state_table[] = {
[SCI_STP_DEV_NCQ_ERROR] = {
.enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
},
+ [SCI_STP_DEV_ATAPI_ERROR] = { },
[SCI_STP_DEV_AWAIT_RESET] = { },
[SCI_SMP_DEV_IDLE] = {
.enter_state = sci_smp_remote_device_ready_idle_substate_enter,
@@ -1414,88 +1438,3 @@ int isci_remote_device_found(struct domain_device *domain_dev)
return status == SCI_SUCCESS ? 0 : -ENODEV;
}
-/**
- * isci_device_is_reset_pending() - This function will check if there is any
- * pending reset condition on the device.
- * @request: This parameter is the isci_device object.
- *
- * true if there is a reset pending for the device.
- */
-bool isci_device_is_reset_pending(
- struct isci_host *isci_host,
- struct isci_remote_device *isci_device)
-{
- struct isci_request *isci_request;
- struct isci_request *tmp_req;
- bool reset_is_pending = false;
- unsigned long flags;
-
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_device = %p\n", __func__, isci_device);
-
- spin_lock_irqsave(&isci_host->scic_lock, flags);
-
- /* Check for reset on all pending requests. */
- list_for_each_entry_safe(isci_request, tmp_req,
- &isci_device->reqs_in_process, dev_node) {
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_device = %p request = %p\n",
- __func__, isci_device, isci_request);
-
- if (isci_request->ttype == io_task) {
- struct sas_task *task = isci_request_access_task(
- isci_request);
-
- spin_lock(&task->task_state_lock);
- if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
- reset_is_pending = true;
- spin_unlock(&task->task_state_lock);
- }
- }
-
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
-
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_device = %p reset_is_pending = %d\n",
- __func__, isci_device, reset_is_pending);
-
- return reset_is_pending;
-}
-
-/**
- * isci_device_clear_reset_pending() - This function will clear if any pending
- * reset condition flags on the device.
- * @request: This parameter is the isci_device object.
- *
- * true if there is a reset pending for the device.
- */
-void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev)
-{
- struct isci_request *isci_request;
- struct isci_request *tmp_req;
- unsigned long flags = 0;
-
- dev_dbg(&ihost->pdev->dev, "%s: idev=%p, ihost=%p\n",
- __func__, idev, ihost);
-
- spin_lock_irqsave(&ihost->scic_lock, flags);
-
- /* Clear reset pending on all pending requests. */
- list_for_each_entry_safe(isci_request, tmp_req,
- &idev->reqs_in_process, dev_node) {
- dev_dbg(&ihost->pdev->dev, "%s: idev = %p request = %p\n",
- __func__, idev, isci_request);
-
- if (isci_request->ttype == io_task) {
-
- unsigned long flags2;
- struct sas_task *task = isci_request_access_task(
- isci_request);
-
- spin_lock_irqsave(&task->task_state_lock, flags2);
- task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
- spin_unlock_irqrestore(&task->task_state_lock, flags2);
- }
- }
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-}
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 57ccfc3..483ee50 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -132,10 +132,7 @@ void isci_remote_device_nuke_requests(struct isci_host *ihost,
struct isci_remote_device *idev);
void isci_remote_device_gone(struct domain_device *domain_dev);
int isci_remote_device_found(struct domain_device *domain_dev);
-bool isci_device_is_reset_pending(struct isci_host *ihost,
- struct isci_remote_device *idev);
-void isci_device_clear_reset_pending(struct isci_host *ihost,
- struct isci_remote_device *idev);
+
/**
* sci_remote_device_stop() - This method will stop both transmission and
* reception of link activity for the supplied remote device. This method
@@ -244,6 +241,15 @@ enum sci_remote_device_states {
SCI_STP_DEV_NCQ_ERROR,
/**
+ * This is the ATAPI error state for the STP ATAPI remote device.
+ * This state is entered when ATAPI device sends error status FIS
+ * without data while the device object is in CMD state.
+ * A suspension event is expected in this state.
+ * The device object will resume right away.
+ */
+ SCI_STP_DEV_ATAPI_ERROR,
+
+ /**
* This is the READY substate indicates the device is waiting for the RESET task
* coming to be recovered from certain hardware specific error.
*/
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index b70f999..f3cbecc 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -191,7 +191,7 @@ static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq)
task_iu->task_func = isci_tmf->tmf_code;
task_iu->task_tag =
- (ireq->ttype == tmf_task) ?
+ (test_bit(IREQ_TMF, &ireq->flags)) ?
isci_tmf->io_tag :
SCI_CONTROLLER_INVALID_IO_TAG;
}
@@ -481,7 +481,29 @@ static void sci_stp_optimized_request_construct(struct isci_request *ireq,
}
}
+static void sci_atapi_construct(struct isci_request *ireq)
+{
+ struct host_to_dev_fis *h2d_fis = &ireq->stp.cmd;
+ struct sas_task *task;
+
+ /* To simplify the implementation we take advantage of the
+ * silicon's partial acceleration of atapi protocol (dma data
+ * transfers), so we promote all commands to dma protocol. This
+ * breaks compatibility with ATA_HORKAGE_ATAPI_MOD16_DMA drives.
+ */
+ h2d_fis->features |= ATAPI_PKT_DMA;
+ scu_stp_raw_request_construct_task_context(ireq);
+
+ task = isci_request_access_task(ireq);
+ if (task->data_dir == DMA_NONE)
+ task->total_xfer_len = 0;
+
+ /* clear the response so we can detect arrivial of an
+ * unsolicited h2d fis
+ */
+ ireq->stp.rsp.fis_type = 0;
+}
static enum sci_status
sci_io_request_construct_sata(struct isci_request *ireq,
@@ -491,9 +513,10 @@ sci_io_request_construct_sata(struct isci_request *ireq,
{
enum sci_status status = SCI_SUCCESS;
struct sas_task *task = isci_request_access_task(ireq);
+ struct domain_device *dev = ireq->target_device->domain_dev;
/* check for management protocols */
- if (ireq->ttype == tmf_task) {
+ if (test_bit(IREQ_TMF, &ireq->flags)) {
struct isci_tmf *tmf = isci_request_access_tmf(ireq);
if (tmf->tmf_code == isci_tmf_sata_srst_high ||
@@ -519,6 +542,13 @@ sci_io_request_construct_sata(struct isci_request *ireq,
}
+ /* ATAPI */
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
+ task->ata_task.fis.command == ATA_CMD_PACKET) {
+ sci_atapi_construct(ireq);
+ return SCI_SUCCESS;
+ }
+
/* non data */
if (task->data_dir == DMA_NONE) {
scu_stp_raw_request_construct_task_context(ireq);
@@ -602,7 +632,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
enum sci_status status = SCI_SUCCESS;
/* check for management protocols */
- if (ireq->ttype == tmf_task) {
+ if (test_bit(IREQ_TMF, &ireq->flags)) {
struct isci_tmf *tmf = isci_request_access_tmf(ireq);
if (tmf->tmf_code == isci_tmf_sata_srst_high ||
@@ -627,7 +657,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
/**
* sci_req_tx_bytes - bytes transferred when reply underruns request
- * @sci_req: request that was terminated early
+ * @ireq: request that was terminated early
*/
#define SCU_TASK_CONTEXT_SRAM 0x200000
static u32 sci_req_tx_bytes(struct isci_request *ireq)
@@ -729,6 +759,10 @@ sci_io_request_terminate(struct isci_request *ireq)
case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED:
case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG:
case SCI_REQ_STP_SOFT_RESET_WAIT_D2H:
+ case SCI_REQ_ATAPI_WAIT_H2D:
+ case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ case SCI_REQ_ATAPI_WAIT_TC_COMP:
sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
return SCI_SUCCESS;
case SCI_REQ_TASK_WAIT_TC_RESP:
@@ -1194,8 +1228,8 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
{
struct isci_stp_request *stp_req = &ireq->stp.req;
struct scu_sgl_element_pair *sgl_pair;
+ enum sci_status status = SCI_SUCCESS;
struct scu_sgl_element *sgl;
- enum sci_status status;
u32 offset;
u32 len = 0;
@@ -1249,7 +1283,7 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
*/
static enum sci_status
sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req,
- u8 *data_buf, u32 len)
+ u8 *data_buf, u32 len)
{
struct isci_request *ireq;
u8 *src_addr;
@@ -1423,6 +1457,128 @@ static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_re
return status;
}
+static enum sci_status process_unsolicited_fis(struct isci_request *ireq,
+ u32 frame_index)
+{
+ struct isci_host *ihost = ireq->owning_controller;
+ enum sci_status status;
+ struct dev_to_host_fis *frame_header;
+ u32 *frame_buffer;
+
+ status = sci_unsolicited_frame_control_get_header(&ihost->uf_control,
+ frame_index,
+ (void **)&frame_header);
+
+ if (status != SCI_SUCCESS)
+ return status;
+
+ if (frame_header->fis_type != FIS_REGD2H) {
+ dev_err(&ireq->isci_host->pdev->dev,
+ "%s ERROR: invalid fis type 0x%X\n",
+ __func__, frame_header->fis_type);
+ return SCI_FAILURE;
+ }
+
+ sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
+ frame_index,
+ (void **)&frame_buffer);
+
+ sci_controller_copy_sata_response(&ireq->stp.rsp,
+ (u32 *)frame_header,
+ frame_buffer);
+
+ /* Frame has been decoded return it to the controller */
+ sci_controller_release_frame(ihost, frame_index);
+
+ return status;
+}
+
+static enum sci_status atapi_d2h_reg_frame_handler(struct isci_request *ireq,
+ u32 frame_index)
+{
+ struct sas_task *task = isci_request_access_task(ireq);
+ enum sci_status status;
+
+ status = process_unsolicited_fis(ireq, frame_index);
+
+ if (status == SCI_SUCCESS) {
+ if (ireq->stp.rsp.status & ATA_ERR)
+ status = SCI_IO_FAILURE_RESPONSE_VALID;
+ } else {
+ status = SCI_IO_FAILURE_RESPONSE_VALID;
+ }
+
+ if (status != SCI_SUCCESS) {
+ ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
+ ireq->sci_status = status;
+ } else {
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ }
+
+ /* the d2h ufi is the end of non-data commands */
+ if (task->data_dir == DMA_NONE)
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+
+ return status;
+}
+
+static void scu_atapi_reconstruct_raw_frame_task_context(struct isci_request *ireq)
+{
+ struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
+ void *atapi_cdb = ireq->ttype_ptr.io_task_ptr->ata_task.atapi_packet;
+ struct scu_task_context *task_context = ireq->tc;
+
+ /* fill in the SCU Task Context for a DATA fis containing CDB in Raw Frame
+ * type. The TC for previous Packet fis was already there, we only need to
+ * change the H2D fis content.
+ */
+ memset(&ireq->stp.cmd, 0, sizeof(struct host_to_dev_fis));
+ memcpy(((u8 *)&ireq->stp.cmd + sizeof(u32)), atapi_cdb, ATAPI_CDB_LEN);
+ memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context));
+ task_context->type.stp.fis_type = FIS_DATA;
+ task_context->transfer_length_bytes = dev->cdb_len;
+}
+
+static void scu_atapi_construct_task_context(struct isci_request *ireq)
+{
+ struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
+ struct sas_task *task = isci_request_access_task(ireq);
+ struct scu_task_context *task_context = ireq->tc;
+ int cdb_len = dev->cdb_len;
+
+ /* reference: SSTL 1.13.4.2
+ * task_type, sata_direction
+ */
+ if (task->data_dir == DMA_TO_DEVICE) {
+ task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
+ task_context->sata_direction = 0;
+ } else {
+ /* todo: for NO_DATA command, we need to send out raw frame. */
+ task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
+ task_context->sata_direction = 1;
+ }
+
+ memset(&task_context->type.stp, 0, sizeof(task_context->type.stp));
+ task_context->type.stp.fis_type = FIS_DATA;
+
+ memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
+ memcpy(&ireq->stp.cmd.lbal, task->ata_task.atapi_packet, cdb_len);
+ task_context->ssp_command_iu_length = cdb_len / sizeof(u32);
+
+ /* task phase is set to TX_CMD */
+ task_context->task_phase = 0x1;
+
+ /* retry counter */
+ task_context->stp_retry_count = 0;
+
+ /* data transfer size. */
+ task_context->transfer_length_bytes = task->total_xfer_len;
+
+ /* setup sgl */
+ sci_request_build_sgl(ireq);
+}
+
enum sci_status
sci_io_request_frame_handler(struct isci_request *ireq,
u32 frame_index)
@@ -1835,6 +1991,24 @@ sci_io_request_frame_handler(struct isci_request *ireq,
return status;
}
+ case SCI_REQ_ATAPI_WAIT_PIO_SETUP: {
+ struct sas_task *task = isci_request_access_task(ireq);
+
+ sci_controller_release_frame(ihost, frame_index);
+ ireq->target_device->working_request = ireq;
+ if (task->data_dir == DMA_NONE) {
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_TC_COMP);
+ scu_atapi_reconstruct_raw_frame_task_context(ireq);
+ } else {
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
+ scu_atapi_construct_task_context(ireq);
+ }
+
+ sci_controller_continue_io(ireq);
+ return SCI_SUCCESS;
+ }
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ return atapi_d2h_reg_frame_handler(ireq, frame_index);
case SCI_REQ_ABORTING:
/*
* TODO: Is it even possible to get an unsolicited frame in the
@@ -1900,10 +2074,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
sci_remote_device_suspend(ireq->target_device,
SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
- /* Fall through to the default case */
+ /* Fall through to the default case */
default:
/* All other completion status cause the IO to be complete. */
ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
@@ -1966,6 +2139,112 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq,
return SCI_SUCCESS;
}
+static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code,
+ enum sci_base_request_states next)
+{
+ enum sci_status status = SCI_SUCCESS;
+
+ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ sci_change_state(&ireq->sm, next);
+ break;
+ default:
+ /* All other completion status cause the IO to be complete.
+ * If a NAK was received, then it is up to the user to retry
+ * the request.
+ */
+ ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
+ ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
+
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+ }
+
+ return status;
+}
+
+static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ireq,
+ u32 completion_code)
+{
+ struct isci_remote_device *idev = ireq->target_device;
+ struct dev_to_host_fis *d2h = &ireq->stp.rsp;
+ enum sci_status status = SCI_SUCCESS;
+
+ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+ case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+
+ case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): {
+ u16 len = sci_req_tx_bytes(ireq);
+
+ /* likely non-error data underrrun, workaround missing
+ * d2h frame from the controller
+ */
+ if (d2h->fis_type != FIS_REGD2H) {
+ d2h->fis_type = FIS_REGD2H;
+ d2h->flags = (1 << 6);
+ d2h->status = 0x50;
+ d2h->error = 0;
+ d2h->lbal = 0;
+ d2h->byte_count_low = len & 0xff;
+ d2h->byte_count_high = len >> 8;
+ d2h->device = 0xa0;
+ d2h->lbal_exp = 0;
+ d2h->lbam_exp = 0;
+ d2h->lbah_exp = 0;
+ d2h->_r_a = 0;
+ d2h->sector_count = 0x3;
+ d2h->sector_count_exp = 0;
+ d2h->_r_b = 0;
+ d2h->_r_c = 0;
+ d2h->_r_d = 0;
+ }
+
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS_IO_DONE_EARLY;
+ status = ireq->sci_status;
+
+ /* the hw will have suspended the rnc, so complete the
+ * request upon pending resume
+ */
+ sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
+ break;
+ }
+ case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
+ /* In this case, there is no UF coming after.
+ * compelte the IO now.
+ */
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+
+ default:
+ if (d2h->fis_type == FIS_REGD2H) {
+ /* UF received change the device state to ATAPI_ERROR */
+ status = ireq->sci_status;
+ sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
+ } else {
+ /* If receiving any non-sucess TC status, no UF
+ * received yet, then an UF for the status fis
+ * is coming after (XXX: suspect this is
+ * actually a protocol error or a bug like the
+ * DONE_UNEXP_FIS case)
+ */
+ ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
+ ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
+ }
+ break;
+ }
+
+ return status;
+}
+
enum sci_status
sci_io_request_tc_completion(struct isci_request *ireq,
u32 completion_code)
@@ -2017,6 +2296,17 @@ sci_io_request_tc_completion(struct isci_request *ireq,
return request_aborting_state_tc_event(ireq,
completion_code);
+ case SCI_REQ_ATAPI_WAIT_H2D:
+ return atapi_raw_completion(ireq, completion_code,
+ SCI_REQ_ATAPI_WAIT_PIO_SETUP);
+
+ case SCI_REQ_ATAPI_WAIT_TC_COMP:
+ return atapi_raw_completion(ireq, completion_code,
+ SCI_REQ_ATAPI_WAIT_D2H);
+
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ return atapi_data_tc_completion_handler(ireq, completion_code);
+
default:
dev_warn(&ihost->pdev->dev,
"%s: SCIC IO Request given task completion "
@@ -2340,14 +2630,8 @@ static void isci_task_save_for_upper_layer_completion(
switch (task_notification_selection) {
case isci_perform_normal_io_completion:
-
/* Normal notification (task_done) */
- dev_dbg(&host->pdev->dev,
- "%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n",
- __func__,
- task,
- task->task_status.resp, response,
- task->task_status.stat, status);
+
/* Add to the completed list. */
list_add(&request->completed_node,
&host->requests_to_complete);
@@ -2360,13 +2644,6 @@ static void isci_task_save_for_upper_layer_completion(
/* No notification to libsas because this request is
* already in the abort path.
*/
- dev_dbg(&host->pdev->dev,
- "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n",
- __func__,
- task,
- task->task_status.resp, response,
- task->task_status.stat, status);
-
/* Wake up whatever process was waiting for this
* request to complete.
*/
@@ -2383,30 +2660,22 @@ static void isci_task_save_for_upper_layer_completion(
case isci_perform_error_io_completion:
/* Use sas_task_abort */
- dev_dbg(&host->pdev->dev,
- "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n",
- __func__,
- task,
- task->task_status.resp, response,
- task->task_status.stat, status);
/* Add to the aborted list. */
list_add(&request->completed_node,
&host->requests_to_errorback);
break;
default:
- dev_dbg(&host->pdev->dev,
- "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n",
- __func__,
- task,
- task->task_status.resp, response,
- task->task_status.stat, status);
-
/* Add to the error to libsas list. */
list_add(&request->completed_node,
&host->requests_to_errorback);
break;
}
+ dev_dbg(&host->pdev->dev,
+ "%s: %d - task = %p, response=%d (%d), status=%d (%d)\n",
+ __func__, task_notification_selection, task,
+ (task) ? task->task_status.resp : 0, response,
+ (task) ? task->task_status.stat : 0, status);
}
static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_fis *fis)
@@ -2423,6 +2692,8 @@ static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_
*/
if (fis->status & ATA_DF)
ts->stat = SAS_PROTO_RESPONSE;
+ else if (fis->status & ATA_ERR)
+ ts->stat = SAM_STAT_CHECK_CONDITION;
else
ts->stat = SAM_STAT_GOOD;
@@ -2436,9 +2707,9 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
struct sas_task *task = isci_request_access_task(request);
struct ssp_response_iu *resp_iu;
unsigned long task_flags;
- struct isci_remote_device *idev = isci_lookup_device(task->dev);
- enum service_response response = SAS_TASK_UNDELIVERED;
- enum exec_status status = SAS_ABORTED_TASK;
+ struct isci_remote_device *idev = request->target_device;
+ enum service_response response = SAS_TASK_UNDELIVERED;
+ enum exec_status status = SAS_ABORTED_TASK;
enum isci_request_status request_status;
enum isci_completion_selection complete_to_host
= isci_perform_normal_io_completion;
@@ -2769,7 +3040,6 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
/* complete the io request to the core. */
sci_controller_complete_io(ihost, request->target_device, request);
- isci_put_device(idev);
/* set terminated handle so it cannot be completed or
* terminated again, and to cause any calls into abort
@@ -2782,37 +3052,42 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
{
struct isci_request *ireq = container_of(sm, typeof(*ireq), sm);
struct domain_device *dev = ireq->target_device->domain_dev;
+ enum sci_base_request_states state;
struct sas_task *task;
/* XXX as hch said always creating an internal sas_task for tmf
* requests would simplify the driver
*/
- task = ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL;
+ task = (test_bit(IREQ_TMF, &ireq->flags)) ? NULL : isci_request_access_task(ireq);
/* all unaccelerated request types (non ssp or ncq) handled with
* substates
*/
if (!task && dev->dev_type == SAS_END_DEV) {
- sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP);
+ state = SCI_REQ_TASK_WAIT_TC_COMP;
} else if (!task &&
(isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high ||
isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) {
- sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED);
+ state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED;
} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
- sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP);
+ state = SCI_REQ_SMP_WAIT_RESP;
} else if (task && sas_protocol_ata(task->task_proto) &&
!task->ata_task.use_ncq) {
- u32 state;
-
- if (task->data_dir == DMA_NONE)
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
+ task->ata_task.fis.command == ATA_CMD_PACKET) {
+ state = SCI_REQ_ATAPI_WAIT_H2D;
+ } else if (task->data_dir == DMA_NONE) {
state = SCI_REQ_STP_NON_DATA_WAIT_H2D;
- else if (task->ata_task.dma_xfer)
+ } else if (task->ata_task.dma_xfer) {
state = SCI_REQ_STP_UDMA_WAIT_TC_COMP;
- else /* PIO */
+ } else /* PIO */ {
state = SCI_REQ_STP_PIO_WAIT_H2D;
-
- sci_change_state(sm, state);
+ }
+ } else {
+ /* SSP or NCQ are fully accelerated, no substates */
+ return;
}
+ sci_change_state(sm, state);
}
static void sci_request_completed_state_enter(struct sci_base_state_machine *sm)
@@ -2904,6 +3179,10 @@ static const struct sci_base_state sci_request_state_table[] = {
[SCI_REQ_TASK_WAIT_TC_RESP] = { },
[SCI_REQ_SMP_WAIT_RESP] = { },
[SCI_REQ_SMP_WAIT_TC_COMP] = { },
+ [SCI_REQ_ATAPI_WAIT_H2D] = { },
+ [SCI_REQ_ATAPI_WAIT_PIO_SETUP] = { },
+ [SCI_REQ_ATAPI_WAIT_D2H] = { },
+ [SCI_REQ_ATAPI_WAIT_TC_COMP] = { },
[SCI_REQ_COMPLETED] = {
.enter_state = sci_request_completed_state_enter,
},
@@ -3263,7 +3542,7 @@ static struct isci_request *isci_io_request_from_tag(struct isci_host *ihost,
ireq = isci_request_from_tag(ihost, tag);
ireq->ttype_ptr.io_task_ptr = task;
- ireq->ttype = io_task;
+ clear_bit(IREQ_TMF, &ireq->flags);
task->lldd_task = ireq;
return ireq;
@@ -3277,7 +3556,7 @@ struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost,
ireq = isci_request_from_tag(ihost, tag);
ireq->ttype_ptr.tmf_task_ptr = isci_tmf;
- ireq->ttype = tmf_task;
+ set_bit(IREQ_TMF, &ireq->flags);
return ireq;
}
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 58d70b6..be38933 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -77,11 +77,6 @@ enum isci_request_status {
dead = 0x07
};
-enum task_type {
- io_task = 0,
- tmf_task = 1
-};
-
enum sci_request_protocol {
SCIC_NO_PROTOCOL,
SCIC_SMP_PROTOCOL,
@@ -96,7 +91,6 @@ enum sci_request_protocol {
* to wait for another fis or if the transfer is complete. Upon
* receipt of a d2h fis this will be the status field of that fis.
* @sgl - track pio transfer progress as we iterate through the sgl
- * @device_cdb_len - atapi device advertises it's transfer constraints at setup
*/
struct isci_stp_request {
u32 pio_len;
@@ -107,7 +101,6 @@ struct isci_stp_request {
u8 set;
u32 offset;
} sgl;
- u32 device_cdb_len;
};
struct isci_request {
@@ -118,7 +111,6 @@ struct isci_request {
#define IREQ_ACTIVE 3
unsigned long flags;
/* XXX kill ttype and ttype_ptr, allocate full sas_task */
- enum task_type ttype;
union ttype_ptr_union {
struct sas_task *io_task_ptr; /* When ttype==io_task */
struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */
@@ -249,6 +241,32 @@ enum sci_base_request_states {
SCI_REQ_STP_PIO_DATA_OUT,
/*
+ * While in this state the IO request object is waiting for the TC
+ * completion notification for the H2D Register FIS
+ */
+ SCI_REQ_ATAPI_WAIT_H2D,
+
+ /*
+ * While in this state the IO request object is waiting for either a
+ * PIO Setup.
+ */
+ SCI_REQ_ATAPI_WAIT_PIO_SETUP,
+
+ /*
+ * The non-data IO transit to this state in this state after receiving
+ * TC completion. While in this state IO request object is waiting for
+ * D2H status frame as UF.
+ */
+ SCI_REQ_ATAPI_WAIT_D2H,
+
+ /*
+ * When transmitting raw frames hardware reports task context completion
+ * after every frame submission, so in the non-accelerated case we need
+ * to expect the completion for the "cdb" frame.
+ */
+ SCI_REQ_ATAPI_WAIT_TC_COMP,
+
+ /*
* The AWAIT_TC_COMPLETION sub-state indicates that the started raw
* task management request is waiting for the transmission of the
* initial frame (i.e. command, task, etc.).
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index d6bcdd0..e294d11 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -212,16 +212,27 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- /* Indicate QUEUE_FULL so that the scsi
- * midlayer retries. if the request
- * failed for remote device reasons,
- * it gets returned as
- * SAS_TASK_UNDELIVERED next time
- * through.
- */
- isci_task_refuse(ihost, task,
- SAS_TASK_COMPLETE,
- SAS_QUEUE_FULL);
+ if (test_bit(IDEV_GONE, &idev->flags)) {
+
+ /* Indicate that the device
+ * is gone.
+ */
+ isci_task_refuse(ihost, task,
+ SAS_TASK_UNDELIVERED,
+ SAS_DEVICE_UNKNOWN);
+ } else {
+ /* Indicate QUEUE_FULL so that
+ * the scsi midlayer retries.
+ * If the request failed for
+ * remote device reasons, it
+ * gets returned as
+ * SAS_TASK_UNDELIVERED next
+ * time through.
+ */
+ isci_task_refuse(ihost, task,
+ SAS_TASK_COMPLETE,
+ SAS_QUEUE_FULL);
+ }
}
}
}
@@ -243,7 +254,7 @@ static enum sci_status isci_sata_management_task_request_build(struct isci_reque
struct isci_tmf *isci_tmf;
enum sci_status status;
- if (tmf_task != ireq->ttype)
+ if (!test_bit(IREQ_TMF, &ireq->flags))
return SCI_FAILURE;
isci_tmf = isci_request_access_tmf(ireq);
@@ -327,6 +338,60 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
return ireq;
}
+/**
+* isci_request_mark_zombie() - This function must be called with scic_lock held.
+*/
+static void isci_request_mark_zombie(struct isci_host *ihost, struct isci_request *ireq)
+{
+ struct completion *tmf_completion = NULL;
+ struct completion *req_completion;
+
+ /* Set the request state to "dead". */
+ ireq->status = dead;
+
+ req_completion = ireq->io_request_completion;
+ ireq->io_request_completion = NULL;
+
+ if (test_bit(IREQ_TMF, &ireq->flags)) {
+ /* Break links with the TMF request. */
+ struct isci_tmf *tmf = isci_request_access_tmf(ireq);
+
+ /* In the case where a task request is dying,
+ * the thread waiting on the complete will sit and
+ * timeout unless we wake it now. Since the TMF
+ * has a default error status, complete it here
+ * to wake the waiting thread.
+ */
+ if (tmf) {
+ tmf_completion = tmf->complete;
+ tmf->complete = NULL;
+ }
+ ireq->ttype_ptr.tmf_task_ptr = NULL;
+ dev_dbg(&ihost->pdev->dev, "%s: tmf_code %d, managed tag %#x\n",
+ __func__, tmf->tmf_code, tmf->io_tag);
+ } else {
+ /* Break links with the sas_task - the callback is done
+ * elsewhere.
+ */
+ struct sas_task *task = isci_request_access_task(ireq);
+
+ if (task)
+ task->lldd_task = NULL;
+
+ ireq->ttype_ptr.io_task_ptr = NULL;
+ }
+
+ dev_warn(&ihost->pdev->dev, "task context unrecoverable (tag: %#x)\n",
+ ireq->io_tag);
+
+ /* Don't force waiting threads to timeout. */
+ if (req_completion)
+ complete(req_completion);
+
+ if (tmf_completion != NULL)
+ complete(tmf_completion);
+}
+
static int isci_task_execute_tmf(struct isci_host *ihost,
struct isci_remote_device *idev,
struct isci_tmf *tmf, unsigned long timeout_ms)
@@ -364,6 +429,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
/* Assign the pointer to the TMF's completion kernel wait structure. */
tmf->complete = &completion;
+ tmf->status = SCI_FAILURE_TIMEOUT;
ireq = isci_task_request_build(ihost, idev, tag, tmf);
if (!ireq)
@@ -399,18 +465,35 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
msecs_to_jiffies(timeout_ms));
if (timeleft == 0) {
+ /* The TMF did not complete - this could be because
+ * of an unplug. Terminate the TMF request now.
+ */
spin_lock_irqsave(&ihost->scic_lock, flags);
if (tmf->cb_state_func != NULL)
- tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data);
+ tmf->cb_state_func(isci_tmf_timed_out, tmf,
+ tmf->cb_data);
- sci_controller_terminate_request(ihost,
- idev,
- ireq);
+ sci_controller_terminate_request(ihost, idev, ireq);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
- wait_for_completion(tmf->complete);
+ timeleft = wait_for_completion_timeout(
+ &completion,
+ msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
+
+ if (!timeleft) {
+ /* Strange condition - the termination of the TMF
+ * request timed-out.
+ */
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+
+ /* If the TMF status has not changed, kill it. */
+ if (tmf->status == SCI_FAILURE_TIMEOUT)
+ isci_request_mark_zombie(ihost, ireq);
+
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ }
}
isci_print_tmf(tmf);
@@ -501,48 +584,17 @@ static enum isci_request_status isci_task_validate_request_to_abort(
return old_state;
}
-/**
-* isci_request_cleanup_completed_loiterer() - This function will take care of
-* the final cleanup on any request which has been explicitly terminated.
-* @isci_host: This parameter specifies the ISCI host object
-* @isci_device: This is the device to which the request is pending.
-* @isci_request: This parameter specifies the terminated request object.
-* @task: This parameter is the libsas I/O request.
-*/
-static void isci_request_cleanup_completed_loiterer(
- struct isci_host *isci_host,
- struct isci_remote_device *isci_device,
- struct isci_request *isci_request,
- struct sas_task *task)
+static int isci_request_is_dealloc_managed(enum isci_request_status stat)
{
- unsigned long flags;
-
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_device=%p, request=%p, task=%p\n",
- __func__, isci_device, isci_request, task);
-
- if (task != NULL) {
-
- spin_lock_irqsave(&task->task_state_lock, flags);
- task->lldd_task = NULL;
-
- task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
-
- isci_set_task_doneflags(task);
-
- /* If this task is not in the abort path, call task_done. */
- if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-
- spin_unlock_irqrestore(&task->task_state_lock, flags);
- task->task_done(task);
- } else
- spin_unlock_irqrestore(&task->task_state_lock, flags);
- }
-
- if (isci_request != NULL) {
- spin_lock_irqsave(&isci_host->scic_lock, flags);
- list_del_init(&isci_request->dev_node);
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ switch (stat) {
+ case aborted:
+ case aborting:
+ case terminating:
+ case completed:
+ case dead:
+ return true;
+ default:
+ return false;
}
}
@@ -563,11 +615,9 @@ static void isci_terminate_request_core(struct isci_host *ihost,
enum sci_status status = SCI_SUCCESS;
bool was_terminated = false;
bool needs_cleanup_handling = false;
- enum isci_request_status request_status;
unsigned long flags;
unsigned long termination_completed = 1;
struct completion *io_request_completion;
- struct sas_task *task;
dev_dbg(&ihost->pdev->dev,
"%s: device = %p; request = %p\n",
@@ -577,10 +627,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
io_request_completion = isci_request->io_request_completion;
- task = (isci_request->ttype == io_task)
- ? isci_request_access_task(isci_request)
- : NULL;
-
/* Note that we are not going to control
* the target to abort the request.
*/
@@ -619,42 +665,27 @@ static void isci_terminate_request_core(struct isci_host *ihost,
__func__, isci_request, io_request_completion);
/* Wait here for the request to complete. */
- #define TERMINATION_TIMEOUT_MSEC 500
termination_completed
= wait_for_completion_timeout(
io_request_completion,
- msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC));
+ msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
if (!termination_completed) {
/* The request to terminate has timed out. */
- spin_lock_irqsave(&ihost->scic_lock,
- flags);
+ spin_lock_irqsave(&ihost->scic_lock, flags);
/* Check for state changes. */
- if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) {
+ if (!test_bit(IREQ_TERMINATED,
+ &isci_request->flags)) {
/* The best we can do is to have the
* request die a silent death if it
* ever really completes.
- *
- * Set the request state to "dead",
- * and clear the task pointer so that
- * an actual completion event callback
- * doesn't do anything.
*/
- isci_request->status = dead;
- isci_request->io_request_completion
- = NULL;
-
- if (isci_request->ttype == io_task) {
-
- /* Break links with the
- * sas_task.
- */
- isci_request->ttype_ptr.io_task_ptr
- = NULL;
- }
+ isci_request_mark_zombie(ihost,
+ isci_request);
+ needs_cleanup_handling = true;
} else
termination_completed = 1;
@@ -691,29 +722,28 @@ static void isci_terminate_request_core(struct isci_host *ihost,
* needs to be detached and freed here.
*/
spin_lock_irqsave(&isci_request->state_lock, flags);
- request_status = isci_request->status;
-
- if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
- && ((request_status == aborted)
- || (request_status == aborting)
- || (request_status == terminating)
- || (request_status == completed)
- || (request_status == dead)
- )
- ) {
-
- /* The completion routine won't free a request in
- * the aborted/aborting/etc. states, so we do
- * it here.
- */
- needs_cleanup_handling = true;
- }
+
+ needs_cleanup_handling
+ = isci_request_is_dealloc_managed(
+ isci_request->status);
+
spin_unlock_irqrestore(&isci_request->state_lock, flags);
}
- if (needs_cleanup_handling)
- isci_request_cleanup_completed_loiterer(
- ihost, idev, isci_request, task);
+ if (needs_cleanup_handling) {
+
+ dev_dbg(&ihost->pdev->dev,
+ "%s: cleanup isci_device=%p, request=%p\n",
+ __func__, idev, isci_request);
+
+ if (isci_request != NULL) {
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ isci_free_tag(ihost, isci_request->io_tag);
+ isci_request_change_state(isci_request, unallocated);
+ list_del_init(&isci_request->dev_node);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ }
+ }
}
}
@@ -772,7 +802,9 @@ void isci_terminate_pending_requests(struct isci_host *ihost,
dev_dbg(&ihost->pdev->dev,
"%s: idev=%p request=%p; task=%p old_state=%d\n",
__func__, idev, ireq,
- ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL,
+ (!test_bit(IREQ_TMF, &ireq->flags)
+ ? isci_request_access_task(ireq)
+ : NULL),
old_state);
/* If the old_state is started:
@@ -889,22 +921,14 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun)
"%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
__func__, domain_device, isci_host, isci_device);
- if (isci_device)
- set_bit(IDEV_EH, &isci_device->flags);
+ if (!isci_device) {
+ /* If the device is gone, stop the escalations. */
+ dev_dbg(&isci_host->pdev->dev, "%s: No dev\n", __func__);
- /* If there is a device reset pending on any request in the
- * device's list, fail this LUN reset request in order to
- * escalate to the device reset.
- */
- if (!isci_device ||
- isci_device_is_reset_pending(isci_host, isci_device)) {
- dev_dbg(&isci_host->pdev->dev,
- "%s: No dev (%p), or "
- "RESET PENDING: domain_device=%p\n",
- __func__, isci_device, domain_device);
- ret = TMF_RESP_FUNC_FAILED;
+ ret = TMF_RESP_FUNC_COMPLETE;
goto out;
}
+ set_bit(IDEV_EH, &isci_device->flags);
/* Send the task management part of the reset. */
if (sas_protocol_ata(domain_device->tproto)) {
@@ -1013,7 +1037,8 @@ int isci_task_abort_task(struct sas_task *task)
struct isci_tmf tmf;
int ret = TMF_RESP_FUNC_FAILED;
unsigned long flags;
- bool any_dev_reset = false;
+ int perform_termination = 0;
+ int target_done_already = 0;
/* Get the isci_request reference from the task. Note that
* this check does not depend on the pending request list
@@ -1028,96 +1053,43 @@ int isci_task_abort_task(struct sas_task *task)
/* If task is already done, the request isn't valid */
if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
(task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
- old_request)
+ old_request) {
isci_device = isci_lookup_device(task->dev);
-
+ target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET,
+ &old_request->flags);
+ }
spin_unlock(&task->task_state_lock);
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
dev_dbg(&isci_host->pdev->dev,
- "%s: task = %p\n", __func__, task);
-
- if (!isci_device || !old_request)
- goto out;
-
- set_bit(IDEV_EH, &isci_device->flags);
-
- /* This version of the driver will fail abort requests for
- * SATA/STP. Failing the abort request this way will cause the
- * SCSI error handler thread to escalate to LUN reset
- */
- if (sas_protocol_ata(task->task_proto)) {
- dev_dbg(&isci_host->pdev->dev,
- " task %p is for a STP/SATA device;"
- " returning TMF_RESP_FUNC_FAILED\n"
- " to cause a LUN reset...\n", task);
- goto out;
- }
-
- dev_dbg(&isci_host->pdev->dev,
- "%s: old_request == %p\n", __func__, old_request);
+ "%s: dev = %p, task = %p, old_request == %p\n",
+ __func__, isci_device, task, old_request);
- any_dev_reset = isci_device_is_reset_pending(isci_host, isci_device);
-
- spin_lock_irqsave(&task->task_state_lock, flags);
-
- any_dev_reset = any_dev_reset || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET);
+ if (isci_device)
+ set_bit(IDEV_EH, &isci_device->flags);
- /* If the extraction of the request reference from the task
- * failed, then the request has been completed (or if there is a
- * pending reset then this abort request function must be failed
- * in order to escalate to the target reset).
+ /* Device reset conditions signalled in task_state_flags are the
+ * responsbility of libsas to observe at the start of the error
+ * handler thread.
*/
- if ((old_request == NULL) || any_dev_reset) {
-
- /* If the device reset task flag is set, fail the task
- * management request. Otherwise, the original request
- * has completed.
- */
- if (any_dev_reset) {
-
- /* Turn off the task's DONE to make sure this
- * task is escalated to a target reset.
- */
- task->task_state_flags &= ~SAS_TASK_STATE_DONE;
-
- /* Make the reset happen as soon as possible. */
- task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
-
- spin_unlock_irqrestore(&task->task_state_lock, flags);
-
- /* Fail the task management request in order to
- * escalate to the target reset.
- */
- ret = TMF_RESP_FUNC_FAILED;
-
- dev_dbg(&isci_host->pdev->dev,
- "%s: Failing task abort in order to "
- "escalate to target reset because\n"
- "SAS_TASK_NEED_DEV_RESET is set for "
- "task %p on dev %p\n",
- __func__, task, isci_device);
-
-
- } else {
- /* The request has already completed and there
- * is nothing to do here other than to set the task
- * done bit, and indicate that the task abort function
- * was sucessful.
- */
- isci_set_task_doneflags(task);
-
- spin_unlock_irqrestore(&task->task_state_lock, flags);
+ if (!isci_device || !old_request) {
+ /* The request has already completed and there
+ * is nothing to do here other than to set the task
+ * done bit, and indicate that the task abort function
+ * was sucessful.
+ */
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
- ret = TMF_RESP_FUNC_COMPLETE;
+ ret = TMF_RESP_FUNC_COMPLETE;
- dev_dbg(&isci_host->pdev->dev,
- "%s: abort task not needed for %p\n",
- __func__, task);
- }
+ dev_dbg(&isci_host->pdev->dev,
+ "%s: abort task not needed for %p\n",
+ __func__, task);
goto out;
- } else {
- spin_unlock_irqrestore(&task->task_state_lock, flags);
}
spin_lock_irqsave(&isci_host->scic_lock, flags);
@@ -1146,24 +1118,44 @@ int isci_task_abort_task(struct sas_task *task)
goto out;
}
if (task->task_proto == SAS_PROTOCOL_SMP ||
- test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
+ sas_protocol_ata(task->task_proto) ||
+ target_done_already) {
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
dev_dbg(&isci_host->pdev->dev,
- "%s: SMP request (%d)"
+ "%s: %s request"
" or complete_in_target (%d), thus no TMF\n",
- __func__, (task->task_proto == SAS_PROTOCOL_SMP),
+ __func__,
+ ((task->task_proto == SAS_PROTOCOL_SMP)
+ ? "SMP"
+ : (sas_protocol_ata(task->task_proto)
+ ? "SATA/STP"
+ : "<other>")
+ ),
test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags));
- /* Set the state on the task. */
- isci_task_all_done(task);
-
- ret = TMF_RESP_FUNC_COMPLETE;
+ if (test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ ret = TMF_RESP_FUNC_COMPLETE;
+ } else {
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ }
- /* Stopping and SMP devices are not sent a TMF, and are not
- * reset, but the outstanding I/O request is terminated below.
+ /* STP and SMP devices are not sent a TMF, but the
+ * outstanding I/O request is terminated below. This is
+ * because SATA/STP and SMP discovery path timeouts directly
+ * call the abort task interface for cleanup.
*/
+ perform_termination = 1;
+
} else {
/* Fill in the tmf stucture */
isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
@@ -1172,22 +1164,24 @@ int isci_task_abort_task(struct sas_task *task)
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
- #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */
+ #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
ret = isci_task_execute_tmf(isci_host, isci_device, &tmf,
ISCI_ABORT_TASK_TIMEOUT_MS);
- if (ret != TMF_RESP_FUNC_COMPLETE)
+ if (ret == TMF_RESP_FUNC_COMPLETE)
+ perform_termination = 1;
+ else
dev_dbg(&isci_host->pdev->dev,
- "%s: isci_task_send_tmf failed\n",
- __func__);
+ "%s: isci_task_send_tmf failed\n", __func__);
}
- if (ret == TMF_RESP_FUNC_COMPLETE) {
+ if (perform_termination) {
set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags);
/* Clean up the request on our side, and wait for the aborted
* I/O to complete.
*/
- isci_terminate_request_core(isci_host, isci_device, old_request);
+ isci_terminate_request_core(isci_host, isci_device,
+ old_request);
}
/* Make sure we do not leave a reference to aborted_io_completion */
@@ -1288,7 +1282,8 @@ isci_task_request_complete(struct isci_host *ihost,
enum sci_task_status completion_status)
{
struct isci_tmf *tmf = isci_request_access_tmf(ireq);
- struct completion *tmf_complete;
+ struct completion *tmf_complete = NULL;
+ struct completion *request_complete = ireq->io_request_completion;
dev_dbg(&ihost->pdev->dev,
"%s: request = %p, status=%d\n",
@@ -1296,278 +1291,53 @@ isci_task_request_complete(struct isci_host *ihost,
isci_request_change_state(ireq, completed);
- tmf->status = completion_status;
set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags);
- if (tmf->proto == SAS_PROTOCOL_SSP) {
- memcpy(&tmf->resp.resp_iu,
- &ireq->ssp.rsp,
- SSP_RESP_IU_MAX_SIZE);
- } else if (tmf->proto == SAS_PROTOCOL_SATA) {
- memcpy(&tmf->resp.d2h_fis,
- &ireq->stp.rsp,
- sizeof(struct dev_to_host_fis));
+ if (tmf) {
+ tmf->status = completion_status;
+
+ if (tmf->proto == SAS_PROTOCOL_SSP) {
+ memcpy(&tmf->resp.resp_iu,
+ &ireq->ssp.rsp,
+ SSP_RESP_IU_MAX_SIZE);
+ } else if (tmf->proto == SAS_PROTOCOL_SATA) {
+ memcpy(&tmf->resp.d2h_fis,
+ &ireq->stp.rsp,
+ sizeof(struct dev_to_host_fis));
+ }
+ /* PRINT_TMF( ((struct isci_tmf *)request->task)); */
+ tmf_complete = tmf->complete;
}
-
- /* PRINT_TMF( ((struct isci_tmf *)request->task)); */
- tmf_complete = tmf->complete;
-
sci_controller_complete_io(ihost, ireq->target_device, ireq);
/* set the 'terminated' flag handle to make sure it cannot be terminated
* or completed again.
*/
set_bit(IREQ_TERMINATED, &ireq->flags);
- isci_request_change_state(ireq, unallocated);
- list_del_init(&ireq->dev_node);
-
- /* The task management part completes last. */
- complete(tmf_complete);
-}
-
-static void isci_smp_task_timedout(unsigned long _task)
-{
- struct sas_task *task = (void *) _task;
- unsigned long flags;
-
- spin_lock_irqsave(&task->task_state_lock, flags);
- if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
- task->task_state_flags |= SAS_TASK_STATE_ABORTED;
- spin_unlock_irqrestore(&task->task_state_lock, flags);
-
- complete(&task->completion);
-}
-
-static void isci_smp_task_done(struct sas_task *task)
-{
- if (!del_timer(&task->timer))
- return;
- complete(&task->completion);
-}
-
-static struct sas_task *isci_alloc_task(void)
-{
- struct sas_task *task = kzalloc(sizeof(*task), GFP_KERNEL);
-
- if (task) {
- INIT_LIST_HEAD(&task->list);
- spin_lock_init(&task->task_state_lock);
- task->task_state_flags = SAS_TASK_STATE_PENDING;
- init_timer(&task->timer);
- init_completion(&task->completion);
- }
-
- return task;
-}
-
-static void isci_free_task(struct isci_host *ihost, struct sas_task *task)
-{
- if (task) {
- BUG_ON(!list_empty(&task->list));
- kfree(task);
- }
-}
-
-static int isci_smp_execute_task(struct isci_host *ihost,
- struct domain_device *dev, void *req,
- int req_size, void *resp, int resp_size)
-{
- int res, retry;
- struct sas_task *task = NULL;
-
- for (retry = 0; retry < 3; retry++) {
- task = isci_alloc_task();
- if (!task)
- return -ENOMEM;
-
- task->dev = dev;
- task->task_proto = dev->tproto;
- sg_init_one(&task->smp_task.smp_req, req, req_size);
- sg_init_one(&task->smp_task.smp_resp, resp, resp_size);
-
- task->task_done = isci_smp_task_done;
-
- task->timer.data = (unsigned long) task;
- task->timer.function = isci_smp_task_timedout;
- task->timer.expires = jiffies + 10*HZ;
- add_timer(&task->timer);
-
- res = isci_task_execute_task(task, 1, GFP_KERNEL);
-
- if (res) {
- del_timer(&task->timer);
- dev_dbg(&ihost->pdev->dev,
- "%s: executing SMP task failed:%d\n",
- __func__, res);
- goto ex_err;
- }
-
- wait_for_completion(&task->completion);
- res = -ECOMM;
- if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
- dev_dbg(&ihost->pdev->dev,
- "%s: smp task timed out or aborted\n",
- __func__);
- isci_task_abort_task(task);
- if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
- dev_dbg(&ihost->pdev->dev,
- "%s: SMP task aborted and not done\n",
- __func__);
- goto ex_err;
- }
- }
- if (task->task_status.resp == SAS_TASK_COMPLETE &&
- task->task_status.stat == SAM_STAT_GOOD) {
- res = 0;
- break;
- }
- if (task->task_status.resp == SAS_TASK_COMPLETE &&
- task->task_status.stat == SAS_DATA_UNDERRUN) {
- /* no error, but return the number of bytes of
- * underrun */
- res = task->task_status.residual;
- break;
- }
- if (task->task_status.resp == SAS_TASK_COMPLETE &&
- task->task_status.stat == SAS_DATA_OVERRUN) {
- res = -EMSGSIZE;
- break;
- } else {
- dev_dbg(&ihost->pdev->dev,
- "%s: task to dev %016llx response: 0x%x "
- "status 0x%x\n", __func__,
- SAS_ADDR(dev->sas_addr),
- task->task_status.resp,
- task->task_status.stat);
- isci_free_task(ihost, task);
- task = NULL;
- }
- }
-ex_err:
- BUG_ON(retry == 3 && task != NULL);
- isci_free_task(ihost, task);
- return res;
-}
-
-#define DISCOVER_REQ_SIZE 16
-#define DISCOVER_RESP_SIZE 56
-
-int isci_smp_get_phy_attached_dev_type(struct isci_host *ihost,
- struct domain_device *dev,
- int phy_id, int *adt)
-{
- struct smp_resp *disc_resp;
- u8 *disc_req;
- int res;
-
- disc_resp = kzalloc(DISCOVER_RESP_SIZE, GFP_KERNEL);
- if (!disc_resp)
- return -ENOMEM;
-
- disc_req = kzalloc(DISCOVER_REQ_SIZE, GFP_KERNEL);
- if (disc_req) {
- disc_req[0] = SMP_REQUEST;
- disc_req[1] = SMP_DISCOVER;
- disc_req[9] = phy_id;
- } else {
- kfree(disc_resp);
- return -ENOMEM;
- }
- res = isci_smp_execute_task(ihost, dev, disc_req, DISCOVER_REQ_SIZE,
- disc_resp, DISCOVER_RESP_SIZE);
- if (!res) {
- if (disc_resp->result != SMP_RESP_FUNC_ACC)
- res = disc_resp->result;
- else
- *adt = disc_resp->disc.attached_dev_type;
+ /* As soon as something is in the terminate path, deallocation is
+ * managed there. Note that the final non-managed state of a task
+ * request is "completed".
+ */
+ if ((ireq->status == completed) ||
+ !isci_request_is_dealloc_managed(ireq->status)) {
+ isci_request_change_state(ireq, unallocated);
+ isci_free_tag(ihost, ireq->io_tag);
+ list_del_init(&ireq->dev_node);
}
- kfree(disc_req);
- kfree(disc_resp);
-
- return res;
-}
-static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy_num)
-{
- struct domain_device *dev = idev->domain_dev;
- struct isci_port *iport = idev->isci_port;
- struct isci_host *ihost = iport->isci_host;
- int res, iteration = 0, attached_device_type;
- #define STP_WAIT_MSECS 25000
- unsigned long tmo = msecs_to_jiffies(STP_WAIT_MSECS);
- unsigned long deadline = jiffies + tmo;
- enum {
- SMP_PHYWAIT_PHYDOWN,
- SMP_PHYWAIT_PHYUP,
- SMP_PHYWAIT_DONE
- } phy_state = SMP_PHYWAIT_PHYDOWN;
-
- /* While there is time, wait for the phy to go away and come back */
- while (time_is_after_jiffies(deadline) && phy_state != SMP_PHYWAIT_DONE) {
- int event = atomic_read(&iport->event);
-
- ++iteration;
-
- tmo = wait_event_timeout(ihost->eventq,
- event != atomic_read(&iport->event) ||
- !test_bit(IPORT_BCN_BLOCKED, &iport->flags),
- tmo);
- /* link down, stop polling */
- if (!test_bit(IPORT_BCN_BLOCKED, &iport->flags))
- break;
+ /* "request_complete" is set if the task was being terminated. */
+ if (request_complete)
+ complete(request_complete);
- dev_dbg(&ihost->pdev->dev,
- "%s: iport %p, iteration %d,"
- " phase %d: time_remaining %lu, bcns = %d\n",
- __func__, iport, iteration, phy_state,
- tmo, test_bit(IPORT_BCN_PENDING, &iport->flags));
-
- res = isci_smp_get_phy_attached_dev_type(ihost, dev, phy_num,
- &attached_device_type);
- tmo = deadline - jiffies;
-
- if (res) {
- dev_dbg(&ihost->pdev->dev,
- "%s: iteration %d, phase %d:"
- " SMP error=%d, time_remaining=%lu\n",
- __func__, iteration, phy_state, res, tmo);
- break;
- }
- dev_dbg(&ihost->pdev->dev,
- "%s: iport %p, iteration %d,"
- " phase %d: time_remaining %lu, bcns = %d, "
- "attdevtype = %x\n",
- __func__, iport, iteration, phy_state,
- tmo, test_bit(IPORT_BCN_PENDING, &iport->flags),
- attached_device_type);
-
- switch (phy_state) {
- case SMP_PHYWAIT_PHYDOWN:
- /* Has the device gone away? */
- if (!attached_device_type)
- phy_state = SMP_PHYWAIT_PHYUP;
-
- break;
-
- case SMP_PHYWAIT_PHYUP:
- /* Has the device come back? */
- if (attached_device_type)
- phy_state = SMP_PHYWAIT_DONE;
- break;
-
- case SMP_PHYWAIT_DONE:
- break;
- }
-
- }
- dev_dbg(&ihost->pdev->dev, "%s: done\n", __func__);
+ /* The task management part completes last. */
+ if (tmf_complete)
+ complete(tmf_complete);
}
static int isci_reset_device(struct isci_host *ihost,
struct isci_remote_device *idev)
{
struct sas_phy *phy = sas_find_local_phy(idev->domain_dev);
- struct isci_port *iport = idev->isci_port;
enum sci_status status;
unsigned long flags;
int rc;
@@ -1587,13 +1357,6 @@ static int isci_reset_device(struct isci_host *ihost,
}
spin_unlock_irqrestore(&ihost->scic_lock, flags);
- /* Make sure all pending requests are able to be fully terminated. */
- isci_device_clear_reset_pending(ihost, idev);
-
- /* If this is a device on an expander, disable BCN processing. */
- if (!scsi_is_sas_phy_local(phy))
- set_bit(IPORT_BCN_BLOCKED, &iport->flags);
-
rc = sas_phy_reset(phy, true);
/* Terminate in-progress I/O now. */
@@ -1604,21 +1367,6 @@ static int isci_reset_device(struct isci_host *ihost,
status = sci_remote_device_reset_complete(idev);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
- /* If this is a device on an expander, bring the phy back up. */
- if (!scsi_is_sas_phy_local(phy)) {
- /* A phy reset will cause the device to go away then reappear.
- * Since libsas will take action on incoming BCNs (eg. remove
- * a device going through an SMP phy-control driven reset),
- * we need to wait until the phy comes back up before letting
- * discovery proceed in libsas.
- */
- isci_wait_for_smp_phy_reset(idev, phy->number);
-
- spin_lock_irqsave(&ihost->scic_lock, flags);
- isci_port_bcn_enable(ihost, idev->isci_port);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
- }
-
if (status != SCI_SUCCESS) {
dev_dbg(&ihost->pdev->dev,
"%s: sci_remote_device_reset_complete(%p) "
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index 4a7fa90..bc78c0a 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -58,6 +58,8 @@
#include <scsi/sas_ata.h>
#include "host.h"
+#define ISCI_TERMINATION_TIMEOUT_MSEC 500
+
struct isci_request;
/**
@@ -224,35 +226,6 @@ enum isci_completion_selection {
isci_perform_error_io_completion /* Use sas_task_abort */
};
-static inline void isci_set_task_doneflags(
- struct sas_task *task)
-{
- /* Since no futher action will be taken on this task,
- * make sure to mark it complete from the lldd perspective.
- */
- task->task_state_flags |= SAS_TASK_STATE_DONE;
- task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
- task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
-}
-/**
- * isci_task_all_done() - This function clears the task bits to indicate the
- * LLDD is done with the task.
- *
- *
- */
-static inline void isci_task_all_done(
- struct sas_task *task)
-{
- unsigned long flags;
-
- /* Since no futher action will be taken on this task,
- * make sure to mark it complete from the lldd perspective.
- */
- spin_lock_irqsave(&task->task_state_lock, flags);
- isci_set_task_doneflags(task);
- spin_unlock_irqrestore(&task->task_state_lock, flags);
-}
-
/**
* isci_task_set_completion_status() - This function sets the completion status
* for the request.
@@ -286,6 +259,25 @@ isci_task_set_completion_status(
task->task_status.resp = response;
task->task_status.stat = status;
+ switch (task->task_proto) {
+
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+
+ if (task_notification_selection
+ == isci_perform_error_io_completion) {
+ /* SATA/STP I/O has it's own means of scheduling device
+ * error handling on the normal path.
+ */
+ task_notification_selection
+ = isci_perform_normal_io_completion;
+ }
+ break;
+ default:
+ break;
+ }
+
switch (task_notification_selection) {
case isci_perform_error_io_completion:
@@ -315,7 +307,9 @@ isci_task_set_completion_status(
/* Fall through to the normal case... */
case isci_perform_normal_io_completion:
/* Normal notification (task_done) */
- isci_set_task_doneflags(task);
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
break;
default:
WARN_ONCE(1, "unknown task_notification_selection: %d\n",
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index b9cb814..7269e92 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -35,6 +35,7 @@
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <asm/unaligned.h>
#include <scsi/fc/fc_gs.h>
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index 9b25969..fb9161d 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -21,6 +21,7 @@
* Provide interface to send ELS/CT FC frames
*/
+#include <linux/export.h>
#include <asm/unaligned.h>
#include <scsi/fc/fc_gs.h>
#include <scsi/fc/fc_ns.h>
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 3b8a645..9de9db2 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -26,6 +26,7 @@
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <scsi/fc/fc_fc2.h>
@@ -65,16 +66,15 @@ static struct workqueue_struct *fc_exch_workqueue;
* assigned range of exchanges to per cpu pool.
*/
struct fc_exch_pool {
+ spinlock_t lock;
+ struct list_head ex_list;
u16 next_index;
u16 total_exches;
/* two cache of free slot in exch array */
u16 left;
u16 right;
-
- spinlock_t lock;
- struct list_head ex_list;
-};
+} ____cacheline_aligned_in_smp;
/**
* struct fc_exch_mgr - The Exchange Manager (EM).
@@ -91,13 +91,13 @@ struct fc_exch_pool {
* It manages the allocation of exchange IDs.
*/
struct fc_exch_mgr {
+ struct fc_exch_pool *pool;
+ mempool_t *ep_pool;
enum fc_class class;
struct kref kref;
u16 min_xid;
u16 max_xid;
- mempool_t *ep_pool;
u16 pool_max_index;
- struct fc_exch_pool *pool;
/*
* currently exchange mgr stats are updated but not used.
@@ -470,6 +470,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
struct fc_frame_header *fh = fc_frame_header_get(fp);
int error;
u32 f_ctl;
+ u8 fh_type = fh->fh_type;
ep = fc_seq_exch(sp);
WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT);
@@ -494,6 +495,9 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
*/
error = lport->tt.frame_send(lport, fp);
+ if (fh_type == FC_TYPE_BLS)
+ return error;
+
/*
* Update the exchange and sequence flags,
* assuming all frames for the sequence have been sent.
@@ -575,42 +579,35 @@ static void fc_seq_set_resp(struct fc_seq *sp,
}
/**
- * fc_seq_exch_abort() - Abort an exchange and sequence
- * @req_sp: The sequence to be aborted
+ * fc_exch_abort_locked() - Abort an exchange
+ * @ep: The exchange to be aborted
* @timer_msec: The period of time to wait before aborting
*
- * Generally called because of a timeout or an abort from the upper layer.
+ * Locking notes: Called with exch lock held
+ *
+ * Return value: 0 on success else error code
*/
-static int fc_seq_exch_abort(const struct fc_seq *req_sp,
- unsigned int timer_msec)
+static int fc_exch_abort_locked(struct fc_exch *ep,
+ unsigned int timer_msec)
{
struct fc_seq *sp;
- struct fc_exch *ep;
struct fc_frame *fp;
int error;
- ep = fc_seq_exch(req_sp);
-
- spin_lock_bh(&ep->ex_lock);
if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) ||
- ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) {
- spin_unlock_bh(&ep->ex_lock);
+ ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP))
return -ENXIO;
- }
/*
* Send the abort on a new sequence if possible.
*/
sp = fc_seq_start_next_locked(&ep->seq);
- if (!sp) {
- spin_unlock_bh(&ep->ex_lock);
+ if (!sp)
return -ENOMEM;
- }
ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL;
if (timer_msec)
fc_exch_timer_set_locked(ep, timer_msec);
- spin_unlock_bh(&ep->ex_lock);
/*
* If not logged into the fabric, don't send ABTS but leave
@@ -633,6 +630,28 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp,
}
/**
+ * fc_seq_exch_abort() - Abort an exchange and sequence
+ * @req_sp: The sequence to be aborted
+ * @timer_msec: The period of time to wait before aborting
+ *
+ * Generally called because of a timeout or an abort from the upper layer.
+ *
+ * Return value: 0 on success else error code
+ */
+static int fc_seq_exch_abort(const struct fc_seq *req_sp,
+ unsigned int timer_msec)
+{
+ struct fc_exch *ep;
+ int error;
+
+ ep = fc_seq_exch(req_sp);
+ spin_lock_bh(&ep->ex_lock);
+ error = fc_exch_abort_locked(ep, timer_msec);
+ spin_unlock_bh(&ep->ex_lock);
+ return error;
+}
+
+/**
* fc_exch_timeout() - Handle exchange timer expiration
* @work: The work_struct identifying the exchange that timed out
*/
@@ -802,10 +821,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask);
spin_lock_bh(&pool->lock);
ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
- if (ep) {
+ if (ep && ep->xid == xid)
fc_exch_hold(ep);
- WARN_ON(ep->xid != xid);
- }
spin_unlock_bh(&pool->lock);
}
return ep;
@@ -965,8 +982,30 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
sp = &ep->seq;
if (sp->id != fh->fh_seq_id) {
atomic_inc(&mp->stats.seq_not_found);
- reject = FC_RJT_SEQ_ID; /* sequence/exch should exist */
- goto rel;
+ if (f_ctl & FC_FC_END_SEQ) {
+ /*
+ * Update sequence_id based on incoming last
+ * frame of sequence exchange. This is needed
+ * for FCoE target where DDP has been used
+ * on target where, stack is indicated only
+ * about last frame's (payload _header) header.
+ * Whereas "seq_id" which is part of
+ * frame_header is allocated by initiator
+ * which is totally different from "seq_id"
+ * allocated when XFER_RDY was sent by target.
+ * To avoid false -ve which results into not
+ * sending RSP, hence write request on other
+ * end never finishes.
+ */
+ spin_lock_bh(&ep->ex_lock);
+ sp->ssb_stat |= SSB_ST_RESP;
+ sp->id = fh->fh_seq_id;
+ spin_unlock_bh(&ep->ex_lock);
+ } else {
+ /* sequence/exch should exist */
+ reject = FC_RJT_SEQ_ID;
+ goto rel;
+ }
}
}
WARN_ON(ep != fc_seq_exch(sp));
@@ -1695,6 +1734,7 @@ static void fc_exch_reset(struct fc_exch *ep)
int rc = 1;
spin_lock_bh(&ep->ex_lock);
+ fc_exch_abort_locked(ep, 0);
ep->state |= FC_EX_RST_CLEANUP;
if (cancel_delayed_work(&ep->timeout_work))
atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
@@ -1754,6 +1794,9 @@ restart:
goto restart;
}
}
+ pool->next_index = 0;
+ pool->left = FC_XID_UNKNOWN;
+ pool->right = FC_XID_UNKNOWN;
spin_unlock_bh(&pool->lock);
}
@@ -1942,6 +1985,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
struct fc_exch *ep;
struct fc_seq *sp = NULL;
struct fc_frame_header *fh;
+ struct fc_fcp_pkt *fsp = NULL;
int rc = 1;
ep = fc_exch_alloc(lport, fp);
@@ -1964,8 +2008,10 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
fc_exch_setup_hdr(ep, fp, ep->f_ctl);
sp->cnt++;
- if (ep->xid <= lport->lro_xid && fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD)
+ if (ep->xid <= lport->lro_xid && fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD) {
+ fsp = fr_fsp(fp);
fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
+ }
if (unlikely(lport->tt.frame_send(lport, fp)))
goto err;
@@ -1979,7 +2025,8 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
spin_unlock_bh(&ep->ex_lock);
return sp;
err:
- fc_fcp_ddp_done(fr_fsp(fp));
+ if (fsp)
+ fc_fcp_ddp_done(fsp);
rc = fc_exch_done_locked(ep);
spin_unlock_bh(&ep->ex_lock);
if (!rc)
@@ -2238,6 +2285,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
goto free_mempool;
for_each_possible_cpu(cpu) {
pool = per_cpu_ptr(mp->pool, cpu);
+ pool->next_index = 0;
pool->left = FC_XID_UNKNOWN;
pool->right = FC_XID_UNKNOWN;
spin_lock_init(&pool->lock);
@@ -2443,8 +2491,11 @@ int fc_setup_exch_mgr(void)
fc_exch_workqueue = create_singlethread_workqueue("fc_exch_workqueue");
if (!fc_exch_workqueue)
- return -ENOMEM;
+ goto err;
return 0;
+err:
+ kmem_cache_destroy(fc_em_cachep);
+ return -ENOMEM;
}
/**
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 9cd2149..735b324 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -498,7 +498,7 @@ crc_err:
stats = per_cpu_ptr(lport->dev_stats, get_cpu());
stats->ErrorFrames++;
/* per cpu count, not total count, but OK for limit */
- if (stats->InvalidCRCCount++ < 5)
+ if (stats->InvalidCRCCount++ < FC_MAX_ERROR_CNT)
printk(KERN_WARNING "libfc: CRC error on data "
"frame for port (%6.6x)\n",
lport->port_id);
@@ -690,7 +690,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
}
/**
- * fc_fcp_abts_resp() - Send an ABTS response
+ * fc_fcp_abts_resp() - Receive an ABTS response
* @fsp: The FCP packet that is being aborted
* @fp: The response frame
*/
@@ -730,7 +730,7 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
}
/**
- * fc_fcp_recv() - Reveive an FCP frame
+ * fc_fcp_recv() - Receive an FCP frame
* @seq: The sequence the frame is on
* @fp: The received frame
* @arg: The related FCP packet
@@ -759,7 +759,6 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
goto out;
if (fc_fcp_lock_pkt(fsp))
goto out;
- fsp->last_pkt_time = jiffies;
if (fh->fh_type == FC_TYPE_BLS) {
fc_fcp_abts_resp(fsp, fp);
@@ -1030,11 +1029,26 @@ restart:
fc_fcp_pkt_hold(fsp);
spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
- if (!fc_fcp_lock_pkt(fsp)) {
+ spin_lock_bh(&fsp->scsi_pkt_lock);
+ if (!(fsp->state & FC_SRB_COMPL)) {
+ fsp->state |= FC_SRB_COMPL;
+ /*
+ * TODO: dropping scsi_pkt_lock and then reacquiring
+ * again around fc_fcp_cleanup_cmd() is required,
+ * since fc_fcp_cleanup_cmd() calls into
+ * fc_seq_set_resp() and that func preempts cpu using
+ * schedule. May be schedule and related code should be
+ * removed instead of unlocking here to avoid scheduling
+ * while atomic bug.
+ */
+ spin_unlock_bh(&fsp->scsi_pkt_lock);
+
fc_fcp_cleanup_cmd(fsp, error);
+
+ spin_lock_bh(&fsp->scsi_pkt_lock);
fc_io_compl(fsp);
- fc_fcp_unlock_pkt(fsp);
}
+ spin_unlock_bh(&fsp->scsi_pkt_lock);
fc_fcp_pkt_release(fsp);
spin_lock_irqsave(&si->scsi_queue_lock, flags);
@@ -1084,6 +1098,7 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv);
if (unlikely(rc)) {
spin_lock_irqsave(&si->scsi_queue_lock, flags);
+ fsp->cmd->SCp.ptr = NULL;
list_del(&fsp->list);
spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
}
@@ -1147,7 +1162,6 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
rc = -1;
goto unlock;
}
- fsp->last_pkt_time = jiffies;
fsp->seq_ptr = seq;
fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
@@ -1645,12 +1659,10 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
struct fc_seq *seq;
struct fcp_srr *srr;
struct fc_frame *fp;
- u8 cdb_op;
unsigned int rec_tov;
rport = fsp->rport;
rpriv = rport->dd_data;
- cdb_op = fsp->cdb_cmd.fc_cdb[0];
if (!(rpriv->flags & FC_RP_FLAGS_RETRY) ||
rpriv->rp_state != RPORT_ST_READY)
@@ -2020,6 +2032,11 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
struct fc_fcp_internal *si;
int rc = FAILED;
unsigned long flags;
+ int rval;
+
+ rval = fc_block_scsi_eh(sc_cmd);
+ if (rval)
+ return rval;
lport = shost_priv(sc_cmd->device->host);
if (lport->state != LPORT_ST_READY)
@@ -2069,9 +2086,9 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
int rc = FAILED;
int rval;
- rval = fc_remote_port_chkready(rport);
+ rval = fc_block_scsi_eh(sc_cmd);
if (rval)
- goto out;
+ return rval;
lport = shost_priv(sc_cmd->device->host);
@@ -2117,6 +2134,8 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
FC_SCSI_DBG(lport, "Resetting host\n");
+ fc_block_scsi_eh(sc_cmd);
+
lport->tt.lport_reset(lport);
wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT;
while (!fc_fcp_lport_queue_ready(lport) && time_before(jiffies,
diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c
index b773512..1bf9841 100644
--- a/drivers/scsi/libfc/fc_libfc.c
+++ b/drivers/scsi/libfc/fc_libfc.c
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/scatterlist.h>
#include <linux/crc32.h>
+#include <linux/module.h>
#include <scsi/libfc.h>
#include <scsi/fc_encode.h>
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 389ab80..e77094a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -88,6 +88,8 @@
*/
#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
@@ -1025,6 +1027,8 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);
}
fc_lport_state_enter(lport, LPORT_ST_RESET);
+ fc_host_post_event(lport->host, fc_get_event_number(),
+ FCH_EVT_LIPRESET, 0);
fc_vports_linkchange(lport);
fc_lport_reset_locked(lport);
if (lport->link_up)
@@ -1350,7 +1354,6 @@ static void fc_lport_timeout(struct work_struct *work)
WARN_ON(1);
break;
case LPORT_ST_READY:
- WARN_ON(1);
break;
case LPORT_ST_RESET:
break;
@@ -1471,6 +1474,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
void *lp_arg)
{
struct fc_lport *lport = lp_arg;
+ struct fc_frame_header *fh;
struct fc_els_flogi *flp;
u32 did;
u16 csp_flags;
@@ -1498,49 +1502,56 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
goto err;
}
+ fh = fc_frame_header_get(fp);
did = fc_frame_did(fp);
- if (fc_frame_payload_op(fp) == ELS_LS_ACC && did) {
- flp = fc_frame_payload_get(fp, sizeof(*flp));
- if (flp) {
- mfs = ntohs(flp->fl_csp.sp_bb_data) &
- FC_SP_BB_DATA_MASK;
- if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
- mfs < lport->mfs)
- lport->mfs = mfs;
- csp_flags = ntohs(flp->fl_csp.sp_features);
- r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
- e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
- if (csp_flags & FC_SP_FT_EDTR)
- e_d_tov /= 1000000;
-
- lport->npiv_enabled = !!(csp_flags & FC_SP_FT_NPIV_ACC);
-
- if ((csp_flags & FC_SP_FT_FPORT) == 0) {
- if (e_d_tov > lport->e_d_tov)
- lport->e_d_tov = e_d_tov;
- lport->r_a_tov = 2 * e_d_tov;
- fc_lport_set_port_id(lport, did, fp);
- printk(KERN_INFO "host%d: libfc: "
- "Port (%6.6x) entered "
- "point-to-point mode\n",
- lport->host->host_no, did);
- fc_lport_ptp_setup(lport, fc_frame_sid(fp),
- get_unaligned_be64(
- &flp->fl_wwpn),
- get_unaligned_be64(
- &flp->fl_wwnn));
- } else {
- lport->e_d_tov = e_d_tov;
- lport->r_a_tov = r_a_tov;
- fc_host_fabric_name(lport->host) =
- get_unaligned_be64(&flp->fl_wwnn);
- fc_lport_set_port_id(lport, did, fp);
- fc_lport_enter_dns(lport);
- }
- }
- } else {
- FC_LPORT_DBG(lport, "FLOGI RJT or bad response\n");
+ if (fh->fh_r_ctl != FC_RCTL_ELS_REP || did == 0 ||
+ fc_frame_payload_op(fp) != ELS_LS_ACC) {
+ FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
+ flp = fc_frame_payload_get(fp, sizeof(*flp));
+ if (!flp) {
+ FC_LPORT_DBG(lport, "FLOGI bad response\n");
fc_lport_error(lport, fp);
+ goto err;
+ }
+
+ mfs = ntohs(flp->fl_csp.sp_bb_data) &
+ FC_SP_BB_DATA_MASK;
+ if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
+ mfs < lport->mfs)
+ lport->mfs = mfs;
+ csp_flags = ntohs(flp->fl_csp.sp_features);
+ r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
+ e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
+ if (csp_flags & FC_SP_FT_EDTR)
+ e_d_tov /= 1000000;
+
+ lport->npiv_enabled = !!(csp_flags & FC_SP_FT_NPIV_ACC);
+
+ if ((csp_flags & FC_SP_FT_FPORT) == 0) {
+ if (e_d_tov > lport->e_d_tov)
+ lport->e_d_tov = e_d_tov;
+ lport->r_a_tov = 2 * e_d_tov;
+ fc_lport_set_port_id(lport, did, fp);
+ printk(KERN_INFO "host%d: libfc: "
+ "Port (%6.6x) entered "
+ "point-to-point mode\n",
+ lport->host->host_no, did);
+ fc_lport_ptp_setup(lport, fc_frame_sid(fp),
+ get_unaligned_be64(
+ &flp->fl_wwpn),
+ get_unaligned_be64(
+ &flp->fl_wwnn));
+ } else {
+ lport->e_d_tov = e_d_tov;
+ lport->r_a_tov = r_a_tov;
+ fc_host_fabric_name(lport->host) =
+ get_unaligned_be64(&flp->fl_wwnn);
+ fc_lport_set_port_id(lport, did, fp);
+ fc_lport_enter_dns(lport);
}
out:
diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c
index f33b897..9fbf78e 100644
--- a/drivers/scsi/libfc/fc_npiv.c
+++ b/drivers/scsi/libfc/fc_npiv.c
@@ -22,6 +22,7 @@
*/
#include <scsi/libfc.h>
+#include <linux/export.h>
/**
* fc_vport_create() - Create a new NPIV vport instance
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 3b66937..b9e4348 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -51,6 +51,7 @@
#include <linux/rcupdate.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <linux/export.h>
#include <asm/unaligned.h>
#include <scsi/libfc.h>
@@ -153,18 +154,6 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
}
/**
- * fc_rport_free_rcu() - Free a remote port
- * @rcu: The rcu_head structure inside the remote port
- */
-static void fc_rport_free_rcu(struct rcu_head *rcu)
-{
- struct fc_rport_priv *rdata;
-
- rdata = container_of(rcu, struct fc_rport_priv, rcu);
- kfree(rdata);
-}
-
-/**
* fc_rport_destroy() - Free a remote port after last reference is released
* @kref: The remote port's kref
*/
@@ -173,7 +162,7 @@ static void fc_rport_destroy(struct kref *kref)
struct fc_rport_priv *rdata;
rdata = container_of(kref, struct fc_rport_priv, kref);
- call_rcu(&rdata->rcu, fc_rport_free_rcu);
+ kfree_rcu(rdata, rcu);
}
/**
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index db9238f..5e170e3 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -112,12 +112,12 @@ static void sas_ata_task_done(struct sas_task *task)
if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
((stat->stat == SAM_STAT_CHECK_CONDITION &&
dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
- ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
+ memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE);
if (!link->sactive) {
- qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
+ qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
} else {
- link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command);
+ link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
if (unlikely(link->eh_info.err_mask))
qc->flags |= ATA_QCFLAG_FAILED;
}
@@ -138,8 +138,8 @@ static void sas_ata_task_done(struct sas_task *task)
qc->flags |= ATA_QCFLAG_FAILED;
}
- dev->sata_dev.tf.feature = 0x04; /* status err */
- dev->sata_dev.tf.command = ATA_ERR;
+ dev->sata_dev.fis[3] = 0x04; /* status err */
+ dev->sata_dev.fis[2] = ATA_ERR;
}
}
@@ -197,7 +197,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
qc->tf.nsect = 0;
}
- ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
+ ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis);
task->uldd_task = qc;
if (ata_is_atapi(qc->tf.protocol)) {
memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
@@ -252,7 +252,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
{
struct domain_device *dev = qc->ap->private_data;
- memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
+ ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf);
return true;
}
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index f583193..676e169 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -219,17 +219,20 @@ out_err2:
/* ---------- Device registration and unregistration ---------- */
-static inline void sas_unregister_common_dev(struct domain_device *dev)
+static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_device *dev)
{
sas_notify_lldd_dev_gone(dev);
if (!dev->parent)
dev->port->port_dev = NULL;
else
list_del_init(&dev->siblings);
+
+ spin_lock_irq(&port->dev_list_lock);
list_del_init(&dev->dev_list_node);
+ spin_unlock_irq(&port->dev_list_lock);
}
-void sas_unregister_dev(struct domain_device *dev)
+void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
{
if (dev->rphy) {
sas_remove_children(&dev->rphy->dev);
@@ -241,15 +244,15 @@ void sas_unregister_dev(struct domain_device *dev)
kfree(dev->ex_dev.ex_phy);
dev->ex_dev.ex_phy = NULL;
}
- sas_unregister_common_dev(dev);
+ sas_unregister_common_dev(port, dev);
}
void sas_unregister_domain_devices(struct asd_sas_port *port)
{
struct domain_device *dev, *n;
- list_for_each_entry_safe_reverse(dev,n,&port->dev_list,dev_list_node)
- sas_unregister_dev(dev);
+ list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node)
+ sas_unregister_dev(port, dev);
port->port->rphy = NULL;
@@ -333,14 +336,16 @@ static void sas_revalidate_domain(struct work_struct *work)
struct sas_discovery_event *ev =
container_of(work, struct sas_discovery_event, work);
struct asd_sas_port *port = ev->port;
+ struct domain_device *ddev = port->port_dev;
sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock,
&port->disc.pending);
SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
task_pid_nr(current));
- if (port->port_dev)
- res = sas_ex_revalidate_domain(port->port_dev);
+ if (ddev && (ddev->dev_type == FANOUT_DEV ||
+ ddev->dev_type == EDGE_DEV))
+ res = sas_ex_revalidate_domain(ddev);
SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
port->id, task_pid_nr(current), res);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index d2f9576..dbe3568 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -338,6 +338,7 @@ static void ex_assign_report_general(struct domain_device *dev,
dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
+ dev->ex_dev.t2t_supp = rg->t2t_supp;
dev->ex_dev.conf_route_table = rg->conf_route_table;
dev->ex_dev.configuring = rg->configuring;
memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
@@ -760,7 +761,10 @@ static struct domain_device *sas_ex_discover_end_dev(
out_list_del:
sas_rphy_free(child->rphy);
child->rphy = NULL;
+
+ spin_lock_irq(&parent->port->dev_list_lock);
list_del(&child->dev_list_node);
+ spin_unlock_irq(&parent->port->dev_list_lock);
out_free:
sas_port_delete(phy->port);
out_err:
@@ -1140,15 +1144,17 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
};
struct domain_device *parent = child->parent;
- sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x "
- "has %c:%c routing link!\n",
+ sas_printk("%s ex %016llx (T2T supp:%d) phy 0x%x <--> %s ex %016llx "
+ "(T2T supp:%d) phy 0x%x has %c:%c routing link!\n",
ex_type[parent->dev_type],
SAS_ADDR(parent->sas_addr),
+ parent->ex_dev.t2t_supp,
parent_phy->phy_id,
ex_type[child->dev_type],
SAS_ADDR(child->sas_addr),
+ child->ex_dev.t2t_supp,
child_phy->phy_id,
ra_char[parent_phy->routing_attr],
@@ -1245,10 +1251,15 @@ static int sas_check_parent_topology(struct domain_device *child)
sas_print_parent_topology_bug(child, parent_phy, child_phy);
res = -ENODEV;
}
- } else if (parent_phy->routing_attr == TABLE_ROUTING &&
- child_phy->routing_attr != SUBTRACTIVE_ROUTING) {
- sas_print_parent_topology_bug(child, parent_phy, child_phy);
- res = -ENODEV;
+ } else if (parent_phy->routing_attr == TABLE_ROUTING) {
+ if (child_phy->routing_attr == SUBTRACTIVE_ROUTING ||
+ (child_phy->routing_attr == TABLE_ROUTING &&
+ child_ex->t2t_supp && parent_ex->t2t_supp)) {
+ /* All good */;
+ } else {
+ sas_print_parent_topology_bug(child, parent_phy, child_phy);
+ res = -ENODEV;
+ }
}
break;
case FANOUT_DEV:
@@ -1743,7 +1754,7 @@ out:
return res;
}
-static void sas_unregister_ex_tree(struct domain_device *dev)
+static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_device *dev)
{
struct expander_device *ex = &dev->ex_dev;
struct domain_device *child, *n;
@@ -1752,11 +1763,11 @@ static void sas_unregister_ex_tree(struct domain_device *dev)
child->gone = 1;
if (child->dev_type == EDGE_DEV ||
child->dev_type == FANOUT_DEV)
- sas_unregister_ex_tree(child);
+ sas_unregister_ex_tree(port, child);
else
- sas_unregister_dev(child);
+ sas_unregister_dev(port, child);
}
- sas_unregister_dev(dev);
+ sas_unregister_dev(port, dev);
}
static void sas_unregister_devs_sas_addr(struct domain_device *parent,
@@ -1773,9 +1784,9 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
child->gone = 1;
if (child->dev_type == EDGE_DEV ||
child->dev_type == FANOUT_DEV)
- sas_unregister_ex_tree(child);
+ sas_unregister_ex_tree(parent->port, child);
else
- sas_unregister_dev(child);
+ sas_unregister_dev(parent->port, child);
break;
}
}
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 04ad8dd..bb8f492 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -11,6 +11,7 @@
#include <linux/scatterlist.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "sas_internal.h"
@@ -51,6 +52,91 @@ static void sas_host_smp_discover(struct sas_ha_struct *sas_ha, u8 *resp_data,
resp_data[15] = rphy->identify.target_port_protocols;
}
+/**
+ * to_sas_gpio_gp_bit - given the gpio frame data find the byte/bit position of 'od'
+ * @od: od bit to find
+ * @data: incoming bitstream (from frame)
+ * @index: requested data register index (from frame)
+ * @count: total number of registers in the bitstream (from frame)
+ * @bit: bit position of 'od' in the returned byte
+ *
+ * returns NULL if 'od' is not in 'data'
+ *
+ * From SFF-8485 v0.7:
+ * "In GPIO_TX[1], bit 0 of byte 3 contains the first bit (i.e., OD0.0)
+ * and bit 7 of byte 0 contains the 32nd bit (i.e., OD10.1).
+ *
+ * In GPIO_TX[2], bit 0 of byte 3 contains the 33rd bit (i.e., OD10.2)
+ * and bit 7 of byte 0 contains the 64th bit (i.e., OD21.0)."
+ *
+ * The general-purpose (raw-bitstream) RX registers have the same layout
+ * although 'od' is renamed 'id' for 'input data'.
+ *
+ * SFF-8489 defines the behavior of the LEDs in response to the 'od' values.
+ */
+static u8 *to_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count, u8 *bit)
+{
+ unsigned int reg;
+ u8 byte;
+
+ /* gp registers start at index 1 */
+ if (index == 0)
+ return NULL;
+
+ index--; /* make index 0-based */
+ if (od < index * 32)
+ return NULL;
+
+ od -= index * 32;
+ reg = od >> 5;
+
+ if (reg >= count)
+ return NULL;
+
+ od &= (1 << 5) - 1;
+ byte = 3 - (od >> 3);
+ *bit = od & ((1 << 3) - 1);
+
+ return &data[reg * 4 + byte];
+}
+
+int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count)
+{
+ u8 *byte;
+ u8 bit;
+
+ byte = to_sas_gpio_gp_bit(od, data, index, count, &bit);
+ if (!byte)
+ return -1;
+
+ return (*byte >> bit) & 1;
+}
+EXPORT_SYMBOL(try_test_sas_gpio_gp_bit);
+
+static int sas_host_smp_write_gpio(struct sas_ha_struct *sas_ha, u8 *resp_data,
+ u8 reg_type, u8 reg_index, u8 reg_count,
+ u8 *req_data)
+{
+ struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt);
+ int written;
+
+ if (i->dft->lldd_write_gpio == NULL) {
+ resp_data[2] = SMP_RESP_FUNC_UNK;
+ return 0;
+ }
+
+ written = i->dft->lldd_write_gpio(sas_ha, reg_type, reg_index,
+ reg_count, req_data);
+
+ if (written < 0) {
+ resp_data[2] = SMP_RESP_FUNC_FAILED;
+ written = 0;
+ } else
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+
+ return written;
+}
+
static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data,
u8 phy_id)
{
@@ -230,9 +316,23 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
/* Can't implement; hosts have no routes */
break;
- case SMP_WRITE_GPIO_REG:
- /* FIXME: need GPIO support in the transport class */
+ case SMP_WRITE_GPIO_REG: {
+ /* SFF-8485 v0.7 */
+ const int base_frame_size = 11;
+ int to_write = req_data[4];
+
+ if (blk_rq_bytes(req) < base_frame_size + to_write * 4 ||
+ req->resid_len < base_frame_size + to_write * 4) {
+ resp_data[2] = SMP_RESP_INV_FRM_LEN;
+ break;
+ }
+
+ to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
+ req_data[3], to_write, &req_data[8]);
+ req->resid_len -= base_frame_size + to_write * 4;
+ rsp->resid_len -= 8;
break;
+ }
case SMP_CONF_ROUTE_INFO:
/* Can't implement; hosts have no routes */
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2dc5534..d81c3b1 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -37,7 +37,32 @@
#include "../scsi_sas_internal.h"
-struct kmem_cache *sas_task_cache;
+static struct kmem_cache *sas_task_cache;
+
+struct sas_task *sas_alloc_task(gfp_t flags)
+{
+ struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
+
+ if (task) {
+ INIT_LIST_HEAD(&task->list);
+ spin_lock_init(&task->task_state_lock);
+ task->task_state_flags = SAS_TASK_STATE_PENDING;
+ init_timer(&task->timer);
+ init_completion(&task->completion);
+ }
+
+ return task;
+}
+EXPORT_SYMBOL_GPL(sas_alloc_task);
+
+void sas_free_task(struct sas_task *task)
+{
+ if (task) {
+ BUG_ON(!list_empty(&task->list));
+ kmem_cache_free(sas_task_cache, task);
+ }
+}
+EXPORT_SYMBOL_GPL(sas_free_task);
/*------------ SAS addr hash -----------*/
void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
@@ -152,10 +177,15 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
static int sas_get_linkerrors(struct sas_phy *phy)
{
- if (scsi_is_sas_phy_local(phy))
- /* FIXME: we have no local phy stats
- * gathering at this time */
- return -EINVAL;
+ if (scsi_is_sas_phy_local(phy)) {
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+ struct sas_internal *i =
+ to_sas_internal(sas_ha->core.shost->transportt);
+
+ return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
+ }
return sas_smp_get_phy_events(phy);
}
@@ -293,8 +323,7 @@ EXPORT_SYMBOL_GPL(sas_domain_release_transport);
static int __init sas_class_init(void)
{
- sas_task_cache = kmem_cache_create("sas_task", sizeof(struct sas_task),
- 0, SLAB_HWCACHE_ALIGN, NULL);
+ sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN);
if (!sas_task_cache)
return -ENOMEM;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index eeba76c..b6e233d 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -25,6 +25,7 @@
#include <linux/kthread.h>
#include <linux/firmware.h>
+#include <linux/export.h>
#include <linux/ctype.h>
#include "sas_internal.h"
@@ -182,79 +183,56 @@ int sas_queue_up(struct sas_task *task)
return 0;
}
-/**
- * sas_queuecommand -- Enqueue a command for processing
- * @parameters: See SCSI Core documentation
- *
- * Note: XXX: Remove the host unlock/lock pair when SCSI Core can
- * call us without holding an IRQ spinlock...
- */
-static int sas_queuecommand_lck(struct scsi_cmnd *cmd,
- void (*scsi_done)(struct scsi_cmnd *))
- __releases(host->host_lock)
- __acquires(dev->sata_dev.ap->lock)
- __releases(dev->sata_dev.ap->lock)
- __acquires(host->host_lock)
+int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
- int res = 0;
- struct domain_device *dev = cmd_to_domain_dev(cmd);
- struct Scsi_Host *host = cmd->device->host;
struct sas_internal *i = to_sas_internal(host->transportt);
+ struct domain_device *dev = cmd_to_domain_dev(cmd);
+ struct sas_ha_struct *sas_ha = dev->port->ha;
+ struct sas_task *task;
+ int res = 0;
- spin_unlock_irq(host->host_lock);
+ /* If the device fell off, no sense in issuing commands */
+ if (dev->gone) {
+ cmd->result = DID_BAD_TARGET << 16;
+ goto out_done;
+ }
- {
- struct sas_ha_struct *sas_ha = dev->port->ha;
- struct sas_task *task;
-
- /* If the device fell off, no sense in issuing commands */
- if (dev->gone) {
- cmd->result = DID_BAD_TARGET << 16;
- scsi_done(cmd);
- goto out;
- }
+ if (dev_is_sata(dev)) {
+ unsigned long flags;
- if (dev_is_sata(dev)) {
- unsigned long flags;
+ spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
+ res = ata_sas_queuecmd(cmd, dev->sata_dev.ap);
+ spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
+ return res;
+ }
- spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
- res = ata_sas_queuecmd(cmd, dev->sata_dev.ap);
- spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
- goto out;
- }
+ task = sas_create_task(cmd, dev, GFP_ATOMIC);
+ if (!task)
+ return SCSI_MLQUEUE_HOST_BUSY;
- res = -ENOMEM;
- task = sas_create_task(cmd, dev, GFP_ATOMIC);
- if (!task)
- goto out;
+ /* Queue up, Direct Mode or Task Collector Mode. */
+ if (sas_ha->lldd_max_execute_num < 2)
+ res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
+ else
+ res = sas_queue_up(task);
- cmd->scsi_done = scsi_done;
- /* Queue up, Direct Mode or Task Collector Mode. */
- if (sas_ha->lldd_max_execute_num < 2)
- res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
- else
- res = sas_queue_up(task);
+ if (res)
+ goto out_free_task;
+ return 0;
- /* Examine */
- if (res) {
- SAS_DPRINTK("lldd_execute_task returned: %d\n", res);
- ASSIGN_SAS_TASK(cmd, NULL);
- sas_free_task(task);
- if (res == -SAS_QUEUE_FULL) {
- cmd->result = DID_SOFT_ERROR << 16; /* retry */
- res = 0;
- scsi_done(cmd);
- }
- goto out;
- }
- }
-out:
- spin_lock_irq(host->host_lock);
- return res;
+out_free_task:
+ SAS_DPRINTK("lldd_execute_task returned: %d\n", res);
+ ASSIGN_SAS_TASK(cmd, NULL);
+ sas_free_task(task);
+ if (res == -SAS_QUEUE_FULL)
+ cmd->result = DID_SOFT_ERROR << 16; /* retry */
+ else
+ cmd->result = DID_ERROR << 16;
+out_done:
+ cmd->scsi_done(cmd);
+ return 0;
}
-DEF_SCSI_QCMD(sas_queuecommand)
-
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
{
struct sas_task *task = TO_SAS_TASK(cmd);
@@ -784,8 +762,7 @@ int sas_target_alloc(struct scsi_target *starget)
return 0;
}
-#define SAS_DEF_QD 32
-#define SAS_MAX_QD 64
+#define SAS_DEF_QD 256
int sas_slave_configure(struct scsi_device *scsi_dev)
{
@@ -825,34 +802,41 @@ void sas_slave_destroy(struct scsi_device *scsi_dev)
struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
if (dev_is_sata(dev))
- dev->sata_dev.ap->link.device[0].class = ATA_DEV_NONE;
+ sas_to_ata_dev(dev)->class = ATA_DEV_NONE;
}
-int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth,
- int reason)
+int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
{
- int res = min(new_depth, SAS_MAX_QD);
+ struct domain_device *dev = sdev_to_domain_dev(sdev);
- if (reason != SCSI_QDEPTH_DEFAULT)
+ if (dev_is_sata(dev))
+ return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth,
+ reason);
+
+ switch (reason) {
+ case SCSI_QDEPTH_DEFAULT:
+ case SCSI_QDEPTH_RAMP_UP:
+ if (!sdev->tagged_supported)
+ depth = 1;
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+ break;
+ case SCSI_QDEPTH_QFULL:
+ scsi_track_queue_full(sdev, depth);
+ break;
+ default:
return -EOPNOTSUPP;
-
- if (scsi_dev->tagged_supported)
- scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev),
- res);
- else {
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- sas_printk("device %llx LUN %x queue depth changed to 1\n",
- SAS_ADDR(dev->sas_addr),
- scsi_dev->lun);
- scsi_adjust_queue_depth(scsi_dev, 0, 1);
- res = 1;
}
- return res;
+ return depth;
}
int sas_change_queue_type(struct scsi_device *scsi_dev, int qt)
{
+ struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
+
+ if (dev_is_sata(dev))
+ return -EINVAL;
+
if (!scsi_dev->tagged_supported)
return 0;
diff --git a/drivers/scsi/libsas/sas_task.c b/drivers/scsi/libsas/sas_task.c
index b13a334..a78e5bd 100644
--- a/drivers/scsi/libsas/sas_task.c
+++ b/drivers/scsi/libsas/sas_task.c
@@ -1,4 +1,5 @@
#include <linux/kernel.h>
+#include <linux/export.h>
#include <scsi/sas.h>
#include <scsi/libsas.h>
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 0441361..bb4c8e0 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -680,6 +680,9 @@ struct lpfc_hba {
uint32_t cfg_enable_rrq;
uint32_t cfg_topology;
uint32_t cfg_link_speed;
+#define LPFC_FCF_FOV 1 /* Fast fcf failover */
+#define LPFC_FCF_PRIORITY 2 /* Priority fcf failover */
+ uint32_t cfg_fcf_failover_policy;
uint32_t cfg_cr_delay;
uint32_t cfg_cr_count;
uint32_t cfg_multi_ring_support;
@@ -843,17 +846,37 @@ struct lpfc_hba {
struct dentry *debug_hbqinfo;
struct dentry *debug_dumpHostSlim;
struct dentry *debug_dumpHBASlim;
- struct dentry *debug_dumpData; /* BlockGuard BPL*/
- struct dentry *debug_dumpDif; /* BlockGuard BPL*/
+ struct dentry *debug_dumpData; /* BlockGuard BPL */
+ struct dentry *debug_dumpDif; /* BlockGuard BPL */
+ struct dentry *debug_InjErrLBA; /* LBA to inject errors at */
+ struct dentry *debug_writeGuard; /* inject write guard_tag errors */
+ struct dentry *debug_writeApp; /* inject write app_tag errors */
+ struct dentry *debug_writeRef; /* inject write ref_tag errors */
+ struct dentry *debug_readApp; /* inject read app_tag errors */
+ struct dentry *debug_readRef; /* inject read ref_tag errors */
+
+ /* T10 DIF error injection */
+ uint32_t lpfc_injerr_wgrd_cnt;
+ uint32_t lpfc_injerr_wapp_cnt;
+ uint32_t lpfc_injerr_wref_cnt;
+ uint32_t lpfc_injerr_rapp_cnt;
+ uint32_t lpfc_injerr_rref_cnt;
+ sector_t lpfc_injerr_lba;
+#define LPFC_INJERR_LBA_OFF (sector_t)0xffffffffffffffff
+
struct dentry *debug_slow_ring_trc;
struct lpfc_debugfs_trc *slow_ring_trc;
atomic_t slow_ring_trc_cnt;
/* iDiag debugfs sub-directory */
struct dentry *idiag_root;
struct dentry *idiag_pci_cfg;
+ struct dentry *idiag_bar_acc;
struct dentry *idiag_que_info;
struct dentry *idiag_que_acc;
struct dentry *idiag_drb_acc;
+ struct dentry *idiag_ctl_acc;
+ struct dentry *idiag_mbx_acc;
+ struct dentry *idiag_ext_acc;
#endif
/* Used for deferred freeing of ELS data buffers */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 80ca11c..d0ebaeb 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/aer.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
@@ -52,6 +53,13 @@
#define LPFC_MIN_DEVLOSS_TMO 1
#define LPFC_MAX_DEVLOSS_TMO 255
+/*
+ * Write key size should be multiple of 4. If write key is changed
+ * make sure that library write key is also changed.
+ */
+#define LPFC_REG_WRITE_KEY_SIZE 4
+#define LPFC_REG_WRITE_KEY "EMLX"
+
/**
* lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
* @incr: integer to convert.
@@ -693,7 +701,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
int rc;
if (!phba->cfg_enable_hba_reset)
- return -EIO;
+ return -EACCES;
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -742,9 +750,11 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
-
int status = -EINVAL;
+ if (!phba->cfg_enable_hba_reset)
+ return -EACCES;
+
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
status = phba->lpfc_selective_reset(phba);
@@ -765,16 +775,21 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
* Returns:
* zero for success
**/
-static int
+int
lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
{
- struct lpfc_register portstat_reg;
+ struct lpfc_register portstat_reg = {0};
int i;
-
+ msleep(100);
lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0);
+ /* verify if privilaged for the request operation */
+ if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
+ !bf_get(lpfc_sliport_status_err, &portstat_reg))
+ return -EPERM;
+
/* wait for the SLI port firmware ready after firmware reset */
for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
msleep(10);
@@ -810,18 +825,24 @@ static ssize_t
lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
{
struct completion online_compl;
+ struct pci_dev *pdev = phba->pcidev;
uint32_t reg_val;
int status = 0;
int rc;
if (!phba->cfg_enable_hba_reset)
- return -EIO;
+ return -EACCES;
if ((phba->sli_rev < LPFC_SLI_REV4) ||
(bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
LPFC_SLI_INTF_IF_TYPE_2))
return -EPERM;
+ /* Disable SR-IOV virtual functions if enabled */
+ if (phba->cfg_sriov_nr_virtfn) {
+ pci_disable_sriov(pdev);
+ phba->cfg_sriov_nr_virtfn = 0;
+ }
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
if (status != 0)
@@ -849,7 +870,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
rc = lpfc_sli4_pdev_status_reg_wait(phba);
if (rc)
- return -EIO;
+ return rc;
init_completion(&online_compl);
rc = lpfc_workq_post_event(phba, &status, &online_compl,
@@ -975,7 +996,7 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
if (!status)
return strlen(buf);
else
- return -EIO;
+ return status;
}
/**
@@ -2184,6 +2205,9 @@ lpfc_param_show(enable_npiv);
lpfc_param_init(enable_npiv, 1, 0, 1);
static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
+LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
+ "FCF Fast failover=1 Priority failover=2");
+
int lpfc_enable_rrq;
module_param(lpfc_enable_rrq, int, S_IRUGO);
MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
@@ -3766,6 +3790,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_fdmi_on,
&dev_attr_lpfc_max_luns,
&dev_attr_lpfc_enable_npiv,
+ &dev_attr_lpfc_fcf_failover_policy,
&dev_attr_lpfc_enable_rrq,
&dev_attr_nport_evt_cnt,
&dev_attr_board_mode,
@@ -3872,18 +3897,23 @@ sysfs_ctlreg_write(struct file *filp, struct kobject *kobj,
if ((off + count) > FF_REG_AREA_SIZE)
return -ERANGE;
- if (count == 0) return 0;
+ if (count <= LPFC_REG_WRITE_KEY_SIZE)
+ return 0;
if (off % 4 || count % 4 || (unsigned long)buf % 4)
return -EINVAL;
- if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
+ /* This is to protect HBA registers from accidental writes. */
+ if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE))
+ return -EINVAL;
+
+ if (!(vport->fc_flag & FC_OFFLINE_MODE))
return -EPERM;
- }
spin_lock_irq(&phba->hbalock);
- for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
- writel(*((uint32_t *)(buf + buf_off)),
+ for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE;
+ buf_off += sizeof(uint32_t))
+ writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)),
phba->ctrl_regs_memmap_p + off + buf_off);
spin_unlock_irq(&phba->hbalock);
@@ -4084,8 +4114,10 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- int rc;
+ LPFC_MBOXQ_t *mboxq;
MAILBOX_t *pmb;
+ uint32_t mbox_tmo;
+ int rc;
if (off > MAILBOX_CMD_SIZE)
return -ERANGE;
@@ -4110,7 +4142,8 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
if (off == 0 &&
phba->sysfs_mbox.state == SMBOX_WRITING &&
phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) {
- pmb = &phba->sysfs_mbox.mbox->u.mb;
+ mboxq = (LPFC_MBOXQ_t *)&phba->sysfs_mbox.mbox;
+ pmb = &mboxq->u.mb;
switch (pmb->mbxCommand) {
/* Offline only */
case MBX_INIT_LINK:
@@ -4220,9 +4253,8 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
} else {
spin_unlock_irq(&phba->hbalock);
- rc = lpfc_sli_issue_mbox_wait (phba,
- phba->sysfs_mbox.mbox,
- lpfc_mbox_tmo_val(phba, pmb->mbxCommand) * HZ);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
+ rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
spin_lock_irq(&phba->hbalock);
}
@@ -4467,9 +4499,10 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
spin_lock_irq(shost->host_lock);
- if ((vport->fc_flag & FC_FABRIC) ||
- ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
- (vport->fc_flag & FC_PUBLIC_LOOP)))
+ if ((vport->port_state > LPFC_FLOGI) &&
+ ((vport->fc_flag & FC_FABRIC) ||
+ ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
+ (vport->fc_flag & FC_PUBLIC_LOOP))))
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else
/* fabric is local port if there is no F/FL_Port */
@@ -4542,9 +4575,17 @@ lpfc_get_stats(struct Scsi_Host *shost)
memset(hs, 0, sizeof (struct fc_host_statistics));
hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
- hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
+ /*
+ * The MBX_READ_STATUS returns tx_k_bytes which has to
+ * converted to words
+ */
+ hs->tx_words = (uint64_t)
+ ((uint64_t)pmb->un.varRdStatus.xmitByteCnt
+ * (uint64_t)256);
hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
- hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256);
+ hs->rx_words = (uint64_t)
+ ((uint64_t)pmb->un.varRdStatus.rcvByteCnt
+ * (uint64_t)256);
memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
pmb->mbxCommand = MBX_READ_LNK_STAT;
@@ -4986,6 +5027,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_link_speed_init(phba, lpfc_link_speed);
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
+ lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy);
lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
lpfc_use_msi_init(phba, lpfc_use_msi);
lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index f46378f..6760c69 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -42,6 +42,7 @@
#include "lpfc.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
+#include "lpfc_debugfs.h"
#include "lpfc_vport.h"
#include "lpfc_version.h"
@@ -1566,7 +1567,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
uint32_t link_flags;
uint32_t timeout;
LPFC_MBOXQ_t *pmboxq;
- int mbxstatus;
+ int mbxstatus = MBX_SUCCESS;
int i = 0;
int rc = 0;
@@ -1740,7 +1741,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
uint32_t link_flags, timeout, req_len, alloc_len;
struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
LPFC_MBOXQ_t *pmboxq = NULL;
- int mbxstatus, i, rc = 0;
+ int mbxstatus = MBX_SUCCESS, i, rc = 0;
/* no data to return just the return code */
job->reply->reply_payload_rcv_len = 0;
@@ -3177,6 +3178,11 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
"(x%x/x%x) complete bsg job done, bsize:%d\n",
phba->mbox_ext_buf_ctx.nembType,
phba->mbox_ext_buf_ctx.mboxType, size);
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba,
+ phba->mbox_ext_buf_ctx.nembType,
+ phba->mbox_ext_buf_ctx.mboxType,
+ dma_ebuf, sta_pos_addr,
+ phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);
} else
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -3429,6 +3435,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
"ext_buf_cnt:%d\n", ext_buf_cnt);
}
+ /* before dma descriptor setup */
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
+ sta_pre_addr, dmabuf, ext_buf_cnt);
+
/* reject non-embedded mailbox command with none external buffer */
if (ext_buf_cnt == 0) {
rc = -EPERM;
@@ -3476,6 +3486,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
}
}
+ /* after dma descriptor setup */
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
+ sta_pos_addr, dmabuf, ext_buf_cnt);
+
/* construct base driver mbox command */
pmb = &pmboxq->u.mb;
pmbx = (uint8_t *)dmabuf->virt;
@@ -3590,12 +3604,20 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
"ext_buf_cnt:%d\n", ext_buf_cnt);
}
+ /* before dma buffer descriptor setup */
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
+ sta_pre_addr, dmabuf, ext_buf_cnt);
+
if (ext_buf_cnt == 0)
return -EPERM;
/* for the first external buffer */
lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
+ /* after dma descriptor setup */
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
+ sta_pos_addr, dmabuf, ext_buf_cnt);
+
/* log for looking forward */
for (i = 1; i < ext_buf_cnt; i++) {
if (nemb_tp == nemb_mse)
@@ -3844,6 +3866,12 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list,
struct lpfc_dmabuf, list);
list_del_init(&dmabuf->list);
+
+ /* after dma buffer descriptor setup */
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
+ mbox_rd, dma_ebuf, sta_pos_addr,
+ dmabuf, index);
+
pbuf = (uint8_t *)dmabuf->virt;
job->reply->reply_payload_rcv_len =
sg_copy_from_buffer(job->reply_payload.sg_list,
@@ -3926,6 +3954,11 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
dmabuf);
list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
+ /* after write dma buffer */
+ lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
+ mbox_wr, dma_ebuf, sta_pos_addr,
+ dmabuf, index);
+
if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"2968 SLI_CONFIG ext-buffer wr all %d "
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 1e41af8..60f9534 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -209,7 +209,7 @@ void __lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_mbox_cmd_check(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_mbox_dev_check(struct lpfc_hba *);
-int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
+int lpfc_mbox_tmo_val(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
@@ -235,9 +235,11 @@ int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *);
void lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *);
void lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *);
uint16_t lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *);
+void lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *, uint16_t);
int lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *, uint16_t);
void lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *, uint16_t);
int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t);
+void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *, int align);
void lpfc_mem_free(struct lpfc_hba *);
@@ -371,6 +373,10 @@ extern struct lpfc_hbq_init *lpfc_hbq_defs[];
/* SLI4 if_type 2 externs. */
int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *);
int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *);
+int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t,
+ uint16_t *, uint16_t *);
+int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t,
+ uint16_t *, uint16_t *);
/* externs BlockGuard */
extern char *_dump_buf_data;
@@ -437,7 +443,13 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
uint32_t);
+void lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *, enum nemb_type,
+ enum mbox_type, enum dma_type, enum sta_type,
+ struct lpfc_dmabuf *, uint32_t);
+void lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *, MAILBOX_t *);
int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *);
/* functions to support SR-IOV */
int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int);
uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *);
+int lpfc_sli4_queue_create(struct lpfc_hba *);
+void lpfc_sli4_queue_destroy(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 779b88e..707081d 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1856,6 +1856,9 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
case 2:
c = 'B';
break;
+ case 3:
+ c = 'X';
+ break;
default:
c = 0;
break;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index ffe82d1..2838259 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -20,6 +20,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
@@ -48,6 +49,7 @@
#include "lpfc_version.h"
#include "lpfc_compat.h"
#include "lpfc_debugfs.h"
+#include "lpfc_bsg.h"
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
/*
@@ -135,7 +137,11 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
int i, index, len, enable;
uint32_t ms;
struct lpfc_debugfs_trc *dtp;
- char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
+ char *buffer;
+
+ buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return 0;
enable = lpfc_debugfs_enable;
lpfc_debugfs_enable = 0;
@@ -167,6 +173,8 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
}
lpfc_debugfs_enable = enable;
+ kfree(buffer);
+
return len;
}
@@ -195,8 +203,11 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
int i, index, len, enable;
uint32_t ms;
struct lpfc_debugfs_trc *dtp;
- char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
+ char *buffer;
+ buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return 0;
enable = lpfc_debugfs_enable;
lpfc_debugfs_enable = 0;
@@ -228,6 +239,8 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
}
lpfc_debugfs_enable = enable;
+ kfree(buffer);
+
return len;
}
@@ -378,7 +391,11 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
int len = 0;
int i, off;
uint32_t *ptr;
- char buffer[1024];
+ char *buffer;
+
+ buffer = kmalloc(1024, GFP_KERNEL);
+ if (!buffer)
+ return 0;
off = 0;
spin_lock_irq(&phba->hbalock);
@@ -407,6 +424,8 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
}
spin_unlock_irq(&phba->hbalock);
+ kfree(buffer);
+
return len;
}
@@ -978,6 +997,85 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
return nbytes;
}
+static int
+lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t
+lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct dentry *dent = file->f_dentry;
+ struct lpfc_hba *phba = file->private_data;
+ char cbuf[16];
+ int cnt = 0;
+
+ if (dent == phba->debug_writeGuard)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wgrd_cnt);
+ else if (dent == phba->debug_writeApp)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wapp_cnt);
+ else if (dent == phba->debug_writeRef)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wref_cnt);
+ else if (dent == phba->debug_readApp)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rapp_cnt);
+ else if (dent == phba->debug_readRef)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rref_cnt);
+ else if (dent == phba->debug_InjErrLBA)
+ cnt = snprintf(cbuf, 16, "0x%lx\n",
+ (unsigned long) phba->lpfc_injerr_lba);
+ else
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0547 Unknown debugfs error injection entry\n");
+
+ return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
+}
+
+static ssize_t
+lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct dentry *dent = file->f_dentry;
+ struct lpfc_hba *phba = file->private_data;
+ char dstbuf[32];
+ unsigned long tmp;
+ int size;
+
+ memset(dstbuf, 0, 32);
+ size = (nbytes < 32) ? nbytes : 32;
+ if (copy_from_user(dstbuf, buf, size))
+ return 0;
+
+ if (strict_strtoul(dstbuf, 0, &tmp))
+ return 0;
+
+ if (dent == phba->debug_writeGuard)
+ phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_writeApp)
+ phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_writeRef)
+ phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_readApp)
+ phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_readRef)
+ phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_InjErrLBA)
+ phba->lpfc_injerr_lba = (sector_t)tmp;
+ else
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0548 Unknown debugfs error injection entry\n");
+
+ return nbytes;
+}
+
+static int
+lpfc_debugfs_dif_err_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
/**
* lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
* @inode: The inode pointer that contains a vport pointer.
@@ -1147,7 +1245,8 @@ static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
{
char mybuf[64];
char *pbuf, *step_str;
- int bsize, i;
+ int i;
+ size_t bsize;
/* Protect copy from user */
if (!access_ok(VERIFY_READ, buf, nbytes))
@@ -1326,8 +1425,8 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
return 0;
if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
- where = idiag.cmd.data[0];
- count = idiag.cmd.data[1];
+ where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+ count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
} else
return 0;
@@ -1372,6 +1471,11 @@ pcicfg_browse:
len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
"%08x ", u32val);
offset += sizeof(uint32_t);
+ if (offset >= LPFC_PCI_CFG_SIZE) {
+ len += snprintf(pbuffer+len,
+ LPFC_PCI_CFG_SIZE-len, "\n");
+ break;
+ }
index -= sizeof(uint32_t);
if (!index)
len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
@@ -1384,8 +1488,11 @@ pcicfg_browse:
}
/* Set up the offset for next portion of pci cfg read */
- idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
- if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+ if (index == 0) {
+ idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
+ if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+ idiag.offset.last_rd = 0;
+ } else
idiag.offset.last_rd = 0;
return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
@@ -1438,8 +1545,8 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
goto error_out;
/* Read command from PCI config space, set up command fields */
- where = idiag.cmd.data[0];
- count = idiag.cmd.data[1];
+ where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+ count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
if (count == LPFC_PCI_CFG_BROWSE) {
if (where % sizeof(uint32_t))
goto error_out;
@@ -1474,9 +1581,9 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
goto error_out;
/* Write command to PCI config space, read-modify-write */
- where = idiag.cmd.data[0];
- count = idiag.cmd.data[1];
- value = idiag.cmd.data[2];
+ where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+ count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
+ value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX];
/* Sanity checks */
if ((count != sizeof(uint8_t)) &&
(count != sizeof(uint16_t)) &&
@@ -1569,6 +1676,292 @@ error_out:
}
/**
+ * lpfc_idiag_baracc_read - idiag debugfs pci bar access read
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba pci bar memory mapped space
+ * according to the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ int offset_label, offset, offset_run, len = 0, index;
+ int bar_num, acc_range, bar_size;
+ char *pbuffer;
+ void __iomem *mem_mapped_bar;
+ uint32_t if_type;
+ struct pci_dev *pdev;
+ uint32_t u32val;
+
+ pdev = phba->pcidev;
+ if (!pdev)
+ return 0;
+
+ /* This is a user read operation */
+ debug->op = LPFC_IDIAG_OP_RD;
+
+ if (!debug->buffer)
+ debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL);
+ if (!debug->buffer)
+ return 0;
+ pbuffer = debug->buffer;
+
+ if (*ppos)
+ return 0;
+
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
+ bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
+ offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
+ acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
+ bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
+ } else
+ return 0;
+
+ if (acc_range == 0)
+ return 0;
+
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+ if (bar_num == IDIAG_BARACC_BAR_0)
+ mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+ else if (bar_num == IDIAG_BARACC_BAR_1)
+ mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
+ else if (bar_num == IDIAG_BARACC_BAR_2)
+ mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
+ else
+ return 0;
+ } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+ if (bar_num == IDIAG_BARACC_BAR_0)
+ mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+ else
+ return 0;
+ } else
+ return 0;
+
+ /* Read single PCI bar space register */
+ if (acc_range == SINGLE_WORD) {
+ offset_run = offset;
+ u32val = readl(mem_mapped_bar + offset_run);
+ len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+ "%05x: %08x\n", offset_run, u32val);
+ } else
+ goto baracc_browse;
+
+ return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+
+baracc_browse:
+
+ /* Browse all PCI bar space registers */
+ offset_label = idiag.offset.last_rd;
+ offset_run = offset_label;
+
+ /* Read PCI bar memory mapped space */
+ len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+ "%05x: ", offset_label);
+ index = LPFC_PCI_BAR_RD_SIZE;
+ while (index > 0) {
+ u32val = readl(mem_mapped_bar + offset_run);
+ len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+ "%08x ", u32val);
+ offset_run += sizeof(uint32_t);
+ if (acc_range == LPFC_PCI_BAR_BROWSE) {
+ if (offset_run >= bar_size) {
+ len += snprintf(pbuffer+len,
+ LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+ break;
+ }
+ } else {
+ if (offset_run >= offset +
+ (acc_range * sizeof(uint32_t))) {
+ len += snprintf(pbuffer+len,
+ LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+ break;
+ }
+ }
+ index -= sizeof(uint32_t);
+ if (!index)
+ len += snprintf(pbuffer+len,
+ LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+ else if (!(index % (8 * sizeof(uint32_t)))) {
+ offset_label += (8 * sizeof(uint32_t));
+ len += snprintf(pbuffer+len,
+ LPFC_PCI_BAR_RD_BUF_SIZE-len,
+ "\n%05x: ", offset_label);
+ }
+ }
+
+ /* Set up the offset for next portion of pci bar read */
+ if (index == 0) {
+ idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE;
+ if (acc_range == LPFC_PCI_BAR_BROWSE) {
+ if (idiag.offset.last_rd >= bar_size)
+ idiag.offset.last_rd = 0;
+ } else {
+ if (offset_run >= offset +
+ (acc_range * sizeof(uint32_t)))
+ idiag.offset.last_rd = offset;
+ }
+ } else {
+ if (acc_range == LPFC_PCI_BAR_BROWSE)
+ idiag.offset.last_rd = 0;
+ else
+ idiag.offset.last_rd = offset;
+ }
+
+ return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and
+ * then perform the syntax check for PCI bar memory mapped space read or
+ * write command accordingly. In the case of PCI bar memory mapped space
+ * read command, it sets up the command in the idiag command struct for
+ * the debugfs read operation. In the case of PCI bar memorpy mapped space
+ * write operation, it executes the write operation into the PCI bar memory
+ * mapped space accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ */
+static ssize_t
+lpfc_idiag_baracc_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ uint32_t bar_num, bar_size, offset, value, acc_range;
+ struct pci_dev *pdev;
+ void __iomem *mem_mapped_bar;
+ uint32_t if_type;
+ uint32_t u32val;
+ int rc;
+
+ pdev = phba->pcidev;
+ if (!pdev)
+ return -EFAULT;
+
+ /* This is a user write operation */
+ debug->op = LPFC_IDIAG_OP_WR;
+
+ rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+ if (rc < 0)
+ return rc;
+
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
+
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+ if ((bar_num != IDIAG_BARACC_BAR_0) &&
+ (bar_num != IDIAG_BARACC_BAR_1) &&
+ (bar_num != IDIAG_BARACC_BAR_2))
+ goto error_out;
+ } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+ if (bar_num != IDIAG_BARACC_BAR_0)
+ goto error_out;
+ } else
+ goto error_out;
+
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+ if (bar_num == IDIAG_BARACC_BAR_0) {
+ idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+ LPFC_PCI_IF0_BAR0_SIZE;
+ mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+ } else if (bar_num == IDIAG_BARACC_BAR_1) {
+ idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+ LPFC_PCI_IF0_BAR1_SIZE;
+ mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
+ } else if (bar_num == IDIAG_BARACC_BAR_2) {
+ idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+ LPFC_PCI_IF0_BAR2_SIZE;
+ mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
+ } else
+ goto error_out;
+ } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+ if (bar_num == IDIAG_BARACC_BAR_0) {
+ idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+ LPFC_PCI_IF2_BAR0_SIZE;
+ mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+ } else
+ goto error_out;
+ } else
+ goto error_out;
+
+ offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
+ if (offset % sizeof(uint32_t))
+ goto error_out;
+
+ bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
+ /* Sanity check on PCI config read command line arguments */
+ if (rc != LPFC_PCI_BAR_RD_CMD_ARG)
+ goto error_out;
+ acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
+ if (acc_range == LPFC_PCI_BAR_BROWSE) {
+ if (offset > bar_size - sizeof(uint32_t))
+ goto error_out;
+ /* Starting offset to browse */
+ idiag.offset.last_rd = offset;
+ } else if (acc_range > SINGLE_WORD) {
+ if (offset + acc_range * sizeof(uint32_t) > bar_size)
+ goto error_out;
+ /* Starting offset to browse */
+ idiag.offset.last_rd = offset;
+ } else if (acc_range != SINGLE_WORD)
+ goto error_out;
+ } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR ||
+ idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST ||
+ idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
+ /* Sanity check on PCI bar write command line arguments */
+ if (rc != LPFC_PCI_BAR_WR_CMD_ARG)
+ goto error_out;
+ /* Write command to PCI bar space, read-modify-write */
+ acc_range = SINGLE_WORD;
+ value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX];
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) {
+ writel(value, mem_mapped_bar + offset);
+ readl(mem_mapped_bar + offset);
+ }
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) {
+ u32val = readl(mem_mapped_bar + offset);
+ u32val |= value;
+ writel(u32val, mem_mapped_bar + offset);
+ readl(mem_mapped_bar + offset);
+ }
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
+ u32val = readl(mem_mapped_bar + offset);
+ u32val &= ~value;
+ writel(u32val, mem_mapped_bar + offset);
+ readl(mem_mapped_bar + offset);
+ }
+ } else
+ /* All other opecodes are illegal for now */
+ goto error_out;
+
+ return nbytes;
+error_out:
+ memset(&idiag, 0, sizeof(idiag));
+ return -EINVAL;
+}
+
+/**
* lpfc_idiag_queinfo_read - idiag debugfs read queue information
* @file: The file pointer to read from.
* @buf: The buffer to copy the data to.
@@ -1870,8 +2263,8 @@ lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
return 0;
if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
- index = idiag.cmd.data[2];
- count = idiag.cmd.data[3];
+ index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
+ count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
pque = (struct lpfc_queue *)idiag.ptr_private;
} else
return 0;
@@ -1943,12 +2336,12 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
return rc;
/* Get and sanity check on command feilds */
- quetp = idiag.cmd.data[0];
- queid = idiag.cmd.data[1];
- index = idiag.cmd.data[2];
- count = idiag.cmd.data[3];
- offset = idiag.cmd.data[4];
- value = idiag.cmd.data[5];
+ quetp = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX];
+ queid = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX];
+ index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
+ count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
+ offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX];
+ value = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX];
/* Sanity check on command line arguments */
if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
@@ -2217,7 +2610,7 @@ lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
return 0;
if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
- drb_reg_id = idiag.cmd.data[0];
+ drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
else
return 0;
@@ -2256,7 +2649,7 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
{
struct lpfc_debug *debug = file->private_data;
struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
- uint32_t drb_reg_id, value, reg_val;
+ uint32_t drb_reg_id, value, reg_val = 0;
void __iomem *drb_reg;
int rc;
@@ -2268,8 +2661,8 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
return rc;
/* Sanity check on command line arguments */
- drb_reg_id = idiag.cmd.data[0];
- value = idiag.cmd.data[1];
+ drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
+ value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX];
if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
@@ -2329,6 +2722,679 @@ error_out:
return -EINVAL;
}
+/**
+ * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers
+ * @phba: The pointer to hba structure.
+ * @pbuffer: The pointer to the buffer to copy the data to.
+ * @len: The lenght of bytes to copied.
+ * @drbregid: The id to doorbell registers.
+ *
+ * Description:
+ * This routine reads a control register and copies its content to the
+ * user buffer pointed to by @pbuffer.
+ *
+ * Returns:
+ * This function returns the amount of data that was copied into @pbuffer.
+ **/
+static int
+lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
+ int len, uint32_t ctlregid)
+{
+
+ if (!pbuffer)
+ return 0;
+
+ switch (ctlregid) {
+ case LPFC_CTL_PORT_SEM:
+ len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+ "Port SemReg: 0x%08x\n",
+ readl(phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_SEM_OFFSET));
+ break;
+ case LPFC_CTL_PORT_STA:
+ len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+ "Port StaReg: 0x%08x\n",
+ readl(phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_STA_OFFSET));
+ break;
+ case LPFC_CTL_PORT_CTL:
+ len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+ "Port CtlReg: 0x%08x\n",
+ readl(phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_CTL_OFFSET));
+ break;
+ case LPFC_CTL_PORT_ER1:
+ len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+ "Port Er1Reg: 0x%08x\n",
+ readl(phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_ER1_OFFSET));
+ break;
+ case LPFC_CTL_PORT_ER2:
+ len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+ "Port Er2Reg: 0x%08x\n",
+ readl(phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_ER2_OFFSET));
+ break;
+ case LPFC_CTL_PDEV_CTL:
+ len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+ "PDev CtlReg: 0x%08x\n",
+ readl(phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PDEV_CTL_OFFSET));
+ break;
+ default:
+ break;
+ }
+ return len;
+}
+
+/**
+ * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba port and device registers according
+ * to the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ uint32_t ctl_reg_id, i;
+ char *pbuffer;
+ int len = 0;
+
+ /* This is a user read operation */
+ debug->op = LPFC_IDIAG_OP_RD;
+
+ if (!debug->buffer)
+ debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
+ if (!debug->buffer)
+ return 0;
+ pbuffer = debug->buffer;
+
+ if (*ppos)
+ return 0;
+
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD)
+ ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
+ else
+ return 0;
+
+ if (ctl_reg_id == LPFC_CTL_ACC_ALL)
+ for (i = 1; i <= LPFC_CTL_MAX; i++)
+ len = lpfc_idiag_ctlacc_read_reg(phba,
+ pbuffer, len, i);
+ else
+ len = lpfc_idiag_ctlacc_read_reg(phba,
+ pbuffer, len, ctl_reg_id);
+
+ return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for port and device control register read (dump)
+ * or write (set) command accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_ctlacc_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ uint32_t ctl_reg_id, value, reg_val = 0;
+ void __iomem *ctl_reg;
+ int rc;
+
+ /* This is a user write operation */
+ debug->op = LPFC_IDIAG_OP_WR;
+
+ rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+ if (rc < 0)
+ return rc;
+
+ /* Sanity check on command line arguments */
+ ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
+ value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX];
+
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
+ idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
+ idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+ if (rc != LPFC_CTL_ACC_WR_CMD_ARG)
+ goto error_out;
+ if (ctl_reg_id > LPFC_CTL_MAX)
+ goto error_out;
+ } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) {
+ if (rc != LPFC_CTL_ACC_RD_CMD_ARG)
+ goto error_out;
+ if ((ctl_reg_id > LPFC_CTL_MAX) &&
+ (ctl_reg_id != LPFC_CTL_ACC_ALL))
+ goto error_out;
+ } else
+ goto error_out;
+
+ /* Perform the write access operation */
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
+ idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
+ idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+ switch (ctl_reg_id) {
+ case LPFC_CTL_PORT_SEM:
+ ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_SEM_OFFSET;
+ break;
+ case LPFC_CTL_PORT_STA:
+ ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_STA_OFFSET;
+ break;
+ case LPFC_CTL_PORT_CTL:
+ ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_CTL_OFFSET;
+ break;
+ case LPFC_CTL_PORT_ER1:
+ ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_ER1_OFFSET;
+ break;
+ case LPFC_CTL_PORT_ER2:
+ ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PORT_ER2_OFFSET;
+ break;
+ case LPFC_CTL_PDEV_CTL:
+ ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_CTL_PDEV_CTL_OFFSET;
+ break;
+ default:
+ goto error_out;
+ }
+
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR)
+ reg_val = value;
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) {
+ reg_val = readl(ctl_reg);
+ reg_val |= value;
+ }
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+ reg_val = readl(ctl_reg);
+ reg_val &= ~value;
+ }
+ writel(reg_val, ctl_reg);
+ readl(ctl_reg); /* flush */
+ }
+ return nbytes;
+
+error_out:
+ /* Clean out command structure on command error out */
+ memset(&idiag, 0, sizeof(idiag));
+ return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup
+ * @phba: Pointer to HBA context object.
+ * @pbuffer: Pointer to data buffer.
+ *
+ * Description:
+ * This routine gets the driver mailbox access debugfs setup information.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static int
+lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer)
+{
+ uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
+ int len = 0;
+
+ mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+ mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+ mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+ mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+ len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+ "mbx_dump_map: 0x%08x\n", mbx_dump_map);
+ len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+ "mbx_dump_cnt: %04d\n", mbx_dump_cnt);
+ len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+ "mbx_word_cnt: %04d\n", mbx_word_cnt);
+ len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+ "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd);
+
+ return len;
+}
+
+/**
+ * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba driver mailbox access debugfs setup
+ * information.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ char *pbuffer;
+ int len = 0;
+
+ /* This is a user read operation */
+ debug->op = LPFC_IDIAG_OP_RD;
+
+ if (!debug->buffer)
+ debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL);
+ if (!debug->buffer)
+ return 0;
+ pbuffer = debug->buffer;
+
+ if (*ppos)
+ return 0;
+
+ if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) &&
+ (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP))
+ return 0;
+
+ len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer);
+
+ return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for driver mailbox command (dump) and sets up the
+ * necessary states in the idiag command struct accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
+ int rc;
+
+ /* This is a user write operation */
+ debug->op = LPFC_IDIAG_OP_WR;
+
+ rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+ if (rc < 0)
+ return rc;
+
+ /* Sanity check on command line arguments */
+ mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+ mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+ mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+ mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+ if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) {
+ if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL))
+ goto error_out;
+ if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) &&
+ (mbx_dump_map != LPFC_MBX_DMP_ALL))
+ goto error_out;
+ if (mbx_word_cnt > sizeof(MAILBOX_t))
+ goto error_out;
+ } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) {
+ if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL))
+ goto error_out;
+ if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) &&
+ (mbx_dump_map != LPFC_MBX_DMP_ALL))
+ goto error_out;
+ if (mbx_word_cnt > (BSG_MBOX_SIZE)/4)
+ goto error_out;
+ if (mbx_mbox_cmd != 0x9b)
+ goto error_out;
+ } else
+ goto error_out;
+
+ if (mbx_word_cnt == 0)
+ goto error_out;
+ if (rc != LPFC_MBX_DMP_ARG)
+ goto error_out;
+ if (mbx_mbox_cmd & ~0xff)
+ goto error_out;
+
+ /* condition for stop mailbox dump */
+ if (mbx_dump_cnt == 0)
+ goto reset_out;
+
+ return nbytes;
+
+reset_out:
+ /* Clean out command structure on command error out */
+ memset(&idiag, 0, sizeof(idiag));
+ return nbytes;
+
+error_out:
+ /* Clean out command structure on command error out */
+ memset(&idiag, 0, sizeof(idiag));
+ return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_extacc_avail_get - get the available extents information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the available extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+ uint16_t ext_cnt, ext_size;
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\nAvailable Extents Information:\n");
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tPort Available VPI extents: ");
+ lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI,
+ &ext_cnt, &ext_size);
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tPort Available VFI extents: ");
+ lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI,
+ &ext_cnt, &ext_size);
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tPort Available RPI extents: ");
+ lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI,
+ &ext_cnt, &ext_size);
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tPort Available XRI extents: ");
+ lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI,
+ &ext_cnt, &ext_size);
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+ return len;
+}
+
+/**
+ * lpfc_idiag_extacc_alloc_get - get the allocated extents information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the allocated extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+ uint16_t ext_cnt, ext_size;
+ int rc;
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\nAllocated Extents Information:\n");
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tHost Allocated VPI extents: ");
+ rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI,
+ &ext_cnt, &ext_size);
+ if (!rc)
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Port %d Extent %3d, Size %3d\n",
+ phba->brd_no, ext_cnt, ext_size);
+ else
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "N/A\n");
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tHost Allocated VFI extents: ");
+ rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI,
+ &ext_cnt, &ext_size);
+ if (!rc)
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Port %d Extent %3d, Size %3d\n",
+ phba->brd_no, ext_cnt, ext_size);
+ else
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "N/A\n");
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tHost Allocated RPI extents: ");
+ rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI,
+ &ext_cnt, &ext_size);
+ if (!rc)
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Port %d Extent %3d, Size %3d\n",
+ phba->brd_no, ext_cnt, ext_size);
+ else
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "N/A\n");
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tHost Allocated XRI extents: ");
+ rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI,
+ &ext_cnt, &ext_size);
+ if (!rc)
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "Port %d Extent %3d, Size %3d\n",
+ phba->brd_no, ext_cnt, ext_size);
+ else
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "N/A\n");
+
+ return len;
+}
+
+/**
+ * lpfc_idiag_extacc_drivr_get - get driver extent information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the driver extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+ struct lpfc_rsrc_blks *rsrc_blks;
+ int index;
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\nDriver Extents Information:\n");
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tVPI extents:\n");
+ index = 0;
+ list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) {
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\t\tBlock %3d: Start %4d, Count %4d\n",
+ index, rsrc_blks->rsrc_start,
+ rsrc_blks->rsrc_size);
+ index++;
+ }
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tVFI extents:\n");
+ index = 0;
+ list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list,
+ list) {
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\t\tBlock %3d: Start %4d, Count %4d\n",
+ index, rsrc_blks->rsrc_start,
+ rsrc_blks->rsrc_size);
+ index++;
+ }
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tRPI extents:\n");
+ index = 0;
+ list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list,
+ list) {
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\t\tBlock %3d: Start %4d, Count %4d\n",
+ index, rsrc_blks->rsrc_start,
+ rsrc_blks->rsrc_size);
+ index++;
+ }
+
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\tXRI extents:\n");
+ index = 0;
+ list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list,
+ list) {
+ len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+ "\t\tBlock %3d: Start %4d, Count %4d\n",
+ index, rsrc_blks->rsrc_start,
+ rsrc_blks->rsrc_size);
+ index++;
+ }
+
+ return len;
+}
+
+/**
+ * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for extent information access commands and sets
+ * up the necessary states in the idiag command struct accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_extacc_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ uint32_t ext_map;
+ int rc;
+
+ /* This is a user write operation */
+ debug->op = LPFC_IDIAG_OP_WR;
+
+ rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+ if (rc < 0)
+ return rc;
+
+ ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
+
+ if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
+ goto error_out;
+ if (rc != LPFC_EXT_ACC_CMD_ARG)
+ goto error_out;
+ if (!(ext_map & LPFC_EXT_ACC_ALL))
+ goto error_out;
+
+ return nbytes;
+error_out:
+ /* Clean out command structure on command error out */
+ memset(&idiag, 0, sizeof(idiag));
+ return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_extacc_read - idiag debugfs read access to extent information
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the proper extent information according to
+ * the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ char *pbuffer;
+ uint32_t ext_map;
+ int len = 0;
+
+ /* This is a user read operation */
+ debug->op = LPFC_IDIAG_OP_RD;
+
+ if (!debug->buffer)
+ debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL);
+ if (!debug->buffer)
+ return 0;
+ pbuffer = debug->buffer;
+ if (*ppos)
+ return 0;
+ if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
+ return 0;
+
+ ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
+ if (ext_map & LPFC_EXT_ACC_AVAIL)
+ len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len);
+ if (ext_map & LPFC_EXT_ACC_ALLOC)
+ len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len);
+ if (ext_map & LPFC_EXT_ACC_DRIVR)
+ len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len);
+
+ return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
#undef lpfc_debugfs_op_disc_trc
static const struct file_operations lpfc_debugfs_op_disc_trc = {
.owner = THIS_MODULE,
@@ -2394,6 +3460,16 @@ static const struct file_operations lpfc_debugfs_op_dumpDif = {
.release = lpfc_debugfs_dumpDataDif_release,
};
+#undef lpfc_debugfs_op_dif_err
+static const struct file_operations lpfc_debugfs_op_dif_err = {
+ .owner = THIS_MODULE,
+ .open = lpfc_debugfs_dif_err_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_debugfs_dif_err_read,
+ .write = lpfc_debugfs_dif_err_write,
+ .release = lpfc_debugfs_dif_err_release,
+};
+
#undef lpfc_debugfs_op_slow_ring_trc
static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
.owner = THIS_MODULE,
@@ -2419,6 +3495,16 @@ static const struct file_operations lpfc_idiag_op_pciCfg = {
.release = lpfc_idiag_cmd_release,
};
+#undef lpfc_idiag_op_barAcc
+static const struct file_operations lpfc_idiag_op_barAcc = {
+ .owner = THIS_MODULE,
+ .open = lpfc_idiag_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_idiag_baracc_read,
+ .write = lpfc_idiag_baracc_write,
+ .release = lpfc_idiag_cmd_release,
+};
+
#undef lpfc_idiag_op_queInfo
static const struct file_operations lpfc_idiag_op_queInfo = {
.owner = THIS_MODULE,
@@ -2427,7 +3513,7 @@ static const struct file_operations lpfc_idiag_op_queInfo = {
.release = lpfc_idiag_release,
};
-#undef lpfc_idiag_op_queacc
+#undef lpfc_idiag_op_queAcc
static const struct file_operations lpfc_idiag_op_queAcc = {
.owner = THIS_MODULE,
.open = lpfc_idiag_open,
@@ -2437,7 +3523,7 @@ static const struct file_operations lpfc_idiag_op_queAcc = {
.release = lpfc_idiag_cmd_release,
};
-#undef lpfc_idiag_op_drbacc
+#undef lpfc_idiag_op_drbAcc
static const struct file_operations lpfc_idiag_op_drbAcc = {
.owner = THIS_MODULE,
.open = lpfc_idiag_open,
@@ -2447,7 +3533,233 @@ static const struct file_operations lpfc_idiag_op_drbAcc = {
.release = lpfc_idiag_cmd_release,
};
+#undef lpfc_idiag_op_ctlAcc
+static const struct file_operations lpfc_idiag_op_ctlAcc = {
+ .owner = THIS_MODULE,
+ .open = lpfc_idiag_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_idiag_ctlacc_read,
+ .write = lpfc_idiag_ctlacc_write,
+ .release = lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_mbxAcc
+static const struct file_operations lpfc_idiag_op_mbxAcc = {
+ .owner = THIS_MODULE,
+ .open = lpfc_idiag_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_idiag_mbxacc_read,
+ .write = lpfc_idiag_mbxacc_write,
+ .release = lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_extAcc
+static const struct file_operations lpfc_idiag_op_extAcc = {
+ .owner = THIS_MODULE,
+ .open = lpfc_idiag_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_idiag_extacc_read,
+ .write = lpfc_idiag_extacc_write,
+ .release = lpfc_idiag_cmd_release,
+};
+
+#endif
+
+/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a DMA buffer descriptor.
+ *
+ * Description:
+ * This routine dump a bsg pass-through non-embedded mailbox command with
+ * external buffer.
+ **/
+void
+lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp,
+ enum mbox_type mbox_tp, enum dma_type dma_tp,
+ enum sta_type sta_tp,
+ struct lpfc_dmabuf *dmabuf, uint32_t ext_buf)
+{
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt;
+ char line_buf[LPFC_MBX_ACC_LBUF_SZ];
+ int len = 0;
+ uint32_t do_dump = 0;
+ uint32_t *pword;
+ uint32_t i;
+
+ if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)
+ return;
+
+ mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+ mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+ mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+ mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+ if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) ||
+ (*mbx_dump_cnt == 0) ||
+ (*mbx_word_cnt == 0))
+ return;
+
+ if (*mbx_mbox_cmd != 0x9B)
+ return;
+
+ if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) {
+ if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) {
+ do_dump |= LPFC_BSG_DMP_MBX_RD_MBX;
+ printk(KERN_ERR "\nRead mbox command (x%x), "
+ "nemb:0x%x, extbuf_cnt:%d:\n",
+ sta_tp, nemb_tp, ext_buf);
+ }
+ }
+ if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) {
+ if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) {
+ do_dump |= LPFC_BSG_DMP_MBX_RD_BUF;
+ printk(KERN_ERR "\nRead mbox buffer (x%x), "
+ "nemb:0x%x, extbuf_seq:%d:\n",
+ sta_tp, nemb_tp, ext_buf);
+ }
+ }
+ if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) {
+ if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) {
+ do_dump |= LPFC_BSG_DMP_MBX_WR_MBX;
+ printk(KERN_ERR "\nWrite mbox command (x%x), "
+ "nemb:0x%x, extbuf_cnt:%d:\n",
+ sta_tp, nemb_tp, ext_buf);
+ }
+ }
+ if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) {
+ if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) {
+ do_dump |= LPFC_BSG_DMP_MBX_WR_BUF;
+ printk(KERN_ERR "\nWrite mbox buffer (x%x), "
+ "nemb:0x%x, extbuf_seq:%d:\n",
+ sta_tp, nemb_tp, ext_buf);
+ }
+ }
+
+ /* dump buffer content */
+ if (do_dump) {
+ pword = (uint32_t *)dmabuf->virt;
+ for (i = 0; i < *mbx_word_cnt; i++) {
+ if (!(i % 8)) {
+ if (i != 0)
+ printk(KERN_ERR "%s\n", line_buf);
+ len = 0;
+ len += snprintf(line_buf+len,
+ LPFC_MBX_ACC_LBUF_SZ-len,
+ "%03d: ", i);
+ }
+ len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
+ "%08x ", (uint32_t)*pword);
+ pword++;
+ }
+ if ((i - 1) % 8)
+ printk(KERN_ERR "%s\n", line_buf);
+ (*mbx_dump_cnt)--;
+ }
+
+ /* Clean out command structure on reaching dump count */
+ if (*mbx_dump_cnt == 0)
+ memset(&idiag, 0, sizeof(idiag));
+ return;
+#endif
+}
+
+/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a DMA buffer descriptor.
+ *
+ * Description:
+ * This routine dump a pass-through non-embedded mailbox command from issue
+ * mailbox command.
+ **/
+void
+lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox)
+{
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd;
+ char line_buf[LPFC_MBX_ACC_LBUF_SZ];
+ int len = 0;
+ uint32_t *pword;
+ uint8_t *pbyte;
+ uint32_t i, j;
+
+ if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP)
+ return;
+
+ mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+ mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+ mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+ mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+ if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) ||
+ (*mbx_dump_cnt == 0) ||
+ (*mbx_word_cnt == 0))
+ return;
+
+ if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) &&
+ (*mbx_mbox_cmd != pmbox->mbxCommand))
+ return;
+
+ /* dump buffer content */
+ if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) {
+ printk(KERN_ERR "Mailbox command:0x%x dump by word:\n",
+ pmbox->mbxCommand);
+ pword = (uint32_t *)pmbox;
+ for (i = 0; i < *mbx_word_cnt; i++) {
+ if (!(i % 8)) {
+ if (i != 0)
+ printk(KERN_ERR "%s\n", line_buf);
+ len = 0;
+ memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
+ len += snprintf(line_buf+len,
+ LPFC_MBX_ACC_LBUF_SZ-len,
+ "%03d: ", i);
+ }
+ len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
+ "%08x ",
+ ((uint32_t)*pword) & 0xffffffff);
+ pword++;
+ }
+ if ((i - 1) % 8)
+ printk(KERN_ERR "%s\n", line_buf);
+ printk(KERN_ERR "\n");
+ }
+ if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) {
+ printk(KERN_ERR "Mailbox command:0x%x dump by byte:\n",
+ pmbox->mbxCommand);
+ pbyte = (uint8_t *)pmbox;
+ for (i = 0; i < *mbx_word_cnt; i++) {
+ if (!(i % 8)) {
+ if (i != 0)
+ printk(KERN_ERR "%s\n", line_buf);
+ len = 0;
+ memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
+ len += snprintf(line_buf+len,
+ LPFC_MBX_ACC_LBUF_SZ-len,
+ "%03d: ", i);
+ }
+ for (j = 0; j < 4; j++) {
+ len += snprintf(line_buf+len,
+ LPFC_MBX_ACC_LBUF_SZ-len,
+ "%02x",
+ ((uint8_t)*pbyte) & 0xff);
+ pbyte++;
+ }
+ len += snprintf(line_buf+len,
+ LPFC_MBX_ACC_LBUF_SZ-len, " ");
+ }
+ if ((i - 1) % 8)
+ printk(KERN_ERR "%s\n", line_buf);
+ printk(KERN_ERR "\n");
+ }
+ (*mbx_dump_cnt)--;
+
+ /* Clean out command structure on reaching dump count */
+ if (*mbx_dump_cnt == 0)
+ memset(&idiag, 0, sizeof(idiag));
+ return;
#endif
+}
/**
* lpfc_debugfs_initialize - Initialize debugfs for a vport
@@ -2566,6 +3878,74 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
goto debug_failed;
}
+ /* Setup DIF Error Injections */
+ snprintf(name, sizeof(name), "InjErrLBA");
+ phba->debug_InjErrLBA =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_InjErrLBA) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0807 Cannot create debugfs InjErrLBA\n");
+ goto debug_failed;
+ }
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+
+ snprintf(name, sizeof(name), "writeGuardInjErr");
+ phba->debug_writeGuard =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_writeGuard) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0802 Cannot create debugfs writeGuard\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "writeAppInjErr");
+ phba->debug_writeApp =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_writeApp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0803 Cannot create debugfs writeApp\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "writeRefInjErr");
+ phba->debug_writeRef =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_writeRef) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0804 Cannot create debugfs writeRef\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "readAppInjErr");
+ phba->debug_readApp =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_readApp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0805 Cannot create debugfs readApp\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "readRefInjErr");
+ phba->debug_readRef =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_readRef) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0806 Cannot create debugfs readApp\n");
+ goto debug_failed;
+ }
+
/* Setup slow ring trace */
if (lpfc_debugfs_max_slow_ring_trc) {
num = lpfc_debugfs_max_slow_ring_trc - 1;
@@ -2672,7 +4052,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
vport, &lpfc_debugfs_op_nodelist);
if (!vport->debug_nodelist) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Can't create debugfs nodelist\n");
+ "2985 Can't create debugfs nodelist\n");
goto debug_failed;
}
@@ -2709,6 +4089,20 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
idiag.offset.last_rd = 0;
}
+ /* iDiag PCI BAR access */
+ snprintf(name, sizeof(name), "barAcc");
+ if (!phba->idiag_bar_acc) {
+ phba->idiag_bar_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
+ if (!phba->idiag_bar_acc) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "3056 Can't create idiag debugfs\n");
+ goto debug_failed;
+ }
+ idiag.offset.last_rd = 0;
+ }
+
/* iDiag get PCI function queue information */
snprintf(name, sizeof(name), "queInfo");
if (!phba->idiag_que_info) {
@@ -2748,6 +4142,50 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
}
}
+ /* iDiag access PCI function control registers */
+ snprintf(name, sizeof(name), "ctlAcc");
+ if (!phba->idiag_ctl_acc) {
+ phba->idiag_ctl_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
+ if (!phba->idiag_ctl_acc) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "2981 Can't create idiag debugfs\n");
+ goto debug_failed;
+ }
+ }
+
+ /* iDiag access mbox commands */
+ snprintf(name, sizeof(name), "mbxAcc");
+ if (!phba->idiag_mbx_acc) {
+ phba->idiag_mbx_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
+ if (!phba->idiag_mbx_acc) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "2980 Can't create idiag debugfs\n");
+ goto debug_failed;
+ }
+ }
+
+ /* iDiag extents access commands */
+ if (phba->sli4_hba.extents_in_use) {
+ snprintf(name, sizeof(name), "extAcc");
+ if (!phba->idiag_ext_acc) {
+ phba->idiag_ext_acc =
+ debugfs_create_file(name,
+ S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba,
+ &lpfc_idiag_op_extAcc);
+ if (!phba->idiag_ext_acc) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "2986 Cant create "
+ "idiag debugfs\n");
+ goto debug_failed;
+ }
+ }
+ }
+
debug_failed:
return;
#endif
@@ -2782,7 +4220,6 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(vport->debug_nodelist); /* nodelist */
vport->debug_nodelist = NULL;
}
-
if (vport->vport_debugfs_root) {
debugfs_remove(vport->vport_debugfs_root); /* vportX */
vport->vport_debugfs_root = NULL;
@@ -2811,6 +4248,30 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(phba->debug_dumpDif); /* dumpDif */
phba->debug_dumpDif = NULL;
}
+ if (phba->debug_InjErrLBA) {
+ debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
+ phba->debug_InjErrLBA = NULL;
+ }
+ if (phba->debug_writeGuard) {
+ debugfs_remove(phba->debug_writeGuard); /* writeGuard */
+ phba->debug_writeGuard = NULL;
+ }
+ if (phba->debug_writeApp) {
+ debugfs_remove(phba->debug_writeApp); /* writeApp */
+ phba->debug_writeApp = NULL;
+ }
+ if (phba->debug_writeRef) {
+ debugfs_remove(phba->debug_writeRef); /* writeRef */
+ phba->debug_writeRef = NULL;
+ }
+ if (phba->debug_readApp) {
+ debugfs_remove(phba->debug_readApp); /* readApp */
+ phba->debug_readApp = NULL;
+ }
+ if (phba->debug_readRef) {
+ debugfs_remove(phba->debug_readRef); /* readRef */
+ phba->debug_readRef = NULL;
+ }
if (phba->slow_ring_trc) {
kfree(phba->slow_ring_trc);
@@ -2826,6 +4287,21 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
* iDiag release
*/
if (phba->sli_rev == LPFC_SLI_REV4) {
+ if (phba->idiag_ext_acc) {
+ /* iDiag extAcc */
+ debugfs_remove(phba->idiag_ext_acc);
+ phba->idiag_ext_acc = NULL;
+ }
+ if (phba->idiag_mbx_acc) {
+ /* iDiag mbxAcc */
+ debugfs_remove(phba->idiag_mbx_acc);
+ phba->idiag_mbx_acc = NULL;
+ }
+ if (phba->idiag_ctl_acc) {
+ /* iDiag ctlAcc */
+ debugfs_remove(phba->idiag_ctl_acc);
+ phba->idiag_ctl_acc = NULL;
+ }
if (phba->idiag_drb_acc) {
/* iDiag drbAcc */
debugfs_remove(phba->idiag_drb_acc);
@@ -2841,6 +4317,11 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(phba->idiag_que_info);
phba->idiag_que_info = NULL;
}
+ if (phba->idiag_bar_acc) {
+ /* iDiag barAcc */
+ debugfs_remove(phba->idiag_bar_acc);
+ phba->idiag_bar_acc = NULL;
+ }
if (phba->idiag_pci_cfg) {
/* iDiag pciCfg */
debugfs_remove(phba->idiag_pci_cfg);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 6525a5e..f83bd94 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -39,14 +39,51 @@
/* hbqinfo output buffer size */
#define LPFC_HBQINFO_SIZE 8192
+/*
+ * For SLI4 iDiag debugfs diagnostics tool
+ */
+
/* pciConf */
#define LPFC_PCI_CFG_BROWSE 0xffff
#define LPFC_PCI_CFG_RD_CMD_ARG 2
#define LPFC_PCI_CFG_WR_CMD_ARG 3
#define LPFC_PCI_CFG_SIZE 4096
-#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
+#define IDIAG_PCICFG_WHERE_INDX 0
+#define IDIAG_PCICFG_COUNT_INDX 1
+#define IDIAG_PCICFG_VALUE_INDX 2
+
+/* barAcc */
+#define LPFC_PCI_BAR_BROWSE 0xffff
+#define LPFC_PCI_BAR_RD_CMD_ARG 3
+#define LPFC_PCI_BAR_WR_CMD_ARG 3
+
+#define LPFC_PCI_IF0_BAR0_SIZE (1024 * 16)
+#define LPFC_PCI_IF0_BAR1_SIZE (1024 * 128)
+#define LPFC_PCI_IF0_BAR2_SIZE (1024 * 128)
+#define LPFC_PCI_IF2_BAR0_SIZE (1024 * 32)
+
+#define LPFC_PCI_BAR_RD_BUF_SIZE 4096
+#define LPFC_PCI_BAR_RD_SIZE (LPFC_PCI_BAR_RD_BUF_SIZE/4)
+
+#define LPFC_PCI_IF0_BAR0_RD_SIZE (LPFC_PCI_IF0_BAR0_SIZE/4)
+#define LPFC_PCI_IF0_BAR1_RD_SIZE (LPFC_PCI_IF0_BAR1_SIZE/4)
+#define LPFC_PCI_IF0_BAR2_RD_SIZE (LPFC_PCI_IF0_BAR2_SIZE/4)
+#define LPFC_PCI_IF2_BAR0_RD_SIZE (LPFC_PCI_IF2_BAR0_SIZE/4)
+
+#define IDIAG_BARACC_BAR_NUM_INDX 0
+#define IDIAG_BARACC_OFF_SET_INDX 1
+#define IDIAG_BARACC_ACC_MOD_INDX 2
+#define IDIAG_BARACC_REG_VAL_INDX 2
+#define IDIAG_BARACC_BAR_SZE_INDX 3
+
+#define IDIAG_BARACC_BAR_0 0
+#define IDIAG_BARACC_BAR_1 1
+#define IDIAG_BARACC_BAR_2 2
+
+#define SINGLE_WORD 1
+
/* queue info */
#define LPFC_QUE_INFO_GET_BUF_SIZE 4096
@@ -63,7 +100,14 @@
#define LPFC_IDIAG_WQ 4
#define LPFC_IDIAG_RQ 5
-/* doorbell acc */
+#define IDIAG_QUEACC_QUETP_INDX 0
+#define IDIAG_QUEACC_QUEID_INDX 1
+#define IDIAG_QUEACC_INDEX_INDX 2
+#define IDIAG_QUEACC_COUNT_INDX 3
+#define IDIAG_QUEACC_OFFST_INDX 4
+#define IDIAG_QUEACC_VALUE_INDX 5
+
+/* doorbell register acc */
#define LPFC_DRB_ACC_ALL 0xffff
#define LPFC_DRB_ACC_RD_CMD_ARG 1
#define LPFC_DRB_ACC_WR_CMD_ARG 2
@@ -76,6 +120,67 @@
#define LPFC_DRB_MAX 4
+#define IDIAG_DRBACC_REGID_INDX 0
+#define IDIAG_DRBACC_VALUE_INDX 1
+
+/* control register acc */
+#define LPFC_CTL_ACC_ALL 0xffff
+#define LPFC_CTL_ACC_RD_CMD_ARG 1
+#define LPFC_CTL_ACC_WR_CMD_ARG 2
+#define LPFC_CTL_ACC_BUF_SIZE 256
+
+#define LPFC_CTL_PORT_SEM 1
+#define LPFC_CTL_PORT_STA 2
+#define LPFC_CTL_PORT_CTL 3
+#define LPFC_CTL_PORT_ER1 4
+#define LPFC_CTL_PORT_ER2 5
+#define LPFC_CTL_PDEV_CTL 6
+
+#define LPFC_CTL_MAX 6
+
+#define IDIAG_CTLACC_REGID_INDX 0
+#define IDIAG_CTLACC_VALUE_INDX 1
+
+/* mailbox access */
+#define LPFC_MBX_DMP_ARG 4
+
+#define LPFC_MBX_ACC_BUF_SIZE 512
+#define LPFC_MBX_ACC_LBUF_SZ 128
+
+#define LPFC_MBX_DMP_MBX_WORD 0x00000001
+#define LPFC_MBX_DMP_MBX_BYTE 0x00000002
+#define LPFC_MBX_DMP_MBX_ALL (LPFC_MBX_DMP_MBX_WORD | LPFC_MBX_DMP_MBX_BYTE)
+
+#define LPFC_BSG_DMP_MBX_RD_MBX 0x00000001
+#define LPFC_BSG_DMP_MBX_RD_BUF 0x00000002
+#define LPFC_BSG_DMP_MBX_WR_MBX 0x00000004
+#define LPFC_BSG_DMP_MBX_WR_BUF 0x00000008
+#define LPFC_BSG_DMP_MBX_ALL (LPFC_BSG_DMP_MBX_RD_MBX | \
+ LPFC_BSG_DMP_MBX_RD_BUF | \
+ LPFC_BSG_DMP_MBX_WR_MBX | \
+ LPFC_BSG_DMP_MBX_WR_BUF)
+
+#define LPFC_MBX_DMP_ALL 0xffff
+#define LPFC_MBX_ALL_CMD 0xff
+
+#define IDIAG_MBXACC_MBCMD_INDX 0
+#define IDIAG_MBXACC_DPMAP_INDX 1
+#define IDIAG_MBXACC_DPCNT_INDX 2
+#define IDIAG_MBXACC_WDCNT_INDX 3
+
+/* extents access */
+#define LPFC_EXT_ACC_CMD_ARG 1
+#define LPFC_EXT_ACC_BUF_SIZE 4096
+
+#define LPFC_EXT_ACC_AVAIL 0x1
+#define LPFC_EXT_ACC_ALLOC 0x2
+#define LPFC_EXT_ACC_DRIVR 0x4
+#define LPFC_EXT_ACC_ALL (LPFC_EXT_ACC_DRIVR | \
+ LPFC_EXT_ACC_AVAIL | \
+ LPFC_EXT_ACC_ALLOC)
+
+#define IDIAG_EXTACC_EXMAP_INDX 0
+
#define SIZE_U8 sizeof(uint8_t)
#define SIZE_U16 sizeof(uint16_t)
#define SIZE_U32 sizeof(uint32_t)
@@ -110,6 +215,11 @@ struct lpfc_idiag_cmd {
#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
+#define LPFC_IDIAG_CMD_BARACC_RD 0x00000008
+#define LPFC_IDIAG_CMD_BARACC_WR 0x00000009
+#define LPFC_IDIAG_CMD_BARACC_ST 0x0000000a
+#define LPFC_IDIAG_CMD_BARACC_CL 0x0000000b
+
#define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011
#define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012
#define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013
@@ -119,6 +229,17 @@ struct lpfc_idiag_cmd {
#define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022
#define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023
#define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024
+
+#define LPFC_IDIAG_CMD_CTLACC_RD 0x00000031
+#define LPFC_IDIAG_CMD_CTLACC_WR 0x00000032
+#define LPFC_IDIAG_CMD_CTLACC_ST 0x00000033
+#define LPFC_IDIAG_CMD_CTLACC_CL 0x00000034
+
+#define LPFC_IDIAG_CMD_MBXACC_DP 0x00000041
+#define LPFC_IDIAG_BSG_MBXACC_DP 0x00000042
+
+#define LPFC_IDIAG_CMD_EXTACC_RD 0x00000051
+
uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
};
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 1725b81..445826a 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -874,6 +874,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
phba->fcf.current_rec.fcf_indx,
irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->ulpTimeout);
+ lpfc_sli4_set_fcf_flogi_fail(phba,
+ phba->fcf.current_rec.fcf_indx);
fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba);
rc = lpfc_sli4_fcf_rr_next_proc(vport, fcf_index);
if (rc)
@@ -3384,7 +3386,14 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
cmdiocb->context1 = NULL;
}
}
+
+ /*
+ * The driver received a LOGO from the rport and has ACK'd it.
+ * At this point, the driver is done so release the IOCB and
+ * remove the ndlp reference.
+ */
lpfc_els_free_iocb(phba, cmdiocb);
+ lpfc_nlp_put(ndlp);
return;
}
@@ -4080,9 +4089,6 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
phba->fc_stat.elsXmitACC++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
- lpfc_nlp_put(ndlp);
- elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
- * it could be freed */
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
@@ -4164,6 +4170,11 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
psli = &phba->sli;
cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len;
+ /* The accumulated length can exceed the BPL_SIZE. For
+ * now, use this as the limit
+ */
+ if (cmdsize > LPFC_BPL_SIZE)
+ cmdsize = LPFC_BPL_SIZE;
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
ndlp->nlp_DID, ELS_CMD_ACC);
if (!elsiocb)
@@ -4187,9 +4198,6 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
phba->fc_stat.elsXmitACC++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
- lpfc_nlp_put(ndlp);
- elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
- * it could be freed */
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
@@ -7256,16 +7264,11 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
icmd->un.elsreq64.myID = 0;
icmd->un.elsreq64.fl = 1;
- if ((phba->sli_rev == LPFC_SLI_REV4) &&
- (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
- LPFC_SLI_INTF_IF_TYPE_0)) {
- /* FDISC needs to be 1 for WQE VPI */
- elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1;
- elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ;
- /* Set the ulpContext to the vpi */
- elsiocb->iocb.ulpContext = phba->vpi_ids[vport->vpi];
- } else {
- /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
+ /*
+ * SLI3 ports require a different context type value than SLI4.
+ * Catch SLI3 ports here and override the prep.
+ */
+ if (phba->sli_rev == LPFC_SLI_REV3) {
icmd->ulpCt_h = 1;
icmd->ulpCt_l = 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bef17e3..091f68e 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1109,6 +1109,28 @@ out:
return;
}
+/**
+ * lpfc_sli4_clear_fcf_rr_bmask
+ * @phba pointer to the struct lpfc_hba for this port.
+ * This fucnction resets the round robin bit mask and clears the
+ * fcf priority list. The list deletions are done while holding the
+ * hbalock. The ON_LIST flag and the FLOGI_FAILED flags are cleared
+ * from the lpfc_fcf_pri record.
+ **/
+void
+lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *phba)
+{
+ struct lpfc_fcf_pri *fcf_pri;
+ struct lpfc_fcf_pri *next_fcf_pri;
+ memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+ spin_lock_irq(&phba->hbalock);
+ list_for_each_entry_safe(fcf_pri, next_fcf_pri,
+ &phba->fcf.fcf_pri_list, list) {
+ list_del_init(&fcf_pri->list);
+ fcf_pri->fcf_rec.flag = 0;
+ }
+ spin_unlock_irq(&phba->hbalock);
+}
static void
lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
@@ -1130,7 +1152,8 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
spin_unlock_irq(&phba->hbalock);
/* If there is a pending FCoE event, restart FCF table scan. */
- if (lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF))
+ if ((!(phba->hba_flag & FCF_RR_INPROG)) &&
+ lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF))
goto fail_out;
/* Mark successful completion of FCF table scan */
@@ -1250,6 +1273,30 @@ lpfc_vlan_id_match(uint16_t curr_vlan_id, uint16_t new_vlan_id)
}
/**
+ * lpfc_update_fcf_record - Update driver fcf record
+ * __lpfc_update_fcf_record_pri - update the lpfc_fcf_pri record.
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index: Index for the lpfc_fcf_record.
+ * @new_fcf_record: pointer to hba fcf record.
+ *
+ * This routine updates the driver FCF priority record from the new HBA FCF
+ * record. This routine is called with the host lock held.
+ **/
+static void
+__lpfc_update_fcf_record_pri(struct lpfc_hba *phba, uint16_t fcf_index,
+ struct fcf_record *new_fcf_record
+ )
+{
+ struct lpfc_fcf_pri *fcf_pri;
+
+ fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+ fcf_pri->fcf_rec.fcf_index = fcf_index;
+ /* FCF record priority */
+ fcf_pri->fcf_rec.priority = new_fcf_record->fip_priority;
+
+}
+
+/**
* lpfc_copy_fcf_record - Copy fcf information to lpfc_hba.
* @fcf: pointer to driver fcf record.
* @new_fcf_record: pointer to fcf record.
@@ -1332,6 +1379,9 @@ __lpfc_update_fcf_record(struct lpfc_hba *phba, struct lpfc_fcf_rec *fcf_rec,
fcf_rec->addr_mode = addr_mode;
fcf_rec->vlan_id = vlan_id;
fcf_rec->flag |= (flag | RECORD_VALID);
+ __lpfc_update_fcf_record_pri(phba,
+ bf_get(lpfc_fcf_record_fcf_index, new_fcf_record),
+ new_fcf_record);
}
/**
@@ -1362,7 +1412,7 @@ lpfc_register_fcf(struct lpfc_hba *phba)
if (phba->pport->port_state != LPFC_FLOGI) {
phba->hba_flag |= FCF_RR_INPROG;
spin_unlock_irq(&phba->hbalock);
- lpfc_issue_init_vfi(phba->pport);
+ lpfc_initial_flogi(phba->pport);
return;
}
spin_unlock_irq(&phba->hbalock);
@@ -1834,6 +1884,8 @@ lpfc_sli4_fcf_record_match(struct lpfc_hba *phba,
return false;
if (!lpfc_fab_name_match(fcf_rec->fabric_name, new_fcf_record))
return false;
+ if (fcf_rec->priority != new_fcf_record->fip_priority)
+ return false;
return true;
}
@@ -1897,6 +1949,152 @@ stop_flogi_current_fcf:
}
/**
+ * lpfc_sli4_fcf_pri_list_del
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to delete
+ * This routine checks the on list flag of the fcf_index to be deleted.
+ * If it is one the list then it is removed from the list, and the flag
+ * is cleared. This routine grab the hbalock before removing the fcf
+ * record from the list.
+ **/
+static void lpfc_sli4_fcf_pri_list_del(struct lpfc_hba *phba,
+ uint16_t fcf_index)
+{
+ struct lpfc_fcf_pri *new_fcf_pri;
+
+ new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+ lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+ "3058 deleting idx x%x pri x%x flg x%x\n",
+ fcf_index, new_fcf_pri->fcf_rec.priority,
+ new_fcf_pri->fcf_rec.flag);
+ spin_lock_irq(&phba->hbalock);
+ if (new_fcf_pri->fcf_rec.flag & LPFC_FCF_ON_PRI_LIST) {
+ if (phba->fcf.current_rec.priority ==
+ new_fcf_pri->fcf_rec.priority)
+ phba->fcf.eligible_fcf_cnt--;
+ list_del_init(&new_fcf_pri->list);
+ new_fcf_pri->fcf_rec.flag &= ~LPFC_FCF_ON_PRI_LIST;
+ }
+ spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_set_fcf_flogi_fail
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to update
+ * This routine acquires the hbalock and then set the LPFC_FCF_FLOGI_FAILED
+ * flag so the the round robin slection for the particular priority level
+ * will try a different fcf record that does not have this bit set.
+ * If the fcf record is re-read for any reason this flag is cleared brfore
+ * adding it to the priority list.
+ **/
+void
+lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *phba, uint16_t fcf_index)
+{
+ struct lpfc_fcf_pri *new_fcf_pri;
+ new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+ spin_lock_irq(&phba->hbalock);
+ new_fcf_pri->fcf_rec.flag |= LPFC_FCF_FLOGI_FAILED;
+ spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_fcf_pri_list_add
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to add
+ * This routine checks the priority of the fcf_index to be added.
+ * If it is a lower priority than the current head of the fcf_pri list
+ * then it is added to the list in the right order.
+ * If it is the same priority as the current head of the list then it
+ * is added to the head of the list and its bit in the rr_bmask is set.
+ * If the fcf_index to be added is of a higher priority than the current
+ * head of the list then the rr_bmask is cleared, its bit is set in the
+ * rr_bmask and it is added to the head of the list.
+ * returns:
+ * 0=success 1=failure
+ **/
+int lpfc_sli4_fcf_pri_list_add(struct lpfc_hba *phba, uint16_t fcf_index,
+ struct fcf_record *new_fcf_record)
+{
+ uint16_t current_fcf_pri;
+ uint16_t last_index;
+ struct lpfc_fcf_pri *fcf_pri;
+ struct lpfc_fcf_pri *next_fcf_pri;
+ struct lpfc_fcf_pri *new_fcf_pri;
+ int ret;
+
+ new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+ lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+ "3059 adding idx x%x pri x%x flg x%x\n",
+ fcf_index, new_fcf_record->fip_priority,
+ new_fcf_pri->fcf_rec.flag);
+ spin_lock_irq(&phba->hbalock);
+ if (new_fcf_pri->fcf_rec.flag & LPFC_FCF_ON_PRI_LIST)
+ list_del_init(&new_fcf_pri->list);
+ new_fcf_pri->fcf_rec.fcf_index = fcf_index;
+ new_fcf_pri->fcf_rec.priority = new_fcf_record->fip_priority;
+ if (list_empty(&phba->fcf.fcf_pri_list)) {
+ list_add(&new_fcf_pri->list, &phba->fcf.fcf_pri_list);
+ ret = lpfc_sli4_fcf_rr_index_set(phba,
+ new_fcf_pri->fcf_rec.fcf_index);
+ goto out;
+ }
+
+ last_index = find_first_bit(phba->fcf.fcf_rr_bmask,
+ LPFC_SLI4_FCF_TBL_INDX_MAX);
+ if (last_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+ ret = 0; /* Empty rr list */
+ goto out;
+ }
+ current_fcf_pri = phba->fcf.fcf_pri[last_index].fcf_rec.priority;
+ if (new_fcf_pri->fcf_rec.priority <= current_fcf_pri) {
+ list_add(&new_fcf_pri->list, &phba->fcf.fcf_pri_list);
+ if (new_fcf_pri->fcf_rec.priority < current_fcf_pri) {
+ memset(phba->fcf.fcf_rr_bmask, 0,
+ sizeof(*phba->fcf.fcf_rr_bmask));
+ /* fcfs_at_this_priority_level = 1; */
+ phba->fcf.eligible_fcf_cnt = 1;
+ } else
+ /* fcfs_at_this_priority_level++; */
+ phba->fcf.eligible_fcf_cnt++;
+ ret = lpfc_sli4_fcf_rr_index_set(phba,
+ new_fcf_pri->fcf_rec.fcf_index);
+ goto out;
+ }
+
+ list_for_each_entry_safe(fcf_pri, next_fcf_pri,
+ &phba->fcf.fcf_pri_list, list) {
+ if (new_fcf_pri->fcf_rec.priority <=
+ fcf_pri->fcf_rec.priority) {
+ if (fcf_pri->list.prev == &phba->fcf.fcf_pri_list)
+ list_add(&new_fcf_pri->list,
+ &phba->fcf.fcf_pri_list);
+ else
+ list_add(&new_fcf_pri->list,
+ &((struct lpfc_fcf_pri *)
+ fcf_pri->list.prev)->list);
+ ret = 0;
+ goto out;
+ } else if (fcf_pri->list.next == &phba->fcf.fcf_pri_list
+ || new_fcf_pri->fcf_rec.priority <
+ next_fcf_pri->fcf_rec.priority) {
+ list_add(&new_fcf_pri->list, &fcf_pri->list);
+ ret = 0;
+ goto out;
+ }
+ if (new_fcf_pri->fcf_rec.priority > fcf_pri->fcf_rec.priority)
+ continue;
+
+ }
+ ret = 1;
+out:
+ /* we use = instead of |= to clear the FLOGI_FAILED flag. */
+ new_fcf_pri->fcf_rec.flag = LPFC_FCF_ON_PRI_LIST;
+ spin_unlock_irq(&phba->hbalock);
+ return ret;
+}
+
+/**
* lpfc_mbx_cmpl_fcf_scan_read_fcf_rec - fcf scan read_fcf mbox cmpl handler.
* @phba: pointer to lpfc hba data structure.
* @mboxq: pointer to mailbox object.
@@ -1958,6 +2156,9 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
* record for roundrobin FCF failover.
*/
if (!rc) {
+ lpfc_sli4_fcf_pri_list_del(phba,
+ bf_get(lpfc_fcf_record_fcf_index,
+ new_fcf_record));
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
"2781 FCF (x%x) failed connection "
"list check: (x%x/x%x)\n",
@@ -2005,7 +2206,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
goto read_next_fcf;
} else {
fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
- rc = lpfc_sli4_fcf_rr_index_set(phba, fcf_index);
+ rc = lpfc_sli4_fcf_pri_list_add(phba, fcf_index,
+ new_fcf_record);
if (rc)
goto read_next_fcf;
}
@@ -2018,7 +2220,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
*/
spin_lock_irq(&phba->hbalock);
if (phba->fcf.fcf_flag & FCF_IN_USE) {
- if (lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
+ if (phba->cfg_fcf_failover_policy == LPFC_FCF_FOV &&
+ lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
new_fcf_record, vlan_id)) {
if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) ==
phba->fcf.current_rec.fcf_indx) {
@@ -2232,7 +2435,8 @@ read_next_fcf:
(phba->fcf.fcf_flag & FCF_REDISC_PEND))
return;
- if (phba->fcf.fcf_flag & FCF_IN_USE) {
+ if (phba->cfg_fcf_failover_policy == LPFC_FCF_FOV &&
+ phba->fcf.fcf_flag & FCF_IN_USE) {
/*
* In case the current in-use FCF record no
* longer existed during FCF discovery that
@@ -2423,7 +2627,8 @@ lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
/* Update the eligible FCF record index bmask */
fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
- rc = lpfc_sli4_fcf_rr_index_set(phba, fcf_index);
+
+ rc = lpfc_sli4_fcf_pri_list_add(phba, fcf_index, new_fcf_record);
out:
lpfc_sli4_mbox_cmd_free(phba, mboxq);
@@ -2441,7 +2646,9 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
struct lpfc_vport *vport = mboxq->vport;
- if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) {
+ /* VFI not supported on interface type 0, just do the flogi */
+ if (mboxq->u.mb.mbxStatus && (bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_0)) {
lpfc_printf_vlog(vport, KERN_ERR,
LOG_MBOX,
"2891 Init VFI mailbox failed 0x%x\n",
@@ -2450,6 +2657,7 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
}
+
lpfc_initial_flogi(vport);
mempool_free(mboxq, phba->mbox_mem_pool);
return;
@@ -2893,8 +3101,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
goto out;
}
/* Reset FCF roundrobin bmask for new discovery */
- memset(phba->fcf.fcf_rr_bmask, 0,
- sizeof(*phba->fcf.fcf_rr_bmask));
+ lpfc_sli4_clear_fcf_rr_bmask(phba);
}
return;
@@ -5592,7 +5799,7 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
/* Reset FCF roundrobin bmask for new discovery */
- memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+ lpfc_sli4_clear_fcf_rr_bmask(phba);
rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST);
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index df53d10..046edc4 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -2955,18 +2955,18 @@ typedef struct _SLI2_RDSC {
typedef struct _PCB {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t type:8;
-#define TYPE_NATIVE_SLI2 0x01;
+#define TYPE_NATIVE_SLI2 0x01
uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2 0x01;
+#define FEATURE_INITIAL_SLI2 0x01
uint32_t rsvd:12;
uint32_t maxRing:4;
#else /* __LITTLE_ENDIAN_BITFIELD */
uint32_t maxRing:4;
uint32_t rsvd:12;
uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2 0x01;
+#define FEATURE_INITIAL_SLI2 0x01
uint32_t type:8;
-#define TYPE_NATIVE_SLI2 0x01;
+#define TYPE_NATIVE_SLI2 0x01
#endif
uint32_t mailBoxSize;
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 7f8003b..98d2152 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -41,6 +41,8 @@
* Or clear that bit field:
* bf_set(example_bit_field, &t1, 0);
*/
+#define bf_get_be32(name, ptr) \
+ ((be32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bf_get_le32(name, ptr) \
((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bf_get(name, ptr) \
@@ -678,7 +680,6 @@ struct lpfc_register {
#define lpfc_rq_doorbell_num_posted_SHIFT 16
#define lpfc_rq_doorbell_num_posted_MASK 0x3FFF
#define lpfc_rq_doorbell_num_posted_WORD word0
-#define LPFC_RQ_POST_BATCH 8 /* RQEs to post at one time */
#define lpfc_rq_doorbell_id_SHIFT 0
#define lpfc_rq_doorbell_id_MASK 0xFFFF
#define lpfc_rq_doorbell_id_WORD word0
@@ -784,6 +785,8 @@ union lpfc_sli4_cfg_shdr {
#define LPFC_Q_CREATE_VERSION_2 2
#define LPFC_Q_CREATE_VERSION_1 1
#define LPFC_Q_CREATE_VERSION_0 0
+#define LPFC_OPCODE_VERSION_0 0
+#define LPFC_OPCODE_VERSION_1 1
} request;
struct {
uint32_t word6;
@@ -825,6 +828,7 @@ struct mbox_header {
#define LPFC_EXTENT_VERSION_DEFAULT 0
/* Subsystem Definitions */
+#define LPFC_MBOX_SUBSYSTEM_NA 0x0
#define LPFC_MBOX_SUBSYSTEM_COMMON 0x1
#define LPFC_MBOX_SUBSYSTEM_FCOE 0xC
@@ -835,25 +839,34 @@ struct mbox_header {
#define HOST_ENDIAN_HIGH_WORD1 0xFF7856FF
/* Common Opcodes */
-#define LPFC_MBOX_OPCODE_CQ_CREATE 0x0C
-#define LPFC_MBOX_OPCODE_EQ_CREATE 0x0D
-#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15
-#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20
-#define LPFC_MBOX_OPCODE_NOP 0x21
-#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35
-#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36
-#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37
-#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A
-#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D
-#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A
-#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A
-#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B
-#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C
-#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D
-#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0
-#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4
-#define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC
-#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5
+#define LPFC_MBOX_OPCODE_NA 0x00
+#define LPFC_MBOX_OPCODE_CQ_CREATE 0x0C
+#define LPFC_MBOX_OPCODE_EQ_CREATE 0x0D
+#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15
+#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20
+#define LPFC_MBOX_OPCODE_NOP 0x21
+#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35
+#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36
+#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37
+#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A
+#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D
+#define LPFC_MBOX_OPCODE_GET_PORT_NAME 0x4D
+#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A
+#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A
+#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B
+#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C
+#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D
+#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0
+#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4
+#define LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG 0xA5
+#define LPFC_MBOX_OPCODE_GET_PROFILE_LIST 0xA6
+#define LPFC_MBOX_OPCODE_SET_ACT_PROFILE 0xA8
+#define LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG 0xA9
+#define LPFC_MBOX_OPCODE_READ_OBJECT 0xAB
+#define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC
+#define LPFC_MBOX_OPCODE_READ_OBJECT_LIST 0xAD
+#define LPFC_MBOX_OPCODE_DELETE_OBJECT 0xAE
+#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5
/* FCoE Opcodes */
#define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01
@@ -867,6 +880,7 @@ struct mbox_header {
#define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A
#define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B
#define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10
+#define LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS 0x21
#define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE 0x22
#define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK 0x23
@@ -1470,16 +1484,81 @@ struct sli4_sge { /* SLI-4 */
uint32_t addr_lo;
uint32_t word2;
-#define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/
-#define lpfc_sli4_sge_offset_MASK 0x1FFFFFFF
+#define lpfc_sli4_sge_offset_SHIFT 0
+#define lpfc_sli4_sge_offset_MASK 0x07FFFFFF
#define lpfc_sli4_sge_offset_WORD word2
-#define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets
- this flag !! */
+#define lpfc_sli4_sge_type_SHIFT 27
+#define lpfc_sli4_sge_type_MASK 0x0000000F
+#define lpfc_sli4_sge_type_WORD word2
+#define LPFC_SGE_TYPE_DATA 0x0
+#define LPFC_SGE_TYPE_DIF 0x4
+#define LPFC_SGE_TYPE_LSP 0x5
+#define LPFC_SGE_TYPE_PEDIF 0x6
+#define LPFC_SGE_TYPE_PESEED 0x7
+#define LPFC_SGE_TYPE_DISEED 0x8
+#define LPFC_SGE_TYPE_ENC 0x9
+#define LPFC_SGE_TYPE_ATM 0xA
+#define LPFC_SGE_TYPE_SKIP 0xC
+#define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets it */
#define lpfc_sli4_sge_last_MASK 0x00000001
#define lpfc_sli4_sge_last_WORD word2
uint32_t sge_len;
};
+struct sli4_sge_diseed { /* SLI-4 */
+ uint32_t ref_tag;
+ uint32_t ref_tag_tran;
+
+ uint32_t word2;
+#define lpfc_sli4_sge_dif_apptran_SHIFT 0
+#define lpfc_sli4_sge_dif_apptran_MASK 0x0000FFFF
+#define lpfc_sli4_sge_dif_apptran_WORD word2
+#define lpfc_sli4_sge_dif_af_SHIFT 24
+#define lpfc_sli4_sge_dif_af_MASK 0x00000001
+#define lpfc_sli4_sge_dif_af_WORD word2
+#define lpfc_sli4_sge_dif_na_SHIFT 25
+#define lpfc_sli4_sge_dif_na_MASK 0x00000001
+#define lpfc_sli4_sge_dif_na_WORD word2
+#define lpfc_sli4_sge_dif_hi_SHIFT 26
+#define lpfc_sli4_sge_dif_hi_MASK 0x00000001
+#define lpfc_sli4_sge_dif_hi_WORD word2
+#define lpfc_sli4_sge_dif_type_SHIFT 27
+#define lpfc_sli4_sge_dif_type_MASK 0x0000000F
+#define lpfc_sli4_sge_dif_type_WORD word2
+#define lpfc_sli4_sge_dif_last_SHIFT 31 /* Last SEG in the SGL sets it */
+#define lpfc_sli4_sge_dif_last_MASK 0x00000001
+#define lpfc_sli4_sge_dif_last_WORD word2
+ uint32_t word3;
+#define lpfc_sli4_sge_dif_apptag_SHIFT 0
+#define lpfc_sli4_sge_dif_apptag_MASK 0x0000FFFF
+#define lpfc_sli4_sge_dif_apptag_WORD word3
+#define lpfc_sli4_sge_dif_bs_SHIFT 16
+#define lpfc_sli4_sge_dif_bs_MASK 0x00000007
+#define lpfc_sli4_sge_dif_bs_WORD word3
+#define lpfc_sli4_sge_dif_ai_SHIFT 19
+#define lpfc_sli4_sge_dif_ai_MASK 0x00000001
+#define lpfc_sli4_sge_dif_ai_WORD word3
+#define lpfc_sli4_sge_dif_me_SHIFT 20
+#define lpfc_sli4_sge_dif_me_MASK 0x00000001
+#define lpfc_sli4_sge_dif_me_WORD word3
+#define lpfc_sli4_sge_dif_re_SHIFT 21
+#define lpfc_sli4_sge_dif_re_MASK 0x00000001
+#define lpfc_sli4_sge_dif_re_WORD word3
+#define lpfc_sli4_sge_dif_ce_SHIFT 22
+#define lpfc_sli4_sge_dif_ce_MASK 0x00000001
+#define lpfc_sli4_sge_dif_ce_WORD word3
+#define lpfc_sli4_sge_dif_nr_SHIFT 23
+#define lpfc_sli4_sge_dif_nr_MASK 0x00000001
+#define lpfc_sli4_sge_dif_nr_WORD word3
+#define lpfc_sli4_sge_dif_oprx_SHIFT 24
+#define lpfc_sli4_sge_dif_oprx_MASK 0x0000000F
+#define lpfc_sli4_sge_dif_oprx_WORD word3
+#define lpfc_sli4_sge_dif_optx_SHIFT 28
+#define lpfc_sli4_sge_dif_optx_MASK 0x0000000F
+#define lpfc_sli4_sge_dif_optx_WORD word3
+/* optx and oprx use BG_OP_IN defines in lpfc_hw.h */
+};
+
struct fcf_record {
uint32_t max_rcv_size;
uint32_t fka_adv_period;
@@ -2019,6 +2098,15 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001
#define lpfc_mbx_rd_conf_extnts_inuse_WORD word1
uint32_t word2;
+#define lpfc_mbx_rd_conf_lnk_numb_SHIFT 0
+#define lpfc_mbx_rd_conf_lnk_numb_MASK 0x0000003F
+#define lpfc_mbx_rd_conf_lnk_numb_WORD word2
+#define lpfc_mbx_rd_conf_lnk_type_SHIFT 6
+#define lpfc_mbx_rd_conf_lnk_type_MASK 0x00000003
+#define lpfc_mbx_rd_conf_lnk_type_WORD word2
+#define lpfc_mbx_rd_conf_lnk_ldv_SHIFT 8
+#define lpfc_mbx_rd_conf_lnk_ldv_MASK 0x00000001
+#define lpfc_mbx_rd_conf_lnk_ldv_WORD word2
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
@@ -2552,8 +2640,152 @@ struct lpfc_mbx_get_prof_cfg {
} u;
};
+struct lpfc_controller_attribute {
+ uint32_t version_string[8];
+ uint32_t manufacturer_name[8];
+ uint32_t supported_modes;
+ uint32_t word17;
+#define lpfc_cntl_attr_eprom_ver_lo_SHIFT 0
+#define lpfc_cntl_attr_eprom_ver_lo_MASK 0x000000ff
+#define lpfc_cntl_attr_eprom_ver_lo_WORD word17
+#define lpfc_cntl_attr_eprom_ver_hi_SHIFT 8
+#define lpfc_cntl_attr_eprom_ver_hi_MASK 0x000000ff
+#define lpfc_cntl_attr_eprom_ver_hi_WORD word17
+ uint32_t mbx_da_struct_ver;
+ uint32_t ep_fw_da_struct_ver;
+ uint32_t ncsi_ver_str[3];
+ uint32_t dflt_ext_timeout;
+ uint32_t model_number[8];
+ uint32_t description[16];
+ uint32_t serial_number[8];
+ uint32_t ip_ver_str[8];
+ uint32_t fw_ver_str[8];
+ uint32_t bios_ver_str[8];
+ uint32_t redboot_ver_str[8];
+ uint32_t driver_ver_str[8];
+ uint32_t flash_fw_ver_str[8];
+ uint32_t functionality;
+ uint32_t word105;
+#define lpfc_cntl_attr_max_cbd_len_SHIFT 0
+#define lpfc_cntl_attr_max_cbd_len_MASK 0x0000ffff
+#define lpfc_cntl_attr_max_cbd_len_WORD word105
+#define lpfc_cntl_attr_asic_rev_SHIFT 16
+#define lpfc_cntl_attr_asic_rev_MASK 0x000000ff
+#define lpfc_cntl_attr_asic_rev_WORD word105
+#define lpfc_cntl_attr_gen_guid0_SHIFT 24
+#define lpfc_cntl_attr_gen_guid0_MASK 0x000000ff
+#define lpfc_cntl_attr_gen_guid0_WORD word105
+ uint32_t gen_guid1_12[3];
+ uint32_t word109;
+#define lpfc_cntl_attr_gen_guid13_14_SHIFT 0
+#define lpfc_cntl_attr_gen_guid13_14_MASK 0x0000ffff
+#define lpfc_cntl_attr_gen_guid13_14_WORD word109
+#define lpfc_cntl_attr_gen_guid15_SHIFT 16
+#define lpfc_cntl_attr_gen_guid15_MASK 0x000000ff
+#define lpfc_cntl_attr_gen_guid15_WORD word109
+#define lpfc_cntl_attr_hba_port_cnt_SHIFT 24
+#define lpfc_cntl_attr_hba_port_cnt_MASK 0x000000ff
+#define lpfc_cntl_attr_hba_port_cnt_WORD word109
+ uint32_t word110;
+#define lpfc_cntl_attr_dflt_lnk_tmo_SHIFT 0
+#define lpfc_cntl_attr_dflt_lnk_tmo_MASK 0x0000ffff
+#define lpfc_cntl_attr_dflt_lnk_tmo_WORD word110
+#define lpfc_cntl_attr_multi_func_dev_SHIFT 24
+#define lpfc_cntl_attr_multi_func_dev_MASK 0x000000ff
+#define lpfc_cntl_attr_multi_func_dev_WORD word110
+ uint32_t word111;
+#define lpfc_cntl_attr_cache_valid_SHIFT 0
+#define lpfc_cntl_attr_cache_valid_MASK 0x000000ff
+#define lpfc_cntl_attr_cache_valid_WORD word111
+#define lpfc_cntl_attr_hba_status_SHIFT 8
+#define lpfc_cntl_attr_hba_status_MASK 0x000000ff
+#define lpfc_cntl_attr_hba_status_WORD word111
+#define lpfc_cntl_attr_max_domain_SHIFT 16
+#define lpfc_cntl_attr_max_domain_MASK 0x000000ff
+#define lpfc_cntl_attr_max_domain_WORD word111
+#define lpfc_cntl_attr_lnk_numb_SHIFT 24
+#define lpfc_cntl_attr_lnk_numb_MASK 0x0000003f
+#define lpfc_cntl_attr_lnk_numb_WORD word111
+#define lpfc_cntl_attr_lnk_type_SHIFT 30
+#define lpfc_cntl_attr_lnk_type_MASK 0x00000003
+#define lpfc_cntl_attr_lnk_type_WORD word111
+ uint32_t fw_post_status;
+ uint32_t hba_mtu[8];
+ uint32_t word121;
+ uint32_t reserved1[3];
+ uint32_t word125;
+#define lpfc_cntl_attr_pci_vendor_id_SHIFT 0
+#define lpfc_cntl_attr_pci_vendor_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_vendor_id_WORD word125
+#define lpfc_cntl_attr_pci_device_id_SHIFT 16
+#define lpfc_cntl_attr_pci_device_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_device_id_WORD word125
+ uint32_t word126;
+#define lpfc_cntl_attr_pci_subvdr_id_SHIFT 0
+#define lpfc_cntl_attr_pci_subvdr_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_subvdr_id_WORD word126
+#define lpfc_cntl_attr_pci_subsys_id_SHIFT 16
+#define lpfc_cntl_attr_pci_subsys_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_subsys_id_WORD word126
+ uint32_t word127;
+#define lpfc_cntl_attr_pci_bus_num_SHIFT 0
+#define lpfc_cntl_attr_pci_bus_num_MASK 0x000000ff
+#define lpfc_cntl_attr_pci_bus_num_WORD word127
+#define lpfc_cntl_attr_pci_dev_num_SHIFT 8
+#define lpfc_cntl_attr_pci_dev_num_MASK 0x000000ff
+#define lpfc_cntl_attr_pci_dev_num_WORD word127
+#define lpfc_cntl_attr_pci_fnc_num_SHIFT 16
+#define lpfc_cntl_attr_pci_fnc_num_MASK 0x000000ff
+#define lpfc_cntl_attr_pci_fnc_num_WORD word127
+#define lpfc_cntl_attr_inf_type_SHIFT 24
+#define lpfc_cntl_attr_inf_type_MASK 0x000000ff
+#define lpfc_cntl_attr_inf_type_WORD word127
+ uint32_t unique_id[2];
+ uint32_t word130;
+#define lpfc_cntl_attr_num_netfil_SHIFT 0
+#define lpfc_cntl_attr_num_netfil_MASK 0x000000ff
+#define lpfc_cntl_attr_num_netfil_WORD word130
+ uint32_t reserved2[4];
+};
+
+struct lpfc_mbx_get_cntl_attributes {
+ union lpfc_sli4_cfg_shdr cfg_shdr;
+ struct lpfc_controller_attribute cntl_attr;
+};
+
+struct lpfc_mbx_get_port_name {
+ struct mbox_header header;
+ union {
+ struct {
+ uint32_t word4;
+#define lpfc_mbx_get_port_name_lnk_type_SHIFT 0
+#define lpfc_mbx_get_port_name_lnk_type_MASK 0x00000003
+#define lpfc_mbx_get_port_name_lnk_type_WORD word4
+ } request;
+ struct {
+ uint32_t word4;
+#define lpfc_mbx_get_port_name_name0_SHIFT 0
+#define lpfc_mbx_get_port_name_name0_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name0_WORD word4
+#define lpfc_mbx_get_port_name_name1_SHIFT 8
+#define lpfc_mbx_get_port_name_name1_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name1_WORD word4
+#define lpfc_mbx_get_port_name_name2_SHIFT 16
+#define lpfc_mbx_get_port_name_name2_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name2_WORD word4
+#define lpfc_mbx_get_port_name_name3_SHIFT 24
+#define lpfc_mbx_get_port_name_name3_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name3_WORD word4
+#define LPFC_LINK_NUMBER_0 0
+#define LPFC_LINK_NUMBER_1 1
+#define LPFC_LINK_NUMBER_2 2
+#define LPFC_LINK_NUMBER_3 3
+ } response;
+ } u;
+};
+
/* Mailbox Completion Queue Error Messages */
-#define MB_CQE_STATUS_SUCCESS 0x0
+#define MB_CQE_STATUS_SUCCESS 0x0
#define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1
#define MB_CQE_STATUS_INVALID_PARAMETER 0x2
#define MB_CQE_STATUS_INSUFFICIENT_RESOURCES 0x3
@@ -2637,8 +2869,9 @@ struct lpfc_mqe {
struct lpfc_mbx_run_link_diag_test link_diag_test;
struct lpfc_mbx_get_func_cfg get_func_cfg;
struct lpfc_mbx_get_prof_cfg get_prof_cfg;
- struct lpfc_mbx_nop nop;
struct lpfc_mbx_wr_object wr_object;
+ struct lpfc_mbx_get_port_name get_port_name;
+ struct lpfc_mbx_nop nop;
} un;
};
@@ -2855,6 +3088,9 @@ struct wqe_common {
#define wqe_ctxt_tag_MASK 0x0000FFFF
#define wqe_ctxt_tag_WORD word6
uint32_t word7;
+#define wqe_dif_SHIFT 0
+#define wqe_dif_MASK 0x00000003
+#define wqe_dif_WORD word7
#define wqe_ct_SHIFT 2
#define wqe_ct_MASK 0x00000003
#define wqe_ct_WORD word7
@@ -2867,12 +3103,21 @@ struct wqe_common {
#define wqe_class_SHIFT 16
#define wqe_class_MASK 0x00000007
#define wqe_class_WORD word7
+#define wqe_ar_SHIFT 19
+#define wqe_ar_MASK 0x00000001
+#define wqe_ar_WORD word7
+#define wqe_ag_SHIFT wqe_ar_SHIFT
+#define wqe_ag_MASK wqe_ar_MASK
+#define wqe_ag_WORD wqe_ar_WORD
#define wqe_pu_SHIFT 20
#define wqe_pu_MASK 0x00000003
#define wqe_pu_WORD word7
#define wqe_erp_SHIFT 22
#define wqe_erp_MASK 0x00000001
#define wqe_erp_WORD word7
+#define wqe_conf_SHIFT wqe_erp_SHIFT
+#define wqe_conf_MASK wqe_erp_MASK
+#define wqe_conf_WORD wqe_erp_WORD
#define wqe_lnk_SHIFT 23
#define wqe_lnk_MASK 0x00000001
#define wqe_lnk_WORD word7
@@ -2931,6 +3176,9 @@ struct wqe_common {
#define wqe_xc_SHIFT 21
#define wqe_xc_MASK 0x00000001
#define wqe_xc_WORD word10
+#define wqe_sr_SHIFT 22
+#define wqe_sr_MASK 0x00000001
+#define wqe_sr_WORD word10
#define wqe_ccpe_SHIFT 23
#define wqe_ccpe_MASK 0x00000001
#define wqe_ccpe_WORD word10
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 027b797..55bc4fc 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -24,6 +24,7 @@
#include <linux/dma-mapping.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
@@ -58,8 +59,7 @@ spinlock_t _dump_buf_lock;
static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
static int lpfc_post_rcv_buf(struct lpfc_hba *);
-static int lpfc_sli4_queue_create(struct lpfc_hba *);
-static void lpfc_sli4_queue_destroy(struct lpfc_hba *);
+static int lpfc_sli4_queue_verify(struct lpfc_hba *);
static int lpfc_create_bootstrap_mbox(struct lpfc_hba *);
static int lpfc_setup_endian_order(struct lpfc_hba *);
static int lpfc_sli4_read_config(struct lpfc_hba *);
@@ -1438,6 +1438,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
struct Scsi_Host *shost;
uint32_t if_type;
struct lpfc_register portstat_reg;
+ int rc;
/* If the pci channel is offline, ignore possible errors, since
* we cannot communicate with the pci card anyway.
@@ -1480,16 +1481,24 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
lpfc_sli4_offline_eratt(phba);
return;
}
- if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) {
- /*
- * TODO: Attempt port recovery via a port reset.
- * When fully implemented, the driver should
- * attempt to recover the port here and return.
- * For now, log an error and take the port offline.
- */
+ /*
+ * On error status condition, driver need to wait for port
+ * ready before performing reset.
+ */
+ rc = lpfc_sli4_pdev_status_reg_wait(phba);
+ if (!rc) {
+ /* need reset: attempt for port recovery */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2887 Port Error: Attempting "
"Port Recovery\n");
+ lpfc_offline_prep(phba);
+ lpfc_offline(phba);
+ lpfc_sli_brdrestart(phba);
+ if (lpfc_online(phba) == 0) {
+ lpfc_unblock_mgmt_io(phba);
+ return;
+ }
+ /* fall through for not able to recover */
}
lpfc_sli4_offline_eratt(phba);
break;
@@ -1724,11 +1733,20 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
j = 0;
Length -= (3+i);
while(i--) {
- phba->Port[j++] = vpd[index++];
- if (j == 19)
- break;
+ if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (phba->sli4_hba.pport_name_sta ==
+ LPFC_SLI4_PPNAME_GET)) {
+ j++;
+ index++;
+ } else
+ phba->Port[j++] = vpd[index++];
+ if (j == 19)
+ break;
}
- phba->Port[j] = 0;
+ if ((phba->sli_rev != LPFC_SLI_REV4) ||
+ (phba->sli4_hba.pport_name_sta ==
+ LPFC_SLI4_PPNAME_NON))
+ phba->Port[j] = 0;
continue;
}
else {
@@ -1958,7 +1976,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
case PCI_DEVICE_ID_LANCER_FCOE:
case PCI_DEVICE_ID_LANCER_FCOE_VF:
oneConnect = 1;
- m = (typeof(m)){"OCe50100", "PCIe", "FCoE"};
+ m = (typeof(m)){"OCe15100", "PCIe", "FCoE"};
break;
default:
m = (typeof(m)){"Unknown", "", ""};
@@ -2432,17 +2450,19 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
uint8_t actcmd = MBX_HEARTBEAT;
unsigned long timeout;
-
+ timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies;
spin_lock_irqsave(&phba->hbalock, iflag);
phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
- if (phba->sli.mbox_active)
+ if (phba->sli.mbox_active) {
actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
+ /* Determine how long we might wait for the active mailbox
+ * command to be gracefully completed by firmware.
+ */
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ phba->sli.mbox_active) * 1000) + jiffies;
+ }
spin_unlock_irqrestore(&phba->hbalock, iflag);
- /* Determine how long we might wait for the active mailbox
- * command to be gracefully completed by firmware.
- */
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
- jiffies;
+
/* Wait for the outstnading mailbox command to complete */
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
@@ -3634,8 +3654,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
lpfc_sli4_fcf_dead_failthrough(phba);
} else {
/* Reset FCF roundrobin bmask for new discovery */
- memset(phba->fcf.fcf_rr_bmask, 0,
- sizeof(*phba->fcf.fcf_rr_bmask));
+ lpfc_sli4_clear_fcf_rr_bmask(phba);
/*
* Handling fast FCF failover to a DEAD FCF event is
* considered equalivant to receiving CVL to all vports.
@@ -3721,8 +3740,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
* Reset FCF roundrobin bmask for new
* discovery.
*/
- memset(phba->fcf.fcf_rr_bmask, 0,
- sizeof(*phba->fcf.fcf_rr_bmask));
+ lpfc_sli4_clear_fcf_rr_bmask(phba);
}
break;
default:
@@ -3951,7 +3969,7 @@ static int
lpfc_enable_pci_dev(struct lpfc_hba *phba)
{
struct pci_dev *pdev;
- int bars;
+ int bars = 0;
/* Obtain PCI device reference */
if (!phba->pcidev)
@@ -3980,6 +3998,8 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba)
out_disable_device:
pci_disable_device(pdev);
out_error:
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1401 Failed to enable pci device, bars:x%x\n", bars);
return -ENODEV;
}
@@ -4053,9 +4073,6 @@ lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba)
uint16_t nr_virtfn;
int pos;
- if (!pdev->is_physfn)
- return 0;
-
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
if (pos == 0)
return 0;
@@ -4476,15 +4493,15 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
}
}
mempool_free(mboxq, phba->mbox_mem_pool);
- /* Create all the SLI4 queues */
- rc = lpfc_sli4_queue_create(phba);
+ /* Verify all the SLI4 queues */
+ rc = lpfc_sli4_queue_verify(phba);
if (rc)
goto out_free_bsmbx;
/* Create driver internal CQE event pool */
rc = lpfc_sli4_cq_event_pool_create(phba);
if (rc)
- goto out_destroy_queue;
+ goto out_free_bsmbx;
/* Initialize and populate the iocb list per host */
rc = lpfc_init_sgl_list(phba);
@@ -4518,14 +4535,21 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
goto out_remove_rpi_hdrs;
}
- phba->sli4_hba.fcp_eq_hdl = kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
+ /*
+ * The cfg_fcp_eq_count can be zero whenever there is exactly one
+ * interrupt vector. This is not an error
+ */
+ if (phba->cfg_fcp_eq_count) {
+ phba->sli4_hba.fcp_eq_hdl =
+ kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
phba->cfg_fcp_eq_count), GFP_KERNEL);
- if (!phba->sli4_hba.fcp_eq_hdl) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2572 Failed allocate memory for fast-path "
- "per-EQ handle array\n");
- rc = -ENOMEM;
- goto out_free_fcf_rr_bmask;
+ if (!phba->sli4_hba.fcp_eq_hdl) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2572 Failed allocate memory for "
+ "fast-path per-EQ handle array\n");
+ rc = -ENOMEM;
+ goto out_free_fcf_rr_bmask;
+ }
}
phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
@@ -4569,8 +4593,6 @@ out_free_sgl_list:
lpfc_free_sgl_list(phba);
out_destroy_cq_event_pool:
lpfc_sli4_cq_event_pool_destroy(phba);
-out_destroy_queue:
- lpfc_sli4_queue_destroy(phba);
out_free_bsmbx:
lpfc_destroy_bootstrap_mbox(phba);
out_free_mem:
@@ -4610,9 +4632,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
/* Free the SCSI sgl management array */
kfree(phba->sli4_hba.lpfc_scsi_psb_array);
- /* Free the SLI4 queues */
- lpfc_sli4_queue_destroy(phba);
-
/* Free the completion queue EQ event pool */
lpfc_sli4_cq_event_release_all(phba);
lpfc_sli4_cq_event_pool_destroy(phba);
@@ -6141,24 +6160,21 @@ lpfc_setup_endian_order(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_queue_create - Create all the SLI4 queues
+ * lpfc_sli4_queue_verify - Verify and update EQ and CQ counts
* @phba: pointer to lpfc hba data structure.
*
- * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA
- * operation. For each SLI4 queue type, the parameters such as queue entry
- * count (queue depth) shall be taken from the module parameter. For now,
- * we just use some constant number as place holder.
+ * This routine is invoked to check the user settable queue counts for EQs and
+ * CQs. after this routine is called the counts will be set to valid values that
+ * adhere to the constraints of the system's interrupt vectors and the port's
+ * queue resources.
*
* Return codes
* 0 - successful
* -ENOMEM - No available memory
- * -EIO - The mailbox failed to complete successfully.
**/
static int
-lpfc_sli4_queue_create(struct lpfc_hba *phba)
+lpfc_sli4_queue_verify(struct lpfc_hba *phba)
{
- struct lpfc_queue *qdesc;
- int fcp_eqidx, fcp_cqidx, fcp_wqidx;
int cfg_fcp_wq_count;
int cfg_fcp_eq_count;
@@ -6231,14 +6247,43 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
/* The overall number of event queues used */
phba->sli4_hba.cfg_eqn = phba->cfg_fcp_eq_count + LPFC_SP_EQN_DEF;
- /*
- * Create Event Queues (EQs)
- */
-
/* Get EQ depth from module parameter, fake the default for now */
phba->sli4_hba.eq_esize = LPFC_EQE_SIZE_4B;
phba->sli4_hba.eq_ecount = LPFC_EQE_DEF_COUNT;
+ /* Get CQ depth from module parameter, fake the default for now */
+ phba->sli4_hba.cq_esize = LPFC_CQE_SIZE;
+ phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT;
+
+ return 0;
+out_error:
+ return -ENOMEM;
+}
+
+/**
+ * lpfc_sli4_queue_create - Create all the SLI4 queues
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA
+ * operation. For each SLI4 queue type, the parameters such as queue entry
+ * count (queue depth) shall be taken from the module parameter. For now,
+ * we just use some constant number as place holder.
+ *
+ * Return codes
+ * 0 - sucessful
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
+ **/
+int
+lpfc_sli4_queue_create(struct lpfc_hba *phba)
+{
+ struct lpfc_queue *qdesc;
+ int fcp_eqidx, fcp_cqidx, fcp_wqidx;
+
+ /*
+ * Create Event Queues (EQs)
+ */
+
/* Create slow path event queue */
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
phba->sli4_hba.eq_ecount);
@@ -6249,14 +6294,20 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
}
phba->sli4_hba.sp_eq = qdesc;
- /* Create fast-path FCP Event Queue(s) */
- phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) *
- phba->cfg_fcp_eq_count), GFP_KERNEL);
- if (!phba->sli4_hba.fp_eq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2576 Failed allocate memory for fast-path "
- "EQ record array\n");
- goto out_free_sp_eq;
+ /*
+ * Create fast-path FCP Event Queue(s). The cfg_fcp_eq_count can be
+ * zero whenever there is exactly one interrupt vector. This is not
+ * an error.
+ */
+ if (phba->cfg_fcp_eq_count) {
+ phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) *
+ phba->cfg_fcp_eq_count), GFP_KERNEL);
+ if (!phba->sli4_hba.fp_eq) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2576 Failed allocate memory for "
+ "fast-path EQ record array\n");
+ goto out_free_sp_eq;
+ }
}
for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) {
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
@@ -6273,10 +6324,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
* Create Complete Queues (CQs)
*/
- /* Get CQ depth from module parameter, fake the default for now */
- phba->sli4_hba.cq_esize = LPFC_CQE_SIZE;
- phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT;
-
/* Create slow-path Mailbox Command Complete Queue */
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount);
@@ -6298,16 +6345,25 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
phba->sli4_hba.els_cq = qdesc;
- /* Create fast-path FCP Completion Queue(s), one-to-one with EQs */
- phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
- phba->cfg_fcp_eq_count), GFP_KERNEL);
+ /*
+ * Create fast-path FCP Completion Queue(s), one-to-one with FCP EQs.
+ * If there are no FCP EQs then create exactly one FCP CQ.
+ */
+ if (phba->cfg_fcp_eq_count)
+ phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
+ phba->cfg_fcp_eq_count),
+ GFP_KERNEL);
+ else
+ phba->sli4_hba.fcp_cq = kzalloc(sizeof(struct lpfc_queue *),
+ GFP_KERNEL);
if (!phba->sli4_hba.fcp_cq) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2577 Failed allocate memory for fast-path "
"CQ record array\n");
goto out_free_els_cq;
}
- for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) {
+ fcp_cqidx = 0;
+ do {
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount);
if (!qdesc) {
@@ -6317,7 +6373,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
goto out_free_fcp_cq;
}
phba->sli4_hba.fcp_cq[fcp_cqidx] = qdesc;
- }
+ } while (++fcp_cqidx < phba->cfg_fcp_eq_count);
/* Create Mailbox Command Queue */
phba->sli4_hba.mq_esize = LPFC_MQE_SIZE;
@@ -6449,7 +6505,7 @@ out_error:
* -ENOMEM - No available memory
* -EIO - The mailbox failed to complete successfully.
**/
-static void
+void
lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
{
int fcp_qidx;
@@ -6725,6 +6781,10 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
"0540 Receive Queue not allocated\n");
goto out_destroy_fcp_wq;
}
+
+ lpfc_rq_adjust_repost(phba, phba->sli4_hba.hdr_rq, LPFC_ELS_HBQ);
+ lpfc_rq_adjust_repost(phba, phba->sli4_hba.dat_rq, LPFC_ELS_HBQ);
+
rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
phba->sli4_hba.els_cq, LPFC_USOL);
if (rc) {
@@ -6733,6 +6793,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
"rc = 0x%x\n", rc);
goto out_destroy_fcp_wq;
}
+
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2592 USL RQ setup: hdr-rq-id=%d, dat-rq-id=%d "
"parent cq-id=%d\n",
@@ -6792,8 +6853,10 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
/* Unset ELS complete queue */
lpfc_cq_destroy(phba, phba->sli4_hba.els_cq);
/* Unset FCP response complete queue */
- for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
+ fcp_qidx = 0;
+ do {
lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]);
+ } while (++fcp_qidx < phba->cfg_fcp_eq_count);
/* Unset fast-path event queue */
for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]);
@@ -7042,10 +7105,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
* the loop again.
*/
for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
+ msleep(10);
if (lpfc_readl(phba->sli4_hba.u.if_type2.
STATUSregaddr, &reg_data.word0)) {
rc = -ENODEV;
- break;
+ goto out;
}
if (bf_get(lpfc_sliport_status_rdy, &reg_data))
break;
@@ -7053,7 +7117,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
reset_again++;
break;
}
- msleep(10);
}
/*
@@ -7067,11 +7130,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
}
/* Detect any port errors. */
- if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
- &reg_data.word0)) {
- rc = -ENODEV;
- break;
- }
if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
(rdy_chk >= 1000)) {
phba->work_status[0] = readl(
@@ -7104,6 +7162,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
break;
}
+out:
/* Catch the not-ready port failure after a port reset. */
if (num_resets >= MAX_IF_TYPE_2_RESETS)
rc = -ENODEV;
@@ -7151,12 +7210,13 @@ lpfc_sli4_send_nop_mbox_cmds(struct lpfc_hba *phba, uint32_t cnt)
lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
LPFC_MBOX_OPCODE_NOP, length, LPFC_SLI4_MBX_EMBED);
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
for (cmdsent = 0; cmdsent < cnt; cmdsent++) {
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else
+ else {
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+ }
if (rc == MBX_TIMEOUT)
break;
/* Check return status */
@@ -7976,6 +8036,7 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba)
/* Reset SLI4 HBA FCoE function */
lpfc_pci_function_reset(phba);
+ lpfc_sli4_queue_destroy(phba);
return;
}
@@ -8089,6 +8150,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
/* Reset SLI4 HBA FCoE function */
lpfc_pci_function_reset(phba);
+ lpfc_sli4_queue_destroy(phba);
/* Stop the SLI4 device port */
phba->pport->work_port_events = 0;
@@ -8122,7 +8184,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_PORT_CAPABILITIES);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
}
@@ -8184,6 +8246,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
int rc;
struct lpfc_mqe *mqe = &mboxq->u.mqe;
struct lpfc_pc_sli4_params *sli4_params;
+ uint32_t mbox_tmo;
int length;
struct lpfc_sli4_parameters *mbx_sli4_parameters;
@@ -8202,9 +8265,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
length, LPFC_SLI4_MBX_EMBED);
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else
- rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
- lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
+ else {
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
+ rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+ }
if (unlikely(rc))
return rc;
sli4_params = &phba->sli4_hba.pc_sli4_params;
@@ -8273,11 +8337,8 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
/* Perform generic PCI device enabling operation */
error = lpfc_enable_pci_dev(phba);
- if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1401 Failed to enable pci device.\n");
+ if (error)
goto out_free_phba;
- }
/* Set up SLI API function jump table for PCI-device group-0 HBAs */
error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_LP);
@@ -8324,6 +8385,9 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_iocb_list;
}
+ /* Get the default values for Model Name and Description */
+ lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
+
/* Create SCSI host to the physical port */
error = lpfc_create_shost(phba);
if (error) {
@@ -8887,16 +8951,17 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
uint32_t offset = 0, temp_offset = 0;
INIT_LIST_HEAD(&dma_buffer_list);
- if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) ||
- (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) ||
- (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
- (image->size != fw->size)) {
+ if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) ||
+ (bf_get_be32(lpfc_grp_hdr_file_type, image) !=
+ LPFC_FILE_TYPE_GROUP) ||
+ (bf_get_be32(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
+ (be32_to_cpu(image->size) != fw->size)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3022 Invalid FW image found. "
- "Magic:%d Type:%x ID:%x\n",
- image->magic_number,
- bf_get(lpfc_grp_hdr_file_type, image),
- bf_get(lpfc_grp_hdr_id, image));
+ "Magic:%x Type:%x ID:%x\n",
+ be32_to_cpu(image->magic_number),
+ bf_get_be32(lpfc_grp_hdr_file_type, image),
+ bf_get_be32(lpfc_grp_hdr_id, image));
return -EINVAL;
}
lpfc_decode_firmware_rev(phba, fwrev, 1);
@@ -8926,11 +8991,11 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
while (offset < fw->size) {
temp_offset = offset;
list_for_each_entry(dmabuf, &dma_buffer_list, list) {
- if (offset + SLI4_PAGE_SIZE > fw->size) {
- temp_offset += fw->size - offset;
+ if (temp_offset + SLI4_PAGE_SIZE > fw->size) {
memcpy(dmabuf->virt,
fw->data + temp_offset,
- fw->size - offset);
+ fw->size - temp_offset);
+ temp_offset = fw->size;
break;
}
memcpy(dmabuf->virt, fw->data + temp_offset,
@@ -8986,7 +9051,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
uint32_t cfg_mode, intr_mode;
int mcnt;
int adjusted_fcp_eq_count;
- int fcp_qidx;
const struct firmware *fw;
uint8_t file_name[16];
@@ -8997,11 +9061,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
/* Perform generic PCI device enabling operation */
error = lpfc_enable_pci_dev(phba);
- if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1409 Failed to enable pci device.\n");
+ if (error)
goto out_free_phba;
- }
/* Set up SLI API function jump table for PCI-device group-1 HBAs */
error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_OC);
@@ -9046,6 +9107,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
}
INIT_LIST_HEAD(&phba->active_rrq_list);
+ INIT_LIST_HEAD(&phba->fcf.fcf_pri_list);
/* Set up common device driver resources */
error = lpfc_setup_driver_resource_phase2(phba);
@@ -9055,6 +9117,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_iocb_list;
}
+ /* Get the default values for Model Name and Description */
+ lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
+
/* Create SCSI host to the physical port */
error = lpfc_create_shost(phba);
if (error) {
@@ -9094,16 +9159,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
adjusted_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1;
else
adjusted_fcp_eq_count = phba->cfg_fcp_eq_count;
- /* Free unused EQs */
- for (fcp_qidx = adjusted_fcp_eq_count;
- fcp_qidx < phba->cfg_fcp_eq_count;
- fcp_qidx++) {
- lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]);
- /* do not delete the first fcp_cq */
- if (fcp_qidx)
- lpfc_sli4_queue_free(
- phba->sli4_hba.fcp_cq[fcp_qidx]);
- }
phba->cfg_fcp_eq_count = adjusted_fcp_eq_count;
/* Set up SLI-4 HBA */
if (lpfc_sli4_hba_setup(phba)) {
@@ -9153,7 +9208,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
/* Check if there are static vports to be created. */
lpfc_create_static_vport(phba);
-
return 0;
out_disable_intr:
@@ -9287,6 +9341,7 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg)
/* Disable interrupt from device */
lpfc_sli4_disable_intr(phba);
+ lpfc_sli4_queue_destroy(phba);
/* Save device state to PCI config space */
pci_save_state(pdev);
@@ -9416,6 +9471,7 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
/* Disable interrupt and pci device */
lpfc_sli4_disable_intr(phba);
+ lpfc_sli4_queue_destroy(phba);
pci_disable_device(phba->pcidev);
/* Flush all driver's outstanding SCSI I/Os as we are to reset */
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index e3b790e..baf53e6 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -36,6 +36,7 @@
#define LOG_SECURITY 0x00008000 /* Security events */
#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
#define LOG_FIP 0x00020000 /* FIP events */
+#define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */
#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 83450cc..2ebc7d2 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1598,9 +1598,12 @@ lpfc_mbox_dev_check(struct lpfc_hba *phba)
* Timeout value to be used for the given mailbox command
**/
int
-lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
+lpfc_mbox_tmo_val(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
- switch (cmd) {
+ MAILBOX_t *mbox = &mboxq->u.mb;
+ uint8_t subsys, opcode;
+
+ switch (mbox->mbxCommand) {
case MBX_WRITE_NV: /* 0x03 */
case MBX_UPDATE_CFG: /* 0x1B */
case MBX_DOWN_LOAD: /* 0x1C */
@@ -1610,6 +1613,28 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
case MBX_LOAD_EXP_ROM: /* 0x9C */
return LPFC_MBOX_TMO_FLASH_CMD;
case MBX_SLI4_CONFIG: /* 0x9b */
+ subsys = lpfc_sli_config_mbox_subsys_get(phba, mboxq);
+ opcode = lpfc_sli_config_mbox_opcode_get(phba, mboxq);
+ if (subsys == LPFC_MBOX_SUBSYSTEM_COMMON) {
+ switch (opcode) {
+ case LPFC_MBOX_OPCODE_READ_OBJECT:
+ case LPFC_MBOX_OPCODE_WRITE_OBJECT:
+ case LPFC_MBOX_OPCODE_READ_OBJECT_LIST:
+ case LPFC_MBOX_OPCODE_DELETE_OBJECT:
+ case LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG:
+ case LPFC_MBOX_OPCODE_GET_PROFILE_LIST:
+ case LPFC_MBOX_OPCODE_SET_ACT_PROFILE:
+ case LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG:
+ case LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG:
+ return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO;
+ }
+ }
+ if (subsys == LPFC_MBOX_SUBSYSTEM_FCOE) {
+ switch (opcode) {
+ case LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS:
+ return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO;
+ }
+ }
return LPFC_MBOX_SLI4_CONFIG_TMO;
}
return LPFC_MBOX_TMO;
@@ -1859,7 +1884,7 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
}
/* Complete the initialization for the particular Opcode. */
- opcode = lpfc_sli4_mbox_opcode_get(phba, mbox);
+ opcode = lpfc_sli_config_mbox_opcode_get(phba, mbox);
switch (opcode) {
case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT:
if (emb == LPFC_SLI4_MBX_EMBED)
@@ -1886,23 +1911,56 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
}
/**
- * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command
+ * lpfc_sli_config_mbox_subsys_get - Get subsystem from a sli_config mbox cmd
* @phba: pointer to lpfc hba data structure.
- * @mbox: pointer to lpfc mbox command.
+ * @mbox: pointer to lpfc mbox command queue entry.
+ *
+ * This routine gets the subsystem from a SLI4 specific SLI_CONFIG mailbox
+ * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if the
+ * sub-header is not present, subsystem LPFC_MBOX_SUBSYSTEM_NA (0x0) shall
+ * be returned.
+ **/
+uint8_t
+lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
+{
+ struct lpfc_mbx_sli4_config *sli4_cfg;
+ union lpfc_sli4_cfg_shdr *cfg_shdr;
+
+ if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG)
+ return LPFC_MBOX_SUBSYSTEM_NA;
+ sli4_cfg = &mbox->u.mqe.un.sli4_config;
+
+ /* For embedded mbox command, get opcode from embedded sub-header*/
+ if (bf_get(lpfc_mbox_hdr_emb, &sli4_cfg->header.cfg_mhdr)) {
+ cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
+ return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request);
+ }
+
+ /* For non-embedded mbox command, get opcode from first dma page */
+ if (unlikely(!mbox->sge_array))
+ return LPFC_MBOX_SUBSYSTEM_NA;
+ cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0];
+ return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request);
+}
+
+/**
+ * lpfc_sli_config_mbox_opcode_get - Get opcode from a sli_config mbox cmd
+ * @phba: pointer to lpfc hba data structure.
+ * @mbox: pointer to lpfc mbox command queue entry.
*
- * This routine gets the opcode from a SLI4 specific mailbox command for
- * sending IOCTL command. If the mailbox command is not MBX_SLI4_CONFIG
- * (0x9B) or if the IOCTL sub-header is not present, opcode 0x0 shall be
+ * This routine gets the opcode from a SLI4 specific SLI_CONFIG mailbox
+ * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if
+ * the sub-header is not present, opcode LPFC_MBOX_OPCODE_NA (0x0) be
* returned.
**/
uint8_t
-lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
+lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
{
struct lpfc_mbx_sli4_config *sli4_cfg;
union lpfc_sli4_cfg_shdr *cfg_shdr;
if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG)
- return 0;
+ return LPFC_MBOX_OPCODE_NA;
sli4_cfg = &mbox->u.mqe.un.sli4_config;
/* For embedded mbox command, get opcode from embedded sub-header*/
@@ -1913,7 +1971,7 @@ lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
/* For non-embedded mbox command, get opcode from first dma page */
if (unlikely(!mbox->sge_array))
- return 0;
+ return LPFC_MBOX_OPCODE_NA;
cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0];
return bf_get(lpfc_mbox_hdr_opcode, &cfg_shdr->request);
}
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index eadd241..2e1e54e 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -21,6 +21,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
+#include <linux/export.h>
#include <linux/delay.h>
#include <asm/unaligned.h>
@@ -58,6 +59,13 @@ static char *dif_op_str[] = {
"SCSI_PROT_READ_PASS",
"SCSI_PROT_WRITE_PASS",
};
+
+struct scsi_dif_tuple {
+ __be16 guard_tag; /* Checksum */
+ __be16 app_tag; /* Opaque storage */
+ __be32 ref_tag; /* Target LBA or indirect LBA */
+};
+
static void
lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
static void
@@ -1263,6 +1271,174 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
return 0;
}
+static inline unsigned
+lpfc_cmd_blksize(struct scsi_cmnd *sc)
+{
+ return sc->device->sector_size;
+}
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+/*
+ * Given a scsi cmnd, determine the BlockGuard tags to be used with it
+ * @sc: The SCSI command to examine
+ * @reftag: (out) BlockGuard reference tag for transmitted data
+ * @apptag: (out) BlockGuard application tag for transmitted data
+ * @new_guard (in) Value to replace CRC with if needed
+ *
+ * Returns (1) if error injection was performed, (0) otherwise
+ */
+static int
+lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ uint32_t *reftag, uint16_t *apptag, uint32_t new_guard)
+{
+ struct scatterlist *sgpe; /* s/g prot entry */
+ struct scatterlist *sgde; /* s/g data entry */
+ struct scsi_dif_tuple *src;
+ uint32_t op = scsi_get_prot_op(sc);
+ uint32_t blksize;
+ uint32_t numblks;
+ sector_t lba;
+ int rc = 0;
+
+ if (op == SCSI_PROT_NORMAL)
+ return 0;
+
+ lba = scsi_get_lba(sc);
+ if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
+ blksize = lpfc_cmd_blksize(sc);
+ numblks = (scsi_bufflen(sc) + blksize - 1) / blksize;
+
+ /* Make sure we have the right LBA if one is specified */
+ if ((phba->lpfc_injerr_lba < lba) ||
+ (phba->lpfc_injerr_lba >= (lba + numblks)))
+ return 0;
+ }
+
+ sgpe = scsi_prot_sglist(sc);
+ sgde = scsi_sglist(sc);
+
+ /* Should we change the Reference Tag */
+ if (reftag) {
+ /*
+ * If we are SCSI_PROT_WRITE_STRIP, the protection data is
+ * being stripped from the wire, thus it doesn't matter.
+ */
+ if ((op == SCSI_PROT_WRITE_PASS) ||
+ (op == SCSI_PROT_WRITE_INSERT)) {
+ if (phba->lpfc_injerr_wref_cnt) {
+
+ /* DEADBEEF will be the reftag on the wire */
+ *reftag = 0xDEADBEEF;
+ phba->lpfc_injerr_wref_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9081 BLKGRD: Injecting reftag error: "
+ "write lba x%lx\n", (unsigned long)lba);
+ }
+ } else {
+ if (phba->lpfc_injerr_rref_cnt) {
+ *reftag = 0xDEADBEEF;
+ phba->lpfc_injerr_rref_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9076 BLKGRD: Injecting reftag error: "
+ "read lba x%lx\n", (unsigned long)lba);
+ }
+ }
+ }
+
+ /* Should we change the Application Tag */
+ if (apptag) {
+ /*
+ * If we are SCSI_PROT_WRITE_STRIP, the protection data is
+ * being stripped from the wire, thus it doesn't matter.
+ */
+ if ((op == SCSI_PROT_WRITE_PASS) ||
+ (op == SCSI_PROT_WRITE_INSERT)) {
+ if (phba->lpfc_injerr_wapp_cnt) {
+
+ /* DEAD will be the apptag on the wire */
+ *apptag = 0xDEAD;
+ phba->lpfc_injerr_wapp_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9077 BLKGRD: Injecting apptag error: "
+ "write lba x%lx\n", (unsigned long)lba);
+ }
+ } else {
+ if (phba->lpfc_injerr_rapp_cnt) {
+ *apptag = 0xDEAD;
+ phba->lpfc_injerr_rapp_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9078 BLKGRD: Injecting apptag error: "
+ "read lba x%lx\n", (unsigned long)lba);
+ }
+ }
+ }
+
+ /* Should we change the Guard Tag */
+
+ /*
+ * If we are SCSI_PROT_WRITE_INSERT, the protection data is
+ * being on the wire is being fully generated on the HBA.
+ * The host cannot change it or force an error.
+ */
+ if (((op == SCSI_PROT_WRITE_STRIP) ||
+ (op == SCSI_PROT_WRITE_PASS)) &&
+ phba->lpfc_injerr_wgrd_cnt) {
+ if (sgpe) {
+ src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+ /*
+ * Just inject an error in the first
+ * prot block.
+ */
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9079 BLKGRD: Injecting guard error: "
+ "write lba x%lx oldGuard x%x refTag x%x\n",
+ (unsigned long)lba, src->guard_tag,
+ src->ref_tag);
+
+ src->guard_tag = (uint16_t)new_guard;
+ phba->lpfc_injerr_wgrd_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ } else {
+ blksize = lpfc_cmd_blksize(sc);
+ /*
+ * Jump past the first data block
+ * and inject an error in the
+ * prot data. The prot data is already
+ * embedded after the regular data.
+ */
+ src = (struct scsi_dif_tuple *)
+ (sg_virt(sgde) + blksize);
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9080 BLKGRD: Injecting guard error: "
+ "write lba x%lx oldGuard x%x refTag x%x\n",
+ (unsigned long)lba, src->guard_tag,
+ src->ref_tag);
+
+ src->guard_tag = (uint16_t)new_guard;
+ phba->lpfc_injerr_wgrd_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+ }
+ }
+ return rc;
+}
+#endif
+
/*
* Given a scsi cmnd, determine the BlockGuard opcodes to be used with it
* @sc: The SCSI command to examine
@@ -1341,18 +1517,6 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
return ret;
}
-struct scsi_dif_tuple {
- __be16 guard_tag; /* Checksum */
- __be16 app_tag; /* Opaque storage */
- __be32 ref_tag; /* Target LBA or indirect LBA */
-};
-
-static inline unsigned
-lpfc_cmd_blksize(struct scsi_cmnd *sc)
-{
- return sc->device->sector_size;
-}
-
/*
* This function sets up buffer list for protection groups of
* type LPFC_PG_TYPE_NO_DIF
@@ -1401,6 +1565,11 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
blksize = lpfc_cmd_blksize(sc);
reftag = scsi_get_lba(sc) & 0xffffffff;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ /* reftag is the only error we can inject here */
+ lpfc_bg_err_inject(phba, sc, &reftag, 0, 0);
+#endif
+
/* setup PDE5 with what we have */
pde5 = (struct lpfc_pde5 *) bpl;
memset(pde5, 0, sizeof(struct lpfc_pde5));
@@ -1532,6 +1701,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
blksize = lpfc_cmd_blksize(sc);
reftag = scsi_get_lba(sc) & 0xffffffff;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ /* reftag / guard tag are the only errors we can inject here */
+ lpfc_bg_err_inject(phba, sc, &reftag, 0, 0xDEAD);
+#endif
+
split_offset = 0;
do {
/* setup PDE5 with what we have */
@@ -1671,7 +1845,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
}
} while (!alldone);
-
out:
return num_bde;
@@ -2075,6 +2248,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
else
bf_set(lpfc_sli4_sge_last, sgl, 0);
bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
+ bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
sgl->word2 = cpu_to_le32(sgl->word2);
sgl->sge_len = cpu_to_le32(dma_len);
dma_offset += dma_len;
@@ -2325,8 +2499,9 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
}
lp = (uint32_t *)cmnd->sense_buffer;
- if (!scsi_status && (resp_info & RESID_UNDER))
- logit = LOG_FCP;
+ if (!scsi_status && (resp_info & RESID_UNDER) &&
+ vport->cfg_log_verbose & LOG_FCP_UNDER)
+ logit = LOG_FCP_UNDER;
lpfc_printf_vlog(vport, KERN_WARNING, logit,
"9024 FCP command x%x failed: x%x SNS x%x x%x "
@@ -2342,7 +2517,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
if (resp_info & RESID_UNDER) {
scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
- lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER,
"9025 FCP Read Underrun, expected %d, "
"residual %d Data: x%x x%x x%x\n",
be32_to_cpu(fcpcmd->fcpDl),
@@ -2449,6 +2624,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_fast_path_event *fast_path_evt;
struct Scsi_Host *shost;
uint32_t queue_depth, scsi_id;
+ uint32_t logit = LOG_FCP;
/* Sanity check on return of outstanding command */
if (!(lpfc_cmd->pCmd))
@@ -2470,16 +2646,22 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
else if (lpfc_cmd->status >= IOSTAT_CNT)
lpfc_cmd->status = IOSTAT_DEFAULT;
-
- lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
- "9030 FCP cmd x%x failed <%d/%d> "
- "status: x%x result: x%x Data: x%x x%x\n",
- cmd->cmnd[0],
- cmd->device ? cmd->device->id : 0xffff,
- cmd->device ? cmd->device->lun : 0xffff,
- lpfc_cmd->status, lpfc_cmd->result,
- pIocbOut->iocb.ulpContext,
- lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
+ if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR
+ && !lpfc_cmd->fcp_rsp->rspStatus3
+ && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER)
+ && !(phba->cfg_log_verbose & LOG_FCP_UNDER))
+ logit = 0;
+ else
+ logit = LOG_FCP | LOG_FCP_UNDER;
+ lpfc_printf_vlog(vport, KERN_WARNING, logit,
+ "9030 FCP cmd x%x failed <%d/%d> "
+ "status: x%x result: x%x Data: x%x x%x\n",
+ cmd->cmnd[0],
+ cmd->device ? cmd->device->id : 0xffff,
+ cmd->device ? cmd->device->lun : 0xffff,
+ lpfc_cmd->status, lpfc_cmd->result,
+ pIocbOut->iocb.ulpContext,
+ lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
switch (lpfc_cmd->status) {
case IOSTAT_FCP_RSP_ERROR:
@@ -3056,8 +3238,9 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
}
ndlp = rdata->pnode;
- if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
- scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
+ if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) &&
+ (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) ||
+ (phba->sli_rev == LPFC_SLI_REV4))) {
lpfc_printf_log(phba, KERN_ERR, LOG_BG,
"9058 BLKGRD: ERROR: rcvd protected cmd:%02x"
@@ -3691,9 +3874,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
fc_host_post_vendor_event(shost, fc_get_event_number(),
sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
- ret = fc_block_scsi_eh(cmnd);
- if (ret)
- return ret;
+ status = fc_block_scsi_eh(cmnd);
+ if (status)
+ return status;
/*
* Since the driver manages a single bus device, reset all
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 5b28ea1..4d4104f 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -379,10 +379,10 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
dq->host_index = ((dq->host_index + 1) % dq->entry_count);
/* Ring The Header Receive Queue Doorbell */
- if (!(hq->host_index % LPFC_RQ_POST_BATCH)) {
+ if (!(hq->host_index % hq->entry_repost)) {
doorbell.word0 = 0;
bf_set(lpfc_rq_doorbell_num_posted, &doorbell,
- LPFC_RQ_POST_BATCH);
+ hq->entry_repost);
bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id);
writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr);
}
@@ -1864,7 +1864,7 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
{
if (phba->sli_rev == LPFC_SLI_REV4)
return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
- lpfc_hbq_defs[qno]->entry_count);
+ lpfc_hbq_defs[qno]->entry_count);
else
return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
lpfc_hbq_defs[qno]->init_count);
@@ -2200,10 +2200,13 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
/* Unknown mailbox command compl */
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"(%d):0323 Unknown Mailbox command "
- "x%x (x%x) Cmpl\n",
+ "x%x (x%x/x%x) Cmpl\n",
pmb->vport ? pmb->vport->vpi : 0,
pmbox->mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, pmb));
+ lpfc_sli_config_mbox_subsys_get(phba,
+ pmb),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ pmb));
phba->link_state = LPFC_HBA_ERROR;
phba->work_hs = HS_FFER3;
lpfc_handle_eratt(phba);
@@ -2215,17 +2218,19 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) {
/* Mbox cmd cmpl error - RETRYing */
lpfc_printf_log(phba, KERN_INFO,
- LOG_MBOX | LOG_SLI,
- "(%d):0305 Mbox cmd cmpl "
- "error - RETRYing Data: x%x "
- "(x%x) x%x x%x x%x\n",
- pmb->vport ? pmb->vport->vpi :0,
- pmbox->mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba,
- pmb),
- pmbox->mbxStatus,
- pmbox->un.varWords[0],
- pmb->vport->port_state);
+ LOG_MBOX | LOG_SLI,
+ "(%d):0305 Mbox cmd cmpl "
+ "error - RETRYing Data: x%x "
+ "(x%x/x%x) x%x x%x x%x\n",
+ pmb->vport ? pmb->vport->vpi : 0,
+ pmbox->mbxCommand,
+ lpfc_sli_config_mbox_subsys_get(phba,
+ pmb),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ pmb),
+ pmbox->mbxStatus,
+ pmbox->un.varWords[0],
+ pmb->vport->port_state);
pmbox->mbxStatus = 0;
pmbox->mbxOwner = OWN_HOST;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
@@ -2236,11 +2241,12 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
/* Mailbox cmd <cmd> Cmpl <cmpl> */
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0307 Mailbox cmd x%x (x%x) Cmpl x%p "
+ "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p "
"Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
pmb->vport ? pmb->vport->vpi : 0,
pmbox->mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, pmb),
+ lpfc_sli_config_mbox_subsys_get(phba, pmb),
+ lpfc_sli_config_mbox_opcode_get(phba, pmb),
pmb->mbox_cmpl,
*((uint32_t *) pmbox),
pmbox->un.varWords[0],
@@ -4686,6 +4692,175 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
}
/**
+ * lpfc_sli4_retrieve_pport_name - Retrieve SLI4 device physical port name
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine retrieves SLI4 device physical port name this PCI function
+ * is attached to.
+ *
+ * Return codes
+ * 0 - sucessful
+ * otherwise - failed to retrieve physical port name
+ **/
+static int
+lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba)
+{
+ LPFC_MBOXQ_t *mboxq;
+ struct lpfc_mbx_read_config *rd_config;
+ struct lpfc_mbx_get_cntl_attributes *mbx_cntl_attr;
+ struct lpfc_controller_attribute *cntl_attr;
+ struct lpfc_mbx_get_port_name *get_port_name;
+ void *virtaddr = NULL;
+ uint32_t alloclen, reqlen;
+ uint32_t shdr_status, shdr_add_status;
+ union lpfc_sli4_cfg_shdr *shdr;
+ char cport_name = 0;
+ int rc;
+
+ /* We assume nothing at this point */
+ phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL;
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_NON;
+
+ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq)
+ return -ENOMEM;
+
+ /* obtain link type and link number via READ_CONFIG */
+ lpfc_read_config(phba, mboxq);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ if (rc == MBX_SUCCESS) {
+ rd_config = &mboxq->u.mqe.un.rd_config;
+ if (bf_get(lpfc_mbx_rd_conf_lnk_ldv, rd_config)) {
+ phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL;
+ phba->sli4_hba.lnk_info.lnk_tp =
+ bf_get(lpfc_mbx_rd_conf_lnk_type, rd_config);
+ phba->sli4_hba.lnk_info.lnk_no =
+ bf_get(lpfc_mbx_rd_conf_lnk_numb, rd_config);
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3081 lnk_type:%d, lnk_numb:%d\n",
+ phba->sli4_hba.lnk_info.lnk_tp,
+ phba->sli4_hba.lnk_info.lnk_no);
+ goto retrieve_ppname;
+ } else
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3082 Mailbox (x%x) returned ldv:x0\n",
+ bf_get(lpfc_mqe_command,
+ &mboxq->u.mqe));
+ } else
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3083 Mailbox (x%x) failed, status:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ bf_get(lpfc_mqe_status, &mboxq->u.mqe));
+
+ /* obtain link type and link number via COMMON_GET_CNTL_ATTRIBUTES */
+ reqlen = sizeof(struct lpfc_mbx_get_cntl_attributes);
+ alloclen = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES, reqlen,
+ LPFC_SLI4_MBX_NEMBED);
+ if (alloclen < reqlen) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3084 Allocated DMA memory size (%d) is "
+ "less than the requested DMA memory size "
+ "(%d)\n", alloclen, reqlen);
+ rc = -ENOMEM;
+ goto out_free_mboxq;
+ }
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ virtaddr = mboxq->sge_array->addr[0];
+ mbx_cntl_attr = (struct lpfc_mbx_get_cntl_attributes *)virtaddr;
+ shdr = &mbx_cntl_attr->cfg_shdr;
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3085 Mailbox x%x (x%x/x%x) failed, "
+ "rc:x%x, status:x%x, add_status:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+ rc, shdr_status, shdr_add_status);
+ rc = -ENXIO;
+ goto out_free_mboxq;
+ }
+ cntl_attr = &mbx_cntl_attr->cntl_attr;
+ phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL;
+ phba->sli4_hba.lnk_info.lnk_tp =
+ bf_get(lpfc_cntl_attr_lnk_type, cntl_attr);
+ phba->sli4_hba.lnk_info.lnk_no =
+ bf_get(lpfc_cntl_attr_lnk_numb, cntl_attr);
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3086 lnk_type:%d, lnk_numb:%d\n",
+ phba->sli4_hba.lnk_info.lnk_tp,
+ phba->sli4_hba.lnk_info.lnk_no);
+
+retrieve_ppname:
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_GET_PORT_NAME,
+ sizeof(struct lpfc_mbx_get_port_name) -
+ sizeof(struct lpfc_sli4_cfg_mhdr),
+ LPFC_SLI4_MBX_EMBED);
+ get_port_name = &mboxq->u.mqe.un.get_port_name;
+ shdr = (union lpfc_sli4_cfg_shdr *)&get_port_name->header.cfg_shdr;
+ bf_set(lpfc_mbox_hdr_version, &shdr->request, LPFC_OPCODE_VERSION_1);
+ bf_set(lpfc_mbx_get_port_name_lnk_type, &get_port_name->u.request,
+ phba->sli4_hba.lnk_info.lnk_tp);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3087 Mailbox x%x (x%x/x%x) failed: "
+ "rc:x%x, status:x%x, add_status:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+ rc, shdr_status, shdr_add_status);
+ rc = -ENXIO;
+ goto out_free_mboxq;
+ }
+ switch (phba->sli4_hba.lnk_info.lnk_no) {
+ case LPFC_LINK_NUMBER_0:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name0,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ case LPFC_LINK_NUMBER_1:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name1,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ case LPFC_LINK_NUMBER_2:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name2,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ case LPFC_LINK_NUMBER_3:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name3,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ default:
+ break;
+ }
+
+ if (phba->sli4_hba.pport_name_sta == LPFC_SLI4_PPNAME_GET) {
+ phba->Port[0] = cport_name;
+ phba->Port[1] = '\0';
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3091 SLI get port name: %s\n", phba->Port);
+ }
+
+out_free_mboxq:
+ if (rc != MBX_TIMEOUT) {
+ if (bf_get(lpfc_mqe_command, &mboxq->u.mqe) == MBX_SLI4_CONFIG)
+ lpfc_sli4_mbox_cmd_free(phba, mboxq);
+ else
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ }
+ return rc;
+}
+
+/**
* lpfc_sli4_arm_cqeq_intr - Arm sli-4 device completion and event queues
* @phba: pointer to lpfc hba data structure.
*
@@ -4714,10 +4889,15 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
* lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count.
* @phba: Pointer to HBA context object.
* @type: The resource extent type.
+ * @extnt_count: buffer to hold port available extent count.
+ * @extnt_size: buffer to hold element count per extent.
*
- * This function allocates all SLI4 resource identifiers.
+ * This function calls the port and retrievs the number of available
+ * extents and their size for a particular extent type.
+ *
+ * Returns: 0 if successful. Nonzero otherwise.
**/
-static int
+int
lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
uint16_t *extnt_count, uint16_t *extnt_size)
{
@@ -4749,7 +4929,7 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
if (unlikely(rc)) {
@@ -4894,7 +5074,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
req_len, *emb);
if (alloc_len < req_len) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "9000 Allocated DMA memory size (x%x) is "
+ "2982 Allocated DMA memory size (x%x) is "
"less than the requested DMA memory "
"size (x%x)\n", alloc_len, req_len);
return -ENOMEM;
@@ -4906,7 +5086,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
@@ -5189,7 +5369,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, mbox_tmo);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
if (unlikely(rc)) {
@@ -5508,6 +5688,154 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
}
/**
+ * lpfc_sli4_get_allocated_extnts - Get the port's allocated extents.
+ * @phba: Pointer to HBA context object.
+ * @type: The resource extent type.
+ * @extnt_count: buffer to hold port extent count response
+ * @extnt_size: buffer to hold port extent size response.
+ *
+ * This function calls the port to read the host allocated extents
+ * for a particular type.
+ **/
+int
+lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type,
+ uint16_t *extnt_cnt, uint16_t *extnt_size)
+{
+ bool emb;
+ int rc = 0;
+ uint16_t curr_blks = 0;
+ uint32_t req_len, emb_len;
+ uint32_t alloc_len, mbox_tmo;
+ struct list_head *blk_list_head;
+ struct lpfc_rsrc_blks *rsrc_blk;
+ LPFC_MBOXQ_t *mbox;
+ void *virtaddr = NULL;
+ struct lpfc_mbx_nembed_rsrc_extent *n_rsrc;
+ struct lpfc_mbx_alloc_rsrc_extents *rsrc_ext;
+ union lpfc_sli4_cfg_shdr *shdr;
+
+ switch (type) {
+ case LPFC_RSC_TYPE_FCOE_VPI:
+ blk_list_head = &phba->lpfc_vpi_blk_list;
+ break;
+ case LPFC_RSC_TYPE_FCOE_XRI:
+ blk_list_head = &phba->sli4_hba.lpfc_xri_blk_list;
+ break;
+ case LPFC_RSC_TYPE_FCOE_VFI:
+ blk_list_head = &phba->sli4_hba.lpfc_vfi_blk_list;
+ break;
+ case LPFC_RSC_TYPE_FCOE_RPI:
+ blk_list_head = &phba->sli4_hba.lpfc_rpi_blk_list;
+ break;
+ default:
+ return -EIO;
+ }
+
+ /* Count the number of extents currently allocatd for this type. */
+ list_for_each_entry(rsrc_blk, blk_list_head, list) {
+ if (curr_blks == 0) {
+ /*
+ * The GET_ALLOCATED mailbox does not return the size,
+ * just the count. The size should be just the size
+ * stored in the current allocated block and all sizes
+ * for an extent type are the same so set the return
+ * value now.
+ */
+ *extnt_size = rsrc_blk->rsrc_size;
+ }
+ curr_blks++;
+ }
+
+ /* Calculate the total requested length of the dma memory. */
+ req_len = curr_blks * sizeof(uint16_t);
+
+ /*
+ * Calculate the size of an embedded mailbox. The uint32_t
+ * accounts for extents-specific word.
+ */
+ emb_len = sizeof(MAILBOX_t) - sizeof(struct mbox_header) -
+ sizeof(uint32_t);
+
+ /*
+ * Presume the allocation and response will fit into an embedded
+ * mailbox. If not true, reconfigure to a non-embedded mailbox.
+ */
+ emb = LPFC_SLI4_MBX_EMBED;
+ req_len = emb_len;
+ if (req_len > emb_len) {
+ req_len = curr_blks * sizeof(uint16_t) +
+ sizeof(union lpfc_sli4_cfg_shdr) +
+ sizeof(uint32_t);
+ emb = LPFC_SLI4_MBX_NEMBED;
+ }
+
+ mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mbox)
+ return -ENOMEM;
+ memset(mbox, 0, sizeof(LPFC_MBOXQ_t));
+
+ alloc_len = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT,
+ req_len, emb);
+ if (alloc_len < req_len) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2983 Allocated DMA memory size (x%x) is "
+ "less than the requested DMA memory "
+ "size (x%x)\n", alloc_len, req_len);
+ rc = -ENOMEM;
+ goto err_exit;
+ }
+ rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, curr_blks, type, emb);
+ if (unlikely(rc)) {
+ rc = -EIO;
+ goto err_exit;
+ }
+
+ if (!phba->sli4_hba.intr_enable)
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
+ else {
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
+ rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
+ }
+
+ if (unlikely(rc)) {
+ rc = -EIO;
+ goto err_exit;
+ }
+
+ /*
+ * Figure out where the response is located. Then get local pointers
+ * to the response data. The port does not guarantee to respond to
+ * all extents counts request so update the local variable with the
+ * allocated count from the port.
+ */
+ if (emb == LPFC_SLI4_MBX_EMBED) {
+ rsrc_ext = &mbox->u.mqe.un.alloc_rsrc_extents;
+ shdr = &rsrc_ext->header.cfg_shdr;
+ *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, &rsrc_ext->u.rsp);
+ } else {
+ virtaddr = mbox->sge_array->addr[0];
+ n_rsrc = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr;
+ shdr = &n_rsrc->cfg_shdr;
+ *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, n_rsrc);
+ }
+
+ if (bf_get(lpfc_mbox_hdr_status, &shdr->response)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+ "2984 Failed to read allocated resources "
+ "for type %d - Status 0x%x Add'l Status 0x%x.\n",
+ type,
+ bf_get(lpfc_mbox_hdr_status, &shdr->response),
+ bf_get(lpfc_mbox_hdr_add_status, &shdr->response));
+ rc = -EIO;
+ goto err_exit;
+ }
+ err_exit:
+ lpfc_sli4_mbox_cmd_free(phba, mbox);
+ return rc;
+}
+
+/**
* lpfc_sli4_hba_setup - SLI4 device intialization PCI function
* @phba: Pointer to HBA context object.
*
@@ -5595,6 +5923,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
kfree(vpd);
goto out_free_mbox;
}
+
+ /*
+ * Retrieve sli4 device physical port name, failure of doing it
+ * is considered as non-fatal.
+ */
+ rc = lpfc_sli4_retrieve_pport_name(phba);
+ if (!rc)
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "3080 Successful retrieving SLI4 device "
+ "physical port name: %s.\n", phba->Port);
+
/*
* Evaluate the read rev and vpd data. Populate the driver
* state with the results. If this routine fails, the failure
@@ -5665,9 +6004,13 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
* then turn off the global config parameters to disable the
* feature in the driver. This is not a fatal error.
*/
- if ((phba->cfg_enable_bg) &&
- !(bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)))
- ftr_rsp++;
+ phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED;
+ if (phba->cfg_enable_bg) {
+ if (bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))
+ phba->sli3_options |= LPFC_SLI3_BG_ENABLED;
+ else
+ ftr_rsp++;
+ }
if (phba->max_vpi && phba->cfg_enable_npiv &&
!(bf_get(lpfc_mbx_rq_ftr_rsp_npiv, &mqe->un.req_ftrs)))
@@ -5784,12 +6127,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
goto out_free_mbox;
}
+ /* Create all the SLI4 queues */
+ rc = lpfc_sli4_queue_create(phba);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3089 Failed to allocate queues\n");
+ rc = -ENODEV;
+ goto out_stop_timers;
+ }
/* Set up all the queues to the device */
rc = lpfc_sli4_queue_setup(phba);
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0381 Error %d during queue setup.\n ", rc);
- goto out_stop_timers;
+ goto out_destroy_queue;
}
/* Arm the CQs and then EQs on device */
@@ -5862,15 +6213,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock);
- if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
+ if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) {
rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+ if (rc)
+ goto out_unset_queue;
+ }
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ return rc;
out_unset_queue:
/* Unset all the queues set up in this routine when error out */
- if (rc)
- lpfc_sli4_queue_unset(phba);
+ lpfc_sli4_queue_unset(phba);
+out_destroy_queue:
+ lpfc_sli4_queue_destroy(phba);
out_stop_timers:
- if (rc)
- lpfc_stop_hba_timers(phba);
+ lpfc_stop_hba_timers(phba);
out_free_mbox:
mempool_free(mboxq, phba->mbox_mem_pool);
return rc;
@@ -6165,7 +6521,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
}
/* timeout active mbox command */
mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand))));
+ (HZ * lpfc_mbox_tmo_val(phba, pmbox))));
}
/* Mailbox cmd <cmd> issue */
@@ -6289,9 +6645,8 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
drvr_flag);
goto out_not_finished;
}
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
- mb->mbxCommand) *
- 1000) + jiffies;
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) *
+ 1000) + jiffies;
i = 0;
/* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP) ||
@@ -6402,21 +6757,21 @@ static int
lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
- uint8_t actcmd = MBX_HEARTBEAT;
int rc = 0;
- unsigned long timeout;
+ unsigned long timeout = 0;
/* Mark the asynchronous mailbox command posting as blocked */
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
- if (phba->sli.mbox_active)
- actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
- spin_unlock_irq(&phba->hbalock);
/* Determine how long we might wait for the active mailbox
* command to be gracefully completed by firmware.
*/
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
- jiffies;
+ if (phba->sli.mbox_active)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ phba->sli.mbox_active) *
+ 1000) + jiffies;
+ spin_unlock_irq(&phba->hbalock);
+
/* Wait for the outstnading mailbox command to complete */
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
@@ -6511,11 +6866,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
spin_unlock_irqrestore(&phba->hbalock, iflag);
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2532 Mailbox command x%x (x%x) "
+ "(%d):2532 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, MBX_POLL);
return MBXERR_ERROR;
}
@@ -6538,7 +6894,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
dma_address = &phba->sli4_hba.bmbx.dma_address;
writel(dma_address->addr_hi, phba->sli4_hba.BMBXregaddr);
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
* 1000) + jiffies;
do {
bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
@@ -6554,7 +6910,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
/* Post the low mailbox dma address to the port. */
writel(dma_address->addr_lo, phba->sli4_hba.BMBXregaddr);
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
* 1000) + jiffies;
do {
bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
@@ -6593,11 +6949,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
lpfc_sli4_swap_str(phba, mboxq);
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0356 Mailbox cmd x%x (x%x) Status x%x "
+ "(%d):0356 Mailbox cmd x%x (x%x/x%x) Status x%x "
"Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x x%x x%x"
" x%x x%x CQ: x%x x%x x%x x%x\n",
- mboxq->vport ? mboxq->vport->vpi : 0,
- mbx_cmnd, lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd,
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
bf_get(lpfc_mqe_status, mb),
mb->un.mb_words[0], mb->un.mb_words[1],
mb->un.mb_words[2], mb->un.mb_words[3],
@@ -6637,14 +6994,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
unsigned long iflags;
int rc;
+ /* dump from issue mailbox command if setup */
+ lpfc_idiag_mbxacc_dump_issue_mbox(phba, &mboxq->u.mb);
+
rc = lpfc_mbox_dev_check(phba);
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2544 Mailbox command x%x (x%x) "
+ "(%d):2544 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
goto out_not_finished;
}
@@ -6658,20 +7019,25 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
if (rc != MBX_SUCCESS)
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
"(%d):2541 Mailbox command x%x "
- "(x%x) cannot issue Data: x%x x%x\n",
+ "(x%x/x%x) cannot issue Data: "
+ "x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba,
+ mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ mboxq),
psli->sli_flag, flag);
return rc;
} else if (flag == MBX_POLL) {
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
"(%d):2542 Try to issue mailbox command "
- "x%x (x%x) synchronously ahead of async"
+ "x%x (x%x/x%x) synchronously ahead of async"
"mailbox command queue: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
/* Try to block the asynchronous mailbox posting */
rc = lpfc_sli4_async_mbox_block(phba);
@@ -6680,16 +7046,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
rc = lpfc_sli4_post_sync_mbox(phba, mboxq);
if (rc != MBX_SUCCESS)
lpfc_printf_log(phba, KERN_ERR,
- LOG_MBOX | LOG_SLI,
- "(%d):2597 Mailbox command "
- "x%x (x%x) cannot issue "
- "Data: x%x x%x\n",
- mboxq->vport ?
- mboxq->vport->vpi : 0,
- mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba,
- mboxq),
- psli->sli_flag, flag);
+ LOG_MBOX | LOG_SLI,
+ "(%d):2597 Mailbox command "
+ "x%x (x%x/x%x) cannot issue "
+ "Data: x%x x%x\n",
+ mboxq->vport ?
+ mboxq->vport->vpi : 0,
+ mboxq->u.mb.mbxCommand,
+ lpfc_sli_config_mbox_subsys_get(phba,
+ mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ mboxq),
+ psli->sli_flag, flag);
/* Unblock the async mailbox posting afterward */
lpfc_sli4_async_mbox_unblock(phba);
}
@@ -6700,11 +7068,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
rc = lpfc_mbox_cmd_check(phba, mboxq);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2543 Mailbox command x%x (x%x) "
+ "(%d):2543 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
goto out_not_finished;
}
@@ -6716,10 +7085,11 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
spin_unlock_irqrestore(&phba->hbalock, iflags);
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
"(%d):0354 Mbox cmd issue - Enqueue Data: "
- "x%x (x%x) x%x x%x x%x\n",
+ "x%x (x%x/x%x) x%x x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0xffffff,
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
phba->pport->port_state,
psli->sli_flag, MBX_NOWAIT);
/* Wake up worker thread to transport mailbox command from head */
@@ -6796,13 +7166,14 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
/* Start timer for the mbox_tmo and log some mailbox post messages */
mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, mbx_cmnd))));
+ (HZ * lpfc_mbox_tmo_val(phba, mboxq))));
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0355 Mailbox cmd x%x (x%x) issue Data: "
+ "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: "
"x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
phba->pport->port_state, psli->sli_flag);
if (mbx_cmnd != MBX_HEARTBEAT) {
@@ -6826,11 +7197,12 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
rc = lpfc_sli4_mq_put(phba->sli4_hba.mbx_wq, mqe);
if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2533 Mailbox command x%x (x%x) "
+ "(%d):2533 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, MBX_NOWAIT);
goto out_not_finished;
}
@@ -7166,6 +7538,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
if (inbound == 1)
offset = 0;
bf_set(lpfc_sli4_sge_offset, sgl, offset);
+ bf_set(lpfc_sli4_sge_type, sgl,
+ LPFC_SGE_TYPE_DATA);
offset += bde.tus.f.bdeSize;
}
sgl->word2 = cpu_to_le32(sgl->word2);
@@ -9203,7 +9577,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
/* now issue the command */
retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
-
if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
wait_event_interruptible_timeout(done_q,
pmboxq->mbox_flag & LPFC_MBX_WAKE,
@@ -9247,23 +9620,24 @@ void
lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
- uint8_t actcmd = MBX_HEARTBEAT;
unsigned long timeout;
+ timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies;
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
spin_unlock_irq(&phba->hbalock);
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
spin_lock_irq(&phba->hbalock);
- if (phba->sli.mbox_active)
- actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
- spin_unlock_irq(&phba->hbalock);
/* Determine how long we might wait for the active mailbox
* command to be gracefully completed by firmware.
*/
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) *
- 1000) + jiffies;
+ if (phba->sli.mbox_active)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ phba->sli.mbox_active) *
+ 1000) + jiffies;
+ spin_unlock_irq(&phba->hbalock);
+
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
msleep(2);
@@ -10259,12 +10633,17 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe)
/* Move mbox data to caller's mailbox region, do endian swapping */
if (pmb->mbox_cmpl && mbox)
lpfc_sli_pcimem_bcopy(mbox, mqe, sizeof(struct lpfc_mqe));
- /* Set the mailbox status with SLI4 range 0x4000 */
- mcqe_status = bf_get(lpfc_mcqe_status, mcqe);
- if (mcqe_status != MB_CQE_STATUS_SUCCESS)
- bf_set(lpfc_mqe_status, mqe,
- (LPFC_MBX_ERROR_RANGE | mcqe_status));
+ /*
+ * For mcqe errors, conditionally move a modified error code to
+ * the mbox so that the error will not be missed.
+ */
+ mcqe_status = bf_get(lpfc_mcqe_status, mcqe);
+ if (mcqe_status != MB_CQE_STATUS_SUCCESS) {
+ if (bf_get(lpfc_mqe_status, mqe) == MBX_SUCCESS)
+ bf_set(lpfc_mqe_status, mqe,
+ (LPFC_MBX_ERROR_RANGE | mcqe_status));
+ }
if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_MBOX_VPORT,
@@ -10640,7 +11019,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
case LPFC_MCQ:
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % cq->entry_repost))
lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
}
break;
@@ -10652,7 +11031,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
else
workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
cqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % cq->entry_repost))
lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
}
break;
@@ -10884,7 +11263,7 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
/* Process all the entries to the CQ */
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_fp_handle_wcqe(phba, cq, cqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % cq->entry_repost))
lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
}
@@ -10954,6 +11333,8 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id)
/* Get to the EQ struct associated with this vector */
speq = phba->sli4_hba.sp_eq;
+ if (unlikely(!speq))
+ return IRQ_NONE;
/* Check device state for handling interrupt */
if (unlikely(lpfc_intr_state_check(phba))) {
@@ -10971,7 +11352,7 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id)
*/
while ((eqe = lpfc_sli4_eq_get(speq))) {
lpfc_sli4_sp_handle_eqe(phba, eqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % speq->entry_repost))
lpfc_sli4_eq_release(speq, LPFC_QUEUE_NOARM);
}
@@ -11031,6 +11412,8 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id)
if (unlikely(!phba))
return IRQ_NONE;
+ if (unlikely(!phba->sli4_hba.fp_eq))
+ return IRQ_NONE;
/* Get to the EQ struct associated with this vector */
fpeq = phba->sli4_hba.fp_eq[fcp_eqidx];
@@ -11051,7 +11434,7 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id)
*/
while ((eqe = lpfc_sli4_eq_get(fpeq))) {
lpfc_sli4_fp_handle_eqe(phba, eqe, fcp_eqidx);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % fpeq->entry_repost))
lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_NOARM);
}
@@ -11203,6 +11586,15 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
}
queue->entry_size = entry_size;
queue->entry_count = entry_count;
+
+ /*
+ * entry_repost is calculated based on the number of entries in the
+ * queue. This works out except for RQs. If buffers are NOT initially
+ * posted for every RQE, entry_repost should be adjusted accordingly.
+ */
+ queue->entry_repost = (entry_count >> 3);
+ if (queue->entry_repost < LPFC_QUEUE_MIN_REPOST)
+ queue->entry_repost = LPFC_QUEUE_MIN_REPOST;
queue->phba = phba;
return queue;
@@ -11768,6 +12160,31 @@ out:
}
/**
+ * lpfc_rq_adjust_repost - Adjust entry_repost for an RQ
+ * @phba: HBA structure that indicates port to create a queue on.
+ * @rq: The queue structure to use for the receive queue.
+ * @qno: The associated HBQ number
+ *
+ *
+ * For SLI4 we need to adjust the RQ repost value based on
+ * the number of buffers that are initially posted to the RQ.
+ */
+void
+lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno)
+{
+ uint32_t cnt;
+
+ cnt = lpfc_hbq_defs[qno]->entry_count;
+
+ /* Recalc repost for RQs based on buffers initially posted */
+ cnt = (cnt >> 3);
+ if (cnt < LPFC_QUEUE_MIN_REPOST)
+ cnt = LPFC_QUEUE_MIN_REPOST;
+
+ rq->entry_repost = cnt;
+}
+
+/**
* lpfc_rq_create - Create a Receive Queue on the HBA
* @phba: HBA structure that indicates port to create a queue on.
* @hrq: The queue structure to use to create the header receive queue.
@@ -12333,7 +12750,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
/* The IOCTL status is embedded in the mailbox subheader. */
@@ -12548,7 +12965,7 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12711,7 +13128,7 @@ lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12835,7 +13252,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12991,7 +13408,7 @@ lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -13140,7 +13557,8 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr,
uint32_t did = (fc_hdr->fh_d_id[0] << 16 |
fc_hdr->fh_d_id[1] << 8 |
fc_hdr->fh_d_id[2]);
-
+ if (did == Fabric_DID)
+ return phba->pport;
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
@@ -14156,7 +14574,7 @@ lpfc_sli4_init_vpi(struct lpfc_vport *vport)
if (!mboxq)
return -ENOMEM;
lpfc_init_vpi(phba, mboxq, vport->vpi);
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
if (rc != MBX_SUCCESS) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
@@ -14479,6 +14897,92 @@ fail_fcf_read:
}
/**
+ * lpfc_check_next_fcf_pri
+ * phba pointer to the lpfc_hba struct for this port.
+ * This routine is called from the lpfc_sli4_fcf_rr_next_index_get
+ * routine when the rr_bmask is empty. The FCF indecies are put into the
+ * rr_bmask based on their priority level. Starting from the highest priority
+ * to the lowest. The most likely FCF candidate will be in the highest
+ * priority group. When this routine is called it searches the fcf_pri list for
+ * next lowest priority group and repopulates the rr_bmask with only those
+ * fcf_indexes.
+ * returns:
+ * 1=success 0=failure
+ **/
+int
+lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba)
+{
+ uint16_t next_fcf_pri;
+ uint16_t last_index;
+ struct lpfc_fcf_pri *fcf_pri;
+ int rc;
+ int ret = 0;
+
+ last_index = find_first_bit(phba->fcf.fcf_rr_bmask,
+ LPFC_SLI4_FCF_TBL_INDX_MAX);
+ lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+ "3060 Last IDX %d\n", last_index);
+ if (list_empty(&phba->fcf.fcf_pri_list)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+ "3061 Last IDX %d\n", last_index);
+ return 0; /* Empty rr list */
+ }
+ next_fcf_pri = 0;
+ /*
+ * Clear the rr_bmask and set all of the bits that are at this
+ * priority.
+ */
+ memset(phba->fcf.fcf_rr_bmask, 0,
+ sizeof(*phba->fcf.fcf_rr_bmask));
+ spin_lock_irq(&phba->hbalock);
+ list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+ if (fcf_pri->fcf_rec.flag & LPFC_FCF_FLOGI_FAILED)
+ continue;
+ /*
+ * the 1st priority that has not FLOGI failed
+ * will be the highest.
+ */
+ if (!next_fcf_pri)
+ next_fcf_pri = fcf_pri->fcf_rec.priority;
+ spin_unlock_irq(&phba->hbalock);
+ if (fcf_pri->fcf_rec.priority == next_fcf_pri) {
+ rc = lpfc_sli4_fcf_rr_index_set(phba,
+ fcf_pri->fcf_rec.fcf_index);
+ if (rc)
+ return 0;
+ }
+ spin_lock_irq(&phba->hbalock);
+ }
+ /*
+ * if next_fcf_pri was not set above and the list is not empty then
+ * we have failed flogis on all of them. So reset flogi failed
+ * and start at the begining.
+ */
+ if (!next_fcf_pri && !list_empty(&phba->fcf.fcf_pri_list)) {
+ list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+ fcf_pri->fcf_rec.flag &= ~LPFC_FCF_FLOGI_FAILED;
+ /*
+ * the 1st priority that has not FLOGI failed
+ * will be the highest.
+ */
+ if (!next_fcf_pri)
+ next_fcf_pri = fcf_pri->fcf_rec.priority;
+ spin_unlock_irq(&phba->hbalock);
+ if (fcf_pri->fcf_rec.priority == next_fcf_pri) {
+ rc = lpfc_sli4_fcf_rr_index_set(phba,
+ fcf_pri->fcf_rec.fcf_index);
+ if (rc)
+ return 0;
+ }
+ spin_lock_irq(&phba->hbalock);
+ }
+ } else
+ ret = 1;
+ spin_unlock_irq(&phba->hbalock);
+
+ return ret;
+}
+/**
* lpfc_sli4_fcf_rr_next_index_get - Get next eligible fcf record index
* @phba: pointer to lpfc hba data structure.
*
@@ -14494,6 +14998,7 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
uint16_t next_fcf_index;
/* Search start from next bit of currently registered FCF index */
+next_priority:
next_fcf_index = (phba->fcf.current_rec.fcf_indx + 1) %
LPFC_SLI4_FCF_TBL_INDX_MAX;
next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
@@ -14501,17 +15006,46 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
next_fcf_index);
/* Wrap around condition on phba->fcf.fcf_rr_bmask */
- if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
+ if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+ /*
+ * If we have wrapped then we need to clear the bits that
+ * have been tested so that we can detect when we should
+ * change the priority level.
+ */
next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
LPFC_SLI4_FCF_TBL_INDX_MAX, 0);
+ }
+
/* Check roundrobin failover list empty condition */
- if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+ if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX ||
+ next_fcf_index == phba->fcf.current_rec.fcf_indx) {
+ /*
+ * If next fcf index is not found check if there are lower
+ * Priority level fcf's in the fcf_priority list.
+ * Set up the rr_bmask with all of the avaiable fcf bits
+ * at that level and continue the selection process.
+ */
+ if (lpfc_check_next_fcf_pri_level(phba))
+ goto next_priority;
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
"2844 No roundrobin failover FCF available\n");
- return LPFC_FCOE_FCF_NEXT_NONE;
+ if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
+ return LPFC_FCOE_FCF_NEXT_NONE;
+ else {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+ "3063 Only FCF available idx %d, flag %x\n",
+ next_fcf_index,
+ phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag);
+ return next_fcf_index;
+ }
}
+ if (next_fcf_index < LPFC_SLI4_FCF_TBL_INDX_MAX &&
+ phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag &
+ LPFC_FCF_FLOGI_FAILED)
+ goto next_priority;
+
lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
"2845 Get next roundrobin failover FCF (x%x)\n",
next_fcf_index);
@@ -14563,6 +15097,7 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index)
void
lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
{
+ struct lpfc_fcf_pri *fcf_pri;
if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
"2762 FCF (x%x) reached driver's book "
@@ -14571,6 +15106,14 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
return;
}
/* Clear the eligible FCF record index bmask */
+ spin_lock_irq(&phba->hbalock);
+ list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+ if (fcf_pri->fcf_rec.fcf_index == fcf_index) {
+ list_del_init(&fcf_pri->list);
+ break;
+ }
+ }
+ spin_unlock_irq(&phba->hbalock);
clear_bit(fcf_index, phba->fcf.fcf_rr_bmask);
lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
@@ -14907,7 +15450,7 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
/* The IOCTL status is embedded in the mailbox subheader. */
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index a0075b0..29c13b6 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -293,13 +293,11 @@ struct lpfc_sli {
struct lpfc_lnk_stat lnk_stat_offsets;
};
-#define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox
- command */
-#define LPFC_MBOX_SLI4_CONFIG_TMO 60 /* Sec tmo for outstanding mbox
- command */
-#define LPFC_MBOX_TMO_FLASH_CMD 300 /* Sec tmo for outstanding FLASH write
- * or erase cmds. This is especially
- * long because of the potential of
- * multiple flash erases that can be
- * spawned.
- */
+/* Timeout for normal outstanding mbox command (Seconds) */
+#define LPFC_MBOX_TMO 30
+/* Timeout for non-flash-based outstanding sli_config mbox command (Seconds) */
+#define LPFC_MBOX_SLI4_CONFIG_TMO 60
+/* Timeout for flash-based outstanding sli_config mbox command (Seconds) */
+#define LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO 300
+/* Timeout for other flash-based outstanding mbox command (Seconds) */
+#define LPFC_MBOX_TMO_FLASH_CMD 300
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 88387c1..d5cffd8 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -23,7 +23,6 @@
#define LPFC_XRI_EXCH_BUSY_WAIT_T1 10
#define LPFC_XRI_EXCH_BUSY_WAIT_T2 30000
#define LPFC_RELEASE_NOTIFICATION_INTERVAL 32
-#define LPFC_GET_QE_REL_INT 32
#define LPFC_RPI_LOW_WATER_MARK 10
#define LPFC_UNREG_FCF 1
@@ -126,6 +125,8 @@ struct lpfc_queue {
struct list_head child_list;
uint32_t entry_count; /* Number of entries to support on the queue */
uint32_t entry_size; /* Size of each queue entry. */
+ uint32_t entry_repost; /* Count of entries before doorbell is rung */
+#define LPFC_QUEUE_MIN_REPOST 8
uint32_t queue_id; /* Queue ID assigned by the hardware */
uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */
struct list_head page_list;
@@ -159,6 +160,25 @@ struct lpfc_fcf_rec {
#define RECORD_VALID 0x02
};
+struct lpfc_fcf_pri_rec {
+ uint16_t fcf_index;
+#define LPFC_FCF_ON_PRI_LIST 0x0001
+#define LPFC_FCF_FLOGI_FAILED 0x0002
+ uint16_t flag;
+ uint32_t priority;
+};
+
+struct lpfc_fcf_pri {
+ struct list_head list;
+ struct lpfc_fcf_pri_rec fcf_rec;
+};
+
+/*
+ * Maximum FCF table index, it is for driver internal book keeping, it
+ * just needs to be no less than the supported HBA's FCF table size.
+ */
+#define LPFC_SLI4_FCF_TBL_INDX_MAX 32
+
struct lpfc_fcf {
uint16_t fcfi;
uint32_t fcf_flag;
@@ -178,15 +198,13 @@ struct lpfc_fcf {
uint32_t eligible_fcf_cnt;
struct lpfc_fcf_rec current_rec;
struct lpfc_fcf_rec failover_rec;
+ struct list_head fcf_pri_list;
+ struct lpfc_fcf_pri fcf_pri[LPFC_SLI4_FCF_TBL_INDX_MAX];
+ uint32_t current_fcf_scan_pri;
struct timer_list redisc_wait;
unsigned long *fcf_rr_bmask; /* Eligible FCF indexes for RR failover */
};
-/*
- * Maximum FCF table index, it is for driver internal book keeping, it
- * just needs to be no less than the supported HBA's FCF table size.
- */
-#define LPFC_SLI4_FCF_TBL_INDX_MAX 32
#define LPFC_REGION23_SIGNATURE "RG23"
#define LPFC_REGION23_VERSION 1
@@ -371,6 +389,16 @@ struct lpfc_iov {
uint32_t vf_number;
};
+struct lpfc_sli4_lnk_info {
+ uint8_t lnk_dv;
+#define LPFC_LNK_DAT_INVAL 0
+#define LPFC_LNK_DAT_VAL 1
+ uint8_t lnk_tp;
+#define LPFC_LNK_GE 0x0 /* FCoE */
+#define LPFC_LNK_FC 0x1 /* FC */
+ uint8_t lnk_no;
+};
+
/* SLI4 HBA data structure entries */
struct lpfc_sli4_hba {
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
@@ -486,6 +514,10 @@ struct lpfc_sli4_hba {
struct list_head sp_els_xri_aborted_work_queue;
struct list_head sp_unsol_work_queue;
struct lpfc_sli4_link link_state;
+ struct lpfc_sli4_lnk_info lnk_info;
+ uint32_t pport_name_sta;
+#define LPFC_SLI4_PPNAME_NON 0
+#define LPFC_SLI4_PPNAME_GET 1
struct lpfc_iov iov;
spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
@@ -536,6 +568,7 @@ struct lpfc_rsrc_blks {
* SLI4 specific function prototypes
*/
int lpfc_pci_function_reset(struct lpfc_hba *);
+int lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *);
int lpfc_sli4_hba_setup(struct lpfc_hba *);
int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
uint8_t, uint32_t, bool);
@@ -559,6 +592,7 @@ uint32_t lpfc_wq_create(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_queue *, uint32_t);
uint32_t lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_queue *, struct lpfc_queue *, uint32_t);
+void lpfc_rq_adjust_repost(struct lpfc_hba *, struct lpfc_queue *, int);
uint32_t lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *);
uint32_t lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *);
uint32_t lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *);
@@ -615,5 +649,5 @@ void lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_sli4_unregister_fcf(struct lpfc_hba *);
int lpfc_sli4_post_status_check(struct lpfc_hba *);
-uint8_t lpfc_sli4_mbox_opcode_get(struct lpfc_hba *, struct lpfcMboxq *);
-
+uint8_t lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
+uint8_t lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index c03921b..b0630e3 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.23"
+#define LPFC_DRIVER_VERSION "8.3.27"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 1feb551..cff6ca6 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -692,13 +692,14 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
/* Indicate free memory when release */
NLP_SET_FREE_REQ(ndlp);
} else {
- if (!NLP_CHK_NODE_ACT(ndlp))
+ if (!NLP_CHK_NODE_ACT(ndlp)) {
ndlp = lpfc_enable_node(vport, ndlp,
NLP_STE_UNUSED_NODE);
if (!ndlp)
goto skip_logo;
+ }
- /* Remove ndlp from vport npld list */
+ /* Remove ndlp from vport list */
lpfc_dequeue_node(vport, ndlp);
spin_lock_irq(&phba->ndlp_lock);
if (!NLP_CHK_FREE_REQ(ndlp))
@@ -711,8 +712,17 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
}
spin_unlock_irq(&phba->ndlp_lock);
}
- if (!(vport->vpi_state & LPFC_VPI_REGISTERED))
+
+ /*
+ * If the vpi is not registered, then a valid FDISC doesn't
+ * exist and there is no need for a ELS LOGO. Just cleanup
+ * the ndlp.
+ */
+ if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) {
+ lpfc_nlp_put(ndlp);
goto skip_logo;
+ }
+
vport->unreg_vpi_cmpl = VPORT_INVAL;
timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
if (!lpfc_issue_els_npiv_logo(vport, ndlp))
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 2e6619e..35bd138 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -67,10 +67,11 @@
*
* NEC MegaRAID PCI Express ROMB 1000 0408 1033 8287
*
- * For history of changes, see Documentation/ChangeLog.megaraid
+ * For history of changes, see Documentation/scsi/ChangeLog.megaraid
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include "megaraid_mbox.h"
static int megaraid_init(void);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 7370c08..049c22f 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -33,9 +33,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.05.38-rc1"
-#define MEGASAS_RELDATE "May. 11, 2011"
-#define MEGASAS_EXT_VERSION "Wed. May. 11 17:00:00 PDT 2011"
+#define MEGASAS_VERSION "00.00.06.12-rc1"
+#define MEGASAS_RELDATE "Oct. 5, 2011"
+#define MEGASAS_EXT_VERSION "Wed. Oct. 5 17:00:00 PDT 2011"
/*
* Device IDs
@@ -48,6 +48,7 @@
#define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073
#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071
#define PCI_DEVICE_ID_LSI_FUSION 0x005b
+#define PCI_DEVICE_ID_LSI_INVADER 0x005d
/*
* =====================================
@@ -138,6 +139,7 @@
#define MFI_CMD_ABORT 0x06
#define MFI_CMD_SMP 0x07
#define MFI_CMD_STP 0x08
+#define MFI_CMD_INVALID 0xff
#define MR_DCMD_CTRL_GET_INFO 0x01010000
#define MR_DCMD_LD_GET_LIST 0x03010000
@@ -221,6 +223,7 @@ enum MFI_STAT {
MFI_STAT_RESERVATION_IN_PROGRESS = 0x36,
MFI_STAT_I2C_ERRORS_DETECTED = 0x37,
MFI_STAT_PCI_ERRORS_DETECTED = 0x38,
+ MFI_STAT_CONFIG_SEQ_MISMATCH = 0x67,
MFI_STAT_INVALID_STATUS = 0xFF
};
@@ -716,7 +719,7 @@ struct megasas_ctrl_info {
#define MEGASAS_DEFAULT_INIT_ID -1
#define MEGASAS_MAX_LUN 8
#define MEGASAS_MAX_LD 64
-#define MEGASAS_DEFAULT_CMD_PER_LUN 128
+#define MEGASAS_DEFAULT_CMD_PER_LUN 256
#define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \
MEGASAS_MAX_DEV_PER_CHANNEL)
#define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \
@@ -755,6 +758,7 @@ struct megasas_ctrl_info {
#define MEGASAS_INT_CMDS 32
#define MEGASAS_SKINNY_INT_CMDS 5
+#define MEGASAS_MAX_MSIX_QUEUES 16
/*
* FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
* SGLs based on the size of dma_addr_t
@@ -1276,6 +1280,11 @@ struct megasas_aen_event {
struct megasas_instance *instance;
};
+struct megasas_irq_context {
+ struct megasas_instance *instance;
+ u32 MSIxIndex;
+};
+
struct megasas_instance {
u32 *producer;
@@ -1286,7 +1295,6 @@ struct megasas_instance {
u32 *reply_queue;
dma_addr_t reply_queue_h;
- unsigned long base_addr;
struct megasas_register_set __iomem *reg_set;
struct megasas_pd_list pd_list[MEGASAS_MAX_PD];
@@ -1349,8 +1357,9 @@ struct megasas_instance {
/* Ptr to hba specific information */
void *ctrl_context;
- u8 msi_flag;
- struct msix_entry msixentry;
+ unsigned int msix_vectors;
+ struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES];
+ struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
u64 map_id;
struct megasas_cmd *map_update_cmd;
unsigned long bar;
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 5eac650..e45c865 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FILE: megaraid_sas_base.c
- * Version : v00.00.05.38-rc1
+ * Version : v00.00.06.12-rc1
*
* Authors: LSI Corporation
* Sreenivas Bagalkote
@@ -54,6 +54,7 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
#include "megaraid_sas_fusion.h"
#include "megaraid_sas.h"
@@ -83,7 +84,7 @@ MODULE_VERSION(MEGASAS_VERSION);
MODULE_AUTHOR("megaraidlinux@lsi.com");
MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
-int megasas_transition_to_ready(struct megasas_instance *instance);
+int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
static int megasas_get_pd_list(struct megasas_instance *instance);
static int megasas_issue_init_mfi(struct megasas_instance *instance);
static int megasas_register_aen(struct megasas_instance *instance,
@@ -113,6 +114,8 @@ static struct pci_device_id megasas_pci_table[] = {
/* xscale IOP */
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)},
/* Fusion */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INVADER)},
+ /* Invader */
{}
};
@@ -212,6 +215,10 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
cmd->scmd = NULL;
cmd->frame_count = 0;
+ if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
+ (reset_devices))
+ cmd->frame->hdr.cmd = MFI_CMD_INVALID;
list_add_tail(&cmd->list, &instance->cmd_pool);
spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
@@ -1582,7 +1589,8 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
{
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) {
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
} else {
writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
@@ -1955,7 +1963,8 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
/*
* First wait for all commands to complete
*/
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
ret = megasas_reset_fusion(scmd->device->host);
else
ret = megasas_generic_reset(scmd);
@@ -2056,6 +2065,20 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
}
}
+static int megasas_change_queue_depth(struct scsi_device *sdev,
+ int queue_depth, int reason)
+{
+ if (reason != SCSI_QDEPTH_DEFAULT)
+ return -EOPNOTSUPP;
+
+ if (queue_depth > sdev->host->can_queue)
+ queue_depth = sdev->host->can_queue;
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev),
+ queue_depth);
+
+ return queue_depth;
+}
+
/*
* Scsi host template for megaraid_sas driver
*/
@@ -2073,6 +2096,7 @@ static struct scsi_host_template megasas_template = {
.eh_timed_out = megasas_reset_timer,
.bios_param = megasas_bios_param,
.use_clustering = ENABLE_CLUSTERING,
+ .change_queue_depth = megasas_change_queue_depth,
};
/**
@@ -2144,7 +2168,16 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
cmd->scmd->SCp.ptr = NULL;
switch (hdr->cmd) {
-
+ case MFI_CMD_INVALID:
+ /* Some older 1068 controller FW may keep a pended
+ MR_DCMD_CTRL_EVENT_GET_INFO left over from the main kernel
+ when booting the kdump kernel. Ignore this command to
+ prevent a kernel panic on shutdown of the kdump kernel. */
+ printk(KERN_WARNING "megaraid_sas: MFI_CMD_INVALID command "
+ "completed.\n");
+ printk(KERN_WARNING "megaraid_sas: If you have a controller "
+ "other than PERC5, please upgrade your firmware.\n");
+ break;
case MFI_CMD_PD_SCSI_IO:
case MFI_CMD_LD_SCSI_IO:
@@ -2460,7 +2493,7 @@ process_fw_state_change_wq(struct work_struct *work)
msleep(1000);
}
- if (megasas_transition_to_ready(instance)) {
+ if (megasas_transition_to_ready(instance, 1)) {
printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
megaraid_sas_kill_hba(instance);
@@ -2515,7 +2548,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
instance->reg_set)
) == 0) {
/* Hardware may not set outbound_intr_status in MSI-X mode */
- if (!instance->msi_flag)
+ if (!instance->msix_vectors)
return IRQ_NONE;
}
@@ -2573,16 +2606,14 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
*/
static irqreturn_t megasas_isr(int irq, void *devp)
{
- struct megasas_instance *instance;
+ struct megasas_irq_context *irq_context = devp;
+ struct megasas_instance *instance = irq_context->instance;
unsigned long flags;
irqreturn_t rc;
- if (atomic_read(
- &(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
+ if (atomic_read(&instance->fw_reset_no_pci_access))
return IRQ_HANDLED;
- instance = (struct megasas_instance *)devp;
-
spin_lock_irqsave(&instance->hba_lock, flags);
rc = megasas_deplete_reply_queue(instance, DID_OK);
spin_unlock_irqrestore(&instance->hba_lock, flags);
@@ -2600,7 +2631,7 @@ static irqreturn_t megasas_isr(int irq, void *devp)
* has to wait for the ready state.
*/
int
-megasas_transition_to_ready(struct megasas_instance* instance)
+megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
{
int i;
u8 max_wait;
@@ -2622,11 +2653,13 @@ megasas_transition_to_ready(struct megasas_instance* instance)
switch (fw_state) {
case MFI_STATE_FAULT:
-
printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
- max_wait = MEGASAS_RESET_WAIT_TIME;
- cur_state = MFI_STATE_FAULT;
- break;
+ if (ocr) {
+ max_wait = MEGASAS_RESET_WAIT_TIME;
+ cur_state = MFI_STATE_FAULT;
+ break;
+ } else
+ return -ENODEV;
case MFI_STATE_WAIT_HANDSHAKE:
/*
@@ -2637,7 +2670,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION)) {
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)) {
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
@@ -2657,7 +2692,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION)) {
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)) {
writel(MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
} else
@@ -2678,11 +2715,15 @@ megasas_transition_to_ready(struct megasas_instance* instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device
- == PCI_DEVICE_ID_LSI_FUSION)) {
+ == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device
+ == PCI_DEVICE_ID_LSI_INVADER)) {
writel(MFI_RESET_FLAGS,
&instance->reg_set->doorbell);
- if (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) {
+ if ((instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)) {
for (i = 0; i < (10 * 1000); i += 20) {
if (readl(
&instance->
@@ -2905,6 +2946,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
memset(cmd->frame, 0, total_sz);
cmd->frame->io.context = cmd->index;
cmd->frame->io.pad_0 = 0;
+ if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
+ (reset_devices))
+ cmd->frame->hdr.cmd = MFI_CMD_INVALID;
}
return 0;
@@ -3454,21 +3499,23 @@ static int megasas_init_fw(struct megasas_instance *instance)
u32 max_sectors_1;
u32 max_sectors_2;
u32 tmp_sectors, msix_enable;
+ resource_size_t base_addr;
struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info;
unsigned long bar_list;
+ int i;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
- instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
if (pci_request_selected_regions(instance->pdev, instance->bar,
"megasas: LSI")) {
printk(KERN_DEBUG "megasas: IO memory region busy!\n");
return -EBUSY;
}
- instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+ base_addr = pci_resource_start(instance->pdev, instance->bar);
+ instance->reg_set = ioremap_nocache(base_addr, 8192);
if (!instance->reg_set) {
printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
@@ -3479,6 +3526,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
instance->instancet = &megasas_instance_template_fusion;
break;
case PCI_DEVICE_ID_LSI_SAS1078R:
@@ -3500,18 +3548,52 @@ static int megasas_init_fw(struct megasas_instance *instance)
break;
}
- /*
- * We expect the FW state to be READY
- */
- if (megasas_transition_to_ready(instance))
- goto fail_ready_state;
+ if (megasas_transition_to_ready(instance, 0)) {
+ atomic_set(&instance->fw_reset_no_pci_access, 1);
+ instance->instancet->adp_reset
+ (instance, instance->reg_set);
+ atomic_set(&instance->fw_reset_no_pci_access, 0);
+ dev_info(&instance->pdev->dev,
+ "megasas: FW restarted successfully from %s!\n",
+ __func__);
+
+ /*waitting for about 30 second before retry*/
+ ssleep(30);
+
+ if (megasas_transition_to_ready(instance, 0))
+ goto fail_ready_state;
+ }
/* Check if MSI-X is supported while in ready state */
msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
0x4000000) >> 0x1a;
- if (msix_enable && !msix_disable &&
- !pci_enable_msix(instance->pdev, &instance->msixentry, 1))
- instance->msi_flag = 1;
+ if (msix_enable && !msix_disable) {
+ /* Check max MSI-X vectors */
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
+ instance->msix_vectors = (readl(&instance->reg_set->
+ outbound_scratch_pad_2
+ ) & 0x1F) + 1;
+ } else
+ instance->msix_vectors = 1;
+ /* Don't bother allocating more MSI-X vectors than cpus */
+ instance->msix_vectors = min(instance->msix_vectors,
+ (unsigned int)num_online_cpus());
+ for (i = 0; i < instance->msix_vectors; i++)
+ instance->msixentry[i].entry = i;
+ i = pci_enable_msix(instance->pdev, instance->msixentry,
+ instance->msix_vectors);
+ if (i >= 0) {
+ if (i) {
+ if (!pci_enable_msix(instance->pdev,
+ instance->msixentry, i))
+ instance->msix_vectors = i;
+ else
+ instance->msix_vectors = 0;
+ }
+ } else
+ instance->msix_vectors = 0;
+ }
/* Get operational params, sge flags, send init cmd to controller */
if (instance->instancet->init_adapter(instance))
@@ -3875,7 +3957,8 @@ static int megasas_io_attach(struct megasas_instance *instance)
host->max_cmd_len = 16;
/* Fusion only supports host reset */
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
host->hostt->eh_device_reset_handler = NULL;
host->hostt->eh_bus_reset_handler = NULL;
}
@@ -3925,7 +4008,7 @@ fail_set_dma_mask:
static int __devinit
megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- int rval, pos;
+ int rval, pos, i, j;
struct Scsi_Host *host;
struct megasas_instance *instance;
u16 control = 0;
@@ -3985,6 +4068,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
{
struct fusion_context *fusion;
@@ -4076,7 +4160,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->last_time = 0;
instance->disableOnlineCtrlReset = 1;
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
else
INIT_WORK(&instance->work_init, process_fw_state_change_wq);
@@ -4090,11 +4175,32 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/*
* Register IRQ
*/
- if (request_irq(instance->msi_flag ? instance->msixentry.vector :
- pdev->irq, instance->instancet->service_isr,
- IRQF_SHARED, "megasas", instance)) {
- printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
- goto fail_irq;
+ if (instance->msix_vectors) {
+ for (i = 0 ; i < instance->msix_vectors; i++) {
+ instance->irq_context[i].instance = instance;
+ instance->irq_context[i].MSIxIndex = i;
+ if (request_irq(instance->msixentry[i].vector,
+ instance->instancet->service_isr, 0,
+ "megasas",
+ &instance->irq_context[i])) {
+ printk(KERN_DEBUG "megasas: Failed to "
+ "register IRQ for vector %d.\n", i);
+ for (j = 0 ; j < i ; j++)
+ free_irq(
+ instance->msixentry[j].vector,
+ &instance->irq_context[j]);
+ goto fail_irq;
+ }
+ }
+ } else {
+ instance->irq_context[0].instance = instance;
+ instance->irq_context[0].MSIxIndex = 0;
+ if (request_irq(pdev->irq, instance->instancet->service_isr,
+ IRQF_SHARED, "megasas",
+ &instance->irq_context[0])) {
+ printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ goto fail_irq;
+ }
}
instance->instancet->enable_intr(instance->reg_set);
@@ -4138,15 +4244,20 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, NULL);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
fail_irq:
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
megasas_release_fusion(instance);
else
megasas_release_mfi(instance);
fail_init_mfi:
- if (instance->msi_flag)
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
fail_alloc_dma_buf:
if (instance->evt_detail)
@@ -4262,6 +4373,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *host;
struct megasas_instance *instance;
+ int i;
instance = pci_get_drvdata(pdev);
host = instance->host;
@@ -4285,9 +4397,14 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
pci_set_drvdata(instance->pdev, instance);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
- if (instance->msi_flag)
+
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
pci_save_state(pdev);
@@ -4305,7 +4422,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
static int
megasas_resume(struct pci_dev *pdev)
{
- int rval;
+ int rval, i, j;
struct Scsi_Host *host;
struct megasas_instance *instance;
@@ -4339,15 +4456,17 @@ megasas_resume(struct pci_dev *pdev)
/*
* We expect the FW state to be READY
*/
- if (megasas_transition_to_ready(instance))
+ if (megasas_transition_to_ready(instance, 0))
goto fail_ready_state;
/* Now re-enable MSI-X */
- if (instance->msi_flag)
- pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+ if (instance->msix_vectors)
+ pci_enable_msix(instance->pdev, instance->msixentry,
+ instance->msix_vectors);
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
{
megasas_reset_reply_desc(instance);
if (megasas_ioc_init_fusion(instance)) {
@@ -4373,11 +4492,32 @@ megasas_resume(struct pci_dev *pdev)
/*
* Register IRQ
*/
- if (request_irq(instance->msi_flag ? instance->msixentry.vector :
- pdev->irq, instance->instancet->service_isr,
- IRQF_SHARED, "megasas", instance)) {
- printk(KERN_ERR "megasas: Failed to register IRQ\n");
- goto fail_irq;
+ if (instance->msix_vectors) {
+ for (i = 0 ; i < instance->msix_vectors; i++) {
+ instance->irq_context[i].instance = instance;
+ instance->irq_context[i].MSIxIndex = i;
+ if (request_irq(instance->msixentry[i].vector,
+ instance->instancet->service_isr, 0,
+ "megasas",
+ &instance->irq_context[i])) {
+ printk(KERN_DEBUG "megasas: Failed to "
+ "register IRQ for vector %d.\n", i);
+ for (j = 0 ; j < i ; j++)
+ free_irq(
+ instance->msixentry[j].vector,
+ &instance->irq_context[j]);
+ goto fail_irq;
+ }
+ }
+ } else {
+ instance->irq_context[0].instance = instance;
+ instance->irq_context[0].MSIxIndex = 0;
+ if (request_irq(pdev->irq, instance->instancet->service_isr,
+ IRQF_SHARED, "megasas",
+ &instance->irq_context[0])) {
+ printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ goto fail_irq;
+ }
}
instance->instancet->enable_intr(instance->reg_set);
@@ -4474,13 +4614,18 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
- if (instance->msi_flag)
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
megasas_release_fusion(instance);
for (i = 0; i < 2 ; i++)
if (fusion->ld_map[i])
@@ -4521,14 +4666,20 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
*/
static void megasas_shutdown(struct pci_dev *pdev)
{
+ int i;
struct megasas_instance *instance = pci_get_drvdata(pdev);
+
instance->unload = 1;
megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
- if (instance->msi_flag)
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 8fe3a45..5255dd6 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -52,6 +52,7 @@
#include <scsi/scsi_host.h>
#include "megaraid_sas_fusion.h"
+#include "megaraid_sas.h"
#include <asm/div64.h>
#define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
@@ -226,8 +227,9 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
* span - Span number
* block - Absolute Block number in the physical disk
*/
-u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
- u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context,
+u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
+ u16 stripRef, u64 *pdBlock, u16 *pDevHandle,
+ struct RAID_CONTEXT *pRAID_Context,
struct MR_FW_RAID_MAP_ALL *map)
{
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
@@ -279,7 +281,8 @@ u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
*pDevHandle = MR_PdDevHandleGet(pd, map);
else {
*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
- if (raid->level >= 5)
+ if ((raid->level >= 5) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
/* Get alternate Pd. */
@@ -288,7 +291,6 @@ u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
/* Get dev handle from Pd */
*pDevHandle = MR_PdDevHandleGet(pd, map);
}
- retval = FALSE;
}
*pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
@@ -307,7 +309,8 @@ u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
* This function will return 0 if region lock was acquired OR return num strips
*/
u8
-MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+MR_BuildRaidContext(struct megasas_instance *instance,
+ struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT *pRAID_Context,
struct MR_FW_RAID_MAP_ALL *map)
{
@@ -395,8 +398,12 @@ MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
}
pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
- pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ :
- raid->regTypeReqOnWrite;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
+ pRAID_Context->regLockFlags = (isRead) ?
+ raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
+ else
+ pRAID_Context->regLockFlags = (isRead) ?
+ REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
pRAID_Context->VirtualDiskTgtId = raid->targetId;
pRAID_Context->regLockRowLBA = regStart;
pRAID_Context->regLockLength = regSize;
@@ -405,7 +412,8 @@ MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
/*Get Phy Params only if FP capable, or else leave it to MR firmware
to do the calculation.*/
if (io_info->fpOkForIo) {
- retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe,
+ retval = MR_GetPhyParams(instance, ld, start_strip,
+ ref_in_start_stripe,
&io_info->pdBlock,
&io_info->devHandle, pRAID_Context,
map);
@@ -416,7 +424,8 @@ MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
} else if (isRead) {
uint stripIdx;
for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
- if (!MR_GetPhyParams(ld, start_strip + stripIdx,
+ if (!MR_GetPhyParams(instance, ld,
+ start_strip + stripIdx,
ref_in_start_stripe,
&io_info->pdBlock,
&io_info->devHandle,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index f13e7ab..3e0f71c 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -74,7 +74,8 @@ megasas_issue_polled(struct megasas_instance *instance,
struct megasas_cmd *cmd);
u8
-MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+MR_BuildRaidContext(struct megasas_instance *instance,
+ struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT *pRAID_Context,
struct MR_FW_RAID_MAP_ALL *map);
u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
@@ -89,7 +90,7 @@ u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo);
u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *in_info);
-int megasas_transition_to_ready(struct megasas_instance *instance);
+int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
void megaraid_sas_kill_hba(struct megasas_instance *instance);
extern u32 megasas_dbg_lvl;
@@ -101,6 +102,10 @@ extern u32 megasas_dbg_lvl;
void
megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
{
+ /* For Thunderbolt/Invader also clear intr on enable */
+ writel(~0, &regs->outbound_intr_status);
+ readl(&regs->outbound_intr_status);
+
writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */
@@ -139,11 +144,6 @@ megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
return 0;
- /*
- * dummy read to flush PCI
- */
- readl(&regs->outbound_intr_status);
-
return 1;
}
@@ -385,7 +385,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
int
megasas_alloc_cmds_fusion(struct megasas_instance *instance)
{
- int i, j;
+ int i, j, count;
u32 max_cmd, io_frames_sz;
struct fusion_context *fusion;
struct megasas_cmd_fusion *cmd;
@@ -409,9 +409,10 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
goto fail_req_desc;
}
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
fusion->reply_frames_desc_pool =
pci_pool_create("reply_frames pool", instance->pdev,
- fusion->reply_alloc_sz, 16, 0);
+ fusion->reply_alloc_sz * count, 16, 0);
if (!fusion->reply_frames_desc_pool) {
printk(KERN_ERR "megasas; Could not allocate memory for "
@@ -430,7 +431,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
}
reply_desc = fusion->reply_frames_desc;
- for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++)
+ for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
reply_desc->Words = ULLONG_MAX;
io_frames_sz = fusion->io_frames_alloc_sz;
@@ -590,7 +591,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
struct megasas_init_frame *init_frame;
struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
dma_addr_t ioc_init_handle;
- u32 context;
struct megasas_cmd *cmd;
u8 ret;
struct fusion_context *fusion;
@@ -634,14 +634,13 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
fusion->reply_frames_desc_phys;
IOCInitMessage->SystemRequestFrameBaseAddress =
fusion->io_request_frames_phys;
-
+ /* Set to 0 for none or 1 MSI-X vectors */
+ IOCInitMessage->HostMSIxVectors = (instance->msix_vectors > 0 ?
+ instance->msix_vectors : 0);
init_frame = (struct megasas_init_frame *)cmd->frame;
memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
frame_hdr = &cmd->frame->hdr;
- context = init_frame->context;
- init_frame->context = context;
-
frame_hdr->cmd_status = 0xFF;
frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
@@ -881,7 +880,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
struct megasas_register_set __iomem *reg_set;
struct fusion_context *fusion;
u32 max_cmd;
- int i = 0;
+ int i = 0, count;
fusion = instance->ctrl_context;
@@ -933,7 +932,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
sizeof(union MPI2_SGE_IO_UNION))/16;
- fusion->last_reply_idx = 0;
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+ for (i = 0 ; i < count; i++)
+ fusion->last_reply_idx[i] = 0;
/*
* Allocate memory for descriptors
@@ -1043,7 +1044,9 @@ map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
case MFI_STAT_DEVICE_NOT_FOUND:
cmd->scmd->result = DID_BAD_TARGET << 16;
break;
-
+ case MFI_STAT_CONFIG_SEQ_MISMATCH:
+ cmd->scmd->result = DID_IMM_RETRY << 16;
+ break;
default:
printk(KERN_DEBUG "megasas: FW status %#x\n", status);
cmd->scmd->result = DID_ERROR << 16;
@@ -1066,14 +1069,17 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
struct megasas_cmd_fusion *cmd)
{
- int i, sg_processed;
- int sge_count, sge_idx;
+ int i, sg_processed, sge_count;
struct scatterlist *os_sgl;
struct fusion_context *fusion;
fusion = instance->ctrl_context;
- cmd->io_request->ChainOffset = 0;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
+ sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
+ sgl_ptr_end->Flags = 0;
+ }
sge_count = scsi_dma_map(scp);
@@ -1082,16 +1088,14 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
if (sge_count > instance->max_num_sge || !sge_count)
return sge_count;
- if (sge_count > fusion->max_sge_in_main_msg) {
- /* One element to store the chain info */
- sge_idx = fusion->max_sge_in_main_msg - 1;
- } else
- sge_idx = sge_count;
-
scsi_for_each_sg(scp, os_sgl, sge_count, i) {
sgl_ptr->Length = sg_dma_len(os_sgl);
sgl_ptr->Address = sg_dma_address(os_sgl);
sgl_ptr->Flags = 0;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if (i == sge_count - 1)
+ sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
+ }
sgl_ptr++;
sg_processed = i + 1;
@@ -1100,13 +1104,30 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
(sge_count > fusion->max_sge_in_main_msg)) {
struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
- cmd->io_request->ChainOffset =
- fusion->chain_offset_io_request;
+ if (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER) {
+ if ((cmd->io_request->IoFlags &
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
+ cmd->io_request->ChainOffset =
+ fusion->
+ chain_offset_io_request;
+ else
+ cmd->io_request->ChainOffset = 0;
+ } else
+ cmd->io_request->ChainOffset =
+ fusion->chain_offset_io_request;
+
sg_chain = sgl_ptr;
/* Prepare chain element */
sg_chain->NextChainOffset = 0;
- sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
- MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+ if (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)
+ sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
+ else
+ sg_chain->Flags =
+ (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+ MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
sg_chain->Length = (sizeof(union MPI2_SGE_IO_UNION)
*(sge_count - sg_processed));
sg_chain->Address = cmd->sg_frame_phys_addr;
@@ -1399,11 +1420,18 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
io_request->RaidContext.regLockFlags = 0;
fp_possible = 0;
} else {
- if (MR_BuildRaidContext(&io_info, &io_request->RaidContext,
+ if (MR_BuildRaidContext(instance, &io_info,
+ &io_request->RaidContext,
local_map_ptr))
fp_possible = io_info.fpOkForIo;
}
+ /* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU
+ id by default, not CPU group id, otherwise all MSI-X queues won't
+ be utilized */
+ cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
+ raw_smp_processor_id() % instance->msix_vectors : 0;
+
if (fp_possible) {
megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
local_map_ptr, start_lba_lo);
@@ -1412,6 +1440,20 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
cmd->request_desc->SCSIIO.RequestFlags =
(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if (io_request->RaidContext.regLockFlags ==
+ REGION_TYPE_UNUSED)
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.Type = MPI2_TYPE_CUDA;
+ io_request->RaidContext.nseg = 0x1;
+ io_request->IoFlags |=
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
+ io_request->RaidContext.regLockFlags |=
+ (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
+ MR_RL_FLAGS_SEQ_NUM_ENABLE);
+ }
if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
(io_info.isRead)) {
io_info.devHandle =
@@ -1426,11 +1468,23 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
} else {
io_request->RaidContext.timeoutValue =
local_map_ptr->raidMap.fpPdIoTimeoutSec;
- io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
- io_request->DevHandle = device_id;
cmd->request_desc->SCSIIO.RequestFlags =
(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if (io_request->RaidContext.regLockFlags ==
+ REGION_TYPE_UNUSED)
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.Type = MPI2_TYPE_CUDA;
+ io_request->RaidContext.regLockFlags |=
+ (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
+ MR_RL_FLAGS_SEQ_NUM_ENABLE);
+ io_request->RaidContext.nseg = 0x1;
+ }
+ io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
} /* Not FP */
}
@@ -1513,8 +1567,10 @@ megasas_build_io_fusion(struct megasas_instance *instance,
io_request->EEDPFlags = 0;
io_request->Control = 0;
io_request->EEDPBlockSize = 0;
- io_request->IoFlags = 0;
+ io_request->ChainOffset = 0;
io_request->RaidContext.RAIDFlags = 0;
+ io_request->RaidContext.Type = 0;
+ io_request->RaidContext.nseg = 0;
memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
/*
@@ -1612,7 +1668,6 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
req_desc->Words = 0;
cmd->request_desc = req_desc;
- cmd->request_desc->Words = 0;
if (megasas_build_io_fusion(instance, scmd, cmd)) {
megasas_return_cmd_fusion(instance, cmd);
@@ -1647,7 +1702,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
* Completes all commands that is in reply descriptor queue
*/
int
-complete_cmd_fusion(struct megasas_instance *instance)
+complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
{
union MPI2_REPLY_DESCRIPTORS_UNION *desc;
struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
@@ -1667,7 +1722,9 @@ complete_cmd_fusion(struct megasas_instance *instance)
return IRQ_HANDLED;
desc = fusion->reply_frames_desc;
- desc += fusion->last_reply_idx;
+ desc += ((MSIxIndex * fusion->reply_alloc_sz)/
+ sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)) +
+ fusion->last_reply_idx[MSIxIndex];
reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
@@ -1740,16 +1797,19 @@ complete_cmd_fusion(struct megasas_instance *instance)
break;
}
- fusion->last_reply_idx++;
- if (fusion->last_reply_idx >= fusion->reply_q_depth)
- fusion->last_reply_idx = 0;
+ fusion->last_reply_idx[MSIxIndex]++;
+ if (fusion->last_reply_idx[MSIxIndex] >=
+ fusion->reply_q_depth)
+ fusion->last_reply_idx[MSIxIndex] = 0;
desc->Words = ULLONG_MAX;
num_completed++;
/* Get the next reply descriptor */
- if (!fusion->last_reply_idx)
- desc = fusion->reply_frames_desc;
+ if (!fusion->last_reply_idx[MSIxIndex])
+ desc = fusion->reply_frames_desc +
+ ((MSIxIndex * fusion->reply_alloc_sz)/
+ sizeof(union MPI2_REPLY_DESCRIPTORS_UNION));
else
desc++;
@@ -1769,7 +1829,7 @@ complete_cmd_fusion(struct megasas_instance *instance)
return IRQ_NONE;
wmb();
- writel(fusion->last_reply_idx,
+ writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex],
&instance->reg_set->reply_post_host_index);
megasas_check_and_restore_queue_depth(instance);
return IRQ_HANDLED;
@@ -1787,6 +1847,9 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
struct megasas_instance *instance =
(struct megasas_instance *)instance_addr;
unsigned long flags;
+ u32 count, MSIxIndex;
+
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
/* If we have already declared adapter dead, donot complete cmds */
spin_lock_irqsave(&instance->hba_lock, flags);
@@ -1797,7 +1860,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
spin_unlock_irqrestore(&instance->hba_lock, flags);
spin_lock_irqsave(&instance->completion_lock, flags);
- complete_cmd_fusion(instance);
+ for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
+ complete_cmd_fusion(instance, MSIxIndex);
spin_unlock_irqrestore(&instance->completion_lock, flags);
}
@@ -1806,20 +1870,24 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
*/
irqreturn_t megasas_isr_fusion(int irq, void *devp)
{
- struct megasas_instance *instance = (struct megasas_instance *)devp;
+ struct megasas_irq_context *irq_context = devp;
+ struct megasas_instance *instance = irq_context->instance;
u32 mfiStatus, fw_state;
- if (!instance->msi_flag) {
+ if (!instance->msix_vectors) {
mfiStatus = instance->instancet->clear_intr(instance->reg_set);
if (!mfiStatus)
return IRQ_NONE;
}
/* If we are resetting, bail */
- if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags))
+ if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) {
+ instance->instancet->clear_intr(instance->reg_set);
return IRQ_HANDLED;
+ }
- if (!complete_cmd_fusion(instance)) {
+ if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) {
+ instance->instancet->clear_intr(instance->reg_set);
/* If we didn't complete any commands, check for FW fault */
fw_state = instance->instancet->read_fw_status_reg(
instance->reg_set) & MFI_STATE_MASK;
@@ -1866,6 +1934,14 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
fusion = instance->ctrl_context;
io_req = cmd->io_request;
+
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
+ (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
+ sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
+ sgl_ptr_end->Flags = 0;
+ }
+
mpi25_ieee_chain =
(struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
@@ -1928,15 +2004,12 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance,
struct megasas_cmd *cmd)
{
union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
- union desc_value d_val;
req_desc = build_mpt_cmd(instance, cmd);
if (!req_desc) {
printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n");
return;
}
- d_val.word = req_desc->Words;
-
instance->instancet->fire_cmd(instance, req_desc->u.low,
req_desc->u.high, instance->reg_set);
}
@@ -2029,14 +2102,16 @@ out:
void megasas_reset_reply_desc(struct megasas_instance *instance)
{
- int i;
+ int i, count;
struct fusion_context *fusion;
union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
fusion = instance->ctrl_context;
- fusion->last_reply_idx = 0;
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+ for (i = 0 ; i < count ; i++)
+ fusion->last_reply_idx[i] = 0;
reply_desc = fusion->reply_frames_desc;
- for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++)
+ for (i = 0 ; i < fusion->reply_q_depth * count; i++, reply_desc++)
reply_desc->Words = ULLONG_MAX;
}
@@ -2057,8 +2132,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
"returning FAILED.\n");
- retval = FAILED;
- goto out;
+ return FAILED;
}
mutex_lock(&instance->reset_mutex);
@@ -2173,7 +2247,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
}
/* Wait for FW to become ready */
- if (megasas_transition_to_ready(instance)) {
+ if (megasas_transition_to_ready(instance, 1)) {
printk(KERN_WARNING "megaraid_sas: Failed to "
"transition controller to ready.\n");
continue;
@@ -2186,6 +2260,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
continue;
}
+ clear_bit(MEGASAS_FUSION_IN_RESET,
+ &instance->reset_flags);
instance->instancet->enable_intr(instance->reg_set);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
@@ -2247,6 +2323,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
megaraid_sas_kill_hba(instance);
retval = FAILED;
} else {
+ clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
instance->instancet->enable_intr(instance->reg_set);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index 82b577a..088c9f9 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -43,6 +43,15 @@
#define HOST_DIAG_WRITE_ENABLE 0x80
#define HOST_DIAG_RESET_ADAPTER 0x4
#define MEGASAS_FUSION_MAX_RESET_TRIES 3
+#define MAX_MSIX_QUEUES_FUSION 16
+
+/* Invader defines */
+#define MPI2_TYPE_CUDA 0x2
+#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH 0x4000
+#define MR_RL_FLAGS_GRANT_DESTINATION_CPU0 0x00
+#define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10
+#define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80
+#define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8
/* T10 PI defines */
#define MR_PROT_INFO_TYPE_CONTROLLER 0x8
@@ -70,7 +79,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
*/
#define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7
#define MEGASAS_REQ_DESCRIPT_FLAGS_MFA 0x1
-
+#define MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK 0x2
#define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1
#define MEGASAS_FP_CMD_LEN 16
@@ -82,7 +91,9 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
*/
struct RAID_CONTEXT {
- u16 resvd0;
+ u8 Type:4;
+ u8 nseg:4;
+ u8 resvd0;
u16 timeoutValue;
u8 regLockFlags;
u8 resvd1;
@@ -527,7 +538,7 @@ struct MR_LD_RAID {
u8 ldState;
u8 regTypeReqOnWrite;
u8 modFactor;
- u8 reserved2[1];
+ u8 regTypeReqOnRead;
u16 seqNum;
struct {
@@ -663,7 +674,7 @@ struct fusion_context {
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
struct dma_pool *reply_frames_desc_pool;
- u16 last_reply_idx;
+ u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION];
u32 reply_q_depth;
u32 request_alloc_sz;
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index a3e6038..8dc1b32 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2010 LSI Corporation.
+ * Copyright (c) 2000-2011 LSI Corporation.
*
*
* Name: mpi2.h
@@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.17
+ * mpi2.h Version: 02.00.20
*
* Version History
* ---------------
@@ -64,6 +64,11 @@
* 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT.
* Added alternative defines for the SGE Direction bit.
* 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
+ * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added MPI2_FUNCTION_SEND_HOST_MESSAGE.
+ * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@@ -89,7 +94,7 @@
#define MPI2_VERSION_02_00 (0x0200)
/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x11)
+#define MPI2_HEADER_VERSION_UNIT (0x14)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -513,6 +518,8 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F)
/* Power Management Control */
#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30)
+/* Send Host Message */
+#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31)
/* beginning of product-specific range */
#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0)
/* end of product-specific range */
@@ -1060,10 +1067,14 @@ typedef struct _MPI2_IEEE_SGE_UNION
#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
+ /* IEEE Simple Element only */
#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
+ /* IEEE Simple Element only */
#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
-
+ /* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR (0x03)
+ /* IEEE Chain Element only */
/****************************************************************************
* IEEE SGE operation Macros
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index f5b9c76..cfd95b4 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2010 LSI Corporation.
+ * Copyright (c) 2000-2011 LSI Corporation.
*
*
* Name: mpi2_cnfg.h
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.16
+ * mpi2_cnfg.h Version: 02.00.19
*
* Version History
* ---------------
@@ -127,6 +127,19 @@
* Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
* 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing)
* defines.
+ * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to
+ * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ * the Pinout field.
+ * Added BoardTemperature and BoardTemperatureUnits fields
+ * to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
+ * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST.
+ * Added IO Unit Page 8, IO Unit Page 9,
+ * and IO Unit Page 10.
+ * Added SASNotifyPrimitiveMasks field to
+ * MPI2_CONFIG_PAGE_IOC_7.
+ * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec).
* --------------------------------------------------------------------------
*/
@@ -210,6 +223,7 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
+#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
/*****************************************************************************
@@ -321,7 +335,9 @@ typedef struct _MPI2_CONFIG_REQUEST
U8 VP_ID; /* 0x08 */
U8 VF_ID; /* 0x09 */
U16 Reserved1; /* 0x0A */
- U32 Reserved2; /* 0x0C */
+ U8 Reserved2; /* 0x0C */
+ U8 ProxyVF_ID; /* 0x0D */
+ U16 Reserved4; /* 0x0E */
U32 Reserved3; /* 0x10 */
MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
U32 PageAddress; /* 0x18 */
@@ -612,23 +628,31 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
U32 Pinout; /* 0x00 */
U8 Connector[16]; /* 0x04 */
U8 Location; /* 0x14 */
- U8 Reserved1; /* 0x15 */
+ U8 ReceptacleID; /* 0x15 */
U16 Slot; /* 0x16 */
U32 Reserved2; /* 0x18 */
} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
/* defines for the Pinout field */
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100)
-#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x00000002)
-#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001)
+#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00)
+#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8)
+
+#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF)
+#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00)
+#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02)
+#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04)
+#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08)
+#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
+#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
/* defines for the Location field */
#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
@@ -662,7 +686,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7
MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
-#define MPI2_MANUFACTURING7_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
/* defines for the Flags field */
#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
@@ -849,11 +873,13 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
U16 IOCTemperature; /* 0x10 */
U8 IOCTemperatureUnits; /* 0x12 */
U8 IOCSpeed; /* 0x13 */
- U32 Reserved3; /* 0x14 */
+ U16 BoardTemperature; /* 0x14 */
+ U8 BoardTemperatureUnits; /* 0x16 */
+ U8 Reserved3; /* 0x17 */
} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
-#define MPI2_IOUNITPAGE7_PAGEVERSION (0x01)
+#define MPI2_IOUNITPAGE7_PAGEVERSION (0x02)
/* defines for IO Unit Page 7 PCIeWidth field */
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01)
@@ -881,7 +907,6 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008)
#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004)
-
/* defines for IO Unit Page 7 IOCTemperatureUnits field */
#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00)
#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01)
@@ -893,6 +918,125 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04)
#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08)
+/* defines for IO Unit Page 7 BoardTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02)
+
+/* IO Unit Page 8 */
+
+#define MPI2_IOUNIT8_NUM_THRESHOLDS (4)
+
+typedef struct _MPI2_IOUNIT8_SENSOR {
+ U16 Flags; /* 0x00 */
+ U16 Reserved1; /* 0x02 */
+ U16
+ Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /* 0x04 */
+ U32 Reserved2; /* 0x0C */
+ U32 Reserved3; /* 0x10 */
+ U32 Reserved4; /* 0x14 */
+} MPI2_IOUNIT8_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT8_SENSOR,
+Mpi2IOUnit8Sensor_t, MPI2_POINTER pMpi2IOUnit8Sensor_t;
+
+/* defines for IO Unit Page 8 Sensor Flags field */
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumSensors at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
+#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Reserved2; /* 0x08 */
+ U8 NumSensors; /* 0x0C */
+ U8 PollingInterval; /* 0x0D */
+ U16 Reserved3; /* 0x0E */
+ MPI2_IOUNIT8_SENSOR
+ Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/* 0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
+Mpi2IOUnitPage8_t, MPI2_POINTER pMpi2IOUnitPage8_t;
+
+#define MPI2_IOUNITPAGE8_PAGEVERSION (0x00)
+
+
+/* IO Unit Page 9 */
+
+typedef struct _MPI2_IOUNIT9_SENSOR {
+ U16 CurrentTemperature; /* 0x00 */
+ U16 Reserved1; /* 0x02 */
+ U8 Flags; /* 0x04 */
+ U8 Reserved2; /* 0x05 */
+ U16 Reserved3; /* 0x06 */
+ U32 Reserved4; /* 0x08 */
+ U32 Reserved5; /* 0x0C */
+} MPI2_IOUNIT9_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT9_SENSOR,
+Mpi2IOUnit9Sensor_t, MPI2_POINTER pMpi2IOUnit9Sensor_t;
+
+/* defines for IO Unit Page 9 Sensor Flags field */
+#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumSensors at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
+#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Reserved2; /* 0x08 */
+ U8 NumSensors; /* 0x0C */
+ U8 Reserved4; /* 0x0D */
+ U16 Reserved3; /* 0x0E */
+ MPI2_IOUNIT9_SENSOR
+ Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/* 0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_9, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
+Mpi2IOUnitPage9_t, MPI2_POINTER pMpi2IOUnitPage9_t;
+
+#define MPI2_IOUNITPAGE9_PAGEVERSION (0x00)
+
+
+/* IO Unit Page 10 */
+
+typedef struct _MPI2_IOUNIT10_FUNCTION {
+ U8 CreditPercent; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U16 Reserved2; /* 0x02 */
+} MPI2_IOUNIT10_FUNCTION, MPI2_POINTER PTR_MPI2_IOUNIT10_FUNCTION,
+Mpi2IOUnit10Function_t, MPI2_POINTER pMpi2IOUnit10Function_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumFunctions at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
+#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 NumFunctions; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ U32 Reserved3; /* 0x08 */
+ U32 Reserved4; /* 0x0C */
+ MPI2_IOUNIT10_FUNCTION
+ Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/* 0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_10, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
+Mpi2IOUnitPage10_t, MPI2_POINTER pMpi2IOUnitPage10_t;
+
+#define MPI2_IOUNITPAGE10_PAGEVERSION (0x01)
+
/****************************************************************************
@@ -1000,12 +1144,12 @@ typedef struct _MPI2_CONFIG_PAGE_IOC_7
U32 Reserved1; /* 0x04 */
U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
U16 SASBroadcastPrimitiveMasks; /* 0x18 */
- U16 Reserved2; /* 0x1A */
+ U16 SASNotifyPrimitiveMasks; /* 0x1A */
U32 Reserved3; /* 0x1C */
} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
-#define MPI2_IOCPAGE7_PAGEVERSION (0x01)
+#define MPI2_IOCPAGE7_PAGEVERSION (0x02)
/* IOC Page 8 */
@@ -2048,16 +2192,16 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00)
/* defines for PowerManagementCapabilities field */
-#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x000001000)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x000000800)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x000000400)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x000000200)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x000000100)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x000000010)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x000000008)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x000000004)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x000000002)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x000000001)
+#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001)
@@ -2244,6 +2388,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
/* values for SAS Device Page 0 Flags field */
+#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE (0x8000)
#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000)
#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800)
#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400)
@@ -2799,5 +2944,25 @@ typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03)
+/****************************************************************************
+* Extended Manufacturing Config Pages
+****************************************************************************/
+
+/*
+ * Generic structure to use for product-specific extended manufacturing pages
+ * (currently Extended Manufacturing Page 40 through Extended Manufacturing
+ * Page 60).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 ProductSpecificInfo; /* 0x08 */
+} MPI2_CONFIG_PAGE_EXT_MAN_PS,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
+ Mpi2ExtManufacturingPagePS_t,
+ MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
+
+/* PageVersion should be provided by product-specific code */
+
#endif
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index 165454d..de90162 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -6,7 +6,7 @@
* Title: MPI SCSI initiator mode messages and structures
* Creation Date: June 23, 2006
*
- * mpi2_init.h Version: 02.00.10
+ * mpi2_init.h Version: 02.00.11
*
* Version History
* ---------------
@@ -33,6 +33,7 @@
* Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
* 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it.
* 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request.
+ * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
* --------------------------------------------------------------------------
*/
@@ -139,6 +140,9 @@ typedef struct _MPI2_SCSI_IO_REQUEST
#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
+/* number of SGLOffset fields */
+#define MPI2_SCSIIO_NUM_SGLOFFSETS (4)
+
/* SCSI IO IoFlags bits */
/* Large CDB Address Space */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index 761cbdb..93d9b69 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2010 LSI Corporation.
+ * Copyright (c) 2000-2011 LSI Corporation.
*
*
* Name: mpi2_ioc.h
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
- * mpi2_ioc.h Version: 02.00.15
+ * mpi2_ioc.h Version: 02.00.17
*
* Version History
* ---------------
@@ -103,6 +103,13 @@
* defines.
* 05-12-10 02.00.15 Marked Task Set Full Event as obsolete.
* Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
+ * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added
+ * SASNotifyPrimitiveMasks field to
+ * MPI2_EVENT_NOTIFICATION_REQUEST.
+ * Added Temperature Threshold Event.
+ * Added Host Message Event.
+ * Added Send Host Message request and reply.
* --------------------------------------------------------------------------
*/
@@ -420,7 +427,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
U32 Reserved6; /* 0x10 */
U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
U16 SASBroadcastPrimitiveMasks; /* 0x24 */
- U16 Reserved7; /* 0x26 */
+ U16 SASNotifyPrimitiveMasks; /* 0x26 */
U32 Reserved8; /* 0x28 */
} MPI2_EVENT_NOTIFICATION_REQUEST,
MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
@@ -475,6 +482,9 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
#define MPI2_EVENT_GPIO_INTERRUPT (0x0023)
#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024)
#define MPI2_EVENT_SAS_QUIESCE (0x0025)
+#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026)
+#define MPI2_EVENT_TEMP_THRESHOLD (0x0027)
+#define MPI2_EVENT_HOST_MESSAGE (0x0028)
/* Log Entry Added Event data */
@@ -506,6 +516,39 @@ typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT {
MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t;
+/* Temperature Threshold Event data */
+
+typedef struct _MPI2_EVENT_DATA_TEMPERATURE {
+ U16 Status; /* 0x00 */
+ U8 SensorNum; /* 0x02 */
+ U8 Reserved1; /* 0x03 */
+ U16 CurrentTemperature; /* 0x04 */
+ U16 Reserved2; /* 0x06 */
+ U32 Reserved3; /* 0x08 */
+ U32 Reserved4; /* 0x0C */
+} MPI2_EVENT_DATA_TEMPERATURE,
+MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE,
+Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t;
+
+/* Temperature Threshold Event data Status bits */
+#define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008)
+#define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004)
+#define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002)
+#define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001)
+
+
+/* Host Message Event data */
+
+typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE {
+ U8 SourceVF_ID; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U16 Reserved2; /* 0x02 */
+ U32 Reserved3; /* 0x04 */
+ U32 HostData[1]; /* 0x08 */
+} MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE,
+Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t;
+
+
/* Hard Reset Received Event data */
typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
@@ -748,6 +791,24 @@ typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07)
#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08)
+/* SAS Notify Primitive Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE {
+ U8 PhyNum; /* 0x00 */
+ U8 Port; /* 0x01 */
+ U8 Reserved1; /* 0x02 */
+ U8 Primitive; /* 0x03 */
+} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
+MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
+Mpi2EventDataSasNotifyPrimitive_t,
+MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t;
+
+/* defines for the Primitive field */
+#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01)
+#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02)
+#define MPI2_EVENT_NOTIFY_RESERVED1 (0x03)
+#define MPI2_EVENT_NOTIFY_RESERVED2 (0x04)
+
/* SAS Initiator Device Status Change Event data */
@@ -1000,6 +1061,53 @@ typedef struct _MPI2_EVENT_ACK_REPLY
/****************************************************************************
+* SendHostMessage message
+****************************************************************************/
+
+/* SendHostMessage Request message */
+typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST {
+ U16 HostDataLength; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved1; /* 0x04 */
+ U8 Reserved2; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U8 Reserved4; /* 0x0C */
+ U8 DestVF_ID; /* 0x0D */
+ U16 Reserved5; /* 0x0E */
+ U32 Reserved6; /* 0x10 */
+ U32 Reserved7; /* 0x14 */
+ U32 Reserved8; /* 0x18 */
+ U32 Reserved9; /* 0x1C */
+ U32 Reserved10; /* 0x20 */
+ U32 HostData[1]; /* 0x24 */
+} MPI2_SEND_HOST_MESSAGE_REQUEST,
+MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST,
+Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t;
+
+
+/* SendHostMessage Reply message */
+typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY {
+ U16 HostDataLength; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved1; /* 0x04 */
+ U8 Reserved2; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U16 Reserved4; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY,
+Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t;
+
+
+/****************************************************************************
* FWDownload message
****************************************************************************/
@@ -1032,6 +1140,7 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST
#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
+#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
/* FWDownload TransactionContext Element */
typedef struct _MPI2_FW_DOWNLOAD_TCSGE
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 679fe6a..a11a909 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -80,9 +79,14 @@ static int msix_disable = -1;
module_param(msix_disable, int, 0);
MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
-static int missing_delay[2] = {-1, -1};
-module_param_array(missing_delay, int, NULL, 0);
-MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
+static int mpt2sas_fwfault_debug;
+MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
+ "and halt firmware - (default=0)");
+
+static int disable_discovery = -1;
+module_param(disable_discovery, int, 0);
+MODULE_PARM_DESC(disable_discovery, " disable discovery ");
+
/* diag_buffer_enable is bitwise
* bit 0 set = TRACE
@@ -96,14 +100,6 @@ module_param(diag_buffer_enable, int, 0);
MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
"(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
-static int mpt2sas_fwfault_debug;
-MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
- "and halt firmware - (default=0)");
-
-static int disable_discovery = -1;
-module_param(disable_discovery, int, 0);
-MODULE_PARM_DESC(disable_discovery, " disable discovery ");
-
/**
* _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
*
@@ -694,6 +690,7 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
}
ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
+
complete(&ioc->base_cmds.done);
return 1;
}
@@ -836,25 +833,31 @@ union reply_descriptor {
static irqreturn_t
_base_interrupt(int irq, void *bus_id)
{
+ struct adapter_reply_queue *reply_q = bus_id;
union reply_descriptor rd;
u32 completed_cmds;
u8 request_desript_type;
u16 smid;
u8 cb_idx;
u32 reply;
- u8 msix_index;
- struct MPT2SAS_ADAPTER *ioc = bus_id;
+ u8 msix_index = reply_q->msix_index;
+ struct MPT2SAS_ADAPTER *ioc = reply_q->ioc;
Mpi2ReplyDescriptorsUnion_t *rpf;
u8 rc;
if (ioc->mask_interrupts)
return IRQ_NONE;
- rpf = &ioc->reply_post_free[ioc->reply_post_host_index];
+ if (!atomic_add_unless(&reply_q->busy, 1, 1))
+ return IRQ_NONE;
+
+ rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index];
request_desript_type = rpf->Default.ReplyFlags
& MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
- if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
+ atomic_dec(&reply_q->busy);
return IRQ_NONE;
+ }
completed_cmds = 0;
cb_idx = 0xFF;
@@ -863,9 +866,7 @@ _base_interrupt(int irq, void *bus_id)
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out;
reply = 0;
- cb_idx = 0xFF;
smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
- msix_index = rpf->Default.MSIxIndex;
if (request_desript_type ==
MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
reply = le32_to_cpu
@@ -909,32 +910,86 @@ _base_interrupt(int irq, void *bus_id)
next:
rpf->Words = cpu_to_le64(ULLONG_MAX);
- ioc->reply_post_host_index = (ioc->reply_post_host_index ==
+ reply_q->reply_post_host_index =
+ (reply_q->reply_post_host_index ==
(ioc->reply_post_queue_depth - 1)) ? 0 :
- ioc->reply_post_host_index + 1;
+ reply_q->reply_post_host_index + 1;
request_desript_type =
- ioc->reply_post_free[ioc->reply_post_host_index].Default.
- ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+ reply_q->reply_post_free[reply_q->reply_post_host_index].
+ Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
completed_cmds++;
if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
goto out;
- if (!ioc->reply_post_host_index)
- rpf = ioc->reply_post_free;
+ if (!reply_q->reply_post_host_index)
+ rpf = reply_q->reply_post_free;
else
rpf++;
} while (1);
out:
- if (!completed_cmds)
+ if (!completed_cmds) {
+ atomic_dec(&reply_q->busy);
return IRQ_NONE;
-
+ }
wmb();
- writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex);
+ if (ioc->is_warpdrive) {
+ writel(reply_q->reply_post_host_index,
+ ioc->reply_post_host_index[msix_index]);
+ atomic_dec(&reply_q->busy);
+ return IRQ_HANDLED;
+ }
+ writel(reply_q->reply_post_host_index | (msix_index <<
+ MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex);
+ atomic_dec(&reply_q->busy);
return IRQ_HANDLED;
}
/**
+ * _base_is_controller_msix_enabled - is controller support muli-reply queues
+ * @ioc: per adapter object
+ *
+ */
+static inline int
+_base_is_controller_msix_enabled(struct MPT2SAS_ADAPTER *ioc)
+{
+ return (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable;
+}
+
+/**
+ * mpt2sas_base_flush_reply_queues - flushing the MSIX reply queues
+ * @ioc: per adapter object
+ * Context: ISR conext
+ *
+ * Called when a Task Management request has completed. We want
+ * to flush the other reply queues so all the outstanding IO has been
+ * completed back to OS before we process the TM completetion.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct adapter_reply_queue *reply_q;
+
+ /* If MSIX capability is turned off
+ * then multi-queues are not enabled
+ */
+ if (!_base_is_controller_msix_enabled(ioc))
+ return;
+
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ if (ioc->shost_recovery)
+ return;
+ /* TMs are on msix_index == 0 */
+ if (reply_q->msix_index == 0)
+ continue;
+ _base_interrupt(reply_q->vector, (void *)reply_q);
+ }
+}
+
+/**
* mpt2sas_base_release_callback_handler - clear interrupt callback handler
* @cb_idx: callback index
*
@@ -1112,15 +1167,153 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
}
/* get msix vector count */
- pci_read_config_word(ioc->pdev, base + 2, &message_control);
- ioc->msix_vector_count = (message_control & 0x3FF) + 1;
-
+ /* NUMA_IO not supported for older controllers */
+ if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2)
+ ioc->msix_vector_count = 1;
+ else {
+ pci_read_config_word(ioc->pdev, base + 2, &message_control);
+ ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+ }
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
"vector_count(%d)\n", ioc->name, ioc->msix_vector_count));
+
return 0;
}
/**
+ * _base_free_irq - free irq
+ * @ioc: per adapter object
+ *
+ * Freeing respective reply_queue from the list.
+ */
+static void
+_base_free_irq(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct adapter_reply_queue *reply_q, *next;
+
+ if (list_empty(&ioc->reply_queue_list))
+ return;
+
+ list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
+ list_del(&reply_q->list);
+ synchronize_irq(reply_q->vector);
+ free_irq(reply_q->vector, reply_q);
+ kfree(reply_q);
+ }
+}
+
+/**
+ * _base_request_irq - request irq
+ * @ioc: per adapter object
+ * @index: msix index into vector table
+ * @vector: irq vector
+ *
+ * Inserting respective reply_queue into the list.
+ */
+static int
+_base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector)
+{
+ struct adapter_reply_queue *reply_q;
+ int r;
+
+ reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
+ if (!reply_q) {
+ printk(MPT2SAS_ERR_FMT "unable to allocate memory %d!\n",
+ ioc->name, (int)sizeof(struct adapter_reply_queue));
+ return -ENOMEM;
+ }
+ reply_q->ioc = ioc;
+ reply_q->msix_index = index;
+ reply_q->vector = vector;
+ atomic_set(&reply_q->busy, 0);
+ if (ioc->msix_enable)
+ snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
+ MPT2SAS_DRIVER_NAME, ioc->id, index);
+ else
+ snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
+ MPT2SAS_DRIVER_NAME, ioc->id);
+ r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
+ reply_q);
+ if (r) {
+ printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
+ reply_q->name, vector);
+ kfree(reply_q);
+ return -EBUSY;
+ }
+
+ INIT_LIST_HEAD(&reply_q->list);
+ list_add_tail(&reply_q->list, &ioc->reply_queue_list);
+ return 0;
+}
+
+/**
+ * _base_assign_reply_queues - assigning msix index for each cpu
+ * @ioc: per adapter object
+ *
+ * The enduser would need to set the affinity via /proc/irq/#/smp_affinity
+ *
+ * It would nice if we could call irq_set_affinity, however it is not
+ * an exported symbol
+ */
+static void
+_base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct adapter_reply_queue *reply_q;
+ int cpu_id;
+ int cpu_grouping, loop, grouping, grouping_mod;
+
+ if (!_base_is_controller_msix_enabled(ioc))
+ return;
+
+ memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
+ /* when there are more cpus than available msix vectors,
+ * then group cpus togeather on same irq
+ */
+ if (ioc->cpu_count > ioc->msix_vector_count) {
+ grouping = ioc->cpu_count / ioc->msix_vector_count;
+ grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
+ if (grouping < 2 || (grouping == 2 && !grouping_mod))
+ cpu_grouping = 2;
+ else if (grouping < 4 || (grouping == 4 && !grouping_mod))
+ cpu_grouping = 4;
+ else if (grouping < 8 || (grouping == 8 && !grouping_mod))
+ cpu_grouping = 8;
+ else
+ cpu_grouping = 16;
+ } else
+ cpu_grouping = 0;
+
+ loop = 0;
+ reply_q = list_entry(ioc->reply_queue_list.next,
+ struct adapter_reply_queue, list);
+ for_each_online_cpu(cpu_id) {
+ if (!cpu_grouping) {
+ ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
+ reply_q = list_entry(reply_q->list.next,
+ struct adapter_reply_queue, list);
+ } else {
+ if (loop < cpu_grouping) {
+ ioc->cpu_msix_table[cpu_id] =
+ reply_q->msix_index;
+ loop++;
+ } else {
+ reply_q = list_entry(reply_q->list.next,
+ struct adapter_reply_queue, list);
+ ioc->cpu_msix_table[cpu_id] =
+ reply_q->msix_index;
+ loop = 1;
+ }
+ }
+ }
+}
+
+/**
* _base_disable_msix - disables msix
* @ioc: per adapter object
*
@@ -1142,10 +1335,13 @@ _base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
static int
_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
{
- struct msix_entry entries;
+ struct msix_entry *entries, *a;
int r;
+ int i;
u8 try_msix = 0;
+ INIT_LIST_HEAD(&ioc->reply_queue_list);
+
if (msix_disable == -1 || msix_disable == 0)
try_msix = 1;
@@ -1155,43 +1351,48 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
if (_base_check_enable_msix(ioc) != 0)
goto try_ioapic;
- memset(&entries, 0, sizeof(struct msix_entry));
- r = pci_enable_msix(ioc->pdev, &entries, 1);
- if (r) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
- "failed (r=%d) !!!\n", ioc->name, r));
+ ioc->reply_queue_count = min_t(u8, ioc->cpu_count,
+ ioc->msix_vector_count);
+
+ entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (!entries) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "kcalloc "
+ "failed @ at %s:%d/%s() !!!\n", ioc->name, __FILE__,
+ __LINE__, __func__));
goto try_ioapic;
}
- r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
- ioc->name, ioc);
+ for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++)
+ a->entry = i;
+
+ r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count);
if (r) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
- "interrupt %d !!!\n", ioc->name, entries.vector));
- pci_disable_msix(ioc->pdev);
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
+ "failed (r=%d) !!!\n", ioc->name, r));
+ kfree(entries);
goto try_ioapic;
}
- ioc->pci_irq = entries.vector;
ioc->msix_enable = 1;
+ for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) {
+ r = _base_request_irq(ioc, i, a->vector);
+ if (r) {
+ _base_free_irq(ioc);
+ _base_disable_msix(ioc);
+ kfree(entries);
+ goto try_ioapic;
+ }
+ }
+
+ kfree(entries);
return 0;
/* failback to io_apic interrupt routing */
try_ioapic:
- r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
- ioc->name, ioc);
- if (r) {
- printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
- ioc->name, ioc->pdev->irq);
- r = -EBUSY;
- goto out_fail;
- }
-
- ioc->pci_irq = ioc->pdev->irq;
- return 0;
+ r = _base_request_irq(ioc, 0, ioc->pdev->irq);
- out_fail:
return r;
}
@@ -1210,6 +1411,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
int i, r = 0;
u64 pio_chip = 0;
u64 chip_phys = 0;
+ struct adapter_reply_queue *reply_q;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",
ioc->name, __func__));
@@ -1272,9 +1474,11 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
if (r)
goto out_fail;
- printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
- ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
- "IO-APIC enabled"), ioc->pci_irq);
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
+ printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
+ reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
+ "IO-APIC enabled"), reply_q->vector);
+
printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
@@ -1289,7 +1493,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
if (ioc->chip_phys)
iounmap(ioc->chip);
ioc->chip_phys = 0;
- ioc->pci_irq = -1;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
@@ -1536,6 +1739,12 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
}
#endif
+static inline u8
+_base_get_msix_index(struct MPT2SAS_ADAPTER *ioc)
+{
+ return ioc->cpu_msix_table[raw_smp_processor_id()];
+}
+
/**
* mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
* @ioc: per adapter object
@@ -1552,7 +1761,7 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
- descriptor.SCSIIO.MSIxIndex = 0; /* TODO */
+ descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
descriptor.SCSIIO.SMID = cpu_to_le16(smid);
descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
descriptor.SCSIIO.LMID = 0;
@@ -1576,7 +1785,7 @@ mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
descriptor.HighPriority.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
- descriptor.HighPriority.MSIxIndex = 0; /* TODO */
+ descriptor.HighPriority.MSIxIndex = 0;
descriptor.HighPriority.SMID = cpu_to_le16(smid);
descriptor.HighPriority.LMID = 0;
descriptor.HighPriority.Reserved1 = 0;
@@ -1598,7 +1807,7 @@ mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
u64 *request = (u64 *)&descriptor;
descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
- descriptor.Default.MSIxIndex = 0; /* TODO */
+ descriptor.Default.MSIxIndex = _base_get_msix_index(ioc);
descriptor.Default.SMID = cpu_to_le16(smid);
descriptor.Default.LMID = 0;
descriptor.Default.DescriptorTypeDependent = 0;
@@ -1623,7 +1832,7 @@ mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
descriptor.SCSITarget.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
- descriptor.SCSITarget.MSIxIndex = 0; /* TODO */
+ descriptor.SCSITarget.MSIxIndex = _base_get_msix_index(ioc);
descriptor.SCSITarget.SMID = cpu_to_le16(smid);
descriptor.SCSITarget.LMID = 0;
descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
@@ -1891,7 +2100,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
}
/**
- * _base_update_missing_delay - change the missing delay timers
+ * mpt2sas_base_update_missing_delay - change the missing delay timers
* @ioc: per adapter object
* @device_missing_delay: amount of time till device is reported missing
* @io_missing_delay: interval IO is returned when there is a missing device
@@ -1902,8 +2111,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
* delay, as well as the io missing delay. This should be called at driver
* load time.
*/
-static void
-_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+void
+mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay)
{
u16 dmd, dmd_new, dmd_orignal;
@@ -2126,7 +2335,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
struct mpt2sas_facts *facts;
u16 max_sge_elements;
u16 chains_needed_per_io;
- u32 sz, total_sz;
+ u32 sz, total_sz, reply_post_free_sz;
u32 retry_sz;
u16 max_request_credit;
int i;
@@ -2429,7 +2638,12 @@ chain_done:
total_sz += sz;
/* reply post queue, 16 byte align */
- sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t);
+ reply_post_free_sz = ioc->reply_post_queue_depth *
+ sizeof(Mpi2DefaultReplyDescriptor_t);
+ if (_base_is_controller_msix_enabled(ioc))
+ sz = reply_post_free_sz * ioc->reply_queue_count;
+ else
+ sz = reply_post_free_sz;
ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
ioc->pdev, sz, 16, 0);
if (!ioc->reply_post_free_dma_pool) {
@@ -3117,6 +3331,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
facts->MaxChainDepth = mpi_reply.MaxChainDepth;
facts->WhoInit = mpi_reply.WhoInit;
facts->NumberOfPorts = mpi_reply.NumberOfPorts;
+ facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
facts->MaxReplyDescriptorPostQueueDepth =
le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
@@ -3174,7 +3389,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
-
+ if (_base_is_controller_msix_enabled(ioc))
+ mpi_request.HostMSIxVectors = ioc->reply_queue_count;
mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
mpi_request.ReplyDescriptorPostQueueDepth =
cpu_to_le16(ioc->reply_post_queue_depth);
@@ -3233,6 +3449,58 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
/**
+ * mpt2sas_port_enable_done - command completion routine for port enable
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ * 0 means the mf is freed from this function.
+ */
+u8
+mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+ u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+ u16 ioc_status;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
+ return 1;
+
+ if (ioc->port_enable_cmds.status == MPT2_CMD_NOT_USED)
+ return 1;
+
+ ioc->port_enable_cmds.status |= MPT2_CMD_COMPLETE;
+ if (mpi_reply) {
+ ioc->port_enable_cmds.status |= MPT2_CMD_REPLY_VALID;
+ memcpy(ioc->port_enable_cmds.reply, mpi_reply,
+ mpi_reply->MsgLength*4);
+ }
+ ioc->port_enable_cmds.status &= ~MPT2_CMD_PENDING;
+
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+ ioc->port_enable_failed = 1;
+
+ if (ioc->is_driver_loading) {
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ mpt2sas_port_enable_complete(ioc);
+ return 1;
+ } else {
+ ioc->start_scan_failed = ioc_status;
+ ioc->start_scan = 0;
+ return 1;
+ }
+ }
+ complete(&ioc->port_enable_cmds.done);
+ return 1;
+}
+
+
+/**
* _base_send_port_enable - send port_enable(discovery stuff) to firmware
* @ioc: per adapter object
* @sleep_flag: CAN_SLEEP or NO_SLEEP
@@ -3243,67 +3511,151 @@ static int
_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
{
Mpi2PortEnableRequest_t *mpi_request;
- u32 ioc_state;
+ Mpi2PortEnableReply_t *mpi_reply;
unsigned long timeleft;
int r = 0;
u16 smid;
+ u16 ioc_status;
printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
- if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
+ if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
ioc->name, __func__);
return -EAGAIN;
}
- smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+ smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
if (!smid) {
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
return -EAGAIN;
}
- ioc->base_cmds.status = MPT2_CMD_PENDING;
+ ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->base_cmds.smid = smid;
+ ioc->port_enable_cmds.smid = smid;
memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
+ init_completion(&ioc->port_enable_cmds.done);
mpt2sas_base_put_smid_default(ioc, smid);
- init_completion(&ioc->base_cmds.done);
- timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+ timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
300*HZ);
- if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
+ if (!(ioc->port_enable_cmds.status & MPT2_CMD_COMPLETE)) {
printk(MPT2SAS_ERR_FMT "%s: timeout\n",
ioc->name, __func__);
_debug_dump_mf(mpi_request,
sizeof(Mpi2PortEnableRequest_t)/4);
- if (ioc->base_cmds.status & MPT2_CMD_RESET)
+ if (ioc->port_enable_cmds.status & MPT2_CMD_RESET)
r = -EFAULT;
else
r = -ETIME;
goto out;
- } else
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
- ioc->name, __func__));
+ }
+ mpi_reply = ioc->port_enable_cmds.reply;
- ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL,
- 60, sleep_flag);
- if (ioc_state) {
- printk(MPT2SAS_ERR_FMT "%s: failed going to operational state "
- " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "%s: failed with (ioc_status=0x%08x)\n",
+ ioc->name, __func__, ioc_status);
r = -EFAULT;
+ goto out;
}
out:
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- printk(MPT2SAS_INFO_FMT "port enable: %s\n",
- ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
+ ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
+ printk(MPT2SAS_INFO_FMT "port enable: %s\n", ioc->name, ((r == 0) ?
+ "SUCCESS" : "FAILED"));
return r;
}
/**
+ * mpt2sas_port_enable - initiate firmware discovery (don't wait for reply)
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc)
+{
+ Mpi2PortEnableRequest_t *mpi_request;
+ u16 smid;
+
+ printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
+
+ if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
+ printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+
+ ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->port_enable_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
+
+ mpt2sas_base_put_smid_default(ioc, smid);
+ return 0;
+}
+
+/**
+ * _base_determine_wait_on_discovery - desposition
+ * @ioc: per adapter object
+ *
+ * Decide whether to wait on discovery to complete. Used to either
+ * locate boot device, or report volumes ahead of physical devices.
+ *
+ * Returns 1 for wait, 0 for don't wait
+ */
+static int
+_base_determine_wait_on_discovery(struct MPT2SAS_ADAPTER *ioc)
+{
+ /* We wait for discovery to complete if IR firmware is loaded.
+ * The sas topology events arrive before PD events, so we need time to
+ * turn on the bit in ioc->pd_handles to indicate PD
+ * Also, it maybe required to report Volumes ahead of physical
+ * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set.
+ */
+ if (ioc->ir_firmware)
+ return 1;
+
+ /* if no Bios, then we don't need to wait */
+ if (!ioc->bios_pg3.BiosVersion)
+ return 0;
+
+ /* Bios is present, then we drop down here.
+ *
+ * If there any entries in the Bios Page 2, then we wait
+ * for discovery to complete.
+ */
+
+ /* Current Boot Device */
+ if ((ioc->bios_pg2.CurrentBootDeviceForm &
+ MPI2_BIOSPAGE2_FORM_MASK) ==
+ MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
+ /* Request Boot Device */
+ (ioc->bios_pg2.ReqBootDeviceForm &
+ MPI2_BIOSPAGE2_FORM_MASK) ==
+ MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
+ /* Alternate Request Boot Device */
+ (ioc->bios_pg2.ReqAltBootDeviceForm &
+ MPI2_BIOSPAGE2_FORM_MASK) ==
+ MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED)
+ return 0;
+
+ return 1;
+}
+
+
+/**
* _base_unmask_events - turn on notification for this event
* @ioc: per adapter object
* @event: firmware event
@@ -3618,6 +3970,9 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u16 smid;
struct _tr_list *delayed_tr, *delayed_tr_next;
u8 hide_flag;
+ struct adapter_reply_queue *reply_q;
+ long reply_post_free;
+ u32 reply_post_free_sz;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -3683,21 +4038,47 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
ioc->reply_sz)
ioc->reply_free[i] = cpu_to_le32(reply_address);
+ /* initialize reply queues */
+ if (ioc->is_driver_loading)
+ _base_assign_reply_queues(ioc);
+
/* initialize Reply Post Free Queue */
- for (i = 0; i < ioc->reply_post_queue_depth; i++)
- ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
+ reply_post_free = (long)ioc->reply_post_free;
+ reply_post_free_sz = ioc->reply_post_queue_depth *
+ sizeof(Mpi2DefaultReplyDescriptor_t);
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ reply_q->reply_post_host_index = 0;
+ reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
+ reply_post_free;
+ for (i = 0; i < ioc->reply_post_queue_depth; i++)
+ reply_q->reply_post_free[i].Words =
+ cpu_to_le64(ULLONG_MAX);
+ if (!_base_is_controller_msix_enabled(ioc))
+ goto skip_init_reply_post_free_queue;
+ reply_post_free += reply_post_free_sz;
+ }
+ skip_init_reply_post_free_queue:
r = _base_send_ioc_init(ioc, sleep_flag);
if (r)
return r;
- /* initialize the index's */
+ /* initialize reply free host index */
ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
- ioc->reply_post_host_index = 0;
writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
- writel(0, &ioc->chip->ReplyPostHostIndex);
+
+ /* initialize reply post host index */
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT,
+ &ioc->chip->ReplyPostHostIndex);
+ if (!_base_is_controller_msix_enabled(ioc))
+ goto skip_init_reply_post_host_index;
+ }
+
+ skip_init_reply_post_host_index:
_base_unmask_interrupts(ioc);
+
r = _base_event_notification(ioc, sleep_flag);
if (r)
return r;
@@ -3705,22 +4086,19 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
if (sleep_flag == CAN_SLEEP)
_base_static_config_pages(ioc);
- if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) {
- if (ioc->manu_pg10.OEMIdentifier == 0x80) {
+
+ if (ioc->is_driver_loading) {
+ if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
+ == 0x80) {
hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 &
MFG_PAGE10_HIDE_SSDS_MASK);
if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
ioc->mfg_pg10_hide_flag = hide_flag;
}
+ ioc->wait_for_discovery_to_complete =
+ _base_determine_wait_on_discovery(ioc);
+ return r; /* scan_start and scan_finished support */
}
-
- if (ioc->wait_for_port_enable_to_complete) {
- if (diag_buffer_enable != 0)
- mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
- if (disable_discovery > 0)
- return r;
- }
-
r = _base_send_port_enable(ioc, sleep_flag);
if (r)
return r;
@@ -3746,14 +4124,10 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
ioc->shost_recovery = 1;
_base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
ioc->shost_recovery = 0;
- if (ioc->pci_irq) {
- synchronize_irq(pdev->irq);
- free_irq(ioc->pci_irq, ioc);
- }
+ _base_free_irq(ioc);
_base_disable_msix(ioc);
if (ioc->chip_phys)
iounmap(ioc->chip);
- ioc->pci_irq = -1;
ioc->chip_phys = 0;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_pcie_error_reporting(pdev);
@@ -3771,14 +4145,50 @@ int
mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
{
int r, i;
+ int cpu_id, last_cpu_id = 0;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
+ /* setup cpu_msix_table */
+ ioc->cpu_count = num_online_cpus();
+ for_each_online_cpu(cpu_id)
+ last_cpu_id = cpu_id;
+ ioc->cpu_msix_table_sz = last_cpu_id + 1;
+ ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
+ ioc->reply_queue_count = 1;
+ if (!ioc->cpu_msix_table) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
+ "cpu_msix_table failed!!!\n", ioc->name));
+ r = -ENOMEM;
+ goto out_free_resources;
+ }
+
+ if (ioc->is_warpdrive) {
+ ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
+ sizeof(resource_size_t *), GFP_KERNEL);
+ if (!ioc->reply_post_host_index) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation "
+ "for cpu_msix_table failed!!!\n", ioc->name));
+ r = -ENOMEM;
+ goto out_free_resources;
+ }
+ }
+
r = mpt2sas_base_map_resources(ioc);
if (r)
return r;
+ if (ioc->is_warpdrive) {
+ ioc->reply_post_host_index[0] =
+ (resource_size_t *)&ioc->chip->ReplyPostHostIndex;
+
+ for (i = 1; i < ioc->cpu_msix_table_sz; i++)
+ ioc->reply_post_host_index[i] = (resource_size_t *)
+ ((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+ * 4)));
+ }
+
pci_set_drvdata(ioc->pdev, ioc->shost);
r = _base_get_ioc_facts(ioc, CAN_SLEEP);
if (r)
@@ -3825,6 +4235,10 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ /* port_enable command bits */
+ ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
+
/* transport internal command bits */
ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
@@ -3866,8 +4280,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
goto out_free_resources;
}
- init_completion(&ioc->shost_recovery_done);
-
for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
ioc->event_masks[i] = -1;
@@ -3886,11 +4298,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
if (r)
goto out_free_resources;
- if (missing_delay[0] != -1 && missing_delay[1] != -1)
- _base_update_missing_delay(ioc, missing_delay[0],
- missing_delay[1]);
- mpt2sas_base_start_watchdog(ioc);
return 0;
out_free_resources:
@@ -3899,12 +4307,16 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
pci_set_drvdata(ioc->pdev, NULL);
+ kfree(ioc->cpu_msix_table);
+ if (ioc->is_warpdrive)
+ kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
kfree(ioc->scsih_cmds.reply);
kfree(ioc->config_cmds.reply);
kfree(ioc->base_cmds.reply);
+ kfree(ioc->port_enable_cmds.reply);
kfree(ioc->ctl_cmds.reply);
kfree(ioc->ctl_cmds.sense);
kfree(ioc->pfacts);
@@ -3936,11 +4348,15 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
pci_set_drvdata(ioc->pdev, NULL);
+ kfree(ioc->cpu_msix_table);
+ if (ioc->is_warpdrive)
+ kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply);
kfree(ioc->ctl_cmds.sense);
kfree(ioc->base_cmds.reply);
+ kfree(ioc->port_enable_cmds.reply);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
kfree(ioc->scsih_cmds.reply);
@@ -3982,6 +4398,20 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
complete(&ioc->base_cmds.done);
}
+ if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
+ ioc->port_enable_failed = 1;
+ ioc->port_enable_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->port_enable_cmds.smid);
+ if (ioc->is_driver_loading) {
+ ioc->start_scan_failed =
+ MPI2_IOCSTATUS_INTERNAL_ERROR;
+ ioc->start_scan = 0;
+ ioc->port_enable_cmds.status =
+ MPT2_CMD_NOT_USED;
+ } else
+ complete(&ioc->port_enable_cmds.done);
+
+ }
if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
ioc->config_cmds.status |= MPT2_CMD_RESET;
mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
@@ -4047,7 +4477,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
{
int r;
unsigned long flags;
- u8 pe_complete = ioc->wait_for_port_enable_to_complete;
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__));
@@ -4094,7 +4523,8 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
/* If this hard reset is called while port enable is active, then
* there is no reason to call make_ioc_operational
*/
- if (pe_complete) {
+ if (ioc->is_driver_loading && ioc->port_enable_failed) {
+ ioc->remove_host = 1;
r = -EFAULT;
goto out;
}
@@ -4108,7 +4538,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
ioc->ioc_reset_in_progress_status = r;
ioc->shost_recovery = 0;
- complete(&ioc->shost_recovery_done);
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
mutex_unlock(&ioc->reset_in_progress_mutex);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index e1735f9..aa4daf6 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,11 +69,11 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "08.100.00.02"
-#define MPT2SAS_MAJOR_VERSION 08
+#define MPT2SAS_DRIVER_VERSION "10.100.00.00"
+#define MPT2SAS_MAJOR_VERSION 10
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
-#define MPT2SAS_RELEASE_VERSION 02
+#define MPT2SAS_RELEASE_VERSION 00
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
@@ -544,6 +544,28 @@ struct _tr_list {
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
+/**
+ * struct adapter_reply_queue - the reply queue struct
+ * @ioc: per adapter object
+ * @msix_index: msix index into vector table
+ * @vector: irq vector
+ * @reply_post_host_index: head index in the pool where FW completes IO
+ * @reply_post_free: reply post base virt address
+ * @name: the name registered to request_irq()
+ * @busy: isr is actively processing replies on another cpu
+ * @list: this list
+*/
+struct adapter_reply_queue {
+ struct MPT2SAS_ADAPTER *ioc;
+ u8 msix_index;
+ unsigned int vector;
+ u32 reply_post_host_index;
+ Mpi2ReplyDescriptorsUnion_t *reply_post_free;
+ char name[MPT_NAME_LENGTH];
+ atomic_t busy;
+ struct list_head list;
+};
+
/* IOC Facts and Port Facts converted from little endian to cpu */
union mpi2_version_union {
MPI2_VERSION_STRUCT Struct;
@@ -592,11 +614,21 @@ struct mpt2sas_port_facts {
};
/**
+ * enum mutex_type - task management mutex type
+ * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
+ * @TM_MUTEX_ON: mutex is required
+ */
+enum mutex_type {
+ TM_MUTEX_OFF = 0,
+ TM_MUTEX_ON = 1,
+};
+
+/**
* struct MPT2SAS_ADAPTER - per adapter struct
* @list: ioc_list
* @shost: shost object
* @id: unique adapter id
- * @pci_irq: irq number
+ * @cpu_count: number online cpus
* @name: generic ioc string
* @tmp_string: tmp string used for logging
* @pdev: pci pdev object
@@ -623,9 +655,16 @@ struct mpt2sas_port_facts {
* @ignore_loginfos: ignore loginfos during task management
* @remove_host: flag for when driver unloads, to avoid sending dev resets
* @pci_error_recovery: flag to prevent ioc access until slot reset completes
- * @wait_for_port_enable_to_complete:
+ * @wait_for_discovery_to_complete: flag set at driver load time when
+ * waiting on reporting devices
+ * @is_driver_loading: flag set at driver load time
+ * @port_enable_failed: flag set when port enable has failed
+ * @start_scan: flag set from scan_start callback, cleared from _mpt2sas_fw_work
+ * @start_scan_failed: means port enable failed, return's the ioc_status
* @msix_enable: flag indicating msix is enabled
* @msix_vector_count: number msix vectors
+ * @cpu_msix_table: table for mapping cpus to msix index
+ * @cpu_msix_table_sz: table size
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
* @scsih_cb_idx: scsih internal commands
@@ -716,7 +755,8 @@ struct mpt2sas_port_facts {
* @reply_post_queue_depth: reply post queue depth
* @reply_post_free: pool for reply post (64bit descriptor)
* @reply_post_free_dma:
- * @reply_post_free_dma_pool:
+ * @reply_queue_count: number of reply queue's
+ * @reply_queue_list: link list contaning the reply queue info
* @reply_post_host_index: head index in the pool where FW completes IO
* @delayed_tr_list: target reset link list
* @delayed_tr_volume_list: volume target reset link list
@@ -725,7 +765,7 @@ struct MPT2SAS_ADAPTER {
struct list_head list;
struct Scsi_Host *shost;
u8 id;
- u32 pci_irq;
+ int cpu_count;
char name[MPT_NAME_LENGTH];
char tmp_string[MPT_STRING_LENGTH];
struct pci_dev *pdev;
@@ -751,21 +791,30 @@ struct MPT2SAS_ADAPTER {
/* misc flags */
int aen_event_read_flag;
u8 broadcast_aen_busy;
+ u16 broadcast_aen_pending;
u8 shost_recovery;
struct mutex reset_in_progress_mutex;
- struct completion shost_recovery_done;
spinlock_t ioc_reset_in_progress_lock;
u8 ioc_link_reset_in_progress;
- int ioc_reset_in_progress_status;
+ u8 ioc_reset_in_progress_status;
u8 ignore_loginfos;
u8 remove_host;
u8 pci_error_recovery;
- u8 wait_for_port_enable_to_complete;
+ u8 wait_for_discovery_to_complete;
+ struct completion port_enable_done;
+ u8 is_driver_loading;
+ u8 port_enable_failed;
+
+ u8 start_scan;
+ u16 start_scan_failed;
u8 msix_enable;
u16 msix_vector_count;
+ u8 *cpu_msix_table;
+ resource_size_t **reply_post_host_index;
+ u16 cpu_msix_table_sz;
u32 ioc_reset_count;
/* internal commands, callback index */
@@ -775,11 +824,13 @@ struct MPT2SAS_ADAPTER {
u8 scsih_cb_idx;
u8 ctl_cb_idx;
u8 base_cb_idx;
+ u8 port_enable_cb_idx;
u8 config_cb_idx;
u8 tm_tr_cb_idx;
u8 tm_tr_volume_cb_idx;
u8 tm_sas_control_cb_idx;
struct _internal_cmd base_cmds;
+ struct _internal_cmd port_enable_cmds;
struct _internal_cmd transport_cmds;
struct _internal_cmd scsih_cmds;
struct _internal_cmd tm_cmds;
@@ -896,7 +947,8 @@ struct MPT2SAS_ADAPTER {
Mpi2ReplyDescriptorsUnion_t *reply_post_free;
dma_addr_t reply_post_free_dma;
struct dma_pool *reply_post_free_dma_pool;
- u32 reply_post_host_index;
+ u8 reply_queue_count;
+ struct list_head reply_queue_list;
struct list_head delayed_tr_list;
struct list_head delayed_tr_volume_list;
@@ -940,6 +992,7 @@ void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid);
void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr);
__le32 mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc,
u16 smid);
+void mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc);
/* hi-priority queue */
u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
@@ -960,6 +1013,8 @@ void mpt2sas_base_release_callback_handler(u8 cb_idx);
u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
+u8 mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ u8 msix_index, u32 reply);
void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr);
u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked);
@@ -974,12 +1029,17 @@ void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_ty
void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+ u16 device_missing_delay, u8 io_missing_delay);
+
+int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
+
/* scsih shared API */
u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
u32 reply);
int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- uint channel, uint id, uint lun, u8 type, u16 smid_task,
- ulong timeout, struct scsi_cmnd *scmd);
+ uint channel, uint id, uint lun, u8 type, u16 smid_task,
+ ulong timeout, unsigned long serial_number, enum mutex_type m_type);
void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
@@ -991,6 +1051,8 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAP
struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address(
struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
+void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc);
+
void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
/* config shared API */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
index 6861244..36ea0b2 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -41,7 +41,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -1357,6 +1356,9 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
Mpi2ConfigReply_t mpi_reply;
int r, i, config_page_sz;
u16 ioc_status;
+ int config_num;
+ u16 element_type;
+ u16 phys_disk_dev_handle;
*volume_handle = 0;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
@@ -1372,35 +1374,53 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
if (r)
goto out;
- mpi_request.PageAddress =
- cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
config_page = kmalloc(config_page_sz, GFP_KERNEL);
- if (!config_page)
- goto out;
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- config_page_sz);
- if (r)
+ if (!config_page) {
+ r = -1;
goto out;
-
- r = -1;
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- goto out;
- for (i = 0; i < config_page->NumElements; i++) {
- if ((le16_to_cpu(config_page->ConfigElement[i].ElementFlags) &
- MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) !=
- MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT)
- continue;
- if (le16_to_cpu(config_page->ConfigElement[i].
- PhysDiskDevHandle) == pd_handle) {
- *volume_handle = le16_to_cpu(config_page->
- ConfigElement[i].VolDevHandle);
- r = 0;
+ }
+ config_num = 0xff;
+ while (1) {
+ mpi_request.PageAddress = cpu_to_le32(config_num +
+ MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+ config_page_sz);
+ if (r)
+ goto out;
+ r = -1;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
goto out;
+ for (i = 0; i < config_page->NumElements; i++) {
+ element_type = le16_to_cpu(config_page->
+ ConfigElement[i].ElementFlags) &
+ MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
+ if (element_type ==
+ MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
+ element_type ==
+ MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
+ phys_disk_dev_handle =
+ le16_to_cpu(config_page->ConfigElement[i].
+ PhysDiskDevHandle);
+ if (phys_disk_dev_handle == pd_handle) {
+ *volume_handle =
+ le16_to_cpu(config_page->
+ ConfigElement[i].VolDevHandle);
+ r = 0;
+ goto out;
+ }
+ } else if (element_type ==
+ MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
+ *volume_handle = 0;
+ r = 0;
+ goto out;
+ }
}
+ config_num = config_page->ConfigNum;
}
out:
kfree(config_page);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index d1c3bba..aabcb91 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -994,7 +993,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
mpt2sas_scsih_issue_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
- NULL);
+ 0, TM_MUTEX_ON);
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
} else
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
@@ -1208,6 +1207,9 @@ _ctl_do_reset(void __user *arg)
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
+ if (ioc->shost_recovery || ioc->pci_error_recovery ||
+ ioc->is_driver_loading)
+ return -EAGAIN;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__));
@@ -2179,7 +2181,8 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
!ioc)
return -ENODEV;
- if (ioc->shost_recovery || ioc->pci_error_recovery)
+ if (ioc->shost_recovery || ioc->pci_error_recovery ||
+ ioc->is_driver_loading)
return -EAGAIN;
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
@@ -2298,7 +2301,8 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
- if (ioc->shost_recovery || ioc->pci_error_recovery)
+ if (ioc->shost_recovery || ioc->pci_error_recovery ||
+ ioc->is_driver_loading)
return -EAGAIN;
memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
@@ -2705,6 +2709,33 @@ _ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
_ctl_ioc_reset_count_show, NULL);
+/**
+ * _ctl_ioc_reply_queue_count_show - number of reply queues
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is number of reply queues
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_ioc_reply_queue_count_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 reply_queue_count;
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ if ((ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
+ reply_queue_count = ioc->reply_queue_count;
+ else
+ reply_queue_count = 1;
+ return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
+}
+static DEVICE_ATTR(reply_queue_count, S_IRUGO,
+ _ctl_ioc_reply_queue_count_show, NULL);
+
struct DIAG_BUFFER_START {
__le32 Size;
__le32 DiagVersion;
@@ -2915,6 +2946,7 @@ struct device_attribute *mpt2sas_host_attrs[] = {
&dev_attr_host_trace_buffer_size,
&dev_attr_host_trace_buffer,
&dev_attr_host_trace_buffer_enable,
+ &dev_attr_reply_queue_count,
NULL,
};
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index d6e8353..01780a9 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -41,7 +41,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -72,6 +71,9 @@ static void _firmware_event_work(struct work_struct *work);
static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+static void _scsih_scan_start(struct Scsi_Host *shost);
+static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
+
/* global parameters */
LIST_HEAD(mpt2sas_ioc_list);
@@ -80,6 +82,7 @@ static u8 scsi_io_cb_idx = -1;
static u8 tm_cb_idx = -1;
static u8 ctl_cb_idx = -1;
static u8 base_cb_idx = -1;
+static u8 port_enable_cb_idx = -1;
static u8 transport_cb_idx = -1;
static u8 scsih_cb_idx = -1;
static u8 config_cb_idx = -1;
@@ -94,12 +97,32 @@ static u32 logging_level;
MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
"(default=0)");
+static ushort max_sectors = 0xFFFF;
+module_param(max_sectors, ushort, 0);
+MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192 default=8192");
+
+static int missing_delay[2] = {-1, -1};
+module_param_array(missing_delay, int, NULL, 0);
+MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
+
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
#define MPT2SAS_MAX_LUN (16895)
static int max_lun = MPT2SAS_MAX_LUN;
module_param(max_lun, int, 0);
MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+/* diag_buffer_enable is bitwise
+ * bit 0 set = TRACE
+ * bit 1 set = SNAPSHOT
+ * bit 2 set = EXTENDED
+ *
+ * Either bit can be set, or both
+ */
+static int diag_buffer_enable = -1;
+module_param(diag_buffer_enable, int, 0);
+MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
+ "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
+
/**
* struct sense_info - common structure for obtaining sense keys
* @skey: sense key
@@ -114,8 +137,8 @@ struct sense_info {
#define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC)
-#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
-
+#define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD)
+#define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
/**
* struct fw_event_work - firmware event struct
* @list: link list framework
@@ -369,31 +392,34 @@ _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle,
Mpi2SasDevicePage0_t sas_device_pg0;
Mpi2ConfigReply_t mpi_reply;
u32 ioc_status;
+ *sas_address = 0;
if (handle <= ioc->sas_hba.num_phys) {
*sas_address = ioc->sas_hba.sas_address;
return 0;
- } else
- *sas_address = 0;
+ }
if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
return -ENXIO;
}
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
- "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
- __FILE__, __LINE__, __func__);
- return -EIO;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+ return 0;
}
- *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
- return 0;
+ /* we hit this becuase the given parent handle doesn't exist */
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ return -ENXIO;
+ /* else error case */
+ printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), "
+ "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
+ __FILE__, __LINE__, __func__);
+ return -EIO;
}
/**
@@ -421,7 +447,11 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
u16 slot;
/* only process this function when driver loads */
- if (!ioc->wait_for_port_enable_to_complete)
+ if (!ioc->is_driver_loading)
+ return;
+
+ /* no Bios, return immediately */
+ if (!ioc->bios_pg3.BiosVersion)
return;
if (!is_raid) {
@@ -584,8 +614,15 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
- sas_device->sas_address_parent))
+ sas_device->sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
+ } else if (!sas_device->starget) {
+ if (!ioc->is_driver_loading)
+ mpt2sas_transport_port_remove(ioc,
+ sas_device->sas_address,
+ sas_device->sas_address_parent);
+ _scsih_sas_device_remove(ioc, sas_device);
+ }
}
/**
@@ -1397,6 +1434,10 @@ _scsih_slave_destroy(struct scsi_device *sdev)
{
struct MPT2SAS_TARGET *sas_target_priv_data;
struct scsi_target *starget;
+ struct Scsi_Host *shost;
+ struct MPT2SAS_ADAPTER *ioc;
+ struct _sas_device *sas_device;
+ unsigned long flags;
if (!sdev->hostdata)
return;
@@ -1404,6 +1445,19 @@ _scsih_slave_destroy(struct scsi_device *sdev)
starget = scsi_target(sdev);
sas_target_priv_data = starget->hostdata;
sas_target_priv_data->num_luns--;
+
+ shost = dev_to_shost(&starget->dev);
+ ioc = shost_priv(shost);
+
+ if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_target_priv_data->sas_address);
+ if (sas_device)
+ sas_device->starget = NULL;
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ }
+
kfree(sdev->hostdata);
sdev->hostdata = NULL;
}
@@ -1595,8 +1649,10 @@ _scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device)
* _scsih_get_volume_capabilities - volume capabilities
* @ioc: per adapter object
* @sas_device: the raid_device object
+ *
+ * Returns 0 for success, else 1
*/
-static void
+static int
_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
struct _raid_device *raid_device)
{
@@ -1609,9 +1665,10 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
&num_pds)) || !num_pds) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+ __func__));
+ return 1;
}
raid_device->num_pds = num_pds;
@@ -1619,17 +1676,19 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
sizeof(Mpi2RaidVol0PhysDisk_t));
vol_pg0 = kzalloc(sz, GFP_KERNEL);
if (!vol_pg0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+ __func__));
+ return 1;
}
if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+ __func__));
kfree(vol_pg0);
- return;
+ return 1;
}
raid_device->volume_type = vol_pg0->VolumeType;
@@ -1649,6 +1708,7 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
}
kfree(vol_pg0);
+ return 0;
}
/**
* _scsih_disable_ddio - Disable direct I/O for all the volumes
@@ -1919,13 +1979,20 @@ _scsih_slave_configure(struct scsi_device *sdev)
sas_target_priv_data->handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return 0;
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+ __LINE__, __func__));
+ return 1;
}
_scsih_get_volume_capabilities(ioc, raid_device);
+ if (_scsih_get_volume_capabilities(ioc, raid_device)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+ __LINE__, __func__));
+ return 1;
+ }
/*
* WARPDRIVE: Initialize the required data for Direct IO
*/
@@ -1999,11 +2066,22 @@ _scsih_slave_configure(struct scsi_device *sdev)
if (sas_device) {
if (sas_target_priv_data->flags &
MPT_TARGET_FLAGS_RAID_COMPONENT) {
- mpt2sas_config_get_volume_handle(ioc,
- sas_device->handle, &sas_device->volume_handle);
- mpt2sas_config_get_volume_wwid(ioc,
+ if (mpt2sas_config_get_volume_handle(ioc,
+ sas_device->handle, &sas_device->volume_handle)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__));
+ return 1;
+ }
+ if (sas_device->volume_handle &&
+ mpt2sas_config_get_volume_wwid(ioc,
sas_device->volume_handle,
- &sas_device->volume_wwid);
+ &sas_device->volume_wwid)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__));
+ return 1;
+ }
}
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
@@ -2032,6 +2110,11 @@ _scsih_slave_configure(struct scsi_device *sdev)
if (!ssp_target)
_scsih_display_sata_capabilities(ioc, sas_device, sdev);
+ } else {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+ __func__));
+ return 1;
}
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
@@ -2158,6 +2241,7 @@ _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
return 1;
if (ioc->tm_cmds.smid != smid)
return 1;
+ mpt2sas_base_flush_reply_queues(ioc);
ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
if (mpi_reply) {
@@ -2236,6 +2320,8 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
* @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
* @smid_task: smid assigned to the task
* @timeout: timeout in seconds
+ * @serial_number: the serial_number from scmd
+ * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
* Context: user
*
* A generic API for sending task management requests to firmware.
@@ -2247,17 +2333,18 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
int
mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
- struct scsi_cmnd *scmd)
+ unsigned long serial_number, enum mutex_type m_type)
{
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
u16 smid = 0;
u32 ioc_state;
unsigned long timeleft;
- struct scsi_cmnd *scmd_lookup;
+ struct scsiio_tracker *scsi_lookup = NULL;
int rc;
- mutex_lock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_lock(&ioc->tm_cmds.mutex);
if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
__func__, ioc->name);
@@ -2277,18 +2364,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
if (ioc_state & MPI2_DOORBELL_USED) {
dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
"active!\n", ioc->name));
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
goto err_out;
}
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
mpt2sas_base_fault_info(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
goto err_out;
}
@@ -2300,6 +2387,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
goto err_out;
}
+ if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+ scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
+
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
" task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
smid_task));
@@ -2307,6 +2397,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
ioc->tm_cmds.smid = smid;
memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+ memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = type;
@@ -2322,9 +2413,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
_debug_dump_mf(mpi_request,
sizeof(Mpi2SCSITaskManagementRequest_t)/4);
if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
mpt2sas_scsih_clear_tm_flag(ioc, handle);
goto err_out;
@@ -2346,20 +2437,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
}
}
- /* sanity check:
- * Check to see the commands were terminated.
- * This is only needed for eh callbacks, hence the scmd check.
- */
- rc = FAILED;
- if (scmd == NULL)
- goto bypass_sanity_checks;
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
- scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task);
- if (scmd_lookup)
- rc = FAILED;
- else
- rc = SUCCESS;
+ rc = SUCCESS;
+ if (scsi_lookup->scmd == NULL)
+ break;
+ rc = FAILED;
break;
case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2369,24 +2452,31 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
rc = SUCCESS;
break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
rc = FAILED;
else
rc = SUCCESS;
break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+ rc = SUCCESS;
+ break;
+ default:
+ rc = FAILED;
+ break;
}
- bypass_sanity_checks:
-
mpt2sas_scsih_clear_tm_flag(ioc, handle);
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_unlock(&ioc->tm_cmds.mutex);
return rc;
err_out:
- mutex_unlock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_unlock(&ioc->tm_cmds.mutex);
return rc;
}
@@ -2496,7 +2586,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
handle = sas_device_priv_data->sas_target->handle;
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd);
+ MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+ scmd->serial_number, TM_MUTEX_ON);
out:
sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
@@ -2557,7 +2648,8 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd);
+ MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
+ TM_MUTEX_ON);
out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
@@ -2617,7 +2709,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
- 30, scmd);
+ 30, 0, TM_MUTEX_ON);
out:
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
@@ -2702,22 +2794,43 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
/**
- * _scsih_queue_rescan - queue a topology rescan from user context
+ * _scsih_error_recovery_delete_devices - remove devices not responding
* @ioc: per adapter object
*
* Return nothing.
*/
static void
-_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
+_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
{
struct fw_event_work *fw_event;
- if (ioc->wait_for_port_enable_to_complete)
+ if (ioc->is_driver_loading)
return;
+
fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
if (!fw_event)
return;
- fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
+
+ fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
+ fw_event->ioc = ioc;
+ _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * mpt2sas_port_enable_complete - port enable completed (fake event)
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct fw_event_work *fw_event;
+
+ fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+ if (!fw_event)
+ return;
+ fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
fw_event->ioc = ioc;
_scsih_fw_event_add(ioc, fw_event);
}
@@ -2750,6 +2863,31 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
}
/**
+ * _scsih_ublock_io_all_device - unblock every device
+ * @ioc: per adapter object
+ *
+ * change the device state from block to running
+ */
+static void
+_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (!sas_device_priv_data->block)
+ continue;
+ sas_device_priv_data->block = 0;
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle));
+ scsi_internal_device_unblock(sdev);
+ }
+}
+/**
* _scsih_ublock_io_device - set the device state to SDEV_RUNNING
* @ioc: per adapter object
* @handle: device handle
@@ -2779,6 +2917,34 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
}
/**
+ * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (sas_device_priv_data->block)
+ continue;
+ sas_device_priv_data->block = 1;
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle));
+ scsi_internal_device_block(sdev);
+ }
+}
+
+
+/**
* _scsih_block_io_device - set the device state to SDEV_BLOCK
* @ioc: per adapter object
* @handle: device handle
@@ -2912,14 +3078,27 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
Mpi2SCSITaskManagementRequest_t *mpi_request;
u16 smid;
struct _sas_device *sas_device;
- struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
+ u64 sas_address = 0;
unsigned long flags;
struct _tr_list *delayed_tr;
+ u32 ioc_state;
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
- "progress!\n", __func__, ioc->name));
+ if (ioc->remove_host) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
+ "removed: handle(0x%04x)\n", __func__, ioc->name, handle));
+ return;
+ } else if (ioc->pci_error_recovery) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
+ "error recovery: handle(0x%04x)\n", __func__, ioc->name,
+ handle));
+ return;
+ }
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
+ "operational: handle(0x%04x)\n", __func__, ioc->name,
+ handle));
return;
}
@@ -2933,13 +3112,18 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
sas_device->starget->hostdata) {
sas_target_priv_data = sas_device->starget->hostdata;
sas_target_priv_data->deleted = 1;
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "setting delete flag: handle(0x%04x), "
- "sas_addr(0x%016llx)\n", ioc->name, handle,
- (unsigned long long) sas_device->sas_address));
+ sas_address = sas_device->sas_address;
}
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_target_priv_data) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
+ "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
+ (unsigned long long)sas_address));
+ _scsih_ublock_io_device(ioc, handle);
+ sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
+ }
+
smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
if (!smid) {
delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
@@ -3120,11 +3304,21 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
mpt2sas_base_get_reply_virt_addr(ioc, reply);
Mpi2SasIoUnitControlRequest_t *mpi_request;
u16 smid_sas_ctrl;
+ u32 ioc_state;
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
- "progress!\n", __func__, ioc->name));
+ if (ioc->remove_host) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
+ "removed\n", __func__, ioc->name));
+ return 1;
+ } else if (ioc->pci_error_recovery) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
+ "error recovery\n", __func__, ioc->name));
+ return 1;
+ }
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
+ "operational\n", __func__, ioc->name));
return 1;
}
@@ -4189,6 +4383,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
u32 log_info;
struct MPT2SAS_DEVICE *sas_device_priv_data;
u32 response_code = 0;
+ unsigned long flags;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
@@ -4213,6 +4408,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
* the failed direct I/O should be redirected to volume
*/
if (_scsih_scsi_direct_io_get(ioc, smid)) {
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ ioc->scsi_lookup[smid - 1].scmd = scmd;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
_scsih_scsi_direct_io_set(ioc, smid, 0);
memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
mpi_request->DevHandle =
@@ -5026,7 +5224,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
/* get device name */
sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
- if (ioc->wait_for_port_enable_to_complete)
+ if (ioc->wait_for_discovery_to_complete)
_scsih_sas_device_init_add(ioc, sas_device);
else
_scsih_sas_device_add(ioc, sas_device);
@@ -5062,6 +5260,9 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
if (sas_device_backup.starget && sas_device_backup.starget->hostdata) {
sas_target_priv_data = sas_device_backup.starget->hostdata;
sas_target_priv_data->deleted = 1;
+ _scsih_ublock_io_device(ioc, sas_device_backup.handle);
+ sas_target_priv_data->handle =
+ MPT2SAS_INVALID_DEVICE_HANDLE;
}
_scsih_ublock_io_device(ioc, sas_device_backup.handle);
@@ -5215,7 +5416,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
_scsih_sas_topology_change_event_debug(ioc, event_data);
#endif
- if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
+ if (ioc->remove_host || ioc->pci_error_recovery)
return;
if (!ioc->sas_hba.num_phys)
@@ -5276,6 +5477,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
switch (reason_code) {
case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
+ if (ioc->shost_recovery)
+ break;
+
if (link_rate == prev_link_rate)
break;
@@ -5289,6 +5493,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
break;
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
+ if (ioc->shost_recovery)
+ break;
+
mpt2sas_transport_update_links(ioc, sas_address,
handle, phy_number, link_rate);
@@ -5376,9 +5583,10 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
break;
}
printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
- "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
- reason_str, le16_to_cpu(event_data->DevHandle),
- (unsigned long long)le64_to_cpu(event_data->SASAddress));
+ "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
+ ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
+ (unsigned long long)le64_to_cpu(event_data->SASAddress),
+ le16_to_cpu(event_data->TaskTag));
if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
event_data->ASC, event_data->ASCQ);
@@ -5518,25 +5726,38 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
u32 termination_count;
u32 query_count;
Mpi2SCSITaskManagementReply_t *mpi_reply;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
-#endif
u16 ioc_status;
unsigned long flags;
int r;
+ u8 max_retries = 0;
+ u8 task_abort_retries;
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: "
- "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
- event_data->PortWidth));
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
+ mutex_lock(&ioc->tm_cmds.mutex);
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
+ "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
+ event_data->PortWidth));
+
+ _scsih_block_io_all_device(ioc);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- ioc->broadcast_aen_busy = 0;
+ mpi_reply = ioc->tm_cmds.reply;
+broadcast_aen_retry:
+
+ /* sanity checks for retrying this loop */
+ if (max_retries++ == 5) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
+ ioc->name, __func__));
+ goto out;
+ } else if (max_retries > 1)
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
+ ioc->name, __func__, max_retries - 1));
+
termination_count = 0;
query_count = 0;
- mpi_reply = ioc->tm_cmds.reply;
for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+ if (ioc->shost_recovery)
+ goto out;
scmd = _scsih_scsi_lookup_get(ioc, smid);
if (!scmd)
continue;
@@ -5557,34 +5778,90 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
lun = sas_device_priv_data->lun;
query_count++;
+ if (ioc->shost_recovery)
+ goto out;
+
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
- MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL);
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
+ MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
+ TM_MUTEX_OFF);
+ if (r == FAILED) {
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: FAILED when sending "
+ "QUERY_TASK: scmd(%p)\n", scmd);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
& MPI2_IOCSTATUS_MASK;
- if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
- (mpi_reply->ResponseCode ==
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
+ "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
+ scmd);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
+
+ /* see if IO is still owned by IOC and target */
+ if (mpi_reply->ResponseCode ==
MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
mpi_reply->ResponseCode ==
- MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) {
+ MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
continue;
}
+ task_abort_retries = 0;
+ tm_retry:
+ if (task_abort_retries++ == 60) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "%s: ABORT_TASK: giving up\n", ioc->name,
+ __func__));
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
+
+ if (ioc->shost_recovery)
+ goto out_no_lock;
+
r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
- scmd);
- if (r == FAILED)
- sdev_printk(KERN_WARNING, sdev, "task abort: FAILED "
+ scmd->serial_number, TM_MUTEX_OFF);
+ if (r == FAILED) {
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
"scmd(%p)\n", scmd);
+ goto tm_retry;
+ }
+
+ if (task_abort_retries > 1)
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
+ " scmd(%p)\n",
+ task_abort_retries - 1, scmd);
+
termination_count += le32_to_cpu(mpi_reply->TerminationCount);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
}
+
+ if (ioc->broadcast_aen_pending) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
+ " pending AEN\n", ioc->name, __func__));
+ ioc->broadcast_aen_pending = 0;
+ goto broadcast_aen_retry;
+ }
+
+ out:
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ out_no_lock:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"%s - exit, query_count = %d termination_count = %d\n",
ioc->name, __func__, query_count, termination_count));
+
+ ioc->broadcast_aen_busy = 0;
+ if (!ioc->shost_recovery)
+ _scsih_ublock_io_all_device(ioc);
+ mutex_unlock(&ioc->tm_cmds.mutex);
}
/**
@@ -5646,8 +5923,11 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
static void
_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
{
- struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ if (starget == NULL)
+ return;
+ sas_target_priv_data = starget->hostdata;
if (no_uld_attach)
sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
else
@@ -5702,7 +5982,7 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
raid_device->handle = handle;
raid_device->wwid = wwid;
_scsih_raid_device_add(ioc, raid_device);
- if (!ioc->wait_for_port_enable_to_complete) {
+ if (!ioc->wait_for_discovery_to_complete) {
rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
raid_device->id, 0);
if (rc)
@@ -5984,6 +6264,10 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
_scsih_sas_ir_config_change_event_debug(ioc, event_data);
#endif
+
+ if (ioc->shost_recovery)
+ return;
+
foreign_config = (le32_to_cpu(event_data->Flags) &
MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
@@ -6042,6 +6326,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
int rc;
Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+ if (ioc->shost_recovery)
+ return;
+
if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
return;
@@ -6124,6 +6411,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
u64 sas_address;
+ if (ioc->shost_recovery)
+ return;
+
if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
return;
@@ -6367,10 +6657,10 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
u32 device_info;
u16 slot;
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+ printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
if (list_empty(&ioc->sas_device_list))
- return;
+ goto out;
handle = 0xFFFF;
while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
@@ -6389,6 +6679,9 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
_scsih_mark_responding_sas_device(ioc, sas_address, slot,
handle);
}
+out:
+ printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
+ ioc->name);
}
/**
@@ -6465,10 +6758,14 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
u16 handle;
u8 phys_disk_num;
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+ if (!ioc->ir_firmware)
+ return;
+
+ printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
+ ioc->name);
if (list_empty(&ioc->raid_device_list))
- return;
+ goto out;
handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
@@ -6507,6 +6804,9 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
set_bit(handle, ioc->pd_handles);
}
}
+out:
+ printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
+ "complete\n", ioc->name);
}
/**
@@ -6566,10 +6866,10 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
u64 sas_address;
u16 handle;
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+ printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
if (list_empty(&ioc->sas_expander_list))
- return;
+ goto out;
handle = 0xFFFF;
while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
@@ -6588,6 +6888,8 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
_scsih_mark_responding_expander(ioc, sas_address, handle);
}
+ out:
+ printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
}
/**
@@ -6603,6 +6905,8 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
struct _sas_node *sas_expander;
struct _raid_device *raid_device, *raid_device_next;
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
+ ioc->name);
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
@@ -6622,6 +6926,9 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
_scsih_remove_device(ioc, sas_device);
}
+ if (!ioc->ir_firmware)
+ goto retry_expander_search;
+
list_for_each_entry_safe(raid_device, raid_device_next,
&ioc->raid_device_list, list) {
if (raid_device->responding) {
@@ -6648,52 +6955,282 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
mpt2sas_expander_remove(ioc, sas_expander->sas_address);
goto retry_expander_search;
}
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
+ ioc->name);
+ /* unblock devices */
+ _scsih_ublock_io_all_device(ioc);
+}
+
+static void
+_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_node *sas_expander, u16 handle)
+{
+ Mpi2ExpanderPage1_t expander_pg1;
+ Mpi2ConfigReply_t mpi_reply;
+ int i;
+
+ for (i = 0 ; i < sas_expander->num_phys ; i++) {
+ if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
+ &expander_pg1, i, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
+ le16_to_cpu(expander_pg1.AttachedDevHandle), i,
+ expander_pg1.NegotiatedLinkRate >> 4);
+ }
}
/**
- * _scsih_hide_unhide_sas_devices - add/remove device to/from OS
+ * _scsih_scan_for_devices_after_reset - scan for devices after host reset
* @ioc: per adapter object
*
* Return nothing.
*/
static void
-_scsih_hide_unhide_sas_devices(struct MPT2SAS_ADAPTER *ioc)
+_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
{
- struct _sas_device *sas_device, *sas_device_next;
+ Mpi2ExpanderPage0_t expander_pg0;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ Mpi2RaidVolPage1_t volume_pg1;
+ Mpi2RaidVolPage0_t volume_pg0;
+ Mpi2RaidPhysDiskPage0_t pd_pg0;
+ Mpi2EventIrConfigElement_t element;
+ Mpi2ConfigReply_t mpi_reply;
+ u8 phys_disk_num;
+ u16 ioc_status;
+ u16 handle, parent_handle;
+ u64 sas_address;
+ struct _sas_device *sas_device;
+ struct _sas_node *expander_device;
+ static struct _raid_device *raid_device;
+ u8 retry_count;
- if (!ioc->is_warpdrive || ioc->mfg_pg10_hide_flag !=
- MFG_PAGE10_HIDE_IF_VOL_PRESENT)
- return;
+ printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
- if (ioc->hide_drives) {
- if (_scsih_get_num_volumes(ioc))
- return;
- ioc->hide_drives = 0;
- list_for_each_entry_safe(sas_device, sas_device_next,
- &ioc->sas_device_list, list) {
- if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
- sas_device->sas_address_parent)) {
- _scsih_sas_device_remove(ioc, sas_device);
- } else if (!sas_device->starget) {
- mpt2sas_transport_port_remove(ioc,
- sas_device->sas_address,
- sas_device->sas_address_parent);
- _scsih_sas_device_remove(ioc, sas_device);
+ _scsih_sas_host_refresh(ioc);
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n",
+ ioc->name);
+ /* expanders */
+ handle = 0xFFFF;
+ while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+ MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
+ handle = le16_to_cpu(expander_pg0.DevHandle);
+ expander_device = mpt2sas_scsih_expander_find_by_sas_address(
+ ioc, le64_to_cpu(expander_pg0.SASAddress));
+ if (expander_device)
+ _scsih_refresh_expander_links(ioc, expander_device,
+ handle);
+ else {
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(expander_pg0.SASAddress));
+ _scsih_expander_add(ioc, handle);
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(expander_pg0.SASAddress));
+ }
+ }
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n",
+ ioc->name);
+
+ if (!ioc->ir_firmware)
+ goto skip_to_sas;
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name);
+ /* phys disk */
+ phys_disk_num = 0xFF;
+ while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+ &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
+ phys_disk_num))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:"
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
+ phys_disk_num = pd_pg0.PhysDiskNum;
+ handle = le16_to_cpu(pd_pg0.DevHandle);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device)
+ continue;
+ if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+ &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+ handle) != 0)
+ continue;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
+ parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+ if (!_scsih_get_sas_address(ioc, parent_handle,
+ &sas_address)) {
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: "
+ " handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
+ mpt2sas_transport_update_links(ioc, sas_address,
+ handle, sas_device_pg0.PhyNum,
+ MPI2_SAS_NEG_LINK_RATE_1_5);
+ set_bit(handle, ioc->pd_handles);
+ retry_count = 0;
+ /* This will retry adding the end device.
+ * _scsih_add_device() will decide on retries and
+ * return "1" when it should be retried
+ */
+ while (_scsih_add_device(ioc, handle, retry_count++,
+ 1)) {
+ ssleep(1);
}
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: "
+ " handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
}
- } else {
- if (!_scsih_get_num_volumes(ioc))
- return;
- ioc->hide_drives = 1;
- list_for_each_entry_safe(sas_device, sas_device_next,
- &ioc->sas_device_list, list) {
- mpt2sas_transport_port_remove(ioc,
- sas_device->sas_address,
- sas_device->sas_address_parent);
+ }
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n",
+ ioc->name);
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name);
+ /* volumes */
+ handle = 0xFFFF;
+ while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+ &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
+ handle = le16_to_cpu(volume_pg1.DevHandle);
+ raid_device = _scsih_raid_device_find_by_wwid(ioc,
+ le64_to_cpu(volume_pg1.WWID));
+ if (raid_device)
+ continue;
+ if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
+ &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+ sizeof(Mpi2RaidVolPage0_t)))
+ continue;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
+ if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
+ volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
+ volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
+ memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
+ element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
+ element.VolDevHandle = volume_pg1.DevHandle;
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: "
+ " handle (0x%04x)\n", ioc->name,
+ volume_pg1.DevHandle);
+ _scsih_sas_volume_add(ioc, &element);
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: "
+ " handle (0x%04x)\n", ioc->name,
+ volume_pg1.DevHandle);
}
}
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n",
+ ioc->name);
+
+ skip_to_sas:
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n",
+ ioc->name);
+ /* sas devices */
+ handle = 0xFFFF;
+ while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+ &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
+ handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:"
+ " ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
+ handle = le16_to_cpu(sas_device_pg0.DevHandle);
+ if (!(_scsih_is_end_device(
+ le32_to_cpu(sas_device_pg0.DeviceInfo))))
+ continue;
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ le64_to_cpu(sas_device_pg0.SASAddress));
+ if (sas_device)
+ continue;
+ parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+ if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
+ mpt2sas_transport_update_links(ioc, sas_address, handle,
+ sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+ retry_count = 0;
+ /* This will retry adding the end device.
+ * _scsih_add_device() will decide on retries and
+ * return "1" when it should be retried
+ */
+ while (_scsih_add_device(ioc, handle, retry_count++,
+ 0)) {
+ ssleep(1);
+ }
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
+ }
+ }
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n",
+ ioc->name);
+
+ printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
}
+
/**
* mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
* @ioc: per adapter object
@@ -6729,7 +7266,6 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
}
_scsih_fw_event_cleanup_queue(ioc);
_scsih_flush_running_cmds(ioc);
- _scsih_queue_rescan(ioc);
break;
case MPT2_IOC_DONE_RESET:
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
@@ -6739,6 +7275,13 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
_scsih_search_responding_sas_devices(ioc);
_scsih_search_responding_raid_devices(ioc);
_scsih_search_responding_expanders(ioc);
+ if (!ioc->is_driver_loading) {
+ _scsih_prep_device_scan(ioc);
+ _scsih_search_responding_sas_devices(ioc);
+ _scsih_search_responding_raid_devices(ioc);
+ _scsih_search_responding_expanders(ioc);
+ _scsih_error_recovery_delete_devices(ioc);
+ }
break;
}
}
@@ -6756,7 +7299,6 @@ _firmware_event_work(struct work_struct *work)
{
struct fw_event_work *fw_event = container_of(work,
struct fw_event_work, delayed_work.work);
- unsigned long flags;
struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
/* the queue is being flushed so ignore this event */
@@ -6766,23 +7308,23 @@ _firmware_event_work(struct work_struct *work)
return;
}
- if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
- _scsih_fw_event_free(ioc, fw_event);
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery) {
- init_completion(&ioc->shost_recovery_done);
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
- flags);
- wait_for_completion(&ioc->shost_recovery_done);
- } else
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
- flags);
+ switch (fw_event->event) {
+ case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
+ while (scsi_host_in_recovery(ioc->shost))
+ ssleep(1);
_scsih_remove_unresponding_sas_devices(ioc);
- _scsih_hide_unhide_sas_devices(ioc);
- return;
- }
+ _scsih_scan_for_devices_after_reset(ioc);
+ break;
+ case MPT2SAS_PORT_ENABLE_COMPLETE:
+ ioc->start_scan = 0;
- switch (fw_event->event) {
+ if (missing_delay[0] != -1 && missing_delay[1] != -1)
+ mpt2sas_base_update_missing_delay(ioc, missing_delay[0],
+ missing_delay[1]);
+
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
+ "from worker thread\n", ioc->name));
+ break;
case MPT2SAS_TURN_ON_FAULT_LED:
_scsih_turn_on_fault_led(ioc, fw_event->device_handle);
break;
@@ -6859,10 +7401,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
mpi_reply->EventData;
if (baen_data->Primitive !=
- MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
- ioc->broadcast_aen_busy)
+ MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
return 1;
- ioc->broadcast_aen_busy = 1;
+
+ if (ioc->broadcast_aen_busy) {
+ ioc->broadcast_aen_pending++;
+ return 1;
+ } else
+ ioc->broadcast_aen_busy = 1;
break;
}
@@ -6975,6 +7521,8 @@ static struct scsi_host_template scsih_driver_template = {
.slave_configure = _scsih_slave_configure,
.target_destroy = _scsih_target_destroy,
.slave_destroy = _scsih_slave_destroy,
+ .scan_finished = _scsih_scan_finished,
+ .scan_start = _scsih_scan_start,
.change_queue_depth = _scsih_change_queue_depth,
.change_queue_type = _scsih_change_queue_type,
.eh_abort_handler = _scsih_abort,
@@ -7235,7 +7783,12 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
unsigned long flags;
int rc;
+ /* no Bios, return immediately */
+ if (!ioc->bios_pg3.BiosVersion)
+ return;
+
device = NULL;
+ is_raid = 0;
if (ioc->req_boot_device.device) {
device = ioc->req_boot_device.device;
is_raid = ioc->req_boot_device.is_raid;
@@ -7271,8 +7824,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
sas_device->sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
} else if (!sas_device->starget) {
- mpt2sas_transport_port_remove(ioc, sas_address,
- sas_address_parent);
+ if (!ioc->is_driver_loading)
+ mpt2sas_transport_port_remove(ioc, sas_address,
+ sas_address_parent);
_scsih_sas_device_remove(ioc, sas_device);
}
}
@@ -7326,9 +7880,10 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
kfree(sas_device);
continue;
} else if (!sas_device->starget) {
- mpt2sas_transport_port_remove(ioc,
- sas_device->sas_address,
- sas_device->sas_address_parent);
+ if (!ioc->is_driver_loading)
+ mpt2sas_transport_port_remove(ioc,
+ sas_device->sas_address,
+ sas_device->sas_address_parent);
list_del(&sas_device->list);
kfree(sas_device);
continue;
@@ -7349,9 +7904,7 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
static void
_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
{
- u16 volume_mapping_flags =
- le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
- MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+ u16 volume_mapping_flags;
if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
return; /* return when IOC doesn't support initiator mode */
@@ -7359,18 +7912,93 @@ _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
_scsih_probe_boot_devices(ioc);
if (ioc->ir_firmware) {
- if ((volume_mapping_flags &
- MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) {
- _scsih_probe_sas(ioc);
+ volume_mapping_flags =
+ le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
+ MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+ if (volume_mapping_flags ==
+ MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
_scsih_probe_raid(ioc);
+ _scsih_probe_sas(ioc);
} else {
- _scsih_probe_raid(ioc);
_scsih_probe_sas(ioc);
+ _scsih_probe_raid(ioc);
}
} else
_scsih_probe_sas(ioc);
}
+
+/**
+ * _scsih_scan_start - scsi lld callback for .scan_start
+ * @shost: SCSI host pointer
+ *
+ * The shost has the ability to discover targets on its own instead
+ * of scanning the entire bus. In our implemention, we will kick off
+ * firmware discovery.
+ */
+static void
+_scsih_scan_start(struct Scsi_Host *shost)
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ int rc;
+
+ if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
+ mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
+
+ ioc->start_scan = 1;
+ rc = mpt2sas_port_enable(ioc);
+
+ if (rc != 0)
+ printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
+}
+
+/**
+ * _scsih_scan_finished - scsi lld callback for .scan_finished
+ * @shost: SCSI host pointer
+ * @time: elapsed time of the scan in jiffies
+ *
+ * This function will be called periodically until it returns 1 with the
+ * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
+ * we wait for firmware discovery to complete, then return 1.
+ */
+static int
+_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ if (time >= (300 * HZ)) {
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
+ "(timeout=300s)\n", ioc->name);
+ ioc->is_driver_loading = 0;
+ return 1;
+ }
+
+ if (ioc->start_scan)
+ return 0;
+
+ if (ioc->start_scan_failed) {
+ printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
+ "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
+ ioc->is_driver_loading = 0;
+ ioc->wait_for_discovery_to_complete = 0;
+ ioc->remove_host = 1;
+ return 1;
+ }
+
+ printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+
+ if (ioc->wait_for_discovery_to_complete) {
+ ioc->wait_for_discovery_to_complete = 0;
+ _scsih_probe_devices(ioc);
+ }
+ mpt2sas_base_start_watchdog(ioc);
+ ioc->is_driver_loading = 0;
+ return 1;
+}
+
+
/**
* _scsih_probe - attach and add scsi host
* @pdev: PCI device struct
@@ -7407,6 +8035,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->tm_cb_idx = tm_cb_idx;
ioc->ctl_cb_idx = ctl_cb_idx;
ioc->base_cb_idx = base_cb_idx;
+ ioc->port_enable_cb_idx = port_enable_cb_idx;
ioc->transport_cb_idx = transport_cb_idx;
ioc->scsih_cb_idx = scsih_cb_idx;
ioc->config_cb_idx = config_cb_idx;
@@ -7438,6 +8067,25 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
shost->transportt = mpt2sas_transport_template;
shost->unique_id = ioc->id;
+ if (max_sectors != 0xFFFF) {
+ if (max_sectors < 64) {
+ shost->max_sectors = 64;
+ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+ "for max_sectors, range is 64 to 8192. Assigning "
+ "value of 64.\n", ioc->name, max_sectors);
+ } else if (max_sectors > 8192) {
+ shost->max_sectors = 8192;
+ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+ "for max_sectors, range is 64 to 8192. Assigning "
+ "default value of 8192.\n", ioc->name,
+ max_sectors);
+ } else {
+ shost->max_sectors = max_sectors & 0xFFFE;
+ printk(MPT2SAS_INFO_FMT "The max_sectors value is "
+ "set to %d\n", ioc->name, shost->max_sectors);
+ }
+ }
+
if ((scsi_add_host(shost, &pdev->dev))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -7460,14 +8108,13 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_thread_fail;
}
- ioc->wait_for_port_enable_to_complete = 1;
+ ioc->is_driver_loading = 1;
if ((mpt2sas_base_attach(ioc))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
goto out_attach_fail;
}
- ioc->wait_for_port_enable_to_complete = 0;
if (ioc->is_warpdrive) {
if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
ioc->hide_drives = 0;
@@ -7481,8 +8128,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
} else
ioc->hide_drives = 0;
+ scsi_scan_host(shost);
- _scsih_probe_devices(ioc);
return 0;
out_attach_fail:
@@ -7490,6 +8137,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_thread_fail:
list_del(&ioc->list);
scsi_remove_host(shost);
+ scsi_host_put(shost);
out_add_shost_fail:
return -ENODEV;
}
@@ -7518,7 +8166,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
mpt2sas_base_free_resources(ioc);
pci_save_state(pdev);
- pci_disable_device(pdev);
pci_set_power_state(pdev, device_state);
return 0;
}
@@ -7736,6 +8383,8 @@ _scsih_init(void)
/* base internal commands callback handler */
base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
+ port_enable_cb_idx = mpt2sas_base_register_callback_handler(
+ mpt2sas_port_enable_done);
/* transport internal commands callback handler */
transport_cb_idx = mpt2sas_base_register_callback_handler(
@@ -7790,6 +8439,7 @@ _scsih_exit(void)
mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
mpt2sas_base_release_callback_handler(tm_cb_idx);
mpt2sas_base_release_callback_handler(base_cb_idx);
+ mpt2sas_base_release_callback_handler(port_enable_cb_idx);
mpt2sas_base_release_callback_handler(transport_cb_idx);
mpt2sas_base_release_callback_handler(scsih_cb_idx);
mpt2sas_base_release_callback_handler(config_cb_idx);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index 15c7980..2307322 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -163,7 +163,7 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
return -EIO;
}
- memset(identify, 0, sizeof(identify));
+ memset(identify, 0, sizeof(*identify));
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
/* sas_address */
diff --git a/drivers/scsi/mvsas/Kconfig b/drivers/scsi/mvsas/Kconfig
index c82b012..78f7e20 100644
--- a/drivers/scsi/mvsas/Kconfig
+++ b/drivers/scsi/mvsas/Kconfig
@@ -3,7 +3,7 @@
#
# Copyright 2007 Red Hat, Inc.
# Copyright 2008 Marvell. <kewei@marvell.com>
-# Copyright 2009-20011 Marvell. <yuxiangl@marvell.com>
+# Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
#
# This file is licensed under GPLv2.
#
@@ -41,3 +41,10 @@ config SCSI_MVSAS_DEBUG
help
Compiles the 88SE64XX/88SE94XX driver in debug mode. In debug mode,
the driver prints some messages to the console.
+config SCSI_MVSAS_TASKLET
+ bool "Support for interrupt tasklet"
+ default n
+ depends on SCSI_MVSAS
+ help
+ Compiles the 88SE64xx/88SE94xx driver in interrupt tasklet mode.In this mode,
+ the interrupt will schedule a tasklet.
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c
index 13c9604..8ba4722 100644
--- a/drivers/scsi/mvsas/mv_64xx.c
+++ b/drivers/scsi/mvsas/mv_64xx.c
@@ -33,7 +33,6 @@ static void mvs_64xx_detect_porttype(struct mvs_info *mvi, int i)
u32 reg;
struct mvs_phy *phy = &mvi->phy[i];
- /* TODO check & save device type */
reg = mr32(MVS_GBL_PORT_TYPE);
phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
if (reg & MODE_SAS_SATA & (1 << i))
@@ -48,7 +47,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
u32 tmp;
tmp = mr32(MVS_PCS);
- if (mvi->chip->n_phy <= 4)
+ if (mvi->chip->n_phy <= MVS_SOC_PORTS)
tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT);
else
tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2);
@@ -58,24 +57,16 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
{
void __iomem *regs = mvi->regs;
+ int i;
mvs_phy_hacks(mvi);
if (!(mvi->flags & MVF_FLAG_SOC)) {
- /* TEST - for phy decoding error, adjust voltage levels */
- mw32(MVS_P0_VSR_ADDR + 0, 0x8);
- mw32(MVS_P0_VSR_DATA + 0, 0x2F0);
-
- mw32(MVS_P0_VSR_ADDR + 8, 0x8);
- mw32(MVS_P0_VSR_DATA + 8, 0x2F0);
-
- mw32(MVS_P0_VSR_ADDR + 16, 0x8);
- mw32(MVS_P0_VSR_DATA + 16, 0x2F0);
-
- mw32(MVS_P0_VSR_ADDR + 24, 0x8);
- mw32(MVS_P0_VSR_DATA + 24, 0x2F0);
+ for (i = 0; i < MVS_SOC_PORTS; i++) {
+ mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE8);
+ mvs_write_port_vsr_data(mvi, i, 0x2F0);
+ }
} else {
- int i;
/* disable auto port detection */
mw32(MVS_GBL_PORT_TYPE, 0);
for (i = 0; i < mvi->chip->n_phy; i++) {
@@ -95,7 +86,7 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id)
u32 reg, tmp;
if (!(mvi->flags & MVF_FLAG_SOC)) {
- if (phy_id < 4)
+ if (phy_id < MVS_SOC_PORTS)
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg);
else
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg);
@@ -104,13 +95,13 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id)
reg = mr32(MVS_PHY_CTL);
tmp = reg;
- if (phy_id < 4)
+ if (phy_id < MVS_SOC_PORTS)
tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
else
- tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS;
+ tmp |= (1U << (phy_id - MVS_SOC_PORTS)) << PCTL_LINK_OFFS;
if (!(mvi->flags & MVF_FLAG_SOC)) {
- if (phy_id < 4) {
+ if (phy_id < MVS_SOC_PORTS) {
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
mdelay(10);
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg);
@@ -133,9 +124,9 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
tmp &= ~PHYEV_RDY_CH;
mvs_write_port_irq_stat(mvi, phy_id, tmp);
tmp = mvs_read_phy_ctl(mvi, phy_id);
- if (hard == 1)
+ if (hard == MVS_HARD_RESET)
tmp |= PHY_RST_HARD;
- else if (hard == 0)
+ else if (hard == MVS_SOFT_RESET)
tmp |= PHY_RST;
mvs_write_phy_ctl(mvi, phy_id, tmp);
if (hard) {
@@ -321,6 +312,11 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
/* init phys */
mvs_64xx_phy_hacks(mvi);
+ tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
+ tmp &= 0x0000ffff;
+ tmp |= 0x00fa0000;
+ mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
+
/* enable auto port detection */
mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);
@@ -346,7 +342,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
mvs_64xx_enable_xmt(mvi, i);
- mvs_64xx_phy_reset(mvi, i, 1);
+ mvs_64xx_phy_reset(mvi, i, MVS_HARD_RESET);
msleep(500);
mvs_64xx_detect_porttype(mvi, i);
}
@@ -377,13 +373,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
mvs_update_phyinfo(mvi, i, 1);
}
- /* FIXME: update wide port bitmaps */
-
/* little endian for open address and command table, etc. */
- /*
- * it seems that ( from the spec ) turning on big-endian won't
- * do us any good on big-endian machines, need further confirmation
- */
cctl = mr32(MVS_CTL);
cctl |= CCTL_ENDIAN_CMD;
cctl |= CCTL_ENDIAN_DATA;
@@ -394,15 +384,19 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
/* reset CMD queue */
tmp = mr32(MVS_PCS);
tmp |= PCS_CMD_RST;
+ tmp &= ~PCS_SELF_CLEAR;
mw32(MVS_PCS, tmp);
- /* interrupt coalescing may cause missing HW interrput in some case,
- * and the max count is 0x1ff, while our max slot is 0x200,
+ /*
+ * the max count is 0x1ff, while our max slot is 0x200,
* it will make count 0.
*/
tmp = 0;
- mw32(MVS_INT_COAL, tmp);
+ if (MVS_CHIP_SLOT_SZ > 0x1ff)
+ mw32(MVS_INT_COAL, 0x1ff | COAL_EN);
+ else
+ mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ | COAL_EN);
- tmp = 0x100;
+ tmp = 0x10000 | interrupt_coalescing;
mw32(MVS_INT_COAL_TMOUT, tmp);
/* ladies and gentlemen, start your engines */
@@ -477,13 +471,11 @@ static irqreturn_t mvs_64xx_isr(struct mvs_info *mvi, int irq, u32 stat)
/* clear CMD_CMPLT ASAP */
mw32_f(MVS_INT_STAT, CINT_DONE);
-#ifndef MVS_USE_TASKLET
+
spin_lock(&mvi->lock);
-#endif
mvs_int_full(mvi);
-#ifndef MVS_USE_TASKLET
spin_unlock(&mvi->lock);
-#endif
+
return IRQ_HANDLED;
}
@@ -630,7 +622,6 @@ static void mvs_64xx_phy_work_around(struct mvs_info *mvi, int i)
{
u32 tmp;
struct mvs_phy *phy = &mvi->phy[i];
- /* workaround for HW phy decoding error on 1.5g disk drive */
mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6);
tmp = mvs_read_port_vsr_data(mvi, i);
if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
@@ -661,7 +652,7 @@ void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
tmp |= lrmax;
}
mvs_write_phy_ctl(mvi, phy_id, tmp);
- mvs_64xx_phy_reset(mvi, phy_id, 1);
+ mvs_64xx_phy_reset(mvi, phy_id, MVS_HARD_RESET);
}
static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
@@ -744,11 +735,13 @@ int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
return -1;
}
-#ifndef DISABLE_HOTPLUG_DMA_FIX
-void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
+void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
+ int buf_len, int from, void *prd)
{
int i;
struct mvs_prd *buf_prd = prd;
+ dma_addr_t buf_dma = mvi->bulk_buffer_dma;
+
buf_prd += from;
for (i = 0; i < MAX_SG_ENTRY - from; i++) {
buf_prd->addr = cpu_to_le64(buf_dma);
@@ -756,7 +749,28 @@ void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
++buf_prd;
}
}
-#endif
+
+static void mvs_64xx_tune_interrupt(struct mvs_info *mvi, u32 time)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp = 0;
+ /*
+ * the max count is 0x1ff, while our max slot is 0x200,
+ * it will make count 0.
+ */
+ if (time == 0) {
+ mw32(MVS_INT_COAL, 0);
+ mw32(MVS_INT_COAL_TMOUT, 0x10000);
+ } else {
+ if (MVS_CHIP_SLOT_SZ > 0x1ff)
+ mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
+ else
+ mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
+
+ tmp = 0x10000 | time;
+ mw32(MVS_INT_COAL_TMOUT, tmp);
+ }
+}
const struct mvs_dispatch mvs_64xx_dispatch = {
"mv64xx",
@@ -780,7 +794,6 @@ const struct mvs_dispatch mvs_64xx_dispatch = {
mvs_write_port_irq_stat,
mvs_read_port_irq_mask,
mvs_write_port_irq_mask,
- mvs_get_sas_addr,
mvs_64xx_command_active,
mvs_64xx_clear_srs_irq,
mvs_64xx_issue_stop,
@@ -808,8 +821,8 @@ const struct mvs_dispatch mvs_64xx_dispatch = {
mvs_64xx_spi_buildcmd,
mvs_64xx_spi_issuecmd,
mvs_64xx_spi_waitdataready,
-#ifndef DISABLE_HOTPLUG_DMA_FIX
mvs_64xx_fix_dma,
-#endif
+ mvs_64xx_tune_interrupt,
+ NULL,
};
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 78162c3..7e423e5 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -48,6 +48,216 @@ static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i)
}
}
+void set_phy_tuning(struct mvs_info *mvi, int phy_id,
+ struct phy_tuning phy_tuning)
+{
+ u32 tmp, setting_0 = 0, setting_1 = 0;
+ u8 i;
+
+ /* Remap information for B0 chip:
+ *
+ * R0Ch -> R118h[15:0] (Adapted DFE F3 - F5 coefficient)
+ * R0Dh -> R118h[31:16] (Generation 1 Setting 0)
+ * R0Eh -> R11Ch[15:0] (Generation 1 Setting 1)
+ * R0Fh -> R11Ch[31:16] (Generation 2 Setting 0)
+ * R10h -> R120h[15:0] (Generation 2 Setting 1)
+ * R11h -> R120h[31:16] (Generation 3 Setting 0)
+ * R12h -> R124h[15:0] (Generation 3 Setting 1)
+ * R13h -> R124h[31:16] (Generation 4 Setting 0 (Reserved))
+ */
+
+ /* A0 has a different set of registers */
+ if (mvi->pdev->revision == VANIR_A0_REV)
+ return;
+
+ for (i = 0; i < 3; i++) {
+ /* loop 3 times, set Gen 1, Gen 2, Gen 3 */
+ switch (i) {
+ case 0:
+ setting_0 = GENERATION_1_SETTING;
+ setting_1 = GENERATION_1_2_SETTING;
+ break;
+ case 1:
+ setting_0 = GENERATION_1_2_SETTING;
+ setting_1 = GENERATION_2_3_SETTING;
+ break;
+ case 2:
+ setting_0 = GENERATION_2_3_SETTING;
+ setting_1 = GENERATION_3_4_SETTING;
+ break;
+ }
+
+ /* Set:
+ *
+ * Transmitter Emphasis Enable
+ * Transmitter Emphasis Amplitude
+ * Transmitter Amplitude
+ */
+ mvs_write_port_vsr_addr(mvi, phy_id, setting_0);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp &= ~(0xFBE << 16);
+ tmp |= (((phy_tuning.trans_emp_en << 11) |
+ (phy_tuning.trans_emp_amp << 7) |
+ (phy_tuning.trans_amp << 1)) << 16);
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+ /* Set Transmitter Amplitude Adjust */
+ mvs_write_port_vsr_addr(mvi, phy_id, setting_1);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp &= ~(0xC000);
+ tmp |= (phy_tuning.trans_amp_adj << 14);
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+ }
+}
+
+void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id,
+ struct ffe_control ffe)
+{
+ u32 tmp;
+
+ /* Don't run this if A0/B0 */
+ if ((mvi->pdev->revision == VANIR_A0_REV)
+ || (mvi->pdev->revision == VANIR_B0_REV))
+ return;
+
+ /* FFE Resistor and Capacitor */
+ /* R10Ch DFE Resolution Control/Squelch and FFE Setting
+ *
+ * FFE_FORCE [7]
+ * FFE_RES_SEL [6:4]
+ * FFE_CAP_SEL [3:0]
+ */
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_FFE_CONTROL);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp &= ~0xFF;
+
+ /* Read from HBA_Info_Page */
+ tmp |= ((0x1 << 7) |
+ (ffe.ffe_rss_sel << 4) |
+ (ffe.ffe_cap_sel << 0));
+
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+ /* R064h PHY Mode Register 1
+ *
+ * DFE_DIS 18
+ */
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp &= ~0x40001;
+ /* Hard coding */
+ /* No defines in HBA_Info_Page */
+ tmp |= (0 << 18);
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+ /* R110h DFE F0-F1 Coefficient Control/DFE Update Control
+ *
+ * DFE_UPDATE_EN [11:6]
+ * DFE_FX_FORCE [5:0]
+ */
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_DFE_UPDATE_CRTL);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp &= ~0xFFF;
+ /* Hard coding */
+ /* No defines in HBA_Info_Page */
+ tmp |= ((0x3F << 6) | (0x0 << 0));
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+
+ /* R1A0h Interface and Digital Reference Clock Control/Reserved_50h
+ *
+ * FFE_TRAIN_EN 3
+ */
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp &= ~0x8;
+ /* Hard coding */
+ /* No defines in HBA_Info_Page */
+ tmp |= (0 << 3);
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+}
+
+/*Notice: this function must be called when phy is disabled*/
+void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
+{
+ union reg_phy_cfg phy_cfg, phy_cfg_tmp;
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
+ phy_cfg_tmp.v = mvs_read_port_vsr_data(mvi, phy_id);
+ phy_cfg.v = 0;
+ phy_cfg.u.disable_phy = phy_cfg_tmp.u.disable_phy;
+ phy_cfg.u.sas_support = 1;
+ phy_cfg.u.sata_support = 1;
+ phy_cfg.u.sata_host_mode = 1;
+
+ switch (rate) {
+ case 0x0:
+ /* support 1.5 Gbps */
+ phy_cfg.u.speed_support = 1;
+ phy_cfg.u.snw_3_support = 0;
+ phy_cfg.u.tx_lnk_parity = 1;
+ phy_cfg.u.tx_spt_phs_lnk_rate = 0x30;
+ break;
+ case 0x1:
+
+ /* support 1.5, 3.0 Gbps */
+ phy_cfg.u.speed_support = 3;
+ phy_cfg.u.tx_spt_phs_lnk_rate = 0x3c;
+ phy_cfg.u.tx_lgcl_lnk_rate = 0x08;
+ break;
+ case 0x2:
+ default:
+ /* support 1.5, 3.0, 6.0 Gbps */
+ phy_cfg.u.speed_support = 7;
+ phy_cfg.u.snw_3_support = 1;
+ phy_cfg.u.tx_lnk_parity = 1;
+ phy_cfg.u.tx_spt_phs_lnk_rate = 0x3f;
+ phy_cfg.u.tx_lgcl_lnk_rate = 0x09;
+ break;
+ }
+ mvs_write_port_vsr_data(mvi, phy_id, phy_cfg.v);
+}
+
+static void __devinit
+mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
+{
+ u32 temp;
+ temp = (u32)(*(u32 *)&mvi->hba_info_param.phy_tuning[phy_id]);
+ if (temp == 0xFFFFFFFFL) {
+ mvi->hba_info_param.phy_tuning[phy_id].trans_emp_amp = 0x6;
+ mvi->hba_info_param.phy_tuning[phy_id].trans_amp = 0x1A;
+ mvi->hba_info_param.phy_tuning[phy_id].trans_amp_adj = 0x3;
+ }
+
+ temp = (u8)(*(u8 *)&mvi->hba_info_param.ffe_ctl[phy_id]);
+ if (temp == 0xFFL) {
+ switch (mvi->pdev->revision) {
+ case VANIR_A0_REV:
+ case VANIR_B0_REV:
+ mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7;
+ mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0x7;
+ break;
+ case VANIR_C0_REV:
+ case VANIR_C1_REV:
+ case VANIR_C2_REV:
+ default:
+ mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7;
+ mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0xC;
+ break;
+ }
+ }
+
+ temp = (u8)(*(u8 *)&mvi->hba_info_param.phy_rate[phy_id]);
+ if (temp == 0xFFL)
+ /*set default phy_rate = 6Gbps*/
+ mvi->hba_info_param.phy_rate[phy_id] = 0x2;
+
+ set_phy_tuning(mvi, phy_id,
+ mvi->hba_info_param.phy_tuning[phy_id]);
+ set_phy_ffe_tuning(mvi, phy_id,
+ mvi->hba_info_param.ffe_ctl[phy_id]);
+ set_phy_rate(mvi, phy_id,
+ mvi->hba_info_param.phy_rate[phy_id]);
+}
+
static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
{
void __iomem *regs = mvi->regs;
@@ -61,7 +271,14 @@ static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
{
u32 tmp;
-
+ u32 delay = 5000;
+ if (hard == MVS_PHY_TUNE) {
+ mvs_write_port_cfg_addr(mvi, phy_id, PHYR_SATA_CTL);
+ tmp = mvs_read_port_cfg_data(mvi, phy_id);
+ mvs_write_port_cfg_data(mvi, phy_id, tmp|0x20000000);
+ mvs_write_port_cfg_data(mvi, phy_id, tmp|0x100000);
+ return;
+ }
tmp = mvs_read_port_irq_stat(mvi, phy_id);
tmp &= ~PHYEV_RDY_CH;
mvs_write_port_irq_stat(mvi, phy_id, tmp);
@@ -71,12 +288,15 @@ static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
mvs_write_phy_ctl(mvi, phy_id, tmp);
do {
tmp = mvs_read_phy_ctl(mvi, phy_id);
- } while (tmp & PHY_RST_HARD);
+ udelay(10);
+ delay--;
+ } while ((tmp & PHY_RST_HARD) && delay);
+ if (!delay)
+ mv_dprintk("phy hard reset failed.\n");
} else {
- mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_STAT);
- tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
tmp |= PHY_RST;
- mvs_write_port_vsr_data(mvi, phy_id, tmp);
+ mvs_write_phy_ctl(mvi, phy_id, tmp);
}
}
@@ -90,12 +310,25 @@ static void mvs_94xx_phy_disable(struct mvs_info *mvi, u32 phy_id)
static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
{
- mvs_write_port_vsr_addr(mvi, phy_id, 0x1B4);
- mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
- mvs_write_port_vsr_addr(mvi, phy_id, 0x104);
- mvs_write_port_vsr_data(mvi, phy_id, 0x00018080);
+ u32 tmp;
+ u8 revision = 0;
+
+ revision = mvi->pdev->revision;
+ if (revision == VANIR_A0_REV) {
+ mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA);
+ mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
+ }
+ if (revision == VANIR_B0_REV) {
+ mvs_write_port_vsr_addr(mvi, phy_id, CMD_APP_MEM_CTL);
+ mvs_write_port_vsr_data(mvi, phy_id, 0x08001006);
+ mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA);
+ mvs_write_port_vsr_data(mvi, phy_id, 0x0000705f);
+ }
+
mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
- mvs_write_port_vsr_data(mvi, phy_id, 0x00207fff);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp |= bit(0);
+ mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff);
}
static int __devinit mvs_94xx_init(struct mvs_info *mvi)
@@ -103,7 +336,9 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
void __iomem *regs = mvi->regs;
int i;
u32 tmp, cctl;
+ u8 revision;
+ revision = mvi->pdev->revision;
mvs_show_pcie_usage(mvi);
if (mvi->flags & MVF_FLAG_SOC) {
tmp = mr32(MVS_PHY_CTL);
@@ -133,6 +368,28 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
msleep(100);
}
+ /* disable Multiplexing, enable phy implemented */
+ mw32(MVS_PORTS_IMP, 0xFF);
+
+ if (revision == VANIR_A0_REV) {
+ mw32(MVS_PA_VSR_ADDR, CMD_CMWK_OOB_DET);
+ mw32(MVS_PA_VSR_PORT, 0x00018080);
+ }
+ mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE2);
+ if (revision == VANIR_A0_REV || revision == VANIR_B0_REV)
+ /* set 6G/3G/1.5G, multiplexing, without SSC */
+ mw32(MVS_PA_VSR_PORT, 0x0084d4fe);
+ else
+ /* set 6G/3G/1.5G, multiplexing, with and without SSC */
+ mw32(MVS_PA_VSR_PORT, 0x0084fffe);
+
+ if (revision == VANIR_B0_REV) {
+ mw32(MVS_PA_VSR_ADDR, CMD_APP_MEM_CTL);
+ mw32(MVS_PA_VSR_PORT, 0x08001006);
+ mw32(MVS_PA_VSR_ADDR, CMD_HOST_RD_DATA);
+ mw32(MVS_PA_VSR_PORT, 0x0000705f);
+ }
+
/* reset control */
mw32(MVS_PCS, 0); /* MVS_PCS */
mw32(MVS_STP_REG_SET_0, 0);
@@ -141,17 +398,18 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* init phys */
mvs_phy_hacks(mvi);
- /* disable Multiplexing, enable phy implemented */
- mw32(MVS_PORTS_IMP, 0xFF);
-
-
- mw32(MVS_PA_VSR_ADDR, 0x00000104);
- mw32(MVS_PA_VSR_PORT, 0x00018080);
- mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE8);
- mw32(MVS_PA_VSR_PORT, 0x0084ffff);
+ /* disable non data frame retry */
+ tmp = mvs_cr32(mvi, CMD_SAS_CTL1);
+ if ((revision == VANIR_A0_REV) ||
+ (revision == VANIR_B0_REV) ||
+ (revision == VANIR_C0_REV)) {
+ tmp &= ~0xffff;
+ tmp |= 0x007f;
+ mvs_cw32(mvi, CMD_SAS_CTL1, tmp);
+ }
/* set LED blink when IO*/
- mw32(MVS_PA_VSR_ADDR, 0x00000030);
+ mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED);
tmp = mr32(MVS_PA_VSR_PORT);
tmp &= 0xFFFF00FF;
tmp |= 0x00003300;
@@ -175,12 +433,13 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
mvs_94xx_phy_disable(mvi, i);
/* set phy local SAS address */
mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4,
- (mvi->phy[i].dev_sas_addr));
+ cpu_to_le64(mvi->phy[i].dev_sas_addr));
mvs_94xx_enable_xmt(mvi, i);
+ mvs_94xx_config_reg_from_hba(mvi, i);
mvs_94xx_phy_enable(mvi, i);
- mvs_94xx_phy_reset(mvi, i, 1);
+ mvs_94xx_phy_reset(mvi, i, PHY_RST_HARD);
msleep(500);
mvs_94xx_detect_porttype(mvi, i);
}
@@ -211,16 +470,9 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
mvs_update_phyinfo(mvi, i, 1);
}
- /* FIXME: update wide port bitmaps */
-
/* little endian for open address and command table, etc. */
- /*
- * it seems that ( from the spec ) turning on big-endian won't
- * do us any good on big-endian machines, need further confirmation
- */
cctl = mr32(MVS_CTL);
cctl |= CCTL_ENDIAN_CMD;
- cctl |= CCTL_ENDIAN_DATA;
cctl &= ~CCTL_ENDIAN_OPEN;
cctl |= CCTL_ENDIAN_RSP;
mw32_f(MVS_CTL, cctl);
@@ -228,15 +480,20 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* reset CMD queue */
tmp = mr32(MVS_PCS);
tmp |= PCS_CMD_RST;
+ tmp &= ~PCS_SELF_CLEAR;
mw32(MVS_PCS, tmp);
- /* interrupt coalescing may cause missing HW interrput in some case,
- * and the max count is 0x1ff, while our max slot is 0x200,
+ /*
+ * the max count is 0x1ff, while our max slot is 0x200,
* it will make count 0.
*/
tmp = 0;
- mw32(MVS_INT_COAL, tmp);
+ if (MVS_CHIP_SLOT_SZ > 0x1ff)
+ mw32(MVS_INT_COAL, 0x1ff | COAL_EN);
+ else
+ mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ | COAL_EN);
- tmp = 0x100;
+ /* default interrupt coalescing time is 128us */
+ tmp = 0x10000 | interrupt_coalescing;
mw32(MVS_INT_COAL_TMOUT, tmp);
/* ladies and gentlemen, start your engines */
@@ -249,10 +506,31 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* enable completion queue interrupt */
tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
- CINT_DMA_PCIE);
+ CINT_DMA_PCIE | CINT_NON_SPEC_NCQ_ERROR);
tmp |= CINT_PHY_MASK;
mw32(MVS_INT_MASK, tmp);
+ tmp = mvs_cr32(mvi, CMD_LINK_TIMER);
+ tmp |= 0xFFFF0000;
+ mvs_cw32(mvi, CMD_LINK_TIMER, tmp);
+
+ /* tune STP performance */
+ tmp = 0x003F003F;
+ mvs_cw32(mvi, CMD_PL_TIMER, tmp);
+
+ /* This can improve expander large block size seq write performance */
+ tmp = mvs_cr32(mvi, CMD_PORT_LAYER_TIMER1);
+ tmp |= 0xFFFF007F;
+ mvs_cw32(mvi, CMD_PORT_LAYER_TIMER1, tmp);
+
+ /* change the connection open-close behavior (bit 9)
+ * set bit8 to 1 for performance tuning */
+ tmp = mvs_cr32(mvi, CMD_SL_MODE0);
+ tmp |= 0x00000300;
+ /* set bit0 to 0 to enable retry for no_dest reject case */
+ tmp &= 0xFFFFFFFE;
+ mvs_cw32(mvi, CMD_SL_MODE0, tmp);
+
/* Enable SRS interrupt */
mw32(MVS_INT_MASK_SRS_0, 0xFFFF);
@@ -332,13 +610,10 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
if (((stat & IRQ_SAS_A) && mvi->id == 0) ||
((stat & IRQ_SAS_B) && mvi->id == 1)) {
mw32_f(MVS_INT_STAT, CINT_DONE);
- #ifndef MVS_USE_TASKLET
+
spin_lock(&mvi->lock);
- #endif
mvs_int_full(mvi);
- #ifndef MVS_USE_TASKLET
spin_unlock(&mvi->lock);
- #endif
}
return IRQ_HANDLED;
}
@@ -346,10 +621,48 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx)
{
u32 tmp;
- mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32));
- do {
- tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3));
- } while (tmp & 1 << (slot_idx % 32));
+ tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
+ if (tmp && 1 << (slot_idx % 32)) {
+ mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx);
+ mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3),
+ 1 << (slot_idx % 32));
+ do {
+ tmp = mvs_cr32(mvi,
+ MVS_COMMAND_ACTIVE + (slot_idx >> 3));
+ } while (tmp & 1 << (slot_idx % 32));
+ }
+}
+
+void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ if (clear_all) {
+ tmp = mr32(MVS_INT_STAT_SRS_0);
+ if (tmp) {
+ mv_dprintk("check SRS 0 %08X.\n", tmp);
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+ }
+ tmp = mr32(MVS_INT_STAT_SRS_1);
+ if (tmp) {
+ mv_dprintk("check SRS 1 %08X.\n", tmp);
+ mw32(MVS_INT_STAT_SRS_1, tmp);
+ }
+ } else {
+ if (reg_set > 31)
+ tmp = mr32(MVS_INT_STAT_SRS_1);
+ else
+ tmp = mr32(MVS_INT_STAT_SRS_0);
+
+ if (tmp & (1 << (reg_set % 32))) {
+ mv_dprintk("register set 0x%x was stopped.\n", reg_set);
+ if (reg_set > 31)
+ mw32(MVS_INT_STAT_SRS_1, 1 << (reg_set % 32));
+ else
+ mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32));
+ }
+ }
}
static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
@@ -357,37 +670,56 @@ static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
{
void __iomem *regs = mvi->regs;
u32 tmp;
+ mvs_94xx_clear_srs_irq(mvi, 0, 1);
- if (type == PORT_TYPE_SATA) {
- tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs);
- mw32(MVS_INT_STAT_SRS_0, tmp);
- }
- mw32(MVS_INT_STAT, CINT_CI_STOP);
+ tmp = mr32(MVS_INT_STAT);
+ mw32(MVS_INT_STAT, tmp | CINT_CI_STOP);
tmp = mr32(MVS_PCS) | 0xFF00;
mw32(MVS_PCS, tmp);
}
+static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ u32 err_0, err_1;
+ u8 i;
+ struct mvs_device *device;
+
+ err_0 = mr32(MVS_NON_NCQ_ERR_0);
+ err_1 = mr32(MVS_NON_NCQ_ERR_1);
+
+ mv_dprintk("non specific ncq error err_0:%x,err_1:%x.\n",
+ err_0, err_1);
+ for (i = 0; i < 32; i++) {
+ if (err_0 & bit(i)) {
+ device = mvs_find_dev_by_reg_set(mvi, i);
+ if (device)
+ mvs_release_task(mvi, device->sas_device);
+ }
+ if (err_1 & bit(i)) {
+ device = mvs_find_dev_by_reg_set(mvi, i+32);
+ if (device)
+ mvs_release_task(mvi, device->sas_device);
+ }
+ }
+
+ mw32(MVS_NON_NCQ_ERR_0, err_0);
+ mw32(MVS_NON_NCQ_ERR_1, err_1);
+}
+
static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
{
void __iomem *regs = mvi->regs;
- u32 tmp;
u8 reg_set = *tfs;
if (*tfs == MVS_ID_NOT_MAPPED)
return;
mvi->sata_reg_set &= ~bit(reg_set);
- if (reg_set < 32) {
+ if (reg_set < 32)
w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set);
- tmp = mr32(MVS_INT_STAT_SRS_0) & (u32)mvi->sata_reg_set;
- if (tmp)
- mw32(MVS_INT_STAT_SRS_0, tmp);
- } else {
- w_reg_set_enable(reg_set, mvi->sata_reg_set);
- tmp = mr32(MVS_INT_STAT_SRS_1) & mvi->sata_reg_set;
- if (tmp)
- mw32(MVS_INT_STAT_SRS_1, tmp);
- }
+ else
+ w_reg_set_enable(reg_set, (u32)(mvi->sata_reg_set >> 32));
*tfs = MVS_ID_NOT_MAPPED;
@@ -403,7 +735,7 @@ static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
return 0;
i = mv_ffc64(mvi->sata_reg_set);
- if (i > 32) {
+ if (i >= 32) {
mvi->sata_reg_set |= bit(i);
w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32));
*tfs = i;
@@ -422,9 +754,12 @@ static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
int i;
struct scatterlist *sg;
struct mvs_prd *buf_prd = prd;
+ struct mvs_prd_imt im_len;
+ *(u32 *)&im_len = 0;
for_each_sg(scatter, sg, nr, i) {
buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
- buf_prd->im_len.len = cpu_to_le32(sg_dma_len(sg));
+ im_len.len = sg_dma_len(sg);
+ buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
buf_prd++;
}
}
@@ -433,7 +768,7 @@ static int mvs_94xx_oob_done(struct mvs_info *mvi, int i)
{
u32 phy_st;
phy_st = mvs_read_phy_ctl(mvi, i);
- if (phy_st & PHY_READY_MASK) /* phy ready */
+ if (phy_st & PHY_READY_MASK)
return 1;
return 0;
}
@@ -447,7 +782,7 @@ static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id,
for (i = 0; i < 7; i++) {
mvs_write_port_cfg_addr(mvi, port_id,
CONFIG_ID_FRAME0 + i * 4);
- id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
+ id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
}
memcpy(id, id_frame, 28);
}
@@ -458,15 +793,13 @@ static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id,
int i;
u32 id_frame[7];
- /* mvs_hexdump(28, (u8 *)id_frame, 0); */
for (i = 0; i < 7; i++) {
mvs_write_port_cfg_addr(mvi, port_id,
CONFIG_ATT_ID_FRAME0 + i * 4);
- id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
+ id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
mv_dprintk("94xx phy %d atta frame %d %x.\n",
port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]);
}
- /* mvs_hexdump(28, (u8 *)id_frame, 0); */
memcpy(id, id_frame, 28);
}
@@ -521,12 +854,27 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
phy->att_dev_info = PORT_DEV_STP_TRGT | 1;
}
+ /* enable spin up bit */
+ mvs_write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
+ mvs_write_port_cfg_data(mvi, i, 0x04);
+
}
void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
struct sas_phy_linkrates *rates)
{
- /* TODO */
+ u32 lrmax = 0;
+ u32 tmp;
+
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
+ lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12;
+
+ if (lrmax) {
+ tmp &= ~(0x3 << 12);
+ tmp |= lrmax;
+ }
+ mvs_write_phy_ctl(mvi, phy_id, tmp);
+ mvs_94xx_phy_reset(mvi, phy_id, PHY_RST_HARD);
}
static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi)
@@ -603,27 +951,59 @@ int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
return -1;
}
-#ifndef DISABLE_HOTPLUG_DMA_FIX
-void mvs_94xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
+void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
+ int buf_len, int from, void *prd)
{
int i;
struct mvs_prd *buf_prd = prd;
+ dma_addr_t buf_dma;
+ struct mvs_prd_imt im_len;
+
+ *(u32 *)&im_len = 0;
buf_prd += from;
- for (i = 0; i < MAX_SG_ENTRY - from; i++) {
- buf_prd->addr = cpu_to_le64(buf_dma);
- buf_prd->im_len.len = cpu_to_le32(buf_len);
- ++buf_prd;
+
+#define PRD_CHAINED_ENTRY 0x01
+ if ((mvi->pdev->revision == VANIR_A0_REV) ||
+ (mvi->pdev->revision == VANIR_B0_REV))
+ buf_dma = (phy_mask <= 0x08) ?
+ mvi->bulk_buffer_dma : mvi->bulk_buffer_dma1;
+ else
+ return;
+
+ for (i = from; i < MAX_SG_ENTRY; i++, ++buf_prd) {
+ if (i == MAX_SG_ENTRY - 1) {
+ buf_prd->addr = cpu_to_le64(virt_to_phys(buf_prd - 1));
+ im_len.len = 2;
+ im_len.misc_ctl = PRD_CHAINED_ENTRY;
+ } else {
+ buf_prd->addr = cpu_to_le64(buf_dma);
+ im_len.len = buf_len;
+ }
+ buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
}
}
-#endif
-/*
- * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work
- * with 64xx fixes
- */
-static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set,
- u8 clear_all)
+static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time)
{
+ void __iomem *regs = mvi->regs;
+ u32 tmp = 0;
+ /*
+ * the max count is 0x1ff, while our max slot is 0x200,
+ * it will make count 0.
+ */
+ if (time == 0) {
+ mw32(MVS_INT_COAL, 0);
+ mw32(MVS_INT_COAL_TMOUT, 0x10000);
+ } else {
+ if (MVS_CHIP_SLOT_SZ > 0x1ff)
+ mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
+ else
+ mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
+
+ tmp = 0x10000 | time;
+ mw32(MVS_INT_COAL_TMOUT, tmp);
+ }
+
}
const struct mvs_dispatch mvs_94xx_dispatch = {
@@ -648,7 +1028,6 @@ const struct mvs_dispatch mvs_94xx_dispatch = {
mvs_write_port_irq_stat,
mvs_read_port_irq_mask,
mvs_write_port_irq_mask,
- mvs_get_sas_addr,
mvs_94xx_command_active,
mvs_94xx_clear_srs_irq,
mvs_94xx_issue_stop,
@@ -676,8 +1055,8 @@ const struct mvs_dispatch mvs_94xx_dispatch = {
mvs_94xx_spi_buildcmd,
mvs_94xx_spi_issuecmd,
mvs_94xx_spi_waitdataready,
-#ifndef DISABLE_HOTPLUG_DMA_FIX
mvs_94xx_fix_dma,
-#endif
+ mvs_94xx_tune_interrupt,
+ mvs_94xx_non_spec_ncq_error,
};
diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h
index d72aa61..487aa6f 100644
--- a/drivers/scsi/mvsas/mv_94xx.h
+++ b/drivers/scsi/mvsas/mv_94xx.h
@@ -30,6 +30,14 @@
#define MAX_LINK_RATE SAS_LINK_RATE_6_0_GBPS
+enum VANIR_REVISION_ID {
+ VANIR_A0_REV = 0xA0,
+ VANIR_B0_REV = 0x01,
+ VANIR_C0_REV = 0x02,
+ VANIR_C1_REV = 0x03,
+ VANIR_C2_REV = 0xC2,
+};
+
enum hw_registers {
MVS_GBL_CTL = 0x04, /* global control */
MVS_GBL_INT_STAT = 0x00, /* global irq status */
@@ -101,6 +109,7 @@ enum hw_registers {
MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */
MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */
MVS_PA_VSR_PORT = 0x294, /* All port VSR data */
+ MVS_COMMAND_ACTIVE = 0x300,
};
enum pci_cfg_registers {
@@ -112,26 +121,29 @@ enum pci_cfg_registers {
/* SAS/SATA Vendor Specific Port Registers */
enum sas_sata_vsp_regs {
- VSR_PHY_STAT = 0x00 * 4, /* Phy Status */
- VSR_PHY_MODE1 = 0x01 * 4, /* phy tx */
- VSR_PHY_MODE2 = 0x02 * 4, /* tx scc */
- VSR_PHY_MODE3 = 0x03 * 4, /* pll */
- VSR_PHY_MODE4 = 0x04 * 4, /* VCO */
- VSR_PHY_MODE5 = 0x05 * 4, /* Rx */
- VSR_PHY_MODE6 = 0x06 * 4, /* CDR */
- VSR_PHY_MODE7 = 0x07 * 4, /* Impedance */
- VSR_PHY_MODE8 = 0x08 * 4, /* Voltage */
- VSR_PHY_MODE9 = 0x09 * 4, /* Test */
- VSR_PHY_MODE10 = 0x0A * 4, /* Power */
- VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */
- VSR_PHY_VS0 = 0x0C * 4, /* Vednor Specific 0 */
- VSR_PHY_VS1 = 0x0D * 4, /* Vednor Specific 1 */
+ VSR_PHY_STAT = 0x00 * 4, /* Phy Interrupt Status */
+ VSR_PHY_MODE1 = 0x01 * 4, /* phy Interrupt Enable */
+ VSR_PHY_MODE2 = 0x02 * 4, /* Phy Configuration */
+ VSR_PHY_MODE3 = 0x03 * 4, /* Phy Status */
+ VSR_PHY_MODE4 = 0x04 * 4, /* Phy Counter 0 */
+ VSR_PHY_MODE5 = 0x05 * 4, /* Phy Counter 1 */
+ VSR_PHY_MODE6 = 0x06 * 4, /* Event Counter Control */
+ VSR_PHY_MODE7 = 0x07 * 4, /* Event Counter Select */
+ VSR_PHY_MODE8 = 0x08 * 4, /* Event Counter 0 */
+ VSR_PHY_MODE9 = 0x09 * 4, /* Event Counter 1 */
+ VSR_PHY_MODE10 = 0x0A * 4, /* Event Counter 2 */
+ VSR_PHY_MODE11 = 0x0B * 4, /* Event Counter 3 */
+ VSR_PHY_ACT_LED = 0x0C * 4, /* Activity LED control */
+
+ VSR_PHY_FFE_CONTROL = 0x10C,
+ VSR_PHY_DFE_UPDATE_CRTL = 0x110,
+ VSR_REF_CLOCK_CRTL = 0x1A0,
};
enum chip_register_bits {
PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
- PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
- PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (12),
+ PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 12),
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16),
PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
(0x3 << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
};
@@ -169,22 +181,75 @@ enum pci_interrupt_cause {
IRQ_PCIE_ERR = (1 << 31),
};
+union reg_phy_cfg {
+ u32 v;
+ struct {
+ u32 phy_reset:1;
+ u32 sas_support:1;
+ u32 sata_support:1;
+ u32 sata_host_mode:1;
+ /*
+ * bit 2: 6Gbps support
+ * bit 1: 3Gbps support
+ * bit 0: 1.5Gbps support
+ */
+ u32 speed_support:3;
+ u32 snw_3_support:1;
+ u32 tx_lnk_parity:1;
+ /*
+ * bit 5: G1 (1.5Gbps) Without SSC
+ * bit 4: G1 (1.5Gbps) with SSC
+ * bit 3: G2 (3.0Gbps) Without SSC
+ * bit 2: G2 (3.0Gbps) with SSC
+ * bit 1: G3 (6.0Gbps) without SSC
+ * bit 0: G3 (6.0Gbps) with SSC
+ */
+ u32 tx_spt_phs_lnk_rate:6;
+ /* 8h: 1.5Gbps 9h: 3Gbps Ah: 6Gbps */
+ u32 tx_lgcl_lnk_rate:4;
+ u32 tx_ssc_type:1;
+ u32 sata_spin_up_spt:1;
+ u32 sata_spin_up_en:1;
+ u32 bypass_oob:1;
+ u32 disable_phy:1;
+ u32 rsvd:8;
+ } u;
+};
+
#define MAX_SG_ENTRY 255
struct mvs_prd_imt {
+#ifndef __BIG_ENDIAN
__le32 len:22;
u8 _r_a:2;
u8 misc_ctl:4;
u8 inter_sel:4;
+#else
+ u32 inter_sel:4;
+ u32 misc_ctl:4;
+ u32 _r_a:2;
+ u32 len:22;
+#endif
};
struct mvs_prd {
/* 64-bit buffer address */
__le64 addr;
/* 22-bit length */
- struct mvs_prd_imt im_len;
+ __le32 im_len;
} __attribute__ ((packed));
+/*
+ * these registers are accessed through port vendor
+ * specific address/data registers
+ */
+enum sas_sata_phy_regs {
+ GENERATION_1_SETTING = 0x118,
+ GENERATION_1_2_SETTING = 0x11C,
+ GENERATION_2_3_SETTING = 0x120,
+ GENERATION_3_4_SETTING = 0x124,
+};
+
#define SPI_CTRL_REG_94XX 0xc800
#define SPI_ADDR_REG_94XX 0xc804
#define SPI_WR_DATA_REG_94XX 0xc808
diff --git a/drivers/scsi/mvsas/mv_chips.h b/drivers/scsi/mvsas/mv_chips.h
index 1753a6f..bcc4080 100644
--- a/drivers/scsi/mvsas/mv_chips.h
+++ b/drivers/scsi/mvsas/mv_chips.h
@@ -164,7 +164,6 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
{
u32 tmp;
- /* workaround for SATA R-ERR, to ignore phy glitch */
tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
tmp &= ~(1 << 9);
tmp |= (1 << 10);
@@ -179,23 +178,10 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
tmp |= 0x3fff;
mvs_cw32(mvi, CMD_SAS_CTL0, tmp);
- /* workaround for WDTIMEOUT , set to 550 ms */
mvs_cw32(mvi, CMD_WD_TIMER, 0x7a0000);
/* not to halt for different port op during wideport link change */
mvs_cw32(mvi, CMD_APP_ERR_CONFIG, 0xffefbf7d);
-
- /* workaround for Seagate disk not-found OOB sequence, recv
- * COMINIT before sending out COMWAKE */
- tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
- tmp &= 0x0000ffff;
- tmp |= 0x00fa0000;
- mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
-
- tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
- tmp &= 0x1fffffff;
- tmp |= (2U << 29); /* 8 ms retry */
- mvs_cw32(mvi, CMD_PHY_TIMER, tmp);
}
static inline void mvs_int_sata(struct mvs_info *mvi)
@@ -223,6 +209,9 @@ static inline void mvs_int_full(struct mvs_info *mvi)
mvs_int_port(mvi, i, tmp);
}
+ if (stat & CINT_NON_SPEC_NCQ_ERROR)
+ MVS_CHIP_DISP->non_spec_ncq_error(mvi);
+
if (stat & CINT_SRS)
mvs_int_sata(mvi);
diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h
index bc00c94..f545194 100644
--- a/drivers/scsi/mvsas/mv_defs.h
+++ b/drivers/scsi/mvsas/mv_defs.h
@@ -43,7 +43,6 @@ enum chip_flavors {
/* driver compile-time configuration */
enum driver_configuration {
- MVS_SLOTS = 512, /* command slots */
MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
/* software requires power-of-2
@@ -56,8 +55,7 @@ enum driver_configuration {
MVS_SSP_CMD_SZ = 64, /* SSP command table buffer size */
MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */
MVS_OAF_SZ = 64, /* Open address frame buffer size */
- MVS_QUEUE_SIZE = 32, /* Support Queue depth */
- MVS_CAN_QUEUE = MVS_SLOTS - 2, /* SCSI Queue depth */
+ MVS_QUEUE_SIZE = 64, /* Support Queue depth */
MVS_SOC_CAN_QUEUE = MVS_SOC_SLOTS - 2,
};
@@ -144,6 +142,7 @@ enum hw_register_bits {
CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */
CINT_MEM = (1U << 26), /* int mem parity err */
CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */
+ CINT_NON_SPEC_NCQ_ERROR = (1U << 25), /* Non specific NCQ error */
CINT_SRS = (1U << 3), /* SRS event */
CINT_CI_STOP = (1U << 1), /* cmd issue stopped */
CINT_DONE = (1U << 0), /* cmd completion */
@@ -161,7 +160,7 @@ enum hw_register_bits {
TXQ_CMD_SSP = 1, /* SSP protocol */
TXQ_CMD_SMP = 2, /* SMP protocol */
TXQ_CMD_STP = 3, /* STP/SATA protocol */
- TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP targ free list */
+ TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP target free list */
TXQ_CMD_SLOT_RESET = 7, /* reset command slot */
TXQ_MODE_I = (1U << 28), /* mode: 0=target,1=initiator */
TXQ_MODE_TARGET = 0,
@@ -388,18 +387,20 @@ enum sas_cmd_port_registers {
CMD_SL_MODE0 = 0x1BC, /* SL Mode 0 */
CMD_SL_MODE1 = 0x1C0, /* SL Mode 1 */
CMD_PND_FIFO_CTL1 = 0x1C4, /* Pending FIFO Control 1 */
+ CMD_PORT_LAYER_TIMER1 = 0x1E0, /* Port Layer Timer 1 */
+ CMD_LINK_TIMER = 0x1E4, /* Link Timer */
};
enum mvs_info_flags {
- MVF_MSI = (1U << 0), /* MSI is enabled */
MVF_PHY_PWR_FIX = (1U << 1), /* bug workaround */
MVF_FLAG_SOC = (1U << 2), /* SoC integrated controllers */
};
enum mvs_event_flags {
- PHY_PLUG_EVENT = (3U),
+ PHY_PLUG_EVENT = (3U),
PHY_PLUG_IN = (1U << 0), /* phy plug in */
PHY_PLUG_OUT = (1U << 1), /* phy plug out */
+ EXP_BRCT_CHG = (1U << 2), /* broadcast change */
};
enum mvs_port_type {
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index 90b6366..6f58919 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -34,29 +34,32 @@ MODULE_PARM_DESC(collector, "\n"
"\tThe mvsas SAS LLDD supports both modes.\n"
"\tDefault: 1 (Direct Mode).\n");
+int interrupt_coalescing = 0x80;
+
static struct scsi_transport_template *mvs_stt;
struct kmem_cache *mvs_task_list_cache;
static const struct mvs_chip_info mvs_chips[] = {
- [chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
- [chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
- [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
- [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
- [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
- [chip_9445] = { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
- [chip_9485] = { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
- [chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
- [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
+ [chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
+ [chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
+ [chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, },
+ [chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
+ [chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
+ [chip_9445] = { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
+ [chip_9485] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
+ [chip_1300] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
+ [chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
};
+struct device_attribute *mvst_host_attrs[];
+
#define SOC_SAS_NUM 2
-#define SG_MX 64
static struct scsi_host_template mvs_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
- .slave_configure = mvs_slave_configure,
+ .slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
.scan_finished = mvs_scan_finished,
.scan_start = mvs_scan_start,
@@ -66,14 +69,15 @@ static struct scsi_host_template mvs_sht = {
.can_queue = 1,
.cmd_per_lun = 1,
.this_id = -1,
- .sg_tablesize = SG_MX,
+ .sg_tablesize = SG_ALL,
.max_sectors = SCSI_DEFAULT_MAX_SECTORS,
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = mvs_slave_alloc,
+ .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+ .shost_attrs = mvst_host_attrs,
};
static struct sas_domain_function_template mvs_transport_ops = {
@@ -100,6 +104,7 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
struct asd_sas_phy *sas_phy = &phy->sas_phy;
phy->mvi = mvi;
+ phy->port = NULL;
init_timer(&phy->timer);
sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS;
@@ -128,7 +133,7 @@ static void mvs_free(struct mvs_info *mvi)
if (mvi->flags & MVF_FLAG_SOC)
slot_nr = MVS_SOC_SLOTS;
else
- slot_nr = MVS_SLOTS;
+ slot_nr = MVS_CHIP_SLOT_SZ;
if (mvi->dma_pool)
pci_pool_destroy(mvi->dma_pool);
@@ -148,25 +153,26 @@ static void mvs_free(struct mvs_info *mvi)
dma_free_coherent(mvi->dev,
sizeof(*mvi->slot) * slot_nr,
mvi->slot, mvi->slot_dma);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
+
if (mvi->bulk_buffer)
dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
mvi->bulk_buffer, mvi->bulk_buffer_dma);
-#endif
+ if (mvi->bulk_buffer1)
+ dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
+ mvi->bulk_buffer1, mvi->bulk_buffer_dma1);
MVS_CHIP_DISP->chip_iounmap(mvi);
if (mvi->shost)
scsi_host_put(mvi->shost);
list_for_each_entry(mwq, &mvi->wq_list, entry)
cancel_delayed_work(&mwq->work_q);
+ kfree(mvi->tags);
kfree(mvi);
}
-#ifdef MVS_USE_TASKLET
-struct tasklet_struct mv_tasklet;
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
static void mvs_tasklet(unsigned long opaque)
{
- unsigned long flags;
u32 stat;
u16 core_nr, i = 0;
@@ -179,35 +185,49 @@ static void mvs_tasklet(unsigned long opaque)
if (unlikely(!mvi))
BUG_ON(1);
+ stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq);
+ if (!stat)
+ goto out;
+
for (i = 0; i < core_nr; i++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
- stat = MVS_CHIP_DISP->isr_status(mvi, mvi->irq);
- if (stat)
- MVS_CHIP_DISP->isr(mvi, mvi->irq, stat);
+ MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat);
}
+out:
+ MVS_CHIP_DISP->interrupt_enable(mvi);
}
#endif
static irqreturn_t mvs_interrupt(int irq, void *opaque)
{
- u32 core_nr, i = 0;
+ u32 core_nr;
u32 stat;
struct mvs_info *mvi;
struct sas_ha_struct *sha = opaque;
+#ifndef CONFIG_SCSI_MVSAS_TASKLET
+ u32 i;
+#endif
core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
if (unlikely(!mvi))
return IRQ_NONE;
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+ MVS_CHIP_DISP->interrupt_disable(mvi);
+#endif
stat = MVS_CHIP_DISP->isr_status(mvi, irq);
- if (!stat)
+ if (!stat) {
+ #ifdef CONFIG_SCSI_MVSAS_TASKLET
+ MVS_CHIP_DISP->interrupt_enable(mvi);
+ #endif
return IRQ_NONE;
+ }
-#ifdef MVS_USE_TASKLET
- tasklet_schedule(&mv_tasklet);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+ tasklet_schedule(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
#else
for (i = 0; i < core_nr; i++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
@@ -225,7 +245,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
if (mvi->flags & MVF_FLAG_SOC)
slot_nr = MVS_SOC_SLOTS;
else
- slot_nr = MVS_SLOTS;
+ slot_nr = MVS_CHIP_SLOT_SZ;
spin_lock_init(&mvi->lock);
for (i = 0; i < mvi->chip->n_phy; i++) {
@@ -273,13 +293,18 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
goto err_out;
memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
mvi->bulk_buffer = dma_alloc_coherent(mvi->dev,
TRASH_BUCKET_SIZE,
&mvi->bulk_buffer_dma, GFP_KERNEL);
if (!mvi->bulk_buffer)
goto err_out;
-#endif
+
+ mvi->bulk_buffer1 = dma_alloc_coherent(mvi->dev,
+ TRASH_BUCKET_SIZE,
+ &mvi->bulk_buffer_dma1, GFP_KERNEL);
+ if (!mvi->bulk_buffer1)
+ goto err_out;
+
sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id);
mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0);
if (!mvi->dma_pool) {
@@ -354,11 +379,12 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent,
struct Scsi_Host *shost, unsigned int id)
{
- struct mvs_info *mvi;
+ struct mvs_info *mvi = NULL;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
- mvi = kzalloc(sizeof(*mvi) + MVS_SLOTS * sizeof(struct mvs_slot_info),
- GFP_KERNEL);
+ mvi = kzalloc(sizeof(*mvi) +
+ (1L << mvs_chips[ent->driver_data].slot_width) *
+ sizeof(struct mvs_slot_info), GFP_KERNEL);
if (!mvi)
return NULL;
@@ -367,7 +393,6 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
mvi->chip_id = ent->driver_data;
mvi->chip = &mvs_chips[mvi->chip_id];
INIT_LIST_HEAD(&mvi->wq_list);
- mvi->irq = pdev->irq;
((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi;
((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy;
@@ -375,9 +400,10 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
mvi->id = id;
mvi->sas = sha;
mvi->shost = shost;
-#ifdef MVS_USE_TASKLET
- tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha);
-#endif
+
+ mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL);
+ if (!mvi->tags)
+ goto err_out;
if (MVS_CHIP_DISP->chip_ioremap(mvi))
goto err_out;
@@ -388,7 +414,6 @@ err_out:
return NULL;
}
-/* move to PCI layer or libata core? */
static int pci_go_64(struct pci_dev *pdev)
{
int rc;
@@ -450,7 +475,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
shost->transportt = mvs_stt;
- shost->max_id = 128;
+ shost->max_id = MVS_MAX_DEVICES;
shost->max_lun = ~0;
shost->max_channel = 1;
shost->max_cmd_len = 16;
@@ -493,11 +518,12 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
if (mvi->flags & MVF_FLAG_SOC)
can_queue = MVS_SOC_CAN_QUEUE;
else
- can_queue = MVS_CAN_QUEUE;
+ can_queue = MVS_CHIP_SLOT_SZ;
sha->lldd_queue_size = can_queue;
+ shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
shost->can_queue = can_queue;
- mvi->shost->cmd_per_lun = MVS_SLOTS/sha->num_phys;
+ mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
sha->core.shost = mvi->shost;
}
@@ -518,6 +544,7 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
{
unsigned int rc, nhost = 0;
struct mvs_info *mvi;
+ struct mvs_prv_info *mpi;
irq_handler_t irq_handler = mvs_interrupt;
struct Scsi_Host *shost = NULL;
const struct mvs_chip_info *chip;
@@ -569,6 +596,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
goto err_out_regions;
}
+ memset(&mvi->hba_info_param, 0xFF,
+ sizeof(struct hba_info_page));
+
mvs_init_sas_add(mvi);
mvi->instance = nhost;
@@ -579,8 +609,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
}
nhost++;
} while (nhost < chip->n_host);
-#ifdef MVS_USE_TASKLET
- tasklet_init(&mv_tasklet, mvs_tasklet,
+ mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+ tasklet_init(&(mpi->mv_tasklet), mvs_tasklet,
(unsigned long)SHOST_TO_SAS_HA(shost));
#endif
@@ -625,8 +656,8 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
-#ifdef MVS_USE_TASKLET
- tasklet_kill(&mv_tasklet);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+ tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
#endif
pci_set_drvdata(pdev, NULL);
@@ -635,7 +666,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
scsi_remove_host(mvi->shost);
MVS_CHIP_DISP->interrupt_disable(mvi);
- free_irq(mvi->irq, sha);
+ free_irq(mvi->pdev->irq, sha);
for (i = 0; i < core_nr; i++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
mvs_free(mvi);
@@ -676,6 +707,15 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
{
.vendor = 0x1b4b,
+ .device = 0x9480,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = 0x9480,
+ .class = 0,
+ .class_mask = 0,
+ .driver_data = chip_9480,
+ },
+ {
+ .vendor = 0x1b4b,
.device = 0x9445,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
@@ -692,6 +732,16 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
.class_mask = 0,
.driver_data = chip_9485,
},
+ { PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */
+ { PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1041), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1042), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1043), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1044), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1080), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1083), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+ { PCI_VDEVICE(OCZ, 0x1084), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
{ } /* terminate list */
};
@@ -703,6 +753,70 @@ static struct pci_driver mvs_pci_driver = {
.remove = __devexit_p(mvs_pci_remove),
};
+static ssize_t
+mvs_show_driver_version(struct device *cdev,
+ struct device_attribute *attr, char *buffer)
+{
+ return snprintf(buffer, PAGE_SIZE, "%s\n", DRV_VERSION);
+}
+
+static DEVICE_ATTR(driver_version,
+ S_IRUGO,
+ mvs_show_driver_version,
+ NULL);
+
+static ssize_t
+mvs_store_interrupt_coalescing(struct device *cdev,
+ struct device_attribute *attr,
+ const char *buffer, size_t size)
+{
+ int val = 0;
+ struct mvs_info *mvi = NULL;
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ u8 i, core_nr;
+ if (buffer == NULL)
+ return size;
+
+ if (sscanf(buffer, "%d", &val) != 1)
+ return -EINVAL;
+
+ if (val >= 0x10000) {
+ mv_dprintk("interrupt coalescing timer %d us is"
+ "too long\n", val);
+ return strlen(buffer);
+ }
+
+ interrupt_coalescing = val;
+
+ core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
+
+ if (unlikely(!mvi))
+ return -EINVAL;
+
+ for (i = 0; i < core_nr; i++) {
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
+ if (MVS_CHIP_DISP->tune_interrupt)
+ MVS_CHIP_DISP->tune_interrupt(mvi,
+ interrupt_coalescing);
+ }
+ mv_dprintk("set interrupt coalescing time to %d us\n",
+ interrupt_coalescing);
+ return strlen(buffer);
+}
+
+static ssize_t mvs_show_interrupt_coalescing(struct device *cdev,
+ struct device_attribute *attr, char *buffer)
+{
+ return snprintf(buffer, PAGE_SIZE, "%d\n", interrupt_coalescing);
+}
+
+static DEVICE_ATTR(interrupt_coalescing,
+ S_IRUGO|S_IWUSR,
+ mvs_show_interrupt_coalescing,
+ mvs_store_interrupt_coalescing);
+
/* task handler */
struct task_struct *mvs_th;
static int __init mvs_init(void)
@@ -739,6 +853,12 @@ static void __exit mvs_exit(void)
kmem_cache_destroy(mvs_task_list_cache);
}
+struct device_attribute *mvst_host_attrs[] = {
+ &dev_attr_driver_version,
+ &dev_attr_interrupt_coalescing,
+ NULL,
+};
+
module_init(mvs_init);
module_exit(mvs_exit);
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 0ef2742..c6ad694 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -38,7 +38,7 @@ static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)
void mvs_tag_clear(struct mvs_info *mvi, u32 tag)
{
- void *bitmap = &mvi->tags;
+ void *bitmap = mvi->tags;
clear_bit(tag, bitmap);
}
@@ -49,14 +49,14 @@ void mvs_tag_free(struct mvs_info *mvi, u32 tag)
void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)
{
- void *bitmap = &mvi->tags;
+ void *bitmap = mvi->tags;
set_bit(tag, bitmap);
}
inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)
{
unsigned int index, tag;
- void *bitmap = &mvi->tags;
+ void *bitmap = mvi->tags;
index = find_first_zero_bit(bitmap, mvi->tags_num);
tag = index;
@@ -74,126 +74,6 @@ void mvs_tag_init(struct mvs_info *mvi)
mvs_tag_clear(mvi, i);
}
-void mvs_hexdump(u32 size, u8 *data, u32 baseaddr)
-{
- u32 i;
- u32 run;
- u32 offset;
-
- offset = 0;
- while (size) {
- printk(KERN_DEBUG"%08X : ", baseaddr + offset);
- if (size >= 16)
- run = 16;
- else
- run = size;
- size -= run;
- for (i = 0; i < 16; i++) {
- if (i < run)
- printk(KERN_DEBUG"%02X ", (u32)data[i]);
- else
- printk(KERN_DEBUG" ");
- }
- printk(KERN_DEBUG": ");
- for (i = 0; i < run; i++)
- printk(KERN_DEBUG"%c",
- isalnum(data[i]) ? data[i] : '.');
- printk(KERN_DEBUG"\n");
- data = &data[16];
- offset += run;
- }
- printk(KERN_DEBUG"\n");
-}
-
-#if (_MV_DUMP > 1)
-static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag,
- enum sas_protocol proto)
-{
- u32 offset;
- struct mvs_slot_info *slot = &mvi->slot_info[tag];
-
- offset = slot->cmd_size + MVS_OAF_SZ +
- MVS_CHIP_DISP->prd_size() * slot->n_elem;
- dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n",
- tag);
- mvs_hexdump(32, (u8 *) slot->response,
- (u32) slot->buf_dma + offset);
-}
-#endif
-
-static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag,
- enum sas_protocol proto)
-{
-#if (_MV_DUMP > 1)
- u32 sz, w_ptr;
- u64 addr;
- struct mvs_slot_info *slot = &mvi->slot_info[tag];
-
- /*Delivery Queue */
- sz = MVS_CHIP_SLOT_SZ;
- w_ptr = slot->tx;
- addr = mvi->tx_dma;
- dev_printk(KERN_DEBUG, mvi->dev,
- "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr);
- dev_printk(KERN_DEBUG, mvi->dev,
- "Delivery Queue Base Address=0x%llX (PA)"
- "(tx_dma=0x%llX), Entry=%04d\n",
- addr, (unsigned long long)mvi->tx_dma, w_ptr);
- mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]),
- (u32) mvi->tx_dma + sizeof(u32) * w_ptr);
- /*Command List */
- addr = mvi->slot_dma;
- dev_printk(KERN_DEBUG, mvi->dev,
- "Command List Base Address=0x%llX (PA)"
- "(slot_dma=0x%llX), Header=%03d\n",
- addr, (unsigned long long)slot->buf_dma, tag);
- dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag);
- /*mvs_cmd_hdr */
- mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]),
- (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr));
- /*1.command table area */
- dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n");
- mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma);
- /*2.open address frame area */
- dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n");
- mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size,
- (u32) slot->buf_dma + slot->cmd_size);
- /*3.status buffer */
- mvs_hba_sb_dump(mvi, tag, proto);
- /*4.PRD table */
- dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n");
- mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem,
- (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ,
- (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ);
-#endif
-}
-
-static void mvs_hba_cq_dump(struct mvs_info *mvi)
-{
-#if (_MV_DUMP > 2)
- u64 addr;
- void __iomem *regs = mvi->regs;
- u32 entry = mvi->rx_cons + 1;
- u32 rx_desc = le32_to_cpu(mvi->rx[entry]);
-
- /*Completion Queue */
- addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO);
- dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n",
- mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task);
- dev_printk(KERN_DEBUG, mvi->dev,
- "Completion List Base Address=0x%llX (PA), "
- "CQ_Entry=%04d, CQ_WP=0x%08X\n",
- addr, entry - 1, mvi->rx[0]);
- mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc),
- mvi->rx_dma + sizeof(u32) * entry);
-#endif
-}
-
-void mvs_get_sas_addr(void *buf, u32 buflen)
-{
- /*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/
-}
-
struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
{
unsigned long i = 0, j = 0, hi = 0;
@@ -222,7 +102,6 @@ struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
}
-/* FIXME */
int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
{
unsigned long i = 0, j = 0, n = 0, num = 0;
@@ -253,6 +132,20 @@ int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
return num;
}
+struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi,
+ u8 reg_set)
+{
+ u32 dev_no;
+ for (dev_no = 0; dev_no < MVS_MAX_DEVICES; dev_no++) {
+ if (mvi->devices[dev_no].taskfileset == MVS_ID_NOT_MAPPED)
+ continue;
+
+ if (mvi->devices[dev_no].taskfileset == reg_set)
+ return &mvi->devices[dev_no];
+ }
+ return NULL;
+}
+
static inline void mvs_free_reg_set(struct mvs_info *mvi,
struct mvs_device *dev)
{
@@ -283,7 +176,6 @@ void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard)
}
}
-/* FIXME: locking? */
int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata)
{
@@ -309,12 +201,12 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);
if (tmp & PHY_RST_HARD)
break;
- MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1);
+ MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET);
break;
case PHY_FUNC_LINK_RESET:
MVS_CHIP_DISP->phy_enable(mvi, phy_id);
- MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0);
+ MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_SOFT_RESET);
break;
case PHY_FUNC_DISABLE:
@@ -322,7 +214,7 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_RELEASE_SPINUP_HOLD:
default:
- rc = -EOPNOTSUPP;
+ rc = -ENOSYS;
}
msleep(200);
return rc;
@@ -373,6 +265,12 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
id->dev_type = phy->identify.device_type;
id->initiator_bits = SAS_PROTOCOL_ALL;
id->target_bits = phy->identify.target_port_protocols;
+
+ /* direct attached SAS device */
+ if (phy->att_dev_info & PORT_SSP_TRGT_MASK) {
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, i, 0x00);
+ }
} else if (phy->phy_type & PORT_TYPE_SATA) {
/*Nothing*/
}
@@ -384,46 +282,13 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
PORTE_BYTES_DMAED);
}
-int mvs_slave_alloc(struct scsi_device *scsi_dev)
-{
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- if (dev_is_sata(dev)) {
- /* We don't need to rescan targets
- * if REPORT_LUNS request is failed
- */
- if (scsi_dev->lun > 0)
- return -ENXIO;
- scsi_dev->tagged_supported = 1;
- }
-
- return sas_slave_alloc(scsi_dev);
-}
-
-int mvs_slave_configure(struct scsi_device *sdev)
-{
- struct domain_device *dev = sdev_to_domain_dev(sdev);
- int ret = sas_slave_configure(sdev);
-
- if (ret)
- return ret;
- if (dev_is_sata(dev)) {
- /* may set PIO mode */
- #if MV_DISABLE_NCQ
- struct ata_port *ap = dev->sata_dev.ap;
- struct ata_device *adev = ap->link.device;
- adev->flags |= ATA_DFLAG_NCQ_OFF;
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
- #endif
- }
- return 0;
-}
-
void mvs_scan_start(struct Scsi_Host *shost)
{
int i, j;
unsigned short core_nr;
struct mvs_info *mvi;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ struct mvs_prv_info *mvs_prv = sha->lldd_ha;
core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
@@ -432,15 +297,17 @@ void mvs_scan_start(struct Scsi_Host *shost)
for (i = 0; i < mvi->chip->n_phy; ++i)
mvs_bytes_dmaed(mvi, i);
}
+ mvs_prv->scan_finished = 1;
}
int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
- /* give the phy enabling interrupt event time to come in (1s
- * is empirically about all it takes) */
- if (time < HZ)
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ struct mvs_prv_info *mvs_prv = sha->lldd_ha;
+
+ if (mvs_prv->scan_finished == 0)
return 0;
- /* Wait for discovery to finish */
+
scsi_flush_work(shost);
return 1;
}
@@ -461,10 +328,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
void *buf_prd;
struct mvs_slot_info *slot = &mvi->slot_info[tag];
u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#if _MV_DUMP
- u8 *buf_cmd;
- void *from;
-#endif
+
/*
* DMA-map SMP request, response buffers
*/
@@ -496,15 +360,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
buf_tmp = slot->buf;
buf_tmp_dma = slot->buf_dma;
-#if _MV_DUMP
- buf_cmd = buf_tmp;
- hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
- buf_tmp += req_len;
- buf_tmp_dma += req_len;
- slot->cmd_size = req_len;
-#else
hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req));
-#endif
/* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
buf_oaf = buf_tmp;
@@ -546,19 +402,13 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
/* generate open address frame hdr (first 12 bytes) */
/* initiator, SMP, ftype 1h */
buf_oaf[0] = (1 << 7) | (PROTOCOL_SMP << 4) | 0x01;
- buf_oaf[1] = dev->linkrate & 0xf;
+ buf_oaf[1] = min(sas_port->linkrate, dev->linkrate) & 0xf;
*(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */
memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
/* fill in PRD (scatter/gather) table, if any */
MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
-#if _MV_DUMP
- /* copy cmd table */
- from = kmap_atomic(sg_page(sg_req), KM_IRQ0);
- memcpy(buf_cmd, from + sg_req->offset, req_len);
- kunmap_atomic(from, KM_IRQ0);
-#endif
return 0;
err_out_2:
@@ -616,14 +466,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
(mvi_dev->taskfileset << TXQ_SRS_SHIFT);
mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
if (task->data_dir == DMA_FROM_DEVICE)
flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT);
else
flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#else
- flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#endif
+
if (task->ata_task.use_ncq)
flags |= MCH_FPDMA;
if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
@@ -631,11 +478,8 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
flags |= MCH_ATAPI;
}
- /* FIXME: fill in port multiplier number */
-
hdr->flags = cpu_to_le32(flags);
- /* FIXME: the low order order 5 bits for the TAG if enable NCQ */
if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr_tag))
task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
else
@@ -657,9 +501,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
buf_tmp += MVS_ATA_CMD_SZ;
buf_tmp_dma += MVS_ATA_CMD_SZ;
-#if _MV_DUMP
- slot->cmd_size = MVS_ATA_CMD_SZ;
-#endif
/* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
/* used for STP. unused for SATA? */
@@ -682,9 +523,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
buf_tmp_dma += i;
/* region 4: status buffer (larger the PRD, smaller this buf) ****** */
- /* FIXME: probably unused, for SATA. kept here just in case
- * we get a STP/SATA error information record
- */
slot->response = buf_tmp;
hdr->status_buf = cpu_to_le64(buf_tmp_dma);
if (mvi->flags & MVF_FLAG_SOC)
@@ -709,17 +547,17 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
/* generate open address frame hdr (first 12 bytes) */
/* initiator, STP, ftype 1h */
buf_oaf[0] = (1 << 7) | (PROTOCOL_STP << 4) | 0x1;
- buf_oaf[1] = dev->linkrate & 0xf;
+ buf_oaf[1] = min(sas_port->linkrate, dev->linkrate) & 0xf;
*(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1);
memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
/* fill in PRD (scatter/gather) table, if any */
MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
+
if (task->data_dir == DMA_FROM_DEVICE)
- MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma,
+ MVS_CHIP_DISP->dma_fix(mvi, sas_port->phy_mask,
TRASH_BUCKET_SIZE, tei->n_elem, buf_prd);
-#endif
+
return 0;
}
@@ -761,6 +599,9 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
}
if (is_tmf)
flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT);
+ else
+ flags |= (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT);
+
hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT));
hdr->tags = cpu_to_le32(tag);
hdr->data_len = cpu_to_le32(task->total_xfer_len);
@@ -777,9 +618,6 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
buf_tmp += MVS_SSP_CMD_SZ;
buf_tmp_dma += MVS_SSP_CMD_SZ;
-#if _MV_DUMP
- slot->cmd_size = MVS_SSP_CMD_SZ;
-#endif
/* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
buf_oaf = buf_tmp;
@@ -817,7 +655,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
/* generate open address frame hdr (first 12 bytes) */
/* initiator, SSP, ftype 1h */
buf_oaf[0] = (1 << 7) | (PROTOCOL_SSP << 4) | 0x1;
- buf_oaf[1] = dev->linkrate & 0xf;
+ buf_oaf[1] = min(sas_port->linkrate, dev->linkrate) & 0xf;
*(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1);
memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
@@ -986,7 +824,6 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock(&task->task_state_lock);
- mvs_hba_memory_dump(mvi, tag, task->task_proto);
mvi_dev->running_req++;
++(*pass);
mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
@@ -1189,9 +1026,9 @@ static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
mvs_slot_free(mvi, slot_idx);
}
-static void mvs_update_wideport(struct mvs_info *mvi, int i)
+static void mvs_update_wideport(struct mvs_info *mvi, int phy_no)
{
- struct mvs_phy *phy = &mvi->phy[i];
+ struct mvs_phy *phy = &mvi->phy[phy_no];
struct mvs_port *port = phy->port;
int j, no;
@@ -1246,18 +1083,17 @@ static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
return NULL;
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3);
- s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+ s[3] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2);
- s[2] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+ s[2] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1);
- s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+ s[1] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0);
- s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+ s[0] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
- /* Workaround: take some ATAPI devices for ATA */
if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01))
s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10);
@@ -1269,6 +1105,13 @@ static u32 mvs_is_sig_fis_received(u32 irq_status)
return irq_status & PHYEV_SIG_FIS;
}
+static void mvs_sig_remove_timer(struct mvs_phy *phy)
+{
+ if (phy->timer.function)
+ del_timer(&phy->timer);
+ phy->timer.function = NULL;
+}
+
void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
{
struct mvs_phy *phy = &mvi->phy[i];
@@ -1291,6 +1134,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
if (phy->phy_type & PORT_TYPE_SATA) {
phy->identify.target_port_protocols = SAS_PROTOCOL_STP;
if (mvs_is_sig_fis_received(phy->irq_status)) {
+ mvs_sig_remove_timer(phy);
phy->phy_attached = 1;
phy->att_dev_sas_addr =
i + mvi->id * mvi->chip->n_phy;
@@ -1308,7 +1152,6 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
tmp | PHYEV_SIG_FIS);
phy->phy_attached = 0;
phy->phy_type &= ~PORT_TYPE_SATA;
- MVS_CHIP_DISP->phy_reset(mvi, i, 0);
goto out_done;
}
} else if (phy->phy_type & PORT_TYPE_SAS
@@ -1334,9 +1177,9 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
if (MVS_CHIP_DISP->phy_work_around)
MVS_CHIP_DISP->phy_work_around(mvi, i);
}
- mv_dprintk("port %d attach dev info is %x\n",
+ mv_dprintk("phy %d attach dev info is %x\n",
i + mvi->id * mvi->chip->n_phy, phy->att_dev_info);
- mv_dprintk("port %d attach sas addr is %llx\n",
+ mv_dprintk("phy %d attach sas addr is %llx\n",
i + mvi->id * mvi->chip->n_phy, phy->att_dev_sas_addr);
out_done:
if (get_st)
@@ -1361,10 +1204,10 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
}
hi = i/((struct mvs_prv_info *)sas_ha->lldd_ha)->n_phy;
mvi = ((struct mvs_prv_info *)sas_ha->lldd_ha)->mvi[hi];
- if (sas_port->id >= mvi->chip->n_phy)
- port = &mvi->port[sas_port->id - mvi->chip->n_phy];
+ if (i >= mvi->chip->n_phy)
+ port = &mvi->port[i - mvi->chip->n_phy];
else
- port = &mvi->port[sas_port->id];
+ port = &mvi->port[i];
if (lock)
spin_lock_irqsave(&mvi->lock, flags);
port->port_attached = 1;
@@ -1374,6 +1217,12 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
port->wide_port_phymap = sas_port->phy_mask;
mv_printk("set wide port phy map %x\n", sas_port->phy_mask);
mvs_update_wideport(mvi, sas_phy->id);
+
+ /* direct attached SAS device */
+ if (phy->att_dev_info & PORT_SSP_TRGT_MASK) {
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, i, 0x04);
+ }
}
if (lock)
spin_unlock_irqrestore(&mvi->lock, flags);
@@ -1393,7 +1242,7 @@ static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock)
return;
}
list_for_each_entry(dev, &port->dev_list, dev_list_node)
- mvs_do_release_task(phy->mvi, phy_no, NULL);
+ mvs_do_release_task(phy->mvi, phy_no, dev);
}
@@ -1457,6 +1306,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock)
mvi_device->dev_status = MVS_DEV_NORMAL;
mvi_device->dev_type = dev->dev_type;
mvi_device->mvi_info = mvi;
+ mvi_device->sas_device = dev;
if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
int phy_id;
u8 phy_num = parent_dev->ex_dev.num_phys;
@@ -1508,6 +1358,7 @@ void mvs_dev_gone_notify(struct domain_device *dev)
mv_dprintk("found dev has gone.\n");
}
dev->lldd_dev = NULL;
+ mvi_dev->sas_device = NULL;
spin_unlock_irqrestore(&mvi->lock, flags);
}
@@ -1518,28 +1369,6 @@ void mvs_dev_gone(struct domain_device *dev)
mvs_dev_gone_notify(dev);
}
-static struct sas_task *mvs_alloc_task(void)
-{
- struct sas_task *task = kzalloc(sizeof(struct sas_task), GFP_KERNEL);
-
- if (task) {
- INIT_LIST_HEAD(&task->list);
- spin_lock_init(&task->task_state_lock);
- task->task_state_flags = SAS_TASK_STATE_PENDING;
- init_timer(&task->timer);
- init_completion(&task->completion);
- }
- return task;
-}
-
-static void mvs_free_task(struct sas_task *task)
-{
- if (task) {
- BUG_ON(!list_empty(&task->list));
- kfree(task);
- }
-}
-
static void mvs_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
@@ -1555,7 +1384,6 @@ static void mvs_tmf_timedout(unsigned long data)
complete(&task->completion);
}
-/* XXX */
#define MVS_TASK_TIMEOUT 20
static int mvs_exec_internal_tmf_task(struct domain_device *dev,
void *parameter, u32 para_len, struct mvs_tmf_task *tmf)
@@ -1564,7 +1392,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
struct sas_task *task = NULL;
for (retry = 0; retry < 3; retry++) {
- task = mvs_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -1588,7 +1416,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
}
wait_for_completion(&task->completion);
- res = -TMF_RESP_FUNC_FAILED;
+ res = TMF_RESP_FUNC_FAILED;
/* Even TMF timed out, return direct. */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
@@ -1622,15 +1450,14 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat);
- mvs_free_task(task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- if (task != NULL)
- mvs_free_task(task);
+ sas_free_task(task);
return res;
}
@@ -1638,11 +1465,10 @@ static int mvs_debug_issue_ssp_tmf(struct domain_device *dev,
u8 *lun, struct mvs_tmf_task *tmf)
{
struct sas_ssp_task ssp_task;
- DECLARE_COMPLETION_ONSTACK(completion);
if (!(dev->tproto & SAS_PROTOCOL_SSP))
return TMF_RESP_FUNC_ESUPP;
- strncpy((u8 *)&ssp_task.LUN, lun, 8);
+ memcpy(ssp_task.LUN, lun, 8);
return mvs_exec_internal_tmf_task(dev, &ssp_task,
sizeof(ssp_task), tmf);
@@ -1666,7 +1492,7 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
int mvs_lu_reset(struct domain_device *dev, u8 *lun)
{
unsigned long flags;
- int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
+ int rc = TMF_RESP_FUNC_FAILED;
struct mvs_tmf_task tmf_task;
struct mvs_device * mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
@@ -1675,10 +1501,8 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)
mvi_dev->dev_status = MVS_DEV_EH;
rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
if (rc == TMF_RESP_FUNC_COMPLETE) {
- num = mvs_find_dev_phyno(dev, phyno);
spin_lock_irqsave(&mvi->lock, flags);
- for (i = 0; i < num; i++)
- mvs_release_task(mvi, dev);
+ mvs_release_task(mvi, dev);
spin_unlock_irqrestore(&mvi->lock, flags);
}
/* If failed, fall-through I_T_Nexus reset */
@@ -1696,11 +1520,12 @@ int mvs_I_T_nexus_reset(struct domain_device *dev)
if (mvi_dev->dev_status != MVS_DEV_EH)
return TMF_RESP_FUNC_COMPLETE;
+ else
+ mvi_dev->dev_status = MVS_DEV_NORMAL;
rc = mvs_debug_I_T_nexus_reset(dev);
mv_printk("%s for device[%x]:rc= %d\n",
__func__, mvi_dev->device_id, rc);
- /* housekeeper */
spin_lock_irqsave(&mvi->lock, flags);
mvs_release_task(mvi, dev);
spin_unlock_irqrestore(&mvi->lock, flags);
@@ -1739,9 +1564,6 @@ int mvs_query_task(struct sas_task *task)
case TMF_RESP_FUNC_FAILED:
case TMF_RESP_FUNC_COMPLETE:
break;
- default:
- rc = TMF_RESP_FUNC_COMPLETE;
- break;
}
}
mv_printk("%s:rc= %d\n", __func__, rc);
@@ -1761,8 +1583,8 @@ int mvs_abort_task(struct sas_task *task)
u32 tag;
if (!mvi_dev) {
- mv_printk("%s:%d TMF_RESP_FUNC_FAILED\n", __func__, __LINE__);
- rc = TMF_RESP_FUNC_FAILED;
+ mv_printk("Device has removed\n");
+ return TMF_RESP_FUNC_FAILED;
}
mvi = mvi_dev->mvi_info;
@@ -1807,25 +1629,17 @@ int mvs_abort_task(struct sas_task *task)
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
- /* to do free register_set */
if (SATA_DEV == dev->dev_type) {
struct mvs_slot_info *slot = task->lldd_task;
- struct task_status_struct *tstat;
u32 slot_idx = (u32)(slot - mvi->slot_info);
- tstat = &task->task_status;
- mv_dprintk(KERN_DEBUG "mv_abort_task() mvi=%p task=%p "
+ mv_dprintk("mvs_abort_task() mvi=%p task=%p "
"slot=%p slot_idx=x%x\n",
mvi, task, slot, slot_idx);
- tstat->stat = SAS_ABORTED_TASK;
- if (mvi_dev && mvi_dev->running_req)
- mvi_dev->running_req--;
- if (sas_protocol_ata(task->task_proto))
- mvs_free_reg_set(mvi, mvi_dev);
+ task->task_state_flags |= SAS_TASK_STATE_ABORTED;
mvs_slot_task_free(mvi, task, slot, slot_idx);
- return -1;
+ rc = TMF_RESP_FUNC_COMPLETE;
+ goto out;
}
- } else {
- /* SMP */
}
out:
@@ -1891,12 +1705,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
return stat;
}
+void mvs_set_sense(u8 *buffer, int len, int d_sense,
+ int key, int asc, int ascq)
+{
+ memset(buffer, 0, len);
+
+ if (d_sense) {
+ /* Descriptor format */
+ if (len < 4) {
+ mv_printk("Length %d of sense buffer too small to "
+ "fit sense %x:%x:%x", len, key, asc, ascq);
+ }
+
+ buffer[0] = 0x72; /* Response Code */
+ if (len > 1)
+ buffer[1] = key; /* Sense Key */
+ if (len > 2)
+ buffer[2] = asc; /* ASC */
+ if (len > 3)
+ buffer[3] = ascq; /* ASCQ */
+ } else {
+ if (len < 14) {
+ mv_printk("Length %d of sense buffer too small to "
+ "fit sense %x:%x:%x", len, key, asc, ascq);
+ }
+
+ buffer[0] = 0x70; /* Response Code */
+ if (len > 2)
+ buffer[2] = key; /* Sense Key */
+ if (len > 7)
+ buffer[7] = 0x0a; /* Additional Sense Length */
+ if (len > 12)
+ buffer[12] = asc; /* ASC */
+ if (len > 13)
+ buffer[13] = ascq; /* ASCQ */
+ }
+
+ return;
+}
+
+void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu,
+ u8 key, u8 asc, u8 asc_q)
+{
+ iu->datapres = 2;
+ iu->response_data_len = 0;
+ iu->sense_data_len = 17;
+ iu->status = 02;
+ mvs_set_sense(iu->sense_data, 17, 0,
+ key, asc, asc_q);
+}
+
static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
u32 slot_idx)
{
struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
int stat;
- u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
+ u32 err_dw0 = le32_to_cpu(*(u32 *)slot->response);
+ u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1));
u32 tfs = 0;
enum mvs_port_type type = PORT_TYPE_SAS;
@@ -1908,8 +1773,19 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
stat = SAM_STAT_CHECK_CONDITION;
switch (task->task_proto) {
case SAS_PROTOCOL_SSP:
+ {
stat = SAS_ABORTED_TASK;
+ if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) {
+ struct ssp_response_iu *iu = slot->response +
+ sizeof(struct mvs_err_info);
+ mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01);
+ sas_ssp_task_response(mvi->dev, task, iu);
+ stat = SAM_STAT_CHECK_CONDITION;
+ }
+ if (err_dw1 & bit(31))
+ mv_printk("reuse same slot, retry command.\n");
break;
+ }
case SAS_PROTOCOL_SMP:
stat = SAM_STAT_CHECK_CONDITION;
break;
@@ -1918,10 +1794,8 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
{
- if (err_dw0 == 0x80400002)
- mv_printk("find reserved error, why?\n");
-
task->ata_task.use_ncq = 0;
+ stat = SAS_PROTO_RESPONSE;
mvs_sata_done(mvi, task, slot_idx, err_dw0);
}
break;
@@ -1945,8 +1819,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
void *to;
enum exec_status sts;
- if (mvi->exp_req)
- mvi->exp_req--;
if (unlikely(!task || !task->lldd_task || !task->dev))
return -1;
@@ -1954,8 +1826,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
dev = task->dev;
mvi_dev = dev->lldd_dev;
- mvs_hba_cq_dump(mvi);
-
spin_lock(&task->task_state_lock);
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
@@ -1978,6 +1848,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
return -1;
}
+ /* when no device attaching, go ahead and complete by error handling*/
if (unlikely(!mvi_dev || flags)) {
if (!mvi_dev)
mv_dprintk("port has not device.\n");
@@ -1987,6 +1858,9 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
/* error info record present */
if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
+ mv_dprintk("port %d slot %d rx_desc %X has error info"
+ "%016llX.\n", slot->port->sas_port.id, slot_idx,
+ rx_desc, (u64)(*(u64 *)slot->response));
tstat->stat = mvs_slot_err(mvi, task, slot_idx);
tstat->resp = SAS_TASK_COMPLETE;
goto out;
@@ -2048,8 +1922,7 @@ out:
spin_unlock(&mvi->lock);
if (task->task_done)
task->task_done(task);
- else
- mv_dprintk("why has not task_done.\n");
+
spin_lock(&mvi->lock);
return sts;
@@ -2092,7 +1965,6 @@ void mvs_release_task(struct mvs_info *mvi,
struct domain_device *dev)
{
int i, phyno[WIDE_PORT_MAX_PHY], num;
- /* housekeeper */
num = mvs_find_dev_phyno(dev, phyno);
for (i = 0; i < num; i++)
mvs_do_release_task(mvi, phyno[i], dev);
@@ -2111,13 +1983,13 @@ static void mvs_work_queue(struct work_struct *work)
struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
struct mvs_info *mvi = mwq->mvi;
unsigned long flags;
+ u32 phy_no = (unsigned long) mwq->data;
+ struct sas_ha_struct *sas_ha = mvi->sas;
+ struct mvs_phy *phy = &mvi->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
spin_lock_irqsave(&mvi->lock, flags);
if (mwq->handler & PHY_PLUG_EVENT) {
- u32 phy_no = (unsigned long) mwq->data;
- struct sas_ha_struct *sas_ha = mvi->sas;
- struct mvs_phy *phy = &mvi->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
if (phy->phy_event & PHY_PLUG_OUT) {
u32 tmp;
@@ -2139,6 +2011,11 @@ static void mvs_work_queue(struct work_struct *work)
mv_dprintk("phy%d Attached Device\n", phy_no);
}
}
+ } else if (mwq->handler & EXP_BRCT_CHG) {
+ phy->phy_event &= ~EXP_BRCT_CHG;
+ sas_ha->notify_port_event(sas_phy,
+ PORTE_BROADCAST_RCVD);
+ mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
}
list_del(&mwq->entry);
spin_unlock_irqrestore(&mvi->lock, flags);
@@ -2174,29 +2051,21 @@ static void mvs_sig_time_out(unsigned long tphy)
if (&mvi->phy[phy_no] == phy) {
mv_dprintk("Get signature time out, reset phy %d\n",
phy_no+mvi->id*mvi->chip->n_phy);
- MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1);
+ MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET);
}
}
}
-static void mvs_sig_remove_timer(struct mvs_phy *phy)
-{
- if (phy->timer.function)
- del_timer(&phy->timer);
- phy->timer.function = NULL;
-}
-
void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
{
u32 tmp;
- struct sas_ha_struct *sas_ha = mvi->sas;
struct mvs_phy *phy = &mvi->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
- mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy,
+ MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
+ mv_dprintk("phy %d ctrl sts=0x%08X.\n", phy_no+mvi->id*mvi->chip->n_phy,
MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no));
- mv_dprintk("Port %d irq sts = 0x%X\n", phy_no+mvi->id*mvi->chip->n_phy,
+ mv_dprintk("phy %d irq sts = 0x%08X\n", phy_no+mvi->id*mvi->chip->n_phy,
phy->irq_status);
/*
@@ -2205,11 +2074,12 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
*/
if (phy->irq_status & PHYEV_DCDR_ERR) {
- mv_dprintk("port %d STP decoding error.\n",
+ mv_dprintk("phy %d STP decoding error.\n",
phy_no + mvi->id*mvi->chip->n_phy);
}
if (phy->irq_status & PHYEV_POOF) {
+ mdelay(500);
if (!(phy->phy_event & PHY_PLUG_OUT)) {
int dev_sata = phy->phy_type & PORT_TYPE_SATA;
int ready;
@@ -2220,17 +2090,13 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
(void *)(unsigned long)phy_no,
PHY_PLUG_EVENT);
ready = mvs_is_phy_ready(mvi, phy_no);
- if (!ready)
- mv_dprintk("phy%d Unplug Notice\n",
- phy_no +
- mvi->id * mvi->chip->n_phy);
if (ready || dev_sata) {
if (MVS_CHIP_DISP->stp_reset)
MVS_CHIP_DISP->stp_reset(mvi,
phy_no);
else
MVS_CHIP_DISP->phy_reset(mvi,
- phy_no, 0);
+ phy_no, MVS_SOFT_RESET);
return;
}
}
@@ -2243,13 +2109,12 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
if (phy->timer.function == NULL) {
phy->timer.data = (unsigned long)phy;
phy->timer.function = mvs_sig_time_out;
- phy->timer.expires = jiffies + 10*HZ;
+ phy->timer.expires = jiffies + 5*HZ;
add_timer(&phy->timer);
}
}
if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) {
phy->phy_status = mvs_is_phy_ready(mvi, phy_no);
- mvs_sig_remove_timer(phy);
mv_dprintk("notify plug in on phy[%d]\n", phy_no);
if (phy->phy_status) {
mdelay(10);
@@ -2263,14 +2128,14 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
}
mvs_update_phyinfo(mvi, phy_no, 0);
if (phy->phy_type & PORT_TYPE_SAS) {
- MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2);
+ MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE);
mdelay(10);
}
mvs_bytes_dmaed(mvi, phy_no);
/* whether driver is going to handle hot plug */
if (phy->phy_event & PHY_PLUG_OUT) {
- mvs_port_notify_formed(sas_phy, 0);
+ mvs_port_notify_formed(&phy->sas_phy, 0);
phy->phy_event &= ~PHY_PLUG_OUT;
}
} else {
@@ -2278,13 +2143,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
phy_no + mvi->id*mvi->chip->n_phy);
}
} else if (phy->irq_status & PHYEV_BROAD_CH) {
- mv_dprintk("port %d broadcast change.\n",
+ mv_dprintk("phy %d broadcast change.\n",
phy_no + mvi->id*mvi->chip->n_phy);
- /* exception for Samsung disk drive*/
- mdelay(1000);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ mvs_handle_event(mvi, (void *)(unsigned long)phy_no,
+ EXP_BRCT_CHG);
}
- MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
}
int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index efc6965..da24955 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -43,17 +43,12 @@
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/sas_ata.h>
-#include <linux/version.h>
#include "mv_defs.h"
#define DRV_NAME "mvsas"
-#define DRV_VERSION "0.8.2"
-#define _MV_DUMP 0
+#define DRV_VERSION "0.8.16"
#define MVS_ID_NOT_MAPPED 0x7f
-/* #define DISABLE_HOTPLUG_DMA_FIX */
-// #define MAX_EXP_RUNNING_REQ 2
#define WIDE_PORT_MAX_PHY 4
-#define MV_DISABLE_NCQ 0
#define mv_printk(fmt, arg ...) \
printk(KERN_DEBUG"%s %d:" fmt, __FILE__, __LINE__, ## arg)
#ifdef MV_DEBUG
@@ -64,6 +59,7 @@
#endif
#define MV_MAX_U32 0xffffffff
+extern int interrupt_coalescing;
extern struct mvs_tgt_initiator mvs_tgt;
extern struct mvs_info *tgt_mvi;
extern const struct mvs_dispatch mvs_64xx_dispatch;
@@ -99,6 +95,11 @@ enum dev_status {
MVS_DEV_EH = 0x1,
};
+enum dev_reset {
+ MVS_SOFT_RESET = 0,
+ MVS_HARD_RESET = 1,
+ MVS_PHY_TUNE = 2,
+};
struct mvs_info;
@@ -130,7 +131,6 @@ struct mvs_dispatch {
u32 (*read_port_irq_mask)(struct mvs_info *mvi, u32 port);
void (*write_port_irq_mask)(struct mvs_info *mvi, u32 port, u32 val);
- void (*get_sas_addr)(void *buf, u32 buflen);
void (*command_active)(struct mvs_info *mvi, u32 slot_idx);
void (*clear_srs_irq)(struct mvs_info *mvi, u8 reg_set, u8 clear_all);
void (*issue_stop)(struct mvs_info *mvi, enum mvs_port_type type,
@@ -167,9 +167,10 @@ struct mvs_dispatch {
);
int (*spi_issuecmd)(struct mvs_info *mvi, u32 cmd);
int (*spi_waitdataready)(struct mvs_info *mvi, u32 timeout);
-#ifndef DISABLE_HOTPLUG_DMA_FIX
- void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd);
-#endif
+ void (*dma_fix)(struct mvs_info *mvi, u32 phy_mask,
+ int buf_len, int from, void *prd);
+ void (*tune_interrupt)(struct mvs_info *mvi, u32 time);
+ void (*non_spec_ncq_error)(struct mvs_info *mvi);
};
@@ -179,9 +180,11 @@ struct mvs_chip_info {
u32 fis_offs;
u32 fis_count;
u32 srs_sz;
+ u32 sg_width;
u32 slot_width;
const struct mvs_dispatch *dispatch;
};
+#define MVS_MAX_SG (1U << mvi->chip->sg_width)
#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
#define MVS_RX_FISL_SZ \
(mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))
@@ -249,6 +252,73 @@ struct mvs_device {
u16 reserved;
};
+/* Generate PHY tunning parameters */
+struct phy_tuning {
+ /* 1 bit, transmitter emphasis enable */
+ u8 trans_emp_en:1;
+ /* 4 bits, transmitter emphasis amplitude */
+ u8 trans_emp_amp:4;
+ /* 3 bits, reserved space */
+ u8 Reserved_2bit_1:3;
+ /* 5 bits, transmitter amplitude */
+ u8 trans_amp:5;
+ /* 2 bits, transmitter amplitude adjust */
+ u8 trans_amp_adj:2;
+ /* 1 bit, reserved space */
+ u8 resv_2bit_2:1;
+ /* 2 bytes, reserved space */
+ u8 reserved[2];
+};
+
+struct ffe_control {
+ /* 4 bits, FFE Capacitor Select (value range 0~F) */
+ u8 ffe_cap_sel:4;
+ /* 3 bits, FFE Resistor Select (value range 0~7) */
+ u8 ffe_rss_sel:3;
+ /* 1 bit reserve*/
+ u8 reserved:1;
+};
+
+/*
+ * HBA_Info_Page is saved in Flash/NVRAM, total 256 bytes.
+ * The data area is valid only Signature="MRVL".
+ * If any member fills with 0xFF, the member is invalid.
+ */
+struct hba_info_page {
+ /* Dword 0 */
+ /* 4 bytes, structure signature,should be "MRVL" at first initial */
+ u8 signature[4];
+
+ /* Dword 1-13 */
+ u32 reserved1[13];
+
+ /* Dword 14-29 */
+ /* 64 bytes, SAS address for each port */
+ u64 sas_addr[8];
+
+ /* Dword 30-31 */
+ /* 8 bytes for vanir 8 port PHY FFE seeting
+ * BIT 0~3 : FFE Capacitor select(value range 0~F)
+ * BIT 4~6 : FFE Resistor select(value range 0~7)
+ * BIT 7: reserve.
+ */
+
+ struct ffe_control ffe_ctl[8];
+ /* Dword 32 -43 */
+ u32 reserved2[12];
+
+ /* Dword 44-45 */
+ /* 8 bytes, 0: 1.5G, 1: 3.0G, should be 0x01 at first initial */
+ u8 phy_rate[8];
+
+ /* Dword 46-53 */
+ /* 32 bytes, PHY tuning parameters for each PHY*/
+ struct phy_tuning phy_tuning[8];
+
+ /* Dword 54-63 */
+ u32 reserved3[10];
+}; /* total 256 bytes */
+
struct mvs_slot_info {
struct list_head entry;
union {
@@ -264,9 +334,6 @@ struct mvs_slot_info {
*/
void *buf;
dma_addr_t buf_dma;
-#if _MV_DUMP
- u32 cmd_size;
-#endif
void *response;
struct mvs_port *port;
struct mvs_device *device;
@@ -320,12 +387,10 @@ struct mvs_info {
const struct mvs_chip_info *chip;
int tags_num;
- DECLARE_BITMAP(tags, MVS_SLOTS);
+ unsigned long *tags;
/* further per-slot information */
struct mvs_phy phy[MVS_MAX_PHYS];
struct mvs_port port[MVS_MAX_PHYS];
- u32 irq;
- u32 exp_req;
u32 id;
u64 sata_reg_set;
struct list_head *hba_list;
@@ -337,12 +402,13 @@ struct mvs_info {
u32 flashsectSize;
void *addon;
+ struct hba_info_page hba_info_param;
struct mvs_device devices[MVS_MAX_DEVICES];
-#ifndef DISABLE_HOTPLUG_DMA_FIX
void *bulk_buffer;
dma_addr_t bulk_buffer_dma;
+ void *bulk_buffer1;
+ dma_addr_t bulk_buffer_dma1;
#define TRASH_BUCKET_SIZE 0x20000
-#endif
void *dma_pool;
struct mvs_slot_info slot_info[0];
};
@@ -350,8 +416,10 @@ struct mvs_info {
struct mvs_prv_info{
u8 n_host;
u8 n_phy;
- u16 reserve;
+ u8 scan_finished;
+ u8 reserve;
struct mvs_info *mvi[2];
+ struct tasklet_struct mv_tasklet;
};
struct mvs_wq {
@@ -390,8 +458,6 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
u32 off_lo, u32 off_hi, u64 sas_addr);
-int mvs_slave_alloc(struct scsi_device *scsi_dev);
-int mvs_slave_configure(struct scsi_device *sdev);
void mvs_scan_start(struct Scsi_Host *shost);
int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
int mvs_queue_command(struct sas_task *task, const int num,
@@ -415,6 +481,6 @@ void mvs_do_release_task(struct mvs_info *mvi, int phy_no,
void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events);
void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);
int mvs_int_rx(struct mvs_info *mvi, bool self_clear);
-void mvs_hexdump(u32 size, u8 *data, u32 baseaddr);
+struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, u8 reg_set);
#endif
diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
index 861b5ce..a070351 100644
--- a/drivers/scsi/osd/Kconfig
+++ b/drivers/scsi/osd/Kconfig
@@ -11,10 +11,6 @@
# it under the terms of the GNU General Public version 2 License as
# published by the Free Software Foundation
#
-# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
-# How is it done properly?
-#
-
config SCSI_OSD_INITIATOR
tristate "OSD-Initiator library"
depends on SCSI
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 86afb13f..c06b8e5 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -40,6 +40,7 @@
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include <scsi/osd_initiator.h>
#include <scsi/osd_sec.h>
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 8b7db1e..b7b92f7 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -567,11 +567,11 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
value = pm8001_cr32(pm8001_ha, 0, 0x44);
offset = value & 0x03FFFFFF;
PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 Offset: %x \n", offset));
+ pm8001_printk("Scratchpad 0 Offset: %x\n", offset));
pcilogic = (value & 0xFC000000) >> 26;
pcibar = get_pci_bar_index(pcilogic);
PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 PCI BAR: %d \n", pcibar));
+ pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar));
pm8001_ha->main_cfg_tbl_addr = base_addr =
pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
pm8001_ha->general_stat_tbl_addr =
@@ -1245,7 +1245,7 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) {
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("No free mpi buffer \n"));
+ pm8001_printk("No free mpi buffer\n"));
return -1;
}
BUG_ON(!payload);
@@ -1262,7 +1262,7 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
circularQ->pi_offset, circularQ->producer_idx);
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("after PI= %d CI= %d \n", circularQ->producer_idx,
+ pm8001_printk("after PI= %d CI= %d\n", circularQ->producer_idx,
circularQ->consumer_index));
return 0;
}
@@ -1474,7 +1474,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
switch (status) {
case IO_SUCCESS:
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS"
- ",param = %d \n", param));
+ ",param = %d\n", param));
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
@@ -1490,14 +1490,14 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
break;
case IO_ABORTED:
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag \n"));
+ pm8001_printk("IO_ABORTED IOMB Tag\n"));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
break;
case IO_UNDERFLOW:
/* SSP Completion with error */
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW"
- ",param = %d \n", param));
+ ",param = %d\n", param));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
ts->residual = param;
@@ -1649,6 +1649,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
default:
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
@@ -1937,14 +1938,14 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->buf_valid_size = sizeof(*resp);
} else
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("response to large \n"));
+ pm8001_printk("response to large\n"));
}
if (pm8001_dev)
pm8001_dev->running_req--;
break;
case IO_ABORTED:
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag \n"));
+ pm8001_printk("IO_ABORTED IOMB Tag\n"));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
if (pm8001_dev)
@@ -2728,11 +2729,11 @@ static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("%x phy execute %x phy op failed! \n",
+ pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
} else
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("%x phy execute %x phy op success! \n",
+ pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
return 0;
}
@@ -3018,7 +3019,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case PORT_INVALID:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" PortInvalid portID %d \n", port_id));
+ pm8001_printk(" PortInvalid portID %d\n", port_id));
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" Last phy Down and port invalid\n"));
port->port_attached = 0;
@@ -3027,7 +3028,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case PORT_IN_RESET:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Port In Reset portID %d \n", port_id));
+ pm8001_printk(" Port In Reset portID %d\n", port_id));
break;
case PORT_NOT_ESTABLISHED:
PM8001_MSG_DBG(pm8001_ha,
@@ -3220,7 +3221,7 @@ mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
pm8001_printk(" status = 0x%x\n", status));
for (i = 0; i < GENERAL_EVENT_PAYLOAD; i++)
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("inb_IOMB_payload[0x%x] 0x%x, \n", i,
+ pm8001_printk("inb_IOMB_payload[0x%x] 0x%x,\n", i,
pPayload->inb_IOMB_payload[i]));
return 0;
}
@@ -3312,12 +3313,12 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_SAS_PHY_UP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_START_STATUS \n"));
+ pm8001_printk("HW_EVENT_PHY_START_STATUS\n"));
hw_event_sas_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_PHY_UP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_PHY_UP \n"));
+ pm8001_printk("HW_EVENT_SATA_PHY_UP\n"));
hw_event_sata_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_PHY_STOP_STATUS:
@@ -3329,12 +3330,12 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_SATA_SPINUP_HOLD:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD \n"));
+ pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
break;
case HW_EVENT_PHY_DOWN:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_DOWN \n"));
+ pm8001_printk("HW_EVENT_PHY_DOWN\n"));
sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
phy->phy_state = 0;
@@ -3446,7 +3447,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED \n"));
+ pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"));
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
port_id, phy_id, 0, 0);
@@ -3456,25 +3457,25 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_PORT_RESET_TIMER_TMO:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO \n"));
+ pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO \n"));
+ pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RECOVER:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVER \n"));
+ pm8001_printk("HW_EVENT_PORT_RECOVER\n"));
break;
case HW_EVENT_PORT_RESET_COMPLETE:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE \n"));
+ pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
break;
case EVENT_BROADCAST_ASYNCH_EVENT:
PM8001_MSG_DBG(pm8001_ha,
@@ -3502,21 +3503,21 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
switch (opc) {
case OPC_OUB_ECHO:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO \n"));
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n"));
break;
case OPC_OUB_HW_EVENT:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_HW_EVENT \n"));
+ pm8001_printk("OPC_OUB_HW_EVENT\n"));
mpi_hw_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_COMP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_COMP \n"));
+ pm8001_printk("OPC_OUB_SSP_COMP\n"));
mpi_ssp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SMP_COMP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SMP_COMP \n"));
+ pm8001_printk("OPC_OUB_SMP_COMP\n"));
mpi_smp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_LOCAL_PHY_CNTRL:
@@ -3526,26 +3527,26 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case OPC_OUB_DEV_REGIST:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_REGIST \n"));
+ pm8001_printk("OPC_OUB_DEV_REGIST\n"));
mpi_reg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEREG_DEV:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unresgister the deviece \n"));
+ pm8001_printk("unresgister the deviece\n"));
mpi_dereg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEV_HANDLE:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_DEV_HANDLE \n"));
+ pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n"));
break;
case OPC_OUB_SATA_COMP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_COMP \n"));
+ pm8001_printk("OPC_OUB_SATA_COMP\n"));
mpi_sata_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_EVENT:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_EVENT \n"));
+ pm8001_printk("OPC_OUB_SATA_EVENT\n"));
mpi_sata_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_EVENT:
@@ -3858,19 +3859,19 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
circularQ = &pm8001_ha->inbnd_q_tbl[0];
if (task->data_dir == PCI_DMA_NONE) {
ATAP = 0x04; /* no data*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n"));
} else if (likely(!task->ata_task.device_control_reg_update)) {
if (task->ata_task.dma_xfer) {
ATAP = 0x06; /* DMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n"));
} else {
ATAP = 0x05; /* PIO*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n"));
}
if (task->ata_task.use_ncq &&
dev->sata_dev.command_set != ATAPI_COMMAND_SET) {
ATAP = 0x07; /* FPDMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
}
}
if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 172cefb..c21a216 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -61,7 +61,7 @@ static struct scsi_host_template pm8001_sht = {
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
- .slave_configure = pm8001_slave_configure,
+ .slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
.scan_finished = pm8001_scan_finished,
.scan_start = pm8001_scan_start,
@@ -76,7 +76,7 @@ static struct scsi_host_template pm8001_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = pm8001_slave_alloc,
+ .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = pm8001_host_attrs,
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 6ae059e..fb3dc99 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -210,26 +210,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id);
break;
default:
- rc = -EOPNOTSUPP;
+ rc = -ENOSYS;
}
msleep(300);
return rc;
}
-int pm8001_slave_alloc(struct scsi_device *scsi_dev)
-{
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- if (dev_is_sata(dev)) {
- /* We don't need to rescan targets
- * if REPORT_LUNS request is failed
- */
- if (scsi_dev->lun > 0)
- return -ENXIO;
- scsi_dev->tagged_supported = 1;
- }
- return sas_slave_alloc(scsi_dev);
-}
-
/**
* pm8001_scan_start - we should enable all HBA phys by sending the phy_start
* command to HBA.
@@ -314,22 +300,7 @@ static int pm8001_task_prep_ssp(struct pm8001_hba_info *pm8001_ha,
{
return PM8001_CHIP_DISP->ssp_io_req(pm8001_ha, ccb);
}
-int pm8001_slave_configure(struct scsi_device *sdev)
-{
- struct domain_device *dev = sdev_to_domain_dev(sdev);
- int ret = sas_slave_configure(sdev);
- if (ret)
- return ret;
- if (dev_is_sata(dev)) {
- #ifdef PM8001_DISABLE_NCQ
- struct ata_port *ap = dev->sata_dev.ap;
- struct ata_device *adev = ap->link.device;
- adev->flags |= ATA_DFLAG_NCQ_OFF;
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
- #endif
- }
- return 0;
-}
+
/* Find the local port id that's attached to this device */
static int sas_find_local_port_id(struct domain_device *dev)
{
@@ -385,21 +356,8 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
do {
dev = t->dev;
pm8001_dev = dev->lldd_dev;
- if (DEV_IS_GONE(pm8001_dev)) {
- if (pm8001_dev) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("device %d not ready.\n",
- pm8001_dev->device_id));
- } else {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("device %016llx not "
- "ready.\n", SAS_ADDR(dev->sas_addr)));
- }
- rc = SAS_PHY_DOWN;
- goto out_done;
- }
port = &pm8001_ha->port[sas_find_local_port_id(dev)];
- if (!port->port_attached) {
+ if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
if (sas_protocol_ata(t->task_proto)) {
struct task_status_struct *ts = &t->task_status;
ts->resp = SAS_TASK_UNDELIVERED;
@@ -651,7 +609,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
flag = 1; /* directly sata*/
}
} /*register this device to HBA*/
- PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device \n"));
+ PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
wait_for_completion(&completion);
@@ -669,30 +627,6 @@ int pm8001_dev_found(struct domain_device *dev)
return pm8001_dev_found_notify(dev);
}
-/**
- * pm8001_alloc_task - allocate a task structure for TMF
- */
-static struct sas_task *pm8001_alloc_task(void)
-{
- struct sas_task *task = kzalloc(sizeof(*task), GFP_KERNEL);
- if (task) {
- INIT_LIST_HEAD(&task->list);
- spin_lock_init(&task->task_state_lock);
- task->task_state_flags = SAS_TASK_STATE_PENDING;
- init_timer(&task->timer);
- init_completion(&task->completion);
- }
- return task;
-}
-
-static void pm8001_free_task(struct sas_task *task)
-{
- if (task) {
- BUG_ON(!list_empty(&task->list));
- kfree(task);
- }
-}
-
static void pm8001_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
@@ -728,7 +662,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
for (retry = 0; retry < 3; retry++) {
- task = pm8001_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -789,14 +723,13 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat));
- pm8001_free_task(task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- if (task != NULL)
- pm8001_free_task(task);
+ sas_free_task(task);
return res;
}
@@ -811,7 +744,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
struct sas_task *task = NULL;
for (retry = 0; retry < 3; retry++) {
- task = pm8001_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -864,14 +797,13 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat));
- pm8001_free_task(task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- if (task != NULL)
- pm8001_free_task(task);
+ sas_free_task(task);
return res;
}
@@ -1026,13 +958,14 @@ int pm8001_query_task(struct sas_task *task)
/* The task is still in Lun, release it then */
case TMF_RESP_FUNC_SUCC:
PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("The task is still in Lun \n"));
+ pm8001_printk("The task is still in Lun\n"));
+ break;
/* The task is not in Lun or failed, reset the phy */
case TMF_RESP_FUNC_FAILED:
case TMF_RESP_FUNC_COMPLETE:
PM8001_EH_DBG(pm8001_ha,
pm8001_printk("The task is not in Lun or failed,"
- " reset the phy \n"));
+ " reset the phy\n"));
break;
}
}
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index aa05e66..93959fe 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -54,7 +54,7 @@
#include <scsi/libsas.h>
#include <scsi/scsi_tcq.h>
#include <scsi/sas_ata.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "pm8001_defs.h"
#define DRV_NAME "pm8001"
@@ -471,8 +471,6 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx);
int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
-int pm8001_slave_alloc(struct scsi_device *scsi_dev);
-int pm8001_slave_configure(struct scsi_device *sdev);
void pm8001_scan_start(struct Scsi_Host *shost);
int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time);
int pm8001_queue_command(struct sas_task *task, const int num,
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 532313e..6465dae 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -23,11 +23,23 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
if (ha->fw_dump_reading == 0)
return 0;
- return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
+ if (IS_QLA82XX(ha)) {
+ if (off < ha->md_template_size) {
+ rval = memory_read_from_buffer(buf, count,
+ &off, ha->md_tmplt_hdr, ha->md_template_size);
+ return rval;
+ }
+ off -= ha->md_template_size;
+ rval = memory_read_from_buffer(buf, count,
+ &off, ha->md_dump, ha->md_dump_size);
+ return rval;
+ } else
+ return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
ha->fw_dump_len);
}
@@ -41,12 +53,6 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
struct qla_hw_data *ha = vha->hw;
int reading;
- if (IS_QLA82XX(ha)) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Firmware dump not supported for ISP82xx\n"));
- return count;
- }
-
if (off != 0)
return (0);
@@ -56,9 +62,13 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
if (!ha->fw_dump_reading)
break;
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x705d,
"Firmware dump cleared on (%ld).\n", vha->host_no);
+ if (IS_QLA82XX(vha->hw)) {
+ qla82xx_md_free(vha);
+ qla82xx_md_prep(vha);
+ }
ha->fw_dump_reading = 0;
ha->fw_dumped = 0;
break;
@@ -66,7 +76,7 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
if (ha->fw_dumped && !ha->fw_dump_reading) {
ha->fw_dump_reading = 1;
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x705e,
"Raw firmware dump ready for read on (%ld).\n",
vha->host_no);
}
@@ -75,10 +85,29 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
qla2x00_alloc_fw_dump(vha);
break;
case 3:
- qla2x00_system_error(vha);
+ if (IS_QLA82XX(ha)) {
+ qla82xx_idc_lock(ha);
+ qla82xx_set_reset_owner(vha);
+ qla82xx_idc_unlock(ha);
+ } else
+ qla2x00_system_error(vha);
+ break;
+ case 4:
+ if (IS_QLA82XX(ha)) {
+ if (ha->md_tmplt_hdr)
+ ql_dbg(ql_dbg_user, vha, 0x705b,
+ "MiniDump supported with this firmware.\n");
+ else
+ ql_dbg(ql_dbg_user, vha, 0x709d,
+ "MiniDump not supported with this firmware.\n");
+ }
+ break;
+ case 5:
+ if (IS_QLA82XX(ha))
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
}
- return (count);
+ return -EINVAL;
}
static struct bin_attribute sysfs_fw_dump_attr = {
@@ -122,7 +151,7 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size ||
!ha->isp_ops->write_nvram)
- return 0;
+ return -EINVAL;
/* Checksum NVRAM. */
if (IS_FWI2_CAPABLE(ha)) {
@@ -148,7 +177,7 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
}
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x705f,
"HBA not online, failing NVRAM update.\n");
return -EAGAIN;
}
@@ -158,12 +187,14 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
count);
+ ql_dbg(ql_dbg_user, vha, 0x7060,
+ "Setting ISP_ABORT_NEEDED\n");
/* NVRAM settings take effect immediately. */
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
- return (count);
+ return count;
}
static struct bin_attribute sysfs_nvram_attr = {
@@ -237,10 +268,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
int val, valid;
if (off)
- return 0;
+ return -EINVAL;
if (unlikely(pci_channel_offline(ha->pdev)))
- return 0;
+ return -EAGAIN;
if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
return -EINVAL;
@@ -251,20 +282,20 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
case 0:
if (ha->optrom_state != QLA_SREADING &&
ha->optrom_state != QLA_SWRITING)
- break;
+ return -EINVAL;
ha->optrom_state = QLA_SWAITING;
- DEBUG2(qla_printk(KERN_INFO, ha,
+ ql_dbg(ql_dbg_user, vha, 0x7061,
"Freeing flash region allocation -- 0x%x bytes.\n",
- ha->optrom_region_size));
+ ha->optrom_region_size);
vfree(ha->optrom_buffer);
ha->optrom_buffer = NULL;
break;
case 1:
if (ha->optrom_state != QLA_SWAITING)
- break;
+ return -EINVAL;
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
@@ -273,23 +304,23 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
ha->optrom_state = QLA_SREADING;
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
if (ha->optrom_buffer == NULL) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7062,
"Unable to allocate memory for optrom retrieval "
"(%x).\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
- return count;
+ return -ENOMEM;
}
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "HBA not online, failing NVRAM update.\n");
+ ql_log(ql_log_warn, vha, 0x7063,
+ "HBA not online, failing NVRAM update.\n");
return -EAGAIN;
}
- DEBUG2(qla_printk(KERN_INFO, ha,
+ ql_dbg(ql_dbg_user, vha, 0x7064,
"Reading flash region -- 0x%x/0x%x.\n",
- ha->optrom_region_start, ha->optrom_region_size));
+ ha->optrom_region_start, ha->optrom_region_size);
memset(ha->optrom_buffer, 0, ha->optrom_region_size);
ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
@@ -297,7 +328,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
break;
case 2:
if (ha->optrom_state != QLA_SWAITING)
- break;
+ return -EINVAL;
/*
* We need to be more restrictive on which FLASH regions are
@@ -328,7 +359,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
else if (IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha))
valid = 1;
if (!valid) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7065,
"Invalid start region 0x%x/0x%x.\n", start, size);
return -EINVAL;
}
@@ -340,39 +371,39 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
ha->optrom_state = QLA_SWRITING;
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
if (ha->optrom_buffer == NULL) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7066,
"Unable to allocate memory for optrom update "
- "(%x).\n", ha->optrom_region_size);
+ "(%x)\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
- return count;
+ return -ENOMEM;
}
- DEBUG2(qla_printk(KERN_INFO, ha,
+ ql_dbg(ql_dbg_user, vha, 0x7067,
"Staging flash region write -- 0x%x/0x%x.\n",
- ha->optrom_region_start, ha->optrom_region_size));
+ ha->optrom_region_start, ha->optrom_region_size);
memset(ha->optrom_buffer, 0, ha->optrom_region_size);
break;
case 3:
if (ha->optrom_state != QLA_SWRITING)
- break;
+ return -ENOMEM;
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7068,
"HBA not online, failing flash update.\n");
return -EAGAIN;
}
- DEBUG2(qla_printk(KERN_INFO, ha,
+ ql_dbg(ql_dbg_user, vha, 0x7069,
"Writing flash region -- 0x%x/0x%x.\n",
- ha->optrom_region_start, ha->optrom_region_size));
+ ha->optrom_region_start, ha->optrom_region_size);
ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
ha->optrom_region_start, ha->optrom_region_size);
break;
default:
- count = -EINVAL;
+ return -EINVAL;
}
return count;
}
@@ -396,10 +427,10 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
struct qla_hw_data *ha = vha->hw;
if (unlikely(pci_channel_offline(ha->pdev)))
- return 0;
+ return -EAGAIN;
if (!capable(CAP_SYS_ADMIN))
- return 0;
+ return -EINVAL;
if (IS_NOCACHE_VPD_TYPE(ha))
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
@@ -425,7 +456,7 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
return 0;
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x706a,
"HBA not online, failing VPD update.\n");
return -EAGAIN;
}
@@ -436,17 +467,17 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
/* Update flash version information for 4Gb & above. */
if (!IS_FWI2_CAPABLE(ha))
- goto done;
+ return -EINVAL;
tmp_data = vmalloc(256);
if (!tmp_data) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x706b,
"Unable to allocate memory for VPD information update.\n");
- goto done;
+ return -ENOMEM;
}
ha->isp_ops->get_flash_version(vha, tmp_data);
vfree(tmp_data);
-done:
+
return count;
}
@@ -480,7 +511,7 @@ qla2x00_sysfs_read_sfp(struct file *filp, struct kobject *kobj,
ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->sfp_data_dma);
if (!ha->sfp_data) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x706c,
"Unable to allocate memory for SFP read-data.\n");
return 0;
}
@@ -499,11 +530,11 @@ do_read:
rval = qla2x00_read_sfp(vha, ha->sfp_data_dma, ha->sfp_data,
addr, offset, SFP_BLOCK_SIZE, 0);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x706d,
"Unable to read SFP data (%x/%x/%x).\n", rval,
addr, offset);
- count = 0;
- break;
+
+ return -EIO;
}
memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
buf += SFP_BLOCK_SIZE;
@@ -533,26 +564,31 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
int type;
if (off != 0)
- return 0;
+ return -EINVAL;
type = simple_strtol(buf, NULL, 10);
switch (type) {
case 0x2025c:
- qla_printk(KERN_INFO, ha,
- "Issuing ISP reset on (%ld).\n", vha->host_no);
+ ql_log(ql_log_info, vha, 0x706e,
+ "Issuing ISP reset.\n");
scsi_block_requests(vha->host);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ if (IS_QLA82XX(ha)) {
+ qla82xx_idc_lock(ha);
+ qla82xx_set_reset_owner(vha);
+ qla82xx_idc_unlock(ha);
+ }
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
scsi_unblock_requests(vha->host);
break;
case 0x2025d:
if (!IS_QLA81XX(ha))
- break;
+ return -EPERM;
- qla_printk(KERN_INFO, ha,
- "Issuing MPI reset on (%ld).\n", vha->host_no);
+ ql_log(ql_log_info, vha, 0x706f,
+ "Issuing MPI reset.\n");
/* Make sure FC side is not in reset */
qla2x00_wait_for_hba_online(vha);
@@ -560,20 +596,19 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
/* Issue MPI reset */
scsi_block_requests(vha->host);
if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
- qla_printk(KERN_WARNING, ha,
- "MPI reset failed on (%ld).\n", vha->host_no);
+ ql_log(ql_log_warn, vha, 0x7070,
+ "MPI reset failed.\n");
scsi_unblock_requests(vha->host);
break;
case 0x2025e:
if (!IS_QLA82XX(ha) || vha != base_vha) {
- qla_printk(KERN_INFO, ha,
- "FCoE ctx reset not supported for host%ld.\n",
- vha->host_no);
- return count;
+ ql_log(ql_log_info, vha, 0x7071,
+ "FCoE ctx reset no supported.\n");
+ return -EPERM;
}
- qla_printk(KERN_INFO, ha,
- "Issuing FCoE CTX reset on host%ld.\n", vha->host_no);
+ ql_log(ql_log_info, vha, 0x7072,
+ "Issuing FCoE ctx reset.\n");
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_fcoe_ctx_reset(vha);
@@ -605,15 +640,15 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
ha->edc_data_len = 0;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
- return 0;
+ return -EINVAL;
if (!ha->edc_data) {
ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->edc_data_dma);
if (!ha->edc_data) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Unable to allocate memory for EDC write.\n"));
- return 0;
+ ql_log(ql_log_warn, vha, 0x7073,
+ "Unable to allocate memory for EDC write.\n");
+ return -ENOMEM;
}
}
@@ -631,10 +666,10 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
rval = qla2x00_write_sfp(vha, ha->edc_data_dma, ha->edc_data,
dev, adr, len, opt);
if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Unable to write EDC (%x) %02x:%02x:%04x:%02x:%02x.\n",
- rval, dev, adr, opt, len, buf[8]));
- return 0;
+ ql_log(ql_log_warn, vha, 0x7074,
+ "Unable to write EDC (%x) %02x:%04x:%02x:%02hhx\n",
+ rval, dev, adr, opt, len, buf[8]);
+ return -EIO;
}
return count;
@@ -663,15 +698,15 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
ha->edc_data_len = 0;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
- return 0;
+ return -EINVAL;
if (!ha->edc_data) {
ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->edc_data_dma);
if (!ha->edc_data) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Unable to allocate memory for EDC status.\n"));
- return 0;
+ ql_log(ql_log_warn, vha, 0x708c,
+ "Unable to allocate memory for EDC status.\n");
+ return -ENOMEM;
}
}
@@ -688,10 +723,10 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
rval = qla2x00_read_sfp(vha, ha->edc_data_dma, ha->edc_data,
dev, adr, len, opt);
if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Unable to write EDC status (%x) %02x:%02x:%04x:%02x.\n",
- rval, dev, adr, opt, len));
- return 0;
+ ql_log(ql_log_info, vha, 0x7075,
+ "Unable to write EDC status (%x) %02x:%04x:%02x.\n",
+ rval, dev, adr, opt, len);
+ return -EIO;
}
ha->edc_data_len = len;
@@ -749,7 +784,7 @@ qla2x00_sysfs_read_xgmac_stats(struct file *filp, struct kobject *kobj,
ha->xgmac_data = dma_alloc_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
&ha->xgmac_data_dma, GFP_KERNEL);
if (!ha->xgmac_data) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7076,
"Unable to allocate memory for XGMAC read-data.\n");
return 0;
}
@@ -761,7 +796,7 @@ do_read:
rval = qla2x00_get_xgmac_stats(vha, ha->xgmac_data_dma,
XGMAC_DATA_SIZE, &actual_size);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7077,
"Unable to read XGMAC data (%x).\n", rval);
count = 0;
}
@@ -801,9 +836,9 @@ qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj,
ha->dcbx_tlv = dma_alloc_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
&ha->dcbx_tlv_dma, GFP_KERNEL);
if (!ha->dcbx_tlv) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7078,
"Unable to allocate memory for DCBX TLV read-data.\n");
- return 0;
+ return -ENOMEM;
}
do_read:
@@ -813,9 +848,9 @@ do_read:
rval = qla2x00_get_dcbx_params(vha, ha->dcbx_tlv_dma,
DCBX_TLV_DATA_SIZE);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Unable to read DCBX TLV data (%x).\n", rval);
- count = 0;
+ ql_log(ql_log_warn, vha, 0x7079,
+ "Unable to read DCBX TLV (%x).\n", rval);
+ return -EIO;
}
memcpy(buf, ha->dcbx_tlv, count);
@@ -869,9 +904,13 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
iter->attr);
if (ret)
- qla_printk(KERN_INFO, vha->hw,
- "Unable to create sysfs %s binary attribute "
- "(%d).\n", iter->name, ret);
+ ql_log(ql_log_warn, vha, 0x00f3,
+ "Unable to create sysfs %s binary attribute (%d).\n",
+ iter->name, ret);
+ else
+ ql_dbg(ql_dbg_init, vha, 0x00f4,
+ "Successfully created sysfs %s binary attribure.\n",
+ iter->name);
}
}
@@ -1126,7 +1165,7 @@ qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
return -EPERM;
if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x707a,
"Abort ISP active -- ignoring beacon request.\n");
return -EBUSY;
}
@@ -1322,9 +1361,8 @@ qla2x00_thermal_temp_show(struct device *dev,
temp = frac = 0;
if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): isp reset in progress.\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x707b,
+ "ISP reset active.\n");
else if (!vha->hw->flags.eeh_busy)
rval = qla2x00_get_thermal_temp(vha, &temp, &frac);
if (rval != QLA_SUCCESS)
@@ -1343,8 +1381,8 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
- DEBUG2_3_11(printk("%s(%ld): isp reset in progress.\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x707c,
+ "ISP reset active.\n");
else if (!vha->hw->flags.eeh_busy)
rval = qla2x00_get_firmware_state(vha, state);
if (rval != QLA_SUCCESS)
@@ -1645,8 +1683,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
if (stats == NULL) {
- DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
- __func__, base_vha->host_no));
+ ql_log(ql_log_warn, vha, 0x707d,
+ "Failed to allocate memory for stats.\n");
goto done;
}
memset(stats, 0, DMA_POOL_SIZE);
@@ -1724,12 +1762,31 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost)
scsi_qla_host_t *vha = shost_priv(shost);
struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev);
- if (!base_vha->flags.online)
+ if (!base_vha->flags.online) {
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
- else if (atomic_read(&base_vha->loop_state) == LOOP_TIMEOUT)
- fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
- else
+ return;
+ }
+
+ switch (atomic_read(&base_vha->loop_state)) {
+ case LOOP_UPDATE:
+ fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS;
+ break;
+ case LOOP_DOWN:
+ if (test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags))
+ fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS;
+ else
+ fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+ break;
+ case LOOP_DEAD:
+ fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+ break;
+ case LOOP_READY:
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+ break;
+ default:
+ fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+ break;
+ }
}
static int
@@ -1746,15 +1803,14 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
ret = qla24xx_vport_create_req_sanity_check(fc_vport);
if (ret) {
- DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
- "status %x\n", ret));
+ ql_log(ql_log_warn, vha, 0x707e,
+ "Vport sanity check failed, status %x\n", ret);
return (ret);
}
vha = qla24xx_create_vhost(fc_vport);
if (vha == NULL) {
- DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
- vha));
+ ql_log(ql_log_warn, vha, 0x707f, "Vport create host failed.\n");
return FC_VPORT_FAILED;
}
if (disable) {
@@ -1764,8 +1820,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
atomic_set(&vha->vp_state, VP_FAILED);
/* ready to create vport */
- qla_printk(KERN_INFO, vha->hw, "VP entry id %d assigned.\n",
- vha->vp_idx);
+ ql_log(ql_log_info, vha, 0x7080,
+ "VP entry id %d assigned.\n", vha->vp_idx);
/* initialized vport states */
atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -1775,21 +1831,23 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
if (atomic_read(&base_vha->loop_state) == LOOP_DOWN ||
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
/* Don't retry or attempt login of this virtual port */
- DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x7081,
+ "Vport loop state is not UP.\n");
atomic_set(&vha->loop_state, LOOP_DEAD);
if (!disable)
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
}
- if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) {
+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4) {
+ int prot = 0;
vha->flags.difdix_supported = 1;
- DEBUG18(qla_printk(KERN_INFO, ha,
- "Registering for DIF/DIX type 1 and 3"
- " protection.\n"));
+ ql_dbg(ql_dbg_user, vha, 0x7082,
+ "Registered for DIF/DIX type 1 and 3 protection.\n");
+ if (ql2xenabledif == 1)
+ prot = SHOST_DIX_TYPE0_PROTECTION;
scsi_host_set_prot(vha->host,
- SHOST_DIF_TYPE1_PROTECTION
+ prot | SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE2_PROTECTION
| SHOST_DIF_TYPE3_PROTECTION
| SHOST_DIX_TYPE1_PROTECTION
@@ -1802,8 +1860,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
&ha->pdev->dev)) {
- DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
- vha->host_no, vha->vp_idx));
+ ql_dbg(ql_dbg_user, vha, 0x7083,
+ "scsi_add_host failure for VP[%d].\n", vha->vp_idx);
goto vport_create_failed_2;
}
@@ -1820,6 +1878,10 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
if (ha->flags.cpu_affinity_enabled) {
req = ha->req_q_map[1];
+ ql_dbg(ql_dbg_multiq, vha, 0xc000,
+ "Request queue %p attached with "
+ "VP[%d], cpu affinity =%d\n",
+ req, vha->vp_idx, ha->flags.cpu_affinity_enabled);
goto vport_queue;
} else if (ql2xmaxqueues == 1 || !ha->npiv_info)
goto vport_queue;
@@ -1836,13 +1898,16 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, 0,
qos);
if (!ret)
- qla_printk(KERN_WARNING, ha,
- "Can't create request queue for vp_idx:%d\n",
- vha->vp_idx);
+ ql_log(ql_log_warn, vha, 0x7084,
+ "Can't create request queue for VP[%d]\n",
+ vha->vp_idx);
else {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Request Que:%d (QoS: %d) created for vp_idx:%d\n",
- ret, qos, vha->vp_idx));
+ ql_dbg(ql_dbg_multiq, vha, 0xc001,
+ "Request Que:%d Q0s: %d) created for VP[%d]\n",
+ ret, qos, vha->vp_idx);
+ ql_dbg(ql_dbg_user, vha, 0x7085,
+ "Request Que:%d Q0s: %d) created for VP[%d]\n",
+ ret, qos, vha->vp_idx);
req = ha->req_q_map[ret];
}
}
@@ -1882,12 +1947,13 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
if (vha->timer_active) {
qla2x00_vp_stop_timer(vha);
- DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
- " = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
+ ql_dbg(ql_dbg_user, vha, 0x7086,
+ "Timer for the VP[%d] has stopped\n", vha->vp_idx);
}
/* No pending activities shall be there on the vha now */
- DEBUG(msleep(random32()%10)); /* Just to see if something falls on
+ if (ql2xextended_error_logging & ql_dbg_user)
+ msleep(random32()%10); /* Just to see if something falls on
* the net we have placed below */
BUG_ON(atomic_read(&vha->vref_count));
@@ -1901,12 +1967,12 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
- qla_printk(KERN_WARNING, ha,
- "Queue delete failed.\n");
+ ql_log(ql_log_warn, vha, 0x7087,
+ "Queue delete failed.\n");
}
scsi_host_put(vha->host);
- qla_printk(KERN_INFO, ha, "vport %d deleted\n", id);
+ ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id);
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 8c10e2c..8b641a8 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -36,7 +36,8 @@ done:
}
int
-qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
+qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
+ struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
{
int i, ret, num_valid;
uint8_t *bcode;
@@ -51,18 +52,17 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
if (bcode_val == 0xFFFFFFFF) {
/* No FCP Priority config data in flash */
- DEBUG2(printk(KERN_INFO
- "%s: No FCP priority config data.\n",
- __func__));
+ ql_dbg(ql_dbg_user, vha, 0x7051,
+ "No FCP Priority config data.\n");
return 0;
}
if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' ||
bcode[3] != 'S') {
/* Invalid FCP priority data header*/
- DEBUG2(printk(KERN_ERR
- "%s: Invalid FCP Priority data header. bcode=0x%x\n",
- __func__, bcode_val));
+ ql_dbg(ql_dbg_user, vha, 0x7052,
+ "Invalid FCP Priority data header. bcode=0x%x.\n",
+ bcode_val);
return 0;
}
if (flag != 1)
@@ -77,15 +77,14 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
if (num_valid == 0) {
/* No valid FCP priority data entries */
- DEBUG2(printk(KERN_ERR
- "%s: No valid FCP Priority data entries.\n",
- __func__));
+ ql_dbg(ql_dbg_user, vha, 0x7053,
+ "No valid FCP Priority data entries.\n");
ret = 0;
} else {
/* FCP priority data is valid */
- DEBUG2(printk(KERN_INFO
- "%s: Valid FCP priority data. num entries = %d\n",
- __func__, num_valid));
+ ql_dbg(ql_dbg_user, vha, 0x7054,
+ "Valid FCP priority data. num entries = %d.\n",
+ num_valid);
}
return ret;
@@ -182,10 +181,9 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
if (!ha->fcp_prio_cfg) {
ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
if (!ha->fcp_prio_cfg) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory "
- "for fcp prio config data (%x).\n",
- FCP_PRIO_CFG_SIZE);
+ ql_log(ql_log_warn, vha, 0x7050,
+ "Unable to allocate memory for fcp prio "
+ "config data (%x).\n", FCP_PRIO_CFG_SIZE);
bsg_job->reply->result = (DID_ERROR << 16);
ret = -ENOMEM;
goto exit_fcp_prio_cfg;
@@ -198,9 +196,9 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
FCP_PRIO_CFG_SIZE);
/* validate fcp priority data */
- if (!qla24xx_fcp_prio_cfg_valid(
- (struct qla_fcp_prio_cfg *)
- ha->fcp_prio_cfg, 1)) {
+
+ if (!qla24xx_fcp_prio_cfg_valid(vha,
+ (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) {
bsg_job->reply->result = (DID_ERROR << 16);
ret = -EINVAL;
/* If buffer was invalidatic int
@@ -256,9 +254,8 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
/* pass through is supported only for ISP 4Gb or higher */
if (!IS_FWI2_CAPABLE(ha)) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld):ELS passthru not supported for ISP23xx based "
- "adapters\n", vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x7001,
+ "ELS passthru not supported for ISP23xx based adapters.\n");
rval = -EPERM;
goto done;
}
@@ -266,11 +263,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
/* Multiple SG's are not supported for ELS requests */
if (bsg_job->request_payload.sg_cnt > 1 ||
bsg_job->reply_payload.sg_cnt > 1) {
- DEBUG2(printk(KERN_INFO
- "multiple SG's are not supported for ELS requests"
- " [request_sg_cnt: %x reply_sg_cnt: %x]\n",
- bsg_job->request_payload.sg_cnt,
- bsg_job->reply_payload.sg_cnt));
+ ql_dbg(ql_dbg_user, vha, 0x7002,
+ "Multiple SG's are not suppored for ELS requests, "
+ "request_sg_cnt=%x reply_sg_cnt=%x.\n",
+ bsg_job->request_payload.sg_cnt,
+ bsg_job->reply_payload.sg_cnt);
rval = -EPERM;
goto done;
}
@@ -281,9 +278,9 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
* if not perform fabric login
*/
if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "failed to login port %06X for ELS passthru\n",
- fcport->d_id.b24));
+ ql_dbg(ql_dbg_user, vha, 0x7003,
+ "Failed to login port %06X for ELS passthru.\n",
+ fcport->d_id.b24);
rval = -EIO;
goto done;
}
@@ -314,8 +311,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
}
if (!vha->flags.online) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "host not online\n"));
+ ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
rval = -EIO;
goto done;
}
@@ -337,12 +333,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
(rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
- DEBUG2(printk(KERN_INFO
- "dma mapping resulted in different sg counts \
- [request_sg_cnt: %x dma_request_sg_cnt: %x\
- reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
- bsg_job->request_payload.sg_cnt, req_sg_cnt,
- bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
+ ql_log(ql_log_warn, vha, 0x7008,
+ "dma mapping resulted in different sg counts, "
+ "request_sg_cnt: %x dma_request_sg_cnt:%x reply_sg_cnt:%x "
+ "dma_reply_sg_cnt:%x.\n", bsg_job->request_payload.sg_cnt,
+ req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
@@ -363,15 +358,16 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
"bsg_els_rpt" : "bsg_els_hst");
els->u.bsg_job = bsg_job;
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
- "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
- bsg_job->request->rqst_data.h_els.command_code,
- fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_user, vha, 0x700a,
+ "bsg rqst type: %s els type: %x - loop-id=%x "
+ "portid=%-2x%02x%02x.\n", type,
+ bsg_job->request->rqst_data.h_els.command_code, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x700e,
+ "qla2x00_start_sp failed = %d\n", rval);
kfree(sp->ctx);
mempool_free(sp, ha->srb_mempool);
rval = -EIO;
@@ -411,6 +407,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
if (!req_sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x700f,
+ "dma_map_sg return %d for request\n", req_sg_cnt);
rval = -ENOMEM;
goto done;
}
@@ -418,24 +416,25 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
if (!rsp_sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x7010,
+ "dma_map_sg return %d for reply\n", rsp_sg_cnt);
rval = -ENOMEM;
goto done;
}
if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
(rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "[request_sg_cnt: %x dma_request_sg_cnt: %x\
- reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
- bsg_job->request_payload.sg_cnt, req_sg_cnt,
- bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
+ ql_log(ql_log_warn, vha, 0x7011,
+ "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
+ "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
+ req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
if (!vha->flags.online) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "host not online\n"));
+ ql_log(ql_log_warn, vha, 0x7012,
+ "Host is not online.\n");
rval = -EIO;
goto done_unmap_sg;
}
@@ -451,8 +450,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
loop_id = vha->mgmt_svr_loop_id;
break;
default:
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Unknown loop id: %x\n", loop_id));
+ ql_dbg(ql_dbg_user, vha, 0x7013,
+ "Unknown loop id: %x.\n", loop_id);
rval = -EINVAL;
goto done_unmap_sg;
}
@@ -464,6 +463,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
*/
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (!fcport) {
+ ql_log(ql_log_warn, vha, 0x7014,
+ "Failed to allocate fcport.\n");
rval = -ENOMEM;
goto done_unmap_sg;
}
@@ -479,6 +480,8 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
/* Alloc SRB structure */
sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
if (!sp) {
+ ql_log(ql_log_warn, vha, 0x7015,
+ "qla2x00_get_ctx_bsg_sp failed.\n");
rval = -ENOMEM;
goto done_free_fcport;
}
@@ -488,15 +491,17 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
ct->name = "bsg_ct";
ct->u.bsg_job = bsg_job;
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
- "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
- (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
- fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_user, vha, 0x7016,
+ "bsg rqst type: %s else type: %x - "
+ "loop-id=%x portid=%02x%02x%02x.\n", type,
+ (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
+ fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x7017,
+ "qla2x00_start_sp failed=%d.\n", rval);
kfree(sp->ctx);
mempool_free(sp, ha->srb_mempool);
rval = -EIO;
@@ -535,9 +540,8 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
ha->notify_dcbx_comp = 1;
ret = qla81xx_set_port_config(vha, new_config);
if (ret != QLA_SUCCESS) {
- DEBUG2(printk(KERN_ERR
- "%s(%lu): Set port config failed\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7021,
+ "set port config failed.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_set_internal;
@@ -545,11 +549,11 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
/* Wait for DCBX complete event */
if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "State change notificaition not received.\n"));
+ ql_dbg(ql_dbg_user, vha, 0x7022,
+ "State change notification not received.\n");
} else
- DEBUG2(qla_printk(KERN_INFO, ha,
- "State change RECEIVED\n"));
+ ql_dbg(ql_dbg_user, vha, 0x7023,
+ "State change received.\n");
ha->notify_dcbx_comp = 0;
@@ -581,9 +585,8 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
ha->notify_dcbx_comp = wait;
ret = qla81xx_set_port_config(vha, new_config);
if (ret != QLA_SUCCESS) {
- DEBUG2(printk(KERN_ERR
- "%s(%lu): Set port config failed\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7025,
+ "Set port config failed.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_reset_internal;
@@ -592,14 +595,14 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
/* Wait for DCBX complete event */
if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
(20 * HZ))) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "State change notificaition not received.\n"));
+ ql_dbg(ql_dbg_user, vha, 0x7026,
+ "State change notification not received.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_reset_internal;
} else
- DEBUG2(qla_printk(KERN_INFO, ha,
- "State change RECEIVED\n"));
+ ql_dbg(ql_dbg_user, vha, 0x7027,
+ "State change received.\n");
ha->notify_dcbx_comp = 0;
}
@@ -629,11 +632,13 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
- test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+ test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+ ql_log(ql_log_warn, vha, 0x7018, "Abort active or needed.\n");
return -EBUSY;
+ }
if (!vha->flags.online) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "host not online\n"));
+ ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
return -EIO;
}
@@ -641,26 +646,31 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
DMA_TO_DEVICE);
- if (!elreq.req_sg_cnt)
+ if (!elreq.req_sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x701a,
+ "dma_map_sg returned %d for request.\n", elreq.req_sg_cnt);
return -ENOMEM;
+ }
elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
DMA_FROM_DEVICE);
if (!elreq.rsp_sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x701b,
+ "dma_map_sg returned %d for reply.\n", elreq.rsp_sg_cnt);
rval = -ENOMEM;
goto done_unmap_req_sg;
}
if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
(elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
- DEBUG2(printk(KERN_INFO
- "dma mapping resulted in different sg counts "
- "[request_sg_cnt: %x dma_request_sg_cnt: %x "
- "reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
- bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
- bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt));
+ ql_log(ql_log_warn, vha, 0x701c,
+ "dma mapping resulted in different sg counts, "
+ "request_sg_cnt: %x dma_request_sg_cnt: %x "
+ "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
+ bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
+ bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
@@ -668,8 +678,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
&req_data_dma, GFP_KERNEL);
if (!req_data) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for req_data "
- "failed for host=%lu\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x701d,
+ "dma alloc failed for req_data.\n");
rval = -ENOMEM;
goto done_unmap_sg;
}
@@ -677,8 +687,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
&rsp_data_dma, GFP_KERNEL);
if (!rsp_data) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for rsp_data "
- "failed for host=%lu\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7004,
+ "dma alloc failed for rsp_data.\n");
rval = -ENOMEM;
goto done_free_dma_req;
}
@@ -694,13 +704,14 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
if ((ha->current_topology == ISP_CFG_F ||
+ (atomic_read(&vha->loop_state) == LOOP_DOWN) ||
(IS_QLA81XX(ha) &&
le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
&& req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
elreq.options == EXTERNAL_LOOPBACK) {
type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
+ ql_dbg(ql_dbg_user, vha, 0x701e,
+ "BSG request type: %s.\n", type);
command_sent = INT_DEF_LB_ECHO_CMD;
rval = qla2x00_echo_test(vha, &elreq, response);
} else {
@@ -708,9 +719,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
memset(config, 0, sizeof(config));
memset(new_config, 0, sizeof(new_config));
if (qla81xx_get_port_config(vha, config)) {
- DEBUG2(printk(KERN_ERR
- "%s(%lu): Get port config failed\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x701f,
+ "Get port config failed.\n");
bsg_job->reply->reply_payload_rcv_len = 0;
bsg_job->reply->result = (DID_ERROR << 16);
rval = -EPERM;
@@ -718,11 +728,13 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
}
if (elreq.options != EXTERNAL_LOOPBACK) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Internal: current port config = %x\n",
- config[0]));
+ ql_dbg(ql_dbg_user, vha, 0x7020,
+ "Internal: curent port config = %x\n",
+ config[0]);
if (qla81xx_set_internal_loopback(vha, config,
new_config)) {
+ ql_log(ql_log_warn, vha, 0x7024,
+ "Internal loopback failed.\n");
bsg_job->reply->reply_payload_rcv_len =
0;
bsg_job->reply->result =
@@ -746,9 +758,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
}
type = "FC_BSG_HST_VENDOR_LOOPBACK";
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld) bsg rqst type: %s\n",
- vha->host_no, type));
+ ql_dbg(ql_dbg_user, vha, 0x7028,
+ "BSG request type: %s.\n", type);
command_sent = INT_DEF_LB_LOOPBACK_CMD;
rval = qla2x00_loopback_test(vha, &elreq, response);
@@ -763,17 +774,16 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
if (response[0] == MBS_COMMAND_ERROR &&
response[1] == MBS_LB_RESET) {
- DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
- "ISP\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7029,
+ "MBX command error, Aborting ISP.\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
/* Also reset the MPI */
if (qla81xx_restart_mpi_firmware(vha) !=
QLA_SUCCESS) {
- qla_printk(KERN_INFO, ha,
- "MPI reset failed for host%ld.\n",
- vha->host_no);
+ ql_log(ql_log_warn, vha, 0x702a,
+ "MPI reset failed.\n");
}
bsg_job->reply->reply_payload_rcv_len = 0;
@@ -783,17 +793,16 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
}
} else {
type = "FC_BSG_HST_VENDOR_LOOPBACK";
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld) bsg rqst type: %s\n",
- vha->host_no, type));
+ ql_dbg(ql_dbg_user, vha, 0x702b,
+ "BSG request type: %s.\n", type);
command_sent = INT_DEF_LB_LOOPBACK_CMD;
rval = qla2x00_loopback_test(vha, &elreq, response);
}
}
if (rval) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request %s failed\n", vha->host_no, type));
+ ql_log(ql_log_warn, vha, 0x702c,
+ "Vendor request %s failed.\n", type);
fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
sizeof(struct fc_bsg_reply);
@@ -805,8 +814,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
bsg_job->reply->reply_payload_rcv_len = 0;
bsg_job->reply->result = (DID_ERROR << 16);
} else {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request %s completed\n", vha->host_no, type));
+ ql_dbg(ql_dbg_user, vha, 0x702d,
+ "Vendor request %s completed.\n", type);
bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
sizeof(response) + sizeof(uint8_t);
@@ -851,12 +860,13 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
- test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+ test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+ ql_log(ql_log_warn, vha, 0x702e, "Abort active or needed.\n");
return -EBUSY;
+ }
if (!IS_QLA84XX(ha)) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
- "exiting.\n", vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
return -EINVAL;
}
@@ -865,14 +875,14 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
if (rval) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request 84xx reset failed\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7030,
+ "Vendor request 84xx reset failed.\n");
rval = bsg_job->reply->reply_payload_rcv_len = 0;
bsg_job->reply->result = (DID_ERROR << 16);
} else {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request 84xx reset completed\n", vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x7031,
+ "Vendor request 84xx reset completed.\n");
bsg_job->reply->result = DID_OK;
}
@@ -902,21 +912,24 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
return -EBUSY;
if (!IS_QLA84XX(ha)) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
- "exiting.\n", vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x7032,
+ "Not 84xx, exiting.\n");
return -EINVAL;
}
sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
- if (!sg_cnt)
+ if (!sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x7033,
+ "dma_map_sg returned %d for request.\n", sg_cnt);
return -ENOMEM;
+ }
if (sg_cnt != bsg_job->request_payload.sg_cnt) {
- DEBUG2(printk(KERN_INFO
- "dma mapping resulted in different sg counts "
- "request_sg_cnt: %x dma_request_sg_cnt: %x ",
- bsg_job->request_payload.sg_cnt, sg_cnt));
+ ql_log(ql_log_warn, vha, 0x7034,
+ "DMA mapping resulted in different sg counts, "
+ "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
+ bsg_job->request_payload.sg_cnt, sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
@@ -925,8 +938,8 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
&fw_dma, GFP_KERNEL);
if (!fw_buf) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for fw_buf "
- "failed for host=%lu\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7035,
+ "DMA alloc failed for fw_buf.\n");
rval = -ENOMEM;
goto done_unmap_sg;
}
@@ -936,8 +949,8 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (!mn) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
- "failed for host=%lu\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7036,
+ "DMA alloc failed for fw buffer.\n");
rval = -ENOMEM;
goto done_free_fw_buf;
}
@@ -965,15 +978,15 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
if (rval) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request 84xx updatefw failed\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7037,
+ "Vendor request 84xx updatefw failed.\n");
rval = bsg_job->reply->reply_payload_rcv_len = 0;
bsg_job->reply->result = (DID_ERROR << 16);
} else {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request 84xx updatefw completed\n", vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x7038,
+ "Vendor request 84xx updatefw completed.\n");
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK;
@@ -1009,27 +1022,30 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
- test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+ test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+ ql_log(ql_log_warn, vha, 0x7039,
+ "Abort active or needed.\n");
return -EBUSY;
+ }
if (!IS_QLA84XX(ha)) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
- "exiting.\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x703a,
+ "Not 84xx, exiting.\n");
return -EINVAL;
}
ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request +
sizeof(struct fc_bsg_request));
if (!ql84_mgmt) {
- DEBUG2(printk("%s(%ld): mgmt header not provided, exiting.\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x703b,
+ "MGMT header not provided, exiting.\n");
return -EINVAL;
}
mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (!mn) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
- "failed for host=%lu\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x703c,
+ "DMA alloc failed for fw buffer.\n");
return -ENOMEM;
}
@@ -1044,6 +1060,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
if (!sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x703d,
+ "dma_map_sg returned %d for reply.\n", sg_cnt);
rval = -ENOMEM;
goto exit_mgmt;
}
@@ -1051,10 +1069,10 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
dma_direction = DMA_FROM_DEVICE;
if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
- DEBUG2(printk(KERN_INFO
- "dma mapping resulted in different sg counts "
- "reply_sg_cnt: %x dma_reply_sg_cnt: %x\n",
- bsg_job->reply_payload.sg_cnt, sg_cnt));
+ ql_log(ql_log_warn, vha, 0x703e,
+ "DMA mapping resulted in different sg counts, "
+ "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
+ bsg_job->reply_payload.sg_cnt, sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
@@ -1064,9 +1082,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
&mgmt_dma, GFP_KERNEL);
if (!mgmt_b) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
- "failed for host=%lu\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x703f,
+ "DMA alloc failed for mgmt_b.\n");
rval = -ENOMEM;
goto done_unmap_sg;
}
@@ -1094,6 +1111,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
if (!sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x7040,
+ "dma_map_sg returned %d.\n", sg_cnt);
rval = -ENOMEM;
goto exit_mgmt;
}
@@ -1101,10 +1120,10 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
dma_direction = DMA_TO_DEVICE;
if (sg_cnt != bsg_job->request_payload.sg_cnt) {
- DEBUG2(printk(KERN_INFO
- "dma mapping resulted in different sg counts "
- "request_sg_cnt: %x dma_request_sg_cnt: %x ",
- bsg_job->request_payload.sg_cnt, sg_cnt));
+ ql_log(ql_log_warn, vha, 0x7041,
+ "DMA mapping resulted in different sg counts, "
+ "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
+ bsg_job->request_payload.sg_cnt, sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
@@ -1113,9 +1132,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
&mgmt_dma, GFP_KERNEL);
if (!mgmt_b) {
- DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
- "failed for host=%lu\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7042,
+ "DMA alloc failed for mgmt_b.\n");
rval = -ENOMEM;
goto done_unmap_sg;
}
@@ -1156,15 +1174,15 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
if (rval) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request 84xx mgmt failed\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7043,
+ "Vendor request 84xx mgmt failed.\n");
rval = bsg_job->reply->reply_payload_rcv_len = 0;
bsg_job->reply->result = (DID_ERROR << 16);
} else {
- DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
- "request 84xx mgmt completed\n", vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x7044,
+ "Vendor request 84xx mgmt completed.\n");
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK;
@@ -1204,7 +1222,6 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
- struct qla_hw_data *ha = vha->hw;
int rval = 0;
struct qla_port_param *port_param = NULL;
fc_port_t *fcport = NULL;
@@ -1215,26 +1232,27 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
- test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
+ test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+ ql_log(ql_log_warn, vha, 0x7045, "abort active or needed.\n");
return -EBUSY;
+ }
if (!IS_IIDMA_CAPABLE(vha->hw)) {
- DEBUG2(qla_printk(KERN_WARNING, ha, "%s(%lu): iiDMA not "
- "supported\n", __func__, vha->host_no));
+ ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
return -EINVAL;
}
port_param = (struct qla_port_param *)((char *)bsg_job->request +
sizeof(struct fc_bsg_request));
if (!port_param) {
- DEBUG2(printk("%s(%ld): port_param header not provided, "
- "exiting.\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7047,
+ "port_param header not provided.\n");
return -EINVAL;
}
if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
- DEBUG2(printk(KERN_ERR "%s(%ld): Invalid destination type\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7048,
+ "Invalid destination type.\n");
return -EINVAL;
}
@@ -1249,21 +1267,20 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
}
if (!fcport) {
- DEBUG2(printk(KERN_ERR "%s(%ld): Failed to find port\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7049,
+ "Failed to find port.\n");
return -EINVAL;
}
if (atomic_read(&fcport->state) != FCS_ONLINE) {
- DEBUG2(printk(KERN_ERR "%s(%ld): Port not online\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x704a,
+ "Port is not online.\n");
return -EINVAL;
}
if (fcport->flags & FCF_LOGIN_NEEDED) {
- DEBUG2(printk(KERN_ERR "%s(%ld): Remote port not logged in, "
- "flags = 0x%x\n",
- __func__, vha->host_no, fcport->flags));
+ ql_log(ql_log_warn, vha, 0x704b,
+ "Remote port not logged in flags = 0x%x.\n", fcport->flags);
return -EINVAL;
}
@@ -1275,15 +1292,13 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
&port_param->speed, mb);
if (rval) {
- DEBUG16(printk(KERN_ERR "scsi(%ld): iIDMA cmd failed for "
- "%02x%02x%02x%02x%02x%02x%02x%02x -- "
- "%04x %x %04x %04x.\n",
- vha->host_no, fcport->port_name[0],
- fcport->port_name[1],
- fcport->port_name[2], fcport->port_name[3],
- fcport->port_name[4], fcport->port_name[5],
- fcport->port_name[6], fcport->port_name[7], rval,
- fcport->fp_speed, mb[0], mb[1]));
+ ql_log(ql_log_warn, vha, 0x704c,
+ "iIDMA cmd failed for %02x%02x%02x%02x%02x%02x%02x%02x -- "
+ "%04x %x %04x %04x.\n", fcport->port_name[0],
+ fcport->port_name[1], fcport->port_name[2],
+ fcport->port_name[3], fcport->port_name[4],
+ fcport->port_name[5], fcport->port_name[6],
+ fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]);
rval = 0;
bsg_job->reply->result = (DID_ERROR << 16);
@@ -1307,11 +1322,12 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
}
static int
-qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
+qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha,
uint8_t is_update)
{
uint32_t start = 0;
int valid = 0;
+ struct qla_hw_data *ha = vha->hw;
bsg_job->reply->reply_payload_rcv_len = 0;
@@ -1319,14 +1335,20 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
return -EINVAL;
start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
- if (start > ha->optrom_size)
+ if (start > ha->optrom_size) {
+ ql_log(ql_log_warn, vha, 0x7055,
+ "start %d > optrom_size %d.\n", start, ha->optrom_size);
return -EINVAL;
+ }
- if (ha->optrom_state != QLA_SWAITING)
+ if (ha->optrom_state != QLA_SWAITING) {
+ ql_log(ql_log_info, vha, 0x7056,
+ "optrom_state %d.\n", ha->optrom_state);
return -EBUSY;
+ }
ha->optrom_region_start = start;
-
+ ql_dbg(ql_dbg_user, vha, 0x7057, "is_update=%d.\n", is_update);
if (is_update) {
if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
valid = 1;
@@ -1337,9 +1359,9 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
IS_QLA8XXX_TYPE(ha))
valid = 1;
if (!valid) {
- qla_printk(KERN_WARNING, ha,
- "Invalid start region 0x%x/0x%x.\n",
- start, bsg_job->request_payload.payload_len);
+ ql_log(ql_log_warn, vha, 0x7058,
+ "Invalid start region 0x%x/0x%x.\n", start,
+ bsg_job->request_payload.payload_len);
return -EINVAL;
}
@@ -1358,9 +1380,9 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
if (!ha->optrom_buffer) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7059,
"Read: Unable to allocate memory for optrom retrieval "
- "(%x).\n", ha->optrom_region_size);
+ "(%x)\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
return -ENOMEM;
@@ -1378,7 +1400,7 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
struct qla_hw_data *ha = vha->hw;
int rval = 0;
- rval = qla2x00_optrom_setup(bsg_job, ha, 0);
+ rval = qla2x00_optrom_setup(bsg_job, vha, 0);
if (rval)
return rval;
@@ -1406,7 +1428,7 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
struct qla_hw_data *ha = vha->hw;
int rval = 0;
- rval = qla2x00_optrom_setup(bsg_job, ha, 1);
+ rval = qla2x00_optrom_setup(bsg_job, vha, 1);
if (rval)
return rval;
@@ -1426,6 +1448,148 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
}
static int
+qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
+ uint8_t bsg[DMA_POOL_SIZE];
+ struct qla_image_version_list *list = (void *)bsg;
+ struct qla_image_version *image;
+ uint32_t count;
+ dma_addr_t sfp_dma;
+ void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+ if (!sfp) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, list, sizeof(bsg));
+
+ image = list->version;
+ count = list->count;
+ while (count--) {
+ memcpy(sfp, &image->field_info, sizeof(image->field_info));
+ rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
+ image->field_address.device, image->field_address.offset,
+ sizeof(image->field_info), image->field_address.option);
+ if (rval) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_MAILBOX;
+ goto dealloc;
+ }
+ image++;
+ }
+
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
+
+dealloc:
+ dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
+
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job->reply->result = DID_OK << 16;
+ bsg_job->job_done(bsg_job);
+
+ return 0;
+}
+
+static int
+qla2x00_read_fru_status(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
+ uint8_t bsg[DMA_POOL_SIZE];
+ struct qla_status_reg *sr = (void *)bsg;
+ dma_addr_t sfp_dma;
+ uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+ if (!sfp) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
+
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
+ sr->field_address.device, sr->field_address.offset,
+ sizeof(sr->status_reg), sr->field_address.option);
+ sr->status_reg = *sfp;
+
+ if (rval) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_MAILBOX;
+ goto dealloc;
+ }
+
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr));
+
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
+
+dealloc:
+ dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
+
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job->reply->reply_payload_rcv_len = sizeof(*sr);
+ bsg_job->reply->result = DID_OK << 16;
+ bsg_job->job_done(bsg_job);
+
+ return 0;
+}
+
+static int
+qla2x00_write_fru_status(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
+ uint8_t bsg[DMA_POOL_SIZE];
+ struct qla_status_reg *sr = (void *)bsg;
+ dma_addr_t sfp_dma;
+ uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+ if (!sfp) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
+
+ *sfp = sr->status_reg;
+ rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
+ sr->field_address.device, sr->field_address.offset,
+ sizeof(sr->status_reg), sr->field_address.option);
+
+ if (rval) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_MAILBOX;
+ goto dealloc;
+ }
+
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
+
+dealloc:
+ dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
+
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job->reply->result = DID_OK << 16;
+ bsg_job->job_done(bsg_job);
+
+ return 0;
+}
+
+static int
qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
{
switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
@@ -1453,6 +1617,15 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
case QL_VND_UPDATE_FLASH:
return qla2x00_update_optrom(bsg_job);
+ case QL_VND_SET_FRU_VERSION:
+ return qla2x00_update_fru_versions(bsg_job);
+
+ case QL_VND_READ_FRU_STATUS:
+ return qla2x00_read_fru_status(bsg_job);
+
+ case QL_VND_WRITE_FRU_STATUS:
+ return qla2x00_write_fru_status(bsg_job);
+
default:
bsg_job->reply->result = (DID_ERROR << 16);
bsg_job->job_done(bsg_job);
@@ -1464,6 +1637,23 @@ int
qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
{
int ret = -EINVAL;
+ struct fc_rport *rport;
+ fc_port_t *fcport = NULL;
+ struct Scsi_Host *host;
+ scsi_qla_host_t *vha;
+
+ if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
+ rport = bsg_job->rport;
+ fcport = *(fc_port_t **) rport->dd_data;
+ host = rport_to_shost(rport);
+ vha = shost_priv(host);
+ } else {
+ host = bsg_job->shost;
+ vha = shost_priv(host);
+ }
+
+ ql_dbg(ql_dbg_user, vha, 0x7000,
+ "Entered %s msgcode=%d.\n", __func__, bsg_job->request->msgcode);
switch (bsg_job->request->msgcode) {
case FC_BSG_RPT_ELS:
@@ -1480,7 +1670,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
case FC_BSG_HST_DEL_RPORT:
case FC_BSG_RPT_CT:
default:
- DEBUG2(printk("qla2xxx: unsupported BSG request\n"));
+ ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
break;
}
return ret;
@@ -1514,17 +1704,15 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
&& (sp_bsg->u.bsg_job == bsg_job)) {
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld): mbx "
- "abort_command failed\n",
- vha->host_no));
+ ql_log(ql_log_warn, vha, 0x7089,
+ "mbx abort_command "
+ "failed.\n");
bsg_job->req->errors =
bsg_job->reply->result = -EIO;
} else {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld): mbx "
- "abort_command success\n",
- vha->host_no));
+ ql_dbg(ql_dbg_user, vha, 0x708a,
+ "mbx abort_command "
+ "success.\n");
bsg_job->req->errors =
bsg_job->reply->result = 0;
}
@@ -1535,8 +1723,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
}
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld) SRB not found to abort\n", vha->host_no));
+ ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
return 0;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 0f0f54e..70caa63 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -16,6 +16,16 @@
#define QL_VND_FCP_PRIO_CFG_CMD 0x06
#define QL_VND_READ_FLASH 0x07
#define QL_VND_UPDATE_FLASH 0x08
+#define QL_VND_SET_FRU_VERSION 0x0B
+#define QL_VND_READ_FRU_STATUS 0x0C
+#define QL_VND_WRITE_FRU_STATUS 0x0D
+
+/* BSG Vendor specific subcode returns */
+#define EXT_STATUS_OK 0
+#define EXT_STATUS_ERR 1
+#define EXT_STATUS_INVALID_PARAM 6
+#define EXT_STATUS_MAILBOX 11
+#define EXT_STATUS_NO_MEMORY 17
/* BSG definations for interpreting CommandSent field */
#define INT_DEF_LB_LOOPBACK_CMD 0
@@ -141,4 +151,36 @@ struct qla_port_param {
uint16_t mode;
uint16_t speed;
} __attribute__ ((packed));
+
+
+/* FRU VPD */
+
+#define MAX_FRU_SIZE 36
+
+struct qla_field_address {
+ uint16_t offset;
+ uint16_t device;
+ uint16_t option;
+} __packed;
+
+struct qla_field_info {
+ uint8_t version[MAX_FRU_SIZE];
+} __packed;
+
+struct qla_image_version {
+ struct qla_field_address field_address;
+ struct qla_field_info field_info;
+} __packed;
+
+struct qla_image_version_list {
+ uint32_t count;
+ struct qla_image_version version[0];
+} __packed;
+
+struct qla_status_reg {
+ struct qla_field_address field_address;
+ uint8_t status_reg;
+ uint8_t reserved[7];
+} __packed;
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index c53719a..f3cddd5 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -4,10 +4,36 @@
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
+
+/*
+ * Table for showing the current message id in use for particular level
+ * Change this table for addition of log/debug messages.
+ * ----------------------------------------------------------------------
+ * | Level | Last Value Used | Holes |
+ * ----------------------------------------------------------------------
+ * | Module Init and Probe | 0x0116 | |
+ * | Mailbox commands | 0x112b | |
+ * | Device Discovery | 0x2083 | |
+ * | Queue Command and IO tracing | 0x302e | 0x3008 |
+ * | DPC Thread | 0x401c | |
+ * | Async Events | 0x5059 | |
+ * | Timer Routines | 0x6010 | 0x600e,0x600f |
+ * | User Space Interactions | 0x709d | |
+ * | Task Management | 0x8041 | 0x800b |
+ * | AER/EEH | 0x900f | |
+ * | Virtual Port | 0xa007 | |
+ * | ISP82XX Specific | 0xb052 | |
+ * | MultiQ | 0xc00b | |
+ * | Misc | 0xd00b | |
+ * ----------------------------------------------------------------------
+ */
+
#include "qla_def.h"
#include <linux/delay.h>
+static uint32_t ql_dbg_offset = 0x800;
+
static inline void
qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump)
{
@@ -377,17 +403,17 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
return ptr + sizeof(struct qla2xxx_mq_chain);
}
-static void
+void
qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval)
{
struct qla_hw_data *ha = vha->hw;
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Failed to dump firmware (%x)!!!\n", rval);
+ ql_log(ql_log_warn, vha, 0xd000,
+ "Failed to dump firmware (%x).\n", rval);
ha->fw_dumped = 0;
} else {
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0xd001,
"Firmware dump saved to temp buffer (%ld/%p).\n",
vha->host_no, ha->fw_dump);
ha->fw_dumped = 1;
@@ -419,15 +445,16 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "No buffer available for dump!!!\n");
+ ql_log(ql_log_warn, vha, 0xd002,
+ "No buffer available for dump.\n");
goto qla2300_fw_dump_failed;
}
if (ha->fw_dumped) {
- qla_printk(KERN_WARNING, ha,
- "Firmware has been previously dumped (%p) -- ignoring "
- "request...\n", ha->fw_dump);
+ ql_log(ql_log_warn, vha, 0xd003,
+ "Firmware has been previously dumped (%p) "
+ "-- ignoring request.\n",
+ ha->fw_dump);
goto qla2300_fw_dump_failed;
}
fw = &ha->fw_dump->isp.isp23;
@@ -582,15 +609,16 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "No buffer available for dump!!!\n");
+ ql_log(ql_log_warn, vha, 0xd004,
+ "No buffer available for dump.\n");
goto qla2100_fw_dump_failed;
}
if (ha->fw_dumped) {
- qla_printk(KERN_WARNING, ha,
- "Firmware has been previously dumped (%p) -- ignoring "
- "request...\n", ha->fw_dump);
+ ql_log(ql_log_warn, vha, 0xd005,
+ "Firmware has been previously dumped (%p) "
+ "-- ignoring request.\n",
+ ha->fw_dump);
goto qla2100_fw_dump_failed;
}
fw = &ha->fw_dump->isp.isp21;
@@ -779,15 +807,16 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "No buffer available for dump!!!\n");
+ ql_log(ql_log_warn, vha, 0xd006,
+ "No buffer available for dump.\n");
goto qla24xx_fw_dump_failed;
}
if (ha->fw_dumped) {
- qla_printk(KERN_WARNING, ha,
- "Firmware has been previously dumped (%p) -- ignoring "
- "request...\n", ha->fw_dump);
+ ql_log(ql_log_warn, vha, 0xd007,
+ "Firmware has been previously dumped (%p) "
+ "-- ignoring request.\n",
+ ha->fw_dump);
goto qla24xx_fw_dump_failed;
}
fw = &ha->fw_dump->isp.isp24;
@@ -1017,15 +1046,16 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "No buffer available for dump!!!\n");
+ ql_log(ql_log_warn, vha, 0xd008,
+ "No buffer available for dump.\n");
goto qla25xx_fw_dump_failed;
}
if (ha->fw_dumped) {
- qla_printk(KERN_WARNING, ha,
- "Firmware has been previously dumped (%p) -- ignoring "
- "request...\n", ha->fw_dump);
+ ql_log(ql_log_warn, vha, 0xd009,
+ "Firmware has been previously dumped (%p) "
+ "-- ignoring request.\n",
+ ha->fw_dump);
goto qla25xx_fw_dump_failed;
}
fw = &ha->fw_dump->isp.isp25;
@@ -1328,15 +1358,16 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "No buffer available for dump!!!\n");
+ ql_log(ql_log_warn, vha, 0xd00a,
+ "No buffer available for dump.\n");
goto qla81xx_fw_dump_failed;
}
if (ha->fw_dumped) {
- qla_printk(KERN_WARNING, ha,
- "Firmware has been previously dumped (%p) -- ignoring "
- "request...\n", ha->fw_dump);
+ ql_log(ql_log_warn, vha, 0xd00b,
+ "Firmware has been previously dumped (%p) "
+ "-- ignoring request.\n",
+ ha->fw_dump);
goto qla81xx_fw_dump_failed;
}
fw = &ha->fw_dump->isp.isp81;
@@ -1619,106 +1650,255 @@ qla81xx_fw_dump_failed:
/****************************************************************************/
/* Driver Debug Functions. */
/****************************************************************************/
-
+/*
+ * This function is for formatting and logging debug information.
+ * It is to be used when vha is available. It formats the message
+ * and logs it to the messages file.
+ * parameters:
+ * level: The level of the debug messages to be printed.
+ * If ql2xextended_error_logging value is correctly set,
+ * this message will appear in the messages file.
+ * vha: Pointer to the scsi_qla_host_t.
+ * id: This is a unique identifier for the level. It identifies the
+ * part of the code from where the message originated.
+ * msg: The message to be displayed.
+ */
void
-qla2x00_dump_regs(scsi_qla_host_t *vha)
-{
- int i;
- struct qla_hw_data *ha = vha->hw;
- struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
- uint16_t __iomem *mbx_reg;
+ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) {
+
+ char pbuf[QL_DBG_BUF_LEN];
+ va_list ap;
+ uint32_t len;
+ struct pci_dev *pdev = NULL;
+
+ memset(pbuf, 0, QL_DBG_BUF_LEN);
+
+ va_start(ap, msg);
+
+ if ((level & ql2xextended_error_logging) == level) {
+ if (vha != NULL) {
+ pdev = vha->hw->pdev;
+ /* <module-name> <pci-name> <msg-id>:<host> Message */
+ sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR,
+ dev_name(&(pdev->dev)), id + ql_dbg_offset,
+ vha->host_no);
+ } else
+ sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+ "0000:00:00.0", id + ql_dbg_offset);
+
+ len = strlen(pbuf);
+ vsprintf(pbuf+len, msg, ap);
+ pr_warning("%s", pbuf);
+ }
- mbx_reg = IS_FWI2_CAPABLE(ha) ? &reg24->mailbox0:
- MAILBOX_REG(ha, reg, 0);
+ va_end(ap);
- printk("Mailbox registers:\n");
- for (i = 0; i < 6; i++)
- printk("scsi(%ld): mbox %d 0x%04x \n", vha->host_no, i,
- RD_REG_WORD(mbx_reg++));
}
-
+/*
+ * This function is for formatting and logging debug information.
+ * It is to be used when vha is not available and pci is availble,
+ * i.e., before host allocation. It formats the message and logs it
+ * to the messages file.
+ * parameters:
+ * level: The level of the debug messages to be printed.
+ * If ql2xextended_error_logging value is correctly set,
+ * this message will appear in the messages file.
+ * pdev: Pointer to the struct pci_dev.
+ * id: This is a unique id for the level. It identifies the part
+ * of the code from where the message originated.
+ * msg: The message to be displayed.
+ */
void
-qla2x00_dump_buffer(uint8_t * b, uint32_t size)
-{
- uint32_t cnt;
- uint8_t c;
+ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) {
- printk(" 0 1 2 3 4 5 6 7 8 9 "
- "Ah Bh Ch Dh Eh Fh\n");
- printk("----------------------------------------"
- "----------------------\n");
-
- for (cnt = 0; cnt < size;) {
- c = *b++;
- printk("%02x",(uint32_t) c);
- cnt++;
- if (!(cnt % 16))
- printk("\n");
- else
- printk(" ");
+ char pbuf[QL_DBG_BUF_LEN];
+ va_list ap;
+ uint32_t len;
+
+ if (pdev == NULL)
+ return;
+
+ memset(pbuf, 0, QL_DBG_BUF_LEN);
+
+ va_start(ap, msg);
+
+ if ((level & ql2xextended_error_logging) == level) {
+ /* <module-name> <dev-name>:<msg-id> Message */
+ sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+ dev_name(&(pdev->dev)), id + ql_dbg_offset);
+
+ len = strlen(pbuf);
+ vsprintf(pbuf+len, msg, ap);
+ pr_warning("%s", pbuf);
}
- if (cnt % 16)
- printk("\n");
+
+ va_end(ap);
+
}
+/*
+ * This function is for formatting and logging log messages.
+ * It is to be used when vha is available. It formats the message
+ * and logs it to the messages file. All the messages will be logged
+ * irrespective of value of ql2xextended_error_logging.
+ * parameters:
+ * level: The level of the log messages to be printed in the
+ * messages file.
+ * vha: Pointer to the scsi_qla_host_t
+ * id: This is a unique id for the level. It identifies the
+ * part of the code from where the message originated.
+ * msg: The message to be displayed.
+ */
void
-qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
-{
- uint32_t cnt;
- uint8_t c;
- uint8_t last16[16], cur16[16];
- uint32_t lc = 0, num_same16 = 0, j;
+ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) {
- printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 "
- "Ah Bh Ch Dh Eh Fh\n");
- printk(KERN_DEBUG "----------------------------------------"
- "----------------------\n");
+ char pbuf[QL_DBG_BUF_LEN];
+ va_list ap;
+ uint32_t len;
+ struct pci_dev *pdev = NULL;
- for (cnt = 0; cnt < size;) {
- c = *b++;
+ memset(pbuf, 0, QL_DBG_BUF_LEN);
- cur16[lc++] = c;
+ va_start(ap, msg);
- cnt++;
- if (cnt % 16)
- continue;
-
- /* We have 16 now */
- lc = 0;
- if (num_same16 == 0) {
- memcpy(last16, cur16, 16);
- num_same16++;
- continue;
+ if (level <= ql_errlev) {
+ if (vha != NULL) {
+ pdev = vha->hw->pdev;
+ /* <module-name> <msg-id>:<host> Message */
+ sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR,
+ dev_name(&(pdev->dev)), id, vha->host_no);
+ } else
+ sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+ "0000:00:00.0", id);
+
+ len = strlen(pbuf);
+ vsprintf(pbuf+len, msg, ap);
+
+ switch (level) {
+ case 0: /* FATAL LOG */
+ pr_crit("%s", pbuf);
+ break;
+ case 1:
+ pr_err("%s", pbuf);
+ break;
+ case 2:
+ pr_warn("%s", pbuf);
+ break;
+ default:
+ pr_info("%s", pbuf);
+ break;
}
- if (memcmp(cur16, last16, 16) == 0) {
- num_same16++;
- continue;
+ }
+
+ va_end(ap);
+}
+
+/*
+ * This function is for formatting and logging log messages.
+ * It is to be used when vha is not available and pci is availble,
+ * i.e., before host allocation. It formats the message and logs
+ * it to the messages file. All the messages are logged irrespective
+ * of the value of ql2xextended_error_logging.
+ * parameters:
+ * level: The level of the log messages to be printed in the
+ * messages file.
+ * pdev: Pointer to the struct pci_dev.
+ * id: This is a unique id for the level. It identifies the
+ * part of the code from where the message originated.
+ * msg: The message to be displayed.
+ */
+void
+ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) {
+
+ char pbuf[QL_DBG_BUF_LEN];
+ va_list ap;
+ uint32_t len;
+
+ if (pdev == NULL)
+ return;
+
+ memset(pbuf, 0, QL_DBG_BUF_LEN);
+
+ va_start(ap, msg);
+
+ if (level <= ql_errlev) {
+ /* <module-name> <dev-name>:<msg-id> Message */
+ sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR,
+ dev_name(&(pdev->dev)), id);
+
+ len = strlen(pbuf);
+ vsprintf(pbuf+len, msg, ap);
+ switch (level) {
+ case 0: /* FATAL LOG */
+ pr_crit("%s", pbuf);
+ break;
+ case 1:
+ pr_err("%s", pbuf);
+ break;
+ case 2:
+ pr_warn("%s", pbuf);
+ break;
+ default:
+ pr_info("%s", pbuf);
+ break;
}
- for (j = 0; j < 16; j++)
- printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]);
- printk(KERN_DEBUG "\n");
-
- if (num_same16 > 1)
- printk(KERN_DEBUG "> prev pattern repeats (%u)"
- "more times\n", num_same16-1);
- memcpy(last16, cur16, 16);
- num_same16 = 1;
}
- if (num_same16) {
- for (j = 0; j < 16; j++)
- printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]);
- printk(KERN_DEBUG "\n");
+ va_end(ap);
+}
- if (num_same16 > 1)
- printk(KERN_DEBUG "> prev pattern repeats (%u)"
- "more times\n", num_same16-1);
+void
+ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
+{
+ int i;
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
+ struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
+ uint16_t __iomem *mbx_reg;
+
+ if ((level & ql2xextended_error_logging) == level) {
+
+ if (IS_QLA82XX(ha))
+ mbx_reg = &reg82->mailbox_in[0];
+ else if (IS_FWI2_CAPABLE(ha))
+ mbx_reg = &reg24->mailbox0;
+ else
+ mbx_reg = MAILBOX_REG(ha, reg, 0);
+
+ ql_dbg(level, vha, id, "Mailbox registers:\n");
+ for (i = 0; i < 6; i++)
+ ql_dbg(level, vha, id,
+ "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
}
- if (lc) {
- for (j = 0; j < lc; j++)
- printk(KERN_DEBUG "%02x ", (uint32_t)cur16[j]);
- printk(KERN_DEBUG "\n");
+}
+
+
+void
+ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
+ uint8_t *b, uint32_t size)
+{
+ uint32_t cnt;
+ uint8_t c;
+ if ((level & ql2xextended_error_logging) == level) {
+
+ ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 "
+ "9 Ah Bh Ch Dh Eh Fh\n");
+ ql_dbg(level, vha, id, "----------------------------------"
+ "----------------------------\n");
+
+ ql_dbg(level, vha, id, "");
+ for (cnt = 0; cnt < size;) {
+ c = *b++;
+ printk("%02x", (uint32_t) c);
+ cnt++;
+ if (!(cnt % 16))
+ printk("\n");
+ else
+ printk(" ");
+ }
+ if (cnt % 16)
+ ql_dbg(level, vha, id, "\n");
}
}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 9304145..98a377b 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -8,146 +8,6 @@
#include "qla_def.h"
/*
- * Driver debug definitions.
- */
-/* #define QL_DEBUG_LEVEL_1 */ /* Output register accesses to COM1 */
-/* #define QL_DEBUG_LEVEL_2 */ /* Output error msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_3 */ /* Output function trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_4 */ /* Output NVRAM trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_5 */ /* Output ring trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_6 */ /* Output WATCHDOG timer trace to COM1 */
-/* #define QL_DEBUG_LEVEL_7 */ /* Output RISC load trace msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_8 */ /* Output ring saturation msgs to COM1 */
-/* #define QL_DEBUG_LEVEL_9 */ /* Output IOCTL trace msgs */
-/* #define QL_DEBUG_LEVEL_10 */ /* Output IOCTL error msgs */
-/* #define QL_DEBUG_LEVEL_11 */ /* Output Mbx Cmd trace msgs */
-/* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */
-/* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
-/* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
-/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
-/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
-/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
-/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */
-
-/*
-* Macros use for debugging the driver.
-*/
-
-#define DEBUG(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-
-#if defined(QL_DEBUG_LEVEL_1)
-#define DEBUG1(x) do {x;} while (0)
-#else
-#define DEBUG1(x) do {} while (0)
-#endif
-
-#define DEBUG2(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_3(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_3_11(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_11(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_13(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_16(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-#define DEBUG2_17(x) do { if (ql2xextended_error_logging) { x; } } while (0)
-
-#if defined(QL_DEBUG_LEVEL_3)
-#define DEBUG3(x) do {x;} while (0)
-#define DEBUG3_11(x) do {x;} while (0)
-#else
-#define DEBUG3(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_4)
-#define DEBUG4(x) do {x;} while (0)
-#else
-#define DEBUG4(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_5)
-#define DEBUG5(x) do {x;} while (0)
-#else
-#define DEBUG5(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_7)
-#define DEBUG7(x) do {x;} while (0)
-#else
-#define DEBUG7(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_9)
-#define DEBUG9(x) do {x;} while (0)
-#define DEBUG9_10(x) do {x;} while (0)
-#else
-#define DEBUG9(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_10)
-#define DEBUG10(x) do {x;} while (0)
-#define DEBUG9_10(x) do {x;} while (0)
-#else
-#define DEBUG10(x) do {} while (0)
- #if !defined(DEBUG9_10)
- #define DEBUG9_10(x) do {} while (0)
- #endif
-#endif
-
-#if defined(QL_DEBUG_LEVEL_11)
-#define DEBUG11(x) do{x;} while(0)
-#if !defined(DEBUG3_11)
-#define DEBUG3_11(x) do{x;} while(0)
-#endif
-#else
-#define DEBUG11(x) do{} while(0)
- #if !defined(QL_DEBUG_LEVEL_3)
- #define DEBUG3_11(x) do{} while(0)
- #endif
-#endif
-
-#if defined(QL_DEBUG_LEVEL_12)
-#define DEBUG12(x) do {x;} while (0)
-#else
-#define DEBUG12(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_13)
-#define DEBUG13(x) do {x;} while (0)
-#else
-#define DEBUG13(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_14)
-#define DEBUG14(x) do {x;} while (0)
-#else
-#define DEBUG14(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_15)
-#define DEBUG15(x) do {x;} while (0)
-#else
-#define DEBUG15(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_16)
-#define DEBUG16(x) do {x;} while (0)
-#else
-#define DEBUG16(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_17)
-#define DEBUG17(x) do {x;} while (0)
-#else
-#define DEBUG17(x) do {} while (0)
-#endif
-
-#if defined(QL_DEBUG_LEVEL_18)
-#define DEBUG18(x) do {if (ql2xextended_error_logging) x; } while (0)
-#else
-#define DEBUG18(x) do {} while (0)
-#endif
-
-
-/*
* Firmware Dump structure definition
*/
@@ -370,3 +230,50 @@ struct qla2xxx_fw_dump {
struct qla81xx_fw_dump isp81;
} isp;
};
+
+#define QL_MSGHDR "qla2xxx"
+
+#define ql_log_fatal 0 /* display fatal errors */
+#define ql_log_warn 1 /* display critical errors */
+#define ql_log_info 2 /* display all recovered errors */
+#define ql_log_all 3 /* This value is only used by ql_errlev.
+ * No messages will use this value.
+ * This should be always highest value
+ * as compared to other log levels.
+ */
+
+extern int ql_errlev;
+
+void
+ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, char *, ...);
+void
+ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...);
+
+void
+ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, char *, ...);
+void
+ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...);
+
+/* Debug Levels */
+/* The 0x40000000 is the max value any debug level can have
+ * as ql2xextended_error_logging is of type signed int
+ */
+#define ql_dbg_init 0x40000000 /* Init Debug */
+#define ql_dbg_mbx 0x20000000 /* MBX Debug */
+#define ql_dbg_disc 0x10000000 /* Device Discovery Debug */
+#define ql_dbg_io 0x08000000 /* IO Tracing Debug */
+#define ql_dbg_dpc 0x04000000 /* DPC Thead Debug */
+#define ql_dbg_async 0x02000000 /* Async events Debug */
+#define ql_dbg_timer 0x01000000 /* Timer Debug */
+#define ql_dbg_user 0x00800000 /* User Space Interations Debug */
+#define ql_dbg_taskm 0x00400000 /* Task Management Debug */
+#define ql_dbg_aer 0x00200000 /* AER/EEH Debug */
+#define ql_dbg_multiq 0x00100000 /* MultiQ Debug */
+#define ql_dbg_p3p 0x00080000 /* P3P specific Debug */
+#define ql_dbg_vport 0x00040000 /* Virtual Port Debug */
+#define ql_dbg_buffer 0x00020000 /* For dumping the buffer/regs */
+#define ql_dbg_misc 0x00010000 /* For dumping everything that is not
+ * not covered by upper categories
+ */
+
+#define QL_DBG_BUF_LEN 512
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index cc5a792..c491a94 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2438,7 +2438,8 @@ struct qla_hw_data {
uint32_t quiesce_owner:1;
uint32_t thermal_supported:1;
uint32_t isp82xx_reset_hdlr_active:1;
- /* 26 bits */
+ uint32_t isp82xx_reset_owner:1;
+ /* 28 bits */
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -2529,6 +2530,7 @@ struct qla_hw_data {
#define DT_ISP8021 BIT_14
#define DT_ISP_LAST (DT_ISP8021 << 1)
+#define DT_T10_PI BIT_25
#define DT_IIDMA BIT_26
#define DT_FWI2 BIT_27
#define DT_ZIO_SUPPORTED BIT_28
@@ -2566,12 +2568,12 @@ struct qla_hw_data {
IS_QLA25XX(ha) || IS_QLA81XX(ha) || \
IS_QLA82XX(ha))
#define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha))
-#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
- (ha)->flags.msix_enabled)
+#define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled)
#define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha))
#define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha))
#define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha))
+#define IS_T10_PI_CAPABLE(ha) ((ha)->device_type & DT_T10_PI)
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
#define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED)
@@ -2820,6 +2822,12 @@ struct qla_hw_data {
uint8_t fw_type;
__le32 file_prd_off; /* File firmware product offset */
+
+ uint32_t md_template_size;
+ void *md_tmplt_hdr;
+ dma_addr_t md_tmplt_hdr_dma;
+ void *md_dump;
+ uint32_t md_dump_size;
};
/*
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index a5a4e12..0b4c2b7 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -64,7 +64,7 @@ qla2x00_dfs_fce_open(struct inode *inode, struct file *file)
/* Pause tracing to flush FCE buffers. */
rval = qla2x00_disable_fce_trace(vha, &ha->fce_wr, &ha->fce_rd);
if (rval)
- qla_printk(KERN_WARNING, ha,
+ ql_dbg(ql_dbg_user, vha, 0x705c,
"DebugFS: Unable to disable FCE (%d).\n", rval);
ha->flags.fce_enabled = 0;
@@ -92,7 +92,7 @@ qla2x00_dfs_fce_release(struct inode *inode, struct file *file)
rval = qla2x00_enable_fce_trace(vha, ha->fce_dma, ha->fce_bufs,
ha->fce_mb, &ha->fce_bufs);
if (rval) {
- qla_printk(KERN_WARNING, ha,
+ ql_dbg(ql_dbg_user, vha, 0x700d,
"DebugFS: Unable to reinitialize FCE (%d).\n", rval);
ha->flags.fce_enabled = 0;
}
@@ -125,8 +125,8 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
atomic_set(&qla2x00_dfs_root_count, 0);
qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL);
if (!qla2x00_dfs_root) {
- qla_printk(KERN_NOTICE, ha,
- "DebugFS: Unable to create root directory.\n");
+ ql_log(ql_log_warn, vha, 0x00f7,
+ "Unable to create debugfs root directory.\n");
goto out;
}
@@ -137,8 +137,8 @@ create_dir:
mutex_init(&ha->fce_mutex);
ha->dfs_dir = debugfs_create_dir(vha->host_str, qla2x00_dfs_root);
if (!ha->dfs_dir) {
- qla_printk(KERN_NOTICE, ha,
- "DebugFS: Unable to create ha directory.\n");
+ ql_log(ql_log_warn, vha, 0x00f8,
+ "Unable to create debugfs ha directory.\n");
goto out;
}
@@ -148,8 +148,8 @@ create_nodes:
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
&dfs_fce_ops);
if (!ha->dfs_fce) {
- qla_printk(KERN_NOTICE, ha,
- "DebugFS: Unable to fce node.\n");
+ ql_log(ql_log_warn, vha, 0x00f9,
+ "Unable to create debugfs fce node.\n");
goto out;
}
out:
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 691783a..aa69486 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -537,6 +537,11 @@ struct sts_entry_24xx {
/*
* If DIF Error is set in comp_status, these additional fields are
* defined:
+ *
+ * !!! NOTE: Firmware sends expected/actual DIF data in big endian
+ * format; but all of the "data" field gets swab32-d in the beginning
+ * of qla2x00_status_entry().
+ *
* &data[10] : uint8_t report_runt_bg[2]; - computed guard
* &data[12] : uint8_t actual_dif[8]; - DIF Data received
* &data[20] : uint8_t expected_dif[8]; - DIF Data computed
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 0b38122..c0c11af 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -104,6 +104,8 @@ extern int ql2xenablehba_err_chk;
extern int ql2xtargetreset;
extern int ql2xdontresethba;
extern unsigned int ql2xmaxlun;
+extern int ql2xmdcapmask;
+extern int ql2xmdenable;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -185,7 +187,7 @@ extern int qla24xx_start_scsi(srb_t *sp);
int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
uint16_t, uint16_t, uint8_t);
extern int qla2x00_start_sp(srb_t *);
-extern uint16_t qla24xx_calc_iocbs(uint16_t);
+extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t);
extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
extern int qla24xx_dif_start_scsi(srb_t *);
@@ -407,6 +409,8 @@ extern void qla2x00_beacon_blink(struct scsi_qla_host *);
extern int qla24xx_beacon_on(struct scsi_qla_host *);
extern int qla24xx_beacon_off(struct scsi_qla_host *);
extern void qla24xx_beacon_blink(struct scsi_qla_host *);
+extern int qla82xx_beacon_on(struct scsi_qla_host *);
+extern int qla82xx_beacon_off(struct scsi_qla_host *);
extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
@@ -439,6 +443,10 @@ extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
extern void qla2x00_dump_regs(scsi_qla_host_t *);
extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
+extern void ql_dump_regs(uint32_t, scsi_qla_host_t *, int32_t);
+extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t,
+ uint8_t *, uint32_t);
+extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
/*
* Global Function Prototypes in qla_gs.c source file.
@@ -478,7 +486,8 @@ extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16
extern int qla2x00_echo_test(scsi_qla_host_t *,
struct msg_echo_lb *, uint16_t *);
extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
-extern int qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *, uint8_t);
+extern int qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *,
+ struct qla_fcp_prio_cfg *, uint8_t);
/*
* Global Function Prototypes in qla_dfs.c source file.
@@ -565,7 +574,11 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *);
extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
extern void qla82xx_start_iocbs(srb_t *);
extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
+extern int qla82xx_check_md_needed(scsi_qla_host_t *);
extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *);
+extern int qla82xx_mbx_beacon_ctl(scsi_qla_host_t *, int);
+extern char *qdev_state(uint32_t);
+extern void qla82xx_clear_pending_mbx(scsi_qla_host_t *);
/* BSG related functions */
extern int qla24xx_bsg_request(struct fc_bsg_job *);
@@ -575,4 +588,14 @@ extern int qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *,
dma_addr_t, size_t, uint32_t);
extern int qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t,
uint16_t *, uint16_t *);
+
+/* Minidump related functions */
+extern int qla82xx_md_get_template_size(scsi_qla_host_t *);
+extern int qla82xx_md_get_template(scsi_qla_host_t *);
+extern int qla82xx_md_alloc(scsi_qla_host_t *);
+extern void qla82xx_md_free(scsi_qla_host_t *);
+extern int qla82xx_md_collect(scsi_qla_host_t *);
+extern void qla82xx_md_prep(scsi_qla_host_t *);
+extern void qla82xx_set_reset_owner(scsi_qla_host_t *);
+
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 8cd9066..37937aa 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -121,11 +121,10 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
rval = QLA_FUNCTION_FAILED;
if (ms_pkt->entry_status != 0) {
- DEBUG2_3(printk(KERN_WARNING "scsi(%ld): %s failed, error status "
- "(%x) on port_id: %02x%02x%02x.\n",
- vha->host_no, routine, ms_pkt->entry_status,
- vha->d_id.b.domain, vha->d_id.b.area,
- vha->d_id.b.al_pa));
+ ql_dbg(ql_dbg_disc, vha, 0x2031,
+ "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
+ routine, ms_pkt->entry_status, vha->d_id.b.domain,
+ vha->d_id.b.area, vha->d_id.b.al_pa);
} else {
if (IS_FWI2_CAPABLE(ha))
comp_status = le16_to_cpu(
@@ -138,24 +137,24 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
case CS_DATA_OVERRUN: /* Overrun? */
if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
- DEBUG2_3(printk("scsi(%ld): %s failed, "
- "rejected request on port_id: %02x%02x%02x\n",
- vha->host_no, routine,
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
+ "%s failed rejected request on port_id: "
+ "%02x%02x%02x.\n", routine,
vha->d_id.b.domain, vha->d_id.b.area,
- vha->d_id.b.al_pa));
- DEBUG2_3(qla2x00_dump_buffer(
- (uint8_t *)&ct_rsp->header,
- sizeof(struct ct_rsp_hdr)));
+ vha->d_id.b.al_pa);
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
+ 0x2078, (uint8_t *)&ct_rsp->header,
+ sizeof(struct ct_rsp_hdr));
rval = QLA_INVALID_COMMAND;
} else
rval = QLA_SUCCESS;
break;
default:
- DEBUG2_3(printk("scsi(%ld): %s failed, completion "
- "status (%x) on port_id: %02x%02x%02x.\n",
- vha->host_no, routine, comp_status,
+ ql_dbg(ql_dbg_disc, vha, 0x2033,
+ "%s failed, completion status (%x) on port_id: "
+ "%02x%02x%02x.\n", routine, comp_status,
vha->d_id.b.domain, vha->d_id.b.area,
- vha->d_id.b.al_pa));
+ vha->d_id.b.al_pa);
break;
}
}
@@ -202,8 +201,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2062,
+ "GA_NXT issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
@@ -222,11 +221,10 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
fcport->d_id.b.domain = 0xf0;
- DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
- "nn %02x%02x%02x%02x%02x%02x%02x%02x "
+ ql_dbg(ql_dbg_disc, vha, 0x2063,
+ "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
"pn %02x%02x%02x%02x%02x%02x%02x%02x "
- "portid=%02x%02x%02x.\n",
- vha->host_no,
+ "port_id=%02x%02x%02x.\n",
fcport->node_name[0], fcport->node_name[1],
fcport->node_name[2], fcport->node_name[3],
fcport->node_name[4], fcport->node_name[5],
@@ -236,7 +234,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
fcport->port_name[4], fcport->port_name[5],
fcport->port_name[6], fcport->port_name[7],
fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ fcport->d_id.b.al_pa);
}
return (rval);
@@ -287,8 +285,8 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2055,
+ "GID_PT issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
@@ -364,8 +362,8 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed "
- "(%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2056,
+ "GPN_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
"GPN_ID") != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
@@ -424,8 +422,8 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GNN_ID issue IOCB failed "
- "(%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2057,
+ "GNN_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
"GNN_ID") != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
@@ -434,11 +432,10 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
memcpy(list[i].node_name,
ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
- DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
- "nn %02x%02x%02x%02x%02x%02x%02x%02x "
- "pn %02x%02x%02x%02x%02x%02x%02x%02x "
+ ql_dbg(ql_dbg_disc, vha, 0x2058,
+ "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02X%02x "
+ "pn %02x%02x%02x%02x%02x%02x%02X%02x "
"portid=%02x%02x%02x.\n",
- vha->host_no,
list[i].node_name[0], list[i].node_name[1],
list[i].node_name[2], list[i].node_name[3],
list[i].node_name[4], list[i].node_name[5],
@@ -448,7 +445,7 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
list[i].port_name[4], list[i].port_name[5],
list[i].port_name[6], list[i].port_name[7],
list[i].d_id.b.domain, list[i].d_id.b.area,
- list[i].d_id.b.al_pa));
+ list[i].d_id.b.al_pa);
}
/* Last device exit. */
@@ -499,14 +496,14 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RFT_ID issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2043,
+ "RFT_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2044,
+ "RFT_ID exiting normally.\n");
}
return (rval);
@@ -528,8 +525,8 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
struct ct_sns_rsp *ct_rsp;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
- DEBUG2(printk("scsi(%ld): RFF_ID call unsupported on "
- "ISP2100/ISP2200.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2046,
+ "RFF_ID call not supported on ISP2100/ISP2200.\n");
return (QLA_SUCCESS);
}
@@ -556,14 +553,14 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RFF_ID issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2047,
+ "RFF_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RFF_ID exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2048,
+ "RFF_ID exiting normally.\n");
}
return (rval);
@@ -609,14 +606,14 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RNN_ID issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x204d,
+ "RNN_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x204e,
+ "RNN_ID exiting normally.\n");
}
return (rval);
@@ -647,8 +644,8 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
struct ct_sns_rsp *ct_rsp;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
- DEBUG2(printk("scsi(%ld): RSNN_ID call unsupported on "
- "ISP2100/ISP2200.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2050,
+ "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
return (QLA_SUCCESS);
}
@@ -682,14 +679,14 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2051,
+ "RSNN_NN issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RSNN_NN exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2052,
+ "RSNN_NN exiting normally.\n");
}
return (rval);
@@ -757,13 +754,14 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
sizeof(struct sns_cmd_pkt));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GA_NXT Send SNS failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x205f,
+ "GA_NXT Send SNS failed (%d).\n", rval);
} else if (sns_cmd->p.gan_data[8] != 0x80 ||
sns_cmd->p.gan_data[9] != 0x02) {
- DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, "
- "ga_nxt_rsp:\n", vha->host_no));
- DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gan_data, 16));
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207d,
+ "GA_NXT failed, rejected request ga_nxt_rsp:\n");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
+ sns_cmd->p.gan_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
/* Populate fc_port_t entry. */
@@ -778,11 +776,10 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
fcport->d_id.b.domain = 0xf0;
- DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
- "nn %02x%02x%02x%02x%02x%02x%02x%02x "
+ ql_dbg(ql_dbg_disc, vha, 0x2061,
+ "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
"pn %02x%02x%02x%02x%02x%02x%02x%02x "
- "portid=%02x%02x%02x.\n",
- vha->host_no,
+ "port_id=%02x%02x%02x.\n",
fcport->node_name[0], fcport->node_name[1],
fcport->node_name[2], fcport->node_name[3],
fcport->node_name[4], fcport->node_name[5],
@@ -792,7 +789,7 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
fcport->port_name[4], fcport->port_name[5],
fcport->port_name[6], fcport->port_name[7],
fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ fcport->d_id.b.al_pa);
}
return (rval);
@@ -831,13 +828,14 @@ qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(struct sns_cmd_pkt));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GID_PT Send SNS failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x206d,
+ "GID_PT Send SNS failed (%d).\n", rval);
} else if (sns_cmd->p.gid_data[8] != 0x80 ||
sns_cmd->p.gid_data[9] != 0x02) {
- DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, "
- "gid_rsp:\n", vha->host_no));
- DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gid_data, 16));
+ ql_dbg(ql_dbg_disc, vha, 0x202f,
+ "GID_PT failed, rejected request, gid_rsp:\n");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
+ sns_cmd->p.gid_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
/* Set port IDs in switch info list. */
@@ -900,13 +898,14 @@ qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GPN_ID Send SNS failed "
- "(%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2032,
+ "GPN_ID Send SNS failed (%d).\n", rval);
} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
sns_cmd->p.gpn_data[9] != 0x02) {
- DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected "
- "request, gpn_rsp:\n", vha->host_no));
- DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gpn_data, 16));
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
+ "GPN_ID failed, rejected request, gpn_rsp:\n");
+ ql_dump_buffer(ql_dbg_disc, vha, 0x207f,
+ sns_cmd->p.gpn_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
/* Save portname */
@@ -955,24 +954,24 @@ qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GNN_ID Send SNS failed "
- "(%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x203f,
+ "GNN_ID Send SNS failed (%d).\n", rval);
} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
sns_cmd->p.gnn_data[9] != 0x02) {
- DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected "
- "request, gnn_rsp:\n", vha->host_no));
- DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gnn_data, 16));
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
+ "GNN_ID failed, rejected request, gnn_rsp:\n");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
+ sns_cmd->p.gnn_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
/* Save nodename */
memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
WWN_SIZE);
- DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
- "nn %02x%02x%02x%02x%02x%02x%02x%02x "
+ ql_dbg(ql_dbg_disc, vha, 0x206e,
+ "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
"pn %02x%02x%02x%02x%02x%02x%02x%02x "
- "portid=%02x%02x%02x.\n",
- vha->host_no,
+ "port_id=%02x%02x%02x.\n",
list[i].node_name[0], list[i].node_name[1],
list[i].node_name[2], list[i].node_name[3],
list[i].node_name[4], list[i].node_name[5],
@@ -982,7 +981,7 @@ qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
list[i].port_name[4], list[i].port_name[5],
list[i].port_name[6], list[i].port_name[7],
list[i].d_id.b.domain, list[i].d_id.b.area,
- list[i].d_id.b.al_pa));
+ list[i].d_id.b.al_pa);
}
/* Last device exit. */
@@ -1025,17 +1024,18 @@ qla2x00_sns_rft_id(scsi_qla_host_t *vha)
sizeof(struct sns_cmd_pkt));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RFT_ID Send SNS failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2060,
+ "RFT_ID Send SNS failed (%d).\n", rval);
} else if (sns_cmd->p.rft_data[8] != 0x80 ||
sns_cmd->p.rft_data[9] != 0x02) {
- DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected request, "
- "rft_rsp:\n", vha->host_no));
- DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rft_data, 16));
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
+ "RFT_ID failed, rejected request rft_rsp:\n");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
+ sns_cmd->p.rft_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2073,
+ "RFT_ID exiting normally.\n");
}
return (rval);
@@ -1081,17 +1081,18 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
sizeof(struct sns_cmd_pkt));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RNN_ID Send SNS failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x204a,
+ "RNN_ID Send SNS failed (%d).\n", rval);
} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
sns_cmd->p.rnn_data[9] != 0x02) {
- DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected request, "
- "rnn_rsp:\n", vha->host_no));
- DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rnn_data, 16));
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
+ "RNN_ID failed, rejected request, rnn_rsp:\n");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
+ sns_cmd->p.rnn_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x204c,
+ "RNN_ID exiting normally.\n");
}
return (rval);
@@ -1116,10 +1117,10 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
mb, BIT_1|BIT_0);
if (mb[0] != MBS_COMMAND_COMPLETE) {
- DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
- "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n",
- __func__, vha->host_no, vha->mgmt_svr_loop_id, mb[0], mb[1],
- mb[2], mb[6], mb[7]));
+ ql_dbg(ql_dbg_disc, vha, 0x2024,
+ "Failed management_server login: loopid=%x mb[0]=%x "
+ "mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
+ vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6], mb[7]);
ret = QLA_FUNCTION_FAILED;
} else
vha->flags.management_server_logged_in = 1;
@@ -1292,11 +1293,12 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
size += 4 + WWN_SIZE;
- DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n",
- __func__, vha->host_no,
- eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2],
- eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5],
- eiter->a.node_name[6], eiter->a.node_name[7]));
+ ql_dbg(ql_dbg_disc, vha, 0x2025,
+ "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
+ eiter->a.node_name[0], eiter->a.node_name[1],
+ eiter->a.node_name[2], eiter->a.node_name[3],
+ eiter->a.node_name[4], eiter->a.node_name[5],
+ eiter->a.node_name[6], eiter->a.node_name[7]);
/* Manufacturer. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1307,8 +1309,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, vha->host_no,
- eiter->a.manufacturer));
+ ql_dbg(ql_dbg_disc, vha, 0x2026,
+ "Manufacturer = %s.\n", eiter->a.manufacturer);
/* Serial number. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1320,8 +1322,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, vha->host_no,
- eiter->a.serial_num));
+ ql_dbg(ql_dbg_disc, vha, 0x2027,
+ "Serial no. = %s.\n", eiter->a.serial_num);
/* Model name. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1332,8 +1334,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, vha->host_no,
- eiter->a.model));
+ ql_dbg(ql_dbg_disc, vha, 0x2028,
+ "Model Name = %s.\n", eiter->a.model);
/* Model description. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1345,8 +1347,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, vha->host_no,
- eiter->a.model_desc));
+ ql_dbg(ql_dbg_disc, vha, 0x2029,
+ "Model Desc = %s.\n", eiter->a.model_desc);
/* Hardware version. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1357,8 +1359,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, vha->host_no,
- eiter->a.hw_version));
+ ql_dbg(ql_dbg_disc, vha, 0x202a,
+ "Hardware ver = %s.\n", eiter->a.hw_version);
/* Driver version. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1369,8 +1371,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, vha->host_no,
- eiter->a.driver_version));
+ ql_dbg(ql_dbg_disc, vha, 0x202b,
+ "Driver ver = %s.\n", eiter->a.driver_version);
/* Option ROM version. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1381,8 +1383,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, vha->host_no,
- eiter->a.orom_version));
+ ql_dbg(ql_dbg_disc, vha , 0x202c,
+ "Optrom vers = %s.\n", eiter->a.orom_version);
/* Firmware version */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
@@ -1393,44 +1395,46 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, vha->host_no,
- eiter->a.fw_version));
+ ql_dbg(ql_dbg_disc, vha, 0x202d,
+ "Firmware vers = %s.\n", eiter->a.fw_version);
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb(vha, size + 16);
- DEBUG13(printk("%s(%ld): RHBA identifier="
- "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
- vha->host_no, ct_req->req.rhba.hba_identifier[0],
+ ql_dbg(ql_dbg_disc, vha, 0x202e,
+ "RHBA identifier = "
+ "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
+ ct_req->req.rhba.hba_identifier[0],
ct_req->req.rhba.hba_identifier[1],
ct_req->req.rhba.hba_identifier[2],
ct_req->req.rhba.hba_identifier[3],
ct_req->req.rhba.hba_identifier[4],
ct_req->req.rhba.hba_identifier[5],
ct_req->req.rhba.hba_identifier[6],
- ct_req->req.rhba.hba_identifier[7], size));
- DEBUG13(qla2x00_dump_buffer(entries, size));
+ ct_req->req.rhba.hba_identifier[7], size);
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
+ entries, size);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2030,
+ "RHBA issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
ct_rsp->header.explanation_code ==
CT_EXPL_ALREADY_REGISTERED) {
- DEBUG2_13(printk("%s(%ld): HBA already registered.\n",
- __func__, vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2034,
+ "HBA already registered.\n");
rval = QLA_ALREADY_REGISTERED;
}
} else {
- DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2035,
+ "RHBA exiting normally.\n");
}
return rval;
@@ -1464,26 +1468,26 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
/* Prepare FDMI command arguments -- portname. */
memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
- DEBUG13(printk("%s(%ld): DHBA portname="
- "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, vha->host_no,
+ ql_dbg(ql_dbg_disc, vha, 0x2036,
+ "DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
- ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]));
+ ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2037,
+ "DHBA issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2038,
+ "DHBA exiting normally.\n");
}
return rval;
@@ -1534,9 +1538,10 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
eiter->a.fc4_types[2] = 0x01;
size += 4 + 32;
- DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__,
- vha->host_no, eiter->a.fc4_types[2],
- eiter->a.fc4_types[1]));
+ ql_dbg(ql_dbg_disc, vha, 0x2039,
+ "FC4_TYPES=%02x %02x.\n",
+ eiter->a.fc4_types[2],
+ eiter->a.fc4_types[1]);
/* Supported speed. */
eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1561,8 +1566,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
FDMI_PORT_SPEED_1GB);
size += 4 + 4;
- DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, vha->host_no,
- eiter->a.sup_speed));
+ ql_dbg(ql_dbg_disc, vha, 0x203a,
+ "Supported_Speed=%x.\n", eiter->a.sup_speed);
/* Current speed. */
eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1596,8 +1601,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
}
size += 4 + 4;
- DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, vha->host_no,
- eiter->a.cur_speed));
+ ql_dbg(ql_dbg_disc, vha, 0x203b,
+ "Current_Speed=%x.\n", eiter->a.cur_speed);
/* Max frame size. */
eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1609,8 +1614,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
size += 4 + 4;
- DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, vha->host_no,
- eiter->a.max_frame_size));
+ ql_dbg(ql_dbg_disc, vha, 0x203c,
+ "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
/* OS device name. */
eiter = (struct ct_fdmi_port_attr *) (entries + size);
@@ -1621,8 +1626,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, vha->host_no,
- eiter->a.os_dev_name));
+ ql_dbg(ql_dbg_disc, vha, 0x204b,
+ "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
/* Hostname. */
if (strlen(fc_host_system_hostname(vha->host))) {
@@ -1637,35 +1642,36 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- DEBUG13(printk("%s(%ld): HOSTNAME=%s.\n", __func__,
- vha->host_no, eiter->a.host_name));
+ ql_dbg(ql_dbg_disc, vha, 0x203d,
+ "HostName=%s.\n", eiter->a.host_name);
}
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb(vha, size + 16);
- DEBUG13(printk("%s(%ld): RPA portname="
- "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
- vha->host_no, ct_req->req.rpa.port_name[0],
- ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2],
- ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4],
- ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6],
- ct_req->req.rpa.port_name[7], size));
- DEBUG13(qla2x00_dump_buffer(entries, size));
+ ql_dbg(ql_dbg_disc, vha, 0x203e,
+ "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
+ ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
+ ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
+ ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
+ ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
+ size);
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
+ entries, size);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2040,
+ "RPA issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("scsi(%ld): RPA exiting normally.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2041,
+ "RPA exiting nornally.\n");
}
return rval;
@@ -1749,8 +1755,8 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GFPN_ID issue IOCB "
- "failed (%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2023,
+ "GFPN_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
"GFPN_ID") != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
@@ -1860,8 +1866,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3(printk("scsi(%ld): GPSC issue IOCB "
- "failed (%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2059,
+ "GPSC issue IOCB failed (%d).\n", rval);
} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
"GPSC")) != QLA_SUCCESS) {
/* FM command unsupported? */
@@ -1870,9 +1876,9 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
CT_REASON_INVALID_COMMAND_CODE ||
ct_rsp->header.reason_code ==
CT_REASON_COMMAND_UNSUPPORTED)) {
- DEBUG2(printk("scsi(%ld): GPSC command "
- "unsupported, disabling query...\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x205a,
+ "GPSC command unsupported, disabling "
+ "query.\n");
ha->flags.gpsc_supported = 0;
rval = QLA_FUNCTION_FAILED;
break;
@@ -1898,9 +1904,10 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
break;
}
- DEBUG2_3(printk("scsi(%ld): GPSC ext entry - "
- "fpn %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
- "speed=%04x.\n", vha->host_no,
+ ql_dbg(ql_dbg_disc, vha, 0x205b,
+ "GPSC ext entry - fpn "
+ "%02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
+ "speed=%04x.\n",
list[i].fabric_port_name[0],
list[i].fabric_port_name[1],
list[i].fabric_port_name[2],
@@ -1910,7 +1917,7 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
list[i].fabric_port_name[6],
list[i].fabric_port_name[7],
be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
- be16_to_cpu(ct_rsp->rsp.gpsc.speed)));
+ be16_to_cpu(ct_rsp->rsp.gpsc.speed));
}
/* Last device exit. */
@@ -1968,14 +1975,12 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
sizeof(ms_iocb_entry_t));
if (rval != QLA_SUCCESS) {
- DEBUG2_3(printk(KERN_INFO
- "scsi(%ld): GFF_ID issue IOCB failed "
- "(%d).\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x205c,
+ "GFF_ID issue IOCB failed (%d).\n", rval);
} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
"GFF_ID") != QLA_SUCCESS) {
- DEBUG2_3(printk(KERN_INFO
- "scsi(%ld): GFF_ID IOCB status had a "
- "failure status code\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x205d,
+ "GFF_ID IOCB status had a failure status code.\n");
} else {
fcp_scsi_features =
ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b2df2f9..54ea68c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -153,11 +153,10 @@ qla2x00_async_iocb_timeout(srb_t *sp)
fc_port_t *fcport = sp->fcport;
struct srb_ctx *ctx = sp->ctx;
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s timeout - portid=%02x%02x%02x.\n",
- fcport->vha->host_no, sp->handle,
- ctx->name, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
+ "Async-%s timeout - portid=%02x%02x%02x.\n",
+ ctx->name, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
fcport->flags &= ~FCF_ASYNC_SENT;
if (ctx->type == SRB_LOGIN_CMD) {
@@ -211,11 +210,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
if (rval != QLA_SUCCESS)
goto done_free_sp;
- DEBUG2(printk(KERN_DEBUG
- "scsi(%ld:%x): Async-login - loop-id=%x portid=%02x%02x%02x "
- "retries=%d.\n", fcport->vha->host_no, sp->handle, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
- fcport->login_retry));
+ ql_dbg(ql_dbg_disc, vha, 0x2072,
+ "Async-login - loopid=%x portid=%02x%02x%02x retries=%d.\n",
+ fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, fcport->login_retry);
return rval;
done_free_sp:
@@ -259,10 +257,10 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
if (rval != QLA_SUCCESS)
goto done_free_sp;
- DEBUG2(printk(KERN_DEBUG
- "scsi(%ld:%x): Async-logout - loop-id=%x portid=%02x%02x%02x.\n",
- fcport->vha->host_no, sp->handle, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_disc, vha, 0x2070,
+ "Async-logout - loop-id=%x portid=%02x%02x%02x.\n",
+ fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
return rval;
done_free_sp:
@@ -309,11 +307,10 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
if (rval != QLA_SUCCESS)
goto done_free_sp;
- DEBUG2(printk(KERN_DEBUG
- "scsi(%ld:%x): Async-adisc - loop-id=%x portid=%02x%02x%02x.\n",
- fcport->vha->host_no, sp->handle, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
-
+ ql_dbg(ql_dbg_disc, vha, 0x206f,
+ "Async-adisc - loopid=%x portid=%02x%02x%02x.\n",
+ fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
return rval;
done_free_sp:
@@ -362,11 +359,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
if (rval != QLA_SUCCESS)
goto done_free_sp;
- DEBUG2(printk(KERN_DEBUG
- "scsi(%ld:%x): Async-tmf - loop-id=%x portid=%02x%02x%02x.\n",
- fcport->vha->host_no, sp->handle, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
-
+ ql_dbg(ql_dbg_taskm, vha, 0x802f,
+ "Async-tmf loop-id=%x portid=%02x%02x%02x.\n",
+ fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
return rval;
done_free_sp:
@@ -471,9 +467,8 @@ qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): TM IOCB failed (%x).\n",
- __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_taskm, vha, 0x8030,
+ "TM IOCB failed (%x).\n", rval);
}
return;
@@ -519,11 +514,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
set_bit(0, ha->req_qid_map);
set_bit(0, ha->rsp_qid_map);
- qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
+ ql_log(ql_log_info, vha, 0x0040,
+ "Configuring PCI space...\n");
rval = ha->isp_ops->pci_config(vha);
if (rval) {
- DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n",
- vha->host_no));
+ ql_log(ql_log_warn, vha, 0x0044,
+ "Unable to configure PCI space.\n");
return (rval);
}
@@ -531,20 +527,21 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
rval = qla2xxx_get_flash_info(vha);
if (rval) {
- DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n",
- vha->host_no));
+ ql_log(ql_log_fatal, vha, 0x004f,
+ "Unable to validate FLASH data.\n");
return (rval);
}
ha->isp_ops->get_flash_version(vha, req->ring);
-
- qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
+ ql_log(ql_log_info, vha, 0x0061,
+ "Configure NVRAM parameters...\n");
ha->isp_ops->nvram_config(vha);
if (ha->flags.disable_serdes) {
/* Mask HBA via NVRAM settings? */
- qla_printk(KERN_INFO, ha, "Masking HBA WWPN "
+ ql_log(ql_log_info, vha, 0x0077,
+ "Masking HBA WWPN "
"%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n",
vha->port_name[0], vha->port_name[1],
vha->port_name[2], vha->port_name[3],
@@ -553,7 +550,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
return QLA_FUNCTION_FAILED;
}
- qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
+ ql_log(ql_log_info, vha, 0x0078,
+ "Verifying loaded RISC code...\n");
if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) {
rval = ha->isp_ops->chip_diag(vha);
@@ -567,7 +565,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
if (IS_QLA84XX(ha)) {
ha->cs84xx = qla84xx_get_chip(vha);
if (!ha->cs84xx) {
- qla_printk(KERN_ERR, ha,
+ ql_log(ql_log_warn, vha, 0x00d0,
"Unable to configure ISP84XX.\n");
return QLA_FUNCTION_FAILED;
}
@@ -579,8 +577,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
/* Issue verify 84xx FW IOCB to complete 84xx initialization */
rval = qla84xx_init_chip(vha);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_ERR, ha,
- "Unable to initialize ISP84XX.\n");
+ ql_log(ql_log_warn, vha, 0x00d4,
+ "Unable to initialize ISP84XX.\n");
qla84xx_put_chip(vha);
}
}
@@ -797,9 +795,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha)
rval = QLA_FUNCTION_FAILED;
if (ha->flags.disable_risc_code_load) {
- DEBUG2(printk("scsi(%ld): RISC CODE NOT loaded\n",
- vha->host_no));
- qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n");
+ ql_log(ql_log_info, vha, 0x0079, "RISC CODE NOT loaded.\n");
/* Verify checksum of loaded RISC code. */
rval = qla2x00_verify_checksum(vha, ha->fw_srisc_address);
@@ -810,10 +806,9 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha)
}
}
- if (rval) {
- DEBUG2_3(printk("scsi(%ld): **** Load RISC code ****\n",
- vha->host_no));
- }
+ if (rval)
+ ql_dbg(ql_dbg_init, vha, 0x007a,
+ "**** Load RISC code ****.\n");
return (rval);
}
@@ -1105,8 +1100,8 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
/* Assume a failed state */
rval = QLA_FUNCTION_FAILED;
- DEBUG3(printk("scsi(%ld): Testing device at %lx.\n",
- vha->host_no, (u_long)&reg->flash_address));
+ ql_dbg(ql_dbg_init, vha, 0x007b,
+ "Testing device at %lx.\n", (u_long)&reg->flash_address);
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1128,8 +1123,8 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
if (!cnt)
goto chip_diag_failed;
- DEBUG3(printk("scsi(%ld): Reset register cleared by chip reset\n",
- vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x007c,
+ "Reset register cleared by chip reset.\n");
/* Reset RISC processor. */
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
@@ -1150,7 +1145,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
goto chip_diag_failed;
/* Check product ID of chip */
- DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product Id of chip.\n");
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
@@ -1158,8 +1153,9 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4));
if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) ||
mb[3] != PROD_ID_3) {
- qla_printk(KERN_WARNING, ha,
- "Wrong product ID = 0x%x,0x%x,0x%x\n", mb[1], mb[2], mb[3]);
+ ql_log(ql_log_warn, vha, 0x0062,
+ "Wrong product ID = 0x%x,0x%x,0x%x.\n",
+ mb[1], mb[2], mb[3]);
goto chip_diag_failed;
}
@@ -1178,8 +1174,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
if (IS_QLA2200(ha) &&
RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) {
/* Limit firmware transfer size with a 2200A */
- DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x007e, "Found QLA2200A Chip.\n");
ha->device_type |= DT_ISP2200A;
ha->fw_transfer_size = 128;
@@ -1188,24 +1183,20 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
/* Wrap Incoming Mailboxes Test. */
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- DEBUG3(printk("scsi(%ld): Checking mailboxes.\n", vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x007f, "Checking mailboxes.\n");
rval = qla2x00_mbx_reg_test(vha);
- if (rval) {
- DEBUG(printk("scsi(%ld): Failed mailbox send register test\n",
- vha->host_no));
- qla_printk(KERN_WARNING, ha,
- "Failed mailbox send register test\n");
- }
- else {
+ if (rval)
+ ql_log(ql_log_warn, vha, 0x0080,
+ "Failed mailbox send register test.\n");
+ else
/* Flag a successful rval */
rval = QLA_SUCCESS;
- }
spin_lock_irqsave(&ha->hardware_lock, flags);
chip_diag_failed:
if (rval)
- DEBUG2_3(printk("scsi(%ld): Chip diagnostics **** FAILED "
- "****\n", vha->host_no));
+ ql_log(ql_log_info, vha, 0x0081,
+ "Chip diagnostics **** FAILED ****.\n");
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1232,10 +1223,8 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
rval = qla2x00_mbx_reg_test(vha);
if (rval) {
- DEBUG(printk("scsi(%ld): Failed mailbox send register test\n",
- vha->host_no));
- qla_printk(KERN_WARNING, ha,
- "Failed mailbox send register test\n");
+ ql_log(ql_log_warn, vha, 0x0082,
+ "Failed mailbox send register test.\n");
} else {
/* Flag a successful rval */
rval = QLA_SUCCESS;
@@ -1257,8 +1246,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
struct rsp_que *rsp = ha->rsp_q_map[0];
if (ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "Firmware dump previously allocated.\n");
+ ql_dbg(ql_dbg_init, vha, 0x00bd,
+ "Firmware dump already allocated.\n");
return;
}
@@ -1288,8 +1277,9 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
GFP_KERNEL);
if (!tc) {
- qla_printk(KERN_WARNING, ha, "Unable to allocate "
- "(%d KB) for FCE.\n", FCE_SIZE / 1024);
+ ql_log(ql_log_warn, vha, 0x00be,
+ "Unable to allocate (%d KB) for FCE.\n",
+ FCE_SIZE / 1024);
goto try_eft;
}
@@ -1297,16 +1287,15 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
ha->fce_mb, &ha->fce_bufs);
if (rval) {
- qla_printk(KERN_WARNING, ha, "Unable to initialize "
- "FCE (%d).\n", rval);
+ ql_log(ql_log_warn, vha, 0x00bf,
+ "Unable to initialize FCE (%d).\n", rval);
dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
tc_dma);
ha->flags.fce_enabled = 0;
goto try_eft;
}
-
- qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
- FCE_SIZE / 1024);
+ ql_log(ql_log_info, vha, 0x00c0,
+ "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
ha->flags.fce_enabled = 1;
@@ -1317,23 +1306,23 @@ try_eft:
tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
GFP_KERNEL);
if (!tc) {
- qla_printk(KERN_WARNING, ha, "Unable to allocate "
- "(%d KB) for EFT.\n", EFT_SIZE / 1024);
+ ql_log(ql_log_warn, vha, 0x00c1,
+ "Unable to allocate (%d KB) for EFT.\n",
+ EFT_SIZE / 1024);
goto cont_alloc;
}
memset(tc, 0, EFT_SIZE);
rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
if (rval) {
- qla_printk(KERN_WARNING, ha, "Unable to initialize "
- "EFT (%d).\n", rval);
+ ql_log(ql_log_warn, vha, 0x00c2,
+ "Unable to initialize EFT (%d).\n", rval);
dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
tc_dma);
goto cont_alloc;
}
-
- qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
- EFT_SIZE / 1024);
+ ql_log(ql_log_info, vha, 0x00c3,
+ "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
eft_size = EFT_SIZE;
ha->eft_dma = tc_dma;
@@ -1350,8 +1339,9 @@ cont_alloc:
ha->fw_dump = vmalloc(dump_size);
if (!ha->fw_dump) {
- qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
- "firmware dump!!!\n", dump_size / 1024);
+ ql_log(ql_log_warn, vha, 0x00c4,
+ "Unable to allocate (%d KB) for firmware dump.\n",
+ dump_size / 1024);
if (ha->fce) {
dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
@@ -1368,8 +1358,8 @@ cont_alloc:
}
return;
}
- qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n",
- dump_size / 1024);
+ ql_log(ql_log_info, vha, 0x00c5,
+ "Allocated (%d KB) for firmware dump.\n", dump_size / 1024);
ha->fw_dump_len = dump_size;
ha->fw_dump->signature[0] = 'Q';
@@ -1398,23 +1388,21 @@ qla81xx_mpi_sync(scsi_qla_host_t *vha)
int rval;
uint16_t dc;
uint32_t dw;
- struct qla_hw_data *ha = vha->hw;
if (!IS_QLA81XX(vha->hw))
return QLA_SUCCESS;
rval = qla2x00_write_ram_word(vha, 0x7c00, 1);
if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "Sync-MPI: Unable to acquire semaphore.\n"));
+ ql_log(ql_log_warn, vha, 0x0105,
+ "Unable to acquire semaphore.\n");
goto done;
}
pci_read_config_word(vha->hw->pdev, 0x54, &dc);
rval = qla2x00_read_ram_word(vha, 0x7a15, &dw);
if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "Sync-MPI: Unable to read sync.\n"));
+ ql_log(ql_log_warn, vha, 0x0067, "Unable to read sync.\n");
goto done_release;
}
@@ -1426,15 +1414,14 @@ qla81xx_mpi_sync(scsi_qla_host_t *vha)
dw |= dc;
rval = qla2x00_write_ram_word(vha, 0x7a15, dw);
if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "Sync-MPI: Unable to gain sync.\n"));
+ ql_log(ql_log_warn, vha, 0x0114, "Unable to gain sync.\n");
}
done_release:
rval = qla2x00_write_ram_word(vha, 0x7c00, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "Sync-MPI: Unable to release semaphore.\n"));
+ ql_log(ql_log_warn, vha, 0x006d,
+ "Unable to release semaphore.\n");
}
done:
@@ -1479,27 +1466,33 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
/* Load firmware sequences */
rval = ha->isp_ops->load_risc(vha, &srisc_address);
if (rval == QLA_SUCCESS) {
- DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC "
- "code.\n", vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x00c9,
+ "Verifying Checksum of loaded RISC code.\n");
rval = qla2x00_verify_checksum(vha, srisc_address);
if (rval == QLA_SUCCESS) {
/* Start firmware execution. */
- DEBUG(printk("scsi(%ld): Checksum OK, start "
- "firmware.\n", vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x00ca,
+ "Starting firmware.\n");
rval = qla2x00_execute_fw(vha, srisc_address);
/* Retrieve firmware information. */
if (rval == QLA_SUCCESS) {
enable_82xx_npiv:
fw_major_version = ha->fw_major_version;
- rval = qla2x00_get_fw_version(vha,
- &ha->fw_major_version,
- &ha->fw_minor_version,
- &ha->fw_subminor_version,
- &ha->fw_attributes, &ha->fw_memory_size,
- ha->mpi_version, &ha->mpi_capabilities,
- ha->phy_version);
+ if (IS_QLA82XX(ha))
+ qla82xx_check_md_needed(vha);
+ else {
+ rval = qla2x00_get_fw_version(vha,
+ &ha->fw_major_version,
+ &ha->fw_minor_version,
+ &ha->fw_subminor_version,
+ &ha->fw_attributes,
+ &ha->fw_memory_size,
+ ha->mpi_version,
+ &ha->mpi_capabilities,
+ ha->phy_version);
+ }
if (rval != QLA_SUCCESS)
goto failed;
ha->flags.npiv_supported = 0;
@@ -1516,15 +1509,14 @@ enable_82xx_npiv:
&ha->fw_xcb_count, NULL, NULL,
&ha->max_npiv_vports, NULL);
- if (!fw_major_version && ql2xallocfwdump) {
- if (!IS_QLA82XX(ha))
- qla2x00_alloc_fw_dump(vha);
- }
+ if (!fw_major_version && ql2xallocfwdump
+ && !IS_QLA82XX(ha))
+ qla2x00_alloc_fw_dump(vha);
}
} else {
- DEBUG2(printk(KERN_INFO
- "scsi(%ld): ISP Firmware failed checksum.\n",
- vha->host_no));
+ ql_log(ql_log_fatal, vha, 0x00cd,
+ "ISP Firmware failed checksum.\n");
+ goto failed;
}
}
@@ -1549,7 +1541,7 @@ enable_82xx_npiv:
ha->flags.fac_supported = 1;
ha->fdt_block_size = size << 2;
} else {
- qla_printk(KERN_ERR, ha,
+ ql_log(ql_log_warn, vha, 0x00ce,
"Unsupported FAC firmware (%d.%02d.%02d).\n",
ha->fw_major_version, ha->fw_minor_version,
ha->fw_subminor_version);
@@ -1557,8 +1549,8 @@ enable_82xx_npiv:
}
failed:
if (rval) {
- DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
- vha->host_no));
+ ql_log(ql_log_fatal, vha, 0x00cf,
+ "Setup chip ****FAILED****.\n");
}
return (rval);
@@ -1608,10 +1600,11 @@ qla2x00_update_fw_options(scsi_qla_host_t *vha)
return;
/* Serial Link options. */
- DEBUG3(printk("scsi(%ld): Serial link options:\n",
- vha->host_no));
- DEBUG3(qla2x00_dump_buffer((uint8_t *)&ha->fw_seriallink_options,
- sizeof(ha->fw_seriallink_options)));
+ ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115,
+ "Serial link options.\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109,
+ (uint8_t *)&ha->fw_seriallink_options,
+ sizeof(ha->fw_seriallink_options));
ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
if (ha->fw_seriallink_options[3] & BIT_2) {
@@ -1688,7 +1681,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
le16_to_cpu(ha->fw_seriallink_options24[2]),
le16_to_cpu(ha->fw_seriallink_options24[3]));
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x0104,
"Unable to update Serial Link options (%x).\n", rval);
}
}
@@ -1746,8 +1739,9 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
icb->rid = __constant_cpu_to_le16(rid);
if (ha->flags.msix_enabled) {
msix = &ha->msix_entries[1];
- DEBUG2_17(printk(KERN_INFO
- "Registering vector 0x%x for base que\n", msix->entry));
+ ql_dbg(ql_dbg_init, vha, 0x00fd,
+ "Registering vector 0x%x for base que.\n",
+ msix->entry);
icb->msix = cpu_to_le16(msix->entry);
}
/* Use alternate PCI bus number */
@@ -1764,8 +1758,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
icb->firmware_options_2 &=
__constant_cpu_to_le32(~BIT_22);
ha->flags.disable_msix_handshake = 1;
- qla_printk(KERN_INFO, ha,
- "MSIX Handshake Disable Mode turned on\n");
+ ql_dbg(ql_dbg_init, vha, 0x00fe,
+ "MSIX Handshake Disable Mode turned on.\n");
} else {
icb->firmware_options_2 |=
__constant_cpu_to_le32(BIT_22);
@@ -1850,7 +1844,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
/* Update any ISP specific firmware options before initialization. */
ha->isp_ops->update_fw_options(vha);
- DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
if (ha->flags.npiv_supported) {
if (ha->operating_mode == LOOP)
@@ -1866,11 +1860,11 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
rval = qla2x00_init_firmware(vha, ha->init_cb_size);
if (rval) {
- DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
- vha->host_no));
+ ql_log(ql_log_fatal, vha, 0x00d2,
+ "Init Firmware **** FAILED ****.\n");
} else {
- DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_init, vha, 0x00d3,
+ "Init Firmware -- success.\n");
}
return (rval);
@@ -1913,10 +1907,8 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
/* Wait for ISP to finish LIP */
if (!vha->flags.init_done)
- qla_printk(KERN_INFO, ha, "Waiting for LIP to complete...\n");
-
- DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n",
- vha->host_no));
+ ql_log(ql_log_info, vha, 0x801e,
+ "Waiting for LIP to complete.\n");
do {
rval = qla2x00_get_firmware_state(vha, state);
@@ -1925,30 +1917,35 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
vha->device_flags &= ~DFLG_NO_CABLE;
}
if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
- DEBUG16(printk("scsi(%ld): fw_state=%x "
- "84xx=%x.\n", vha->host_no, state[0],
- state[2]));
+ ql_dbg(ql_dbg_taskm, vha, 0x801f,
+ "fw_state=%x 84xx=%x.\n", state[0],
+ state[2]);
if ((state[2] & FSTATE_LOGGED_IN) &&
(state[2] & FSTATE_WAITING_FOR_VERIFY)) {
- DEBUG16(printk("scsi(%ld): Sending "
- "verify iocb.\n", vha->host_no));
+ ql_dbg(ql_dbg_taskm, vha, 0x8028,
+ "Sending verify iocb.\n");
cs84xx_time = jiffies;
rval = qla84xx_init_chip(vha);
- if (rval != QLA_SUCCESS)
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn,
+ vha, 0x8026,
+ "Init chip failed.\n");
break;
+ }
/* Add time taken to initialize. */
cs84xx_time = jiffies - cs84xx_time;
wtime += cs84xx_time;
mtime += cs84xx_time;
- DEBUG16(printk("scsi(%ld): Increasing "
- "wait time by %ld. New time %ld\n",
- vha->host_no, cs84xx_time, wtime));
+ ql_dbg(ql_dbg_taskm, vha, 0x8025,
+ "Increasing wait time by %ld. "
+ "New time %ld.\n", cs84xx_time,
+ wtime);
}
} else if (state[0] == FSTATE_READY) {
- DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
- vha->host_no));
+ ql_dbg(ql_dbg_taskm, vha, 0x8037,
+ "F/W Ready - OK.\n");
qla2x00_get_retry_cnt(vha, &ha->retry_count,
&ha->login_timeout, &ha->r_a_tov);
@@ -1965,7 +1962,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
* other than Wait for Login.
*/
if (time_after_eq(jiffies, mtime)) {
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x8038,
"Cable is unplugged...\n");
vha->device_flags |= DFLG_NO_CABLE;
@@ -1985,17 +1982,17 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
/* Delay for a while */
msleep(500);
- DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
- vha->host_no, state[0], jiffies));
+ ql_dbg(ql_dbg_taskm, vha, 0x8039,
+ "fw_state=%x curr time=%lx.\n", state[0], jiffies);
} while (1);
- DEBUG(printk("scsi(%ld): fw_state=%x (%x, %x, %x, %x) curr time=%lx.\n",
- vha->host_no, state[0], state[1], state[2], state[3], state[4],
- jiffies));
+ ql_dbg(ql_dbg_taskm, vha, 0x803a,
+ "fw_state=%x (%x, %x, %x, %x) " "curr time=%lx.\n", state[0],
+ state[1], state[2], state[3], state[4], jiffies);
if (rval) {
- DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
- vha->host_no));
+ ql_log(ql_log_warn, vha, 0x803b,
+ "Firmware ready **** FAILED ****.\n");
}
return (rval);
@@ -2034,19 +2031,19 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
IS_QLA8XXX_TYPE(ha) ||
(rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
- DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
- __func__, vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2008,
+ "Loop is in a transition state.\n");
} else {
- qla_printk(KERN_WARNING, ha,
- "ERROR -- Unable to get host loop ID.\n");
+ ql_log(ql_log_warn, vha, 0x2009,
+ "Unable to get host loop ID.\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
}
return (rval);
}
if (topo == 4) {
- qla_printk(KERN_INFO, ha,
- "Cannot get topology - retrying.\n");
+ ql_log(ql_log_info, vha, 0x200a,
+ "Cannot get topology - retrying.\n");
return (QLA_FUNCTION_FAILED);
}
@@ -2059,31 +2056,27 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
switch (topo) {
case 0:
- DEBUG3(printk("scsi(%ld): HBA in NL topology.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x200b, "HBA in NL topology.\n");
ha->current_topology = ISP_CFG_NL;
strcpy(connect_type, "(Loop)");
break;
case 1:
- DEBUG3(printk("scsi(%ld): HBA in FL topology.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x200c, "HBA in FL topology.\n");
ha->switch_cap = sw_cap;
ha->current_topology = ISP_CFG_FL;
strcpy(connect_type, "(FL_Port)");
break;
case 2:
- DEBUG3(printk("scsi(%ld): HBA in N P2P topology.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x200d, "HBA in N P2P topology.\n");
ha->operating_mode = P2P;
ha->current_topology = ISP_CFG_N;
strcpy(connect_type, "(N_Port-to-N_Port)");
break;
case 3:
- DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x200e, "HBA in F P2P topology.\n");
ha->switch_cap = sw_cap;
ha->operating_mode = P2P;
ha->current_topology = ISP_CFG_F;
@@ -2091,9 +2084,8 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
break;
default:
- DEBUG3(printk("scsi(%ld): HBA in unknown topology %x. "
- "Using NL.\n",
- vha->host_no, topo));
+ ql_dbg(ql_dbg_disc, vha, 0x200f,
+ "HBA in unknown topology %x, using NL.\n", topo);
ha->current_topology = ISP_CFG_NL;
strcpy(connect_type, "(Loop)");
break;
@@ -2106,14 +2098,16 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
vha->d_id.b.al_pa = al_pa;
if (!vha->flags.init_done)
- qla_printk(KERN_INFO, ha,
- "Topology - %s, Host Loop address 0x%x\n",
+ ql_log(ql_log_info, vha, 0x2010,
+ "Topology - %s, Host Loop address 0x%x.\n",
connect_type, vha->loop_id);
if (rval) {
- DEBUG2_3(printk("scsi(%ld): FAILED.\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x2011,
+ "%s FAILED\n", __func__);
} else {
- DEBUG3(printk("scsi(%ld): exiting normally.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2012,
+ "%s success\n", __func__);
}
return(rval);
@@ -2227,18 +2221,22 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)
chksum += *ptr++;
- DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
- DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+ ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f,
+ "Contents of NVRAM.\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110,
+ (uint8_t *)nv, ha->nvram_size);
/* Bad NVRAM data, set defaults parameters. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
/* Reset NVRAM data. */
- qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
- "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
- nv->nvram_version);
- qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
- "invalid -- WWPN) defaults.\n");
+ ql_log(ql_log_warn, vha, 0x0064,
+ "Inconisistent NVRAM "
+ "detected: checksum=0x%x id=%c version=0x%x.\n",
+ chksum, nv->id[0], nv->nvram_version);
+ ql_log(ql_log_warn, vha, 0x0065,
+ "Falling back to "
+ "functioning (yet invalid -- WWPN) defaults.\n");
/*
* Set default initialization control block.
@@ -2382,8 +2380,13 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
/*
* Set host adapter parameters.
*/
+
+ /*
+ * BIT_7 in the host-parameters section allows for modification to
+ * internal driver logging.
+ */
if (nv->host_p[0] & BIT_7)
- ql2xextended_error_logging = 1;
+ ql2xextended_error_logging = 0x7fffffff;
ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
/* Always load RISC code on non ISP2[12]00 chips. */
if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
@@ -2488,10 +2491,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
- DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
- "delay (%d us).\n", vha->host_no, ha->zio_mode,
- ha->zio_timer * 100));
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x0068,
"ZIO mode %d enabled; timer delay (%d us).\n",
ha->zio_mode, ha->zio_timer * 100);
@@ -2502,8 +2502,8 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
}
if (rval) {
- DEBUG2_3(printk(KERN_WARNING
- "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x0069,
+ "NVRAM configuration failed.\n");
}
return (rval);
}
@@ -2574,15 +2574,15 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
if (test_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags)) {
rval = qla2x00_configure_hba(vha);
if (rval != QLA_SUCCESS) {
- DEBUG(printk("scsi(%ld): Unable to configure HBA.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2013,
+ "Unable to configure HBA.\n");
return (rval);
}
}
save_flags = flags = vha->dpc_flags;
- DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n",
- vha->host_no, flags));
+ ql_dbg(ql_dbg_disc, vha, 0x2014,
+ "Configure loop -- dpc flags = 0x%lx.\n", flags);
/*
* If we have both an RSCN and PORT UPDATE pending then handle them
@@ -2619,15 +2619,21 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
}
if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
- if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
+ ql_dbg(ql_dbg_disc, vha, 0x2015,
+ "Loop resync needed, failing.\n");
rval = QLA_FUNCTION_FAILED;
+ }
else
rval = qla2x00_configure_local_loop(vha);
}
if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
- if (LOOP_TRANSITION(vha))
+ if (LOOP_TRANSITION(vha)) {
+ ql_dbg(ql_dbg_disc, vha, 0x201e,
+ "Needs RSCN update and loop transition.\n");
rval = QLA_FUNCTION_FAILED;
+ }
else
rval = qla2x00_configure_fabric(vha);
}
@@ -2638,16 +2644,17 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
rval = QLA_FUNCTION_FAILED;
} else {
atomic_set(&vha->loop_state, LOOP_READY);
-
- DEBUG(printk("scsi(%ld): LOOP READY\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2069,
+ "LOOP READY.\n");
}
}
if (rval) {
- DEBUG2_3(printk("%s(%ld): *** FAILED ***\n",
- __func__, vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x206a,
+ "%s *** FAILED ***.\n", __func__);
} else {
- DEBUG3(printk("%s: exiting normally\n", __func__));
+ ql_dbg(ql_dbg_disc, vha, 0x206b,
+ "%s: exiting normally.\n", __func__);
}
/* Restore state if a resync event occurred during processing */
@@ -2695,8 +2702,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
new_fcport = NULL;
entries = MAX_FIBRE_DEVICES;
- DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", vha->host_no));
- DEBUG3(qla2x00_get_fcal_position_map(vha, NULL));
+ ql_dbg(ql_dbg_disc, vha, 0x2016,
+ "Getting FCAL position map.\n");
+ if (ql2xextended_error_logging & ql_dbg_disc)
+ qla2x00_get_fcal_position_map(vha, NULL);
/* Get list of logged in devices. */
memset(ha->gid_list, 0, GID_LIST_SIZE);
@@ -2705,14 +2714,17 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS)
goto cleanup_allocation;
- DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n",
- vha->host_no, entries));
- DEBUG3(qla2x00_dump_buffer((uint8_t *)ha->gid_list,
- entries * sizeof(struct gid_list_info)));
+ ql_dbg(ql_dbg_disc, vha, 0x2017,
+ "Entries in ID list (%d).\n", entries);
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
+ (uint8_t *)ha->gid_list,
+ entries * sizeof(struct gid_list_info));
/* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
+ ql_log(ql_log_warn, vha, 0x2018,
+ "Memory allocation failed for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
}
@@ -2726,9 +2738,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
fcport->port_type != FCT_BROADCAST &&
(fcport->flags & FCF_FABRIC_DEVICE) == 0) {
- DEBUG(printk("scsi(%ld): Marking port lost, "
- "loop_id=0x%04x\n",
- vha->host_no, fcport->loop_id));
+ ql_dbg(ql_dbg_disc, vha, 0x2019,
+ "Marking port lost loop_id=0x%04x.\n",
+ fcport->loop_id);
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
}
@@ -2769,12 +2781,12 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
new_fcport->vp_idx = vha->vp_idx;
rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
if (rval2 != QLA_SUCCESS) {
- DEBUG2(printk("scsi(%ld): Failed to retrieve fcport "
- "information -- get_port_database=%x, "
- "loop_id=0x%04x\n",
- vha->host_no, rval2, new_fcport->loop_id));
- DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
- vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x201a,
+ "Failed to retrieve fcport information "
+ "-- get_port_database=%x, loop_id=0x%04x.\n",
+ rval2, new_fcport->loop_id);
+ ql_dbg(ql_dbg_disc, vha, 0x201b,
+ "Scheduling resync.\n");
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
continue;
}
@@ -2810,6 +2822,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
fcport = new_fcport;
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
+ ql_log(ql_log_warn, vha, 0x201c,
+ "Failed to allocate memory for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
}
@@ -2828,8 +2842,8 @@ cleanup_allocation:
kfree(new_fcport);
if (rval != QLA_SUCCESS) {
- DEBUG2(printk("scsi(%ld): Configure local loop error exit: "
- "rval=%x\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x201d,
+ "Configure local loop error exit: rval=%x.\n", rval);
}
return (rval);
@@ -2858,27 +2872,27 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed,
mb);
if (rval != QLA_SUCCESS) {
- DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA "
- "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n",
- vha->host_no, fcport->port_name[0], fcport->port_name[1],
+ ql_dbg(ql_dbg_disc, vha, 0x2004,
+ "Unable to adjust iIDMA "
+ "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x "
+ "%04x.\n", fcport->port_name[0], fcport->port_name[1],
fcport->port_name[2], fcport->port_name[3],
fcport->port_name[4], fcport->port_name[5],
fcport->port_name[6], fcport->port_name[7], rval,
- fcport->fp_speed, mb[0], mb[1]));
+ fcport->fp_speed, mb[0], mb[1]);
} else {
link_speed = link_speeds[LS_UNKNOWN];
if (fcport->fp_speed < 5)
link_speed = link_speeds[fcport->fp_speed];
else if (fcport->fp_speed == 0x13)
link_speed = link_speeds[5];
- DEBUG2(qla_printk(KERN_INFO, ha,
- "iIDMA adjusted to %s GB/s on "
- "%02x%02x%02x%02x%02x%02x%02x%02x.\n",
- link_speed, fcport->port_name[0],
- fcport->port_name[1], fcport->port_name[2],
- fcport->port_name[3], fcport->port_name[4],
- fcport->port_name[5], fcport->port_name[6],
- fcport->port_name[7]));
+ ql_dbg(ql_dbg_disc, vha, 0x2005,
+ "iIDMA adjusted to %s GB/s "
+ "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed,
+ fcport->port_name[0], fcport->port_name[1],
+ fcport->port_name[2], fcport->port_name[3],
+ fcport->port_name[4], fcport->port_name[5],
+ fcport->port_name[6], fcport->port_name[7]);
}
}
@@ -2887,7 +2901,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
{
struct fc_rport_identifiers rport_ids;
struct fc_rport *rport;
- struct qla_hw_data *ha = vha->hw;
unsigned long flags;
qla2x00_rport_del(fcport);
@@ -2899,8 +2912,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
fcport->rport = rport = fc_remote_port_add(vha->host, 0, &rport_ids);
if (!rport) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate fc remote port!\n");
+ ql_log(ql_log_warn, vha, 0x2006,
+ "Unable to allocate fc remote port.\n");
return;
}
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
@@ -2975,8 +2988,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
loop_id = SNS_FL_PORT;
rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1);
if (rval != QLA_SUCCESS) {
- DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL "
- "Port\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x201f,
+ "MBX_GET_PORT_NAME failed, No FL Port.\n");
vha->device_flags &= ~SWITCH_FOUND;
return (QLA_SUCCESS);
@@ -3003,32 +3016,32 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff,
0xfc, mb, BIT_1 | BIT_0);
if (mb[0] != MBS_COMMAND_COMPLETE) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
- "mb[2]=%x mb[6]=%x mb[7]=%x\n", loop_id,
- mb[0], mb[1], mb[2], mb[6], mb[7]));
+ ql_dbg(ql_dbg_disc, vha, 0x2042,
+ "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x "
+ "mb[6]=%x mb[7]=%x.\n", loop_id, mb[0], mb[1],
+ mb[2], mb[6], mb[7]);
return (QLA_SUCCESS);
}
if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
if (qla2x00_rft_id(vha)) {
/* EMPTY */
- DEBUG2(printk("scsi(%ld): Register FC-4 "
- "TYPE failed.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2045,
+ "Register FC-4 TYPE failed.\n");
}
if (qla2x00_rff_id(vha)) {
/* EMPTY */
- DEBUG2(printk("scsi(%ld): Register FC-4 "
- "Features failed.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2049,
+ "Register FC-4 Features failed.\n");
}
if (qla2x00_rnn_id(vha)) {
/* EMPTY */
- DEBUG2(printk("scsi(%ld): Register Node Name "
- "failed.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x204f,
+ "Register Node Name failed.\n");
} else if (qla2x00_rsnn_nn(vha)) {
/* EMPTY */
- DEBUG2(printk("scsi(%ld): Register Symbolic "
- "Node Name failed.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2053,
+ "Register Symobilic Node Name failed.\n");
}
}
@@ -3132,8 +3145,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
}
if (rval) {
- DEBUG2(printk("scsi(%ld): Configure fabric error exit: "
- "rval=%d\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_disc, vha, 0x2068,
+ "Configure fabric error exit rval=%d.\n", rval);
}
return (rval);
@@ -3175,8 +3188,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_KERNEL);
if (!swl) {
/*EMPTY*/
- DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback "
- "on GA_NXT\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2054,
+ "GID_PT allocations failed, fallback on GA_NXT.\n");
} else {
if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) {
kfree(swl);
@@ -3201,6 +3214,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
/* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
+ ql_log(ql_log_warn, vha, 0x205e,
+ "Failed to allocate memory for fcport.\n");
kfree(swl);
return (QLA_MEMORY_ALLOC_FAILED);
}
@@ -3247,9 +3262,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
/* Send GA_NXT to the switch */
rval = qla2x00_ga_nxt(vha, new_fcport);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "SNS scan failed -- assuming zero-entry "
- "result...\n");
+ ql_log(ql_log_warn, vha, 0x2064,
+ "SNS scan failed -- assuming "
+ "zero-entry result.\n");
list_for_each_entry_safe(fcport, fcptemp,
new_fcports, list) {
list_del(&fcport->list);
@@ -3265,9 +3280,11 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
wrap.b24 = new_fcport->d_id.b24;
first_dev = 0;
} else if (new_fcport->d_id.b24 == wrap.b24) {
- DEBUG2(printk("scsi(%ld): device wrap (%02x%02x%02x)\n",
- vha->host_no, new_fcport->d_id.b.domain,
- new_fcport->d_id.b.area, new_fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_disc, vha, 0x2065,
+ "Device wrap (%02x%02x%02x).\n",
+ new_fcport->d_id.b.domain,
+ new_fcport->d_id.b.area,
+ new_fcport->d_id.b.al_pa);
break;
}
@@ -3372,6 +3389,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
nxt_d_id.b24 = new_fcport->d_id.b24;
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
+ ql_log(ql_log_warn, vha, 0x2066,
+ "Memory allocation failed for fcport.\n");
kfree(swl);
return (QLA_MEMORY_ALLOC_FAILED);
}
@@ -3501,10 +3520,10 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
d_id.b.area = MSB(LSW(rscn_entry));
d_id.b.al_pa = LSB(LSW(rscn_entry));
- DEBUG(printk("scsi(%ld): RSCN queue entry[%d] = "
- "[%02x/%02x%02x%02x].\n",
- vha->host_no, vha->rscn_out_ptr, format, d_id.b.domain,
- d_id.b.area, d_id.b.al_pa));
+ ql_dbg(ql_dbg_disc, vha, 0x2020,
+ "RSCN queue entry[%d] = [%02x/%02x%02x%02x].\n",
+ vha->rscn_out_ptr, format, d_id.b.domain, d_id.b.area,
+ d_id.b.al_pa);
vha->rscn_out_ptr++;
if (vha->rscn_out_ptr == MAX_RSCN_COUNT)
@@ -3520,17 +3539,17 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
if (rscn_entry != vha->rscn_queue[rscn_out_iter])
break;
- DEBUG(printk("scsi(%ld): Skipping duplicate RSCN queue "
- "entry found at [%d].\n", vha->host_no,
- rscn_out_iter));
+ ql_dbg(ql_dbg_disc, vha, 0x2021,
+ "Skipping duplicate RSCN queue entry found at "
+ "[%d].\n", rscn_out_iter);
vha->rscn_out_ptr = rscn_out_iter;
}
/* Queue overflow, set switch default case. */
if (vha->flags.rscn_queue_overflow) {
- DEBUG(printk("scsi(%ld): device_resync: rscn "
- "overflow.\n", vha->host_no));
+ ql_dbg(ql_dbg_disc, vha, 0x2022,
+ "device_resync: rscn overflow.\n");
format = 3;
vha->flags.rscn_queue_overflow = 0;
@@ -3659,10 +3678,11 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
tmp_loopid = 0;
for (;;) {
- DEBUG(printk("scsi(%ld): Trying Fabric Login w/loop id 0x%04x "
- "for port %02x%02x%02x.\n",
- vha->host_no, fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_disc, vha, 0x2000,
+ "Trying Fabric Login w/loop id 0x%04x for port "
+ "%02x%02x%02x.\n",
+ fcport->loop_id, fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa);
/* Login fcport on switch. */
ha->isp_ops->fabric_login(vha, fcport->loop_id,
@@ -3680,10 +3700,11 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
tmp_loopid = fcport->loop_id;
fcport->loop_id = mb[1];
- DEBUG(printk("Fabric Login: port in use - next "
- "loop id=0x%04x, port Id=%02x%02x%02x.\n",
+ ql_dbg(ql_dbg_disc, vha, 0x2001,
+ "Fabric Login: port in use - next loop "
+ "id=0x%04x, port id= %02x%02x%02x.\n",
fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa));
+ fcport->d_id.b.area, fcport->d_id.b.al_pa);
} else if (mb[0] == MBS_COMMAND_COMPLETE) {
/*
@@ -3744,11 +3765,11 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
/*
* unrecoverable / not handled error
*/
- DEBUG2(printk("%s(%ld): failed=%x port_id=%02x%02x%02x "
- "loop_id=%x jiffies=%lx.\n",
- __func__, vha->host_no, mb[0],
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, fcport->loop_id, jiffies));
+ ql_dbg(ql_dbg_disc, vha, 0x2002,
+ "Failed=%x port_id=%02x%02x%02x loop_id=%x "
+ "jiffies=%lx.\n", mb[0], fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa,
+ fcport->loop_id, jiffies);
*next_loopid = fcport->loop_id;
ha->isp_ops->fabric_logout(vha, fcport->loop_id,
@@ -3849,7 +3870,8 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
return (QLA_FUNCTION_FAILED);
if (rval)
- DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
+ ql_dbg(ql_dbg_disc, vha, 0x206c,
+ "%s *** FAILED ***.\n", __func__);
return (rval);
}
@@ -3926,8 +3948,8 @@ qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp;
- qla_printk(KERN_INFO, ha,
- "Performing ISP error recovery - ha= %p.\n", ha);
+ ql_dbg(ql_dbg_p3p, vha, 0xb002,
+ "Performing ISP error recovery - ha=%p.\n", ha);
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -3961,8 +3983,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
ha->qla_stats.total_isp_aborts++;
- qla_printk(KERN_INFO, ha,
- "Performing ISP error recovery - ha= %p.\n", ha);
+ ql_log(ql_log_info, vha, 0x00af,
+ "Performing ISP error recovery - ha=%p.\n", ha);
/* For ISP82XX, reset_chip is just disabling interrupts.
* Driver waits for the completion of the commands.
@@ -4013,6 +4035,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
/* Make sure for ISP 82XX IO DMA is complete */
if (IS_QLA82XX(ha)) {
qla82xx_chip_reset_cleanup(vha);
+ ql_log(ql_log_info, vha, 0x00b4,
+ "Done chip reset cleanup.\n");
/* Done waiting for pending commands.
* Reset the online flag.
@@ -4094,7 +4118,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
ha->fce_dma, ha->fce_bufs, ha->fce_mb,
&ha->fce_bufs);
if (rval) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x8033,
"Unable to reinitialize FCE "
"(%d).\n", rval);
ha->flags.fce_enabled = 0;
@@ -4106,7 +4130,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
rval = qla2x00_enable_eft_trace(vha,
ha->eft_dma, EFT_NUM_BUFFERS);
if (rval) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x8034,
"Unable to reinitialize EFT "
"(%d).\n", rval);
}
@@ -4115,9 +4139,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
vha->flags.online = 1;
if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
if (ha->isp_abort_cnt == 0) {
- qla_printk(KERN_WARNING, ha,
- "ISP error recovery failed - "
- "board disabled\n");
+ ql_log(ql_log_fatal, vha, 0x8035,
+ "ISP error recover failed - "
+ "board disabled.\n");
/*
* The next call disables the board
* completely.
@@ -4129,16 +4153,16 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
status = 0;
} else { /* schedule another ISP abort */
ha->isp_abort_cnt--;
- DEBUG(printk("qla%ld: ISP abort - "
- "retry remaining %d\n",
- vha->host_no, ha->isp_abort_cnt));
+ ql_dbg(ql_dbg_taskm, vha, 0x8020,
+ "ISP abort - retry remaining %d.\n",
+ ha->isp_abort_cnt);
status = 1;
}
} else {
ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
- DEBUG(printk("qla2x00(%ld): ISP error recovery "
- "- retrying (%d) more times\n",
- vha->host_no, ha->isp_abort_cnt));
+ ql_dbg(ql_dbg_taskm, vha, 0x8021,
+ "ISP error recovery - retrying (%d) "
+ "more times.\n", ha->isp_abort_cnt);
set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
status = 1;
}
@@ -4147,9 +4171,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
}
if (!status) {
- DEBUG(printk(KERN_INFO
- "qla2x00_abort_isp(%ld): succeeded.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
@@ -4166,8 +4188,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->vport_slock, flags);
} else {
- qla_printk(KERN_INFO, ha,
- "qla2x00_abort_isp: **** FAILED ****\n");
+ ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n");
}
return(status);
@@ -4208,8 +4229,8 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
status = qla2x00_fw_ready(vha);
if (!status) {
- DEBUG(printk("%s(): Start configure loop, "
- "status = %d\n", __func__, status));
+ ql_dbg(ql_dbg_taskm, vha, 0x8031,
+ "Start configure loop status = %d.\n", status);
/* Issue a marker after FW becomes ready. */
qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
@@ -4231,9 +4252,8 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
if ((vha->device_flags & DFLG_NO_CABLE))
status = 0;
- DEBUG(printk("%s(): Configure loop done, status = 0x%x\n",
- __func__,
- status));
+ ql_dbg(ql_dbg_taskm, vha, 0x8032,
+ "Configure loop done, status = 0x%x.\n", status);
}
return (status);
}
@@ -4253,13 +4273,13 @@ qla25xx_init_queues(struct qla_hw_data *ha)
rsp->options &= ~BIT_0;
ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS)
- DEBUG2_17(printk(KERN_WARNING
- "%s Rsp que:%d init failed\n", __func__,
- rsp->id));
+ ql_dbg(ql_dbg_init, base_vha, 0x00ff,
+ "%s Rsp que: %d init failed.\n",
+ __func__, rsp->id);
else
- DEBUG2_17(printk(KERN_INFO
- "%s Rsp que:%d inited\n", __func__,
- rsp->id));
+ ql_dbg(ql_dbg_init, base_vha, 0x0100,
+ "%s Rsp que: %d inited.\n",
+ __func__, rsp->id);
}
}
for (i = 1; i < ha->max_req_queues; i++) {
@@ -4269,13 +4289,13 @@ qla25xx_init_queues(struct qla_hw_data *ha)
req->options &= ~BIT_0;
ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS)
- DEBUG2_17(printk(KERN_WARNING
- "%s Req que:%d init failed\n", __func__,
- req->id));
+ ql_dbg(ql_dbg_init, base_vha, 0x0101,
+ "%s Req que: %d init failed.\n",
+ __func__, req->id);
else
- DEBUG2_17(printk(KERN_WARNING
- "%s Req que:%d inited\n", __func__,
- req->id));
+ ql_dbg(ql_dbg_init, base_vha, 0x0102,
+ "%s Req que: %d inited.\n",
+ __func__, req->id);
}
}
return ret;
@@ -4394,19 +4414,22 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
- DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
- DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+ ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
+ "Contents of NVRAM\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d,
+ (uint8_t *)nv, ha->nvram_size);
/* Bad NVRAM data, set defaults parameters. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
|| nv->id[3] != ' ' ||
nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
/* Reset NVRAM data. */
- qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
- "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
- le16_to_cpu(nv->nvram_version));
- qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
- "invalid -- WWPN) defaults.\n");
+ ql_log(ql_log_warn, vha, 0x006b,
+ "Inconisistent NVRAM detected: checksum=0x%x id=%c "
+ "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
+ ql_log(ql_log_warn, vha, 0x006c,
+ "Falling back to functioning (yet invalid -- WWPN) "
+ "defaults.\n");
/*
* Set default initialization control block.
@@ -4584,10 +4607,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
- DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
- "(%d us).\n", vha->host_no, ha->zio_mode,
- ha->zio_timer * 100));
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x006f,
"ZIO mode %d enabled; timer delay (%d us).\n",
ha->zio_mode, ha->zio_timer * 100);
@@ -4598,8 +4618,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
}
if (rval) {
- DEBUG2_3(printk(KERN_WARNING
- "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x0070,
+ "NVRAM configuration failed.\n");
}
return (rval);
}
@@ -4617,8 +4637,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
- qla_printk(KERN_INFO, ha,
- "FW: Loading from flash (%x)...\n", faddr);
+ ql_dbg(ql_dbg_init, vha, 0x008b,
+ "Loading firmware from flash (%x).\n", faddr);
rval = QLA_SUCCESS;
@@ -4634,11 +4654,12 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware image!\n");
- qla_printk(KERN_WARNING, ha,
- "Firmware data: %08x %08x %08x %08x!\n", dcode[0],
- dcode[1], dcode[2], dcode[3]);
+ ql_log(ql_log_fatal, vha, 0x008c,
+ "Unable to verify the integrity of flash firmware "
+ "image.\n");
+ ql_log(ql_log_fatal, vha, 0x008d,
+ "Firmware data: %08x %08x %08x %08x.\n",
+ dcode[0], dcode[1], dcode[2], dcode[3]);
return QLA_FUNCTION_FAILED;
}
@@ -4657,9 +4678,10 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
if (dlen > risc_size)
dlen = risc_size;
- DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
- "addr %x, number of dwords 0x%x, offset 0x%x.\n",
- vha->host_no, risc_addr, dlen, faddr));
+ ql_dbg(ql_dbg_init, vha, 0x008e,
+ "Loading risc segment@ risc addr %x "
+ "number of dwords 0x%x offset 0x%x.\n",
+ risc_addr, dlen, faddr);
qla24xx_read_flash_data(vha, dcode, faddr, dlen);
for (i = 0; i < dlen; i++)
@@ -4668,12 +4690,9 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
rval = qla2x00_load_ram(vha, req->dma, risc_addr,
dlen);
if (rval) {
- DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
- "segment %d of firmware\n", vha->host_no,
- fragment));
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Failed to load segment %d of "
- "firmware\n", fragment);
+ ql_log(ql_log_fatal, vha, 0x008f,
+ "Failed to load segment %d of firmware.\n",
+ fragment);
break;
}
@@ -4706,9 +4725,10 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
/* Load firmware blob. */
blob = qla2x00_request_firmware(vha);
if (!blob) {
- qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
- qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
- "from: " QLA_FW_URL ".\n");
+ ql_log(ql_log_info, vha, 0x0083,
+ "Fimware image unavailable.\n");
+ ql_log(ql_log_info, vha, 0x0084,
+ "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
return QLA_FUNCTION_FAILED;
}
@@ -4721,8 +4741,8 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
/* Validate firmware image by checking version. */
if (blob->fw->size < 8 * sizeof(uint16_t)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of firmware image (%Zd)!\n",
+ ql_log(ql_log_fatal, vha, 0x0085,
+ "Unable to verify integrity of firmware image (%Zd).\n",
blob->fw->size);
goto fail_fw_integrity;
}
@@ -4731,11 +4751,11 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
wcode[2] == 0 && wcode[3] == 0)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of firmware image!\n");
- qla_printk(KERN_WARNING, ha,
- "Firmware data: %04x %04x %04x %04x!\n", wcode[0],
- wcode[1], wcode[2], wcode[3]);
+ ql_log(ql_log_fatal, vha, 0x0086,
+ "Unable to verify integrity of firmware image.\n");
+ ql_log(ql_log_fatal, vha, 0x0087,
+ "Firmware data: %04x %04x %04x %04x.\n",
+ wcode[0], wcode[1], wcode[2], wcode[3]);
goto fail_fw_integrity;
}
@@ -4748,9 +4768,9 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
/* Validate firmware image size. */
fwclen += risc_size * sizeof(uint16_t);
if (blob->fw->size < fwclen) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_fatal, vha, 0x0088,
"Unable to verify integrity of firmware image "
- "(%Zd)!\n", blob->fw->size);
+ "(%Zd).\n", blob->fw->size);
goto fail_fw_integrity;
}
@@ -4759,10 +4779,9 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
wlen = (uint16_t)(ha->fw_transfer_size >> 1);
if (wlen > risc_size)
wlen = risc_size;
-
- DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
- "addr %x, number of words 0x%x.\n", vha->host_no,
- risc_addr, wlen));
+ ql_dbg(ql_dbg_init, vha, 0x0089,
+ "Loading risc segment@ risc addr %x number of "
+ "words 0x%x.\n", risc_addr, wlen);
for (i = 0; i < wlen; i++)
wcode[i] = swab16(fwcode[i]);
@@ -4770,12 +4789,9 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
rval = qla2x00_load_ram(vha, req->dma, risc_addr,
wlen);
if (rval) {
- DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
- "segment %d of firmware\n", vha->host_no,
- fragment));
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Failed to load segment %d of "
- "firmware\n", fragment);
+ ql_log(ql_log_fatal, vha, 0x008a,
+ "Failed to load segment %d of firmware.\n",
+ fragment);
break;
}
@@ -4811,15 +4827,17 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
/* Load firmware blob. */
blob = qla2x00_request_firmware(vha);
if (!blob) {
- qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
- qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
- "from: " QLA_FW_URL ".\n");
+ ql_log(ql_log_warn, vha, 0x0090,
+ "Fimware image unavailable.\n");
+ ql_log(ql_log_warn, vha, 0x0091,
+ "Firmware images can be retrieved from: "
+ QLA_FW_URL ".\n");
return QLA_FUNCTION_FAILED;
}
- qla_printk(KERN_INFO, ha,
- "FW: Loading via request-firmware...\n");
+ ql_log(ql_log_info, vha, 0x0092,
+ "Loading via request-firmware.\n");
rval = QLA_SUCCESS;
@@ -4831,8 +4849,8 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
/* Validate firmware image by checking version. */
if (blob->fw->size < 8 * sizeof(uint32_t)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of firmware image (%Zd)!\n",
+ ql_log(ql_log_fatal, vha, 0x0093,
+ "Unable to verify integrity of firmware image (%Zd).\n",
blob->fw->size);
goto fail_fw_integrity;
}
@@ -4842,11 +4860,12 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of firmware image!\n");
- qla_printk(KERN_WARNING, ha,
- "Firmware data: %08x %08x %08x %08x!\n", dcode[0],
- dcode[1], dcode[2], dcode[3]);
+ ql_log(ql_log_fatal, vha, 0x0094,
+ "Unable to verify integrity of firmware image (%Zd).\n",
+ blob->fw->size);
+ ql_log(ql_log_fatal, vha, 0x0095,
+ "Firmware data: %08x %08x %08x %08x.\n",
+ dcode[0], dcode[1], dcode[2], dcode[3]);
goto fail_fw_integrity;
}
@@ -4858,9 +4877,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
/* Validate firmware image size. */
fwclen += risc_size * sizeof(uint32_t);
if (blob->fw->size < fwclen) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_fatal, vha, 0x0096,
"Unable to verify integrity of firmware image "
- "(%Zd)!\n", blob->fw->size);
+ "(%Zd).\n", blob->fw->size);
goto fail_fw_integrity;
}
@@ -4871,9 +4890,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
if (dlen > risc_size)
dlen = risc_size;
- DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
- "addr %x, number of dwords 0x%x.\n", vha->host_no,
- risc_addr, dlen));
+ ql_dbg(ql_dbg_init, vha, 0x0097,
+ "Loading risc segment@ risc addr %x "
+ "number of dwords 0x%x.\n", risc_addr, dlen);
for (i = 0; i < dlen; i++)
dcode[i] = swab32(fwcode[i]);
@@ -4881,12 +4900,9 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
rval = qla2x00_load_ram(vha, req->dma, risc_addr,
dlen);
if (rval) {
- DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
- "segment %d of firmware\n", vha->host_no,
- fragment));
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Failed to load segment %d of "
- "firmware\n", fragment);
+ ql_log(ql_log_fatal, vha, 0x0098,
+ "Failed to load segment %d of firmware.\n",
+ fragment);
break;
}
@@ -4950,14 +4966,13 @@ try_blob_fw:
if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
return rval;
- qla_printk(KERN_ERR, ha,
- "FW: Attempting to fallback to golden firmware...\n");
+ ql_log(ql_log_info, vha, 0x0099,
+ "Attempting to fallback to golden firmware.\n");
rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
if (rval != QLA_SUCCESS)
return rval;
- qla_printk(KERN_ERR, ha,
- "FW: Please update operational firmware...\n");
+ ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n");
ha->flags.running_gold_fw = 1;
return rval;
@@ -4984,8 +4999,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
continue;
if (qla2x00_setup_chip(vha) != QLA_SUCCESS)
continue;
- qla_printk(KERN_INFO, ha,
- "Attempting retry of stop-firmware command...\n");
+ ql_log(ql_log_info, vha, 0x8015,
+ "Attempting retry of stop-firmware command.\n");
ret = qla2x00_stop_firmware(vha);
}
}
@@ -5020,10 +5035,10 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
/* Login to SNS first */
ha->isp_ops->fabric_login(vha, NPH_SNS, 0xff, 0xff, 0xfc, mb, BIT_1);
if (mb[0] != MBS_COMMAND_COMPLETE) {
- DEBUG15(qla_printk(KERN_INFO, ha,
- "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
- "mb[2]=%x mb[6]=%x mb[7]=%x\n", NPH_SNS,
- mb[0], mb[1], mb[2], mb[6], mb[7]));
+ ql_dbg(ql_dbg_init, vha, 0x0103,
+ "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x "
+ "mb[6]=%x mb[7]=%x.\n",
+ NPH_SNS, mb[0], mb[1], mb[2], mb[6], mb[7]);
return (QLA_FUNCTION_FAILED);
}
@@ -5143,19 +5158,23 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
- DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
- DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+ ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
+ "Contents of NVRAM:\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112,
+ (uint8_t *)nv, ha->nvram_size);
/* Bad NVRAM data, set defaults parameters. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
|| nv->id[3] != ' ' ||
nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
/* Reset NVRAM data. */
- qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
- "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
+ ql_log(ql_log_info, vha, 0x0073,
+ "Inconisistent NVRAM detected: checksum=0x%x id=%c "
+ "version=0x%x.\n", chksum, nv->id[0],
le16_to_cpu(nv->nvram_version));
- qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
- "invalid -- WWPN) defaults.\n");
+ ql_log(ql_log_info, vha, 0x0074,
+ "Falling back to functioning (yet invalid -- WWPN) "
+ "defaults.\n");
/*
* Set default initialization control block.
@@ -5347,12 +5366,10 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
- DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
- "(%d us).\n", vha->host_no, ha->zio_mode,
- ha->zio_timer * 100));
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x0075,
"ZIO mode %d enabled; timer delay (%d us).\n",
- ha->zio_mode, ha->zio_timer * 100);
+ ha->zio_mode,
+ ha->zio_timer * 100);
icb->firmware_options_2 |= cpu_to_le32(
(uint32_t)ha->zio_mode);
@@ -5361,8 +5378,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
}
if (rval) {
- DEBUG2_3(printk(KERN_WARNING
- "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x0076,
+ "NVRAM configuration failed.\n");
}
return (rval);
}
@@ -5385,9 +5402,8 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
status = qla2x00_fw_ready(vha);
if (!status) {
- qla_printk(KERN_INFO, ha,
- "%s(): Start configure loop, "
- "status = %d\n", __func__, status);
+ ql_log(ql_log_info, vha, 0x803c,
+ "Start configure loop, status =%d.\n", status);
/* Issue a marker after FW becomes ready. */
qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
@@ -5409,9 +5425,8 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
if ((vha->device_flags & DFLG_NO_CABLE))
status = 0;
- qla_printk(KERN_INFO, ha,
- "%s(): Configure loop done, status = 0x%x\n",
- __func__, status);
+ ql_log(ql_log_info, vha, 0x803d,
+ "Configure loop done, status = 0x%x.\n", status);
}
if (!status) {
@@ -5433,11 +5448,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
/* Update the firmware version */
- qla2x00_get_fw_version(vha, &ha->fw_major_version,
- &ha->fw_minor_version, &ha->fw_subminor_version,
- &ha->fw_attributes, &ha->fw_memory_size,
- ha->mpi_version, &ha->mpi_capabilities,
- ha->phy_version);
+ status = qla82xx_check_md_needed(vha);
if (ha->fce) {
ha->flags.fce_enabled = 1;
@@ -5447,9 +5458,9 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
ha->fce_dma, ha->fce_bufs, ha->fce_mb,
&ha->fce_bufs);
if (rval) {
- qla_printk(KERN_WARNING, ha,
- "Unable to reinitialize FCE "
- "(%d).\n", rval);
+ ql_log(ql_log_warn, vha, 0x803e,
+ "Unable to reinitialize FCE (%d).\n",
+ rval);
ha->flags.fce_enabled = 0;
}
}
@@ -5459,17 +5470,16 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
rval = qla2x00_enable_eft_trace(vha,
ha->eft_dma, EFT_NUM_BUFFERS);
if (rval) {
- qla_printk(KERN_WARNING, ha,
- "Unable to reinitialize EFT "
- "(%d).\n", rval);
+ ql_log(ql_log_warn, vha, 0x803f,
+ "Unable to reinitialize EFT (%d).\n",
+ rval);
}
}
}
if (!status) {
- DEBUG(printk(KERN_INFO
- "qla82xx_restart_isp(%ld): succeeded.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_taskm, vha, 0x8040,
+ "qla82xx_restart_isp succeeded.\n");
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
@@ -5486,8 +5496,8 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->vport_slock, flags);
} else {
- qla_printk(KERN_INFO, ha,
- "qla82xx_restart_isp: **** FAILED ****\n");
+ ql_log(ql_log_warn, vha, 0x8041,
+ "qla82xx_restart_isp **** FAILED ****.\n");
}
return status;
@@ -5637,9 +5647,8 @@ qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
if (ret == QLA_SUCCESS)
fcport->fcp_prio = priority;
else
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld): Unable to activate fcp priority, "
- " ret=0x%x\n", vha->host_no, ret));
+ ql_dbg(ql_dbg_user, vha, 0x704f,
+ "Unable to activate fcp priority, ret=0x%x.\n", ret);
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 4c8167e..9902834 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -94,11 +94,40 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
/* Don't print state transitions during initial allocation of fcport */
if (old_state && old_state != state) {
- DEBUG(qla_printk(KERN_WARNING, fcport->vha->hw,
- "scsi(%ld): FCPort state transitioned from %s to %s - "
- "portid=%02x%02x%02x.\n", fcport->vha->host_no,
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
+ "FCPort state transitioned from %s to %s - "
+ "portid=%02x%02x%02x.\n",
port_state_str[old_state], port_state_str[state],
fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ fcport->d_id.b.al_pa);
}
}
+
+static inline int
+qla2x00_hba_err_chk_enabled(srb_t *sp)
+{
+ /*
+ * Uncomment when corresponding SCSI changes are done.
+ *
+ if (!sp->cmd->prot_chk)
+ return 0;
+ *
+ */
+
+ switch (scsi_get_prot_op(sp->cmd)) {
+ case SCSI_PROT_READ_STRIP:
+ case SCSI_PROT_WRITE_INSERT:
+ if (ql2xenablehba_err_chk >= 1)
+ return 1;
+ break;
+ case SCSI_PROT_READ_PASS:
+ case SCSI_PROT_WRITE_PASS:
+ if (ql2xenablehba_err_chk >= 2)
+ return 1;
+ break;
+ case SCSI_PROT_READ_INSERT:
+ case SCSI_PROT_WRITE_STRIP:
+ return 1;
+ }
+ return 0;
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d2fb950..9fbe260 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -120,11 +120,10 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha)
* Returns a pointer to the continuation type 1 IOCB packet.
*/
static inline cont_a64_entry_t *
-qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha)
+qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req)
{
cont_a64_entry_t *cont_pkt;
- struct req_que *req = vha->req;
/* Adjust ring index. */
req->ring_index++;
if (req->ring_index == req->length) {
@@ -150,7 +149,8 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
/* We only support T10 DIF right now */
if (guard != SHOST_DIX_GUARD_CRC) {
- DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard));
+ ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3007,
+ "Unsupported guard: %d for cmd=%p.\n", guard, sp->cmd);
return 0;
}
@@ -291,7 +291,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
* Five DSDs are available in the Continuation
* Type 1 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type1_iocb(vha);
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req);
cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
avail_dsds = 5;
}
@@ -343,9 +343,10 @@ qla2x00_start_scsi(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL)
- != QLA_SUCCESS)
+ if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ QLA_SUCCESS) {
return (QLA_FUNCTION_FAILED);
+ }
vha->marker_needed = 0;
}
@@ -492,8 +493,8 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
mrk24 = NULL;
mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, 0);
if (mrk == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n",
- __func__, base_vha->host_no));
+ ql_log(ql_log_warn, base_vha, 0x3026,
+ "Failed to allocate Marker IOCB.\n");
return (QLA_FUNCTION_FAILED);
}
@@ -549,9 +550,10 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req)
device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id);
struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
- DEBUG5(printk("%s(): IOCB data:\n", __func__));
- DEBUG5(qla2x00_dump_buffer(
- (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE));
+ ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x302d,
+ "IOCB data:\n");
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e,
+ (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE);
/* Adjust ring index. */
req->ring_index++;
@@ -606,7 +608,7 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req)
* Returns the number of IOCB entries needed to store @dsds.
*/
inline uint16_t
-qla24xx_calc_iocbs(uint16_t dsds)
+qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)
{
uint16_t iocbs;
@@ -616,8 +618,6 @@ qla24xx_calc_iocbs(uint16_t dsds)
if ((dsds - 1) % 5)
iocbs++;
}
- DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n",
- __func__, iocbs));
return iocbs;
}
@@ -685,7 +685,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
* Five DSDs are available in the Continuation
* Type 1 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type1_iocb(vha);
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req);
cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
avail_dsds = 5;
}
@@ -710,19 +710,28 @@ struct fw_dif_context {
*
*/
static inline void
-qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
+qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt,
unsigned int protcnt)
{
- struct sd_dif_tuple *spt;
- unsigned char op = scsi_get_prot_op(cmd);
+ struct scsi_cmnd *cmd = sp->cmd;
+ scsi_qla_host_t *vha = shost_priv(cmd->device->host);
switch (scsi_get_prot_type(cmd)) {
- /* For TYPE 0 protection: no checking */
case SCSI_PROT_DIF_TYPE0:
- pkt->ref_tag_mask[0] = 0x00;
- pkt->ref_tag_mask[1] = 0x00;
- pkt->ref_tag_mask[2] = 0x00;
- pkt->ref_tag_mask[3] = 0x00;
+ /*
+ * No check for ql2xenablehba_err_chk, as it would be an
+ * I/O error if hba tag generation is not done.
+ */
+ pkt->ref_tag = cpu_to_le32((uint32_t)
+ (0xffffffff & scsi_get_lba(cmd)));
+
+ if (!qla2x00_hba_err_chk_enabled(sp))
+ break;
+
+ pkt->ref_tag_mask[0] = 0xff;
+ pkt->ref_tag_mask[1] = 0xff;
+ pkt->ref_tag_mask[2] = 0xff;
+ pkt->ref_tag_mask[3] = 0xff;
break;
/*
@@ -730,20 +739,16 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
* match LBA in CDB + N
*/
case SCSI_PROT_DIF_TYPE2:
- if (!ql2xenablehba_err_chk)
- break;
-
- if (scsi_prot_sg_count(cmd)) {
- spt = page_address(sg_page(scsi_prot_sglist(cmd))) +
- scsi_prot_sglist(cmd)[0].offset;
- pkt->app_tag = swab32(spt->app_tag);
- pkt->app_tag_mask[0] = 0xff;
- pkt->app_tag_mask[1] = 0xff;
- }
+ pkt->app_tag = __constant_cpu_to_le16(0);
+ pkt->app_tag_mask[0] = 0x0;
+ pkt->app_tag_mask[1] = 0x0;
pkt->ref_tag = cpu_to_le32((uint32_t)
(0xffffffff & scsi_get_lba(cmd)));
+ if (!qla2x00_hba_err_chk_enabled(sp))
+ break;
+
/* enable ALL bytes of the ref tag */
pkt->ref_tag_mask[0] = 0xff;
pkt->ref_tag_mask[1] = 0xff;
@@ -763,26 +768,15 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
* 16 bit app tag.
*/
case SCSI_PROT_DIF_TYPE1:
- if (!ql2xenablehba_err_chk)
+ pkt->ref_tag = cpu_to_le32((uint32_t)
+ (0xffffffff & scsi_get_lba(cmd)));
+ pkt->app_tag = __constant_cpu_to_le16(0);
+ pkt->app_tag_mask[0] = 0x0;
+ pkt->app_tag_mask[1] = 0x0;
+
+ if (!qla2x00_hba_err_chk_enabled(sp))
break;
- if (protcnt && (op == SCSI_PROT_WRITE_STRIP ||
- op == SCSI_PROT_WRITE_PASS)) {
- spt = page_address(sg_page(scsi_prot_sglist(cmd))) +
- scsi_prot_sglist(cmd)[0].offset;
- DEBUG18(printk(KERN_DEBUG
- "%s(): LBA from user %p, lba = 0x%x\n",
- __func__, spt, (int)spt->ref_tag));
- pkt->ref_tag = swab32(spt->ref_tag);
- pkt->app_tag_mask[0] = 0x0;
- pkt->app_tag_mask[1] = 0x0;
- } else {
- pkt->ref_tag = cpu_to_le32((uint32_t)
- (0xffffffff & scsi_get_lba(cmd)));
- pkt->app_tag = __constant_cpu_to_le16(0);
- pkt->app_tag_mask[0] = 0x0;
- pkt->app_tag_mask[1] = 0x0;
- }
/* enable ALL bytes of the ref tag */
pkt->ref_tag_mask[0] = 0xff;
pkt->ref_tag_mask[1] = 0xff;
@@ -791,15 +785,169 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
break;
}
- DEBUG18(printk(KERN_DEBUG
- "%s(): Setting protection Tags: (BIG) ref tag = 0x%x,"
- " app tag = 0x%x, prot SG count %d , cmd lba 0x%x,"
- " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt,
- (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd)));
+ ql_dbg(ql_dbg_io, vha, 0x3009,
+ "Setting protection Tags: (BIG) ref tag = 0x%x, app tag = 0x%x, "
+ "prot SG count %d, cmd lba 0x%x, prot_type=%u cmd=%p.\n",
+ pkt->ref_tag, pkt->app_tag, protcnt, (int)scsi_get_lba(cmd),
+ scsi_get_prot_type(cmd), cmd);
}
+struct qla2_sgx {
+ dma_addr_t dma_addr; /* OUT */
+ uint32_t dma_len; /* OUT */
+
+ uint32_t tot_bytes; /* IN */
+ struct scatterlist *cur_sg; /* IN */
+
+ /* for book keeping, bzero on initial invocation */
+ uint32_t bytes_consumed;
+ uint32_t num_bytes;
+ uint32_t tot_partial;
+
+ /* for debugging */
+ uint32_t num_sg;
+ srb_t *sp;
+};
static int
+qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx,
+ uint32_t *partial)
+{
+ struct scatterlist *sg;
+ uint32_t cumulative_partial, sg_len;
+ dma_addr_t sg_dma_addr;
+
+ if (sgx->num_bytes == sgx->tot_bytes)
+ return 0;
+
+ sg = sgx->cur_sg;
+ cumulative_partial = sgx->tot_partial;
+
+ sg_dma_addr = sg_dma_address(sg);
+ sg_len = sg_dma_len(sg);
+
+ sgx->dma_addr = sg_dma_addr + sgx->bytes_consumed;
+
+ if ((cumulative_partial + (sg_len - sgx->bytes_consumed)) >= blk_sz) {
+ sgx->dma_len = (blk_sz - cumulative_partial);
+ sgx->tot_partial = 0;
+ sgx->num_bytes += blk_sz;
+ *partial = 0;
+ } else {
+ sgx->dma_len = sg_len - sgx->bytes_consumed;
+ sgx->tot_partial += sgx->dma_len;
+ *partial = 1;
+ }
+
+ sgx->bytes_consumed += sgx->dma_len;
+
+ if (sg_len == sgx->bytes_consumed) {
+ sg = sg_next(sg);
+ sgx->num_sg++;
+ sgx->cur_sg = sg;
+ sgx->bytes_consumed = 0;
+ }
+
+ return 1;
+}
+
+static int
+qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
+ uint32_t *dsd, uint16_t tot_dsds)
+{
+ void *next_dsd;
+ uint8_t avail_dsds = 0;
+ uint32_t dsd_list_len;
+ struct dsd_dma *dsd_ptr;
+ struct scatterlist *sg_prot;
+ uint32_t *cur_dsd = dsd;
+ uint16_t used_dsds = tot_dsds;
+
+ uint32_t prot_int;
+ uint32_t partial;
+ struct qla2_sgx sgx;
+ dma_addr_t sle_dma;
+ uint32_t sle_dma_len, tot_prot_dma_len = 0;
+ struct scsi_cmnd *cmd = sp->cmd;
+
+ prot_int = cmd->device->sector_size;
+
+ memset(&sgx, 0, sizeof(struct qla2_sgx));
+ sgx.tot_bytes = scsi_bufflen(sp->cmd);
+ sgx.cur_sg = scsi_sglist(sp->cmd);
+ sgx.sp = sp;
+
+ sg_prot = scsi_prot_sglist(sp->cmd);
+
+ while (qla24xx_get_one_block_sg(prot_int, &sgx, &partial)) {
+
+ sle_dma = sgx.dma_addr;
+ sle_dma_len = sgx.dma_len;
+alloc_and_fill:
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
+ QLA_DSDS_PER_IOCB : used_dsds;
+ dsd_list_len = (avail_dsds + 1) * 12;
+ used_dsds -= avail_dsds;
+
+ /* allocate tracking DS */
+ dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
+ if (!dsd_ptr)
+ return 1;
+
+ /* allocate new list */
+ dsd_ptr->dsd_addr = next_dsd =
+ dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
+ &dsd_ptr->dsd_list_dma);
+
+ if (!next_dsd) {
+ /*
+ * Need to cleanup only this dsd_ptr, rest
+ * will be done by sp_free_dma()
+ */
+ kfree(dsd_ptr);
+ return 1;
+ }
+
+ list_add_tail(&dsd_ptr->list,
+ &((struct crc_context *)sp->ctx)->dsd_list);
+
+ sp->flags |= SRB_CRC_CTX_DSD_VALID;
+
+ /* add new list to cmd iocb or last list */
+ *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
+ *cur_dsd++ = dsd_list_len;
+ cur_dsd = (uint32_t *)next_dsd;
+ }
+ *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(sle_dma_len);
+ avail_dsds--;
+
+ if (partial == 0) {
+ /* Got a full protection interval */
+ sle_dma = sg_dma_address(sg_prot) + tot_prot_dma_len;
+ sle_dma_len = 8;
+
+ tot_prot_dma_len += sle_dma_len;
+ if (tot_prot_dma_len == sg_dma_len(sg_prot)) {
+ tot_prot_dma_len = 0;
+ sg_prot = sg_next(sg_prot);
+ }
+
+ partial = 1; /* So as to not re-enter this block */
+ goto alloc_and_fill;
+ }
+ }
+ /* Null termination */
+ *cur_dsd++ = 0;
+ *cur_dsd++ = 0;
+ *cur_dsd++ = 0;
+ return 0;
+}
+static int
qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
uint16_t tot_dsds)
{
@@ -811,6 +959,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
uint32_t *cur_dsd = dsd;
int i;
uint16_t used_dsds = tot_dsds;
+ scsi_qla_host_t *vha = shost_priv(sp->cmd->device->host);
uint8_t *cp;
@@ -855,9 +1004,10 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
cur_dsd = (uint32_t *)next_dsd;
}
sle_dma = sg_dma_address(sg);
- DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x,"
- " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma),
- MSD(sle_dma), sg_dma_len(sg)));
+ ql_dbg(ql_dbg_io, vha, 0x300a,
+ "sg entry %d - addr=0x%x 0x%x, " "len=%d for cmd=%p.\n",
+ cur_dsd, i, LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg),
+ sp->cmd);
*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
@@ -865,8 +1015,8 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
cp = page_address(sg_page(sg)) + sg->offset;
- DEBUG18(printk("%s(): User Data buffer= %p:\n",
- __func__ , cp));
+ ql_dbg(ql_dbg_io, vha, 0x300b,
+ "User data buffer=%p for cmd=%p.\n", cp, sp->cmd);
}
}
/* Null termination */
@@ -890,7 +1040,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
struct scsi_cmnd *cmd;
uint32_t *cur_dsd = dsd;
uint16_t used_dsds = tot_dsds;
-
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
uint8_t *cp;
@@ -937,10 +1087,11 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
}
sle_dma = sg_dma_address(sg);
if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
- DEBUG18(printk(KERN_DEBUG
- "%s(): %p, sg entry %d - addr =0x%x"
- "0x%x, len =%d\n", __func__ , cur_dsd, i,
- LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg)));
+ ql_dbg(ql_dbg_io, vha, 0x3027,
+ "%s(): %p, sg_entry %d - "
+ "addr=0x%x0x%x, len=%d.\n",
+ __func__, cur_dsd, i,
+ LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg));
}
*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
@@ -948,8 +1099,9 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
cp = page_address(sg_page(sg)) + sg->offset;
- DEBUG18(printk("%s(): Protection Data buffer = %p:\n",
- __func__ , cp));
+ ql_dbg(ql_dbg_io, vha, 0x3028,
+ "%s(): Protection Data buffer = %p.\n", __func__,
+ cp);
}
avail_dsds--;
}
@@ -977,7 +1129,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
struct scsi_cmnd *cmd;
struct scatterlist *cur_seg;
int sgc;
- uint32_t total_bytes;
+ uint32_t total_bytes = 0;
uint32_t data_bytes;
uint32_t dif_bytes;
uint8_t bundling = 1;
@@ -998,22 +1150,16 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
*((uint32_t *)(&cmd_pkt->entry_type)) =
__constant_cpu_to_le32(COMMAND_TYPE_CRC_2);
+ vha = sp->fcport->vha;
+ ha = vha->hw;
+
/* No data transfer */
data_bytes = scsi_bufflen(cmd);
if (!data_bytes || cmd->sc_data_direction == DMA_NONE) {
- DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n",
- __func__, data_bytes));
cmd_pkt->byte_count = __constant_cpu_to_le32(0);
return QLA_SUCCESS;
}
- vha = sp->fcport->vha;
- ha = vha->hw;
-
- DEBUG18(printk(KERN_DEBUG
- "%s(%ld): Executing cmd sp %p, prot_op=%u.\n", __func__,
- vha->host_no, sp, scsi_get_prot_op(sp->cmd)));
-
cmd_pkt->vp_index = sp->fcport->vp_idx;
/* Set transfer direction */
@@ -1025,8 +1171,10 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
__constant_cpu_to_le16(CF_READ_DATA);
}
- tot_prot_dsds = scsi_prot_sg_count(cmd);
- if (!tot_prot_dsds)
+ if ((scsi_get_prot_op(sp->cmd) == SCSI_PROT_READ_INSERT) ||
+ (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_STRIP) ||
+ (scsi_get_prot_op(sp->cmd) == SCSI_PROT_READ_STRIP) ||
+ (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_INSERT))
bundling = 0;
/* Allocate CRC context from global pool */
@@ -1049,7 +1197,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list);
- qla24xx_set_t10dif_tags(cmd, (struct fw_dif_context *)
+ qla24xx_set_t10dif_tags(sp, (struct fw_dif_context *)
&crc_ctx_pkt->ref_tag, tot_prot_dsds);
cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
@@ -1058,8 +1206,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
/* Determine SCSI command length -- align to 4 byte boundary */
if (cmd->cmd_len > 16) {
- DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n",
- __func__));
additional_fcpcdb_len = cmd->cmd_len - 16;
if ((cmd->cmd_len % 4) != 0) {
/* SCSI cmd > 16 bytes must be multiple of 4 */
@@ -1080,7 +1226,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
fcp_cmnd->additional_cdb_len |= 2;
int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun);
- host_to_fcp_swap((uint8_t *)&fcp_cmnd->lun, sizeof(fcp_cmnd->lun));
memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
@@ -1110,21 +1255,29 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
- DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data"
- "entries %d, data bytes %d, Protection entries %d\n",
- __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds),
- data_bytes, tot_prot_dsds));
-
/* Compute dif len and adjust data len to incude protection */
- total_bytes = data_bytes;
dif_bytes = 0;
blk_size = cmd->device->sector_size;
- if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
- dif_bytes = (data_bytes / blk_size) * 8;
- total_bytes += dif_bytes;
+ dif_bytes = (data_bytes / blk_size) * 8;
+
+ switch (scsi_get_prot_op(sp->cmd)) {
+ case SCSI_PROT_READ_INSERT:
+ case SCSI_PROT_WRITE_STRIP:
+ total_bytes = data_bytes;
+ data_bytes += dif_bytes;
+ break;
+
+ case SCSI_PROT_READ_STRIP:
+ case SCSI_PROT_WRITE_INSERT:
+ case SCSI_PROT_READ_PASS:
+ case SCSI_PROT_WRITE_PASS:
+ total_bytes = data_bytes + dif_bytes;
+ break;
+ default:
+ BUG();
}
- if (!ql2xenablehba_err_chk)
+ if (!qla2x00_hba_err_chk_enabled(sp))
fw_prot_opts |= 0x10; /* Disable Guard tag checking */
if (!bundling) {
@@ -1152,14 +1305,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
additional_fcpcdb_len);
*fcp_dl = htonl(total_bytes);
- DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes"
- " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__,
- vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes,
- crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size));
-
if (!data_bytes || cmd->sc_data_direction == DMA_NONE) {
- DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n",
- __func__, data_bytes));
cmd_pkt->byte_count = __constant_cpu_to_le32(0);
return QLA_SUCCESS;
}
@@ -1167,7 +1313,12 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
cmd_pkt->control_flags |=
__constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE);
- if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd,
+
+ if (!bundling && tot_prot_dsds) {
+ if (qla24xx_walk_and_build_sglist_no_difb(ha, sp,
+ cur_dsd, tot_dsds))
+ goto crc_queuing_error;
+ } else if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd,
(tot_dsds - tot_prot_dsds)))
goto crc_queuing_error;
@@ -1184,8 +1335,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
return QLA_SUCCESS;
crc_queuing_error:
- DEBUG18(qla_printk(KERN_INFO, ha,
- "CMD sent FAILED crc_q error:sp = %p\n", sp));
/* Cleanup will be performed by the caller */
return QLA_FUNCTION_FAILED;
@@ -1227,8 +1376,8 @@ qla24xx_start_scsi(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL)
- != QLA_SUCCESS)
+ if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ QLA_SUCCESS)
return QLA_FUNCTION_FAILED;
vha->marker_needed = 0;
}
@@ -1245,8 +1394,9 @@ qla24xx_start_scsi(srb_t *sp)
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS)
+ if (index == MAX_OUTSTANDING_COMMANDS) {
goto queuing_error;
+ }
/* Map the sg table so we have an accurate count of sg entries needed */
if (scsi_sg_count(cmd)) {
@@ -1258,8 +1408,7 @@ qla24xx_start_scsi(srb_t *sp)
nseg = 0;
tot_dsds = nseg;
-
- req_cnt = qla24xx_calc_iocbs(tot_dsds);
+ req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
@@ -1329,7 +1478,6 @@ qla24xx_start_scsi(srb_t *sp)
/* Specify response queue number where completion should happen */
cmd_pkt->entry_status = (uint8_t) rsp->id;
wmb();
-
/* Adjust ring index. */
req->ring_index++;
if (req->ring_index == req->length) {
@@ -1438,6 +1586,22 @@ qla24xx_dif_start_scsi(srb_t *sp)
goto queuing_error;
else
sp->flags |= SRB_DMA_VALID;
+
+ if ((scsi_get_prot_op(cmd) == SCSI_PROT_READ_INSERT) ||
+ (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_STRIP)) {
+ struct qla2_sgx sgx;
+ uint32_t partial;
+
+ memset(&sgx, 0, sizeof(struct qla2_sgx));
+ sgx.tot_bytes = scsi_bufflen(cmd);
+ sgx.cur_sg = scsi_sglist(cmd);
+ sgx.sp = sp;
+
+ nseg = 0;
+ while (qla24xx_get_one_block_sg(
+ cmd->device->sector_size, &sgx, &partial))
+ nseg++;
+ }
} else
nseg = 0;
@@ -1452,6 +1616,11 @@ qla24xx_dif_start_scsi(srb_t *sp)
goto queuing_error;
else
sp->flags |= SRB_CRC_PROT_DMA_VALID;
+
+ if ((scsi_get_prot_op(cmd) == SCSI_PROT_READ_INSERT) ||
+ (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_STRIP)) {
+ nseg = scsi_bufflen(cmd) / cmd->device->sector_size;
+ }
} else {
nseg = 0;
}
@@ -1478,6 +1647,7 @@ qla24xx_dif_start_scsi(srb_t *sp)
/* Build header part of command packet (excluding the OPCODE). */
req->current_outstanding_cmd = handle;
req->outstanding_cmds[handle] = sp;
+ sp->handle = handle;
sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
req->cnt -= req_cnt;
@@ -1541,9 +1711,6 @@ queuing_error:
/* Cleanup will be performed by the caller (queuecommand) */
spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
- DEBUG18(qla_printk(KERN_INFO, ha,
- "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd)));
return QLA_FUNCTION_FAILED;
}
@@ -1588,8 +1755,11 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS)
+ if (index == MAX_OUTSTANDING_COMMANDS) {
+ ql_log(ql_log_warn, vha, 0x700b,
+ "No room on oustanding cmd array.\n");
goto queuing_error;
+ }
/* Prep command array. */
req->current_outstanding_cmd = handle;
@@ -1906,7 +2076,8 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
* Five DSDs are available in the Cont.
* Type 1 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type1_iocb(vha);
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha,
+ vha->hw->req_q_map[0]);
cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
avail_dsds = 5;
cont_iocb_prsnt = 1;
@@ -1932,6 +2103,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
int index;
uint16_t tot_dsds;
scsi_qla_host_t *vha = sp->fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
int loop_iterartion = 0;
int cont_iocb_prsnt = 0;
@@ -1977,7 +2149,8 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
* Five DSDs are available in the Cont.
* Type 1 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type1_iocb(vha);
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha,
+ ha->req_q_map[0]);
cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
avail_dsds = 5;
cont_iocb_prsnt = 1;
@@ -2006,8 +2179,11 @@ qla2x00_start_sp(srb_t *sp)
rval = QLA_FUNCTION_FAILED;
spin_lock_irqsave(&ha->hardware_lock, flags);
pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
- if (!pkt)
+ if (!pkt) {
+ ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
+ "qla2x00_alloc_iocbs failed.\n");
goto done;
+ }
rval = QLA_SUCCESS;
switch (ctx->type) {
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index e0fa877..7b91b29 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -45,7 +45,7 @@ qla2100_intr_handler(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return (IRQ_NONE);
}
@@ -63,7 +63,7 @@ qla2100_intr_handler(int irq, void *dev_id)
/*
* Issue a "HARD" reset in order for the RISC interrupt
- * bit to be cleared. Schedule a big hammmer to get
+ * bit to be cleared. Schedule a big hammer to get
* out of the RISC PAUSED state.
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
@@ -91,9 +91,9 @@ qla2100_intr_handler(int irq, void *dev_id)
qla2x00_async_event(vha, rsp, mb);
} else {
/*EMPTY*/
- DEBUG2(printk("scsi(%ld): Unrecognized "
- "interrupt type (%d).\n",
- vha->host_no, mb[0]));
+ ql_dbg(ql_dbg_async, vha, 0x5025,
+ "Unrecognized interrupt type (%d).\n",
+ mb[0]);
}
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
@@ -142,7 +142,7 @@ qla2300_intr_handler(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return (IRQ_NONE);
}
@@ -160,16 +160,18 @@ qla2300_intr_handler(int irq, void *dev_id)
hccr = RD_REG_WORD(&reg->hccr);
if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
- qla_printk(KERN_INFO, ha, "Parity error -- "
- "HCCR=%x, Dumping firmware!\n", hccr);
+ ql_log(ql_log_warn, vha, 0x5026,
+ "Parity error -- HCCR=%x, Dumping "
+ "firmware.\n", hccr);
else
- qla_printk(KERN_INFO, ha, "RISC paused -- "
- "HCCR=%x, Dumping firmware!\n", hccr);
+ ql_log(ql_log_warn, vha, 0x5027,
+ "RISC paused -- HCCR=%x, Dumping "
+ "firmware.\n", hccr);
/*
* Issue a "HARD" reset in order for the RISC
* interrupt bit to be cleared. Schedule a big
- * hammmer to get out of the RISC PAUSED state.
+ * hammer to get out of the RISC PAUSED state.
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
RD_REG_WORD(&reg->hccr);
@@ -213,9 +215,8 @@ qla2300_intr_handler(int irq, void *dev_id)
qla2x00_async_event(vha, rsp, mb);
break;
default:
- DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
- "(%d).\n",
- vha->host_no, stat & 0xff));
+ ql_dbg(ql_dbg_async, vha, 0x5028,
+ "Unrecognized interrupt type (%d).\n", stat & 0xff);
break;
}
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
@@ -262,11 +263,11 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
}
if (ha->mcp) {
- DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
- __func__, vha->host_no, ha->mcp->mb[0]));
+ ql_dbg(ql_dbg_async, vha, 0x5000,
+ "Got mbx completion. cmd=%x.\n", ha->mcp->mb[0]);
} else {
- DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
- __func__, vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x5001,
+ "MBX pointer ERROR.\n");
}
}
@@ -285,22 +286,24 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
mb[cnt] = RD_REG_WORD(wptr);
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
- "%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
- event[aen & 0xff],
- mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));
+ ql_dbg(ql_dbg_async, vha, 0x5021,
+ "Inter-Driver Commucation %s -- "
+ "%04x %04x %04x %04x %04x %04x %04x.\n",
+ event[aen & 0xff], mb[0], mb[1], mb[2], mb[3],
+ mb[4], mb[5], mb[6]);
/* Acknowledgement needed? [Notify && non-zero timeout]. */
timeout = (descr >> 8) & 0xf;
if (aen != MBA_IDC_NOTIFY || !timeout)
return;
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
- "ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));
+ ql_dbg(ql_dbg_async, vha, 0x5022,
+ "Inter-Driver Commucation %s -- ACK timeout=%d.\n",
+ vha->host_no, event[aen & 0xff], timeout);
rval = qla2x00_post_idc_ack_work(vha, mb);
if (rval != QLA_SUCCESS)
- qla_printk(KERN_WARNING, vha->hw,
+ ql_log(ql_log_warn, vha, 0x5023,
"IDC failed to post ACK.\n");
}
@@ -393,15 +396,15 @@ skip_rio:
break;
case MBA_RESET: /* Reset */
- DEBUG2(printk("scsi(%ld): Asynchronous RESET.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x5002,
+ "Asynchronous RESET.\n");
set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
break;
case MBA_SYSTEM_ERR: /* System Error */
mbx = IS_QLA81XX(ha) ? RD_REG_WORD(&reg24->mailbox7) : 0;
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_warn, vha, 0x5003,
"ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh "
"mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
@@ -409,7 +412,7 @@ skip_rio:
if (IS_FWI2_CAPABLE(ha)) {
if (mb[1] == 0 && mb[2] == 0) {
- qla_printk(KERN_ERR, ha,
+ ql_log(ql_log_fatal, vha, 0x5004,
"Unrecoverable Hardware Error: adapter "
"marked OFFLINE!\n");
vha->flags.online = 0;
@@ -422,7 +425,7 @@ skip_rio:
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
}
} else if (mb[1] == 0) {
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_fatal, vha, 0x5005,
"Unrecoverable Hardware Error: adapter marked "
"OFFLINE!\n");
vha->flags.online = 0;
@@ -431,31 +434,27 @@ skip_rio:
break;
case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
- DEBUG2(printk("scsi(%ld): ISP Request Transfer Error (%x).\n",
- vha->host_no, mb[1]));
- qla_printk(KERN_WARNING, ha,
- "ISP Request Transfer Error (%x).\n", mb[1]);
+ ql_log(ql_log_warn, vha, 0x5006,
+ "ISP Request Transfer Error (%x).\n", mb[1]);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
- DEBUG2(printk("scsi(%ld): ISP Response Transfer Error.\n",
- vha->host_no));
- qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
+ ql_log(ql_log_warn, vha, 0x5007,
+ "ISP Response Transfer Error.\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
- DEBUG2(printk("scsi(%ld): Asynchronous WAKEUP_THRES.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x5008,
+ "Asynchronous WAKEUP_THRES.\n");
break;
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
- DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", vha->host_no,
- mb[1]));
- qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]);
+ ql_log(ql_log_info, vha, 0x5009,
+ "LIP occurred (%x).\n", mb[1]);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -488,10 +487,8 @@ skip_rio:
ha->link_data_rate = mb[1];
}
- DEBUG2(printk("scsi(%ld): Asynchronous LOOP UP (%s Gbps).\n",
- vha->host_no, link_speed));
- qla_printk(KERN_INFO, ha, "LOOP UP detected (%s Gbps).\n",
- link_speed);
+ ql_log(ql_log_info, vha, 0x500a,
+ "LOOP UP detected (%s Gbps).\n", link_speed);
vha->flags.management_server_logged_in = 0;
qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
@@ -500,12 +497,9 @@ skip_rio:
case MBA_LOOP_DOWN: /* Loop Down Event */
mbx = IS_QLA81XX(ha) ? RD_REG_WORD(&reg24->mailbox4) : 0;
mbx = IS_QLA82XX(ha) ? RD_REG_WORD(&reg82->mailbox_out[4]) : mbx;
- DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
- "(%x %x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3],
- mbx));
- qla_printk(KERN_INFO, ha,
- "LOOP DOWN detected (%x %x %x %x).\n", mb[1], mb[2], mb[3],
- mbx);
+ ql_log(ql_log_info, vha, 0x500b,
+ "LOOP DOWN detected (%x %x %x %x).\n",
+ mb[1], mb[2], mb[3], mbx);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -525,9 +519,7 @@ skip_rio:
break;
case MBA_LIP_RESET: /* LIP reset occurred */
- DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",
- vha->host_no, mb[1]));
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x500c,
"LIP reset occurred (%x).\n", mb[1]);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -554,14 +546,15 @@ skip_rio:
break;
if (IS_QLA8XXX_TYPE(ha)) {
- DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
- "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x500d,
+ "DCBX Completed -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
if (ha->notify_dcbx_comp)
complete(&ha->dcbx_comp);
} else
- DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
- "received.\n", vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x500e,
+ "Asynchronous P2P MODE received.\n");
/*
* Until there's a transition from loop down to loop up, treat
@@ -594,10 +587,7 @@ skip_rio:
if (IS_QLA2100(ha))
break;
- DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection "
- "received.\n",
- vha->host_no));
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_info, vha, 0x500f,
"Configuration change detected: value=%x.\n", mb[1]);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -640,11 +630,9 @@ skip_rio:
/* Global event -- port logout or port unavailable. */
if (mb[1] == 0xffff && mb[2] == 0x7) {
- DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
- vha->host_no));
- DEBUG(printk(KERN_INFO
- "scsi(%ld): Port unavailable %04x %04x %04x.\n",
- vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5010,
+ "Port unavailable %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -674,17 +662,15 @@ skip_rio:
atomic_set(&vha->loop_down_timer, 0);
if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
atomic_read(&vha->loop_state) != LOOP_DEAD) {
- DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE "
- "ignored %04x/%04x/%04x.\n", vha->host_no, mb[1],
- mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5011,
+ "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
+ mb[1], mb[2], mb[3]);
break;
}
- DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
- vha->host_no));
- DEBUG(printk(KERN_INFO
- "scsi(%ld): Port database changed %04x %04x %04x.\n",
- vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5012,
+ "Port database changed %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
/*
* Mark all devices as missing so we will login again.
@@ -707,20 +693,17 @@ skip_rio:
if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
break;
- DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
- vha->host_no));
- DEBUG(printk(KERN_INFO
- "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n",
- vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5013,
+ "RSCN database changed -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
| vha->d_id.b.al_pa;
if (rscn_entry == host_pid) {
- DEBUG(printk(KERN_INFO
- "scsi(%ld): Ignoring RSCN update to local host "
- "port ID (%06x)\n",
- vha->host_no, host_pid));
+ ql_dbg(ql_dbg_async, vha, 0x5014,
+ "Ignoring RSCN update to local host "
+ "port ID (%06x).\n", host_pid);
break;
}
@@ -746,8 +729,8 @@ skip_rio:
/* case MBA_RIO_RESPONSE: */
case MBA_ZIO_RESPONSE:
- DEBUG3(printk("scsi(%ld): [R|Z]IO update completion.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x5015,
+ "[R|Z]IO update completion.\n");
if (IS_FWI2_CAPABLE(ha))
qla24xx_process_response_queue(vha, rsp);
@@ -756,61 +739,68 @@ skip_rio:
break;
case MBA_DISCARD_RND_FRAME:
- DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
- "%04x.\n", vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5016,
+ "Discard RND Frame -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
break;
case MBA_TRACE_NOTIFICATION:
- DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
- vha->host_no, mb[1], mb[2]));
+ ql_dbg(ql_dbg_async, vha, 0x5017,
+ "Trace Notification -- %04x %04x.\n", mb[1], mb[2]);
break;
case MBA_ISP84XX_ALERT:
- DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
- "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5018,
+ "ISP84XX Alert Notification -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
switch (mb[1]) {
case A84_PANIC_RECOVERY:
- qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
- "%04x %04x\n", mb[2], mb[3]);
+ ql_log(ql_log_info, vha, 0x5019,
+ "Alert 84XX: panic recovery %04x %04x.\n",
+ mb[2], mb[3]);
break;
case A84_OP_LOGIN_COMPLETE:
ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
- DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
- "firmware version %x\n", ha->cs84xx->op_fw_version));
+ ql_log(ql_log_info, vha, 0x501a,
+ "Alert 84XX: firmware version %x.\n",
+ ha->cs84xx->op_fw_version);
break;
case A84_DIAG_LOGIN_COMPLETE:
ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
- DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
- "diagnostic firmware version %x\n",
- ha->cs84xx->diag_fw_version));
+ ql_log(ql_log_info, vha, 0x501b,
+ "Alert 84XX: diagnostic firmware version %x.\n",
+ ha->cs84xx->diag_fw_version);
break;
case A84_GOLD_LOGIN_COMPLETE:
ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
ha->cs84xx->fw_update = 1;
- DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
- "firmware version %x\n",
- ha->cs84xx->gold_fw_version));
+ ql_log(ql_log_info, vha, 0x501c,
+ "Alert 84XX: gold firmware version %x.\n",
+ ha->cs84xx->gold_fw_version);
break;
default:
- qla_printk(KERN_ERR, ha,
- "Alert 84xx: Invalid Alert %04x %04x %04x\n",
+ ql_log(ql_log_warn, vha, 0x501d,
+ "Alert 84xx: Invalid Alert %04x %04x %04x.\n",
mb[1], mb[2], mb[3]);
}
spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
break;
case MBA_DCBX_START:
- DEBUG2(printk("scsi(%ld): DCBX Started -- %04x %04x %04x\n",
- vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x501e,
+ "DCBX Started -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
break;
case MBA_DCBX_PARAM_UPDATE:
- DEBUG2(printk("scsi(%ld): DCBX Parameters Updated -- "
- "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x501f,
+ "DCBX Parameters Updated -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
break;
case MBA_FCF_CONF_ERR:
- DEBUG2(printk("scsi(%ld): FCF Configuration Error -- "
- "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ ql_dbg(ql_dbg_async, vha, 0x5020,
+ "FCF Configuration Error -- %04x %04x %04x.\n",
+ mb[1], mb[2], mb[3]);
break;
case MBA_IDC_COMPLETE:
case MBA_IDC_NOTIFY:
@@ -837,10 +827,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
/* Validate handle. */
if (index >= MAX_OUTSTANDING_COMMANDS) {
- DEBUG2(printk("scsi(%ld): Invalid SCSI completion handle %d.\n",
- vha->host_no, index));
- qla_printk(KERN_WARNING, ha,
- "Invalid SCSI completion handle %d.\n", index);
+ ql_log(ql_log_warn, vha, 0x3014,
+ "Invalid SCSI command index (%x).\n", index);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -858,10 +846,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
sp->cmd->result = DID_OK << 16;
qla2x00_sp_compl(ha, sp);
} else {
- DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion"
- " handle(0x%x)\n", vha->host_no, req->id, index));
- qla_printk(KERN_WARNING, ha,
- "Invalid ISP SCSI completion handle\n");
+ ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -881,8 +866,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
index = LSW(pkt->handle);
if (index >= MAX_OUTSTANDING_COMMANDS) {
- qla_printk(KERN_WARNING, ha,
- "%s: Invalid completion handle (%x).\n", func, index);
+ ql_log(ql_log_warn, vha, 0x5031,
+ "Invalid command index (%x).\n", index);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
@@ -891,15 +876,13 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
}
sp = req->outstanding_cmds[index];
if (!sp) {
- qla_printk(KERN_WARNING, ha,
- "%s: Invalid completion handle (%x) -- timed-out.\n", func,
- index);
+ ql_log(ql_log_warn, vha, 0x5032,
+ "Invalid completion handle (%x) -- timed-out.\n", index);
return sp;
}
if (sp->handle != index) {
- qla_printk(KERN_WARNING, ha,
- "%s: SRB handle (%x) mismatch %x.\n", func, sp->handle,
- index);
+ ql_log(ql_log_warn, vha, 0x5033,
+ "SRB handle (%x) mismatch %x.\n", sp->handle, index);
return NULL;
}
@@ -936,17 +919,17 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
QLA_LOGIO_LOGIN_RETRIED : 0;
if (mbx->entry_status) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error entry - portid=%02x%02x%02x "
+ ql_dbg(ql_dbg_async, vha, 0x5043,
+ "Async-%s error entry - portid=%02x%02x%02x "
"entry-status=%x status=%x state-flag=%x "
"status-flags=%x.\n",
- fcport->vha->host_no, sp->handle, type,
- fcport->d_id.b.domain, fcport->d_id.b.area,
+ type, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, mbx->entry_status,
le16_to_cpu(mbx->status), le16_to_cpu(mbx->state_flags),
- le16_to_cpu(mbx->status_flags)));
+ le16_to_cpu(mbx->status_flags));
- DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx)));
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5057,
+ (uint8_t *)mbx, sizeof(*mbx));
goto logio_done;
}
@@ -956,12 +939,10 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
status = 0;
if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
- DEBUG2(printk(KERN_DEBUG
- "scsi(%ld:%x): Async-%s complete - portid=%02x%02x%02x "
- "mbx1=%x.\n",
- fcport->vha->host_no, sp->handle, type,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, le16_to_cpu(mbx->mb1)));
+ ql_dbg(ql_dbg_async, vha, 0x5045,
+ "Async-%s complete - portid=%02x%02x%02x mbx1=%x.\n",
+ type, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, le16_to_cpu(mbx->mb1));
data[0] = MBS_COMMAND_COMPLETE;
if (ctx->type == SRB_LOGIN_CMD) {
@@ -986,14 +967,14 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
break;
}
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s failed - portid=%02x%02x%02x status=%x "
+ ql_log(ql_log_warn, vha, 0x5046,
+ "Async-%s failed - portid=%02x%02x%02x status=%x "
"mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
- fcport->vha->host_no, sp->handle, type, fcport->d_id.b.domain,
+ type, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa, status,
le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
- le16_to_cpu(mbx->mb7)));
+ le16_to_cpu(mbx->mb7));
logio_done:
lio->done(sp);
@@ -1024,9 +1005,8 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
type = "ct pass-through";
break;
default:
- qla_printk(KERN_WARNING, ha,
- "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
- sp_bsg->type);
+ ql_log(ql_log_warn, vha, 0x5047,
+ "Unrecognized SRB: (%p) type=%d.\n", sp, sp_bsg->type);
return;
}
@@ -1044,20 +1024,20 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
bsg_job->reply->reply_payload_rcv_len =
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "scsi(%ld): CT pass-through-%s error "
+ ql_log(ql_log_warn, vha, 0x5048,
+ "CT pass-through-%s error "
"comp_status-status=0x%x total_byte = 0x%x.\n",
- vha->host_no, type, comp_status,
- bsg_job->reply->reply_payload_rcv_len));
+ type, comp_status,
+ bsg_job->reply->reply_payload_rcv_len);
} else {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "scsi(%ld): CT pass-through-%s error "
- "comp_status-status=0x%x.\n",
- vha->host_no, type, comp_status));
+ ql_log(ql_log_warn, vha, 0x5049,
+ "CT pass-through-%s error "
+ "comp_status-status=0x%x.\n", type, comp_status);
bsg_job->reply->result = DID_ERROR << 16;
bsg_job->reply->reply_payload_rcv_len = 0;
}
- DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5058,
+ (uint8_t *)pkt, sizeof(*pkt));
} else {
bsg_job->reply->result = DID_OK << 16;
bsg_job->reply->reply_payload_rcv_len =
@@ -1109,9 +1089,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
type = "ct pass-through";
break;
default:
- qla_printk(KERN_WARNING, ha,
- "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
- sp_bsg->type);
+ ql_log(ql_log_warn, vha, 0x503e,
+ "Unrecognized SRB: (%p) type=%d.\n", sp, sp_bsg->type);
return;
}
@@ -1131,27 +1110,31 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
bsg_job->reply->reply_payload_rcv_len =
le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count);
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x "
+ ql_log(ql_log_info, vha, 0x503f,
+ "ELS-CT pass-through-%s error comp_status-status=0x%x "
"error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n",
- vha->host_no, sp->handle, type, comp_status, fw_status[1], fw_status[2],
- le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count)));
+ type, comp_status, fw_status[1], fw_status[2],
+ le16_to_cpu(((struct els_sts_entry_24xx *)
+ pkt)->total_byte_count));
fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
}
else {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x "
+ ql_log(ql_log_info, vha, 0x5040,
+ "ELS-CT pass-through-%s error comp_status-status=0x%x "
"error subcode 1=0x%x error subcode 2=0x%x.\n",
- vha->host_no, sp->handle, type, comp_status,
- le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1),
- le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2)));
+ type, comp_status,
+ le16_to_cpu(((struct els_sts_entry_24xx *)
+ pkt)->error_subcode_1),
+ le16_to_cpu(((struct els_sts_entry_24xx *)
+ pkt)->error_subcode_2));
bsg_job->reply->result = DID_ERROR << 16;
bsg_job->reply->reply_payload_rcv_len = 0;
fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
}
- DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5056,
+ (uint8_t *)pkt, sizeof(*pkt));
}
else {
bsg_job->reply->result = DID_OK << 16;
@@ -1200,25 +1183,24 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
QLA_LOGIO_LOGIN_RETRIED : 0;
if (logio->entry_status) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error entry - "
+ ql_log(ql_log_warn, vha, 0x5034,
+ "Async-%s error entry - "
"portid=%02x%02x%02x entry-status=%x.\n",
- fcport->vha->host_no, sp->handle, type,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, logio->entry_status));
- DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio)));
+ type, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, logio->entry_status);
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5059,
+ (uint8_t *)logio, sizeof(*logio));
goto logio_done;
}
if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
- DEBUG2(printk(KERN_DEBUG
- "scsi(%ld:%x): Async-%s complete - portid=%02x%02x%02x "
+ ql_dbg(ql_dbg_async, vha, 0x5036,
+ "Async-%s complete - portid=%02x%02x%02x "
"iop0=%x.\n",
- fcport->vha->host_no, sp->handle, type,
- fcport->d_id.b.domain, fcport->d_id.b.area,
+ type, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa,
- le32_to_cpu(logio->io_parameter[0])));
+ le32_to_cpu(logio->io_parameter[0]));
data[0] = MBS_COMMAND_COMPLETE;
if (ctx->type != SRB_LOGIN_CMD)
@@ -1255,14 +1237,14 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
break;
}
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s failed - portid=%02x%02x%02x comp=%x "
+ ql_dbg(ql_dbg_async, vha, 0x5037,
+ "Async-%s failed - portid=%02x%02x%02x comp=%x "
"iop0=%x iop1=%x.\n",
- fcport->vha->host_no, sp->handle, type, fcport->d_id.b.domain,
+ type, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
le16_to_cpu(logio->comp_status),
le32_to_cpu(logio->io_parameter[0]),
- le32_to_cpu(logio->io_parameter[1])));
+ le32_to_cpu(logio->io_parameter[1]));
logio_done:
lio->done(sp);
@@ -1291,38 +1273,34 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
fcport = sp->fcport;
if (sts->entry_status) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error - entry-status(%x).\n",
- fcport->vha->host_no, sp->handle, type,
- sts->entry_status));
+ ql_log(ql_log_warn, vha, 0x5038,
+ "Async-%s error - entry-status(%x).\n",
+ type, sts->entry_status);
} else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error - completion status(%x).\n",
- fcport->vha->host_no, sp->handle, type,
- sts->comp_status));
+ ql_log(ql_log_warn, vha, 0x5039,
+ "Async-%s error - completion status(%x).\n",
+ type, sts->comp_status);
} else if (!(le16_to_cpu(sts->scsi_status) &
SS_RESPONSE_INFO_LEN_VALID)) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error - no response info(%x).\n",
- fcport->vha->host_no, sp->handle, type,
- sts->scsi_status));
+ ql_log(ql_log_warn, vha, 0x503a,
+ "Async-%s error - no response info(%x).\n",
+ type, sts->scsi_status);
} else if (le32_to_cpu(sts->rsp_data_len) < 4) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error - not enough response(%d).\n",
- fcport->vha->host_no, sp->handle, type,
- sts->rsp_data_len));
+ ql_log(ql_log_warn, vha, 0x503b,
+ "Async-%s error - not enough response(%d).\n",
+ type, sts->rsp_data_len);
} else if (sts->data[3]) {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld:%x): Async-%s error - response(%x).\n",
- fcport->vha->host_no, sp->handle, type,
- sts->data[3]));
+ ql_log(ql_log_warn, vha, 0x503c,
+ "Async-%s error - response(%x).\n",
+ type, sts->data[3]);
} else {
error = 0;
}
if (error) {
iocb->u.tmf.data = error;
- DEBUG2(qla2x00_dump_buffer((uint8_t *)sts, sizeof(*sts)));
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
+ (uint8_t *)sts, sizeof(*sts));
}
iocb->done(sp);
@@ -1359,8 +1337,8 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
}
if (pkt->entry_status != 0) {
- DEBUG3(printk(KERN_INFO
- "scsi(%ld): Process error entry.\n", vha->host_no));
+ ql_log(ql_log_warn, vha, 0x5035,
+ "Process error entry.\n");
qla2x00_error_entry(vha, rsp, pkt);
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -1398,10 +1376,10 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
break;
default:
/* Type Not Supported. */
- DEBUG4(printk(KERN_WARNING
- "scsi(%ld): Received unknown response pkt type %x "
+ ql_log(ql_log_warn, vha, 0x504a,
+ "Received unknown response pkt type %x "
"entry status=%x.\n",
- vha->host_no, pkt->entry_type, pkt->entry_status));
+ pkt->entry_type, pkt->entry_status);
break;
}
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -1417,6 +1395,7 @@ static inline void
qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
uint32_t sense_len, struct rsp_que *rsp)
{
+ struct scsi_qla_host *vha = sp->fcport->vha;
struct scsi_cmnd *cp = sp->cmd;
if (sense_len >= SCSI_SENSE_BUFFERSIZE)
@@ -1434,11 +1413,13 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
if (sp->request_sense_length != 0)
rsp->status_srb = sp;
- DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
- "cmd=%p\n", __func__, sp->fcport->vha->host_no,
- cp->device->channel, cp->device->id, cp->device->lun, cp));
+ ql_dbg(ql_dbg_io, vha, 0x301c,
+ "Check condition Sense data, scsi(%ld:%d:%d:%d) cmd=%p.\n",
+ sp->fcport->vha->host_no, cp->device->channel, cp->device->id,
+ cp->device->lun, cp);
if (sense_len)
- DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
+ cp->sense_buffer, sense_len);
}
struct scsi_dif_tuple {
@@ -1453,34 +1434,94 @@ struct scsi_dif_tuple {
* ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
* to indicate to the kernel that the HBA detected error.
*/
-static inline void
+static inline int
qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
{
+ struct scsi_qla_host *vha = sp->fcport->vha;
struct scsi_cmnd *cmd = sp->cmd;
- struct scsi_dif_tuple *ep =
- (struct scsi_dif_tuple *)&sts24->data[20];
- struct scsi_dif_tuple *ap =
- (struct scsi_dif_tuple *)&sts24->data[12];
+ uint8_t *ap = &sts24->data[12];
+ uint8_t *ep = &sts24->data[20];
uint32_t e_ref_tag, a_ref_tag;
uint16_t e_app_tag, a_app_tag;
uint16_t e_guard, a_guard;
- e_ref_tag = be32_to_cpu(ep->ref_tag);
- a_ref_tag = be32_to_cpu(ap->ref_tag);
- e_app_tag = be16_to_cpu(ep->app_tag);
- a_app_tag = be16_to_cpu(ap->app_tag);
- e_guard = be16_to_cpu(ep->guard);
- a_guard = be16_to_cpu(ap->guard);
-
- DEBUG18(printk(KERN_DEBUG
- "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24));
-
- DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
+ /*
+ * swab32 of the "data" field in the beginning of qla2x00_status_entry()
+ * would make guard field appear at offset 2
+ */
+ a_guard = le16_to_cpu(*(uint16_t *)(ap + 2));
+ a_app_tag = le16_to_cpu(*(uint16_t *)(ap + 0));
+ a_ref_tag = le32_to_cpu(*(uint32_t *)(ap + 4));
+ e_guard = le16_to_cpu(*(uint16_t *)(ep + 2));
+ e_app_tag = le16_to_cpu(*(uint16_t *)(ep + 0));
+ e_ref_tag = le32_to_cpu(*(uint32_t *)(ep + 4));
+
+ ql_dbg(ql_dbg_io, vha, 0x3023,
+ "iocb(s) %p Returned STATUS.\n", sts24);
+
+ ql_dbg(ql_dbg_io, vha, 0x3024,
+ "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
" tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
- " tag=0x%x, act guard=0x%x, exp guard=0x%x\n",
+ " tag=0x%x, act guard=0x%x, exp guard=0x%x.\n",
cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
- a_app_tag, e_app_tag, a_guard, e_guard));
+ a_app_tag, e_app_tag, a_guard, e_guard);
+ /*
+ * Ignore sector if:
+ * For type 3: ref & app tag is all 'f's
+ * For type 0,1,2: app tag is all 'f's
+ */
+ if ((a_app_tag == 0xffff) &&
+ ((scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3) ||
+ (a_ref_tag == 0xffffffff))) {
+ uint32_t blocks_done, resid;
+ sector_t lba_s = scsi_get_lba(cmd);
+
+ /* 2TB boundary case covered automatically with this */
+ blocks_done = e_ref_tag - (uint32_t)lba_s + 1;
+
+ resid = scsi_bufflen(cmd) - (blocks_done *
+ cmd->device->sector_size);
+
+ scsi_set_resid(cmd, resid);
+ cmd->result = DID_OK << 16;
+
+ /* Update protection tag */
+ if (scsi_prot_sg_count(cmd)) {
+ uint32_t i, j = 0, k = 0, num_ent;
+ struct scatterlist *sg;
+ struct sd_dif_tuple *spt;
+
+ /* Patch the corresponding protection tags */
+ scsi_for_each_prot_sg(cmd, sg,
+ scsi_prot_sg_count(cmd), i) {
+ num_ent = sg_dma_len(sg) / 8;
+ if (k + num_ent < blocks_done) {
+ k += num_ent;
+ continue;
+ }
+ j = blocks_done - k - 1;
+ k = blocks_done;
+ break;
+ }
+
+ if (k != blocks_done) {
+ qla_printk(KERN_WARNING, sp->fcport->vha->hw,
+ "unexpected tag values tag:lba=%x:%llx)\n",
+ e_ref_tag, (unsigned long long)lba_s);
+ return 1;
+ }
+
+ spt = page_address(sg_page(sg)) + sg->offset;
+ spt += j;
+
+ spt->app_tag = 0xffff;
+ if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE3)
+ spt->ref_tag = 0xffffffff;
+ }
+
+ return 0;
+ }
/* check guard */
if (e_guard != a_guard) {
@@ -1489,28 +1530,30 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
- return;
+ return 1;
}
- /* check appl tag */
- if (e_app_tag != a_app_tag) {
+ /* check ref tag */
+ if (e_ref_tag != a_ref_tag) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
- 0x10, 0x2);
+ 0x10, 0x3);
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
- return;
+ return 1;
}
- /* check ref tag */
- if (e_ref_tag != a_ref_tag) {
+ /* check appl tag */
+ if (e_app_tag != a_app_tag) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
- 0x10, 0x3);
+ 0x10, 0x2);
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
- return;
+ return 1;
}
+
+ return 1;
}
/**
@@ -1568,9 +1611,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
sp = NULL;
if (sp == NULL) {
- qla_printk(KERN_WARNING, ha,
- "scsi(%ld): Invalid status handle (0x%x).\n", vha->host_no,
- sts->handle);
+ ql_log(ql_log_warn, vha, 0x3017,
+ "Invalid status handle (0x%x).\n", sts->handle);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -1581,9 +1623,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
}
cp = sp->cmd;
if (cp == NULL) {
- qla_printk(KERN_WARNING, ha,
- "scsi(%ld): Command already returned (0x%x/%p).\n",
- vha->host_no, sts->handle, sp);
+ ql_log(ql_log_warn, vha, 0x3018,
+ "Command already returned (0x%x/%p).\n",
+ sts->handle, sp);
return;
}
@@ -1628,10 +1670,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
par_sense_len -= rsp_info_len;
}
if (rsp_info_len > 3 && rsp_info[3]) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): FCP I/O protocol failure "
- "(0x%x/0x%x).\n", vha->host_no, cp->device->id,
- cp->device->lun, rsp_info_len, rsp_info[3]));
+ ql_log(ql_log_warn, vha, 0x3019,
+ "FCP I/O protocol failure (0x%x/0x%x).\n",
+ rsp_info_len, rsp_info[3]);
cp->result = DID_BUS_BUSY << 16;
goto out;
@@ -1660,11 +1701,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (!lscsi_status &&
((unsigned)(scsi_bufflen(cp) - resid) <
cp->underflow)) {
- qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): Mid-layer underflow "
+ ql_log(ql_log_warn, vha, 0x301a,
+ "Mid-layer underflow "
"detected (0x%x of 0x%x bytes).\n",
- vha->host_no, cp->device->id,
- cp->device->lun, resid, scsi_bufflen(cp));
+ resid, scsi_bufflen(cp));
cp->result = DID_ERROR << 16;
break;
@@ -1673,9 +1713,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
cp->result = DID_OK << 16 | lscsi_status;
if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d) QUEUE FULL detected.\n",
- vha->host_no, cp->device->id, cp->device->lun));
+ ql_log(ql_log_warn, vha, 0x301b,
+ "QUEUE FULL detected.\n");
break;
}
logit = 0;
@@ -1696,33 +1735,30 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
scsi_set_resid(cp, resid);
if (scsi_status & SS_RESIDUAL_UNDER) {
if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d) Dropped frame(s) detected "
- "(0x%x of 0x%x bytes).\n", vha->host_no,
- cp->device->id, cp->device->lun, resid,
- scsi_bufflen(cp)));
+ ql_log(ql_log_warn, vha, 0x301d,
+ "Dropped frame(s) detected "
+ "(0x%x of 0x%x bytes).\n",
+ resid, scsi_bufflen(cp));
cp->result = DID_ERROR << 16 | lscsi_status;
- break;
+ goto check_scsi_status;
}
if (!lscsi_status &&
((unsigned)(scsi_bufflen(cp) - resid) <
cp->underflow)) {
- qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): Mid-layer underflow "
+ ql_log(ql_log_warn, vha, 0x301e,
+ "Mid-layer underflow "
"detected (0x%x of 0x%x bytes).\n",
- vha->host_no, cp->device->id,
- cp->device->lun, resid, scsi_bufflen(cp));
+ resid, scsi_bufflen(cp));
cp->result = DID_ERROR << 16;
break;
}
} else {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x "
- "of 0x%x bytes).\n", vha->host_no, cp->device->id,
- cp->device->lun, resid, scsi_bufflen(cp)));
+ ql_log(ql_log_warn, vha, 0x301f,
+ "Dropped frame(s) detected (0x%x "
+ "of 0x%x bytes).\n", resid, scsi_bufflen(cp));
cp->result = DID_ERROR << 16 | lscsi_status;
goto check_scsi_status;
@@ -1738,10 +1774,8 @@ check_scsi_status:
*/
if (lscsi_status != 0) {
if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d) QUEUE FULL detected.\n",
- vha->host_no, cp->device->id,
- cp->device->lun));
+ ql_log(ql_log_warn, vha, 0x3020,
+ "QUEUE FULL detected.\n");
logit = 1;
break;
}
@@ -1780,10 +1814,9 @@ check_scsi_status:
break;
}
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d) Port down status: port-state=0x%x\n",
- vha->host_no, cp->device->id, cp->device->lun,
- atomic_read(&fcport->state)));
+ ql_dbg(ql_dbg_io, vha, 0x3021,
+ "Port down status: port-state=0x%x.\n",
+ atomic_read(&fcport->state));
if (atomic_read(&fcport->state) == FCS_ONLINE)
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
@@ -1794,7 +1827,7 @@ check_scsi_status:
break;
case CS_DIF_ERROR:
- qla2x00_handle_dif_error(sp, sts24);
+ logit = qla2x00_handle_dif_error(sp, sts24);
break;
default:
cp->result = DID_ERROR << 16;
@@ -1803,15 +1836,13 @@ check_scsi_status:
out:
if (logit)
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d) FCP command status: 0x%x-0x%x (0x%x) "
- "portid=%02x%02x%02x oxid=0x%x cdb=%02x%02x%02x len=0x%x "
- "rsp_info=0x%x resid=0x%x fw_resid=0x%x\n", vha->host_no,
- cp->device->id, cp->device->lun, comp_status, scsi_status,
- cp->result, fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, ox_id, cp->cmnd[0], cp->cmnd[1],
- cp->cmnd[2], scsi_bufflen(cp), rsp_info_len, resid_len,
- fw_resid_len));
+ ql_dbg(ql_dbg_io, vha, 0x3022,
+ "FCP command status: 0x%x-0x%x (0x%x) "
+ "oxid=0x%x cdb=%02x%02x%02x len=0x%x "
+ "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n",
+ comp_status, scsi_status, cp->result, ox_id, cp->cmnd[0],
+ cp->cmnd[1], cp->cmnd[2], scsi_bufflen(cp), rsp_info_len,
+ resid_len, fw_resid_len);
if (rsp->status_srb == NULL)
qla2x00_sp_compl(ha, sp);
@@ -1829,16 +1860,15 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
{
uint8_t sense_sz = 0;
struct qla_hw_data *ha = rsp->hw;
+ struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
srb_t *sp = rsp->status_srb;
struct scsi_cmnd *cp;
if (sp != NULL && sp->request_sense_length != 0) {
cp = sp->cmd;
if (cp == NULL) {
- DEBUG2(printk("%s(): Cmd already returned back to OS "
- "sp=%p.\n", __func__, sp));
- qla_printk(KERN_INFO, ha,
- "cmd is NULL: already returned to OS (sp=%p)\n",
+ ql_log(ql_log_warn, vha, 0x3025,
+ "cmd is NULL: already returned to OS (sp=%p).\n",
sp);
rsp->status_srb = NULL;
@@ -1855,7 +1885,8 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
if (IS_FWI2_CAPABLE(ha))
host_to_fcp_swap(pkt->data, sizeof(pkt->data));
memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
- DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302c,
+ sp->request_sense_ptr, sense_sz);
sp->request_sense_ptr += sense_sz;
sp->request_sense_length -= sense_sz;
@@ -1881,21 +1912,25 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
uint32_t handle = LSW(pkt->handle);
uint16_t que = MSW(pkt->handle);
struct req_que *req = ha->req_q_map[que];
-#if defined(QL_DEBUG_LEVEL_2)
+
if (pkt->entry_status & RF_INV_E_ORDER)
- qla_printk(KERN_ERR, ha, "%s: Invalid Entry Order\n", __func__);
+ ql_dbg(ql_dbg_async, vha, 0x502a,
+ "Invalid Entry Order.\n");
else if (pkt->entry_status & RF_INV_E_COUNT)
- qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__);
+ ql_dbg(ql_dbg_async, vha, 0x502b,
+ "Invalid Entry Count.\n");
else if (pkt->entry_status & RF_INV_E_PARAM)
- qla_printk(KERN_ERR, ha,
- "%s: Invalid Entry Parameter\n", __func__);
+ ql_dbg(ql_dbg_async, vha, 0x502c,
+ "Invalid Entry Parameter.\n");
else if (pkt->entry_status & RF_INV_E_TYPE)
- qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__);
+ ql_dbg(ql_dbg_async, vha, 0x502d,
+ "Invalid Entry Type.\n");
else if (pkt->entry_status & RF_BUSY)
- qla_printk(KERN_ERR, ha, "%s: Busy\n", __func__);
+ ql_dbg(ql_dbg_async, vha, 0x502e,
+ "Busy.\n");
else
- qla_printk(KERN_ERR, ha, "%s: UNKNOWN flag error\n", __func__);
-#endif
+ ql_dbg(ql_dbg_async, vha, 0x502f,
+ "UNKNOWN flag error.\n");
/* Validate handle. */
if (handle < MAX_OUTSTANDING_COMMANDS)
@@ -1922,10 +1957,8 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
} else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7
|| pkt->entry_type == COMMAND_TYPE_6) {
- DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n",
- vha->host_no));
- qla_printk(KERN_WARNING, ha,
- "Error entry - invalid handle\n");
+ ql_log(ql_log_warn, vha, 0x5030,
+ "Error entry - invalid handle.\n");
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
@@ -1959,11 +1992,11 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
}
if (ha->mcp) {
- DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
- __func__, vha->host_no, ha->mcp->mb[0]));
+ ql_dbg(ql_dbg_async, vha, 0x504d,
+ "Got mailbox completion. cmd=%x.\n", ha->mcp->mb[0]);
} else {
- DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
- __func__, vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x504e,
+ "MBX pointer ERROR.\n");
}
}
@@ -1992,8 +2025,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
}
if (pkt->entry_status != 0) {
- DEBUG3(printk(KERN_INFO
- "scsi(%ld): Process error entry.\n", vha->host_no));
+ ql_dbg(ql_dbg_async, vha, 0x5029,
+ "Process error entry.\n");
qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt);
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -2027,12 +2060,17 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
case ELS_IOCB_TYPE:
qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
break;
+ case MARKER_TYPE:
+ /* Do nothing in this case, this check is to prevent it
+ * from falling into default case
+ */
+ break;
default:
/* Type Not Supported. */
- DEBUG4(printk(KERN_WARNING
- "scsi(%ld): Received unknown response pkt type %x "
+ ql_dbg(ql_dbg_async, vha, 0x5042,
+ "Received unknown response pkt type %x "
"entry status=%x.\n",
- vha->host_no, pkt->entry_type, pkt->entry_status));
+ pkt->entry_type, pkt->entry_status);
break;
}
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -2087,7 +2125,8 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha)
next_test:
if (RD_REG_DWORD(&reg->iobase_c8) & BIT_3)
- qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n");
+ ql_log(ql_log_info, vha, 0x504c,
+ "Additional code -- 0x55AA.\n");
done:
WRT_REG_DWORD(&reg->iobase_window, 0x0000);
@@ -2120,7 +2159,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
@@ -2141,8 +2180,9 @@ qla24xx_intr_handler(int irq, void *dev_id)
hccr = RD_REG_DWORD(&reg->hccr);
- qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
- "Dumping firmware!\n", hccr);
+ ql_log(ql_log_warn, vha, 0x504b,
+ "RISC paused -- HCCR=%x, Dumping firmware.\n",
+ hccr);
qla2xxx_check_risc_status(vha);
@@ -2173,9 +2213,8 @@ qla24xx_intr_handler(int irq, void *dev_id)
qla24xx_process_response_queue(vha, rsp);
break;
default:
- DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
- "(%d).\n",
- vha->host_no, stat & 0xff));
+ ql_dbg(ql_dbg_async, vha, 0x504f,
+ "Unrecognized interrupt type (%d).\n", stat * 0xff);
break;
}
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
@@ -2204,7 +2243,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = rsp->hw;
@@ -2234,13 +2273,13 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = rsp->hw;
/* Clear the interrupt, if enabled, for this response queue */
- if (rsp->options & ~BIT_6) {
+ if (!ha->flags.disable_msix_handshake) {
reg = &ha->iobase->isp24;
spin_lock_irqsave(&ha->hardware_lock, flags);
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
@@ -2267,8 +2306,8 @@ qla24xx_msix_default(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
- DEBUG(printk(
- "%s(): NULL response queue pointer\n", __func__));
+ printk(KERN_INFO
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = rsp->hw;
@@ -2285,8 +2324,9 @@ qla24xx_msix_default(int irq, void *dev_id)
hccr = RD_REG_DWORD(&reg->hccr);
- qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
- "Dumping firmware!\n", hccr);
+ ql_log(ql_log_info, vha, 0x5050,
+ "RISC paused -- HCCR=%x, Dumping firmware.\n",
+ hccr);
qla2xxx_check_risc_status(vha);
@@ -2317,9 +2357,8 @@ qla24xx_msix_default(int irq, void *dev_id)
qla24xx_process_response_queue(vha, rsp);
break;
default:
- DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
- "(%d).\n",
- vha->host_no, stat & 0xff));
+ ql_dbg(ql_dbg_async, vha, 0x5051,
+ "Unrecognized interrupt type (%d).\n", stat & 0xff);
break;
}
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
@@ -2357,6 +2396,7 @@ qla24xx_disable_msix(struct qla_hw_data *ha)
{
int i;
struct qla_msix_entry *qentry;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
for (i = 0; i < ha->msix_count; i++) {
qentry = &ha->msix_entries[i];
@@ -2367,6 +2407,8 @@ qla24xx_disable_msix(struct qla_hw_data *ha)
kfree(ha->msix_entries);
ha->msix_entries = NULL;
ha->flags.msix_enabled = 0;
+ ql_dbg(ql_dbg_init, vha, 0x0042,
+ "Disabled the MSI.\n");
}
static int
@@ -2376,11 +2418,15 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
int i, ret;
struct msix_entry *entries;
struct qla_msix_entry *qentry;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count,
GFP_KERNEL);
- if (!entries)
+ if (!entries) {
+ ql_log(ql_log_warn, vha, 0x00bc,
+ "Failed to allocate memory for msix_entry.\n");
return -ENOMEM;
+ }
for (i = 0; i < ha->msix_count; i++)
entries[i].entry = i;
@@ -2390,16 +2436,18 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
if (ret < MIN_MSIX_COUNT)
goto msix_failed;
- qla_printk(KERN_WARNING, ha,
- "MSI-X: Failed to enable support -- %d/%d\n"
- " Retry with %d vectors\n", ha->msix_count, ret, ret);
+ ql_log(ql_log_warn, vha, 0x00c6,
+ "MSI-X: Failed to enable support "
+ "-- %d/%d\n Retry with %d vectors.\n",
+ ha->msix_count, ret, ret);
ha->msix_count = ret;
ret = pci_enable_msix(ha->pdev, entries, ha->msix_count);
if (ret) {
msix_failed:
- qla_printk(KERN_WARNING, ha, "MSI-X: Failed to enable"
- " support, giving up -- %d/%d\n",
- ha->msix_count, ret);
+ ql_log(ql_log_fatal, vha, 0x00c7,
+ "MSI-X: Failed to enable support, "
+ "giving up -- %d/%d.\n",
+ ha->msix_count, ret);
goto msix_out;
}
ha->max_rsp_queues = ha->msix_count - 1;
@@ -2407,6 +2455,8 @@ msix_failed:
ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
ha->msix_count, GFP_KERNEL);
if (!ha->msix_entries) {
+ ql_log(ql_log_fatal, vha, 0x00c8,
+ "Failed to allocate memory for ha->msix_entries.\n");
ret = -ENOMEM;
goto msix_out;
}
@@ -2433,9 +2483,9 @@ msix_failed:
0, msix_entries[i].name, rsp);
}
if (ret) {
- qla_printk(KERN_WARNING, ha,
- "MSI-X: Unable to register handler -- %x/%d.\n",
- qentry->vector, ret);
+ ql_log(ql_log_fatal, vha, 0x00cb,
+ "MSI-X: unable to register handler -- %x/%d.\n",
+ qentry->vector, ret);
qla24xx_disable_msix(ha);
ha->mqenable = 0;
goto msix_out;
@@ -2448,6 +2498,12 @@ msix_failed:
/* Enable MSI-X vector for response queue update for queue 0 */
if (ha->mqiobase && (ha->max_rsp_queues > 1 || ha->max_req_queues > 1))
ha->mqenable = 1;
+ ql_dbg(ql_dbg_multiq, vha, 0xc005,
+ "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
+ ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
+ ql_dbg(ql_dbg_init, vha, 0x0055,
+ "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
+ ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
msix_out:
kfree(entries);
@@ -2459,6 +2515,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
{
int ret;
device_reg_t __iomem *reg = ha->iobase;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
/* If possible, enable MSI-X. */
if (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
@@ -2469,30 +2526,29 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
(ha->pdev->subsystem_device == 0x7040 ||
ha->pdev->subsystem_device == 0x7041 ||
ha->pdev->subsystem_device == 0x1705)) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X,0x%X).\n",
+ ql_log(ql_log_warn, vha, 0x0034,
+ "MSI-X: Unsupported ISP 2432 SSVID/SSDID (0x%X,0x%X).\n",
ha->pdev->subsystem_vendor,
- ha->pdev->subsystem_device));
+ ha->pdev->subsystem_device);
goto skip_msi;
}
- if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX ||
- !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
- ha->pdev->revision, ha->fw_attributes));
+ if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX)) {
+ ql_log(ql_log_warn, vha, 0x0035,
+ "MSI-X; Unsupported ISP2432 (0x%X, 0x%X).\n",
+ ha->pdev->revision, QLA_MSIX_CHIP_REV_24XX);
goto skip_msix;
}
ret = qla24xx_enable_msix(ha, rsp);
if (!ret) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
- ha->fw_attributes));
+ ql_dbg(ql_dbg_init, vha, 0x0036,
+ "MSI-X: Enabled (0x%X, 0x%X).\n",
+ ha->chip_revision, ha->fw_attributes);
goto clear_risc_ints;
}
- qla_printk(KERN_WARNING, ha,
- "MSI-X: Falling back-to MSI mode -- %d.\n", ret);
+ ql_log(ql_log_info, vha, 0x0037,
+ "MSI-X Falling back-to MSI mode -%d.\n", ret);
skip_msix:
if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
@@ -2501,18 +2557,19 @@ skip_msix:
ret = pci_enable_msi(ha->pdev);
if (!ret) {
- DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
+ ql_dbg(ql_dbg_init, vha, 0x0038,
+ "MSI: Enabled.\n");
ha->flags.msi_enabled = 1;
} else
- qla_printk(KERN_WARNING, ha,
- "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
+ ql_log(ql_log_warn, vha, 0x0039,
+ "MSI-X; Falling back-to INTa mode -- %d.\n", ret);
skip_msi:
ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
ha->flags.msi_enabled ? 0 : IRQF_SHARED,
QLA2XXX_DRIVER_NAME, rsp);
if (ret) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x003a,
"Failed to reserve interrupt %d already in use.\n",
ha->pdev->irq);
goto fail;
@@ -2562,13 +2619,14 @@ int qla25xx_request_irq(struct rsp_que *rsp)
struct qla_hw_data *ha = rsp->hw;
struct qla_init_msix_entry *intr = &msix_entries[2];
struct qla_msix_entry *msix = rsp->msix;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
int ret;
ret = request_irq(msix->vector, intr->handler, 0, intr->name, rsp);
if (ret) {
- qla_printk(KERN_WARNING, ha,
- "MSI-X: Unable to register handler -- %x/%d.\n",
- msix->vector, ret);
+ ql_log(ql_log_fatal, vha, 0x00e6,
+ "MSI-X: Unable to register handler -- %x/%d.\n",
+ msix->vector, ret);
return ret;
}
msix->have_irq = 1;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index c26f0ac..82a3353 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -46,14 +46,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- if (ha->pdev->error_state > pci_channel_io_frozen)
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1000, "Entered %s.\n", __func__);
+
+ if (ha->pdev->error_state > pci_channel_io_frozen) {
+ ql_log(ql_log_warn, base_vha, 0x1001,
+ "error_state is greater than pci_channel_io_frozen, "
+ "exiting.\n");
return QLA_FUNCTION_TIMEOUT;
+ }
if (vha->device_flags & DFLG_DEV_FAILED) {
- DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
- "%s(%ld): Device in failed state, "
- "timeout MBX Exiting.\n",
- __func__, base_vha->host_no));
+ ql_log(ql_log_warn, base_vha, 0x1002,
+ "Device in failed state, exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
@@ -63,19 +67,19 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
rval = QLA_SUCCESS;
abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
- DEBUG11(printk("%s(%ld): entered.\n", __func__, base_vha->host_no));
if (ha->flags.pci_channel_io_perm_failure) {
- DEBUG(printk("%s(%ld): Perm failure on EEH, timeout MBX "
- "Exiting.\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, base_vha, 0x1003,
+ "Perm failure on EEH timeout MBX, exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
if (ha->flags.isp82xx_fw_hung) {
/* Setting Link-Down error */
mcp->mb[0] = MBS_LINK_DOWN_ERROR;
- rval = QLA_FUNCTION_FAILED;
- goto premature_exit;
+ ql_log(ql_log_warn, base_vha, 0x1004,
+ "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
+ return QLA_FUNCTION_TIMEOUT;
}
/*
@@ -85,8 +89,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
*/
if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
/* Timeout occurred. Return error. */
- DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
- "Exiting.\n", __func__, base_vha->host_no));
+ ql_log(ql_log_warn, base_vha, 0x1005,
+ "Cmd access timeout, Exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
@@ -94,8 +98,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/* Save mailbox command for debug */
ha->mcp = mcp;
- DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n",
- base_vha->host_no, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1006,
+ "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]);
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -123,27 +127,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
iptr++;
}
-#if defined(QL_DEBUG_LEVEL_1)
- printk("%s(%ld): Loaded MBX registers (displayed in bytes) = \n",
- __func__, base_vha->host_no);
- qla2x00_dump_buffer((uint8_t *)mcp->mb, 16);
- printk("\n");
- qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16);
- printk("\n");
- qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8);
- printk("\n");
- printk("%s(%ld): I/O address = %p.\n", __func__, base_vha->host_no,
- optr);
- qla2x00_dump_regs(base_vha);
-#endif
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1111,
+ "Loaded MBX registers (displayed in bytes) =.\n");
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1112,
+ (uint8_t *)mcp->mb, 16);
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1113,
+ ".\n");
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1114,
+ ((uint8_t *)mcp->mb + 0x10), 16);
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1115,
+ ".\n");
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1116,
+ ((uint8_t *)mcp->mb + 0x20), 8);
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1117,
+ "I/O Address = %p.\n", optr);
+ ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x100e);
/* Issue set host interrupt command to send cmd out. */
ha->flags.mbox_int = 0;
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
/* Unlock mbx registers and wait for interrupt */
- DEBUG11(printk("%s(%ld): going to unlock irq & waiting for interrupt. "
- "jiffies=%lx.\n", __func__, base_vha->host_no, jiffies));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x100f,
+ "Going to unlock irq & waiting for interrupts. "
+ "jiffies=%lx.\n", jiffies);
/* Wait for mbx cmd completion until timeout */
@@ -155,9 +162,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
HINT_MBX_INT_PENDING) {
spin_unlock_irqrestore(&ha->hardware_lock,
flags);
- DEBUG2_3_11(printk(KERN_INFO
- "%s(%ld): Pending Mailbox timeout. "
- "Exiting.\n", __func__, base_vha->host_no));
+ ha->flags.mbox_busy = 0;
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1010,
+ "Pending mailbox timeout, exiting.\n");
rval = QLA_FUNCTION_TIMEOUT;
goto premature_exit;
}
@@ -173,17 +180,17 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
} else {
- DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
- base_vha->host_no, command));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1011,
+ "Cmd=%x Polling Mode.\n", command);
if (IS_QLA82XX(ha)) {
if (RD_REG_DWORD(&reg->isp82.hint) &
HINT_MBX_INT_PENDING) {
spin_unlock_irqrestore(&ha->hardware_lock,
flags);
- DEBUG2_3_11(printk(KERN_INFO
- "%s(%ld): Pending Mailbox timeout. "
- "Exiting.\n", __func__, base_vha->host_no));
+ ha->flags.mbox_busy = 0;
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1012,
+ "Pending mailbox timeout, exiting.\n");
rval = QLA_FUNCTION_TIMEOUT;
goto premature_exit;
}
@@ -207,17 +214,17 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
command == MBC_LOAD_RISC_RAM_EXTENDED))
msleep(10);
} /* while */
- DEBUG17(qla_printk(KERN_WARNING, ha,
- "Waited %d sec\n",
- (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ)));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1013,
+ "Waited %d sec.\n",
+ (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
}
/* Check whether we timed out */
if (ha->flags.mbox_int) {
uint16_t *iptr2;
- DEBUG3_11(printk("%s(%ld): cmd %x completed.\n", __func__,
- base_vha->host_no, command));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1014,
+ "Cmd=%x completed.\n", command);
/* Got interrupt. Clear the flag. */
ha->flags.mbox_int = 0;
@@ -229,6 +236,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
mcp->mb[0] = MBS_LINK_DOWN_ERROR;
ha->mcp = NULL;
rval = QLA_FUNCTION_FAILED;
+ ql_log(ql_log_warn, base_vha, 0x1015,
+ "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
goto premature_exit;
}
@@ -249,8 +258,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
}
} else {
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \
- defined(QL_DEBUG_LEVEL_11)
uint16_t mb0;
uint32_t ictrl;
@@ -261,14 +268,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
ictrl = RD_REG_WORD(&reg->isp.ictrl);
}
- printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
- __func__, base_vha->host_no, command);
- printk("%s(%ld): icontrol=%x jiffies=%lx\n", __func__,
- base_vha->host_no, ictrl, jiffies);
- printk("%s(%ld): *** mailbox[0] = 0x%x ***\n", __func__,
- base_vha->host_no, mb0);
- qla2x00_dump_regs(base_vha);
-#endif
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1119,
+ "MBX Command timeout for cmd %x.\n", command);
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x111a,
+ "iocontrol=%x jiffies=%lx.\n", ictrl, jiffies);
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x111b,
+ "mb[0] = 0x%x.\n", mb0);
+ ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1019);
rval = QLA_FUNCTION_TIMEOUT;
}
@@ -279,8 +285,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
ha->mcp = NULL;
if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
- DEBUG11(printk("%s(%ld): checking for additional resp "
- "interrupt.\n", __func__, base_vha->host_no));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x101a,
+ "Checking for additional resp interrupt.\n");
/* polling mode for non isp_abort commands. */
qla2x00_poll(ha->rsp_q_map[0]);
@@ -291,38 +297,48 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
ha->flags.eeh_busy) {
/* not in dpc. schedule it for dpc to take over. */
- DEBUG(printk("%s(%ld): timeout schedule "
- "isp_abort_needed.\n", __func__,
- base_vha->host_no));
- DEBUG2_3_11(printk("%s(%ld): timeout schedule "
- "isp_abort_needed.\n", __func__,
- base_vha->host_no));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x101b,
+ "Timeout, schedule isp_abort_needed.\n");
if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
!test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
-
- qla_printk(KERN_WARNING, ha,
- "Mailbox command timeout occurred. "
- "Scheduling ISP " "abort. eeh_busy: 0x%x\n",
- ha->flags.eeh_busy);
+ if (IS_QLA82XX(ha)) {
+ ql_dbg(ql_dbg_mbx, vha, 0x112a,
+ "disabling pause transmit on port "
+ "0 & 1.\n");
+ qla82xx_wr_32(ha,
+ QLA82XX_CRB_NIU + 0x98,
+ CRB_NIU_XG_PAUSE_CTL_P0|
+ CRB_NIU_XG_PAUSE_CTL_P1);
+ }
+ ql_log(ql_log_info, base_vha, 0x101c,
+ "Mailbox cmd timeout occured. "
+ "Scheduling ISP abort eeh_busy=0x%x.\n",
+ ha->flags.eeh_busy);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
} else if (!abort_active) {
/* call abort directly since we are in the DPC thread */
- DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
- __func__, base_vha->host_no));
- DEBUG2_3_11(printk("%s(%ld): timeout calling "
- "abort_isp\n", __func__, base_vha->host_no));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x101d,
+ "Timeout, calling abort_isp.\n");
if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
!test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
-
- qla_printk(KERN_WARNING, ha,
- "Mailbox command timeout occurred. "
- "Issuing ISP abort.\n");
+ if (IS_QLA82XX(ha)) {
+ ql_dbg(ql_dbg_mbx, vha, 0x112b,
+ "disabling pause transmit on port "
+ "0 & 1.\n");
+ qla82xx_wr_32(ha,
+ QLA82XX_CRB_NIU + 0x98,
+ CRB_NIU_XG_PAUSE_CTL_P0|
+ CRB_NIU_XG_PAUSE_CTL_P1);
+ }
+ ql_log(ql_log_info, base_vha, 0x101e,
+ "Mailbox cmd timeout occured. "
+ "Scheduling ISP abort.\n");
set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -332,11 +348,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
&vha->dpc_flags);
}
clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
- DEBUG(printk("%s(%ld): finished abort_isp\n",
- __func__, vha->host_no));
- DEBUG2_3_11(printk(
- "%s(%ld): finished abort_isp\n",
- __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x101f,
+ "Finished abort_isp.\n");
}
}
}
@@ -346,12 +359,11 @@ premature_exit:
complete(&ha->mbx_cmd_comp);
if (rval) {
- DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, "
- "mbx2=%x, cmd=%x ****\n", __func__, base_vha->host_no,
- mcp->mb[0], mcp->mb[1], mcp->mb[2], command));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1020,
+ "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, cmd=%x ****.\n",
+ mcp->mb[0], mcp->mb[1], mcp->mb[2], command);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__,
- base_vha->host_no));
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
}
return rval;
@@ -366,7 +378,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1022, "Entered %s.\n", __func__);
if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) {
mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
@@ -397,10 +409,10 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1023,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1024, "Done %s.\n", __func__);
}
return rval;
@@ -430,7 +442,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1025, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
mcp->out_mb = MBX_0;
@@ -461,15 +473,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1026,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
if (IS_FWI2_CAPABLE(ha)) {
- DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
- __func__, vha->host_no, mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1027,
+ "Done exchanges=%x.\n", mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__,
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1028, "Done %s.\n", __func__);
}
}
@@ -501,7 +512,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1029, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
mcp->out_mb = MBX_0;
@@ -535,11 +546,10 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
failed:
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval);
} else {
/*EMPTY*/
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x102b, "Done %s.\n", __func__);
}
return rval;
}
@@ -565,7 +575,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x102c, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
mcp->out_mb = MBX_0;
@@ -576,15 +586,14 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x102d, "Failed=%x.\n", rval);
} else {
fwopts[0] = mcp->mb[0];
fwopts[1] = mcp->mb[1];
fwopts[2] = mcp->mb[2];
fwopts[3] = mcp->mb[3];
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x102e, "Done %s.\n", __func__);
}
return rval;
@@ -612,7 +621,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x102f, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_SET_FIRMWARE_OPTION;
mcp->mb[1] = fwopts[1];
@@ -636,11 +645,11 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("%s(%ld): failed=%x (%x/%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1030,
+ "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]);
} else {
/*EMPTY*/
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1031, "Done %s.\n", __func__);
}
return rval;
@@ -668,7 +677,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1032, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
mcp->mb[1] = 0xAAAA;
@@ -695,12 +704,10 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_mbx_reg_test(%ld): failed=%x.\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_mbx_reg_test(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1034, "Done %s.\n", __func__);
}
return rval;
@@ -728,7 +735,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1035, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_VERIFY_CHECKSUM;
mcp->out_mb = MBX_0;
@@ -749,11 +756,11 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__,
- vha->host_no, rval, IS_FWI2_CAPABLE(vha->hw) ?
- (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1036,
+ "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ?
+ (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1037, "Done %s.\n", __func__);
}
return rval;
@@ -785,6 +792,8 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x1038, "Entered %s.\n", __func__);
+
mcp->mb[0] = MBC_IOCB_COMMAND_A64;
mcp->mb[1] = 0;
mcp->mb[2] = MSW(phys_addr);
@@ -799,14 +808,14 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval);
} else {
sts_entry_t *sts_entry = (sts_entry_t *) buffer;
/* Mask reserved bits. */
sts_entry->entry_status &=
IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK;
+ ql_dbg(ql_dbg_mbx, vha, 0x103a, "Done %s.\n", __func__);
}
return rval;
@@ -847,7 +856,7 @@ qla2x00_abort_command(srb_t *sp)
struct qla_hw_data *ha = vha->hw;
struct req_que *req = vha->req;
- DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__);
spin_lock_irqsave(&ha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
@@ -876,11 +885,9 @@ qla2x00_abort_command(srb_t *sp)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x103d, "Done %s.\n", __func__);
}
return rval;
@@ -896,10 +903,11 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
struct req_que *req;
struct rsp_que *rsp;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
-
l = l;
vha = fcport->vha;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x103e, "Entered %s.\n", __func__);
+
req = vha->hw->req_q_map[0];
rsp = req->rsp;
mcp->mb[0] = MBC_ABORT_TARGET;
@@ -919,18 +927,17 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x103f, "Failed=%x.\n", rval);
}
/* Issue marker IOCB. */
rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, 0,
MK_SYNC_ID);
if (rval2 != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
- "(%x).\n", __func__, vha->host_no, rval2));
+ ql_dbg(ql_dbg_mbx, vha, 0x1040,
+ "Failed to issue marker IOCB (%x).\n", rval2);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1041, "Done %s.\n", __func__);
}
return rval;
@@ -946,9 +953,10 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
struct req_que *req;
struct rsp_que *rsp;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
-
vha = fcport->vha;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1042, "Entered %s.\n", __func__);
+
req = vha->hw->req_q_map[0];
rsp = req->rsp;
mcp->mb[0] = MBC_LUN_RESET;
@@ -966,18 +974,17 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1043, "Failed=%x.\n", rval);
}
/* Issue marker IOCB. */
rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
MK_SYNC_ID_LUN);
if (rval2 != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
- "(%x).\n", __func__, vha->host_no, rval2));
+ ql_dbg(ql_dbg_mbx, vha, 0x1044,
+ "Failed to issue marker IOCB (%x).\n", rval2);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1045, "Done %s.\n", __func__);
}
return rval;
@@ -1011,8 +1018,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_get_adapter_id(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1046, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
mcp->mb[9] = vha->vp_idx;
@@ -1038,11 +1044,9 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1048, "Done %s.\n", __func__);
if (IS_QLA8XXX_TYPE(vha->hw)) {
vha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
@@ -1083,8 +1087,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_get_retry_cnt(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1049, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_RETRY_COUNT;
mcp->out_mb = MBX_0;
@@ -1095,8 +1098,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_get_retry_cnt(%ld): failed = %x.\n",
- vha->host_no, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x104a,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
/* Convert returned data and check our values. */
*r_a_tov = mcp->mb[3] / 2;
@@ -1107,8 +1110,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
*tov = ratov;
}
- DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d "
- "ratov=%d.\n", vha->host_no, mcp->mb[3], ratov));
+ ql_dbg(ql_dbg_mbx, vha, 0x104b,
+ "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov);
}
return rval;
@@ -1139,8 +1142,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x104c, "Entered %s.\n", __func__);
if (IS_QLA82XX(ha) && ql2xdbwr)
qla82xx_wr_32(ha, ha->nxdb_wr_ptr,
@@ -1174,13 +1176,11 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_init_firmware(%ld): failed=%x "
- "mb0=%x.\n",
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x104d,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_init_firmware(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x104e, "Done %s.\n", __func__);
}
return rval;
@@ -1213,13 +1213,13 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
dma_addr_t pd_dma;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x104f, "Entered %s.\n", __func__);
pd24 = NULL;
pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
if (pd == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Port Database "
- "structure.\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x1050,
+ "Failed to allocate port database structure.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
@@ -1261,12 +1261,10 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
/* Check for logged in state. */
if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
pd24->last_login_state != PDS_PRLI_COMPLETE) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "scsi(%ld): Unable to verify login-state (%x/%x) "
- " - portid=%02x%02x%02x.\n", vha->host_no,
- pd24->current_login_state, pd24->last_login_state,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_mbx, vha, 0x1051,
+ "Unable to verify login-state (%x/%x) for "
+ "loop_id %x.\n", pd24->current_login_state,
+ pd24->last_login_state, fcport->loop_id);
rval = QLA_FUNCTION_FAILED;
goto gpd_error_out;
}
@@ -1290,12 +1288,11 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
/* Check for logged in state. */
if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "scsi(%ld): Unable to verify login-state (%x/%x) "
- " - portid=%02x%02x%02x.\n", vha->host_no,
- pd->master_state, pd->slave_state,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa));
+ ql_dbg(ql_dbg_mbx, vha, 0x100a,
+ "Unable to verify login-state (%x/%x) - "
+ "portid=%02x%02x%02x.\n", pd->master_state,
+ pd->slave_state, fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa);
rval = QLA_FUNCTION_FAILED;
goto gpd_error_out;
}
@@ -1325,10 +1322,11 @@ gpd_error_out:
dma_pool_free(ha->s_dma_pool, pd, pd_dma);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1052,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n", rval,
+ mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1053, "Done %s.\n", __func__);
}
return rval;
@@ -1357,8 +1355,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1054, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
mcp->out_mb = MBX_0;
@@ -1381,12 +1378,10 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): "
- "failed=%x.\n", vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1056, "Done %s.\n", __func__);
}
return rval;
@@ -1418,8 +1413,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1057, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_PORT_NAME;
mcp->mb[9] = vha->vp_idx;
@@ -1439,8 +1433,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1058, "Failed=%x.\n", rval);
} else {
if (name != NULL) {
/* This function returns name in big endian. */
@@ -1454,8 +1447,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
name[7] = LSB(mcp->mb[7]);
}
- DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1059, "Done %s.\n", __func__);
}
return rval;
@@ -1483,7 +1475,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x105a, "Entered %s.\n", __func__);
if (IS_QLA8XXX_TYPE(vha->hw)) {
/* Logout across all FCFs. */
@@ -1517,11 +1509,10 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n",
- __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval);
} else {
/*EMPTY*/
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x105c, "Done %s.\n", __func__);
}
return rval;
@@ -1553,12 +1544,11 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x105d, "Entered %s.\n", __func__);
- DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total "
- "tov=%d.\n", vha->hw->retry_count, vha->hw->login_timeout,
- mcp->tov));
+ ql_dbg(ql_dbg_mbx, vha, 0x105e,
+ "Retry cnt=%d ratov=%d total tov=%d.\n",
+ vha->hw->retry_count, vha->hw->login_timeout, mcp->tov);
mcp->mb[0] = MBC_SEND_SNS_COMMAND;
mcp->mb[1] = cmd_size;
@@ -1575,13 +1565,12 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
- "mb[1]=%x.\n", vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
- DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
- "mb[1]=%x.\n", vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x105f,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1060, "Done %s.\n", __func__);
}
return rval;
@@ -1600,7 +1589,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
struct req_que *req;
struct rsp_que *rsp;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1061, "Entered %s.\n", __func__);
if (ha->flags.cpu_affinity_enabled)
req = ha->req_q_map[0];
@@ -1610,8 +1599,8 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
if (lg == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Login IOCB.\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x1062,
+ "Failed to allocate login IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(lg, 0, sizeof(struct logio_entry_24xx));
@@ -1631,21 +1620,21 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
lg->vp_index = vha->vp_idx;
rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
- "(%x).\n", __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1063,
+ "Failed to issue login IOCB (%x).\n", rval);
} else if (lg->entry_status != 0) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, vha->host_no,
- lg->entry_status));
+ ql_dbg(ql_dbg_mbx, vha, 0x1064,
+ "Failed to complete IOCB -- error status (%x).\n",
+ lg->entry_status);
rval = QLA_FUNCTION_FAILED;
} else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
iop[0] = le32_to_cpu(lg->io_parameter[0]);
iop[1] = le32_to_cpu(lg->io_parameter[1]);
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- completion status (%x) ioparam=%x/%x.\n", __func__,
- vha->host_no, le16_to_cpu(lg->comp_status), iop[0],
- iop[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1065,
+ "Failed to complete IOCB -- completion status (%x) "
+ "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
+ iop[0], iop[1]);
switch (iop[0]) {
case LSC_SCODE_PORTID_USED:
@@ -1673,7 +1662,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
break;
}
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1066, "Done %s.\n", __func__);
iop[0] = le32_to_cpu(lg->io_parameter[0]);
@@ -1728,7 +1717,7 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1067, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
@@ -1771,13 +1760,12 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
rval = QLA_SUCCESS;
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x "
- "mb[0]=%x mb[1]=%x mb[2]=%x.\n", vha->host_no, rval,
- mcp->mb[0], mcp->mb[1], mcp->mb[2]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1068,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1069, "Done %s.\n", __func__);
}
return rval;
@@ -1808,13 +1796,13 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport,
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x106a, "Entered %s.\n", __func__);
+
if (IS_FWI2_CAPABLE(ha))
return qla24xx_login_fabric(vha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, mb_ret, opt);
- DEBUG3(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
if (HAS_EXTENDED_IDS(ha))
mcp->mb[1] = fcport->loop_id;
@@ -1845,15 +1833,12 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport,
if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006)
rval = QLA_SUCCESS;
- DEBUG(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
- "mb[6]=%x mb[7]=%x.\n", __func__, vha->host_no, rval,
- mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]));
- DEBUG2_3(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
- "mb[6]=%x mb[7]=%x.\n", __func__, vha->host_no, rval,
- mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]));
+ ql_dbg(ql_dbg_mbx, vha, 0x106b,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[6]=%x mb[7]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);
} else {
/*EMPTY*/
- DEBUG3(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x106c, "Done %s.\n", __func__);
}
return (rval);
@@ -1870,12 +1855,12 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
struct req_que *req;
struct rsp_que *rsp;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x106d, "Entered %s.\n", __func__);
lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
if (lg == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Logout IOCB.\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x106e,
+ "Failed to allocate logout IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(lg, 0, sizeof(struct logio_entry_24xx));
@@ -1899,22 +1884,22 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
- "(%x).\n", __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x106f,
+ "Failed to issue logout IOCB (%x).\n", rval);
} else if (lg->entry_status != 0) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, vha->host_no,
- lg->entry_status));
+ ql_dbg(ql_dbg_mbx, vha, 0x1070,
+ "Failed to complete IOCB -- error status (%x).\n",
+ lg->entry_status);
rval = QLA_FUNCTION_FAILED;
} else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
- DEBUG2_3_11(printk("%s(%ld %d): failed to complete IOCB "
- "-- completion status (%x) ioparam=%x/%x.\n", __func__,
- vha->host_no, vha->vp_idx, le16_to_cpu(lg->comp_status),
+ ql_dbg(ql_dbg_mbx, vha, 0x1071,
+ "Failed to complete IOCB -- completion status (%x) "
+ "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
le32_to_cpu(lg->io_parameter[0]),
- le32_to_cpu(lg->io_parameter[1])));
+ le32_to_cpu(lg->io_parameter[1]));
} else {
/*EMPTY*/
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1072, "Done %s.\n", __func__);
}
dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -1946,8 +1931,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_fabric_logout(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1073, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
mcp->out_mb = MBX_1|MBX_0;
@@ -1966,12 +1950,11 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_fabric_logout(%ld): failed=%x "
- "mbx1=%x.\n", vha->host_no, rval, mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1074,
+ "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_fabric_logout(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1075, "Done %s.\n", __func__);
}
return rval;
@@ -1999,8 +1982,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1076, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0;
@@ -2014,12 +1996,10 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval);
} else {
/*EMPTY*/
- DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1078, "Done %s.\n", __func__);
}
return rval;
@@ -2045,8 +2025,7 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("qla2x00_get_id_list(%ld): entered.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1079, "Entered %s.\n", __func__);
if (id_list == NULL)
return QLA_FUNCTION_FAILED;
@@ -2075,12 +2054,10 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_get_id_list(%ld): failed=%x.\n",
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval);
} else {
*entries = mcp->mb[1];
- DEBUG11(printk("qla2x00_get_id_list(%ld): done.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x107b, "Done %s.\n", __func__);
}
return rval;
@@ -2108,7 +2085,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x107c, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
mcp->out_mb = MBX_0;
@@ -2121,14 +2098,14 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("%s(%ld): failed = %x.\n", __func__,
- vha->host_no, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x107d,
+ "Failed mb[0]=%x.\n", mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x "
- "mb7=%x mb10=%x mb11=%x mb12=%x.\n", __func__,
- vha->host_no, mcp->mb[1], mcp->mb[2], mcp->mb[3],
- mcp->mb[6], mcp->mb[7], mcp->mb[10], mcp->mb[11],
- mcp->mb[12]));
+ ql_dbg(ql_dbg_mbx, vha, 0x107e,
+ "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x "
+ "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2],
+ mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10],
+ mcp->mb[11], mcp->mb[12]);
if (cur_xchg_cnt)
*cur_xchg_cnt = mcp->mb[3];
@@ -2147,7 +2124,6 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
return (rval);
}
-#if defined(QL_DEBUG_LEVEL_3)
/*
* qla2x00_get_fcal_position_map
* Get FCAL (LILP) position map using mailbox command
@@ -2172,10 +2148,12 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
dma_addr_t pmap_dma;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x107f, "Entered %s.\n", __func__);
+
pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
if (pmap == NULL) {
- DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x1080,
+ "Memory alloc failed.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(pmap, 0, FCAL_MAP_SIZE);
@@ -2193,10 +2171,11 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval == QLA_SUCCESS) {
- DEBUG11(printk("%s(%ld): (mb0=%x/mb1=%x) FC/AL Position Map "
- "size (%x)\n", __func__, vha->host_no, mcp->mb[0],
- mcp->mb[1], (unsigned)pmap[0]));
- DEBUG11(qla2x00_dump_buffer(pmap, pmap[0] + 1));
+ ql_dbg(ql_dbg_mbx, vha, 0x1081,
+ "mb0/mb1=%x/%X FC/AL position map size (%x).\n",
+ mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]);
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d,
+ pmap, pmap[0] + 1);
if (pos_map)
memcpy(pos_map, pmap, FCAL_MAP_SIZE);
@@ -2204,15 +2183,13 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1083, "Done %s.\n", __func__);
}
return rval;
}
-#endif
/*
* qla2x00_get_link_status
@@ -2237,7 +2214,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
uint32_t *siter, *diter, dwords;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1084, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_LINK_STATUS;
mcp->mb[2] = MSW(stats_dma);
@@ -2266,11 +2243,12 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
if (rval == QLA_SUCCESS) {
if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
- DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
- __func__, vha->host_no, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1085,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
rval = QLA_FUNCTION_FAILED;
} else {
/* Copy over data -- firmware data is LE. */
+ ql_dbg(ql_dbg_mbx, vha, 0x1086, "Done %s.\n", __func__);
dwords = offsetof(struct link_statistics, unused1) / 4;
siter = diter = &stats->link_fail_cnt;
while (dwords--)
@@ -2278,8 +2256,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
}
} else {
/* Failed. */
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1087, "Failed=%x.\n", rval);
}
return rval;
@@ -2294,7 +2271,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
mbx_cmd_t *mcp = &mc;
uint32_t *siter, *diter, dwords;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1088, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
mcp->mb[2] = MSW(stats_dma);
@@ -2312,10 +2289,11 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
if (rval == QLA_SUCCESS) {
if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
- DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
- __func__, vha->host_no, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1089,
+ "Failed mb[0]=%x.\n", mcp->mb[0]);
rval = QLA_FUNCTION_FAILED;
} else {
+ ql_dbg(ql_dbg_mbx, vha, 0x108a, "Done %s.\n", __func__);
/* Copy over data -- firmware data is LE. */
dwords = sizeof(struct link_statistics) / 4;
siter = diter = &stats->link_fail_cnt;
@@ -2324,8 +2302,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
}
} else {
/* Failed. */
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x108b, "Failed=%x.\n", rval);
}
return rval;
@@ -2345,7 +2322,7 @@ qla24xx_abort_command(srb_t *sp)
struct qla_hw_data *ha = vha->hw;
struct req_que *req = vha->req;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x108c, "Entered %s.\n", __func__);
spin_lock_irqsave(&ha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
@@ -2360,8 +2337,8 @@ qla24xx_abort_command(srb_t *sp)
abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
if (abt == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Abort IOCB.\n",
- __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x108d,
+ "Failed to allocate abort IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(abt, 0, sizeof(struct abort_entry_24xx));
@@ -2380,20 +2357,20 @@ qla24xx_abort_command(srb_t *sp)
rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n",
- __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x108e,
+ "Failed to issue IOCB (%x).\n", rval);
} else if (abt->entry_status != 0) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, vha->host_no,
- abt->entry_status));
+ ql_dbg(ql_dbg_mbx, vha, 0x108f,
+ "Failed to complete IOCB -- error status (%x).\n",
+ abt->entry_status);
rval = QLA_FUNCTION_FAILED;
} else if (abt->nport_handle != __constant_cpu_to_le16(0)) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- completion status (%x).\n", __func__, vha->host_no,
- le16_to_cpu(abt->nport_handle)));
+ ql_dbg(ql_dbg_mbx, vha, 0x1090,
+ "Failed to complete IOCB -- completion status (%x).\n",
+ le16_to_cpu(abt->nport_handle));
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1091, "Done %s.\n", __func__);
}
dma_pool_free(ha->s_dma_pool, abt, abt_dma);
@@ -2421,19 +2398,20 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
struct req_que *req;
struct rsp_que *rsp;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
-
vha = fcport->vha;
ha = vha->hw;
req = vha->req;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1092, "Entered %s.\n", __func__);
+
if (ha->flags.cpu_affinity_enabled)
rsp = ha->rsp_q_map[tag + 1];
else
rsp = req->rsp;
tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
if (tsk == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
- "IOCB.\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x1093,
+ "Failed to allocate task management IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(tsk, 0, sizeof(struct tsk_mgmt_cmd));
@@ -2457,30 +2435,30 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
sts = &tsk->p.sts;
rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB "
- "(%x).\n", __func__, vha->host_no, name, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1094,
+ "Failed to issue %s reset IOCB (%x).\n", name, rval);
} else if (sts->entry_status != 0) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, vha->host_no,
- sts->entry_status));
+ ql_dbg(ql_dbg_mbx, vha, 0x1095,
+ "Failed to complete IOCB -- error status (%x).\n",
+ sts->entry_status);
rval = QLA_FUNCTION_FAILED;
} else if (sts->comp_status !=
__constant_cpu_to_le16(CS_COMPLETE)) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- completion status (%x).\n", __func__,
- vha->host_no, le16_to_cpu(sts->comp_status)));
+ ql_dbg(ql_dbg_mbx, vha, 0x1096,
+ "Failed to complete IOCB -- completion status (%x).\n",
+ le16_to_cpu(sts->comp_status));
rval = QLA_FUNCTION_FAILED;
} else if (le16_to_cpu(sts->scsi_status) &
SS_RESPONSE_INFO_LEN_VALID) {
if (le32_to_cpu(sts->rsp_data_len) < 4) {
- DEBUG2_3_11(printk("%s(%ld): ignoring inconsistent "
- "data length -- not enough response info (%d).\n",
- __func__, vha->host_no,
- le32_to_cpu(sts->rsp_data_len)));
+ ql_dbg(ql_dbg_mbx, vha, 0x1097,
+ "Ignoring inconsistent data length -- not enough "
+ "response info (%d).\n",
+ le32_to_cpu(sts->rsp_data_len));
} else if (sts->data[3]) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- response (%x).\n", __func__,
- vha->host_no, sts->data[3]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1098,
+ "Failed to complete IOCB -- response (%x).\n",
+ sts->data[3]);
rval = QLA_FUNCTION_FAILED;
}
}
@@ -2489,10 +2467,10 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
if (rval2 != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
- "(%x).\n", __func__, vha->host_no, rval2));
+ ql_dbg(ql_dbg_mbx, vha, 0x1099,
+ "Failed to issue marker IOCB (%x).\n", rval2);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x109a, "Done %s.\n", __func__);
}
dma_pool_free(ha->s_dma_pool, tsk, tsk_dma);
@@ -2533,7 +2511,7 @@ qla2x00_system_error(scsi_qla_host_t *vha)
if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x109b, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_GEN_SYSTEM_ERROR;
mcp->out_mb = MBX_0;
@@ -2543,10 +2521,9 @@ qla2x00_system_error(scsi_qla_host_t *vha)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x109d, "Done %s.\n", __func__);
}
return rval;
@@ -2566,7 +2543,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x109e, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_SERDES_PARAMS;
mcp->mb[1] = BIT_0;
@@ -2581,11 +2558,11 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g,
if (rval != QLA_SUCCESS) {
/*EMPTY*/
- DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x109f,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
/*EMPTY*/
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a0, "Done %s.\n", __func__);
}
return rval;
@@ -2601,7 +2578,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha)
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a1, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_STOP_FIRMWARE;
mcp->out_mb = MBX_0;
@@ -2611,12 +2588,11 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a2, "Failed=%x.\n", rval);
if (mcp->mb[0] == MBS_INVALID_COMMAND)
rval = QLA_INVALID_COMMAND;
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a3, "Done %s.\n", __func__);
}
return rval;
@@ -2630,14 +2606,14 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10a4, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(vha->hw->pdev)))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_TRACE_CONTROL;
mcp->mb[1] = TC_EFT_ENABLE;
mcp->mb[2] = LSW(eft_dma);
@@ -2652,10 +2628,11 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a5,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a6, "Done %s.\n", __func__);
}
return rval;
@@ -2668,14 +2645,14 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10a7, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(vha->hw->pdev)))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_TRACE_CONTROL;
mcp->mb[1] = TC_EFT_DISABLE;
mcp->out_mb = MBX_1|MBX_0;
@@ -2684,10 +2661,11 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a8,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10a9, "Done %s.\n", __func__);
}
return rval;
@@ -2701,14 +2679,14 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10aa, "Entered %s.\n", __func__);
+
if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(vha->hw->pdev)))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_TRACE_CONTROL;
mcp->mb[1] = TC_FCE_ENABLE;
mcp->mb[2] = LSW(fce_dma);
@@ -2727,10 +2705,11 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ab,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ac, "Done %s.\n", __func__);
if (mb)
memcpy(mb, mcp->mb, 8 * sizeof(*mb));
@@ -2748,14 +2727,14 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10ad, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(vha->hw->pdev)))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_TRACE_CONTROL;
mcp->mb[1] = TC_FCE_DISABLE;
mcp->mb[2] = TC_FCE_DISABLE_TRACE;
@@ -2766,10 +2745,11 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ae,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10af, "Done %s.\n", __func__);
if (wr)
*wr = (uint64_t) mcp->mb[5] << 48 |
@@ -2794,11 +2774,11 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10b0, "Entered %s.\n", __func__);
+
if (!IS_IIDMA_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_PORT_PARAMS;
mcp->mb[1] = loop_id;
mcp->mb[2] = mcp->mb[3] = 0;
@@ -2817,10 +2797,9 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
}
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10b2, "Done %s.\n", __func__);
if (port_speed)
*port_speed = mcp->mb[3];
}
@@ -2836,11 +2815,11 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10b3, "Entered %s.\n", __func__);
+
if (!IS_IIDMA_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_PORT_PARAMS;
mcp->mb[1] = loop_id;
mcp->mb[2] = BIT_0;
@@ -2863,10 +2842,9 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
}
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10b4, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10b5, "Done %s.\n", __func__);
}
return rval;
@@ -2882,33 +2860,36 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
scsi_qla_host_t *vp;
unsigned long flags;
+ ql_dbg(ql_dbg_mbx, vha, 0x10b6, "Entered %s.\n", __func__);
+
if (rptid_entry->entry_status != 0)
return;
if (rptid_entry->format == 0) {
- DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
- " number of VPs acquired %d\n", __func__, vha->host_no,
- MSB(le16_to_cpu(rptid_entry->vp_count)),
- LSB(le16_to_cpu(rptid_entry->vp_count))));
- DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__,
- rptid_entry->port_id[2], rptid_entry->port_id[1],
- rptid_entry->port_id[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10b7,
+ "Format 0 : Number of VPs setup %d, number of "
+ "VPs acquired %d.\n",
+ MSB(le16_to_cpu(rptid_entry->vp_count)),
+ LSB(le16_to_cpu(rptid_entry->vp_count)));
+ ql_dbg(ql_dbg_mbx, vha, 0x10b8,
+ "Primary port id %02x%02x%02x.\n",
+ rptid_entry->port_id[2], rptid_entry->port_id[1],
+ rptid_entry->port_id[0]);
} else if (rptid_entry->format == 1) {
vp_idx = LSB(stat);
- DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
- "- status %d - "
- "with port id %02x%02x%02x\n", __func__, vha->host_no,
- vp_idx, MSB(stat),
+ ql_dbg(ql_dbg_mbx, vha, 0x10b9,
+ "Format 1: VP[%d] enabled - status %d - with "
+ "port id %02x%02x%02x.\n", vp_idx, MSB(stat),
rptid_entry->port_id[2], rptid_entry->port_id[1],
- rptid_entry->port_id[0]));
+ rptid_entry->port_id[0]);
vp = vha;
if (vp_idx == 0 && (MSB(stat) != 1))
goto reg_needed;
if (MSB(stat) == 1) {
- DEBUG2(printk("scsi(%ld): Could not acquire ID for "
- "VP[%d].\n", vha->host_no, vp_idx));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ba,
+ "Could not acquire ID for VP[%d].\n", vp_idx);
return;
}
@@ -2963,10 +2944,12 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
/* This can be called by the parent */
+ ql_dbg(ql_dbg_mbx, vha, 0x10bb, "Entered %s.\n", __func__);
+
vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
if (!vpmod) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Modify VP "
- "IOCB.\n", __func__, vha->host_no));
+ ql_log(ql_log_warn, vha, 0x10bc,
+ "Failed to allocate modify VP IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
@@ -2983,22 +2966,21 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
rval = qla2x00_issue_iocb(base_vha, vpmod, vpmod_dma, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue VP config IOCB"
- "(%x).\n", __func__, base_vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10bd,
+ "Failed to issue VP config IOCB (%x).\n", rval);
} else if (vpmod->comp_status != 0) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, base_vha->host_no,
- vpmod->comp_status));
+ ql_dbg(ql_dbg_mbx, vha, 0x10be,
+ "Failed to complete IOCB -- error status (%x).\n",
+ vpmod->comp_status);
rval = QLA_FUNCTION_FAILED;
} else if (vpmod->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- completion status (%x).\n", __func__, base_vha->host_no,
- le16_to_cpu(vpmod->comp_status)));
+ ql_dbg(ql_dbg_mbx, vha, 0x10bf,
+ "Failed to complete IOCB -- completion status (%x).\n",
+ le16_to_cpu(vpmod->comp_status));
rval = QLA_FUNCTION_FAILED;
} else {
/* EMPTY */
- DEBUG11(printk("%s(%ld): done.\n", __func__,
- base_vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10c0, "Done %s.\n", __func__);
fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING);
}
dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma);
@@ -3032,17 +3014,16 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
int vp_index = vha->vp_idx;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- DEBUG11(printk("%s(%ld): entered. Enabling index %d\n", __func__,
- vha->host_no, vp_index));
+ ql_dbg(ql_dbg_mbx, vha, 0x10c1,
+ "Entered %s enabling index %d.\n", __func__, vp_index);
if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
return QLA_PARAMETER_ERROR;
vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
if (!vce) {
- DEBUG2_3(printk("%s(%ld): "
- "failed to allocate VP Control IOCB.\n", __func__,
- base_vha->host_no));
+ ql_log(ql_log_warn, vha, 0x10c2,
+ "Failed to allocate VP control IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx));
@@ -3063,28 +3044,20 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
rval = qla2x00_issue_iocb(base_vha, vce, vce_dma, 0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed to issue VP control IOCB"
- "(%x).\n", __func__, base_vha->host_no, rval));
- printk("%s(%ld): failed to issue VP control IOCB"
- "(%x).\n", __func__, base_vha->host_no, rval);
+ ql_dbg(ql_dbg_mbx, vha, 0x10c3,
+ "Failed to issue VP control IOCB (%x).\n", rval);
} else if (vce->entry_status != 0) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, base_vha->host_no,
- vce->entry_status));
- printk("%s(%ld): failed to complete IOCB "
- "-- error status (%x).\n", __func__, base_vha->host_no,
+ ql_dbg(ql_dbg_mbx, vha, 0x10c4,
+ "Failed to complete IOCB -- error status (%x).\n",
vce->entry_status);
rval = QLA_FUNCTION_FAILED;
} else if (vce->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
- DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
- "-- completion status (%x).\n", __func__, base_vha->host_no,
- le16_to_cpu(vce->comp_status)));
- printk("%s(%ld): failed to complete IOCB "
- "-- completion status (%x).\n", __func__, base_vha->host_no,
+ ql_dbg(ql_dbg_mbx, vha, 0x10c5,
+ "Failed to complet IOCB -- completion status (%x).\n",
le16_to_cpu(vce->comp_status));
rval = QLA_FUNCTION_FAILED;
} else {
- DEBUG2(printk("%s(%ld): done.\n", __func__, base_vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10c6, "Done %s.\n", __func__);
}
dma_pool_free(ha->s_dma_pool, vce, vce_dma);
@@ -3121,6 +3094,8 @@ qla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10c7, "Entered %s.\n", __func__);
+
/*
* This command is implicitly executed by firmware during login for the
* physical hosts
@@ -3155,7 +3130,7 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1009, "Entered %s.\n", __func__);
if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
@@ -3186,10 +3161,10 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1008,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1007, "Done %s.\n", __func__);
}
return rval;
@@ -3214,12 +3189,10 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
unsigned long flags;
struct qla_hw_data *ha = vha->hw;
- DEBUG16(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10c8, "Entered %s.\n", __func__);
mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (mn == NULL) {
- DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
- "IOCB.\n", __func__, vha->host_no));
return QLA_MEMORY_ALLOC_FAILED;
}
@@ -3237,43 +3210,43 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
mn->p.req.entry_count = 1;
mn->p.req.options = cpu_to_le16(options);
- DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
- vha->host_no));
- DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
- sizeof(*mn)));
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c,
+ "Dump of Verify Request.\n");
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e,
+ (uint8_t *)mn, sizeof(*mn));
rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
if (rval != QLA_SUCCESS) {
- DEBUG2_16(printk("%s(%ld): failed to issue Verify "
- "IOCB (%x).\n", __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10cb,
+ "Failed to issue verify IOCB (%x).\n", rval);
goto verify_done;
}
- DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
- vha->host_no));
- DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
- sizeof(*mn)));
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110,
+ "Dump of Verify Response.\n");
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118,
+ (uint8_t *)mn, sizeof(*mn));
status[0] = le16_to_cpu(mn->p.rsp.comp_status);
status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
le16_to_cpu(mn->p.rsp.failure_code) : 0;
- DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
- vha->host_no, status[0], status[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ce,
+ "cs=%x fc=%x.\n", status[0], status[1]);
if (status[0] != CS_COMPLETE) {
rval = QLA_FUNCTION_FAILED;
if (!(options & VCO_DONT_UPDATE_FW)) {
- DEBUG2_16(printk("%s(%ld): Firmware update "
- "failed. Retrying without update "
- "firmware.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10cf,
+ "Firmware update failed. Retrying "
+ "without update firmware.\n");
options |= VCO_DONT_UPDATE_FW;
options &= ~VCO_FORCE_UPDATE;
retry = 1;
}
} else {
- DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
- __func__, vha->host_no,
- le32_to_cpu(mn->p.rsp.fw_ver)));
+ ql_dbg(ql_dbg_mbx, vha, 0x10d0,
+ "Firmware updated to %x.\n",
+ le32_to_cpu(mn->p.rsp.fw_ver));
/* NOTE: we only update OP firmware. */
spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
@@ -3288,10 +3261,9 @@ verify_done:
dma_pool_free(ha->s_dma_pool, mn, mn_dma);
if (rval != QLA_SUCCESS) {
- DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10d1, "Failed=%x.\n", rval);
} else {
- DEBUG16(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10d2, "Done %s.\n", __func__);
}
return rval;
@@ -3307,6 +3279,8 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
struct device_reg_25xxmq __iomem *reg;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x10d3, "Entered %s.\n", __func__);
+
mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
mcp->mb[1] = req->options;
mcp->mb[2] = MSW(LSD(req->dma));
@@ -3344,9 +3318,13 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
rval = qla2x00_mailbox_command(vha, mcp);
- if (rval != QLA_SUCCESS)
- DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x mb0=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0]));
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x10d4,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x10d5, "Done %s.\n", __func__);
+ }
+
return rval;
}
@@ -3360,6 +3338,8 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
struct device_reg_25xxmq __iomem *reg;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x10d6, "Entered %s.\n", __func__);
+
mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
mcp->mb[1] = rsp->options;
mcp->mb[2] = MSW(LSD(rsp->dma));
@@ -3393,10 +3373,13 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
rval = qla2x00_mailbox_command(vha, mcp);
- if (rval != QLA_SUCCESS)
- DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x "
- "mb0=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x10d7,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x10d8, "Done %s.\n", __func__);
+ }
+
return rval;
}
@@ -3407,7 +3390,7 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10d9, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_IDC_ACK;
memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
@@ -3418,10 +3401,10 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10da,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10db, "Done %s.\n", __func__);
}
return rval;
@@ -3434,11 +3417,11 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10dc, "Entered %s.\n", __func__);
+
if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
mcp->out_mb = MBX_1|MBX_0;
@@ -3448,10 +3431,11 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10dd,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10de, "Done %s.\n", __func__);
*sector_size = mcp->mb[1];
}
@@ -3468,7 +3452,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10df, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
@@ -3480,10 +3464,11 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e0,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e1, "Done %s.\n", __func__);
}
return rval;
@@ -3499,7 +3484,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e2, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
@@ -3514,11 +3499,11 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
- "mb[2]=%x.\n", __func__, vha->host_no, rval, mcp->mb[0],
- mcp->mb[1], mcp->mb[2]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e3,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e4, "Done %s.\n", __func__);
}
return rval;
@@ -3531,7 +3516,7 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e5, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_RESTART_MPI_FW;
mcp->out_mb = MBX_0;
@@ -3541,10 +3526,11 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e6,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e7, "Done %s.\n", __func__);
}
return rval;
@@ -3559,11 +3545,11 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x10e8, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
if (len == 1)
opt |= BIT_0;
@@ -3586,10 +3572,10 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
*sfp = mcp->mb[1];
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10e9,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ea, "Done %s.\n", __func__);
}
return rval;
@@ -3604,11 +3590,11 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x10eb, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
if (len == 1)
opt |= BIT_0;
@@ -3631,10 +3617,10 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ec,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ed, "Done %s.\n", __func__);
}
return rval;
@@ -3648,11 +3634,11 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10ee, "Entered %s.\n", __func__);
+
if (!IS_QLA8XXX_TYPE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_GET_XGMAC_STATS;
mcp->mb[2] = MSW(stats_dma);
mcp->mb[3] = LSW(stats_dma);
@@ -3666,11 +3652,12 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x "
- "mb[1]=0x%x mb[2]=0x%x.\n", __func__, vha->host_no, rval,
- mcp->mb[0], mcp->mb[1], mcp->mb[2]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ef,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f0, "Done %s.\n", __func__);
+
*actual_size = mcp->mb[2] << 2;
}
@@ -3686,11 +3673,11 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10f1, "Entered %s.\n", __func__);
+
if (!IS_QLA8XXX_TYPE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_GET_DCBX_PARAMS;
mcp->mb[1] = 0;
mcp->mb[2] = MSW(tlv_dma);
@@ -3705,11 +3692,11 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x "
- "mb[1]=0x%x mb[2]=0x%x.\n", __func__, vha->host_no, rval,
- mcp->mb[0], mcp->mb[1], mcp->mb[2]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f2,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f3, "Done %s.\n", __func__);
}
return rval;
@@ -3722,11 +3709,11 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x10f4, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_READ_RAM_EXTENDED;
mcp->mb[1] = LSW(risc_addr);
mcp->mb[8] = MSW(risc_addr);
@@ -3736,10 +3723,10 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f5,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f6, "Done %s.\n", __func__);
*data = mcp->mb[3] << 16 | mcp->mb[2];
}
@@ -3755,7 +3742,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
mbx_cmd_t *mcp = &mc;
uint32_t iter_cnt = 0x1;
- DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f7, "Entered %s.\n", __func__);
memset(mcp->mb, 0 , sizeof(mcp->mb));
mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
@@ -3794,15 +3781,12 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2(printk(KERN_WARNING
- "(%ld): failed=%x mb[0]=0x%x "
- "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x "
- "mb[19]=0x%x.\n",
- vha->host_no, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
- mcp->mb[3], mcp->mb[18], mcp->mb[19]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f8,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[18]=%x "
+ "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
+ mcp->mb[3], mcp->mb[18], mcp->mb[19]);
} else {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld): done.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10f9, "Done %s.\n", __func__);
}
/* Copy mailbox information */
@@ -3819,7 +3803,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10fa, "Entered %s.\n", __func__);
memset(mcp->mb, 0 , sizeof(mcp->mb));
mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
@@ -3858,12 +3842,11 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2(printk(KERN_WARNING
- "(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
- vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ ql_dbg(ql_dbg_mbx, vha, 0x10fb,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
- DEBUG2(printk(KERN_WARNING
- "scsi(%ld): done.\n", vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10fc, "Done %s.\n", __func__);
}
/* Copy mailbox information */
@@ -3872,14 +3855,14 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
}
int
-qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
+qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG16(printk("%s(%ld): enable_diag=%d entered.\n", __func__,
- ha->host_no, enable_diagnostic));
+ ql_dbg(ql_dbg_mbx, vha, 0x10fd,
+ "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic);
mcp->mb[0] = MBC_ISP84XX_RESET;
mcp->mb[1] = enable_diagnostic;
@@ -3887,13 +3870,12 @@ qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
- rval = qla2x00_mailbox_command(ha, mcp);
+ rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS)
- DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no,
- rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval);
else
- DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ff, "Done %s.\n", __func__);
return rval;
}
@@ -3905,11 +3887,11 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x1100, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_WRITE_RAM_WORD_EXTENDED;
mcp->mb[1] = LSW(risc_addr);
mcp->mb[2] = LSW(data);
@@ -3921,10 +3903,10 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1101,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1102, "Done %s.\n", __func__);
}
return rval;
@@ -3941,8 +3923,7 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
rval = QLA_SUCCESS;
- DEBUG11(qla_printk(KERN_INFO, ha,
- "%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1103, "Entered %s.\n", __func__);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
@@ -3982,11 +3963,10 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
rval = QLA_FUNCTION_FAILED;
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
- __func__, vha->host_no, rval, mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1104,
+ "Failed=%x mb[0]=%x.\n", rval, mb[0]);
} else {
- DEBUG11(printk(KERN_INFO
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1105, "Done %s.\n", __func__);
}
return rval;
@@ -3999,12 +3979,11 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x1106, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(qla_printk(KERN_INFO, ha,
- "%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_DATA_RATE;
mcp->mb[1] = 0;
mcp->out_mb = MBX_1|MBX_0;
@@ -4013,11 +3992,10 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
- __func__, vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1107,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(printk(KERN_INFO
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1108, "Done %s.\n", __func__);
if (mcp->mb[1] != 0x7)
ha->link_data_rate = mcp->mb[1];
}
@@ -4033,8 +4011,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk(KERN_INFO
- "%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1109, "Entered %s.\n", __func__);
if (!IS_QLA81XX(ha))
return QLA_FUNCTION_FAILED;
@@ -4047,15 +4024,13 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): failed=%x (%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x110a,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
/* Copy all bits to preserve original value */
memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
- DEBUG11(printk(KERN_INFO
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x110b, "Done %s.\n", __func__);
}
return rval;
}
@@ -4067,8 +4042,7 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- DEBUG11(printk(KERN_INFO
- "%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x110c, "Entered %s.\n", __func__);
mcp->mb[0] = MBC_SET_PORT_CONFIG;
/* Copy all bits to preserve original setting */
@@ -4080,12 +4054,10 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): failed=%x (%x).\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x110d,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else
- DEBUG11(printk(KERN_INFO
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x110e, "Done %s.\n", __func__);
return rval;
}
@@ -4100,12 +4072,11 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_mbx, vha, 0x110f, "Entered %s.\n", __func__);
+
if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(printk(KERN_INFO
- "%s(%ld): entered.\n", __func__, vha->host_no));
-
mcp->mb[0] = MBC_PORT_PARAMS;
mcp->mb[1] = loop_id;
if (ha->flags.fcp_prio_enabled)
@@ -4127,12 +4098,9 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
}
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): failed=%x.\n", __func__,
- vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval);
} else {
- DEBUG11(printk(KERN_INFO
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10cc, "Done %s.\n", __func__);
}
return rval;
@@ -4145,13 +4113,12 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
uint8_t byte;
struct qla_hw_data *ha = vha->hw;
- DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x10ca, "Entered %s.\n", __func__);
/* Integer part */
rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1, BIT_13|BIT_0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): failed=%x.\n", __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x10c9, "Failed=%x.\n", rval);
ha->flags.thermal_supported = 0;
goto fail;
}
@@ -4160,14 +4127,13 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
/* Fraction part */
rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x10, 1, BIT_13|BIT_0);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(printk(KERN_WARNING
- "%s(%ld): failed=%x.\n", __func__, vha->host_no, rval));
+ ql_dbg(ql_dbg_mbx, vha, 0x1019, "Failed=%x.\n", rval);
ha->flags.thermal_supported = 0;
goto fail;
}
*frac = (byte >> 6) * 25;
- DEBUG11(printk(KERN_INFO "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1018, "Done %s.\n", __func__);
fail:
return rval;
}
@@ -4180,12 +4146,11 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x1017, "Entered %s.\n", __func__);
+
if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(qla_printk(KERN_INFO, ha,
- "%s(%ld): entered.\n", __func__, vha->host_no));
-
memset(mcp, 0, sizeof(mbx_cmd_t));
mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
mcp->mb[1] = 1;
@@ -4197,12 +4162,10 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
- "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x1016,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(qla_printk(KERN_INFO, ha,
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x100e, "Done %s.\n", __func__);
}
return rval;
@@ -4216,12 +4179,11 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ ql_dbg(ql_dbg_mbx, vha, 0x100d, "Entered %s.\n", __func__);
+
if (!IS_QLA82XX(ha))
return QLA_FUNCTION_FAILED;
- DEBUG11(qla_printk(KERN_INFO, ha,
- "%s(%ld): entered.\n", __func__, vha->host_no));
-
memset(mcp, 0, sizeof(mbx_cmd_t));
mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
mcp->mb[1] = 0;
@@ -4233,12 +4195,137 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
- "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
- vha->host_no, rval, mcp->mb[0]));
+ ql_dbg(ql_dbg_mbx, vha, 0x100c,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x100b, "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+int
+qla82xx_md_get_template_size(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ int rval = QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x111f, "Entered %s.\n", __func__);
+
+ memset(mcp->mb, 0 , sizeof(mcp->mb));
+ mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[2] = LSW(RQST_TMPLT_SIZE);
+ mcp->mb[3] = MSW(RQST_TMPLT_SIZE);
+
+ mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
+ MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+
+ mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
+ mcp->tov = MBX_TOV_SECONDS;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ /* Always copy back return mailbox values. */
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1120,
+ "mailbox command FAILED=0x%x, subcode=%x.\n",
+ (mcp->mb[1] << 16) | mcp->mb[0],
+ (mcp->mb[3] << 16) | mcp->mb[2]);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x1121, "Done %s.\n", __func__);
+ ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]);
+ if (!ha->md_template_size) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1122,
+ "Null template size obtained.\n");
+ rval = QLA_FUNCTION_FAILED;
+ }
+ }
+ return rval;
+}
+
+int
+qla82xx_md_get_template(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ int rval = QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1123, "Entered %s.\n", __func__);
+
+ ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev,
+ ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL);
+ if (!ha->md_tmplt_hdr) {
+ ql_log(ql_log_warn, vha, 0x1124,
+ "Unable to allocate memory for Minidump template.\n");
+ return rval;
+ }
+
+ memset(mcp->mb, 0 , sizeof(mcp->mb));
+ mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[2] = LSW(RQST_TMPLT);
+ mcp->mb[3] = MSW(RQST_TMPLT);
+ mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[8] = LSW(ha->md_template_size);
+ mcp->mb[9] = MSW(ha->md_template_size);
+
+ mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8|
+ MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1125,
+ "mailbox command FAILED=0x%x, subcode=%x.\n",
+ ((mcp->mb[1] << 16) | mcp->mb[0]),
+ ((mcp->mb[3] << 16) | mcp->mb[2]));
+ } else
+ ql_dbg(ql_dbg_mbx, vha, 0x1126, "Done %s.\n", __func__);
+ return rval;
+}
+
+int
+qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable)
+{
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA82XX(ha))
+ return QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1127,
+ "Entered %s.\n", __func__);
+
+ memset(mcp, 0, sizeof(mbx_cmd_t));
+ mcp->mb[0] = MBC_SET_LED_CONFIG;
+ if (enable)
+ mcp->mb[7] = 0xE;
+ else
+ mcp->mb[7] = 0xD;
+
+ mcp->out_mb = MBX_7|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = 30;
+ mcp->flags = 0;
+
+ rval = qla2x00_mailbox_command(vha, mcp);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1128,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
- DEBUG11(qla_printk(KERN_INFO, ha,
- "%s(%ld): done.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_mbx, vha, 0x1129,
+ "Done %s.\n", __func__);
}
return rval;
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 5e34391..f488cc6 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -36,8 +36,9 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
mutex_lock(&ha->vport_lock);
vp_id = find_first_zero_bit(ha->vp_idx_map, ha->max_npiv_vports + 1);
if (vp_id > ha->max_npiv_vports) {
- DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n",
- vp_id, ha->max_npiv_vports));
+ ql_dbg(ql_dbg_vport, vha, 0xa000,
+ "vp_id %d is bigger than max-supported %d.\n",
+ vp_id, ha->max_npiv_vports);
mutex_unlock(&ha->vport_lock);
return vp_id;
}
@@ -131,9 +132,9 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
fc_port_t *fcport;
list_for_each_entry(fcport, &vha->vp_fcports, list) {
- DEBUG15(printk("scsi(%ld): Marking port dead, "
- "loop_id=0x%04x :%x\n",
- vha->host_no, fcport->loop_id, fcport->vp_idx));
+ ql_dbg(ql_dbg_vport, vha, 0xa001,
+ "Marking port dead, loop_id=0x%04x : %x.\n",
+ fcport->loop_id, fcport->vp_idx);
qla2x00_mark_device_lost(vha, fcport, 0, 0);
qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
@@ -187,13 +188,13 @@ qla24xx_enable_vp(scsi_qla_host_t *vha)
goto enable_failed;
}
- DEBUG15(qla_printk(KERN_INFO, ha,
- "Virtual port with id: %d - Enabled\n", vha->vp_idx));
+ ql_dbg(ql_dbg_taskm, vha, 0x801a,
+ "Virtual port with id: %d - Enabled.\n", vha->vp_idx);
return 0;
enable_failed:
- DEBUG15(qla_printk(KERN_INFO, ha,
- "Virtual port with id: %d - Disabled\n", vha->vp_idx));
+ ql_dbg(ql_dbg_taskm, vha, 0x801b,
+ "Virtual port with id: %d - Disabled.\n", vha->vp_idx);
return 1;
}
@@ -205,12 +206,12 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
fc_vport = vha->fc_vport;
- DEBUG15(printk("scsi(%ld): %s: change request #3 for this host.\n",
- vha->host_no, __func__));
+ ql_dbg(ql_dbg_vport, vha, 0xa002,
+ "%s: change request #3.\n", __func__);
ret = qla2x00_send_change_request(vha, 0x3, vha->vp_idx);
if (ret != QLA_SUCCESS) {
- DEBUG15(qla_printk(KERN_ERR, vha->hw, "Failed to enable "
- "receiving of RSCN requests: 0x%x\n", ret));
+ ql_dbg(ql_dbg_vport, vha, 0xa003, "Failed to enable "
+ "receiving of RSCN requests: 0x%x.\n", ret);
return;
} else {
/* Corresponds to SCR enabled */
@@ -248,9 +249,9 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
case MBA_CHG_IN_CONNECTION:
case MBA_PORT_UPDATE:
case MBA_RSCN_UPDATE:
- DEBUG15(printk("scsi(%ld)%s: Async_event for"
- " VP[%d], mb = 0x%x, vha=%p\n",
- vha->host_no, __func__, i, *mb, vha));
+ ql_dbg(ql_dbg_async, vha, 0x5024,
+ "Async_event for VP[%d], mb=0x%x vha=%p.\n",
+ i, *mb, vha);
qla2x00_async_event(vha, rsp, mb);
break;
}
@@ -286,37 +287,49 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
- DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n",
- vha->host_no, vha->vp_idx));
+ ql_dbg(ql_dbg_taskm, vha, 0x801d,
+ "Scheduling enable of Vport %d.\n", vha->vp_idx);
return qla24xx_enable_vp(vha);
}
static int
qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
{
+ ql_dbg(ql_dbg_dpc, vha, 0x4012,
+ "Entering %s.\n", __func__);
+ ql_dbg(ql_dbg_dpc, vha, 0x4013,
+ "vp_flags: 0x%lx.\n", vha->vp_flags);
+
qla2x00_do_work(vha);
if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
/* VP acquired. complete port configuration */
+ ql_dbg(ql_dbg_dpc, vha, 0x4014,
+ "Configure VP scheduled.\n");
qla24xx_configure_vp(vha);
+ ql_dbg(ql_dbg_dpc, vha, 0x4015,
+ "Configure VP end.\n");
return 0;
}
if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) {
+ ql_dbg(ql_dbg_dpc, vha, 0x4016,
+ "FCPort update scheduled.\n");
qla2x00_update_fcports(vha);
clear_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags);
+ ql_dbg(ql_dbg_dpc, vha, 0x4017,
+ "FCPort update end.\n");
}
if ((test_and_clear_bit(RELOGIN_NEEDED, &vha->dpc_flags)) &&
!test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) &&
atomic_read(&vha->loop_state) != LOOP_DOWN) {
- DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
- vha->host_no));
+ ql_dbg(ql_dbg_dpc, vha, 0x4018,
+ "Relogin needed scheduled.\n");
qla2x00_relogin(vha);
-
- DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
- vha->host_no));
+ ql_dbg(ql_dbg_dpc, vha, 0x4019,
+ "Relogin needed end.\n");
}
if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) &&
@@ -326,11 +339,17 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) {
+ ql_dbg(ql_dbg_dpc, vha, 0x401a,
+ "Loop resync scheduled.\n");
qla2x00_loop_resync(vha);
clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags);
+ ql_dbg(ql_dbg_dpc, vha, 0x401b,
+ "Loop resync end.\n");
}
}
+ ql_dbg(ql_dbg_dpc, vha, 0x401c,
+ "Exiting %s.\n", __func__);
return 0;
}
@@ -396,9 +415,10 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
/* Check up max-npiv-supports */
if (ha->num_vhosts > ha->max_npiv_vports) {
- DEBUG15(printk("scsi(%ld): num_vhosts %ud is bigger than "
- "max_npv_vports %ud.\n", base_vha->host_no,
- ha->num_vhosts, ha->max_npiv_vports));
+ ql_dbg(ql_dbg_vport, vha, 0xa004,
+ "num_vhosts %ud is bigger "
+ "than max_npiv_vports %ud.\n",
+ ha->num_vhosts, ha->max_npiv_vports);
return VPCERR_UNSUPPORTED;
}
return 0;
@@ -415,7 +435,8 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha = qla2x00_create_host(sht, ha);
if (!vha) {
- DEBUG(printk("qla2xxx: scsi_host_alloc() failed for vport\n"));
+ ql_log(ql_log_warn, vha, 0xa005,
+ "scsi_host_alloc() failed for vport.\n");
return(NULL);
}
@@ -429,8 +450,8 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha->device_flags = 0;
vha->vp_idx = qla24xx_allocate_vp_id(vha);
if (vha->vp_idx > ha->max_npiv_vports) {
- DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
- vha->host_no));
+ ql_dbg(ql_dbg_vport, vha, 0xa006,
+ "Couldn't allocate vp_id.\n");
goto create_vhost_failed;
}
vha->mgmt_svr_loop_id = 10 + vha->vp_idx;
@@ -451,7 +472,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
host->can_queue = base_vha->req->length + 128;
host->this_id = 255;
host->cmd_per_lun = 3;
- if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif)
+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif)
host->max_cmd_len = 32;
else
host->max_cmd_len = MAX_CMDSZ;
@@ -461,8 +482,9 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
host->max_id = MAX_TARGETS_2200;
host->transportt = qla2xxx_transport_vport_template;
- DEBUG15(printk("DEBUG: detect vport hba %ld at address = %p\n",
- vha->host_no, vha));
+ ql_dbg(ql_dbg_vport, vha, 0xa007,
+ "Detect vport hba %ld at address = %p.\n",
+ vha->host_no, vha);
vha->flags.init_done = 1;
@@ -567,9 +589,9 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
if (req) {
ret = qla25xx_delete_req_que(vha, req);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Couldn't delete req que %d\n",
- req->id);
+ ql_log(ql_log_warn, vha, 0x00ea,
+ "Couldn't delete req que %d.\n",
+ req->id);
return ret;
}
}
@@ -581,9 +603,9 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
if (rsp) {
ret = qla25xx_delete_rsp_que(vha, rsp);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Couldn't delete rsp que %d\n",
- rsp->id);
+ ql_log(ql_log_warn, vha, 0x00eb,
+ "Couldn't delete rsp que %d.\n",
+ rsp->id);
return ret;
}
}
@@ -604,8 +626,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
if (req == NULL) {
- qla_printk(KERN_WARNING, ha, "could not allocate memory"
- "for request que\n");
+ ql_log(ql_log_fatal, base_vha, 0x00d9,
+ "Failed to allocate memory for request queue.\n");
goto failed;
}
@@ -614,8 +636,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
(req->length + 1) * sizeof(request_t),
&req->dma, GFP_KERNEL);
if (req->ring == NULL) {
- qla_printk(KERN_WARNING, ha,
- "Memory Allocation failed - request_ring\n");
+ ql_log(ql_log_fatal, base_vha, 0x00da,
+ "Failed to allocte memory for request_ring.\n");
goto que_failed;
}
@@ -623,8 +645,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
que_id = find_first_zero_bit(ha->req_qid_map, ha->max_req_queues);
if (que_id >= ha->max_req_queues) {
mutex_unlock(&ha->vport_lock);
- qla_printk(KERN_INFO, ha, "No resources to create "
- "additional request queue\n");
+ ql_log(ql_log_warn, base_vha, 0x00db,
+ "No resources to create additional request queue.\n");
goto que_failed;
}
set_bit(que_id, ha->req_qid_map);
@@ -633,6 +655,12 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->vp_idx = vp_idx;
req->qos = qos;
+ ql_dbg(ql_dbg_multiq, base_vha, 0xc002,
+ "queue_id=%d rid=%d vp_idx=%d qos=%d.\n",
+ que_id, req->rid, req->vp_idx, req->qos);
+ ql_dbg(ql_dbg_init, base_vha, 0x00dc,
+ "queue_id=%d rid=%d vp_idx=%d qos=%d.\n",
+ que_id, req->rid, req->vp_idx, req->qos);
if (rsp_que < 0)
req->rsp = NULL;
else
@@ -645,6 +673,10 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
options |= BIT_5;
req->options = options;
+ ql_dbg(ql_dbg_multiq, base_vha, 0xc003,
+ "options=0x%x.\n", req->options);
+ ql_dbg(ql_dbg_init, base_vha, 0x00dd,
+ "options=0x%x.\n", req->options);
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
req->outstanding_cmds[cnt] = NULL;
req->current_outstanding_cmd = 1;
@@ -656,10 +688,21 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
reg = ISP_QUE_REG(ha, que_id);
req->max_q_depth = ha->req_q_map[0]->max_q_depth;
mutex_unlock(&ha->vport_lock);
+ ql_dbg(ql_dbg_multiq, base_vha, 0xc004,
+ "ring_ptr=%p ring_index=%d, "
+ "cnt=%d id=%d max_q_depth=%d.\n",
+ req->ring_ptr, req->ring_index,
+ req->cnt, req->id, req->max_q_depth);
+ ql_dbg(ql_dbg_init, base_vha, 0x00de,
+ "ring_ptr=%p ring_index=%d, "
+ "cnt=%d id=%d max_q_depth=%d.\n",
+ req->ring_ptr, req->ring_index, req->cnt,
+ req->id, req->max_q_depth);
ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
+ ql_log(ql_log_fatal, base_vha, 0x00df,
+ "%s failed.\n", __func__);
mutex_lock(&ha->vport_lock);
clear_bit(que_id, ha->req_qid_map);
mutex_unlock(&ha->vport_lock);
@@ -700,8 +743,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
if (rsp == NULL) {
- qla_printk(KERN_WARNING, ha, "could not allocate memory for"
- " response que\n");
+ ql_log(ql_log_warn, base_vha, 0x0066,
+ "Failed to allocate memory for response queue.\n");
goto failed;
}
@@ -710,8 +753,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
(rsp->length + 1) * sizeof(response_t),
&rsp->dma, GFP_KERNEL);
if (rsp->ring == NULL) {
- qla_printk(KERN_WARNING, ha,
- "Memory Allocation failed - response_ring\n");
+ ql_log(ql_log_warn, base_vha, 0x00e1,
+ "Failed to allocate memory for response ring.\n");
goto que_failed;
}
@@ -719,8 +762,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
que_id = find_first_zero_bit(ha->rsp_qid_map, ha->max_rsp_queues);
if (que_id >= ha->max_rsp_queues) {
mutex_unlock(&ha->vport_lock);
- qla_printk(KERN_INFO, ha, "No resources to create "
- "additional response queue\n");
+ ql_log(ql_log_warn, base_vha, 0x00e2,
+ "No resources to create additional request queue.\n");
goto que_failed;
}
set_bit(que_id, ha->rsp_qid_map);
@@ -728,12 +771,16 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
if (ha->flags.msix_enabled)
rsp->msix = &ha->msix_entries[que_id + 1];
else
- qla_printk(KERN_WARNING, ha, "msix not enabled\n");
+ ql_log(ql_log_warn, base_vha, 0x00e3,
+ "MSIX not enalbled.\n");
ha->rsp_q_map[que_id] = rsp;
rsp->rid = rid;
rsp->vp_idx = vp_idx;
rsp->hw = ha;
+ ql_dbg(ql_dbg_init, base_vha, 0x00e4,
+ "queue_id=%d rid=%d vp_idx=%d hw=%p.\n",
+ que_id, rsp->rid, rsp->vp_idx, rsp->hw);
/* Use alternate PCI bus number */
if (MSB(rsp->rid))
options |= BIT_4;
@@ -750,6 +797,14 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
rsp->rsp_q_in = &reg->isp25mq.rsp_q_in;
rsp->rsp_q_out = &reg->isp25mq.rsp_q_out;
mutex_unlock(&ha->vport_lock);
+ ql_dbg(ql_dbg_multiq, base_vha, 0xc00b,
+ "options=%x id=%d rsp_q_in=%p rsp_q_out=%p",
+ rsp->options, rsp->id, rsp->rsp_q_in,
+ rsp->rsp_q_out);
+ ql_dbg(ql_dbg_init, base_vha, 0x00e5,
+ "options=%x id=%d rsp_q_in=%p rsp_q_out=%p",
+ rsp->options, rsp->id, rsp->rsp_q_in,
+ rsp->rsp_q_out);
ret = qla25xx_request_irq(rsp);
if (ret)
@@ -757,7 +812,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
+ ql_log(ql_log_fatal, base_vha, 0x00e7,
+ "%s failed.\n", __func__);
mutex_lock(&ha->vport_lock);
clear_bit(que_id, ha->rsp_qid_map);
mutex_unlock(&ha->vport_lock);
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index e1138bc..0355493 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -7,6 +7,8 @@
#include "qla_def.h"
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/ratelimit.h>
+#include <linux/vmalloc.h>
#include <scsi/scsi_tcq.h>
#define MASK(n) ((1ULL<<(n))-1)
@@ -328,7 +330,7 @@ unsigned qla82xx_crb_hub_agt[64] = {
};
/* Device states */
-char *qdev_state[] = {
+char *q_dev_state[] = {
"Unknown",
"Cold",
"Initializing",
@@ -339,6 +341,11 @@ char *qdev_state[] = {
"Quiescent",
};
+char *qdev_state(uint32_t dev_state)
+{
+ return q_dev_state[dev_state];
+}
+
/*
* In: 'off' is offset from CRB space in 128M pci map
* Out: 'off' is 2M pci map addr
@@ -348,6 +355,7 @@ static void
qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
{
u32 win_read;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
ha->crb_win = CRB_HI(*off);
writel(ha->crb_win,
@@ -358,9 +366,10 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
*/
win_read = RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
if (win_read != ha->crb_win) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "%s: Written crbwin (0x%x) != Read crbwin (0x%x), "
- "off=0x%lx\n", __func__, ha->crb_win, win_read, *off));
+ ql_dbg(ql_dbg_p3p, vha, 0xb000,
+ "%s: Written crbwin (0x%x) "
+ "!= Read crbwin (0x%x), off=0x%lx.\n",
+ ha->crb_win, win_read, *off);
}
*off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
}
@@ -368,6 +377,7 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
static inline unsigned long
qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
/* See if we are currently pointing to the region we want to use next */
if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_DDR_NET)) {
/* No need to change window. PCIX and PCIEregs are in both
@@ -398,9 +408,10 @@ qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off)
return off;
}
/* strange address given */
- qla_printk(KERN_WARNING, ha,
- "%s: Warning: unm_nic_pci_set_crbwindow called with"
- " an unknown address(%llx)\n", QLA2XXX_DRIVER_NAME, off);
+ ql_dbg(ql_dbg_p3p, vha, 0xb001,
+ "%x: Warning: unm_nic_pci_set_crbwindow "
+ "called with an unknown address(%llx).\n",
+ QLA2XXX_DRIVER_NAME, off);
return off;
}
@@ -563,6 +574,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
{
int window;
u32 win_read;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET,
QLA82XX_ADDR_DDR_NET_MAX)) {
@@ -574,8 +586,8 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
win_read = qla82xx_rd_32(ha,
ha->mn_win_crb | QLA82XX_PCI_CRBSPACE);
if ((win_read << 17) != window) {
- qla_printk(KERN_WARNING, ha,
- "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",
+ ql_dbg(ql_dbg_p3p, vha, 0xb003,
+ "%s: Written MNwin (0x%x) != Read MNwin (0x%x).\n",
__func__, window, win_read);
}
addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET;
@@ -583,7 +595,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
QLA82XX_ADDR_OCM0_MAX)) {
unsigned int temp1;
if ((addr & 0x00ff800) == 0xff800) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0xb004,
"%s: QM access not handled.\n", __func__);
addr = -1UL;
}
@@ -596,8 +608,8 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
temp1 = ((window & 0x1FF) << 7) |
((window & 0x0FFFE0000) >> 17);
if (win_read != temp1) {
- qla_printk(KERN_WARNING, ha,
- "%s: Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
+ ql_log(ql_log_warn, vha, 0xb005,
+ "%s: Written OCMwin (0x%x) != Read OCMwin (0x%x).\n",
__func__, temp1, win_read);
}
addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M;
@@ -612,8 +624,8 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
win_read = qla82xx_rd_32(ha,
ha->ms_win_crb | QLA82XX_PCI_CRBSPACE);
if (win_read != window) {
- qla_printk(KERN_WARNING, ha,
- "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n",
+ ql_log(ql_log_warn, vha, 0xb006,
+ "%s: Written MSwin (0x%x) != Read MSwin (0x%x).\n",
__func__, window, win_read);
}
addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET;
@@ -624,9 +636,9 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
*/
if ((qla82xx_pci_set_window_warning_count++ < 8) ||
(qla82xx_pci_set_window_warning_count%64 == 0)) {
- qla_printk(KERN_WARNING, ha,
- "%s: Warning:%s Unknown address range!\n", __func__,
- QLA2XXX_DRIVER_NAME);
+ ql_log(ql_log_warn, vha, 0xb007,
+ "%s: Warning:%s Unknown address range!.\n",
+ __func__, QLA2XXX_DRIVER_NAME);
}
addr = -1UL;
}
@@ -671,6 +683,7 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
uint8_t *mem_ptr = NULL;
unsigned long mem_base;
unsigned long mem_page;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
write_lock_irqsave(&ha->hw_lock, flags);
@@ -682,9 +695,10 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
if ((start == -1UL) ||
(qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
write_unlock_irqrestore(&ha->hw_lock, flags);
- qla_printk(KERN_ERR, ha,
- "%s out of bound pci memory access. "
- "offset is 0x%llx\n", QLA2XXX_DRIVER_NAME, off);
+ ql_log(ql_log_fatal, vha, 0xb008,
+ "%s out of bound pci memory "
+ "access, offset is 0x%llx.\n",
+ QLA2XXX_DRIVER_NAME, off);
return -1;
}
@@ -741,6 +755,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
uint8_t *mem_ptr = NULL;
unsigned long mem_base;
unsigned long mem_page;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
write_lock_irqsave(&ha->hw_lock, flags);
@@ -752,9 +767,10 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
if ((start == -1UL) ||
(qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
write_unlock_irqrestore(&ha->hw_lock, flags);
- qla_printk(KERN_ERR, ha,
- "%s out of bound pci memory access. "
- "offset is 0x%llx\n", QLA2XXX_DRIVER_NAME, off);
+ ql_log(ql_log_fatal, vha, 0xb009,
+ "%s out of bount memory "
+ "access, offset is 0x%llx.\n",
+ QLA2XXX_DRIVER_NAME, off);
return -1;
}
@@ -855,15 +871,16 @@ qla82xx_wait_rom_busy(struct qla_hw_data *ha)
{
long timeout = 0;
long done = 0 ;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
while (done == 0) {
done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);
done &= 4;
timeout++;
if (timeout >= rom_max_timeout) {
- DEBUG(qla_printk(KERN_INFO, ha,
- "%s: Timeout reached waiting for rom busy",
- QLA2XXX_DRIVER_NAME));
+ ql_dbg(ql_dbg_p3p, vha, 0xb00a,
+ "%s: Timeout reached waiting for rom busy.\n",
+ QLA2XXX_DRIVER_NAME);
return -1;
}
}
@@ -875,15 +892,16 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha)
{
long timeout = 0;
long done = 0 ;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
while (done == 0) {
done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);
done &= 2;
timeout++;
if (timeout >= rom_max_timeout) {
- DEBUG(qla_printk(KERN_INFO, ha,
- "%s: Timeout reached waiting for rom done",
- QLA2XXX_DRIVER_NAME));
+ ql_dbg(ql_dbg_p3p, vha, 0xb00b,
+ "%s: Timeout reached waiting for rom done.\n",
+ QLA2XXX_DRIVER_NAME);
return -1;
}
}
@@ -893,15 +911,16 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha)
static int
qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb);
qla82xx_wait_rom_busy(ha);
if (qla82xx_wait_rom_done(ha)) {
- qla_printk(KERN_WARNING, ha,
- "%s: Error waiting for rom done\n",
- QLA2XXX_DRIVER_NAME);
+ ql_log(ql_log_fatal, vha, 0x00ba,
+ "Error waiting for rom done.\n");
return -1;
}
/* Reset abyte_cnt and dummy_byte_cnt */
@@ -917,6 +936,7 @@ static int
qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
{
int ret, loops = 0;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) {
udelay(100);
@@ -924,9 +944,8 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
loops++;
}
if (loops >= 50000) {
- qla_printk(KERN_INFO, ha,
- "%s: qla82xx_rom_lock failed\n",
- QLA2XXX_DRIVER_NAME);
+ ql_log(ql_log_fatal, vha, 0x00b9,
+ "Failed to aquire SEM2 lock.\n");
return -1;
}
ret = qla82xx_do_rom_fast_read(ha, addr, valp);
@@ -937,11 +956,12 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
static int
qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR);
qla82xx_wait_rom_busy(ha);
if (qla82xx_wait_rom_done(ha)) {
- qla_printk(KERN_WARNING, ha,
- "Error waiting for rom done\n");
+ ql_log(ql_log_warn, vha, 0xb00c,
+ "Error waiting for rom done.\n");
return -1;
}
*val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA);
@@ -955,6 +975,7 @@ qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
uint32_t done = 1 ;
uint32_t val;
int ret = 0;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
while ((done != 0) && (ret == 0)) {
@@ -964,8 +985,8 @@ qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
udelay(10);
cond_resched();
if (timeout >= 50000) {
- qla_printk(KERN_WARNING, ha,
- "Timeout reached waiting for write finish");
+ ql_log(ql_log_warn, vha, 0xb00d,
+ "Timeout reached waiting for write finish.\n");
return -1;
}
}
@@ -992,13 +1013,14 @@ qla82xx_flash_set_write_enable(struct qla_hw_data *ha)
static int
qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
if (qla82xx_flash_set_write_enable(ha))
return -1;
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, val);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0x1);
if (qla82xx_wait_rom_done(ha)) {
- qla_printk(KERN_WARNING, ha,
- "Error waiting for rom done\n");
+ ql_log(ql_log_warn, vha, 0xb00e,
+ "Error waiting for rom done.\n");
return -1;
}
return qla82xx_flash_wait_write_finish(ha);
@@ -1007,10 +1029,11 @@ qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
static int
qla82xx_write_disable_flash(struct qla_hw_data *ha)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI);
if (qla82xx_wait_rom_done(ha)) {
- qla_printk(KERN_WARNING, ha,
- "Error waiting for rom done\n");
+ ql_log(ql_log_warn, vha, 0xb00f,
+ "Error waiting for rom done.\n");
return -1;
}
return 0;
@@ -1020,13 +1043,16 @@ static int
ql82xx_rom_lock_d(struct qla_hw_data *ha)
{
int loops = 0;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) {
udelay(100);
cond_resched();
loops++;
}
if (loops >= 50000) {
- qla_printk(KERN_WARNING, ha, "ROM lock failed\n");
+ ql_log(ql_log_warn, vha, 0xb010,
+ "ROM lock failed.\n");
return -1;
}
return 0;;
@@ -1037,10 +1063,12 @@ qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
uint32_t data)
{
int ret = 0;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
ret = ql82xx_rom_lock_d(ha);
if (ret < 0) {
- qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+ ql_log(ql_log_warn, vha, 0xb011,
+ "ROM lock failed.\n");
return ret;
}
@@ -1053,8 +1081,8 @@ qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_PP);
qla82xx_wait_rom_busy(ha);
if (qla82xx_wait_rom_done(ha)) {
- qla_printk(KERN_WARNING, ha,
- "Error waiting for rom done\n");
+ ql_log(ql_log_warn, vha, 0xb012,
+ "Error waiting for rom done.\n");
ret = -1;
goto done_write;
}
@@ -1159,8 +1187,8 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
*/
if (qla82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL ||
qla82xx_rom_fast_read(ha, 4, &n) != 0) {
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Reading crb_init area: n: %08x\n", n);
+ ql_log(ql_log_fatal, vha, 0x006e,
+ "Error Reading crb_init area: n: %08x.\n", n);
return -1;
}
@@ -1172,20 +1200,18 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
/* number of addr/value pair should not exceed 1024 enteries */
if (n >= 1024) {
- qla_printk(KERN_WARNING, ha,
- "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n",
- QLA2XXX_DRIVER_NAME, __func__, n);
+ ql_log(ql_log_fatal, vha, 0x0071,
+ "Card flash not initialized:n=0x%x.\n", n);
return -1;
}
- qla_printk(KERN_INFO, ha,
- "%s: %d CRB init values found in ROM.\n", QLA2XXX_DRIVER_NAME, n);
+ ql_log(ql_log_info, vha, 0x0072,
+ "%d CRB init values found in ROM.\n", n);
buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL);
if (buf == NULL) {
- qla_printk(KERN_WARNING, ha,
- "%s: [ERROR] Unable to malloc memory.\n",
- QLA2XXX_DRIVER_NAME);
+ ql_log(ql_log_fatal, vha, 0x010c,
+ "Unable to allocate memory.\n");
return -1;
}
@@ -1236,9 +1262,8 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
continue;
if (off == ADDR_ERROR) {
- qla_printk(KERN_WARNING, ha,
- "%s: [ERROR] Unknown addr: 0x%08lx\n",
- QLA2XXX_DRIVER_NAME, buf[i].addr);
+ ql_log(ql_log_fatal, vha, 0x0116,
+ "Unknow addr: 0x%08lx.\n", buf[i].addr);
continue;
}
@@ -1370,7 +1395,7 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
if (j >= MAX_CTL_CHECK) {
if (printk_ratelimit())
dev_err(&ha->pdev->dev,
- "failed to write through agent\n");
+ "failed to write through agent.\n");
ret = -1;
break;
}
@@ -1460,7 +1485,7 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha,
if (j >= MAX_CTL_CHECK) {
if (printk_ratelimit())
dev_err(&ha->pdev->dev,
- "failed to read through agent\n");
+ "failed to read through agent.\n");
break;
}
@@ -1633,17 +1658,15 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
uint32_t len = 0;
if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) {
- qla_printk(KERN_WARNING, ha,
- "Failed to reserve selected regions (%s)\n",
- pci_name(ha->pdev));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x000c,
+ "Failed to reserver selected regions.\n");
goto iospace_error_exit;
}
/* Use MMIO operations for all accesses. */
if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) {
- qla_printk(KERN_ERR, ha,
- "region #0 not an MMIO resource (%s), aborting\n",
- pci_name(ha->pdev));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x000d,
+ "Region #0 not an MMIO resource, aborting.\n");
goto iospace_error_exit;
}
@@ -1651,9 +1674,8 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
ha->nx_pcibase =
(unsigned long)ioremap(pci_resource_start(ha->pdev, 0), len);
if (!ha->nx_pcibase) {
- qla_printk(KERN_ERR, ha,
- "cannot remap pcibase MMIO (%s), aborting\n",
- pci_name(ha->pdev));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x000e,
+ "Cannot remap pcibase MMIO, aborting.\n");
pci_release_regions(ha->pdev);
goto iospace_error_exit;
}
@@ -1667,9 +1689,8 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
(unsigned long)ioremap((pci_resource_start(ha->pdev, 4) +
(ha->pdev->devfn << 12)), 4);
if (!ha->nxdb_wr_ptr) {
- qla_printk(KERN_ERR, ha,
- "cannot remap MMIO (%s), aborting\n",
- pci_name(ha->pdev));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x000f,
+ "Cannot remap MMIO, aborting.\n");
pci_release_regions(ha->pdev);
goto iospace_error_exit;
}
@@ -1687,6 +1708,16 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
ha->max_req_queues = ha->max_rsp_queues = 1;
ha->msix_count = ha->max_rsp_queues + 1;
+ ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc006,
+ "nx_pci_base=%p iobase=%p "
+ "max_req_queues=%d msix_count=%d.\n",
+ ha->nx_pcibase, ha->iobase,
+ ha->max_req_queues, ha->msix_count);
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0010,
+ "nx_pci_base=%p iobase=%p "
+ "max_req_queues=%d msix_count=%d.\n",
+ ha->nx_pcibase, ha->iobase,
+ ha->max_req_queues, ha->msix_count);
return 0;
iospace_error_exit:
@@ -1712,6 +1743,9 @@ qla82xx_pci_config(scsi_qla_host_t *vha)
pci_set_master(ha->pdev);
ret = pci_set_mwi(ha->pdev);
ha->chip_revision = ha->pdev->revision;
+ ql_dbg(ql_dbg_init, vha, 0x0043,
+ "Chip revision:%ld.\n",
+ ha->chip_revision);
return 0;
}
@@ -1877,6 +1911,7 @@ qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
{
u32 val = 0;
int retries = 60;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
do {
read_lock(&ha->hw_lock);
@@ -1892,15 +1927,15 @@ qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
default:
break;
}
- qla_printk(KERN_WARNING, ha,
- "CRB_CMDPEG_STATE: 0x%x and retries: 0x%x\n",
- val, retries);
+ ql_log(ql_log_info, vha, 0x00a8,
+ "CRB_CMDPEG_STATE: 0x%x and retries:0x%x.\n",
+ val, retries);
msleep(500);
} while (--retries);
- qla_printk(KERN_INFO, ha,
+ ql_log(ql_log_fatal, vha, 0x00a9,
"Cmd Peg initialization failed: 0x%x.\n", val);
val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE);
@@ -1915,6 +1950,7 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
{
u32 val = 0;
int retries = 60;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
do {
read_lock(&ha->hw_lock);
@@ -1930,17 +1966,16 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
default:
break;
}
-
- qla_printk(KERN_WARNING, ha,
- "CRB_RCVPEG_STATE: 0x%x and retries: 0x%x\n",
- val, retries);
+ ql_log(ql_log_info, vha, 0x00ab,
+ "CRB_RCVPEG_STATE: 0x%x and retries: 0x%x.\n",
+ val, retries);
msleep(500);
} while (--retries);
- qla_printk(KERN_INFO, ha,
- "Rcv Peg initialization failed: 0x%x.\n", val);
+ ql_log(ql_log_fatal, vha, 0x00ac,
+ "Rcv Peg initializatin failed: 0x%x.\n", val);
read_lock(&ha->hw_lock);
qla82xx_wr_32(ha, CRB_RCVPEG_STATE, PHAN_INITIALIZE_FAILED);
read_unlock(&ha->hw_lock);
@@ -1989,13 +2024,11 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
}
if (ha->mcp) {
- DEBUG3_11(printk(KERN_INFO "%s(%ld): "
- "Got mailbox completion. cmd=%x.\n",
- __func__, vha->host_no, ha->mcp->mb[0]));
+ ql_dbg(ql_dbg_async, vha, 0x5052,
+ "Got mailbox completion. cmd=%x.\n", ha->mcp->mb[0]);
} else {
- qla_printk(KERN_INFO, ha,
- "%s(%ld): MBX pointer ERROR!\n",
- __func__, vha->host_no);
+ ql_dbg(ql_dbg_async, vha, 0x5053,
+ "MBX pointer ERROR.\n");
}
}
@@ -2019,13 +2052,13 @@ qla82xx_intr_handler(int irq, void *dev_id)
int status = 0, status1 = 0;
unsigned long flags;
unsigned long iter;
- uint32_t stat;
+ uint32_t stat = 0;
uint16_t mb[4];
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = rsp->hw;
@@ -2075,9 +2108,9 @@ qla82xx_intr_handler(int irq, void *dev_id)
qla24xx_process_response_queue(vha, rsp);
break;
default:
- DEBUG2(printk("scsi(%ld): "
- " Unrecognized interrupt type (%d).\n",
- vha->host_no, stat & 0xff));
+ ql_dbg(ql_dbg_async, vha, 0x5054,
+ "Unrecognized interrupt type (%d).\n",
+ stat & 0xff);
break;
}
}
@@ -2089,8 +2122,8 @@ qla82xx_intr_handler(int irq, void *dev_id)
#ifdef QL_DEBUG_LEVEL_17
if (!irq && ha->flags.eeh_busy)
- qla_printk(KERN_WARNING, ha,
- "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n",
+ ql_log(ql_log_warn, vha, 0x503d,
+ "isr:status %x, cmd_flags %lx, mbox_int %x, stat %x.\n",
status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
#endif
@@ -2111,13 +2144,13 @@ qla82xx_msix_default(int irq, void *dev_id)
struct device_reg_82xx __iomem *reg;
int status = 0;
unsigned long flags;
- uint32_t stat;
+ uint32_t stat = 0;
uint16_t mb[4];
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = rsp->hw;
@@ -2149,9 +2182,9 @@ qla82xx_msix_default(int irq, void *dev_id)
qla24xx_process_response_queue(vha, rsp);
break;
default:
- DEBUG2(printk("scsi(%ld): "
- " Unrecognized interrupt type (%d).\n",
- vha->host_no, stat & 0xff));
+ ql_dbg(ql_dbg_async, vha, 0x5041,
+ "Unrecognized interrupt type (%d).\n",
+ stat & 0xff);
break;
}
}
@@ -2162,9 +2195,9 @@ qla82xx_msix_default(int irq, void *dev_id)
#ifdef QL_DEBUG_LEVEL_17
if (!irq && ha->flags.eeh_busy)
- qla_printk(KERN_WARNING, ha,
- "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n",
- status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
+ ql_log(ql_log_warn, vha, 0x5044,
+ "isr:status %x, cmd_flags %lx, mbox_int %x, stat %x.\n",
+ status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
#endif
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
@@ -2182,21 +2215,22 @@ qla82xx_msix_rsp_q(int irq, void *dev_id)
struct qla_hw_data *ha;
struct rsp_que *rsp;
struct device_reg_82xx __iomem *reg;
+ unsigned long flags;
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = rsp->hw;
reg = &ha->iobase->isp82;
- spin_lock_irq(&ha->hardware_lock);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
qla24xx_process_response_queue(vha, rsp);
WRT_REG_DWORD(&reg->host_int, 0);
- spin_unlock_irq(&ha->hardware_lock);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return IRQ_HANDLED;
}
@@ -2215,7 +2249,7 @@ qla82xx_poll(int irq, void *dev_id)
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
printk(KERN_INFO
- "%s(): NULL response queue pointer\n", __func__);
+ "%s(): NULL response queue pointer.\n", __func__);
return;
}
ha = rsp->hw;
@@ -2245,9 +2279,9 @@ qla82xx_poll(int irq, void *dev_id)
qla24xx_process_response_queue(vha, rsp);
break;
default:
- DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
- "(%d).\n",
- vha->host_no, stat & 0xff));
+ ql_dbg(ql_dbg_p3p, vha, 0xb013,
+ "Unrecognized interrupt type (%d).\n",
+ stat * 0xff);
break;
}
}
@@ -2328,9 +2362,13 @@ qla82xx_need_reset(struct qla_hw_data *ha)
uint32_t drv_state;
int rval;
- drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
- rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
- return rval;
+ if (ha->flags.isp82xx_reset_owner)
+ return 1;
+ else {
+ drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+ rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
+ return rval;
+ }
}
static inline void
@@ -2347,9 +2385,8 @@ qla82xx_set_rst_ready(struct qla_hw_data *ha)
drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
}
drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
- qla_printk(KERN_INFO, ha,
- "%s(%ld):drv_state = 0x%x\n",
- __func__, vha->host_no, drv_state);
+ ql_dbg(ql_dbg_init, vha, 0x00bb,
+ "drv_state = 0x%08x.\n", drv_state);
qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
}
@@ -2392,8 +2429,8 @@ qla82xx_load_fw(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
if (qla82xx_pinit_from_rom(vha) != QLA_SUCCESS) {
- qla_printk(KERN_ERR, ha,
- "%s: Error during CRB Initialization\n", __func__);
+ ql_log(ql_log_fatal, vha, 0x009f,
+ "Error during CRB initialization.\n");
return QLA_FUNCTION_FAILED;
}
udelay(500);
@@ -2411,27 +2448,27 @@ qla82xx_load_fw(scsi_qla_host_t *vha)
if (ql2xfwloadbin == 2)
goto try_blob_fw;
- qla_printk(KERN_INFO, ha,
- "Attempting to load firmware from flash\n");
+ ql_log(ql_log_info, vha, 0x00a0,
+ "Attempting to load firmware from flash.\n");
if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) {
- qla_printk(KERN_ERR, ha,
- "Firmware loaded successfully from flash\n");
+ ql_log(ql_log_info, vha, 0x00a1,
+ "Firmware loaded successully from flash.\n");
return QLA_SUCCESS;
} else {
- qla_printk(KERN_ERR, ha,
- "Firmware load from flash failed\n");
+ ql_log(ql_log_warn, vha, 0x0108,
+ "Firmware load from flash failed.\n");
}
try_blob_fw:
- qla_printk(KERN_INFO, ha,
- "Attempting to load firmware from blob\n");
+ ql_log(ql_log_info, vha, 0x00a2,
+ "Attempting to load firmware from blob.\n");
/* Load firmware blob. */
blob = ha->hablob = qla2x00_request_firmware(vha);
if (!blob) {
- qla_printk(KERN_ERR, ha,
- "Firmware image not present.\n");
+ ql_log(ql_log_fatal, vha, 0x00a3,
+ "Firmware image not preset.\n");
goto fw_load_failed;
}
@@ -2441,20 +2478,19 @@ try_blob_fw:
/* Fallback to URI format */
if (qla82xx_validate_firmware_blob(vha,
QLA82XX_UNIFIED_ROMIMAGE)) {
- qla_printk(KERN_ERR, ha,
- "No valid firmware image found!!!");
+ ql_log(ql_log_fatal, vha, 0x00a4,
+ "No valid firmware image found.\n");
return QLA_FUNCTION_FAILED;
}
}
if (qla82xx_fw_load_from_blob(ha) == QLA_SUCCESS) {
- qla_printk(KERN_ERR, ha,
- "%s: Firmware loaded successfully "
- " from binary blob\n", __func__);
+ ql_log(ql_log_info, vha, 0x00a5,
+ "Firmware loaded successfully from binary blob.\n");
return QLA_SUCCESS;
} else {
- qla_printk(KERN_ERR, ha,
- "Firmware load failed from binary blob\n");
+ ql_log(ql_log_fatal, vha, 0x00a6,
+ "Firmware load failed for binary blob.\n");
blob->fw = NULL;
blob = NULL;
goto fw_load_failed;
@@ -2486,15 +2522,15 @@ qla82xx_start_firmware(scsi_qla_host_t *vha)
qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0);
if (qla82xx_load_fw(vha) != QLA_SUCCESS) {
- qla_printk(KERN_INFO, ha,
- "%s: Error trying to start fw!\n", __func__);
+ ql_log(ql_log_fatal, vha, 0x00a7,
+ "Error trying to start fw.\n");
return QLA_FUNCTION_FAILED;
}
/* Handshake with the card before we register the devices. */
if (qla82xx_check_cmdpeg_state(ha) != QLA_SUCCESS) {
- qla_printk(KERN_INFO, ha,
- "%s: Error during card handshake!\n", __func__);
+ ql_log(ql_log_fatal, vha, 0x00aa,
+ "Error during card handshake.\n");
return QLA_FUNCTION_FAILED;
}
@@ -2573,7 +2609,7 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
*dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
*dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- *dsd_seg++ = cpu_to_le32(dsd_list_len);
+ cmd_pkt->fcp_data_dseg_len = cpu_to_le32(dsd_list_len);
} else {
*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
@@ -2663,8 +2699,11 @@ qla82xx_start_scsi(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
if (qla2x00_marker(vha, req,
- rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS)
+ rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x300c,
+ "qla2x00_marker failed for cmd=%p.\n", cmd);
return QLA_FUNCTION_FAILED;
+ }
vha->marker_needed = 0;
}
@@ -2701,8 +2740,13 @@ qla82xx_start_scsi(srb_t *sp)
uint16_t i;
more_dsd_lists = qla82xx_calc_dsd_lists(tot_dsds);
- if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN)
+ if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN) {
+ ql_dbg(ql_dbg_io, vha, 0x300d,
+ "Num of DSD list %d is than %d for cmd=%p.\n",
+ more_dsd_lists + ha->gbl_dsd_inuse, NUM_DSD_CHAIN,
+ cmd);
goto queuing_error;
+ }
if (more_dsd_lists <= ha->gbl_dsd_avail)
goto sufficient_dsds;
@@ -2711,13 +2755,20 @@ qla82xx_start_scsi(srb_t *sp)
for (i = 0; i < more_dsd_lists; i++) {
dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
- if (!dsd_ptr)
+ if (!dsd_ptr) {
+ ql_log(ql_log_fatal, vha, 0x300e,
+ "Failed to allocate memory for dsd_dma "
+ "for cmd=%p.\n", cmd);
goto queuing_error;
+ }
dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool,
GFP_ATOMIC, &dsd_ptr->dsd_list_dma);
if (!dsd_ptr->dsd_addr) {
kfree(dsd_ptr);
+ ql_log(ql_log_fatal, vha, 0x300f,
+ "Failed to allocate memory for dsd_addr "
+ "for cmd=%p.\n", cmd);
goto queuing_error;
}
list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list);
@@ -2742,17 +2793,16 @@ sufficient_dsds:
ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC);
if (!sp->ctx) {
- DEBUG(printk(KERN_INFO
- "%s(%ld): failed to allocate"
- " ctx.\n", __func__, vha->host_no));
+ ql_log(ql_log_fatal, vha, 0x3010,
+ "Failed to allocate ctx for cmd=%p.\n", cmd);
goto queuing_error;
}
memset(ctx, 0, sizeof(struct ct6_dsd));
ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool,
GFP_ATOMIC, &ctx->fcp_cmnd_dma);
if (!ctx->fcp_cmnd) {
- DEBUG2_3(printk("%s(%ld): failed to allocate"
- " fcp_cmnd.\n", __func__, vha->host_no));
+ ql_log(ql_log_fatal, vha, 0x3011,
+ "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd);
goto queuing_error_fcp_cmnd;
}
@@ -2766,6 +2816,9 @@ sufficient_dsds:
/* SCSI command bigger than 16 bytes must be
* multiple of 4
*/
+ ql_log(ql_log_warn, vha, 0x3012,
+ "scsi cmd len %d not multiple of 4 "
+ "for cmd=%p.\n", cmd->cmd_len, cmd);
goto queuing_error_fcp_cmnd;
}
ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4;
@@ -2797,6 +2850,16 @@ sufficient_dsds:
int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
+ /* build FCP_CMND IU */
+ memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
+ int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun);
+ ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
+
+ if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ ctx->fcp_cmnd->additional_cdb_len |= 1;
+ else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+ ctx->fcp_cmnd->additional_cdb_len |= 2;
+
/*
* Update tagged queuing modifier -- default is TSK_SIMPLE (0).
*/
@@ -2813,16 +2876,6 @@ sufficient_dsds:
}
}
- /* build FCP_CMND IU */
- memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
- int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun);
- ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
-
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
- ctx->fcp_cmnd->additional_cdb_len |= 1;
- else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
- ctx->fcp_cmnd->additional_cdb_len |= 2;
-
memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 +
@@ -2845,7 +2898,7 @@ sufficient_dsds:
cmd_pkt->entry_status = (uint8_t) rsp->id;
} else {
struct cmd_type_7 *cmd_pkt;
- req_cnt = qla24xx_calc_iocbs(tot_dsds);
+ req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
cnt = (uint16_t)RD_REG_DWORD_RELAXED(
&reg->req_q_out[0]);
@@ -2979,8 +3032,8 @@ qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
/* Dword reads to flash. */
for (i = 0; i < length/4; i++, faddr += 4) {
if (qla82xx_rom_fast_read(ha, faddr, &val)) {
- qla_printk(KERN_WARNING, ha,
- "Do ROM fast read failed\n");
+ ql_log(ql_log_warn, vha, 0x0106,
+ "Do ROM fast read failed.\n");
goto done_read;
}
dwptr[i] = __constant_cpu_to_le32(val);
@@ -2994,10 +3047,12 @@ qla82xx_unprotect_flash(struct qla_hw_data *ha)
{
int ret;
uint32_t val;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
ret = ql82xx_rom_lock_d(ha);
if (ret < 0) {
- qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+ ql_log(ql_log_warn, vha, 0xb014,
+ "ROM Lock failed.\n");
return ret;
}
@@ -3013,7 +3068,8 @@ qla82xx_unprotect_flash(struct qla_hw_data *ha)
}
if (qla82xx_write_disable_flash(ha) != 0)
- qla_printk(KERN_WARNING, ha, "Write disable failed\n");
+ ql_log(ql_log_warn, vha, 0xb015,
+ "Write disable failed.\n");
done_unprotect:
qla82xx_rom_unlock(ha);
@@ -3025,10 +3081,12 @@ qla82xx_protect_flash(struct qla_hw_data *ha)
{
int ret;
uint32_t val;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
ret = ql82xx_rom_lock_d(ha);
if (ret < 0) {
- qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+ ql_log(ql_log_warn, vha, 0xb016,
+ "ROM Lock failed.\n");
return ret;
}
@@ -3040,10 +3098,12 @@ qla82xx_protect_flash(struct qla_hw_data *ha)
/* LOCK all sectors */
ret = qla82xx_write_status_reg(ha, val);
if (ret < 0)
- qla_printk(KERN_WARNING, ha, "Write status register failed\n");
+ ql_log(ql_log_warn, vha, 0xb017,
+ "Write status register failed.\n");
if (qla82xx_write_disable_flash(ha) != 0)
- qla_printk(KERN_WARNING, ha, "Write disable failed\n");
+ ql_log(ql_log_warn, vha, 0xb018,
+ "Write disable failed.\n");
done_protect:
qla82xx_rom_unlock(ha);
return ret;
@@ -3053,10 +3113,12 @@ static int
qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
{
int ret = 0;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
ret = ql82xx_rom_lock_d(ha);
if (ret < 0) {
- qla_printk(KERN_WARNING, ha, "ROM Lock failed\n");
+ ql_log(ql_log_warn, vha, 0xb019,
+ "ROM Lock failed.\n");
return ret;
}
@@ -3066,8 +3128,8 @@ qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_SE);
if (qla82xx_wait_rom_done(ha)) {
- qla_printk(KERN_WARNING, ha,
- "Error waiting for rom done\n");
+ ql_log(ql_log_warn, vha, 0xb01a,
+ "Error waiting for rom done.\n");
ret = -1;
goto done;
}
@@ -3110,10 +3172,10 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
&optrom_dma, GFP_KERNEL);
if (!optrom) {
- qla_printk(KERN_DEBUG, ha,
- "Unable to allocate memory for optrom "
- "burst write (%x KB).\n",
- OPTROM_BURST_SIZE / 1024);
+ ql_log(ql_log_warn, vha, 0xb01b,
+ "Unable to allocate memory "
+ "for optron burst write (%x KB).\n",
+ OPTROM_BURST_SIZE / 1024);
}
}
@@ -3122,8 +3184,8 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
ret = qla82xx_unprotect_flash(ha);
if (ret) {
- qla_printk(KERN_WARNING, ha,
- "Unable to unprotect flash for update.\n");
+ ql_log(ql_log_warn, vha, 0xb01c,
+ "Unable to unprotect flash for update.\n");
goto write_done;
}
@@ -3133,9 +3195,9 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
ret = qla82xx_erase_sector(ha, faddr);
if (ret) {
- DEBUG9(qla_printk(KERN_ERR, ha,
- "Unable to erase sector: "
- "address=%x.\n", faddr));
+ ql_log(ql_log_warn, vha, 0xb01d,
+ "Unable to erase sector: address=%x.\n",
+ faddr);
break;
}
}
@@ -3149,12 +3211,12 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
(ha->flash_data_off | faddr),
OPTROM_BURST_DWORDS);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0xb01e,
"Unable to burst-write optrom segment "
"(%x/%x/%llx).\n", ret,
(ha->flash_data_off | faddr),
(unsigned long long)optrom_dma);
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0xb01f,
"Reverting to slow-write.\n");
dma_free_coherent(&ha->pdev->dev,
@@ -3171,16 +3233,16 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
ret = qla82xx_write_flash_dword(ha, faddr,
cpu_to_le32(*dwptr));
if (ret) {
- DEBUG9(printk(KERN_DEBUG "%s(%ld) Unable to program"
- "flash address=%x data=%x.\n", __func__,
- ha->host_no, faddr, *dwptr));
+ ql_dbg(ql_dbg_p3p, vha, 0xb020,
+ "Unable to program flash address=%x data=%x.\n",
+ faddr, *dwptr);
break;
}
}
ret = qla82xx_protect_flash(ha);
if (ret)
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0xb021,
"Unable to protect flash after update.\n");
write_done:
if (optrom)
@@ -3244,9 +3306,12 @@ qla82xx_start_iocbs(srb_t *sp)
void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
if (qla82xx_rom_lock(ha))
/* Someone else is holding the lock. */
- qla_printk(KERN_INFO, ha, "Resetting rom_lock\n");
+ ql_log(ql_log_info, vha, 0xb022,
+ "Resetting rom_lock.\n");
/*
* Either we got the lock, or someone
@@ -3313,7 +3378,8 @@ qla82xx_device_bootstrap(scsi_qla_host_t *vha)
dev_initialize:
/* set to DEV_INITIALIZING */
- qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");
+ ql_log(ql_log_info, vha, 0x009e,
+ "HW State: INITIALIZING.\n");
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING);
/* Driver that sets device state to initializating sets IDC version */
@@ -3324,14 +3390,16 @@ dev_initialize:
qla82xx_idc_lock(ha);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+ ql_log(ql_log_fatal, vha, 0x00ad,
+ "HW State: FAILED.\n");
qla82xx_clear_drv_active(ha);
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED);
return rval;
}
dev_ready:
- qla_printk(KERN_INFO, ha, "HW State: READY\n");
+ ql_log(ql_log_info, vha, 0x00ae,
+ "HW State: READY.\n");
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY);
return QLA_SUCCESS;
@@ -3376,15 +3444,15 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
/* quiescence timeout, other functions didn't ack
* changing the state to DEV_READY
*/
- qla_printk(KERN_INFO, ha,
- "%s: QUIESCENT TIMEOUT\n", QLA2XXX_DRIVER_NAME);
- qla_printk(KERN_INFO, ha,
- "DRV_ACTIVE:%d DRV_STATE:%d\n", drv_active,
- drv_state);
+ ql_log(ql_log_info, vha, 0xb023,
+ "%s : QUIESCENT TIMEOUT.\n", QLA2XXX_DRIVER_NAME);
+ ql_log(ql_log_info, vha, 0xb024,
+ "DRV_ACTIVE:%d DRV_STATE:%d.\n",
+ drv_active, drv_state);
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
- QLA82XX_DEV_READY);
- qla_printk(KERN_INFO, ha,
- "HW State: DEV_READY\n");
+ QLA82XX_DEV_READY);
+ ql_log(ql_log_info, vha, 0xb025,
+ "HW State: DEV_READY.\n");
qla82xx_idc_unlock(ha);
qla2x00_perform_loop_resync(vha);
qla82xx_idc_lock(ha);
@@ -3404,7 +3472,8 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
/* everyone acked so set the state to DEV_QUIESCENCE */
if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) {
- qla_printk(KERN_INFO, ha, "HW State: DEV_QUIESCENT\n");
+ ql_log(ql_log_info, vha, 0xb026,
+ "HW State: DEV_QUIESCENT.\n");
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT);
}
}
@@ -3441,7 +3510,8 @@ qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
/* Disable the board */
- qla_printk(KERN_INFO, ha, "Disabling the board\n");
+ ql_log(ql_log_fatal, vha, 0x00b8,
+ "Disabling the board.\n");
qla82xx_idc_lock(ha);
qla82xx_clear_drv_active(ha);
@@ -3470,6 +3540,7 @@ static void
qla82xx_need_reset_handler(scsi_qla_host_t *vha)
{
uint32_t dev_state, drv_state, drv_active;
+ uint32_t active_mask = 0;
unsigned long reset_timeout;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
@@ -3482,18 +3553,35 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
}
- qla82xx_set_rst_ready(ha);
+ drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ if (!ha->flags.isp82xx_reset_owner) {
+ ql_dbg(ql_dbg_p3p, vha, 0xb028,
+ "reset_acknowledged by 0x%x\n", ha->portnum);
+ qla82xx_set_rst_ready(ha);
+ } else {
+ active_mask = ~(QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
+ drv_active &= active_mask;
+ ql_dbg(ql_dbg_p3p, vha, 0xb029,
+ "active_mask: 0x%08x\n", active_mask);
+ }
/* wait for 10 seconds for reset ack from all functions */
reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);
drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
- while (drv_state != drv_active) {
+ ql_dbg(ql_dbg_p3p, vha, 0xb02a,
+ "drv_state: 0x%08x, drv_active: 0x%08x, "
+ "dev_state: 0x%08x, active_mask: 0x%08x\n",
+ drv_state, drv_active, dev_state, active_mask);
+
+ while (drv_state != drv_active &&
+ dev_state != QLA82XX_DEV_INITIALIZING) {
if (time_after_eq(jiffies, reset_timeout)) {
- qla_printk(KERN_INFO, ha,
- "%s: RESET TIMEOUT!\n", QLA2XXX_DRIVER_NAME);
+ ql_log(ql_log_warn, vha, 0x00b5,
+ "Reset timeout.\n");
break;
}
qla82xx_idc_unlock(ha);
@@ -3501,20 +3589,87 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ if (ha->flags.isp82xx_reset_owner)
+ drv_active &= active_mask;
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
}
- dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
- qla_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state,
- dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+ ql_dbg(ql_dbg_p3p, vha, 0xb02b,
+ "drv_state: 0x%08x, drv_active: 0x%08x, "
+ "dev_state: 0x%08x, active_mask: 0x%08x\n",
+ drv_state, drv_active, dev_state, active_mask);
+
+ ql_log(ql_log_info, vha, 0x00b6,
+ "Device state is 0x%x = %s.\n",
+ dev_state,
+ dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
/* Force to DEV_COLD unless someone else is starting a reset */
- if (dev_state != QLA82XX_DEV_INITIALIZING) {
- qla_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n");
+ if (dev_state != QLA82XX_DEV_INITIALIZING &&
+ dev_state != QLA82XX_DEV_COLD) {
+ ql_log(ql_log_info, vha, 0x00b7,
+ "HW State: COLD/RE-INIT.\n");
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
+ if (ql2xmdenable) {
+ if (qla82xx_md_collect(vha))
+ ql_log(ql_log_warn, vha, 0xb02c,
+ "Not able to collect minidump.\n");
+ } else
+ ql_log(ql_log_warn, vha, 0xb04f,
+ "Minidump disabled.\n");
}
}
int
+qla82xx_check_md_needed(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t fw_major_version, fw_minor_version, fw_subminor_version;
+ int rval = QLA_SUCCESS;
+
+ fw_major_version = ha->fw_major_version;
+ fw_minor_version = ha->fw_minor_version;
+ fw_subminor_version = ha->fw_subminor_version;
+
+ rval = qla2x00_get_fw_version(vha, &ha->fw_major_version,
+ &ha->fw_minor_version, &ha->fw_subminor_version,
+ &ha->fw_attributes, &ha->fw_memory_size,
+ ha->mpi_version, &ha->mpi_capabilities,
+ ha->phy_version);
+
+ if (rval != QLA_SUCCESS)
+ return rval;
+
+ if (ql2xmdenable) {
+ if (!ha->fw_dumped) {
+ if (fw_major_version != ha->fw_major_version ||
+ fw_minor_version != ha->fw_minor_version ||
+ fw_subminor_version != ha->fw_subminor_version) {
+
+ ql_log(ql_log_info, vha, 0xb02d,
+ "Firmware version differs "
+ "Previous version: %d:%d:%d - "
+ "New version: %d:%d:%d\n",
+ ha->fw_major_version,
+ ha->fw_minor_version,
+ ha->fw_subminor_version,
+ fw_major_version, fw_minor_version,
+ fw_subminor_version);
+ /* Release MiniDump resources */
+ qla82xx_md_free(vha);
+ /* ALlocate MiniDump resources */
+ qla82xx_md_prep(vha);
+ } else
+ ql_log(ql_log_info, vha, 0xb02e,
+ "Firmware dump available to retrieve\n",
+ vha->host_no);
+ }
+ }
+ return rval;
+}
+
+
+int
qla82xx_check_fw_alive(scsi_qla_host_t *vha)
{
uint32_t fw_heartbeat_counter;
@@ -3523,8 +3678,12 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha)
fw_heartbeat_counter = qla82xx_rd_32(vha->hw,
QLA82XX_PEG_ALIVE_COUNTER);
/* all 0xff, assume AER/EEH in progress, ignore */
- if (fw_heartbeat_counter == 0xffffffff)
+ if (fw_heartbeat_counter == 0xffffffff) {
+ ql_dbg(ql_dbg_timer, vha, 0x6003,
+ "FW heartbeat counter is 0xffffffff, "
+ "returning status=%d.\n", status);
return status;
+ }
if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
vha->seconds_since_last_heartbeat++;
/* FW not alive after 2 seconds */
@@ -3535,6 +3694,9 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha)
} else
vha->seconds_since_last_heartbeat = 0;
vha->fw_heartbeat_counter = fw_heartbeat_counter;
+ if (status)
+ ql_dbg(ql_dbg_timer, vha, 0x6004,
+ "Returning status=%d.\n", status);
return status;
}
@@ -3565,8 +3727,10 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
old_dev_state = dev_state;
- qla_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state,
- dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+ ql_log(ql_log_info, vha, 0x009b,
+ "Device state is 0x%x = %s.\n",
+ dev_state,
+ dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
/* wait for 30 seconds for device to go ready */
dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
@@ -3574,9 +3738,8 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
while (1) {
if (time_after_eq(jiffies, dev_init_timeout)) {
- DEBUG(qla_printk(KERN_INFO, ha,
- "%s: device init failed!\n",
- QLA2XXX_DRIVER_NAME));
+ ql_log(ql_log_fatal, vha, 0x009c,
+ "Device init failed.\n");
rval = QLA_FUNCTION_FAILED;
break;
}
@@ -3586,28 +3749,36 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
old_dev_state = dev_state;
}
if (loopcount < 5) {
- qla_printk(KERN_INFO, ha,
- "2:Device state is 0x%x = %s\n", dev_state,
- dev_state < MAX_STATES ?
- qdev_state[dev_state] : "Unknown");
+ ql_log(ql_log_info, vha, 0x009d,
+ "Device state is 0x%x = %s.\n",
+ dev_state,
+ dev_state < MAX_STATES ? qdev_state(dev_state) :
+ "Unknown");
}
switch (dev_state) {
case QLA82XX_DEV_READY:
+ qla82xx_check_md_needed(vha);
+ ha->flags.isp82xx_reset_owner = 0;
goto exit;
case QLA82XX_DEV_COLD:
rval = qla82xx_device_bootstrap(vha);
- goto exit;
+ break;
case QLA82XX_DEV_INITIALIZING:
qla82xx_idc_unlock(ha);
msleep(1000);
qla82xx_idc_lock(ha);
break;
case QLA82XX_DEV_NEED_RESET:
- if (!ql2xdontresethba)
- qla82xx_need_reset_handler(vha);
+ if (!ql2xdontresethba)
+ qla82xx_need_reset_handler(vha);
+ else {
+ qla82xx_idc_unlock(ha);
+ msleep(1000);
+ qla82xx_idc_lock(ha);
+ }
dev_init_timeout = jiffies +
- (ha->nx_dev_init_timeout * HZ);
+ (ha->nx_dev_init_timeout * HZ);
break;
case QLA82XX_DEV_NEED_QUIESCENT:
qla82xx_need_qsnt_handler(vha);
@@ -3646,6 +3817,20 @@ exit:
return rval;
}
+void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (ha->flags.mbox_busy) {
+ ha->flags.mbox_int = 1;
+ ha->flags.mbox_busy = 0;
+ ql_log(ql_log_warn, vha, 0x6010,
+ "Doing premature completion of mbx command.\n");
+ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags))
+ complete(&ha->mbx_intr_comp);
+ }
+}
+
void qla82xx_watchdog(scsi_qla_host_t *vha)
{
uint32_t dev_state, halt_status;
@@ -3656,29 +3841,30 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
if (dev_state == QLA82XX_DEV_NEED_RESET &&
!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
- qla_printk(KERN_WARNING, ha,
- "scsi(%ld) %s: Adapter reset needed!\n",
- vha->host_no, __func__);
+ ql_log(ql_log_warn, vha, 0x6001,
+ "Adapter reset needed.\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
} else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
!test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
- DEBUG(qla_printk(KERN_INFO, ha,
- "scsi(%ld) %s - detected quiescence needed\n",
- vha->host_no, __func__));
+ ql_log(ql_log_warn, vha, 0x6002,
+ "Quiescent needed.\n");
set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
} else {
if (qla82xx_check_fw_alive(vha)) {
+ ql_dbg(ql_dbg_timer, vha, 0x6011,
+ "disabling pause transmit on port 0 & 1.\n");
+ qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+ CRB_NIU_XG_PAUSE_CTL_P0|CRB_NIU_XG_PAUSE_CTL_P1);
halt_status = qla82xx_rd_32(ha,
QLA82XX_PEG_HALT_STATUS1);
- qla_printk(KERN_INFO, ha,
- "scsi(%ld): %s, Dumping hw/fw registers:\n "
- " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n "
- " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n "
- " PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n "
- " PEG_NET_4_PC: 0x%x\n",
- vha->host_no, __func__, halt_status,
+ ql_log(ql_log_info, vha, 0x6005,
+ "dumping hw/fw registers:.\n "
+ " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,.\n "
+ " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,.\n "
+ " PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,.\n "
+ " PEG_NET_4_PC: 0x%x.\n", halt_status,
qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS2),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_0 + 0x3c),
@@ -3690,28 +3876,24 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
QLA82XX_CRB_PEG_NET_3 + 0x3c),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_4 + 0x3c));
+ if (LSW(MSB(halt_status)) == 0x67)
+ ql_log(ql_log_warn, vha, 0xb052,
+ "Firmware aborted with "
+ "error code 0x00006700. Device is "
+ "being reset.\n");
if (halt_status & HALT_STATUS_UNRECOVERABLE) {
set_bit(ISP_UNRECOVERABLE,
&vha->dpc_flags);
} else {
- qla_printk(KERN_INFO, ha,
- "scsi(%ld): %s - detect abort needed\n",
- vha->host_no, __func__);
+ ql_log(ql_log_info, vha, 0x6006,
+ "Detect abort needed.\n");
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
}
qla2xxx_wake_dpc(vha);
ha->flags.isp82xx_fw_hung = 1;
- if (ha->flags.mbox_busy) {
- ha->flags.mbox_int = 1;
- DEBUG2(qla_printk(KERN_ERR, ha,
- "scsi(%ld) Due to fw hung, doing "
- "premature completion of mbx "
- "command\n", vha->host_no));
- if (test_bit(MBX_INTR_WAIT,
- &ha->mbx_cmd_flags))
- complete(&ha->mbx_intr_comp);
- }
+ ql_log(ql_log_warn, vha, 0x6007, "Firmware hung.\n");
+ qla82xx_clear_pending_mbx(vha);
}
}
}
@@ -3724,6 +3906,28 @@ int qla82xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
return rval;
}
+void
+qla82xx_set_reset_owner(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t dev_state;
+
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+ if (dev_state == QLA82XX_DEV_READY) {
+ ql_log(ql_log_info, vha, 0xb02f,
+ "HW State: NEED RESET\n");
+ qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+ QLA82XX_DEV_NEED_RESET);
+ ha->flags.isp82xx_reset_owner = 1;
+ ql_dbg(ql_dbg_p3p, vha, 0xb030,
+ "reset_owner is 0x%x\n", ha->portnum);
+ } else
+ ql_log(ql_log_info, vha, 0xb031,
+ "Device state is 0x%x = %s.\n",
+ dev_state,
+ dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
+}
+
/*
* qla82xx_abort_isp
* Resets ISP and aborts all outstanding commands.
@@ -3739,26 +3943,16 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
{
int rval;
struct qla_hw_data *ha = vha->hw;
- uint32_t dev_state;
if (vha->device_flags & DFLG_DEV_FAILED) {
- qla_printk(KERN_WARNING, ha,
- "%s(%ld): Device in failed state, "
- "Exiting.\n", __func__, vha->host_no);
+ ql_log(ql_log_warn, vha, 0x8024,
+ "Device in failed state, exiting.\n");
return QLA_SUCCESS;
}
ha->flags.isp82xx_reset_hdlr_active = 1;
qla82xx_idc_lock(ha);
- dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
- if (dev_state == QLA82XX_DEV_READY) {
- qla_printk(KERN_INFO, ha, "HW State: NEED RESET\n");
- qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
- QLA82XX_DEV_NEED_RESET);
- } else
- qla_printk(KERN_INFO, ha, "HW State: %s\n",
- dev_state < MAX_STATES ?
- qdev_state[dev_state] : "Unknown");
+ qla82xx_set_reset_owner(vha);
qla82xx_idc_unlock(ha);
rval = qla82xx_device_state_handler(vha);
@@ -3777,9 +3971,9 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
vha->flags.online = 1;
if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
if (ha->isp_abort_cnt == 0) {
- qla_printk(KERN_WARNING, ha,
- "ISP error recovery failed - "
- "board disabled\n");
+ ql_log(ql_log_warn, vha, 0x8027,
+ "ISP error recover failed - board "
+ "disabled.\n");
/*
* The next call disables the board
* completely.
@@ -3791,16 +3985,16 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
rval = QLA_SUCCESS;
} else { /* schedule another ISP abort */
ha->isp_abort_cnt--;
- DEBUG(qla_printk(KERN_INFO, ha,
- "qla%ld: ISP abort - retry remaining %d\n",
- vha->host_no, ha->isp_abort_cnt));
+ ql_log(ql_log_warn, vha, 0x8036,
+ "ISP abort - retry remaining %d.\n",
+ ha->isp_abort_cnt);
rval = QLA_FUNCTION_FAILED;
}
} else {
ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
- DEBUG(qla_printk(KERN_INFO, ha,
- "(%ld): ISP error recovery - retrying (%d) "
- "more times\n", vha->host_no, ha->isp_abort_cnt));
+ ql_dbg(ql_dbg_taskm, vha, 0x8029,
+ "ISP error recovery - retrying (%d) more times.\n",
+ ha->isp_abort_cnt);
set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
rval = QLA_FUNCTION_FAILED;
}
@@ -3872,8 +4066,8 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha)
break;
}
}
- DEBUG2(printk(KERN_INFO
- "%s status=%d\n", __func__, status));
+ ql_dbg(ql_dbg_p3p, vha, 0xb027,
+ "%s status=%d.\n", status);
return status;
}
@@ -3894,14 +4088,14 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
msleep(1000);
if (qla82xx_check_fw_alive(vha)) {
ha->flags.isp82xx_fw_hung = 1;
- if (ha->flags.mbox_busy) {
- ha->flags.mbox_int = 1;
- complete(&ha->mbx_intr_comp);
- }
+ qla82xx_clear_pending_mbx(vha);
break;
}
}
}
+ ql_dbg(ql_dbg_init, vha, 0x00b0,
+ "Entered %s fw_hung=%d.\n",
+ __func__, ha->flags.isp82xx_fw_hung);
/* Abort all commands gracefully if fw NOT hung */
if (!ha->flags.isp82xx_fw_hung) {
@@ -3922,13 +4116,13 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
spin_unlock_irqrestore(
&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
- qla_printk(KERN_INFO, ha,
- "scsi(%ld): mbx abort command failed in %s\n",
- vha->host_no, __func__);
+ ql_log(ql_log_info, vha,
+ 0x00b1,
+ "mbx abort failed.\n");
} else {
- qla_printk(KERN_INFO, ha,
- "scsi(%ld): mbx abort command success in %s\n",
- vha->host_no, __func__);
+ ql_log(ql_log_info, vha,
+ 0x00b2,
+ "mbx abort success.\n");
}
spin_lock_irqsave(&ha->hardware_lock, flags);
}
@@ -3940,8 +4134,809 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
/* Wait for pending cmds (physical and virtual) to complete */
if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
WAIT_HOST) == QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "Done wait for pending commands\n"));
+ ql_dbg(ql_dbg_init, vha, 0x00b3,
+ "Done wait for "
+ "pending commands.\n");
+ }
+ }
+}
+
+/* Minidump related functions */
+int
+qla82xx_md_rw_32(struct qla_hw_data *ha, uint32_t off, u32 data, uint8_t flag)
+{
+ uint32_t off_value, rval = 0;
+
+ WRT_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase),
+ (off & 0xFFFF0000));
+
+ /* Read back value to make sure write has gone through */
+ RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+ off_value = (off & 0x0000FFFF);
+
+ if (flag)
+ WRT_REG_DWORD((void *)
+ (off_value + CRB_INDIRECT_2M + ha->nx_pcibase),
+ data);
+ else
+ rval = RD_REG_DWORD((void *)
+ (off_value + CRB_INDIRECT_2M + ha->nx_pcibase));
+
+ return rval;
+}
+
+static int
+qla82xx_minidump_process_control(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct qla82xx_md_entry_crb *crb_entry;
+ uint32_t read_value, opcode, poll_time;
+ uint32_t addr, index, crb_addr;
+ unsigned long wtime;
+ struct qla82xx_md_template_hdr *tmplt_hdr;
+ uint32_t rval = QLA_SUCCESS;
+ int i;
+
+ tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
+ crb_entry = (struct qla82xx_md_entry_crb *)entry_hdr;
+ crb_addr = crb_entry->addr;
+
+ for (i = 0; i < crb_entry->op_count; i++) {
+ opcode = crb_entry->crb_ctrl.opcode;
+ if (opcode & QLA82XX_DBG_OPCODE_WR) {
+ qla82xx_md_rw_32(ha, crb_addr,
+ crb_entry->value_1, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_WR;
}
+
+ if (opcode & QLA82XX_DBG_OPCODE_RW) {
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+ qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_RW;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_AND) {
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+ read_value &= crb_entry->value_2;
+ opcode &= ~QLA82XX_DBG_OPCODE_AND;
+ if (opcode & QLA82XX_DBG_OPCODE_OR) {
+ read_value |= crb_entry->value_3;
+ opcode &= ~QLA82XX_DBG_OPCODE_OR;
+ }
+ qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_OR) {
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+ read_value |= crb_entry->value_3;
+ qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_OR;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_POLL) {
+ poll_time = crb_entry->crb_strd.poll_timeout;
+ wtime = jiffies + poll_time;
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+
+ do {
+ if ((read_value & crb_entry->value_2)
+ == crb_entry->value_1)
+ break;
+ else if (time_after_eq(jiffies, wtime)) {
+ /* capturing dump failed */
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ } else
+ read_value = qla82xx_md_rw_32(ha,
+ crb_addr, 0, 0);
+ } while (1);
+ opcode &= ~QLA82XX_DBG_OPCODE_POLL;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
+ if (crb_entry->crb_strd.state_index_a) {
+ index = crb_entry->crb_strd.state_index_a;
+ addr = tmplt_hdr->saved_state_array[index];
+ } else
+ addr = crb_addr;
+
+ read_value = qla82xx_md_rw_32(ha, addr, 0, 0);
+ index = crb_entry->crb_ctrl.state_index_v;
+ tmplt_hdr->saved_state_array[index] = read_value;
+ opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
+ if (crb_entry->crb_strd.state_index_a) {
+ index = crb_entry->crb_strd.state_index_a;
+ addr = tmplt_hdr->saved_state_array[index];
+ } else
+ addr = crb_addr;
+
+ if (crb_entry->crb_ctrl.state_index_v) {
+ index = crb_entry->crb_ctrl.state_index_v;
+ read_value =
+ tmplt_hdr->saved_state_array[index];
+ } else
+ read_value = crb_entry->value_1;
+
+ qla82xx_md_rw_32(ha, addr, read_value, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
+ index = crb_entry->crb_ctrl.state_index_v;
+ read_value = tmplt_hdr->saved_state_array[index];
+ read_value <<= crb_entry->crb_ctrl.shl;
+ read_value >>= crb_entry->crb_ctrl.shr;
+ if (crb_entry->value_2)
+ read_value &= crb_entry->value_2;
+ read_value |= crb_entry->value_3;
+ read_value += crb_entry->value_1;
+ tmplt_hdr->saved_state_array[index] = read_value;
+ opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
+ }
+ crb_addr += crb_entry->crb_strd.addr_stride;
+ }
+ return rval;
+}
+
+static void
+qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_stride, loop_cnt, i, r_value;
+ struct qla82xx_md_entry_rdocm *ocm_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ ocm_hdr = (struct qla82xx_md_entry_rdocm *)entry_hdr;
+ r_addr = ocm_hdr->read_addr;
+ r_stride = ocm_hdr->read_addr_stride;
+ loop_cnt = ocm_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ r_value = RD_REG_DWORD((void *)(r_addr + ha->nx_pcibase));
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += r_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_rdmux(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
+ struct qla82xx_md_entry_mux *mux_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ mux_hdr = (struct qla82xx_md_entry_mux *)entry_hdr;
+ r_addr = mux_hdr->read_addr;
+ s_addr = mux_hdr->select_addr;
+ s_stride = mux_hdr->select_value_stride;
+ s_value = mux_hdr->select_value;
+ loop_cnt = mux_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, s_addr, s_value, 1);
+ r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(s_value);
+ *data_ptr++ = cpu_to_le32(r_value);
+ s_value += s_stride;
}
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_rdcrb(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_stride, loop_cnt, i, r_value;
+ struct qla82xx_md_entry_crb *crb_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ crb_hdr = (struct qla82xx_md_entry_crb *)entry_hdr;
+ r_addr = crb_hdr->addr;
+ r_stride = crb_hdr->crb_strd.addr_stride;
+ loop_cnt = crb_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_addr);
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += r_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static int
+qla82xx_minidump_process_l2tag(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t addr, r_addr, c_addr, t_r_addr;
+ uint32_t i, k, loop_count, t_value, r_cnt, r_value;
+ unsigned long p_wait, w_time, p_mask;
+ uint32_t c_value_w, c_value_r;
+ struct qla82xx_md_entry_cache *cache_hdr;
+ int rval = QLA_FUNCTION_FAILED;
+ uint32_t *data_ptr = *d_ptr;
+
+ cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
+ loop_count = cache_hdr->op_count;
+ r_addr = cache_hdr->read_addr;
+ c_addr = cache_hdr->control_addr;
+ c_value_w = cache_hdr->cache_ctrl.write_value;
+
+ t_r_addr = cache_hdr->tag_reg_addr;
+ t_value = cache_hdr->addr_ctrl.init_tag_value;
+ r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
+ p_wait = cache_hdr->cache_ctrl.poll_wait;
+ p_mask = cache_hdr->cache_ctrl.poll_mask;
+
+ for (i = 0; i < loop_count; i++) {
+ qla82xx_md_rw_32(ha, t_r_addr, t_value, 1);
+ if (c_value_w)
+ qla82xx_md_rw_32(ha, c_addr, c_value_w, 1);
+
+ if (p_mask) {
+ w_time = jiffies + p_wait;
+ do {
+ c_value_r = qla82xx_md_rw_32(ha, c_addr, 0, 0);
+ if ((c_value_r & p_mask) == 0)
+ break;
+ else if (time_after_eq(jiffies, w_time)) {
+ /* capturing dump failed */
+ ql_dbg(ql_dbg_p3p, vha, 0xb032,
+ "c_value_r: 0x%x, poll_mask: 0x%lx, "
+ "w_time: 0x%lx\n",
+ c_value_r, p_mask, w_time);
+ return rval;
+ }
+ } while (1);
+ }
+
+ addr = r_addr;
+ for (k = 0; k < r_cnt; k++) {
+ r_value = qla82xx_md_rw_32(ha, addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ addr += cache_hdr->read_ctrl.read_addr_stride;
+ }
+ t_value += cache_hdr->addr_ctrl.tag_value_stride;
+ }
+ *d_ptr = data_ptr;
+ return QLA_SUCCESS;
+}
+
+static void
+qla82xx_minidump_process_l1cache(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t addr, r_addr, c_addr, t_r_addr;
+ uint32_t i, k, loop_count, t_value, r_cnt, r_value;
+ uint32_t c_value_w;
+ struct qla82xx_md_entry_cache *cache_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
+ loop_count = cache_hdr->op_count;
+ r_addr = cache_hdr->read_addr;
+ c_addr = cache_hdr->control_addr;
+ c_value_w = cache_hdr->cache_ctrl.write_value;
+
+ t_r_addr = cache_hdr->tag_reg_addr;
+ t_value = cache_hdr->addr_ctrl.init_tag_value;
+ r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
+
+ for (i = 0; i < loop_count; i++) {
+ qla82xx_md_rw_32(ha, t_r_addr, t_value, 1);
+ qla82xx_md_rw_32(ha, c_addr, c_value_w, 1);
+ addr = r_addr;
+ for (k = 0; k < r_cnt; k++) {
+ r_value = qla82xx_md_rw_32(ha, addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ addr += cache_hdr->read_ctrl.read_addr_stride;
+ }
+ t_value += cache_hdr->addr_ctrl.tag_value_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_queue(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t s_addr, r_addr;
+ uint32_t r_stride, r_value, r_cnt, qid = 0;
+ uint32_t i, k, loop_cnt;
+ struct qla82xx_md_entry_queue *q_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ q_hdr = (struct qla82xx_md_entry_queue *)entry_hdr;
+ s_addr = q_hdr->select_addr;
+ r_cnt = q_hdr->rd_strd.read_addr_cnt;
+ r_stride = q_hdr->rd_strd.read_addr_stride;
+ loop_cnt = q_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, s_addr, qid, 1);
+ r_addr = q_hdr->read_addr;
+ for (k = 0; k < r_cnt; k++) {
+ r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += r_stride;
+ }
+ qid += q_hdr->q_strd.queue_id_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_rdrom(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_value;
+ uint32_t i, loop_cnt;
+ struct qla82xx_md_entry_rdrom *rom_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ rom_hdr = (struct qla82xx_md_entry_rdrom *)entry_hdr;
+ r_addr = rom_hdr->read_addr;
+ loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t);
+
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW,
+ (r_addr & 0xFFFF0000), 1);
+ r_value = qla82xx_md_rw_32(ha,
+ MD_DIRECT_ROM_READ_BASE +
+ (r_addr & 0x0000FFFF), 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += sizeof(uint32_t);
+ }
+ *d_ptr = data_ptr;
+}
+
+static int
+qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_value, r_data;
+ uint32_t i, j, loop_cnt;
+ struct qla82xx_md_entry_rdmem *m_hdr;
+ unsigned long flags;
+ int rval = QLA_FUNCTION_FAILED;
+ uint32_t *data_ptr = *d_ptr;
+
+ m_hdr = (struct qla82xx_md_entry_rdmem *)entry_hdr;
+ r_addr = m_hdr->read_addr;
+ loop_cnt = m_hdr->read_data_size/16;
+
+ if (r_addr & 0xf) {
+ ql_log(ql_log_warn, vha, 0xb033,
+ "Read addr 0x%x not 16 bytes alligned\n", r_addr);
+ return rval;
+ }
+
+ if (m_hdr->read_data_size % 16) {
+ ql_log(ql_log_warn, vha, 0xb034,
+ "Read data[0x%x] not multiple of 16 bytes\n",
+ m_hdr->read_data_size);
+ return rval;
+ }
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb035,
+ "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
+ __func__, r_addr, m_hdr->read_data_size, loop_cnt);
+
+ write_lock_irqsave(&ha->hw_lock, flags);
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1);
+ r_value = 0;
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1);
+ r_value = MIU_TA_CTL_ENABLE;
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
+ r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ r_value = qla82xx_md_rw_32(ha,
+ MD_MIU_TEST_AGT_CTRL, 0, 0);
+ if ((r_value & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk_ratelimited(KERN_ERR
+ "failed to read through agent\n");
+ write_unlock_irqrestore(&ha->hw_lock, flags);
+ return rval;
+ }
+
+ for (j = 0; j < 4; j++) {
+ r_data = qla82xx_md_rw_32(ha,
+ MD_MIU_TEST_AGT_RDDATA[j], 0, 0);
+ *data_ptr++ = cpu_to_le32(r_data);
+ }
+ r_addr += 16;
+ }
+ write_unlock_irqrestore(&ha->hw_lock, flags);
+ *d_ptr = data_ptr;
+ return QLA_SUCCESS;
+}
+
+static int
+qla82xx_validate_template_chksum(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint64_t chksum = 0;
+ uint32_t *d_ptr = (uint32_t *)ha->md_tmplt_hdr;
+ int count = ha->md_template_size/sizeof(uint32_t);
+
+ while (count-- > 0)
+ chksum += *d_ptr++;
+ while (chksum >> 32)
+ chksum = (chksum & 0xFFFFFFFF) + (chksum >> 32);
+ return ~chksum;
+}
+
+static void
+qla82xx_mark_entry_skipped(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, int index)
+{
+ entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
+ ql_dbg(ql_dbg_p3p, vha, 0xb036,
+ "Skipping entry[%d]: "
+ "ETYPE[0x%x]-ELEVEL[0x%x]\n",
+ index, entry_hdr->entry_type,
+ entry_hdr->d_ctrl.entry_capture_mask);
+}
+
+int
+qla82xx_md_collect(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int no_entry_hdr = 0;
+ qla82xx_md_entry_hdr_t *entry_hdr;
+ struct qla82xx_md_template_hdr *tmplt_hdr;
+ uint32_t *data_ptr;
+ uint32_t total_data_size = 0, f_capture_mask, data_collected = 0;
+ int i = 0, rval = QLA_FUNCTION_FAILED;
+
+ tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
+ data_ptr = (uint32_t *)ha->md_dump;
+
+ if (ha->fw_dumped) {
+ ql_log(ql_log_info, vha, 0xb037,
+ "Firmware dump available to retrive\n");
+ goto md_failed;
+ }
+
+ ha->fw_dumped = 0;
+
+ if (!ha->md_tmplt_hdr || !ha->md_dump) {
+ ql_log(ql_log_warn, vha, 0xb038,
+ "Memory not allocated for minidump capture\n");
+ goto md_failed;
+ }
+
+ if (qla82xx_validate_template_chksum(vha)) {
+ ql_log(ql_log_info, vha, 0xb039,
+ "Template checksum validation error\n");
+ goto md_failed;
+ }
+
+ no_entry_hdr = tmplt_hdr->num_of_entries;
+ ql_dbg(ql_dbg_p3p, vha, 0xb03a,
+ "No of entry headers in Template: 0x%x\n", no_entry_hdr);
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb03b,
+ "Capture Mask obtained: 0x%x\n", tmplt_hdr->capture_debug_level);
+
+ f_capture_mask = tmplt_hdr->capture_debug_level & 0xFF;
+
+ /* Validate whether required debug level is set */
+ if ((f_capture_mask & 0x3) != 0x3) {
+ ql_log(ql_log_warn, vha, 0xb03c,
+ "Minimum required capture mask[0x%x] level not set\n",
+ f_capture_mask);
+ goto md_failed;
+ }
+ tmplt_hdr->driver_capture_mask = ql2xmdcapmask;
+
+ tmplt_hdr->driver_info[0] = vha->host_no;
+ tmplt_hdr->driver_info[1] = (QLA_DRIVER_MAJOR_VER << 24) |
+ (QLA_DRIVER_MINOR_VER << 16) | (QLA_DRIVER_PATCH_VER << 8) |
+ QLA_DRIVER_BETA_VER;
+
+ total_data_size = ha->md_dump_size;
+
+ ql_dbg(ql_log_info, vha, 0xb03d,
+ "Total minidump data_size 0x%x to be captured\n", total_data_size);
+
+ /* Check whether template obtained is valid */
+ if (tmplt_hdr->entry_type != QLA82XX_TLHDR) {
+ ql_log(ql_log_warn, vha, 0xb04e,
+ "Bad template header entry type: 0x%x obtained\n",
+ tmplt_hdr->entry_type);
+ goto md_failed;
+ }
+
+ entry_hdr = (qla82xx_md_entry_hdr_t *) \
+ (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
+
+ /* Walk through the entry headers */
+ for (i = 0; i < no_entry_hdr; i++) {
+
+ if (data_collected > total_data_size) {
+ ql_log(ql_log_warn, vha, 0xb03e,
+ "More MiniDump data collected: [0x%x]\n",
+ data_collected);
+ goto md_failed;
+ }
+
+ if (!(entry_hdr->d_ctrl.entry_capture_mask &
+ ql2xmdcapmask)) {
+ entry_hdr->d_ctrl.driver_flags |=
+ QLA82XX_DBG_SKIPPED_FLAG;
+ ql_dbg(ql_dbg_p3p, vha, 0xb03f,
+ "Skipping entry[%d]: "
+ "ETYPE[0x%x]-ELEVEL[0x%x]\n",
+ i, entry_hdr->entry_type,
+ entry_hdr->d_ctrl.entry_capture_mask);
+ goto skip_nxt_entry;
+ }
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb040,
+ "[%s]: data ptr[%d]: %p, entry_hdr: %p\n"
+ "entry_type: 0x%x, captrue_mask: 0x%x\n",
+ __func__, i, data_ptr, entry_hdr,
+ entry_hdr->entry_type,
+ entry_hdr->d_ctrl.entry_capture_mask);
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb041,
+ "Data collected: [0x%x], Dump size left:[0x%x]\n",
+ data_collected, (ha->md_dump_size - data_collected));
+
+ /* Decode the entry type and take
+ * required action to capture debug data */
+ switch (entry_hdr->entry_type) {
+ case QLA82XX_RDEND:
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ break;
+ case QLA82XX_CNTRL:
+ rval = qla82xx_minidump_process_control(vha,
+ entry_hdr, &data_ptr);
+ if (rval != QLA_SUCCESS) {
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ goto md_failed;
+ }
+ break;
+ case QLA82XX_RDCRB:
+ qla82xx_minidump_process_rdcrb(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDMEM:
+ rval = qla82xx_minidump_process_rdmem(vha,
+ entry_hdr, &data_ptr);
+ if (rval != QLA_SUCCESS) {
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ goto md_failed;
+ }
+ break;
+ case QLA82XX_BOARD:
+ case QLA82XX_RDROM:
+ qla82xx_minidump_process_rdrom(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_L2DTG:
+ case QLA82XX_L2ITG:
+ case QLA82XX_L2DAT:
+ case QLA82XX_L2INS:
+ rval = qla82xx_minidump_process_l2tag(vha,
+ entry_hdr, &data_ptr);
+ if (rval != QLA_SUCCESS) {
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ goto md_failed;
+ }
+ break;
+ case QLA82XX_L1DAT:
+ case QLA82XX_L1INS:
+ qla82xx_minidump_process_l1cache(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDOCM:
+ qla82xx_minidump_process_rdocm(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDMUX:
+ qla82xx_minidump_process_rdmux(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_QUEUE:
+ qla82xx_minidump_process_queue(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDNOP:
+ default:
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ break;
+ }
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb042,
+ "[%s]: data ptr[%d]: %p\n", __func__, i, data_ptr);
+
+ data_collected = (uint8_t *)data_ptr -
+ (uint8_t *)ha->md_dump;
+skip_nxt_entry:
+ entry_hdr = (qla82xx_md_entry_hdr_t *) \
+ (((uint8_t *)entry_hdr) + entry_hdr->entry_size);
+ }
+
+ if (data_collected != total_data_size) {
+ ql_dbg(ql_log_warn, vha, 0xb043,
+ "MiniDump data mismatch: Data collected: [0x%x],"
+ "total_data_size:[0x%x]\n",
+ data_collected, total_data_size);
+ goto md_failed;
+ }
+
+ ql_log(ql_log_info, vha, 0xb044,
+ "Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
+ vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
+ ha->fw_dumped = 1;
+ qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
+
+md_failed:
+ return rval;
+}
+
+int
+qla82xx_md_alloc(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int i, k;
+ struct qla82xx_md_template_hdr *tmplt_hdr;
+
+ tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
+
+ if (ql2xmdcapmask < 0x3 || ql2xmdcapmask > 0x7F) {
+ ql2xmdcapmask = tmplt_hdr->capture_debug_level & 0xFF;
+ ql_log(ql_log_info, vha, 0xb045,
+ "Forcing driver capture mask to firmware default capture mask: 0x%x.\n",
+ ql2xmdcapmask);
+ }
+
+ for (i = 0x2, k = 1; (i & QLA82XX_DEFAULT_CAP_MASK); i <<= 1, k++) {
+ if (i & ql2xmdcapmask)
+ ha->md_dump_size += tmplt_hdr->capture_size_array[k];
+ }
+
+ if (ha->md_dump) {
+ ql_log(ql_log_warn, vha, 0xb046,
+ "Firmware dump previously allocated.\n");
+ return 1;
+ }
+
+ ha->md_dump = vmalloc(ha->md_dump_size);
+ if (ha->md_dump == NULL) {
+ ql_log(ql_log_warn, vha, 0xb047,
+ "Unable to allocate memory for Minidump size "
+ "(0x%x).\n", ha->md_dump_size);
+ return 1;
+ }
+ return 0;
+}
+
+void
+qla82xx_md_free(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ /* Release the template header allocated */
+ if (ha->md_tmplt_hdr) {
+ ql_log(ql_log_info, vha, 0xb048,
+ "Free MiniDump template: %p, size (%d KB)\n",
+ ha->md_tmplt_hdr, ha->md_template_size / 1024);
+ dma_free_coherent(&ha->pdev->dev, ha->md_template_size,
+ ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
+ ha->md_tmplt_hdr = 0;
+ }
+
+ /* Release the template data buffer allocated */
+ if (ha->md_dump) {
+ ql_log(ql_log_info, vha, 0xb049,
+ "Free MiniDump memory: %p, size (%d KB)\n",
+ ha->md_dump, ha->md_dump_size / 1024);
+ vfree(ha->md_dump);
+ ha->md_dump_size = 0;
+ ha->md_dump = 0;
+ }
+}
+
+void
+qla82xx_md_prep(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int rval;
+
+ /* Get Minidump template size */
+ rval = qla82xx_md_get_template_size(vha);
+ if (rval == QLA_SUCCESS) {
+ ql_log(ql_log_info, vha, 0xb04a,
+ "MiniDump Template size obtained (%d KB)\n",
+ ha->md_template_size / 1024);
+
+ /* Get Minidump template */
+ rval = qla82xx_md_get_template(vha);
+ if (rval == QLA_SUCCESS) {
+ ql_dbg(ql_dbg_p3p, vha, 0xb04b,
+ "MiniDump Template obtained\n");
+
+ /* Allocate memory for minidump */
+ rval = qla82xx_md_alloc(vha);
+ if (rval == QLA_SUCCESS)
+ ql_log(ql_log_info, vha, 0xb04c,
+ "MiniDump memory allocated (%d KB)\n",
+ ha->md_dump_size / 1024);
+ else {
+ ql_log(ql_log_info, vha, 0xb04d,
+ "Free MiniDump template: %p, size: (%d KB)\n",
+ ha->md_tmplt_hdr,
+ ha->md_template_size / 1024);
+ dma_free_coherent(&ha->pdev->dev,
+ ha->md_template_size,
+ ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
+ ha->md_tmplt_hdr = 0;
+ }
+
+ }
+ }
+}
+
+int
+qla82xx_beacon_on(struct scsi_qla_host *vha)
+{
+
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ qla82xx_idc_lock(ha);
+ rval = qla82xx_mbx_beacon_ctl(vha, 1);
+
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0xb050,
+ "mbx set led config failed in %s\n", __func__);
+ goto exit;
+ }
+ ha->beacon_blink_led = 1;
+exit:
+ qla82xx_idc_unlock(ha);
+ return rval;
+}
+
+int
+qla82xx_beacon_off(struct scsi_qla_host *vha)
+{
+
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ qla82xx_idc_lock(ha);
+ rval = qla82xx_mbx_beacon_ctl(vha, 0);
+
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0xb051,
+ "mbx set led config failed in %s\n", __func__);
+ goto exit;
+ }
+ ha->beacon_blink_led = 0;
+exit:
+ qla82xx_idc_unlock(ha);
+ return rval;
}
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 8a21832..57a226b 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -484,8 +484,6 @@
#define QLA82XX_ADDR_OCM1 (0x0000000200400000ULL)
#define QLA82XX_ADDR_OCM1_MAX (0x00000002004fffffULL)
#define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL)
-
-#define QLA82XX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL)
#define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL)
#define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000
@@ -890,6 +888,7 @@ struct ct6_dsd {
};
#define MBC_TOGGLE_INTERRUPT 0x10
+#define MBC_SET_LED_CONFIG 0x125
/* Flash offset */
#define FLT_REG_BOOTLOAD_82XX 0x72
@@ -922,4 +921,260 @@ struct ct6_dsd {
#define M25P_INSTR_DP 0xb9
#define M25P_INSTR_RES 0xab
+/* Minidump related */
+
+/*
+ * Version of the template
+ * 4 Bytes
+ * X.Major.Minor.RELEASE
+ */
+#define QLA82XX_MINIDUMP_VERSION 0x10101
+
+/*
+ * Entry Type Defines
+ */
+#define QLA82XX_RDNOP 0
+#define QLA82XX_RDCRB 1
+#define QLA82XX_RDMUX 2
+#define QLA82XX_QUEUE 3
+#define QLA82XX_BOARD 4
+#define QLA82XX_RDSRE 5
+#define QLA82XX_RDOCM 6
+#define QLA82XX_CACHE 10
+#define QLA82XX_L1DAT 11
+#define QLA82XX_L1INS 12
+#define QLA82XX_L2DTG 21
+#define QLA82XX_L2ITG 22
+#define QLA82XX_L2DAT 23
+#define QLA82XX_L2INS 24
+#define QLA82XX_RDROM 71
+#define QLA82XX_RDMEM 72
+#define QLA82XX_CNTRL 98
+#define QLA82XX_TLHDR 99
+#define QLA82XX_RDEND 255
+
+/*
+ * Opcodes for Control Entries.
+ * These Flags are bit fields.
+ */
+#define QLA82XX_DBG_OPCODE_WR 0x01
+#define QLA82XX_DBG_OPCODE_RW 0x02
+#define QLA82XX_DBG_OPCODE_AND 0x04
+#define QLA82XX_DBG_OPCODE_OR 0x08
+#define QLA82XX_DBG_OPCODE_POLL 0x10
+#define QLA82XX_DBG_OPCODE_RDSTATE 0x20
+#define QLA82XX_DBG_OPCODE_WRSTATE 0x40
+#define QLA82XX_DBG_OPCODE_MDSTATE 0x80
+
+/*
+ * Template Header and Entry Header definitions start here.
+ */
+
+/*
+ * Template Header
+ * Parts of the template header can be modified by the driver.
+ * These include the saved_state_array, capture_debug_level, driver_timestamp
+ */
+
+#define QLA82XX_DBG_STATE_ARRAY_LEN 16
+#define QLA82XX_DBG_CAP_SIZE_ARRAY_LEN 8
+#define QLA82XX_DBG_RSVD_ARRAY_LEN 8
+
+/*
+ * Driver Flags
+ */
+#define QLA82XX_DBG_SKIPPED_FLAG 0x80 /* driver skipped this entry */
+#define QLA82XX_DEFAULT_CAP_MASK 0xFF /* default capture mask */
+
+struct qla82xx_md_template_hdr {
+ uint32_t entry_type;
+ uint32_t first_entry_offset;
+ uint32_t size_of_template;
+ uint32_t capture_debug_level;
+
+ uint32_t num_of_entries;
+ uint32_t version;
+ uint32_t driver_timestamp;
+ uint32_t template_checksum;
+
+ uint32_t driver_capture_mask;
+ uint32_t driver_info[3];
+
+ uint32_t saved_state_array[QLA82XX_DBG_STATE_ARRAY_LEN];
+ uint32_t capture_size_array[QLA82XX_DBG_CAP_SIZE_ARRAY_LEN];
+
+ /* markers_array used to capture some special locations on board */
+ uint32_t markers_array[QLA82XX_DBG_RSVD_ARRAY_LEN];
+ uint32_t num_of_free_entries; /* For internal use */
+ uint32_t free_entry_offset; /* For internal use */
+ uint32_t total_table_size; /* For internal use */
+ uint32_t bkup_table_offset; /* For internal use */
+} __packed;
+
+/*
+ * Entry Header: Common to All Entry Types
+ */
+
+/*
+ * Driver Code is for driver to write some info about the entry.
+ * Currently not used.
+ */
+typedef struct qla82xx_md_entry_hdr {
+ uint32_t entry_type;
+ uint32_t entry_size;
+ uint32_t entry_capture_size;
+ struct {
+ uint8_t entry_capture_mask;
+ uint8_t entry_code;
+ uint8_t driver_code;
+ uint8_t driver_flags;
+ } d_ctrl;
+} __packed qla82xx_md_entry_hdr_t;
+
+/*
+ * Read CRB entry header
+ */
+struct qla82xx_md_entry_crb {
+ qla82xx_md_entry_hdr_t h;
+ uint32_t addr;
+ struct {
+ uint8_t addr_stride;
+ uint8_t state_index_a;
+ uint16_t poll_timeout;
+ } crb_strd;
+
+ uint32_t data_size;
+ uint32_t op_count;
+
+ struct {
+ uint8_t opcode;
+ uint8_t state_index_v;
+ uint8_t shl;
+ uint8_t shr;
+ } crb_ctrl;
+
+ uint32_t value_1;
+ uint32_t value_2;
+ uint32_t value_3;
+} __packed;
+
+/*
+ * Cache entry header
+ */
+struct qla82xx_md_entry_cache {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t tag_reg_addr;
+ struct {
+ uint16_t tag_value_stride;
+ uint16_t init_tag_value;
+ } addr_ctrl;
+
+ uint32_t data_size;
+ uint32_t op_count;
+
+ uint32_t control_addr;
+ struct {
+ uint16_t write_value;
+ uint8_t poll_mask;
+ uint8_t poll_wait;
+ } cache_ctrl;
+
+ uint32_t read_addr;
+ struct {
+ uint8_t read_addr_stride;
+ uint8_t read_addr_cnt;
+ uint16_t rsvd_1;
+ } read_ctrl;
+} __packed;
+
+/*
+ * Read OCM
+ */
+struct qla82xx_md_entry_rdocm {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t rsvd_0;
+ uint32_t rsvd_1;
+ uint32_t data_size;
+ uint32_t op_count;
+
+ uint32_t rsvd_2;
+ uint32_t rsvd_3;
+ uint32_t read_addr;
+ uint32_t read_addr_stride;
+ uint32_t read_addr_cntrl;
+} __packed;
+
+/*
+ * Read Memory
+ */
+struct qla82xx_md_entry_rdmem {
+ qla82xx_md_entry_hdr_t h;
+ uint32_t rsvd[6];
+ uint32_t read_addr;
+ uint32_t read_data_size;
+} __packed;
+
+/*
+ * Read ROM
+ */
+struct qla82xx_md_entry_rdrom {
+ qla82xx_md_entry_hdr_t h;
+ uint32_t rsvd[6];
+ uint32_t read_addr;
+ uint32_t read_data_size;
+} __packed;
+
+struct qla82xx_md_entry_mux {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t select_addr;
+ uint32_t rsvd_0;
+ uint32_t data_size;
+ uint32_t op_count;
+
+ uint32_t select_value;
+ uint32_t select_value_stride;
+ uint32_t read_addr;
+ uint32_t rsvd_1;
+} __packed;
+
+struct qla82xx_md_entry_queue {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t select_addr;
+ struct {
+ uint16_t queue_id_stride;
+ uint16_t rsvd_0;
+ } q_strd;
+
+ uint32_t data_size;
+ uint32_t op_count;
+ uint32_t rsvd_1;
+ uint32_t rsvd_2;
+
+ uint32_t read_addr;
+ struct {
+ uint8_t read_addr_stride;
+ uint8_t read_addr_cnt;
+ uint16_t rsvd_3;
+ } rd_strd;
+} __packed;
+
+#define MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE 0x129
+#define RQST_TMPLT_SIZE 0x0
+#define RQST_TMPLT 0x1
+#define MD_DIRECT_ROM_WINDOW 0x42110030
+#define MD_DIRECT_ROM_READ_BASE 0x42150000
+#define MD_MIU_TEST_AGT_CTRL 0x41000090
+#define MD_MIU_TEST_AGT_ADDR_LO 0x41000094
+#define MD_MIU_TEST_AGT_ADDR_HI 0x41000098
+
+static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC,
+ 0x410000B8, 0x410000BC };
+
+#define CRB_NIU_XG_PAUSE_CTL_P0 0x1
+#define CRB_NIU_XG_PAUSE_CTL_P1 0x8
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7e78020..82a5ca6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -35,6 +35,10 @@ static struct kmem_cache *srb_cachep;
* CT6 CTX allocation cache
*/
static struct kmem_cache *ctx_cachep;
+/*
+ * error level for logging
+ */
+int ql_errlev = ql_log_all;
int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO);
@@ -69,8 +73,17 @@ MODULE_PARM_DESC(ql2xallocfwdump,
int ql2xextended_error_logging;
module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xextended_error_logging,
- "Option to enable extended error logging, "
- "Default is 0 - no logging. 1 - log errors.");
+ "Option to enable extended error logging,\n"
+ "\t\tDefault is 0 - no logging. 0x40000000 - Module Init & Probe.\n"
+ "\t\t0x20000000 - Mailbox Cmnds. 0x10000000 - Device Discovery.\n"
+ "\t\t0x08000000 - IO tracing. 0x04000000 - DPC Thread.\n"
+ "\t\t0x02000000 - Async events. 0x01000000 - Timer routines.\n"
+ "\t\t0x00800000 - User space. 0x00400000 - Task Management.\n"
+ "\t\t0x00200000 - AER/EEH. 0x00100000 - Multi Q.\n"
+ "\t\t0x00080000 - P3P Specific. 0x00040000 - Virtual Port.\n"
+ "\t\t0x00020000 - Buffer Dump. 0x00010000 - Misc.\n"
+ "\t\t0x7fffffff - For enabling all logs, can be too many logs.\n"
+ "\t\tDo LOGICAL OR of the value to enable more than one level");
int ql2xshiftctondsd = 6;
module_param(ql2xshiftctondsd, int, S_IRUGO);
@@ -93,17 +106,21 @@ MODULE_PARM_DESC(ql2xmaxqdepth,
"Maximum queue depth to report for target devices.");
/* Do not change the value of this after module load */
-int ql2xenabledif = 1;
+int ql2xenabledif = 0;
module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenabledif,
" Enable T10-CRC-DIF "
- " Default is 0 - No DIF Support. 1 - Enable it");
+ " Default is 0 - No DIF Support. 1 - Enable it"
+ ", 2 - Enable DIF for all types, except Type 0.");
-int ql2xenablehba_err_chk;
+int ql2xenablehba_err_chk = 2;
module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenablehba_err_chk,
- " Enable T10-CRC-DIF Error isolation by HBA"
- " Default is 0 - Error isolation disabled, 1 - Enable it");
+ " Enable T10-CRC-DIF Error isolation by HBA:\n"
+ " Default is 1.\n"
+ " 0 -- Error isolation disabled\n"
+ " 1 -- Error isolation enabled only for DIX Type 0\n"
+ " 2 -- Error isolation enabled for all Types\n");
int ql2xiidmaenable=1;
module_param(ql2xiidmaenable, int, S_IRUGO);
@@ -126,10 +143,10 @@ MODULE_PARM_DESC(ql2xmultique_tag,
"Set it to 1 to turn on the cpu affinity.");
int ql2xfwloadbin;
-module_param(ql2xfwloadbin, int, S_IRUGO);
+module_param(ql2xfwloadbin, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xfwloadbin,
- "Option to specify location from which to load ISP firmware:\n"
- " 2 -- load firmware via the request_firmware() (hotplug)\n"
+ "Option to specify location from which to load ISP firmware:.\n"
+ " 2 -- load firmware via the request_firmware() (hotplug).\n"
" interface.\n"
" 1 -- load firmware from flash.\n"
" 0 -- use default semantics.\n");
@@ -141,11 +158,11 @@ MODULE_PARM_DESC(ql2xetsenable,
"Default is 0 - skip ETS enablement.");
int ql2xdbwr = 1;
-module_param(ql2xdbwr, int, S_IRUGO);
+module_param(ql2xdbwr, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xdbwr,
- "Option to specify scheme for request queue posting\n"
- " 0 -- Regular doorbell.\n"
- " 1 -- CAMRAM doorbell (faster).\n");
+ "Option to specify scheme for request queue posting.\n"
+ " 0 -- Regular doorbell.\n"
+ " 1 -- CAMRAM doorbell (faster).\n");
int ql2xtargetreset = 1;
module_param(ql2xtargetreset, int, S_IRUGO);
@@ -166,11 +183,11 @@ MODULE_PARM_DESC(ql2xasynctmfenable,
"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
int ql2xdontresethba;
-module_param(ql2xdontresethba, int, S_IRUGO);
+module_param(ql2xdontresethba, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xdontresethba,
- "Option to specify reset behaviour\n"
- " 0 (Default) -- Reset on failure.\n"
- " 1 -- Do not reset on failure.\n");
+ "Option to specify reset behaviour.\n"
+ " 0 (Default) -- Reset on failure.\n"
+ " 1 -- Do not reset on failure.\n");
uint ql2xmaxlun = MAX_LUNS;
module_param(ql2xmaxlun, uint, S_IRUGO);
@@ -178,6 +195,19 @@ MODULE_PARM_DESC(ql2xmaxlun,
"Defines the maximum LU number to register with the SCSI "
"midlayer. Default is 65535.");
+int ql2xmdcapmask = 0x1F;
+module_param(ql2xmdcapmask, int, S_IRUGO);
+MODULE_PARM_DESC(ql2xmdcapmask,
+ "Set the Minidump driver capture mask level. "
+ "Default is 0x7F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F.");
+
+int ql2xmdenable = 1;
+module_param(ql2xmdenable, int, S_IRUGO);
+MODULE_PARM_DESC(ql2xmdenable,
+ "Enable/disable MiniDump. "
+ "0 - MiniDump disabled. "
+ "1 (Default) - MiniDump enabled.");
+
/*
* SCSI host template entry points
*/
@@ -247,8 +277,11 @@ static inline void
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
{
/* Currently used for 82XX only. */
- if (vha->device_flags & DFLG_DEV_FAILED)
+ if (vha->device_flags & DFLG_DEV_FAILED) {
+ ql_dbg(ql_dbg_timer, vha, 0x600d,
+ "Device in a failed state, returning.\n");
return;
+ }
mod_timer(&vha->timer, jiffies + interval * HZ);
}
@@ -273,19 +306,20 @@ static void qla2x00_sp_free_dma(srb_t *);
/* -------------------------------------------------------------------------- */
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
GFP_KERNEL);
if (!ha->req_q_map) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for request queue ptrs\n");
+ ql_log(ql_log_fatal, vha, 0x003b,
+ "Unable to allocate memory for request queue ptrs.\n");
goto fail_req_map;
}
ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
GFP_KERNEL);
if (!ha->rsp_q_map) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for response queue ptrs\n");
+ ql_log(ql_log_fatal, vha, 0x003c,
+ "Unable to allocate memory for response queue ptrs.\n");
goto fail_rsp_map;
}
set_bit(0, ha->rsp_qid_map);
@@ -349,8 +383,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
struct qla_hw_data *ha = vha->hw;
if (!(ha->fw_attributes & BIT_6)) {
- qla_printk(KERN_INFO, ha,
- "Firmware is not multi-queue capable\n");
+ ql_log(ql_log_warn, vha, 0x00d8,
+ "Firmware is not multi-queue capable.\n");
goto fail;
}
if (ql2xmultique_tag) {
@@ -359,8 +393,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
req = qla25xx_create_req_que(ha, options, 0, 0, -1,
QLA_DEFAULT_QUE_QOS);
if (!req) {
- qla_printk(KERN_WARNING, ha,
- "Can't create request queue\n");
+ ql_log(ql_log_warn, vha, 0x00e0,
+ "Failed to create request queue.\n");
goto fail;
}
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
@@ -369,23 +403,27 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
for (ques = 1; ques < ha->max_rsp_queues; ques++) {
ret = qla25xx_create_rsp_que(ha, options, 0, 0, req);
if (!ret) {
- qla_printk(KERN_WARNING, ha,
- "Response Queue create failed\n");
+ ql_log(ql_log_warn, vha, 0x00e8,
+ "Failed to create response queue.\n");
goto fail2;
}
}
ha->flags.cpu_affinity_enabled = 1;
-
- DEBUG2(qla_printk(KERN_INFO, ha,
- "CPU affinity mode enabled, no. of response"
- " queues:%d, no. of request queues:%d\n",
- ha->max_rsp_queues, ha->max_req_queues));
+ ql_dbg(ql_dbg_multiq, vha, 0xc007,
+ "CPU affinity mode enalbed, "
+ "no. of response queues:%d no. of request queues:%d.\n",
+ ha->max_rsp_queues, ha->max_req_queues);
+ ql_dbg(ql_dbg_init, vha, 0x00e9,
+ "CPU affinity mode enalbed, "
+ "no. of response queues:%d no. of request queues:%d.\n",
+ ha->max_rsp_queues, ha->max_req_queues);
}
return 0;
fail2:
qla25xx_delete_queues(vha);
destroy_workqueue(ha->wq);
ha->wq = NULL;
+ vha->req = ha->req_q_map[0];
fail:
ha->mqenable = 0;
kfree(ha->req_q_map);
@@ -526,8 +564,11 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
struct qla_hw_data *ha = vha->hw;
sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
- if (!sp)
+ if (!sp) {
+ ql_log(ql_log_warn, vha, 0x3006,
+ "Memory allocation failed for sp.\n");
return sp;
+ }
atomic_set(&sp->ref_count, 1);
sp->fcport = fcport;
@@ -551,30 +592,43 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
int rval;
if (ha->flags.eeh_busy) {
- if (ha->flags.pci_channel_io_perm_failure)
+ if (ha->flags.pci_channel_io_perm_failure) {
+ ql_dbg(ql_dbg_io, vha, 0x3001,
+ "PCI Channel IO permanent failure, exiting "
+ "cmd=%p.\n", cmd);
cmd->result = DID_NO_CONNECT << 16;
- else
+ } else {
+ ql_dbg(ql_dbg_io, vha, 0x3002,
+ "EEH_Busy, Requeuing the cmd=%p.\n", cmd);
cmd->result = DID_REQUEUE << 16;
+ }
goto qc24_fail_command;
}
rval = fc_remote_port_chkready(rport);
if (rval) {
cmd->result = rval;
+ ql_dbg(ql_dbg_io, vha, 0x3003,
+ "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n",
+ cmd, rval);
goto qc24_fail_command;
}
if (!vha->flags.difdix_supported &&
scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
- DEBUG2(qla_printk(KERN_ERR, ha,
- "DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
- cmd->cmnd[0]));
+ ql_dbg(ql_dbg_io, vha, 0x3004,
+ "DIF Cap not reg, fail DIF capable cmd's:%p.\n",
+ cmd);
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
+ ql_dbg(ql_dbg_io, vha, 0x3005,
+ "Returning DNC, fcport_state=%d loop_state=%d.\n",
+ atomic_read(&fcport->state),
+ atomic_read(&base_vha->loop_state));
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
@@ -586,8 +640,11 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto qc24_host_busy;
rval = ha->isp_ops->start_scsi(sp);
- if (rval != QLA_SUCCESS)
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_io, vha, 0x3013,
+ "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd);
goto qc24_host_busy_free_sp;
+ }
return 0;
@@ -630,7 +687,8 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
int ret = QLA_SUCCESS;
if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
- DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
+ ql_dbg(ql_dbg_taskm, vha, 0x8005,
+ "Return:eh_wait.\n");
return ret;
}
@@ -723,7 +781,8 @@ qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
else
return_status = QLA_FUNCTION_FAILED;
- DEBUG2(printk("%s return_status=%d\n", __func__, return_status));
+ ql_dbg(ql_dbg_taskm, vha, 0x8019,
+ "%s return status=%d.\n", __func__, return_status);
return return_status;
}
@@ -756,49 +815,6 @@ qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
return return_status;
}
-/*
- * qla2x00_wait_for_loop_ready
- * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
- * to be in LOOP_READY state.
- * Input:
- * ha - pointer to host adapter structure
- *
- * Note:
- * Does context switching-Release SPIN_LOCK
- * (if any) before calling this routine.
- *
- *
- * Return:
- * Success (LOOP_READY) : 0
- * Failed (LOOP_NOT_READY) : 1
- */
-static inline int
-qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
-{
- int return_status = QLA_SUCCESS;
- unsigned long loop_timeout ;
- struct qla_hw_data *ha = vha->hw;
- scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
-
- /* wait for 5 min at the max for loop to be ready */
- loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ);
-
- while ((!atomic_read(&base_vha->loop_down_timer) &&
- atomic_read(&base_vha->loop_state) == LOOP_DOWN) ||
- atomic_read(&base_vha->loop_state) != LOOP_READY) {
- if (atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
- return_status = QLA_FUNCTION_FAILED;
- break;
- }
- msleep(1000);
- if (time_after_eq(jiffies, loop_timeout)) {
- return_status = QLA_FUNCTION_FAILED;
- break;
- }
- }
- return (return_status);
-}
-
static void
sp_get(struct srb *sp)
{
@@ -831,10 +847,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
int wait = 0;
struct qla_hw_data *ha = vha->hw;
+ ql_dbg(ql_dbg_taskm, vha, 0x8000,
+ "Entered %s for cmd=%p.\n", __func__, cmd);
if (!CMD_SP(cmd))
return SUCCESS;
ret = fc_block_scsi_eh(cmd);
+ ql_dbg(ql_dbg_taskm, vha, 0x8001,
+ "Return value of fc_block_scsi_eh=%d.\n", ret);
if (ret != 0)
return ret;
ret = SUCCESS;
@@ -849,37 +869,41 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
return SUCCESS;
}
- DEBUG2(printk("%s(%ld): aborting sp %p from RISC.",
- __func__, vha->host_no, sp));
+ ql_dbg(ql_dbg_taskm, vha, 0x8002,
+ "Aborting sp=%p cmd=%p from RISC ", sp, cmd);
/* Get a reference to the sp and drop the lock.*/
sp_get(sp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
- DEBUG2(printk("%s(%ld): abort_command "
- "mbx failed.\n", __func__, vha->host_no));
- ret = FAILED;
+ ql_dbg(ql_dbg_taskm, vha, 0x8003,
+ "Abort command mbx failed for cmd=%p.\n", cmd);
} else {
- DEBUG3(printk("%s(%ld): abort_command "
- "mbx success.\n", __func__, vha->host_no));
+ ql_dbg(ql_dbg_taskm, vha, 0x8004,
+ "Abort command mbx success.\n");
wait = 1;
}
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_sp_compl(ha, sp);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /* Did the command return during mailbox execution? */
+ if (ret == FAILED && !CMD_SP(cmd))
+ ret = SUCCESS;
/* Wait for the command to be returned. */
if (wait) {
if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
- qla_printk(KERN_ERR, ha,
- "scsi(%ld:%d:%d): Abort handler timed out -- %x.\n",
- vha->host_no, id, lun, ret);
+ ql_log(ql_log_warn, vha, 0x8006,
+ "Abort handler timed out for cmd=%p.\n", cmd);
ret = FAILED;
}
}
- qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): Abort command issued -- %d %x.\n",
- vha->host_no, id, lun, wait, ret);
+ ql_log(ql_log_info, vha, 0x801c,
+ "Abort command issued -- %d %x.\n", wait, ret);
return ret;
}
@@ -947,40 +971,53 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
int err;
- if (!fcport)
+ if (!fcport) {
+ ql_log(ql_log_warn, vha, 0x8007,
+ "fcport is NULL.\n");
return FAILED;
+ }
err = fc_block_scsi_eh(cmd);
+ ql_dbg(ql_dbg_taskm, vha, 0x8008,
+ "fc_block_scsi_eh ret=%d.\n", err);
if (err != 0)
return err;
- qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
- vha->host_no, cmd->device->id, cmd->device->lun, name);
+ ql_log(ql_log_info, vha, 0x8009,
+ "%s RESET ISSUED for id %d lun %d cmd=%p.\n", name,
+ cmd->device->id, cmd->device->lun, cmd);
err = 0;
- if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
- goto eh_reset_failed;
- err = 1;
- if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800a,
+ "Wait for hba online failed for cmd=%p.\n", cmd);
goto eh_reset_failed;
+ }
err = 2;
if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
- != QLA_SUCCESS)
+ != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800c,
+ "do_reset failed for cmd=%p.\n", cmd);
goto eh_reset_failed;
+ }
err = 3;
if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
- cmd->device->lun, type) != QLA_SUCCESS)
+ cmd->device->lun, type) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800d,
+ "wait for peding cmds failed for cmd=%p.\n", cmd);
goto eh_reset_failed;
+ }
- qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
- vha->host_no, cmd->device->id, cmd->device->lun, name);
+ ql_log(ql_log_info, vha, 0x800e,
+ "%s RESET SUCCEEDED for id %d lun %d cmd=%p.\n", name,
+ cmd->device->id, cmd->device->lun, cmd);
return SUCCESS;
eh_reset_failed:
- qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n"
- , vha->host_no, cmd->device->id, cmd->device->lun, name,
- reset_errors[err]);
+ ql_log(ql_log_info, vha, 0x800f,
+ "%s RESET FAILED: %s for id %d lun %d cmd=%p.\n", name,
+ reset_errors[err], cmd->device->id, cmd->device->lun);
return FAILED;
}
@@ -1030,37 +1067,45 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
id = cmd->device->id;
lun = cmd->device->lun;
- if (!fcport)
+ if (!fcport) {
+ ql_log(ql_log_warn, vha, 0x8010,
+ "fcport is NULL.\n");
return ret;
+ }
ret = fc_block_scsi_eh(cmd);
+ ql_dbg(ql_dbg_taskm, vha, 0x8011,
+ "fc_block_scsi_eh ret=%d.\n", ret);
if (ret != 0)
return ret;
ret = FAILED;
- qla_printk(KERN_INFO, vha->hw,
- "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
+ ql_log(ql_log_info, vha, 0x8012,
+ "BUS RESET ISSUED for id %d lun %d.\n", id, lun);
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
- DEBUG2(printk("%s failed:board disabled\n",__func__));
+ ql_log(ql_log_fatal, vha, 0x8013,
+ "Wait for hba online failed board disabled.\n");
goto eh_bus_reset_done;
}
- if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
- if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
- ret = SUCCESS;
- }
+ if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
+ ret = SUCCESS;
+
if (ret == FAILED)
goto eh_bus_reset_done;
/* Flush outstanding commands. */
if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) !=
- QLA_SUCCESS)
+ QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x8014,
+ "Wait for pending commands failed.\n");
ret = FAILED;
+ }
eh_bus_reset_done:
- qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
- (ret == FAILED) ? "failed" : "succeeded");
+ ql_log(ql_log_warn, vha, 0x802b,
+ "BUS RESET %s.\n", (ret == FAILED) ? "FAILED" : "SUCCEDED");
return ret;
}
@@ -1093,29 +1138,25 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
id = cmd->device->id;
lun = cmd->device->lun;
- if (!fcport)
+ if (!fcport) {
+ ql_log(ql_log_warn, vha, 0x8016,
+ "fcport is NULL.\n");
return ret;
+ }
ret = fc_block_scsi_eh(cmd);
+ ql_dbg(ql_dbg_taskm, vha, 0x8017,
+ "fc_block_scsi_eh ret=%d.\n", ret);
if (ret != 0)
return ret;
ret = FAILED;
- qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
+ ql_log(ql_log_info, vha, 0x8018,
+ "ADAPTER RESET ISSUED for id %d lun %d.\n", id, lun);
if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS)
goto eh_host_reset_lock;
- /*
- * Fixme-may be dpc thread is active and processing
- * loop_resync,so wait a while for it to
- * be completed and then issue big hammer.Otherwise
- * it may cause I/O failure as big hammer marks the
- * devices as lost kicking of the port_down_timer
- * while dpc is stuck for the mailbox to complete.
- */
- qla2x00_wait_for_loop_ready(vha);
if (vha != base_vha) {
if (qla2x00_vp_abort_isp(vha))
goto eh_host_reset_lock;
@@ -1137,8 +1178,11 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
/* failed. schedule dpc to try */
set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
- if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x802a,
+ "wait for hba online failed.\n");
goto eh_host_reset_lock;
+ }
}
clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
}
@@ -1149,7 +1193,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
ret = SUCCESS;
eh_host_reset_lock:
- qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
+ qla_printk(KERN_INFO, ha, "%s: reset %s.\n", __func__,
(ret == FAILED) ? "failed" : "succeeded");
return ret;
@@ -1179,9 +1223,9 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
ret = ha->isp_ops->target_reset(fcport, 0, 0);
if (ret != QLA_SUCCESS) {
- DEBUG2_3(printk("%s(%ld): bus_reset failed: "
- "target_reset=%d d_id=%x.\n", __func__,
- vha->host_no, ret, fcport->d_id.b24));
+ ql_dbg(ql_dbg_taskm, vha, 0x802c,
+ "Bus Reset failed: Target Reset=%d "
+ "d_id=%x.\n", ret, fcport->d_id.b24);
}
}
}
@@ -1189,23 +1233,19 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
if (ha->flags.enable_lip_full_login && !IS_QLA8XXX_TYPE(ha)) {
ret = qla2x00_full_login_lip(vha);
if (ret != QLA_SUCCESS) {
- DEBUG2_3(printk("%s(%ld): failed: "
- "full_login_lip=%d.\n", __func__, vha->host_no,
- ret));
+ ql_dbg(ql_dbg_taskm, vha, 0x802d,
+ "full_login_lip=%d.\n", ret);
}
atomic_set(&vha->loop_state, LOOP_DOWN);
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
qla2x00_mark_all_devices_lost(vha, 0);
- qla2x00_wait_for_loop_ready(vha);
}
if (ha->flags.enable_lip_reset) {
ret = qla2x00_lip_reset(vha);
- if (ret != QLA_SUCCESS) {
- DEBUG2_3(printk("%s(%ld): failed: "
- "lip_reset=%d.\n", __func__, vha->host_no, ret));
- } else
- qla2x00_wait_for_loop_ready(vha);
+ if (ret != QLA_SUCCESS)
+ ql_dbg(ql_dbg_taskm, vha, 0x802e,
+ "lip_reset failed (%d).\n", ret);
}
/* Issue marker command only when we are going to start the I/O */
@@ -1303,17 +1343,17 @@ static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
if (!scsi_track_queue_full(sdev, qdepth))
return;
- DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
- "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
- fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
- sdev->queue_depth));
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3029,
+ "Queue depth adjusted-down "
+ "to %d for scsi(%ld:%d:%d:%d).\n",
+ sdev->queue_depth, fcport->vha->host_no,
+ sdev->channel, sdev->id, sdev->lun);
}
static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
{
fc_port_t *fcport = sdev->hostdata;
struct scsi_qla_host *vha = fcport->vha;
- struct qla_hw_data *ha = vha->hw;
struct req_que *req = NULL;
req = vha->req;
@@ -1328,10 +1368,11 @@ static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
else
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
- fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
- sdev->queue_depth));
+ ql_dbg(ql_dbg_io, vha, 0x302a,
+ "Queue depth adjusted-up to %d for "
+ "scsi(%ld:%d:%d:%d).\n",
+ sdev->queue_depth, fcport->vha->host_no,
+ sdev->channel, sdev->id, sdev->lun);
}
static int
@@ -1661,9 +1702,9 @@ static struct isp_operations qla82xx_isp_ops = {
.read_nvram = qla24xx_read_nvram_data,
.write_nvram = qla24xx_write_nvram_data,
.fw_dump = qla24xx_fw_dump,
- .beacon_on = qla24xx_beacon_on,
- .beacon_off = qla24xx_beacon_off,
- .beacon_blink = qla24xx_beacon_blink,
+ .beacon_on = qla82xx_beacon_on,
+ .beacon_off = qla82xx_beacon_off,
+ .beacon_blink = NULL,
.read_optrom = qla82xx_read_optrom_data,
.write_optrom = qla82xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
@@ -1777,6 +1818,9 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->flags.port0 = 1;
else
ha->flags.port0 = 0;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x000b,
+ "device_type=0x%x port=%d fw_srisc_address=%p.\n",
+ ha->device_type, ha->flags.port0, ha->fw_srisc_address);
}
static int
@@ -1791,10 +1835,9 @@ qla2x00_iospace_config(struct qla_hw_data *ha)
if (pci_request_selected_regions(ha->pdev, ha->bars,
QLA2XXX_DRIVER_NAME)) {
- qla_printk(KERN_WARNING, ha,
- "Failed to reserve PIO/MMIO regions (%s)\n",
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0011,
+ "Failed to reserve PIO/MMIO regions (%s), aborting.\n",
pci_name(ha->pdev));
-
goto iospace_error_exit;
}
if (!(ha->bars & 1))
@@ -1804,39 +1847,42 @@ qla2x00_iospace_config(struct qla_hw_data *ha)
pio = pci_resource_start(ha->pdev, 0);
if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
- qla_printk(KERN_WARNING, ha,
- "Invalid PCI I/O region size (%s)...\n",
- pci_name(ha->pdev));
+ ql_log_pci(ql_log_warn, ha->pdev, 0x0012,
+ "Invalid pci I/O region size (%s).\n",
+ pci_name(ha->pdev));
pio = 0;
}
} else {
- qla_printk(KERN_WARNING, ha,
- "region #0 not a PIO resource (%s)...\n",
+ ql_log_pci(ql_log_warn, ha->pdev, 0x0013,
+ "Region #0 no a PIO resource (%s).\n",
pci_name(ha->pdev));
pio = 0;
}
ha->pio_address = pio;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0014,
+ "PIO address=%p.\n",
+ ha->pio_address);
skip_pio:
/* Use MMIO operations for all accesses. */
if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
- qla_printk(KERN_ERR, ha,
- "region #1 not an MMIO resource (%s), aborting\n",
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0015,
+ "Region #1 not an MMIO resource (%s), aborting.\n",
pci_name(ha->pdev));
goto iospace_error_exit;
}
if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
- qla_printk(KERN_ERR, ha,
- "Invalid PCI mem region size (%s), aborting\n",
- pci_name(ha->pdev));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0016,
+ "Invalid PCI mem region size (%s), aborting.\n",
+ pci_name(ha->pdev));
goto iospace_error_exit;
}
ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
if (!ha->iobase) {
- qla_printk(KERN_ERR, ha,
- "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
-
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0017,
+ "Cannot remap MMIO (%s), aborting.\n",
+ pci_name(ha->pdev));
goto iospace_error_exit;
}
@@ -1850,6 +1896,8 @@ skip_pio:
ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3),
pci_resource_len(ha->pdev, 3));
if (ha->mqiobase) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0018,
+ "MQIO Base=%p.\n", ha->mqiobase);
/* Read MSIX vector size of the board */
pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix);
ha->msix_count = msix;
@@ -1862,17 +1910,24 @@ skip_pio:
ha->max_req_queues = 2;
} else if (ql2xmaxqueues > 1) {
ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ?
- QLA_MQ_SIZE : ql2xmaxqueues;
- DEBUG2(qla_printk(KERN_INFO, ha, "QoS mode set, max no"
- " of request queues:%d\n", ha->max_req_queues));
+ QLA_MQ_SIZE : ql2xmaxqueues;
+ ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc008,
+ "QoS mode set, max no of request queues:%d.\n",
+ ha->max_req_queues);
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0019,
+ "QoS mode set, max no of request queues:%d.\n",
+ ha->max_req_queues);
}
- qla_printk(KERN_INFO, ha,
- "MSI-X vector count: %d\n", msix);
+ ql_log_pci(ql_log_info, ha->pdev, 0x001a,
+ "MSI-X vector count: %d.\n", msix);
} else
- qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
+ ql_log_pci(ql_log_info, ha->pdev, 0x001b,
+ "BAR 3 not enabled.\n");
mqiobase_exit:
ha->msix_count = ha->max_rsp_queues + 1;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x001c,
+ "MSIX Count:%d.\n", ha->msix_count);
return (0);
iospace_error_exit:
@@ -1936,7 +1991,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
mem_only = 1;
+ ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
+ "Mem only adapter.\n");
}
+ ql_dbg_pci(ql_dbg_init, pdev, 0x0008,
+ "Bars=%d.\n", bars);
if (mem_only) {
if (pci_enable_device_mem(pdev))
@@ -1951,9 +2010,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL);
if (!ha) {
- DEBUG(printk("Unable to allocate memory for ha\n"));
+ ql_log_pci(ql_log_fatal, pdev, 0x0009,
+ "Unable to allocate memory for ha.\n");
goto probe_out;
}
+ ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
+ "Memory allocated for ha=%p.\n", ha);
ha->pdev = pdev;
/* Clear our data area */
@@ -1975,10 +2037,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto probe_hw_failed;
- qla_printk(KERN_INFO, ha,
- "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
- ha->iobase);
-
+ ql_log_pci(ql_log_info, pdev, 0x001d,
+ "Found an ISP%04X irq %d iobase 0x%p.\n",
+ pdev->device, pdev->irq, ha->iobase);
ha->prev_topology = 0;
ha->init_cb_size = sizeof(init_cb_t);
ha->link_data_rate = PORT_SPEED_UNKNOWN;
@@ -2079,7 +2140,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
}
-
+ ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
+ "mbx_count=%d, req_length=%d, "
+ "rsp_length=%d, max_loop_id=%d, init_cb_size=%d, "
+ "gid_list_info_size=%d, optrom_size=%d, nvram_npiv_size=%d, .\n",
+ ha->mbx_count, req_length, rsp_length, ha->max_loop_id,
+ ha->init_cb_size, ha->gid_list_info_size, ha->optrom_size,
+ ha->nvram_npiv_size);
+ ql_dbg_pci(ql_dbg_init, pdev, 0x001f,
+ "isp_ops=%p, flash_conf_off=%d, "
+ "flash_data_off=%d, nvram_conf_off=%d, nvram_data_off=%d.\n",
+ ha->isp_ops, ha->flash_conf_off, ha->flash_data_off,
+ ha->nvram_conf_off, ha->nvram_data_off);
mutex_init(&ha->vport_lock);
init_completion(&ha->mbx_cmd_comp);
complete(&ha->mbx_cmd_comp);
@@ -2089,10 +2161,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
set_bit(0, (unsigned long *) ha->vp_idx_map);
qla2x00_config_dma_addressing(ha);
+ ql_dbg_pci(ql_dbg_init, pdev, 0x0020,
+ "64 Bit addressing is %s.\n",
+ ha->flags.enable_64bit_addressing ? "enable" :
+ "disable");
ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
if (!ret) {
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Failed to allocate memory for adapter\n");
+ ql_log_pci(ql_log_fatal, pdev, 0x0031,
+ "Failed to allocate memory for adapter, aborting.\n");
goto probe_hw_failed;
}
@@ -2104,9 +2180,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
base_vha = qla2x00_create_host(sht, ha);
if (!base_vha) {
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Failed to allocate memory for scsi_host\n");
-
ret = -ENOMEM;
qla2x00_mem_free(ha);
qla2x00_free_req_que(ha, req);
@@ -2133,12 +2206,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (!IS_QLA82XX(ha))
host->sg_tablesize = QLA_SG_ALL;
}
-
+ ql_dbg(ql_dbg_init, base_vha, 0x0032,
+ "can_queue=%d, req=%p, "
+ "mgmt_svr_loop_id=%d, sg_tablesize=%d.\n",
+ host->can_queue, base_vha->req,
+ base_vha->mgmt_svr_loop_id, host->sg_tablesize);
host->max_id = max_id;
host->this_id = 255;
host->cmd_per_lun = 3;
host->unique_id = host->host_no;
- if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif)
+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif)
host->max_cmd_len = 32;
else
host->max_cmd_len = MAX_CMDSZ;
@@ -2147,6 +2224,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->transportt = qla2xxx_transport_template;
sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC);
+ ql_dbg(ql_dbg_init, base_vha, 0x0033,
+ "max_id=%d this_id=%d "
+ "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d "
+ "max_lun=%d transportt=%p, vendor_id=%d.\n", host->max_id,
+ host->this_id, host->cmd_per_lun, host->unique_id,
+ host->max_cmd_len, host->max_channel, host->max_lun,
+ host->transportt, sht->vendor_id);
+
/* Set up the irqs */
ret = qla2x00_request_irqs(ha, rsp);
if (ret)
@@ -2157,9 +2242,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Alloc arrays of request and response ring ptrs */
que_init:
if (!qla2x00_alloc_queues(ha)) {
- qla_printk(KERN_WARNING, ha,
- "[ERROR] Failed to allocate memory for queue"
- " pointers\n");
+ ql_log(ql_log_fatal, base_vha, 0x003d,
+ "Failed to allocate memory for queue pointers.. aborting.\n");
goto probe_init_failed;
}
@@ -2187,20 +2271,33 @@ que_init:
rsp->rsp_q_out = &ha->iobase->isp82.rsp_q_out[0];
}
- if (qla2x00_initialize_adapter(base_vha)) {
- qla_printk(KERN_WARNING, ha,
- "Failed to initialize adapter\n");
+ ql_dbg(ql_dbg_multiq, base_vha, 0xc009,
+ "rsp_q_map=%p req_q_map=%p rsp->req=%p req->rsp=%p.\n",
+ ha->rsp_q_map, ha->req_q_map, rsp->req, req->rsp);
+ ql_dbg(ql_dbg_multiq, base_vha, 0xc00a,
+ "req->req_q_in=%p req->req_q_out=%p "
+ "rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
+ req->req_q_in, req->req_q_out,
+ rsp->rsp_q_in, rsp->rsp_q_out);
+ ql_dbg(ql_dbg_init, base_vha, 0x003e,
+ "rsp_q_map=%p req_q_map=%p rsp->req=%p req->rsp=%p.\n",
+ ha->rsp_q_map, ha->req_q_map, rsp->req, req->rsp);
+ ql_dbg(ql_dbg_init, base_vha, 0x003f,
+ "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
+ req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
- DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
- "Adapter flags %x.\n",
- base_vha->host_no, base_vha->device_flags));
+ if (qla2x00_initialize_adapter(base_vha)) {
+ ql_log(ql_log_fatal, base_vha, 0x00d6,
+ "Failed to initialize adapter - Adapter flags %x.\n",
+ base_vha->device_flags);
if (IS_QLA82XX(ha)) {
qla82xx_idc_lock(ha);
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
QLA82XX_DEV_FAILED);
qla82xx_idc_unlock(ha);
- qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+ ql_log(ql_log_fatal, base_vha, 0x00d7,
+ "HW State: FAILED.\n");
}
ret = -ENODEV;
@@ -2209,9 +2306,8 @@ que_init:
if (ha->mqenable) {
if (qla25xx_setup_mode(base_vha)) {
- qla_printk(KERN_WARNING, ha,
- "Can't create queues, falling back to single"
- " queue mode\n");
+ ql_log(ql_log_warn, base_vha, 0x00ec,
+ "Failed to create queues, falling back to single queue mode.\n");
goto que_init;
}
}
@@ -2223,13 +2319,15 @@ que_init:
* Startup the kernel thread for this host adapter
*/
ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
- "%s_dpc", base_vha->host_str);
+ "%s_dpc", base_vha->host_str);
if (IS_ERR(ha->dpc_thread)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to start DPC thread!\n");
+ ql_log(ql_log_fatal, base_vha, 0x00ed,
+ "Failed to start DPC thread.\n");
ret = PTR_ERR(ha->dpc_thread);
goto probe_failed;
}
+ ql_dbg(ql_dbg_init, base_vha, 0x00ee,
+ "DPC thread started successfully.\n");
skip_dpc:
list_add_tail(&base_vha->list, &ha->vp_list);
@@ -2237,18 +2335,23 @@ skip_dpc:
/* Initialized the timer */
qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
-
- DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
- base_vha->host_no, ha));
-
- if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) {
+ ql_dbg(ql_dbg_init, base_vha, 0x00ef,
+ "Started qla2x00_timer with "
+ "interval=%d.\n", WATCH_INTERVAL);
+ ql_dbg(ql_dbg_init, base_vha, 0x00f0,
+ "Detected hba at address=%p.\n",
+ ha);
+
+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4) {
+ int prot = 0;
base_vha->flags.difdix_supported = 1;
- DEBUG18(qla_printk(KERN_INFO, ha,
- "Registering for DIF/DIX type 1 and 3"
- " protection.\n"));
+ ql_dbg(ql_dbg_init, base_vha, 0x00f1,
+ "Registering for DIF/DIX type 1 and 3 protection.\n");
+ if (ql2xenabledif == 1)
+ prot = SHOST_DIX_TYPE0_PROTECTION;
scsi_host_set_prot(host,
- SHOST_DIF_TYPE1_PROTECTION
+ prot | SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE2_PROTECTION
| SHOST_DIF_TYPE3_PROTECTION
| SHOST_DIX_TYPE1_PROTECTION
@@ -2268,6 +2371,9 @@ skip_dpc:
base_vha->flags.init_done = 1;
base_vha->flags.online = 1;
+ ql_dbg(ql_dbg_init, base_vha, 0x00f2,
+ "Init done and hba is online.\n");
+
scsi_scan_host(host);
qla2x00_alloc_sysfs_attr(base_vha);
@@ -2276,14 +2382,17 @@ skip_dpc:
qla2x00_dfs_setup(base_vha);
- qla_printk(KERN_INFO, ha, "\n"
- " QLogic Fibre Channel HBA Driver: %s\n"
- " QLogic %s - %s\n"
- " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
- qla2x00_version_str, ha->model_number,
- ha->model_desc ? ha->model_desc : "", pdev->device,
- ha->isp_ops->pci_info_str(base_vha, pci_info), pci_name(pdev),
- ha->flags.enable_64bit_addressing ? '+' : '-', base_vha->host_no,
+ ql_log(ql_log_info, base_vha, 0x00fa,
+ "QLogic Fibre Channed HBA Driver: %s.\n",
+ qla2x00_version_str);
+ ql_log(ql_log_info, base_vha, 0x00fb,
+ "QLogic %s - %s.\n",
+ ha->model_number, ha->model_desc ? ha->model_desc : "");
+ ql_log(ql_log_info, base_vha, 0x00fc,
+ "ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n",
+ pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info),
+ pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-',
+ base_vha->host_no,
ha->isp_ops->fw_version_str(base_vha, fw_str));
return 0;
@@ -2513,6 +2622,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
qla2x00_mem_free(ha);
+ qla82xx_md_free(vha);
+
qla2x00_free_queues(ha);
}
@@ -2581,20 +2692,15 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
fcport->login_retry = vha->hw->login_retry_count;
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
- DEBUG(printk("scsi(%ld): Port login retry: "
+ ql_dbg(ql_dbg_disc, vha, 0x2067,
+ "Port login retry "
"%02x%02x%02x%02x%02x%02x%02x%02x, "
- "id = 0x%04x retry cnt=%d\n",
- vha->host_no,
- fcport->port_name[0],
- fcport->port_name[1],
- fcport->port_name[2],
- fcport->port_name[3],
- fcport->port_name[4],
- fcport->port_name[5],
- fcport->port_name[6],
- fcport->port_name[7],
- fcport->loop_id,
- fcport->login_retry));
+ "id = 0x%04x retry cnt=%d.\n",
+ fcport->port_name[0], fcport->port_name[1],
+ fcport->port_name[2], fcport->port_name[3],
+ fcport->port_name[4], fcport->port_name[5],
+ fcport->port_name[6], fcport->port_name[7],
+ fcport->loop_id, fcport->login_retry);
}
}
@@ -2677,6 +2783,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
ctx_cachep);
if (!ha->ctx_mempool)
goto fail_free_srb_mempool;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0021,
+ "ctx_cachep=%p ctx_mempool=%p.\n",
+ ctx_cachep, ha->ctx_mempool);
}
/* Get memory for cached NVRAM */
@@ -2691,22 +2800,29 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
if (!ha->s_dma_pool)
goto fail_free_nvram;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0022,
+ "init_cb=%p gid_list=%p, srb_mempool=%p s_dma_pool=%p.\n",
+ ha->init_cb, ha->gid_list, ha->srb_mempool, ha->s_dma_pool);
+
if (IS_QLA82XX(ha) || ql2xenabledif) {
ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
DSD_LIST_DMA_POOL_SIZE, 8, 0);
if (!ha->dl_dma_pool) {
- qla_printk(KERN_WARNING, ha,
- "Memory Allocation failed - dl_dma_pool\n");
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0023,
+ "Failed to allocate memory for dl_dma_pool.\n");
goto fail_s_dma_pool;
}
ha->fcp_cmnd_dma_pool = dma_pool_create(name, &ha->pdev->dev,
FCP_CMND_DMA_POOL_SIZE, 8, 0);
if (!ha->fcp_cmnd_dma_pool) {
- qla_printk(KERN_WARNING, ha,
- "Memory Allocation failed - fcp_cmnd_dma_pool\n");
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0024,
+ "Failed to allocate memory for fcp_cmnd_dma_pool.\n");
goto fail_dl_dma_pool;
}
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0025,
+ "dl_dma_pool=%p fcp_cmnd_dma_pool=%p.\n",
+ ha->dl_dma_pool, ha->fcp_cmnd_dma_pool);
}
/* Allocate memory for SNS commands */
@@ -2716,6 +2832,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
if (!ha->sns_cmd)
goto fail_dma_pool;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0026,
+ "sns_cmd.\n", ha->sns_cmd);
} else {
/* Get consistent memory allocated for MS IOCB */
ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
@@ -2727,12 +2845,16 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
if (!ha->ct_sns)
goto fail_free_ms_iocb;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0027,
+ "ms_iocb=%p ct_sns=%p.\n",
+ ha->ms_iocb, ha->ct_sns);
}
/* Allocate memory for request ring */
*req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
if (!*req) {
- DEBUG(printk("Unable to allocate memory for req\n"));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0028,
+ "Failed to allocate memory for req.\n");
goto fail_req;
}
(*req)->length = req_len;
@@ -2740,14 +2862,15 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
((*req)->length + 1) * sizeof(request_t),
&(*req)->dma, GFP_KERNEL);
if (!(*req)->ring) {
- DEBUG(printk("Unable to allocate memory for req_ring\n"));
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0029,
+ "Failed to allocate memory for req_ring.\n");
goto fail_req_ring;
}
/* Allocate memory for response ring */
*rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
if (!*rsp) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for rsp\n");
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x002a,
+ "Failed to allocate memory for rsp.\n");
goto fail_rsp;
}
(*rsp)->hw = ha;
@@ -2756,19 +2879,24 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
((*rsp)->length + 1) * sizeof(response_t),
&(*rsp)->dma, GFP_KERNEL);
if (!(*rsp)->ring) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for rsp_ring\n");
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x002b,
+ "Failed to allocate memory for rsp_ring.\n");
goto fail_rsp_ring;
}
(*req)->rsp = *rsp;
(*rsp)->req = *req;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002c,
+ "req=%p req->length=%d req->ring=%p rsp=%p "
+ "rsp->length=%d rsp->ring=%p.\n",
+ *req, (*req)->length, (*req)->ring, *rsp, (*rsp)->length,
+ (*rsp)->ring);
/* Allocate memory for NVRAM data for vports */
if (ha->nvram_npiv_size) {
ha->npiv_info = kzalloc(sizeof(struct qla_npiv_entry) *
- ha->nvram_npiv_size, GFP_KERNEL);
+ ha->nvram_npiv_size, GFP_KERNEL);
if (!ha->npiv_info) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for npiv info\n");
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x002d,
+ "Failed to allocate memory for npiv_info.\n");
goto fail_npiv_info;
}
} else
@@ -2780,6 +2908,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
&ha->ex_init_cb_dma);
if (!ha->ex_init_cb)
goto fail_ex_init_cb;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002e,
+ "ex_init_cb=%p.\n", ha->ex_init_cb);
}
INIT_LIST_HEAD(&ha->gbl_dsd_list);
@@ -2790,6 +2920,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
&ha->async_pd_dma);
if (!ha->async_pd)
goto fail_async_pd;
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002f,
+ "async_pd=%p.\n", ha->async_pd);
}
INIT_LIST_HEAD(&ha->vp_list);
@@ -2855,7 +2987,8 @@ fail_free_init_cb:
ha->init_cb = NULL;
ha->init_cb_dma = 0;
fail:
- DEBUG(printk("%s: Memory allocation failure\n", __func__));
+ ql_log(ql_log_fatal, NULL, 0x0030,
+ "Memory allocation failure.\n");
return -ENOMEM;
}
@@ -3004,8 +3137,8 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) {
- printk(KERN_WARNING
- "qla2xxx: Couldn't allocate host from scsi layer!\n");
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0107,
+ "Failed to allocate host from the scsi layer, aborting.\n");
goto fail;
}
@@ -3024,6 +3157,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
spin_lock_init(&vha->work_lock);
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
+ ql_dbg(ql_dbg_init, vha, 0x0041,
+ "Allocated the host=%p hw=%p vha=%p dev_name=%s",
+ vha->host, vha->hw, vha,
+ dev_name(&(ha->pdev->dev)));
+
return vha;
fail:
@@ -3265,18 +3403,18 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
if (status == QLA_SUCCESS) {
fcport->old_loop_id = fcport->loop_id;
- DEBUG(printk("scsi(%ld): port login OK: logged "
- "in ID 0x%x\n", vha->host_no, fcport->loop_id));
+ ql_dbg(ql_dbg_disc, vha, 0x2003,
+ "Port login OK: logged in ID 0x%x.\n",
+ fcport->loop_id);
qla2x00_update_fcport(vha, fcport);
} else if (status == 1) {
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
/* retry the login again */
- DEBUG(printk("scsi(%ld): Retrying"
- " %d login again loop_id 0x%x\n",
- vha->host_no, fcport->login_retry,
- fcport->loop_id));
+ ql_dbg(ql_dbg_disc, vha, 0x2007,
+ "Retrying %d login again loop_id 0x%x.\n",
+ fcport->login_retry, fcport->loop_id);
} else {
fcport->login_retry = 0;
}
@@ -3316,26 +3454,27 @@ qla2x00_do_dpc(void *data)
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
- DEBUG3(printk("qla2x00: DPC handler sleeping\n"));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4000,
+ "DPC handler sleeping.\n");
schedule();
__set_current_state(TASK_RUNNING);
- DEBUG3(printk("qla2x00: DPC handler waking up\n"));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4001,
+ "DPC handler waking up.\n");
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4002,
+ "dpc_flags=0x%lx.\n", base_vha->dpc_flags);
/* Initialization not yet finished. Don't do anything yet. */
if (!base_vha->flags.init_done)
continue;
if (ha->flags.eeh_busy) {
- DEBUG17(qla_printk(KERN_WARNING, ha,
- "qla2x00_do_dpc: dpc_flags: %lx\n",
- base_vha->dpc_flags));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4003,
+ "eeh_busy=%d.\n", ha->flags.eeh_busy);
continue;
}
- DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
-
ha->dpc_active = 1;
if (ha->flags.mbox_busy) {
@@ -3352,8 +3491,8 @@ qla2x00_do_dpc(void *data)
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
QLA82XX_DEV_FAILED);
qla82xx_idc_unlock(ha);
- qla_printk(KERN_INFO, ha,
- "HW State: FAILED\n");
+ ql_log(ql_log_info, base_vha, 0x4004,
+ "HW State: FAILED.\n");
qla82xx_device_state_handler(base_vha);
continue;
}
@@ -3361,10 +3500,8 @@ qla2x00_do_dpc(void *data)
if (test_and_clear_bit(FCOE_CTX_RESET_NEEDED,
&base_vha->dpc_flags)) {
- DEBUG(printk(KERN_INFO
- "scsi(%ld): dpc: sched "
- "qla82xx_fcoe_ctx_reset ha = %p\n",
- base_vha->host_no, ha));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4005,
+ "FCoE context reset scheduled.\n");
if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
&base_vha->dpc_flags))) {
if (qla82xx_fcoe_ctx_reset(base_vha)) {
@@ -3378,18 +3515,16 @@ qla2x00_do_dpc(void *data)
&base_vha->dpc_flags);
}
- DEBUG(printk("scsi(%ld): dpc:"
- " qla82xx_fcoe_ctx_reset end\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4006,
+ "FCoE context reset end.\n");
}
}
if (test_and_clear_bit(ISP_ABORT_NEEDED,
&base_vha->dpc_flags)) {
- DEBUG(printk("scsi(%ld): dpc: sched "
- "qla2x00_abort_isp ha = %p\n",
- base_vha->host_no, ha));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4007,
+ "ISP abort scheduled.\n");
if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
&base_vha->dpc_flags))) {
@@ -3402,8 +3537,8 @@ qla2x00_do_dpc(void *data)
&base_vha->dpc_flags);
}
- DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4008,
+ "ISP abort end.\n");
}
if (test_and_clear_bit(FCPORT_UPDATE_NEEDED,
@@ -3412,9 +3547,8 @@ qla2x00_do_dpc(void *data)
}
if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
- DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched "
- "qla2x00_quiesce_needed ha = %p\n",
- base_vha->host_no, ha));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
+ "Quiescence mode scheduled.\n");
qla82xx_device_state_handler(base_vha);
clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags);
if (!ha->flags.quiesce_owner) {
@@ -3424,17 +3558,20 @@ qla2x00_do_dpc(void *data)
qla82xx_clear_qsnt_ready(base_vha);
qla82xx_idc_unlock(ha);
}
+ ql_dbg(ql_dbg_dpc, base_vha, 0x400a,
+ "Quiescence mode end.\n");
}
if (test_and_clear_bit(RESET_MARKER_NEEDED,
&base_vha->dpc_flags) &&
(!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
- DEBUG(printk("scsi(%ld): qla2x00_reset_marker()\n",
- base_vha->host_no));
-
+ ql_dbg(ql_dbg_dpc, base_vha, 0x400b,
+ "Reset marker scheduled.\n");
qla2x00_rst_aen(base_vha);
clear_bit(RESET_ACTIVE, &base_vha->dpc_flags);
+ ql_dbg(ql_dbg_dpc, base_vha, 0x400c,
+ "Reset marker end.\n");
}
/* Retry each device up to login retry count */
@@ -3443,19 +3580,18 @@ qla2x00_do_dpc(void *data)
!test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags) &&
atomic_read(&base_vha->loop_state) != LOOP_DOWN) {
- DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x400d,
+ "Relogin scheduled.\n");
qla2x00_relogin(base_vha);
-
- DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x400e,
+ "Relogin end.\n");
}
if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
&base_vha->dpc_flags)) {
- DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x400f,
+ "Loop resync scheduled.\n");
if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,
&base_vha->dpc_flags))) {
@@ -3466,8 +3602,8 @@ qla2x00_do_dpc(void *data)
&base_vha->dpc_flags);
}
- DEBUG(printk("scsi(%ld): qla2x00_loop_resync - end\n",
- base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4010,
+ "Loop resync end.\n");
}
if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&
@@ -3490,7 +3626,8 @@ qla2x00_do_dpc(void *data)
} /* End of while(1) */
__set_current_state(TASK_RUNNING);
- DEBUG(printk("scsi(%ld): DPC handler exiting\n", base_vha->host_no));
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4011,
+ "DPC handler exiting.\n");
/*
* Make sure that nobody tries to wake us up again.
@@ -3597,9 +3734,11 @@ void
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
{
if (atomic_read(&sp->ref_count) == 0) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "SP reference-count to ZERO -- sp=%p\n", sp));
- DEBUG2(BUG());
+ ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015,
+ "SP reference-count to ZERO -- sp=%p cmd=%p.\n",
+ sp, sp->cmd);
+ if (ql2xextended_error_logging & ql_dbg_io)
+ BUG();
return;
}
if (!atomic_dec_and_test(&sp->ref_count))
@@ -3627,6 +3766,9 @@ qla2x00_timer(scsi_qla_host_t *vha)
struct req_que *req;
if (ha->flags.eeh_busy) {
+ ql_dbg(ql_dbg_timer, vha, 0x6000,
+ "EEH = %d, restarting timer.\n",
+ ha->flags.eeh_busy);
qla2x00_restart_timer(vha, WATCH_INTERVAL);
return;
}
@@ -3651,9 +3793,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
if (atomic_read(&vha->loop_down_timer) ==
vha->loop_down_abort_time) {
- DEBUG(printk("scsi(%ld): Loop Down - aborting the "
- "queues before time expire\n",
- vha->host_no));
+ ql_log(ql_log_info, vha, 0x6008,
+ "Loop down - aborting the queues before time expires.\n");
if (!IS_QLA2100(ha) && vha->link_down_timeout)
atomic_set(&vha->loop_state, LOOP_DEAD);
@@ -3698,10 +3839,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
/* if the loop has been down for 4 minutes, reinit adapter */
if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
if (!(vha->device_flags & DFLG_NO_CABLE)) {
- DEBUG(printk("scsi(%ld): Loop down - "
- "aborting ISP.\n",
- vha->host_no));
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x6009,
"Loop down - aborting ISP.\n");
if (IS_QLA82XX(ha))
@@ -3712,15 +3850,18 @@ qla2x00_timer(scsi_qla_host_t *vha)
&vha->dpc_flags);
}
}
- DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
- vha->host_no,
- atomic_read(&vha->loop_down_timer)));
+ ql_dbg(ql_dbg_timer, vha, 0x600a,
+ "Loop down - seconds remaining %d.\n",
+ atomic_read(&vha->loop_down_timer));
}
/* Check if beacon LED needs to be blinked for physical host only */
if (!vha->vp_idx && (ha->beacon_blink_led == 1)) {
- set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
- start_dpc++;
+ /* There is no beacon_blink function for ISP82xx */
+ if (!IS_QLA82XX(ha)) {
+ set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
+ start_dpc++;
+ }
}
/* Process any deferred work. */
@@ -3737,8 +3878,27 @@ qla2x00_timer(scsi_qla_host_t *vha)
test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) ||
test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) ||
test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
- test_bit(RELOGIN_NEEDED, &vha->dpc_flags)))
+ test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) {
+ ql_dbg(ql_dbg_timer, vha, 0x600b,
+ "isp_abort_needed=%d loop_resync_needed=%d "
+ "fcport_update_needed=%d start_dpc=%d "
+ "reset_marker_needed=%d",
+ test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags),
+ test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags),
+ test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags),
+ start_dpc,
+ test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags));
+ ql_dbg(ql_dbg_timer, vha, 0x600c,
+ "beacon_blink_needed=%d isp_unrecoverable=%d "
+ "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d "
+ "relogin_needed=%d.\n",
+ test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags),
+ test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags),
+ test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags),
+ test_bit(VP_DPC_NEEDED, &vha->dpc_flags),
+ test_bit(RELOGIN_NEEDED, &vha->dpc_flags));
qla2xxx_wake_dpc(vha);
+ }
qla2x00_restart_timer(vha, WATCH_INTERVAL);
}
@@ -3807,8 +3967,8 @@ qla2x00_request_firmware(scsi_qla_host_t *vha)
goto out;
if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
- DEBUG2(printk("scsi(%ld): Failed to load firmware image "
- "(%s).\n", vha->host_no, blob->name));
+ ql_log(ql_log_warn, vha, 0x0063,
+ "Failed to load firmware image (%s).\n", blob->name);
blob->fw = NULL;
blob = NULL;
goto out;
@@ -3837,8 +3997,8 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
scsi_qla_host_t *vha = pci_get_drvdata(pdev);
struct qla_hw_data *ha = vha->hw;
- DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n",
- state));
+ ql_dbg(ql_dbg_aer, vha, 0x9000,
+ "PCI error detected, state %x.\n", state);
switch (state) {
case pci_channel_io_normal:
@@ -3849,13 +4009,8 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
/* For ISP82XX complete any pending mailbox cmd */
if (IS_QLA82XX(ha)) {
ha->flags.isp82xx_fw_hung = 1;
- if (ha->flags.mbox_busy) {
- ha->flags.mbox_int = 1;
- DEBUG2(qla_printk(KERN_ERR, ha,
- "Due to pci channel io frozen, doing premature "
- "completion of mbx command\n"));
- complete(&ha->mbx_intr_comp);
- }
+ ql_dbg(ql_dbg_aer, vha, 0x9001, "Pci channel io frozen\n");
+ qla82xx_clear_pending_mbx(vha);
}
qla2x00_free_irqs(vha);
pci_disable_device(pdev);
@@ -3901,8 +4056,8 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (risc_paused) {
- qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, "
- "Dumping firmware!\n");
+ ql_log(ql_log_info, base_vha, 0x9003,
+ "RISC paused -- mmio_enabled, Dumping firmware.\n");
ha->isp_ops->fw_dump(base_vha, 0);
return PCI_ERS_RESULT_NEED_RESET;
@@ -3918,8 +4073,8 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
int fn;
struct pci_dev *other_pdev = NULL;
- DEBUG17(qla_printk(KERN_INFO, ha,
- "scsi(%ld): In qla82xx_error_recovery\n", base_vha->host_no));
+ ql_dbg(ql_dbg_aer, base_vha, 0x9006,
+ "Entered %s.\n", __func__);
set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
@@ -3933,8 +4088,8 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
fn = PCI_FUNC(ha->pdev->devfn);
while (fn > 0) {
fn--;
- DEBUG17(qla_printk(KERN_INFO, ha,
- "Finding pci device at function = 0x%x\n", fn));
+ ql_dbg(ql_dbg_aer, base_vha, 0x9007,
+ "Finding pci device at function = 0x%x.\n", fn);
other_pdev =
pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
@@ -3943,9 +4098,9 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
if (!other_pdev)
continue;
if (atomic_read(&other_pdev->enable_cnt)) {
- DEBUG17(qla_printk(KERN_INFO, ha,
- "Found PCI func available and enabled at 0x%x\n",
- fn));
+ ql_dbg(ql_dbg_aer, base_vha, 0x9008,
+ "Found PCI func available and enable at 0x%x.\n",
+ fn);
pci_dev_put(other_pdev);
break;
}
@@ -3954,8 +4109,9 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
if (!fn) {
/* Reset owner */
- DEBUG17(qla_printk(KERN_INFO, ha,
- "This devfn is reset owner = 0x%x\n", ha->pdev->devfn));
+ ql_dbg(ql_dbg_aer, base_vha, 0x9009,
+ "This devfn is reset owner = 0x%x.\n",
+ ha->pdev->devfn);
qla82xx_idc_lock(ha);
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
@@ -3965,8 +4121,8 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
QLA82XX_IDC_VERSION);
drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
- DEBUG17(qla_printk(KERN_INFO, ha,
- "drv_active = 0x%x\n", drv_active));
+ ql_dbg(ql_dbg_aer, base_vha, 0x900a,
+ "drv_active = 0x%x.\n", drv_active);
qla82xx_idc_unlock(ha);
/* Reset if device is not already reset
@@ -3979,12 +4135,14 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
qla82xx_idc_lock(ha);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+ ql_log(ql_log_info, base_vha, 0x900b,
+ "HW State: FAILED.\n");
qla82xx_clear_drv_active(ha);
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
QLA82XX_DEV_FAILED);
} else {
- qla_printk(KERN_INFO, ha, "HW State: READY\n");
+ ql_log(ql_log_info, base_vha, 0x900c,
+ "HW State: READY.\n");
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
QLA82XX_DEV_READY);
qla82xx_idc_unlock(ha);
@@ -3997,8 +4155,9 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
}
qla82xx_idc_unlock(ha);
} else {
- DEBUG17(qla_printk(KERN_INFO, ha,
- "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
+ ql_dbg(ql_dbg_aer, base_vha, 0x900d,
+ "This devfn is not reset owner = 0x%x.\n",
+ ha->pdev->devfn);
if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
QLA82XX_DEV_READY)) {
ha->flags.isp82xx_fw_hung = 0;
@@ -4022,7 +4181,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
struct rsp_que *rsp;
int rc, retries = 10;
- DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n"));
+ ql_dbg(ql_dbg_aer, base_vha, 0x9004,
+ "Slot Reset.\n");
/* Workaround: qla2xxx driver which access hardware earlier
* needs error state to be pci_channel_io_online.
@@ -4043,7 +4203,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
rc = pci_enable_device(pdev);
if (rc) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, base_vha, 0x9005,
"Can't re-enable PCI device after reset.\n");
goto exit_slot_reset;
}
@@ -4073,8 +4233,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
exit_slot_reset:
- DEBUG17(qla_printk(KERN_WARNING, ha,
- "slot_reset-return:ret=%x\n", ret));
+ ql_dbg(ql_dbg_aer, base_vha, 0x900e,
+ "slot_reset return %x.\n", ret);
return ret;
}
@@ -4086,13 +4246,13 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
struct qla_hw_data *ha = base_vha->hw;
int ret;
- DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n"));
+ ql_dbg(ql_dbg_aer, base_vha, 0x900f,
+ "pci_resume.\n");
ret = qla2x00_wait_for_hba_online(base_vha);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_ERR, ha,
- "the device failed to resume I/O "
- "from slot/link_reset");
+ ql_log(ql_log_fatal, base_vha, 0x9002,
+ "The device failed to resume I/O from slot/link_reset.\n");
}
pci_cleanup_aer_uncorrect_error_status(pdev);
@@ -4156,8 +4316,8 @@ qla2x00_module_init(void)
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
SLAB_HWCACHE_ALIGN, NULL);
if (srb_cachep == NULL) {
- printk(KERN_ERR
- "qla2xxx: Unable to allocate SRB cache...Failing load!\n");
+ ql_log(ql_log_fatal, NULL, 0x0001,
+ "Unable to allocate SRB cache...Failing load!.\n");
return -ENOMEM;
}
@@ -4170,13 +4330,15 @@ qla2x00_module_init(void)
fc_attach_transport(&qla2xxx_transport_functions);
if (!qla2xxx_transport_template) {
kmem_cache_destroy(srb_cachep);
+ ql_log(ql_log_fatal, NULL, 0x0002,
+ "fc_attach_transport failed...Failing load!.\n");
return -ENODEV;
}
apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops);
if (apidev_major < 0) {
- printk(KERN_WARNING "qla2xxx: Unable to register char device "
- "%s\n", QLA2XXX_APIDEV);
+ ql_log(ql_log_fatal, NULL, 0x0003,
+ "Unable to register char device %s.\n", QLA2XXX_APIDEV);
}
qla2xxx_transport_vport_template =
@@ -4184,16 +4346,21 @@ qla2x00_module_init(void)
if (!qla2xxx_transport_vport_template) {
kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
+ ql_log(ql_log_fatal, NULL, 0x0004,
+ "fc_attach_transport vport failed...Failing load!.\n");
return -ENODEV;
}
-
- printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
+ ql_log(ql_log_info, NULL, 0x0005,
+ "QLogic Fibre Channel HBA Driver: %s.\n",
qla2x00_version_str);
ret = pci_register_driver(&qla2xxx_pci_driver);
if (ret) {
kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
fc_release_transport(qla2xxx_transport_vport_template);
+ ql_log(ql_log_fatal, NULL, 0x0006,
+ "pci_register_driver failed...ret=%d Failing load!.\n",
+ ret);
}
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 6936476..eff1356 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -189,6 +189,7 @@ qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, uint16_t data)
uint16_t word;
uint32_t nv_cmd, wait_cnt;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
@@ -220,8 +221,8 @@ qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, uint16_t data)
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
- DEBUG9_10(qla_printk(KERN_WARNING, ha,
- "NVRAM didn't go ready...\n"));
+ ql_dbg(ql_dbg_user, vha, 0x708d,
+ "NVRAM didn't go ready...\n");
break;
}
NVRAM_DELAY();
@@ -308,6 +309,7 @@ qla2x00_clear_nvram_protection(struct qla_hw_data *ha)
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t word, wait_cnt;
uint16_t wprot, wprot_old;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
/* Clear NVRAM write protection. */
ret = QLA_FUNCTION_FAILED;
@@ -350,8 +352,8 @@ qla2x00_clear_nvram_protection(struct qla_hw_data *ha)
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
- DEBUG9_10(qla_printk(KERN_WARNING, ha,
- "NVRAM didn't go ready...\n"));
+ ql_dbg(ql_dbg_user, vha, 0x708e,
+ "NVRAM didn't go ready...\n");
break;
}
NVRAM_DELAY();
@@ -371,6 +373,7 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
{
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t word, wait_cnt;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
if (stat != QLA_SUCCESS)
return;
@@ -409,8 +412,8 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
- DEBUG9_10(qla_printk(KERN_WARNING, ha,
- "NVRAM didn't go ready...\n"));
+ ql_dbg(ql_dbg_user, vha, 0x708f,
+ "NVRAM didn't go ready...\n");
break;
}
NVRAM_DELAY();
@@ -607,9 +610,10 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
for (chksum = 0; cnt; cnt--)
chksum += le16_to_cpu(*wptr++);
if (chksum) {
- qla_printk(KERN_ERR, ha,
+ ql_log(ql_log_fatal, vha, 0x0045,
"Inconsistent FLTL detected: checksum=0x%x.\n", chksum);
- qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location));
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010e,
+ buf, sizeof(struct qla_flt_location));
return QLA_FUNCTION_FAILED;
}
@@ -618,7 +622,9 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
*start = (le16_to_cpu(fltl->start_hi) << 16 |
le16_to_cpu(fltl->start_lo)) >> 2;
end:
- DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start));
+ ql_dbg(ql_dbg_init, vha, 0x0046,
+ "FLTL[%s] = 0x%x.\n",
+ loc, *start);
return QLA_SUCCESS;
}
@@ -685,10 +691,10 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
if (*wptr == __constant_cpu_to_le16(0xffff))
goto no_flash_data;
if (flt->version != __constant_cpu_to_le16(1)) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: "
- "version=0x%x length=0x%x checksum=0x%x.\n",
+ ql_log(ql_log_warn, vha, 0x0047,
+ "Unsupported FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
le16_to_cpu(flt->version), le16_to_cpu(flt->length),
- le16_to_cpu(flt->checksum)));
+ le16_to_cpu(flt->checksum));
goto no_flash_data;
}
@@ -696,10 +702,10 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
for (chksum = 0; cnt; cnt--)
chksum += le16_to_cpu(*wptr++);
if (chksum) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: "
- "version=0x%x length=0x%x checksum=0x%x.\n",
+ ql_log(ql_log_fatal, vha, 0x0048,
+ "Inconsistent FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
le16_to_cpu(flt->version), le16_to_cpu(flt->length),
- chksum));
+ le16_to_cpu(flt->checksum));
goto no_flash_data;
}
@@ -708,10 +714,11 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
for ( ; cnt; cnt--, region++) {
/* Store addresses as DWORD offsets. */
start = le32_to_cpu(region->start) >> 2;
-
- DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x "
- "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
- le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
+ ql_dbg(ql_dbg_init, vha, 0x0049,
+ "FLT[%02x]: start=0x%x "
+ "end=0x%x size=0x%x.\n", le32_to_cpu(region->code),
+ start, le32_to_cpu(region->end) >> 2,
+ le32_to_cpu(region->size));
switch (le32_to_cpu(region->code) & 0xff) {
case FLT_REG_FW:
@@ -796,12 +803,16 @@ no_flash_data:
ha->flt_region_npiv_conf = ha->flags.port0 ?
def_npiv_conf0[def] : def_npiv_conf1[def];
done:
- DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
- "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
- "npiv=0x%x. fcp_prio_cfg=0x%x\n", loc, ha->flt_region_boot,
- ha->flt_region_fw, ha->flt_region_vpd_nvram, ha->flt_region_vpd,
- ha->flt_region_nvram, ha->flt_region_fdt, ha->flt_region_flt,
- ha->flt_region_npiv_conf, ha->flt_region_fcp_prio));
+ ql_dbg(ql_dbg_init, vha, 0x004a,
+ "FLT[%s]: boot=0x%x fw=0x%x vpd_nvram=0x%x vpd=0x%x.\n",
+ loc, ha->flt_region_boot,
+ ha->flt_region_fw, ha->flt_region_vpd_nvram,
+ ha->flt_region_vpd);
+ ql_dbg(ql_dbg_init, vha, 0x004b,
+ "nvram=0x%x fdt=0x%x flt=0x%x npiv=0x%x fcp_prif_cfg=0x%x.\n",
+ ha->flt_region_nvram,
+ ha->flt_region_fdt, ha->flt_region_flt,
+ ha->flt_region_npiv_conf, ha->flt_region_fcp_prio);
}
static void
@@ -833,10 +844,12 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
cnt++)
chksum += le16_to_cpu(*wptr++);
if (chksum) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FDT detected: "
- "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0],
- le16_to_cpu(fdt->version)));
- DEBUG9(qla2x00_dump_buffer((uint8_t *)fdt, sizeof(*fdt)));
+ ql_dbg(ql_dbg_init, vha, 0x004c,
+ "Inconsistent FDT detected:"
+ " checksum=0x%x id=%c version0x%x.\n", chksum,
+ fdt->sig[0], le16_to_cpu(fdt->version));
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0113,
+ (uint8_t *)fdt, sizeof(*fdt));
goto no_flash_data;
}
@@ -890,11 +903,12 @@ no_flash_data:
break;
}
done:
- DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x "
- "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
+ ql_dbg(ql_dbg_init, vha, 0x004d,
+ "FDT[%x]: (0x%x/0x%x) erase=0x%x "
+ "pr=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
- ha->fdt_unprotect_sec_cmd, ha->fdt_wrt_disable,
- ha->fdt_block_size));
+ ha->fdt_wrt_disable, ha->fdt_block_size);
+
}
static void
@@ -919,6 +933,10 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha)
ha->nx_dev_init_timeout = le32_to_cpu(*wptr++);
ha->nx_reset_timeout = le32_to_cpu(*wptr);
}
+ ql_dbg(ql_dbg_init, vha, 0x004e,
+ "nx_dev_init_timeout=%d "
+ "nx_reset_timeout=%d.\n", ha->nx_dev_init_timeout,
+ ha->nx_reset_timeout);
return;
}
@@ -963,17 +981,18 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
if (hdr.version == __constant_cpu_to_le16(0xffff))
return;
if (hdr.version != __constant_cpu_to_le16(1)) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config "
+ ql_dbg(ql_dbg_user, vha, 0x7090,
+ "Unsupported NPIV-Config "
"detected: version=0x%x entries=0x%x checksum=0x%x.\n",
le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
- le16_to_cpu(hdr.checksum)));
+ le16_to_cpu(hdr.checksum));
return;
}
data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL);
if (!data) {
- DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to "
- "allocate memory.\n"));
+ ql_log(ql_log_warn, vha, 0x7091,
+ "Unable to allocate memory for data.\n");
return;
}
@@ -985,10 +1004,11 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
for (wptr = data, chksum = 0; cnt; cnt--)
chksum += le16_to_cpu(*wptr++);
if (chksum) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config "
+ ql_dbg(ql_dbg_user, vha, 0x7092,
+ "Inconsistent NPIV-Config "
"detected: version=0x%x entries=0x%x checksum=0x%x.\n",
le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
- chksum));
+ le16_to_cpu(hdr.checksum));
goto done;
}
@@ -1014,21 +1034,22 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
vid.port_name = wwn_to_u64(entry->port_name);
vid.node_name = wwn_to_u64(entry->node_name);
- DEBUG2(qla_printk(KERN_INFO, ha, "NPIV[%02x]: wwpn=%llx "
- "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt,
- (unsigned long long)vid.port_name,
- (unsigned long long)vid.node_name,
- le16_to_cpu(entry->vf_id),
- entry->q_qos, entry->f_qos));
+ ql_dbg(ql_dbg_user, vha, 0x7093,
+ "NPIV[%02x]: wwpn=%llx "
+ "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt,
+ (unsigned long long)vid.port_name,
+ (unsigned long long)vid.node_name,
+ le16_to_cpu(entry->vf_id),
+ entry->q_qos, entry->f_qos);
if (i < QLA_PRECONFIG_VPORTS) {
vport = fc_vport_create(vha->host, 0, &vid);
if (!vport)
- qla_printk(KERN_INFO, ha,
- "NPIV-Config: Failed to create vport [%02x]: "
- "wwpn=%llx wwnn=%llx.\n", cnt,
- (unsigned long long)vid.port_name,
- (unsigned long long)vid.node_name);
+ ql_log(ql_log_warn, vha, 0x7094,
+ "NPIV-Config Failed to create vport [%02x]: "
+ "wwpn=%llx wwnn=%llx.\n", cnt,
+ (unsigned long long)vid.port_name,
+ (unsigned long long)vid.node_name);
}
}
done:
@@ -1127,9 +1148,10 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
&optrom_dma, GFP_KERNEL);
if (!optrom) {
- qla_printk(KERN_DEBUG, ha,
- "Unable to allocate memory for optrom burst write "
- "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+ ql_log(ql_log_warn, vha, 0x7095,
+ "Unable to allocate "
+ "memory for optrom burst write (%x KB).\n",
+ OPTROM_BURST_SIZE / 1024);
}
}
@@ -1138,7 +1160,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
ret = qla24xx_unprotect_flash(vha);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7096,
"Unable to unprotect flash for update.\n");
goto done;
}
@@ -1156,9 +1178,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
0xff0000) | ((fdata >> 16) & 0xff));
ret = qla24xx_erase_sector(vha, fdata);
if (ret != QLA_SUCCESS) {
- DEBUG9(qla_printk(KERN_WARNING, ha,
- "Unable to erase sector: address=%x.\n",
- faddr));
+ ql_dbg(ql_dbg_user, vha, 0x7007,
+ "Unable to erase erase sector: address=%x.\n",
+ faddr);
break;
}
}
@@ -1172,12 +1194,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
flash_data_addr(ha, faddr),
OPTROM_BURST_DWORDS);
if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7097,
"Unable to burst-write optrom segment "
"(%x/%x/%llx).\n", ret,
flash_data_addr(ha, faddr),
(unsigned long long)optrom_dma);
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7098,
"Reverting to slow-write.\n");
dma_free_coherent(&ha->pdev->dev,
@@ -1194,9 +1216,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
ret = qla24xx_write_flash_dword(ha,
flash_data_addr(ha, faddr), cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
- DEBUG9(printk("%s(%ld) Unable to program flash "
- "address=%x data=%x.\n", __func__,
- vha->host_no, faddr, *dwptr));
+ ql_dbg(ql_dbg_user, vha, 0x7006,
+ "Unable to program flash address=%x data=%x.\n",
+ faddr, *dwptr);
break;
}
@@ -1211,7 +1233,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
ret = qla24xx_protect_flash(vha);
if (ret != QLA_SUCCESS)
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7099,
"Unable to protect flash after update.\n");
done:
if (optrom)
@@ -1324,9 +1346,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
ret = qla24xx_write_flash_dword(ha,
nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
- DEBUG9(qla_printk(KERN_WARNING, ha,
+ ql_dbg(ql_dbg_user, vha, 0x709a,
"Unable to program nvram address=%x data=%x.\n",
- naddr, *dwptr));
+ naddr, *dwptr);
break;
}
}
@@ -1476,7 +1498,7 @@ qla2x00_beacon_on(struct scsi_qla_host *vha)
ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x709b,
"Unable to update fw options (beacon on).\n");
return QLA_FUNCTION_FAILED;
}
@@ -1541,7 +1563,7 @@ qla2x00_beacon_off(struct scsi_qla_host *vha)
rval = qla2x00_set_fw_options(vha, ha->fw_options);
if (rval != QLA_SUCCESS)
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x709c,
"Unable to update fw options (beacon off).\n");
return rval;
}
@@ -1616,7 +1638,7 @@ qla24xx_beacon_on(struct scsi_qla_host *vha)
if (qla2x00_get_fw_options(vha, ha->fw_options) !=
QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x7009,
"Unable to update fw options (beacon on).\n");
return QLA_FUNCTION_FAILED;
}
@@ -1670,14 +1692,14 @@ qla24xx_beacon_off(struct scsi_qla_host *vha)
ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Unable to update fw options (beacon off).\n");
+ ql_log(ql_log_warn, vha, 0x704d,
+ "Unable to update fw options (beacon on).\n");
return QLA_FUNCTION_FAILED;
}
if (qla2x00_get_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Unable to get fw options (beacon off).\n");
+ ql_log(ql_log_warn, vha, 0x704e,
+ "Unable to update fw options (beacon on).\n");
return QLA_FUNCTION_FAILED;
}
@@ -2389,10 +2411,9 @@ try_fast:
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
&optrom_dma, GFP_KERNEL);
if (!optrom) {
- qla_printk(KERN_DEBUG, ha,
- "Unable to allocate memory for optrom burst read "
- "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
-
+ ql_log(ql_log_warn, vha, 0x00cc,
+ "Unable to allocate memory for optrom burst read (%x KB).\n",
+ OPTROM_BURST_SIZE / 1024);
goto slow_read;
}
@@ -2407,12 +2428,11 @@ try_fast:
rval = qla2x00_dump_ram(vha, optrom_dma,
flash_data_addr(ha, faddr), burst);
if (rval) {
- qla_printk(KERN_WARNING, ha,
- "Unable to burst-read optrom segment "
- "(%x/%x/%llx).\n", rval,
- flash_data_addr(ha, faddr),
+ ql_log(ql_log_warn, vha, 0x00f5,
+ "Unable to burst-read optrom segment (%x/%x/%llx).\n",
+ rval, flash_data_addr(ha, faddr),
(unsigned long long)optrom_dma);
- qla_printk(KERN_WARNING, ha,
+ ql_log(ql_log_warn, vha, 0x00f6,
"Reverting to slow-read.\n");
dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
@@ -2556,8 +2576,8 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 ||
qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) {
/* No signature */
- DEBUG2(qla_printk(KERN_DEBUG, ha, "No matching ROM "
- "signature.\n"));
+ ql_log(ql_log_fatal, vha, 0x0050,
+ "No matching ROM signature.\n");
ret = QLA_FUNCTION_FAILED;
break;
}
@@ -2573,8 +2593,8 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' ||
qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') {
/* Incorrect header. */
- DEBUG2(qla_printk(KERN_INFO, ha, "PCI data struct not "
- "found pcir_adr=%x.\n", pcids));
+ ql_log(ql_log_fatal, vha, 0x0051,
+ "PCI data struct not found pcir_adr=%x.\n", pcids);
ret = QLA_FUNCTION_FAILED;
break;
}
@@ -2588,8 +2608,9 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
qla2x00_read_flash_byte(ha, pcids + 0x12);
ha->bios_revision[1] =
qla2x00_read_flash_byte(ha, pcids + 0x13);
- DEBUG3(qla_printk(KERN_DEBUG, ha, "read BIOS %d.%d.\n",
- ha->bios_revision[1], ha->bios_revision[0]));
+ ql_dbg(ql_dbg_init, vha, 0x0052,
+ "Read BIOS %d.%d.\n",
+ ha->bios_revision[1], ha->bios_revision[0]);
break;
case ROM_CODE_TYPE_FCODE:
/* Open Firmware standard for PCI (FCode). */
@@ -2602,12 +2623,14 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
qla2x00_read_flash_byte(ha, pcids + 0x12);
ha->efi_revision[1] =
qla2x00_read_flash_byte(ha, pcids + 0x13);
- DEBUG3(qla_printk(KERN_DEBUG, ha, "read EFI %d.%d.\n",
- ha->efi_revision[1], ha->efi_revision[0]));
+ ql_dbg(ql_dbg_init, vha, 0x0053,
+ "Read EFI %d.%d.\n",
+ ha->efi_revision[1], ha->efi_revision[0]);
break;
default:
- DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized code "
- "type %x at pcids %x.\n", code_type, pcids));
+ ql_log(ql_log_warn, vha, 0x0054,
+ "Unrecognized code type %x at pcids %x.\n",
+ code_type, pcids);
break;
}
@@ -2627,21 +2650,28 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10,
8);
- DEBUG3(qla_printk(KERN_DEBUG, ha, "dumping fw ver from "
- "flash:\n"));
- DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8));
+ ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010a,
+ "Dumping fw "
+ "ver from flash:.\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b,
+ (uint8_t *)dbyte, 8);
if ((dcode[0] == 0xffff && dcode[1] == 0xffff &&
dcode[2] == 0xffff && dcode[3] == 0xffff) ||
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized fw "
- "revision at %x.\n", ha->flt_region_fw * 4));
+ ql_log(ql_log_warn, vha, 0x0057,
+ "Unrecognized fw revision at %x.\n",
+ ha->flt_region_fw * 4);
} else {
/* values are in big endian */
ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1];
ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3];
ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5];
+ ql_dbg(ql_dbg_init, vha, 0x0058,
+ "FW Version: "
+ "%d.%d.%d.\n", ha->fw_revision[0],
+ ha->fw_revision[1], ha->fw_revision[2]);
}
}
@@ -2683,8 +2713,8 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
bcode = mbuf + (pcihdr % 4);
if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) {
/* No signature */
- DEBUG2(qla_printk(KERN_DEBUG, ha, "No matching ROM "
- "signature.\n"));
+ ql_log(ql_log_fatal, vha, 0x0059,
+ "No matching ROM signature.\n");
ret = QLA_FUNCTION_FAILED;
break;
}
@@ -2699,8 +2729,8 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
bcode[0x2] != 'I' || bcode[0x3] != 'R') {
/* Incorrect header. */
- DEBUG2(qla_printk(KERN_INFO, ha, "PCI data struct not "
- "found pcir_adr=%x.\n", pcids));
+ ql_log(ql_log_fatal, vha, 0x005a,
+ "PCI data struct not found pcir_adr=%x.\n", pcids);
ret = QLA_FUNCTION_FAILED;
break;
}
@@ -2712,26 +2742,30 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
/* Intel x86, PC-AT compatible. */
ha->bios_revision[0] = bcode[0x12];
ha->bios_revision[1] = bcode[0x13];
- DEBUG3(qla_printk(KERN_DEBUG, ha, "read BIOS %d.%d.\n",
- ha->bios_revision[1], ha->bios_revision[0]));
+ ql_dbg(ql_dbg_init, vha, 0x005b,
+ "Read BIOS %d.%d.\n",
+ ha->bios_revision[1], ha->bios_revision[0]);
break;
case ROM_CODE_TYPE_FCODE:
/* Open Firmware standard for PCI (FCode). */
ha->fcode_revision[0] = bcode[0x12];
ha->fcode_revision[1] = bcode[0x13];
- DEBUG3(qla_printk(KERN_DEBUG, ha, "read FCODE %d.%d.\n",
- ha->fcode_revision[1], ha->fcode_revision[0]));
+ ql_dbg(ql_dbg_init, vha, 0x005c,
+ "Read FCODE %d.%d.\n",
+ ha->fcode_revision[1], ha->fcode_revision[0]);
break;
case ROM_CODE_TYPE_EFI:
/* Extensible Firmware Interface (EFI). */
ha->efi_revision[0] = bcode[0x12];
ha->efi_revision[1] = bcode[0x13];
- DEBUG3(qla_printk(KERN_DEBUG, ha, "read EFI %d.%d.\n",
- ha->efi_revision[1], ha->efi_revision[0]));
+ ql_dbg(ql_dbg_init, vha, 0x005d,
+ "Read EFI %d.%d.\n",
+ ha->efi_revision[1], ha->efi_revision[0]);
break;
default:
- DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized code "
- "type %x at pcids %x.\n", code_type, pcids));
+ ql_log(ql_log_warn, vha, 0x005e,
+ "Unrecognized code type %x at pcids %x.\n",
+ code_type, pcids);
break;
}
@@ -2753,13 +2787,18 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
- DEBUG2(qla_printk(KERN_INFO, ha, "Unrecognized fw "
- "revision at %x.\n", ha->flt_region_fw * 4));
+ ql_log(ql_log_warn, vha, 0x005f,
+ "Unrecognized fw revision at %x.\n",
+ ha->flt_region_fw * 4);
} else {
ha->fw_revision[0] = dcode[0];
ha->fw_revision[1] = dcode[1];
ha->fw_revision[2] = dcode[2];
ha->fw_revision[3] = dcode[3];
+ ql_dbg(ql_dbg_init, vha, 0x0060,
+ "Firmware revision %d.%d.%d.%d.\n",
+ ha->fw_revision[0], ha->fw_revision[1],
+ ha->fw_revision[2], ha->fw_revision[3]);
}
/* Check for golden firmware and get version if available */
@@ -2775,9 +2814,9 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
if (dcode[4] == 0xFFFFFFFF && dcode[5] == 0xFFFFFFFF &&
dcode[6] == 0xFFFFFFFF && dcode[7] == 0xFFFFFFFF) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "%s(%ld): Unrecognized golden fw at 0x%x.\n",
- __func__, vha->host_no, ha->flt_region_gold_fw * 4));
+ ql_log(ql_log_warn, vha, 0x0056,
+ "Unrecognized golden fw at 0x%x.\n",
+ ha->flt_region_gold_fw * 4);
return ret;
}
@@ -2843,9 +2882,9 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
if (!ha->fcp_prio_cfg) {
ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
if (!ha->fcp_prio_cfg) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for fcp priority data "
- "(%x).\n", FCP_PRIO_CFG_SIZE);
+ ql_log(ql_log_warn, vha, 0x00d5,
+ "Unable to allocate memory for fcp priorty data (%x).\n",
+ FCP_PRIO_CFG_SIZE);
return QLA_FUNCTION_FAILED;
}
}
@@ -2857,7 +2896,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg,
fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
- if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 0))
+ if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 0))
goto fail;
/* read remaining FCP CMD config data from flash */
@@ -2869,7 +2908,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
fcp_prio_addr << 2, (len < max_len ? len : max_len));
/* revalidate the entire FCP priority config data, including entries */
- if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 1))
+ if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1))
goto fail;
ha->flags.fcp_prio_enabled = 1;
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 062c97b..23f33a6 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.03.07.03-k"
+#define QLA2XXX_VERSION "8.03.07.12-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 3
diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig
index 2c33ce6..f1ad02e 100644
--- a/drivers/scsi/qla4xxx/Kconfig
+++ b/drivers/scsi/qla4xxx/Kconfig
@@ -1,7 +1,8 @@
config SCSI_QLA_ISCSI
tristate "QLogic ISP4XXX and ISP82XX host adapter family support"
- depends on PCI && SCSI
+ depends on PCI && SCSI && NET
select SCSI_ISCSI_ATTRS
+ select ISCSI_BOOT_SYSFS
---help---
This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX)
iSCSI host adapter family.
diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile
index 252523d..5b44139 100644
--- a/drivers/scsi/qla4xxx/Makefile
+++ b/drivers/scsi/qla4xxx/Makefile
@@ -1,5 +1,5 @@
qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \
- ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o
+ ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o ql4_bsg.o
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c
index 864d018..0b0a7d4 100644
--- a/drivers/scsi/qla4xxx/ql4_attr.c
+++ b/drivers/scsi/qla4xxx/ql4_attr.c
@@ -55,15 +55,91 @@ qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr,
ha->bootload_patch, ha->bootload_build);
}
+static ssize_t
+qla4xxx_board_id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+ return snprintf(buf, PAGE_SIZE, "0x%08X\n", ha->board_id);
+}
+
+static ssize_t
+qla4xxx_fw_state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ qla4xxx_get_firmware_state(ha);
+ return snprintf(buf, PAGE_SIZE, "0x%08X%8X\n", ha->firmware_state,
+ ha->addl_fw_state);
+}
+
+static ssize_t
+qla4xxx_phy_port_cnt_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ if (!is_qla8022(ha))
+ return -ENOSYS;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_cnt);
+}
+
+static ssize_t
+qla4xxx_phy_port_num_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ if (!is_qla8022(ha))
+ return -ENOSYS;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_num);
+}
+
+static ssize_t
+qla4xxx_iscsi_func_cnt_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ if (!is_qla8022(ha))
+ return -ENOSYS;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->iscsi_pci_func_cnt);
+}
+
+static ssize_t
+qla4xxx_hba_model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_name);
+}
+
static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL);
static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL);
static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL);
+static DEVICE_ATTR(board_id, S_IRUGO, qla4xxx_board_id_show, NULL);
+static DEVICE_ATTR(fw_state, S_IRUGO, qla4xxx_fw_state_show, NULL);
+static DEVICE_ATTR(phy_port_cnt, S_IRUGO, qla4xxx_phy_port_cnt_show, NULL);
+static DEVICE_ATTR(phy_port_num, S_IRUGO, qla4xxx_phy_port_num_show, NULL);
+static DEVICE_ATTR(iscsi_func_cnt, S_IRUGO, qla4xxx_iscsi_func_cnt_show, NULL);
+static DEVICE_ATTR(hba_model, S_IRUGO, qla4xxx_hba_model_show, NULL);
struct device_attribute *qla4xxx_host_attrs[] = {
&dev_attr_fw_version,
&dev_attr_serial_num,
&dev_attr_iscsi_version,
&dev_attr_optrom_version,
+ &dev_attr_board_id,
+ &dev_attr_fw_state,
+ &dev_attr_phy_port_cnt,
+ &dev_attr_phy_port_num,
+ &dev_attr_iscsi_func_cnt,
+ &dev_attr_hba_model,
NULL,
};
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 473c5c8..fd5edc6 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/aer.h>
+#include <linux/bsg-lib.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
@@ -33,9 +34,14 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_bsg_iscsi.h>
+#include <scsi/scsi_netlink.h>
+#include <scsi/libiscsi.h>
#include "ql4_dbg.h"
#include "ql4_nx.h"
+#include "ql4_fw.h"
+#include "ql4_nvram.h"
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4010
#define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010
@@ -109,7 +115,7 @@
#define MAX_BUSES 1
#define MAX_TARGETS MAX_DEV_DB_ENTRIES
#define MAX_LUNS 0xffff
-#define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */
+#define MAX_AEN_ENTRIES MAX_DEV_DB_ENTRIES
#define MAX_DDB_ENTRIES MAX_DEV_DB_ENTRIES
#define MAX_PDU_ENTRIES 32
#define INVALID_ENTRY 0xFFFF
@@ -141,7 +147,7 @@
#define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */
#define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */
-#define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */
+#define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */
/* recovery timeout */
#define LSDW(x) ((u32)((u64)(x)))
@@ -166,6 +172,9 @@
#define RELOGIN_TOV 18
#define ISNS_DEREG_TOV 5
#define HBA_ONLINE_TOV 30
+#define DISABLE_ACB_TOV 30
+#define IP_CONFIG_TOV 30
+#define LOGIN_TOV 12
#define MAX_RESET_HA_RETRIES 2
@@ -227,52 +236,51 @@ struct ql4_aen_log {
* Device Database (DDB) structure
*/
struct ddb_entry {
- struct list_head list; /* ddb list */
struct scsi_qla_host *ha;
struct iscsi_cls_session *sess;
struct iscsi_cls_conn *conn;
- atomic_t state; /* DDB State */
-
- unsigned long flags; /* DDB Flags */
-
uint16_t fw_ddb_index; /* DDB firmware index */
- uint16_t options;
uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */
+ uint16_t ddb_type;
+#define FLASH_DDB 0x01
- uint32_t CmdSn;
- uint16_t target_session_id;
- uint16_t connection_id;
- uint16_t exe_throttle; /* Max mumber of cmds outstanding
- * simultaneously */
- uint16_t task_mgmt_timeout; /* Min time for task mgmt cmds to
- * complete */
+ struct dev_db_entry fw_ddb_entry;
+ int (*unblock_sess)(struct iscsi_cls_session *cls_session);
+ int (*ddb_change)(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ struct ddb_entry *ddb_entry, uint32_t state);
+
+ /* Driver Re-login */
+ unsigned long flags; /* DDB Flags */
uint16_t default_relogin_timeout; /* Max time to wait for
* relogin to complete */
- uint16_t tcp_source_port_num;
- uint32_t default_time2wait; /* Default Min time between
- * relogins (+aens) */
-
- atomic_t retry_relogin_timer; /* Min Time between relogins
- * (4000 only) */
- atomic_t relogin_timer; /* Max Time to wait for relogin to complete */
- atomic_t relogin_retry_count; /* Num of times relogin has been
- * retried */
-
- uint16_t port;
- uint32_t tpgt;
- uint8_t ip_addr[IP_ADDR_LEN];
- uint8_t iscsi_name[ISCSI_NAME_SIZE]; /* 72 x48 */
- uint8_t iscsi_alias[0x20];
- uint8_t isid[6];
- uint16_t iscsi_max_burst_len;
- uint16_t iscsi_max_outsnd_r2t;
- uint16_t iscsi_first_burst_len;
- uint16_t iscsi_max_rcv_data_seg_len;
- uint16_t iscsi_max_snd_data_seg_len;
-
- struct in6_addr remote_ipv6_addr;
- struct in6_addr link_local_ipv6_addr;
+ atomic_t retry_relogin_timer; /* Min Time between relogins
+ * (4000 only) */
+ atomic_t relogin_timer; /* Max Time to wait for
+ * relogin to complete */
+ atomic_t relogin_retry_count; /* Num of times relogin has been
+ * retried */
+ uint32_t default_time2wait; /* Default Min time between
+ * relogins (+aens) */
+
+};
+
+struct qla_ddb_index {
+ struct list_head list;
+ uint16_t fw_ddb_idx;
+ struct dev_db_entry fw_ddb;
+};
+
+#define DDB_IPADDR_LEN 64
+
+struct ql4_tuple_ddb {
+ int port;
+ int tpgt;
+ char ip_addr[DDB_IPADDR_LEN];
+ char iscsi_name[ISCSI_NAME_SIZE];
+ uint16_t options;
+#define DDB_OPT_IPV6 0x0e0e
+#define DDB_OPT_IPV4 0x0f0f
};
/*
@@ -293,8 +301,6 @@ struct ddb_entry {
#define DF_FO_MASKED 3
-#include "ql4_fw.h"
-#include "ql4_nvram.h"
struct ql82xx_hw_data {
/* Offsets for flash/nvram access (set to ~0 if not used). */
@@ -312,7 +318,10 @@ struct ql82xx_hw_data {
uint32_t flt_region_boot;
uint32_t flt_region_bootload;
uint32_t flt_region_fw;
- uint32_t reserved;
+
+ uint32_t flt_iscsi_param;
+ uint32_t flt_region_chap;
+ uint32_t flt_chap_size;
};
struct qla4_8xxx_legacy_intr_set {
@@ -357,6 +366,68 @@ struct isp_operations {
int (*get_sys_info) (struct scsi_qla_host *);
};
+/*qla4xxx ipaddress configuration details */
+struct ipaddress_config {
+ uint16_t ipv4_options;
+ uint16_t tcp_options;
+ uint16_t ipv4_vlan_tag;
+ uint8_t ipv4_addr_state;
+ uint8_t ip_address[IP_ADDR_LEN];
+ uint8_t subnet_mask[IP_ADDR_LEN];
+ uint8_t gateway[IP_ADDR_LEN];
+ uint32_t ipv6_options;
+ uint32_t ipv6_addl_options;
+ uint8_t ipv6_link_local_state;
+ uint8_t ipv6_addr0_state;
+ uint8_t ipv6_addr1_state;
+ uint8_t ipv6_default_router_state;
+ uint16_t ipv6_vlan_tag;
+ struct in6_addr ipv6_link_local_addr;
+ struct in6_addr ipv6_addr0;
+ struct in6_addr ipv6_addr1;
+ struct in6_addr ipv6_default_router_addr;
+ uint16_t eth_mtu_size;
+ uint16_t ipv4_port;
+ uint16_t ipv6_port;
+};
+
+#define QL4_CHAP_MAX_NAME_LEN 256
+#define QL4_CHAP_MAX_SECRET_LEN 100
+#define LOCAL_CHAP 0
+#define BIDI_CHAP 1
+
+struct ql4_chap_format {
+ u8 intr_chap_name[QL4_CHAP_MAX_NAME_LEN];
+ u8 intr_secret[QL4_CHAP_MAX_SECRET_LEN];
+ u8 target_chap_name[QL4_CHAP_MAX_NAME_LEN];
+ u8 target_secret[QL4_CHAP_MAX_SECRET_LEN];
+ u16 intr_chap_name_length;
+ u16 intr_secret_length;
+ u16 target_chap_name_length;
+ u16 target_secret_length;
+};
+
+struct ip_address_format {
+ u8 ip_type;
+ u8 ip_address[16];
+};
+
+struct ql4_conn_info {
+ u16 dest_port;
+ struct ip_address_format dest_ipaddr;
+ struct ql4_chap_format chap;
+};
+
+struct ql4_boot_session_info {
+ u8 target_name[224];
+ struct ql4_conn_info conn_list[1];
+};
+
+struct ql4_boot_tgt_info {
+ struct ql4_boot_session_info boot_pri_sess;
+ struct ql4_boot_session_info boot_sec_sess;
+};
+
/*
* Linux Host Adapter structure
*/
@@ -381,7 +452,7 @@ struct scsi_qla_host {
#define AF_FW_RECOVERY 19 /* 0x00080000 */
#define AF_EEH_BUSY 20 /* 0x00100000 */
#define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */
-
+#define AF_BUILD_DDB_LIST 22 /* 0x00400000 */
unsigned long dpc_flags;
#define DPC_RESET_HA 1 /* 0x00000002 */
@@ -451,10 +522,6 @@ struct scsi_qla_host {
/* --- From Init_FW --- */
/* init_cb_t *init_cb; */
uint16_t firmware_options;
- uint16_t tcp_options;
- uint8_t ip_address[IP_ADDR_LEN];
- uint8_t subnet_mask[IP_ADDR_LEN];
- uint8_t gateway[IP_ADDR_LEN];
uint8_t alias[32];
uint8_t name_string[256];
uint8_t heartbeat_interval;
@@ -462,7 +529,7 @@ struct scsi_qla_host {
/* --- From FlashSysInfo --- */
uint8_t my_mac[MAC_ADDR_LEN];
uint8_t serial_number[16];
-
+ uint16_t port_num;
/* --- From GetFwState --- */
uint32_t firmware_state;
uint32_t addl_fw_state;
@@ -524,31 +591,13 @@ struct scsi_qla_host {
volatile uint8_t mbox_status_count;
volatile uint32_t mbox_status[MBOX_REG_COUNT];
- /* local device database list (contains internal ddb entries) */
- struct list_head ddb_list;
-
- /* Map ddb_list entry by FW ddb index */
+ /* FW ddb index map */
struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES];
/* Saved srb for status continuation entry processing */
struct srb *status_srb;
- /* IPv6 support info from InitFW */
uint8_t acb_version;
- uint8_t ipv4_addr_state;
- uint16_t ipv4_options;
-
- uint32_t resvd2;
- uint32_t ipv6_options;
- uint32_t ipv6_addl_options;
- uint8_t ipv6_link_local_state;
- uint8_t ipv6_addr0_state;
- uint8_t ipv6_addr1_state;
- uint8_t ipv6_default_router_state;
- struct in6_addr ipv6_link_local_addr;
- struct in6_addr ipv6_addr0;
- struct in6_addr ipv6_addr1;
- struct in6_addr ipv6_default_router_addr;
/* qla82xx specific fields */
struct device_reg_82xx __iomem *qla4_8xxx_reg; /* Base I/O address */
@@ -584,6 +633,11 @@ struct scsi_qla_host {
struct completion mbx_intr_comp;
+ struct ipaddress_config ip_config;
+ struct iscsi_iface *iface_ipv4;
+ struct iscsi_iface *iface_ipv6_0;
+ struct iscsi_iface *iface_ipv6_1;
+
/* --- From About Firmware --- */
uint16_t iscsi_major;
uint16_t iscsi_minor;
@@ -591,16 +645,66 @@ struct scsi_qla_host {
uint16_t bootload_minor;
uint16_t bootload_patch;
uint16_t bootload_build;
+ uint16_t def_timeout; /* Default login timeout */
+
+ uint32_t flash_state;
+#define QLFLASH_WAITING 0
+#define QLFLASH_READING 1
+#define QLFLASH_WRITING 2
+ struct dma_pool *chap_dma_pool;
+ uint8_t *chap_list; /* CHAP table cache */
+ struct mutex chap_sem;
+#define CHAP_DMA_BLOCK_SIZE 512
+ struct workqueue_struct *task_wq;
+ unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
+#define SYSFS_FLAG_FW_SEL_BOOT 2
+ struct iscsi_boot_kset *boot_kset;
+ struct ql4_boot_tgt_info boot_tgt;
+ uint16_t phy_port_num;
+ uint16_t phy_port_cnt;
+ uint16_t iscsi_pci_func_cnt;
+ uint8_t model_name[16];
+ struct completion disable_acb_comp;
+ struct dma_pool *fw_ddb_dma_pool;
+#define DDB_DMA_BLOCK_SIZE 512
+ uint16_t pri_ddb_idx;
+ uint16_t sec_ddb_idx;
+ int is_reset;
+};
+
+struct ql4_task_data {
+ struct scsi_qla_host *ha;
+ uint8_t iocb_req_cnt;
+ dma_addr_t data_dma;
+ void *req_buffer;
+ dma_addr_t req_dma;
+ uint32_t req_len;
+ void *resp_buffer;
+ dma_addr_t resp_dma;
+ uint32_t resp_len;
+ struct iscsi_task *task;
+ struct passthru_status sts;
+ struct work_struct task_work;
+};
+
+struct qla_endpoint {
+ struct Scsi_Host *host;
+ struct sockaddr dst_addr;
+};
+
+struct qla_conn {
+ struct qla_endpoint *qla_ep;
};
static inline int is_ipv4_enabled(struct scsi_qla_host *ha)
{
- return ((ha->ipv4_options & IPOPT_IPv4_PROTOCOL_ENABLE) != 0);
+ return ((ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE) != 0);
}
static inline int is_ipv6_enabled(struct scsi_qla_host *ha)
{
- return ((ha->ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE) != 0);
+ return ((ha->ip_config.ipv6_options &
+ IPV6_OPT_IPV6_PROTOCOL_ENABLE) != 0);
}
static inline int is_qla4010(struct scsi_qla_host *ha)
@@ -618,6 +722,11 @@ static inline int is_qla4032(struct scsi_qla_host *ha)
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032;
}
+static inline int is_qla40XX(struct scsi_qla_host *ha)
+{
+ return is_qla4032(ha) || is_qla4022(ha) || is_qla4010(ha);
+}
+
static inline int is_qla8022(struct scsi_qla_host *ha)
{
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
@@ -640,7 +749,7 @@ static inline int adapter_up(struct scsi_qla_host *ha)
static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost)
{
- return (struct scsi_qla_host *)shost->hostdata;
+ return (struct scsi_qla_host *)iscsi_host_priv(shost);
}
static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha)
@@ -760,9 +869,23 @@ static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a)
ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK);
}
+static inline int ql4xxx_reset_active(struct scsi_qla_host *ha)
+{
+ return test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
+ test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
+ test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
+
+}
/*---------------------------------------------------------------------------*/
/* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */
+
+#define INIT_ADAPTER 0
+#define RESET_ADAPTER 1
+
#define PRESERVE_DDB_LIST 0
#define REBUILD_DDB_LIST 1
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 01082aa..4ac07f8 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -12,6 +12,7 @@
#define MAX_PRST_DEV_DB_ENTRIES 64
#define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES
#define MAX_DEV_DB_ENTRIES 512
+#define MAX_DEV_DB_ENTRIES_40XX 256
/*************************************************************************
*
@@ -146,6 +147,13 @@ struct isp_reg {
#define QL4022_NVRAM_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (10+16))
#define QL4022_FLASH_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (13+16))
+/* nvram address for 4032 */
+#define NVRAM_PORT0_BOOT_MODE 0x03b1
+#define NVRAM_PORT0_BOOT_PRI_TGT 0x03b2
+#define NVRAM_PORT0_BOOT_SEC_TGT 0x03bb
+#define NVRAM_PORT1_BOOT_MODE 0x07b1
+#define NVRAM_PORT1_BOOT_PRI_TGT 0x07b2
+#define NVRAM_PORT1_BOOT_SEC_TGT 0x07bb
/* Page # defines for 4022 */
@@ -194,6 +202,9 @@ static inline uint32_t clr_rmask(uint32_t val)
/* ISP 4022 nvram definitions */
#define NVR_WRITE_ENABLE 0x00000010 /* 4022 */
+#define QL4010_NVRAM_SIZE 0x200
+#define QL40X2_NVRAM_SIZE 0x800
+
/* ISP port_status definitions */
/* ISP Semaphore definitions */
@@ -241,6 +252,8 @@ union external_hw_config_reg {
#define FA_BOOT_CODE_ADDR_82 0x20000
#define FA_RISC_CODE_ADDR_82 0x40000
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
+#define FA_FLASH_ISCSI_CHAP 0x540000
+#define FA_FLASH_CHAP_SIZE 0xC0000
/* Flash Description Table */
struct qla_fdt_layout {
@@ -296,8 +309,11 @@ struct qla_flt_header {
#define FLT_REG_FLT 0x1c
#define FLT_REG_BOOTLOAD_82 0x72
#define FLT_REG_FW_82 0x74
+#define FLT_REG_FW_82_1 0x97
#define FLT_REG_GOLD_FW_82 0x75
#define FLT_REG_BOOT_CODE_82 0x78
+#define FLT_REG_ISCSI_PARAM 0x65
+#define FLT_REG_ISCSI_CHAP 0x63
struct qla_flt_region {
uint32_t code;
@@ -331,9 +347,11 @@ struct qla_flt_region {
#define MBOX_CMD_WRITE_FLASH 0x0025
#define MBOX_CMD_READ_FLASH 0x0026
#define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031
+#define MBOX_CMD_CONN_OPEN 0x0074
#define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056
-#define LOGOUT_OPTION_CLOSE_SESSION 0x01
-#define LOGOUT_OPTION_RELOGIN 0x02
+#define LOGOUT_OPTION_CLOSE_SESSION 0x0002
+#define LOGOUT_OPTION_RELOGIN 0x0004
+#define LOGOUT_OPTION_FREE_DDB 0x0008
#define MBOX_CMD_EXECUTE_IOCB_A64 0x005A
#define MBOX_CMD_INITIALIZE_FIRMWARE 0x0060
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK 0x0061
@@ -342,12 +360,15 @@ struct qla_flt_region {
#define MBOX_CMD_GET_DATABASE_ENTRY 0x0064
#define DDB_DS_UNASSIGNED 0x00
#define DDB_DS_NO_CONNECTION_ACTIVE 0x01
+#define DDB_DS_DISCOVERY 0x02
#define DDB_DS_SESSION_ACTIVE 0x04
#define DDB_DS_SESSION_FAILED 0x06
#define DDB_DS_LOGIN_IN_PROCESS 0x07
#define MBOX_CMD_GET_FW_STATE 0x0069
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
#define MBOX_CMD_GET_SYS_INFO 0x0078
+#define MBOX_CMD_GET_NVRAM 0x0078 /* For 40xx */
+#define MBOX_CMD_SET_NVRAM 0x0079 /* For 40xx */
#define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087
#define MBOX_CMD_SET_ACB 0x0088
#define MBOX_CMD_GET_ACB 0x0089
@@ -375,7 +396,10 @@ struct qla_flt_region {
#define FW_ADDSTATE_DHCPv4_LEASE_EXPIRED 0x0008
#define FW_ADDSTATE_LINK_UP 0x0010
#define FW_ADDSTATE_ISNS_SVC_ENABLED 0x0020
+
#define MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS 0x006B
+#define IPV6_DEFAULT_DDB_ENTRY 0x0001
+
#define MBOX_CMD_CONN_OPEN_SESS_LOGIN 0x0074
#define MBOX_CMD_GET_CRASH_RECORD 0x0076 /* 4010 only */
#define MBOX_CMD_GET_CONN_EVENT_LOG 0x0077
@@ -434,6 +458,14 @@ struct qla_flt_region {
#define ACB_STATE_VALID 0x05
#define ACB_STATE_DISABLING 0x06
+/* FLASH offsets */
+#define FLASH_SEGMENT_IFCB 0x04000000
+
+#define FLASH_OPT_RMW_HOLD 0
+#define FLASH_OPT_RMW_INIT 1
+#define FLASH_OPT_COMMIT 2
+#define FLASH_OPT_RMW_COMMIT 3
+
/*************************************************************************/
/* Host Adapter Initialization Control Block (from host) */
@@ -455,7 +487,8 @@ struct addr_ctrl_blk {
uint8_t res0; /* 07 */
uint16_t eth_mtu_size; /* 08-09 */
uint16_t add_fw_options; /* 0A-0B */
-#define SERIALIZE_TASK_MGMT 0x0400
+#define ADFWOPT_SERIALIZE_TASK_MGMT 0x0400
+#define ADFWOPT_AUTOCONN_DISABLE 0x0002
uint8_t hb_interval; /* 0C */
uint8_t inst_num; /* 0D */
@@ -473,8 +506,10 @@ struct addr_ctrl_blk {
uint16_t iscsi_opts; /* 30-31 */
uint16_t ipv4_tcp_opts; /* 32-33 */
+#define TCPOPT_DHCP_ENABLE 0x0200
uint16_t ipv4_ip_opts; /* 34-35 */
-#define IPOPT_IPv4_PROTOCOL_ENABLE 0x8000
+#define IPOPT_IPV4_PROTOCOL_ENABLE 0x8000
+#define IPOPT_VLAN_TAGGING_ENABLE 0x2000
uint16_t iscsi_max_pdu_size; /* 36-37 */
uint8_t ipv4_tos; /* 38 */
@@ -526,6 +561,7 @@ struct addr_ctrl_blk {
uint16_t ipv6_port; /* 204-205 */
uint16_t ipv6_opts; /* 206-207 */
#define IPV6_OPT_IPV6_PROTOCOL_ENABLE 0x8000
+#define IPV6_OPT_VLAN_TAGGING_ENABLE 0x2000
uint16_t ipv6_addtl_opts; /* 208-209 */
#define IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE 0x0002 /* Pri ACB
@@ -569,18 +605,117 @@ struct addr_ctrl_blk {
uint8_t res14[140]; /* 274-2FF */
};
+#define IP_ADDR_COUNT 4 /* Total 4 IP address supported in one interface
+ * One IPv4, one IPv6 link local and 2 IPv6
+ */
+
+#define IP_STATE_MASK 0x0F000000
+#define IP_STATE_SHIFT 24
+
struct init_fw_ctrl_blk {
struct addr_ctrl_blk pri;
/* struct addr_ctrl_blk sec;*/
};
+#define PRIMARI_ACB 0
+#define SECONDARY_ACB 1
+
+struct addr_ctrl_blk_def {
+ uint8_t reserved1[1]; /* 00 */
+ uint8_t control; /* 01 */
+ uint8_t reserved2[11]; /* 02-0C */
+ uint8_t inst_num; /* 0D */
+ uint8_t reserved3[34]; /* 0E-2F */
+ uint16_t iscsi_opts; /* 30-31 */
+ uint16_t ipv4_tcp_opts; /* 32-33 */
+ uint16_t ipv4_ip_opts; /* 34-35 */
+ uint16_t iscsi_max_pdu_size; /* 36-37 */
+ uint8_t ipv4_tos; /* 38 */
+ uint8_t ipv4_ttl; /* 39 */
+ uint8_t reserved4[2]; /* 3A-3B */
+ uint16_t def_timeout; /* 3C-3D */
+ uint16_t iscsi_fburst_len; /* 3E-3F */
+ uint8_t reserved5[4]; /* 40-43 */
+ uint16_t iscsi_max_outstnd_r2t; /* 44-45 */
+ uint8_t reserved6[2]; /* 46-47 */
+ uint16_t ipv4_port; /* 48-49 */
+ uint16_t iscsi_max_burst_len; /* 4A-4B */
+ uint8_t reserved7[4]; /* 4C-4F */
+ uint8_t ipv4_addr[4]; /* 50-53 */
+ uint16_t ipv4_vlan_tag; /* 54-55 */
+ uint8_t ipv4_addr_state; /* 56 */
+ uint8_t ipv4_cacheid; /* 57 */
+ uint8_t reserved8[8]; /* 58-5F */
+ uint8_t ipv4_subnet[4]; /* 60-63 */
+ uint8_t reserved9[12]; /* 64-6F */
+ uint8_t ipv4_gw_addr[4]; /* 70-73 */
+ uint8_t reserved10[84]; /* 74-C7 */
+ uint8_t abort_timer; /* C8 */
+ uint8_t ipv4_tcp_wsf; /* C9 */
+ uint8_t reserved11[10]; /* CA-D3 */
+ uint8_t ipv4_dhcp_vid_len; /* D4 */
+ uint8_t ipv4_dhcp_vid[11]; /* D5-DF */
+ uint8_t reserved12[20]; /* E0-F3 */
+ uint8_t ipv4_dhcp_alt_cid_len; /* F4 */
+ uint8_t ipv4_dhcp_alt_cid[11]; /* F5-FF */
+ uint8_t iscsi_name[224]; /* 100-1DF */
+ uint8_t reserved13[32]; /* 1E0-1FF */
+ uint32_t cookie; /* 200-203 */
+ uint16_t ipv6_port; /* 204-205 */
+ uint16_t ipv6_opts; /* 206-207 */
+ uint16_t ipv6_addtl_opts; /* 208-209 */
+ uint16_t ipv6_tcp_opts; /* 20A-20B */
+ uint8_t ipv6_tcp_wsf; /* 20C */
+ uint16_t ipv6_flow_lbl; /* 20D-20F */
+ uint8_t ipv6_dflt_rtr_addr[16]; /* 210-21F */
+ uint16_t ipv6_vlan_tag; /* 220-221 */
+ uint8_t ipv6_lnk_lcl_addr_state; /* 222 */
+ uint8_t ipv6_addr0_state; /* 223 */
+ uint8_t ipv6_addr1_state; /* 224 */
+ uint8_t ipv6_dflt_rtr_state; /* 225 */
+ uint8_t ipv6_traffic_class; /* 226 */
+ uint8_t ipv6_hop_limit; /* 227 */
+ uint8_t ipv6_if_id[8]; /* 228-22F */
+ uint8_t ipv6_addr0[16]; /* 230-23F */
+ uint8_t ipv6_addr1[16]; /* 240-24F */
+ uint32_t ipv6_nd_reach_time; /* 250-253 */
+ uint32_t ipv6_nd_rexmit_timer; /* 254-257 */
+ uint32_t ipv6_nd_stale_timeout; /* 258-25B */
+ uint8_t ipv6_dup_addr_detect_count; /* 25C */
+ uint8_t ipv6_cache_id; /* 25D */
+ uint8_t reserved14[18]; /* 25E-26F */
+ uint32_t ipv6_gw_advrt_mtu; /* 270-273 */
+ uint8_t reserved15[140]; /* 274-2FF */
+};
+
/*************************************************************************/
+#define MAX_CHAP_ENTRIES_40XX 128
+#define MAX_CHAP_ENTRIES_82XX 1024
+#define MAX_RESRV_CHAP_IDX 3
+#define FLASH_CHAP_OFFSET 0x06000000
+
+struct ql4_chap_table {
+ uint16_t link;
+ uint8_t flags;
+ uint8_t secret_len;
+#define MIN_CHAP_SECRET_LEN 12
+#define MAX_CHAP_SECRET_LEN 100
+ uint8_t secret[MAX_CHAP_SECRET_LEN];
+#define MAX_CHAP_NAME_LEN 256
+ uint8_t name[MAX_CHAP_NAME_LEN];
+ uint16_t reserved;
+#define CHAP_VALID_COOKIE 0x4092
+#define CHAP_INVALID_COOKIE 0xFFEE
+ uint16_t cookie;
+};
+
struct dev_db_entry {
uint16_t options; /* 00-01 */
#define DDB_OPT_DISC_SESSION 0x10
#define DDB_OPT_TARGET 0x02 /* device is a target */
#define DDB_OPT_IPV6_DEVICE 0x100
+#define DDB_OPT_AUTO_SENDTGTS_DISABLE 0x40
#define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */
#define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */
@@ -591,6 +726,7 @@ struct dev_db_entry {
uint16_t tcp_options; /* 0A-0B */
uint16_t ip_options; /* 0C-0D */
uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */
+#define BYTE_UNITS 512
uint32_t res1; /* 10-13 */
uint16_t iscsi_max_snd_data_seg_len; /* 14-15 */
uint16_t iscsi_first_burst_len; /* 16-17 */
@@ -627,7 +763,10 @@ struct dev_db_entry {
uint8_t tcp_rcv_wsf; /* 1C7 */
uint32_t stat_sn; /* 1C8-1CB */
uint32_t exp_stat_sn; /* 1CC-1CF */
- uint8_t res6[0x30]; /* 1D0-1FF */
+ uint8_t res6[0x2b]; /* 1D0-1FB */
+#define DDB_VALID_COOKIE 0x9034
+ uint16_t cookie; /* 1FC-1FD */
+ uint16_t len; /* 1FE-1FF */
};
/*************************************************************************/
@@ -639,6 +778,14 @@ struct dev_db_entry {
#define FLASH_EOF_OFFSET (FLASH_DEFAULTBLOCKSIZE-8) /* 4 bytes
* for EOF
* signature */
+#define FLASH_RAW_ACCESS_ADDR 0x8e000000
+
+#define BOOT_PARAM_OFFSET_PORT0 0x3b0
+#define BOOT_PARAM_OFFSET_PORT1 0x7b0
+
+#define FLASH_OFFSET_DB_INFO 0x05000000
+#define FLASH_OFFSET_DB_END (FLASH_OFFSET_DB_INFO + 0x7fff)
+
struct sys_info_phys_addr {
uint8_t address[6]; /* 00-05 */
@@ -774,6 +921,7 @@ struct qla4_header {
uint8_t entryStatus;
uint8_t systemDefined;
+#define SD_ISCSI_PDU 0x01
uint8_t entryCount;
/* SyetemDefined definition */
@@ -931,21 +1079,22 @@ struct passthru0 {
struct qla4_header hdr; /* 00-03 */
uint32_t handle; /* 04-07 */
uint16_t target; /* 08-09 */
- uint16_t connectionID; /* 0A-0B */
+ uint16_t connection_id; /* 0A-0B */
#define ISNS_DEFAULT_SERVER_CONN_ID ((uint16_t)0x8000)
- uint16_t controlFlags; /* 0C-0D */
+ uint16_t control_flags; /* 0C-0D */
#define PT_FLAG_ETHERNET_FRAME 0x8000
#define PT_FLAG_ISNS_PDU 0x8000
#define PT_FLAG_SEND_BUFFER 0x0200
#define PT_FLAG_WAIT_4_RESPONSE 0x0100
+#define PT_FLAG_ISCSI_PDU 0x1000
uint16_t timeout; /* 0E-0F */
#define PT_DEFAULT_TIMEOUT 30 /* seconds */
- struct data_seg_a64 outDataSeg64; /* 10-1B */
+ struct data_seg_a64 out_dsd; /* 10-1B */
uint32_t res1; /* 1C-1F */
- struct data_seg_a64 inDataSeg64; /* 20-2B */
+ struct data_seg_a64 in_dsd; /* 20-2B */
uint8_t res2[20]; /* 2C-3F */
};
@@ -978,4 +1127,43 @@ struct response {
#define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */
};
+struct ql_iscsi_stats {
+ uint8_t reserved1[656]; /* 0000-028F */
+ uint32_t tx_cmd_pdu; /* 0290-0293 */
+ uint32_t tx_resp_pdu; /* 0294-0297 */
+ uint32_t rx_cmd_pdu; /* 0298-029B */
+ uint32_t rx_resp_pdu; /* 029C-029F */
+
+ uint64_t tx_data_octets; /* 02A0-02A7 */
+ uint64_t rx_data_octets; /* 02A8-02AF */
+
+ uint32_t hdr_digest_err; /* 02B0–02B3 */
+ uint32_t data_digest_err; /* 02B4–02B7 */
+ uint32_t conn_timeout_err; /* 02B8–02BB */
+ uint32_t framing_err; /* 02BC–02BF */
+
+ uint32_t tx_nopout_pdus; /* 02C0–02C3 */
+ uint32_t tx_scsi_cmd_pdus; /* 02C4–02C7 */
+ uint32_t tx_tmf_cmd_pdus; /* 02C8–02CB */
+ uint32_t tx_login_cmd_pdus; /* 02CC–02CF */
+ uint32_t tx_text_cmd_pdus; /* 02D0–02D3 */
+ uint32_t tx_scsi_write_pdus; /* 02D4–02D7 */
+ uint32_t tx_logout_cmd_pdus; /* 02D8–02DB */
+ uint32_t tx_snack_req_pdus; /* 02DC–02DF */
+
+ uint32_t rx_nopin_pdus; /* 02E0–02E3 */
+ uint32_t rx_scsi_resp_pdus; /* 02E4–02E7 */
+ uint32_t rx_tmf_resp_pdus; /* 02E8–02EB */
+ uint32_t rx_login_resp_pdus; /* 02EC–02EF */
+ uint32_t rx_text_resp_pdus; /* 02F0–02F3 */
+ uint32_t rx_scsi_read_pdus; /* 02F4–02F7 */
+ uint32_t rx_logout_resp_pdus; /* 02F8–02FB */
+
+ uint32_t rx_r2t_pdus; /* 02FC–02FF */
+ uint32_t rx_async_pdus; /* 0300–0303 */
+ uint32_t rx_reject_pdus; /* 0304–0307 */
+
+ uint8_t reserved2[264]; /* 0x0308 - 0x040F */
+};
+
#endif /* _QLA4X_FW_H */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index a53a256..d0dd4b3 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -12,20 +12,15 @@ struct iscsi_cls_conn;
int qla4xxx_hw_reset(struct scsi_qla_host *ha);
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
-int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb);
-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
- uint8_t renew_ddb_list);
+int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset);
int qla4xxx_soft_reset(struct scsi_qla_host *ha);
irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id);
-void qla4xxx_free_ddb_list(struct scsi_qla_host *ha);
void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry);
void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen);
int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha);
-int qla4xxx_relogin_device(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry);
int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb);
int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry,
int lun);
@@ -51,15 +46,24 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
uint16_t *connection_id);
int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
- dma_addr_t fw_ddb_entry_dma);
-
-void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry);
+ dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts);
+uint8_t qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma);
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
+ uint16_t fw_ddb_index,
+ uint16_t connection_id,
+ uint16_t option);
+int qla4xxx_disable_acb(struct scsi_qla_host *ha);
+int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ uint32_t *mbox_sts, dma_addr_t acb_dma);
+int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
+ uint32_t acb_type, uint32_t len);
+int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
+ uint32_t ip_idx, uint32_t *sts);
+void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session);
u16 rd_nvram_word(struct scsi_qla_host *ha, int offset);
+u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset);
void qla4xxx_get_crash_record(struct scsi_qla_host *ha);
-struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha);
-int qla4xxx_add_sess(struct ddb_entry *);
-void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry);
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha);
int qla4xxx_about_firmware(struct scsi_qla_host *ha);
void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha,
@@ -68,14 +72,13 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha);
void qla4xxx_srb_compl(struct kref *ref);
struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
uint32_t index);
-int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha);
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
uint32_t state, uint32_t conn_error);
void qla4xxx_dump_buffer(void *b, uint32_t size);
int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
-int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err);
-
+int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+ uint32_t offset, uint32_t length, uint32_t options);
int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
@@ -95,6 +98,11 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha);
void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha);
void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha);
void qla4xxx_dump_registers(struct scsi_qla_host *ha);
+uint8_t qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
+ uint32_t *mbox_cmd,
+ uint32_t *mbox_sts,
+ struct addr_ctrl_blk *init_fw_cb,
+ dma_addr_t init_fw_cb_dma);
void qla4_8xxx_pci_config(struct scsi_qla_host *);
int qla4_8xxx_iospace_config(struct scsi_qla_host *ha);
@@ -134,6 +142,51 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha);
void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha);
void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha);
void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha);
+int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index);
+int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry,
+ struct iscsi_cls_conn *cls_conn,
+ uint32_t *mbx_sts);
+int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry, int options);
+int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ uint32_t *mbx_sts);
+int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index);
+int qla4xxx_send_passthru0(struct iscsi_task *task);
+void qla4xxx_free_ddb_index(struct scsi_qla_host *ha);
+int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
+ uint16_t stats_size, dma_addr_t stats_dma);
+void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry);
+void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry);
+int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index);
+int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username,
+ char *password, uint16_t idx);
+int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size);
+int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size);
+int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
+ uint32_t region, uint32_t field0,
+ uint32_t field1);
+int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index);
+void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session);
+int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session);
+int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session);
+int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ struct ddb_entry *ddb_entry, uint32_t state);
+int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ struct ddb_entry *ddb_entry, uint32_t state);
+void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset);
+
+/* BSG Functions */
+int qla4xxx_bsg_request(struct bsg_job *bsg_job);
+int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job);
+
+void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry);
extern int ql4xextended_error_logging;
extern int ql4xdontresethba;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 42ed5db..1bdfa81 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -11,9 +11,6 @@
#include "ql4_dbg.h"
#include "ql4_inline.h"
-static struct ddb_entry *qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index);
-
static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
{
uint32_t value;
@@ -48,41 +45,15 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
* @ha: pointer to host adapter structure.
* @ddb_entry: pointer to device database entry
*
- * This routine deallocates and unlinks the specified ddb_entry from the
- * adapter's
+ * This routine marks a DDB entry INVALID
**/
void qla4xxx_free_ddb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry)
{
- /* Remove device entry from list */
- list_del_init(&ddb_entry->list);
-
/* Remove device pointer from index mapping arrays */
ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] =
(struct ddb_entry *) INVALID_ENTRY;
ha->tot_ddbs--;
-
- /* Free memory and scsi-ml struct for device entry */
- qla4xxx_destroy_sess(ddb_entry);
-}
-
-/**
- * qla4xxx_free_ddb_list - deallocate all ddbs
- * @ha: pointer to host adapter structure.
- *
- * This routine deallocates and removes all devices on the sppecified adapter.
- **/
-void qla4xxx_free_ddb_list(struct scsi_qla_host *ha)
-{
- struct list_head *ptr;
- struct ddb_entry *ddb_entry;
-
- while (!list_empty(&ha->ddb_list)) {
- ptr = ha->ddb_list.next;
- /* Free memory for device entry and remove */
- ddb_entry = list_entry(ptr, struct ddb_entry, list);
- qla4xxx_free_ddb(ha, ddb_entry);
- }
}
/**
@@ -236,38 +207,44 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) {
ipv4_wait = 1;
}
- if (((ha->ipv6_addl_options &
- IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
- ((ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) ||
- (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) ||
- (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING))) {
+ if (((ha->ip_config.ipv6_addl_options &
+ IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
+ ((ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_ACQUIRING) ||
+ (ha->ip_config.ipv6_addr0_state ==
+ IP_ADDRSTATE_ACQUIRING) ||
+ (ha->ip_config.ipv6_addr1_state ==
+ IP_ADDRSTATE_ACQUIRING))) {
ipv6_wait = 1;
- if ((ha->ipv6_link_local_state ==
- IP_ADDRSTATE_PREFERRED) ||
- (ha->ipv6_addr0_state == IP_ADDRSTATE_PREFERRED) ||
- (ha->ipv6_addr1_state == IP_ADDRSTATE_PREFERRED)) {
+ if ((ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_PREFERRED) ||
+ (ha->ip_config.ipv6_addr0_state ==
+ IP_ADDRSTATE_PREFERRED) ||
+ (ha->ip_config.ipv6_addr1_state ==
+ IP_ADDRSTATE_PREFERRED)) {
DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
"Preferred IP configured."
" Don't wait!\n", ha->host_no,
__func__));
ipv6_wait = 0;
}
- if (memcmp(&ha->ipv6_default_router_addr, ip_address,
- IPv6_ADDR_LEN) == 0) {
+ if (memcmp(&ha->ip_config.ipv6_default_router_addr,
+ ip_address, IPv6_ADDR_LEN) == 0) {
DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
"No Router configured. "
"Don't wait!\n", ha->host_no,
__func__));
ipv6_wait = 0;
}
- if ((ha->ipv6_default_router_state ==
- IPV6_RTRSTATE_MANUAL) &&
- (ha->ipv6_link_local_state ==
- IP_ADDRSTATE_TENTATIVE) &&
- (memcmp(&ha->ipv6_link_local_addr,
- &ha->ipv6_default_router_addr, 4) == 0)) {
+ if ((ha->ip_config.ipv6_default_router_state ==
+ IPV6_RTRSTATE_MANUAL) &&
+ (ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_TENTATIVE) &&
+ (memcmp(&ha->ip_config.ipv6_link_local_addr,
+ &ha->ip_config.ipv6_default_router_addr, 4) ==
+ 0)) {
DEBUG2(printk("scsi%ld: %s: LinkLocal Router & "
"IP configured. Don't wait!\n",
ha->host_no, __func__));
@@ -279,11 +256,14 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
"IP(s) \"", ha->host_no, __func__));
if (ipv4_wait)
DEBUG2(printk("IPv4 "));
- if (ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING)
+ if (ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_ACQUIRING)
DEBUG2(printk("IPv6LinkLocal "));
- if (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING)
+ if (ha->ip_config.ipv6_addr0_state ==
+ IP_ADDRSTATE_ACQUIRING)
DEBUG2(printk("IPv6Addr0 "));
- if (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING)
+ if (ha->ip_config.ipv6_addr1_state ==
+ IP_ADDRSTATE_ACQUIRING)
DEBUG2(printk("IPv6Addr1 "));
DEBUG2(printk("\"\n"));
}
@@ -466,486 +446,19 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
return qla4xxx_get_firmware_status(ha);
}
-static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index,
- uint32_t *new_tgt)
+static void qla4xxx_set_model_info(struct scsi_qla_host *ha)
{
- struct dev_db_entry *fw_ddb_entry = NULL;
- dma_addr_t fw_ddb_entry_dma;
- struct ddb_entry *ddb_entry = NULL;
- int found = 0;
- uint32_t device_state;
-
- *new_tgt = 0;
- /* Make sure the dma buffer is valid */
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (fw_ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
- goto exit_get_ddb_entry_no_free;
- }
-
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
- fw_ddb_entry_dma, NULL, NULL,
- &device_state, NULL, NULL, NULL) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
- "fw_ddb_index %d\n", ha->host_no, __func__,
- fw_ddb_index));
- goto exit_get_ddb_entry;
- }
-
- /* Allocate DDB if not already allocated. */
- DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
- __func__, fw_ddb_index));
- list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
- if ((memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
- ISCSI_NAME_SIZE) == 0) &&
- (ddb_entry->tpgt ==
- le32_to_cpu(fw_ddb_entry->tgt_portal_grp)) &&
- (memcmp(ddb_entry->isid, fw_ddb_entry->isid,
- sizeof(ddb_entry->isid)) == 0)) {
- found++;
- break;
- }
+ uint16_t board_id_string[8];
+ int i;
+ int size = sizeof(ha->nvram->isp4022.boardIdStr);
+ int offset = offsetof(struct eeprom_data, isp4022.boardIdStr) / 2;
+
+ for (i = 0; i < (size / 2) ; i++) {
+ board_id_string[i] = rd_nvram_word(ha, offset);
+ offset += 1;
}
- /* if not found allocate new ddb */
- if (!found) {
- DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
- "new ddb\n", ha->host_no, __func__,
- fw_ddb_index));
- *new_tgt = 1;
- ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
- }
-
-exit_get_ddb_entry:
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
- fw_ddb_entry_dma);
-
-exit_get_ddb_entry_no_free:
- return ddb_entry;
-}
-
-/**
- * qla4xxx_update_ddb_entry - update driver's internal ddb
- * @ha: pointer to host adapter structure.
- * @ddb_entry: pointer to device database structure to be filled
- * @fw_ddb_index: index of the ddb entry in fw ddb table
- *
- * This routine updates the driver's internal device database entry
- * with information retrieved from the firmware's device database
- * entry for the specified device. The ddb_entry->fw_ddb_index field
- * must be initialized prior to calling this routine
- *
- **/
-static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry,
- uint32_t fw_ddb_index)
-{
- struct dev_db_entry *fw_ddb_entry = NULL;
- dma_addr_t fw_ddb_entry_dma;
- int status = QLA_ERROR;
- uint32_t conn_err;
-
- if (ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no,
- __func__));
-
- goto exit_update_ddb_no_free;
- }
-
- /* Make sure the dma buffer is valid */
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (fw_ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
-
- goto exit_update_ddb_no_free;
- }
-
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
- fw_ddb_entry_dma, NULL, NULL,
- &ddb_entry->fw_ddb_device_state, &conn_err,
- &ddb_entry->tcp_source_port_num,
- &ddb_entry->connection_id) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
- "fw_ddb_index %d\n", ha->host_no, __func__,
- fw_ddb_index));
-
- goto exit_update_ddb;
- }
-
- status = QLA_SUCCESS;
- ddb_entry->options = le16_to_cpu(fw_ddb_entry->options);
- ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
- ddb_entry->task_mgmt_timeout =
- le16_to_cpu(fw_ddb_entry->def_timeout);
- ddb_entry->CmdSn = 0;
- ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
- ddb_entry->default_relogin_timeout =
- le16_to_cpu(fw_ddb_entry->def_timeout);
- ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
-
- /* Update index in case it changed */
- ddb_entry->fw_ddb_index = fw_ddb_index;
- ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
-
- ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
- ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
- memcpy(ddb_entry->isid, fw_ddb_entry->isid, sizeof(ddb_entry->isid));
-
- memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
- min(sizeof(ddb_entry->iscsi_name),
- sizeof(fw_ddb_entry->iscsi_name)));
- memcpy(&ddb_entry->iscsi_alias[0], &fw_ddb_entry->iscsi_alias[0],
- min(sizeof(ddb_entry->iscsi_alias),
- sizeof(fw_ddb_entry->iscsi_alias)));
- memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
- min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
-
- ddb_entry->iscsi_max_burst_len = fw_ddb_entry->iscsi_max_burst_len;
- ddb_entry->iscsi_max_outsnd_r2t = fw_ddb_entry->iscsi_max_outsnd_r2t;
- ddb_entry->iscsi_first_burst_len = fw_ddb_entry->iscsi_first_burst_len;
- ddb_entry->iscsi_max_rcv_data_seg_len =
- fw_ddb_entry->iscsi_max_rcv_data_seg_len;
- ddb_entry->iscsi_max_snd_data_seg_len =
- fw_ddb_entry->iscsi_max_snd_data_seg_len;
-
- if (ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
- memcpy(&ddb_entry->remote_ipv6_addr,
- fw_ddb_entry->ip_addr,
- min(sizeof(ddb_entry->remote_ipv6_addr),
- sizeof(fw_ddb_entry->ip_addr)));
- memcpy(&ddb_entry->link_local_ipv6_addr,
- fw_ddb_entry->link_local_ipv6_addr,
- min(sizeof(ddb_entry->link_local_ipv6_addr),
- sizeof(fw_ddb_entry->link_local_ipv6_addr)));
-
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
- " ConnErr %08x IP %pI6 "
- ":%04d \"%s\"\n",
- __func__, fw_ddb_index,
- ddb_entry->fw_ddb_device_state,
- conn_err, fw_ddb_entry->ip_addr,
- le16_to_cpu(fw_ddb_entry->port),
- fw_ddb_entry->iscsi_name));
- } else
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
- " ConnErr %08x IP %pI4 "
- ":%04d \"%s\"\n",
- __func__, fw_ddb_index,
- ddb_entry->fw_ddb_device_state,
- conn_err, fw_ddb_entry->ip_addr,
- le16_to_cpu(fw_ddb_entry->port),
- fw_ddb_entry->iscsi_name));
-exit_update_ddb:
- if (fw_ddb_entry)
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
- fw_ddb_entry, fw_ddb_entry_dma);
-
-exit_update_ddb_no_free:
- return status;
-}
-
-/**
- * qla4xxx_alloc_ddb - allocate device database entry
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- *
- * This routine allocates a ddb_entry, ititializes some values, and
- * inserts it into the ddb list.
- **/
-static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index)
-{
- struct ddb_entry *ddb_entry;
-
- DEBUG2(printk("scsi%ld: %s: fw_ddb_index [%d]\n", ha->host_no,
- __func__, fw_ddb_index));
-
- ddb_entry = qla4xxx_alloc_sess(ha);
- if (ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
- "to add fw_ddb_index [%d]\n",
- ha->host_no, __func__, fw_ddb_index));
- return ddb_entry;
- }
-
- ddb_entry->fw_ddb_index = fw_ddb_index;
- atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
- atomic_set(&ddb_entry->relogin_timer, 0);
- atomic_set(&ddb_entry->relogin_retry_count, 0);
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- list_add_tail(&ddb_entry->list, &ha->ddb_list);
- ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
- ha->tot_ddbs++;
-
- return ddb_entry;
-}
-
-/**
- * qla4_is_relogin_allowed - Are we allowed to login?
- * @ha: Pointer to host adapter structure.
- * @conn_err: Last connection error associated with the ddb
- *
- * This routine tests the given connection error to determine if
- * we are allowed to login.
- **/
-int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err)
-{
- uint32_t err_code, login_rsp_sts_class;
- int relogin = 1;
-
- err_code = ((conn_err & 0x00ff0000) >> 16);
- login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8);
- if (err_code == 0x1c || err_code == 0x06) {
- DEBUG2(ql4_printk(KERN_INFO, ha,
- ": conn_err=0x%08x, send target completed"
- " or access denied failure\n", conn_err));
- relogin = 0;
- }
- if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) {
- /* Login Response PDU returned an error.
- Login Response Status in Error Code Detail
- indicates login should not be retried.*/
- DEBUG2(ql4_printk(KERN_INFO, ha,
- ": conn_err=0x%08x, do not retry relogin\n",
- conn_err));
- relogin = 0;
- }
-
- return relogin;
-}
-
-static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
-{
- unsigned long wtime;
-
- /* Flush the 0x8014 AEN from the firmware as a result of
- * Auto connect. We are basically doing get_firmware_ddb()
- * to determine whether we need to log back in or not.
- * Trying to do a set ddb before we have processed 0x8014
- * will result in another set_ddb() for the same ddb. In other
- * words there will be stale entries in the aen_q.
- */
- wtime = jiffies + (2 * HZ);
- do {
- if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
- if (ha->firmware_state & (BIT_2 | BIT_0))
- return;
-
- if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
- qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
-
- msleep(1000);
- } while (!time_after_eq(jiffies, wtime));
-}
-
-/**
- * qla4xxx_build_ddb_list - builds driver ddb list
- * @ha: Pointer to host adapter structure.
- *
- * This routine searches for all valid firmware ddb entries and builds
- * an internal ddb list. Ddbs that are considered valid are those with
- * a device state of SESSION_ACTIVE.
- * A relogin (set_ddb) is issued for DDBs that are not online.
- **/
-static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
-{
- int status = QLA_ERROR;
- uint32_t fw_ddb_index = 0;
- uint32_t next_fw_ddb_index = 0;
- uint32_t ddb_state;
- uint32_t conn_err;
- struct ddb_entry *ddb_entry;
- struct dev_db_entry *fw_ddb_entry = NULL;
- dma_addr_t fw_ddb_entry_dma;
- uint32_t ipv6_device;
- uint32_t new_tgt;
-
- qla4xxx_flush_AENS(ha);
-
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (fw_ddb_entry == NULL) {
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DMA alloc failed\n",
- __func__));
-
- goto exit_build_ddb_list_no_free;
- }
-
- ql4_printk(KERN_INFO, ha, "Initializing DDBs ...\n");
- for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
- fw_ddb_index = next_fw_ddb_index) {
- /* First, let's see if a device exists here */
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
- 0, NULL, &next_fw_ddb_index,
- &ddb_state, &conn_err,
- NULL, NULL) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: get_ddb_entry, "
- "fw_ddb_index %d failed", ha->host_no,
- __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
-
- DEBUG2(printk("scsi%ld: %s: Getting DDB[%d] ddbstate=0x%x, "
- "next_fw_ddb_index=%d.\n", ha->host_no, __func__,
- fw_ddb_index, ddb_state, next_fw_ddb_index));
-
- /* Issue relogin, if necessary. */
- if (ddb_state == DDB_DS_SESSION_FAILED ||
- ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) {
- /* Try and login to device */
- DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n",
- ha->host_no, __func__, fw_ddb_index));
- ipv6_device = le16_to_cpu(fw_ddb_entry->options) &
- DDB_OPT_IPV6_DEVICE;
- if (qla4_is_relogin_allowed(ha, conn_err) &&
- ((!ipv6_device &&
- *((uint32_t *)fw_ddb_entry->ip_addr))
- || ipv6_device)) {
- qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
- NULL, 0, NULL,
- &next_fw_ddb_index,
- &ddb_state, &conn_err,
- NULL, NULL)
- == QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s:"
- "get_ddb_entry %d failed\n",
- ha->host_no,
- __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
- }
- }
-
- if (ddb_state != DDB_DS_SESSION_ACTIVE)
- goto next_one;
- /*
- * if fw_ddb with session active state found,
- * add to ddb_list
- */
- DEBUG2(printk("scsi%ld: %s: DDB[%d] added to list\n",
- ha->host_no, __func__, fw_ddb_index));
-
- /* Add DDB to internal our ddb list. */
- ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
- if (ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
- "for device at fw_ddb_index %d\n",
- ha->host_no, __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
- /* Fill in the device structure */
- if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
- QLA_ERROR) {
- ha->fw_ddb_index_map[fw_ddb_index] =
- (struct ddb_entry *)INVALID_ENTRY;
-
- DEBUG2(printk("scsi%ld: %s: update_ddb_entry failed "
- "for fw_ddb_index %d.\n",
- ha->host_no, __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
-
-next_one:
- /* We know we've reached the last device when
- * next_fw_ddb_index is 0 */
- if (next_fw_ddb_index == 0)
- break;
- }
-
- status = QLA_SUCCESS;
- ql4_printk(KERN_INFO, ha, "DDB list done..\n");
-
-exit_build_ddb_list:
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
- fw_ddb_entry_dma);
-
-exit_build_ddb_list_no_free:
- return status;
-}
-
-static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
-{
- uint16_t fw_ddb_index;
- int status = QLA_SUCCESS;
-
- /* free the ddb list if is not empty */
- if (!list_empty(&ha->ddb_list))
- qla4xxx_free_ddb_list(ha);
-
- for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
- ha->fw_ddb_index_map[fw_ddb_index] =
- (struct ddb_entry *)INVALID_ENTRY;
-
- ha->tot_ddbs = 0;
-
- /* Perform device discovery and build ddb list. */
- status = qla4xxx_build_ddb_list(ha);
-
- return status;
-}
-
-/**
- * qla4xxx_reinitialize_ddb_list - update the driver ddb list
- * @ha: pointer to host adapter structure.
- *
- * This routine obtains device information from the F/W database after
- * firmware or adapter resets. The device table is preserved.
- **/
-int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha)
-{
- int status = QLA_SUCCESS;
- struct ddb_entry *ddb_entry, *detemp;
-
- /* Update the device information for all devices. */
- list_for_each_entry_safe(ddb_entry, detemp, &ha->ddb_list, list) {
- qla4xxx_update_ddb_entry(ha, ddb_entry,
- ddb_entry->fw_ddb_index);
- if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- DEBUG2(printk ("scsi%ld: %s: ddb index [%d] marked "
- "ONLINE\n", ha->host_no, __func__,
- ddb_entry->fw_ddb_index));
- iscsi_unblock_session(ddb_entry->sess);
- } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
- qla4xxx_mark_device_missing(ha, ddb_entry);
- }
- return status;
-}
-
-/**
- * qla4xxx_relogin_device - re-establish session
- * @ha: Pointer to host adapter structure.
- * @ddb_entry: Pointer to device database entry
- *
- * This routine does a session relogin with the specified device.
- * The ddb entry must be assigned prior to making this call.
- **/
-int qla4xxx_relogin_device(struct scsi_qla_host *ha,
- struct ddb_entry * ddb_entry)
-{
- uint16_t relogin_timer;
-
- relogin_timer = max(ddb_entry->default_relogin_timeout,
- (uint16_t)RELOGIN_TOV);
- atomic_set(&ddb_entry->relogin_timer, relogin_timer);
-
- DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no,
- ddb_entry->fw_ddb_index, relogin_timer));
-
- qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0);
-
- return QLA_SUCCESS;
+ memcpy(ha->model_name, board_id_string, size);
}
static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
@@ -983,6 +496,12 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
else
return QLA_ERROR;
}
+
+ if (is_qla4022(ha) || is_qla4032(ha))
+ qla4xxx_set_model_info(ha);
+ else
+ strcpy(ha->model_name, "QLA4010");
+
DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n",
ha->host_no, __func__, extHwConfig.Asuint32_t));
@@ -1246,23 +765,57 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
}
return status;
}
-
+/**
+ * qla4xxx_free_ddb_index - Free DDBs reserved by firmware
+ * @ha: pointer to adapter structure
+ *
+ * Since firmware is not running in autoconnect mode the DDB indices should
+ * be freed so that when login happens from user space there are free DDB
+ * indices available.
+ **/
+void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+{
+ int max_ddbs;
+ int ret;
+ uint32_t idx = 0, next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
+
+ for (idx = 0; idx < max_ddbs; idx = next_idx) {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL,
+ &next_idx, &state, &conn_err,
+ NULL, NULL);
+ if (ret == QLA_ERROR) {
+ next_idx++;
+ continue;
+ }
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Freeing DDB index = 0x%x\n", idx));
+ ret = qla4xxx_clear_ddb_entry(ha, idx);
+ if (ret == QLA_ERROR)
+ ql4_printk(KERN_ERR, ha,
+ "Unable to clear DDB index = "
+ "0x%x\n", idx);
+ }
+ if (next_idx == 0)
+ break;
+ }
+}
/**
* qla4xxx_initialize_adapter - initiailizes hba
* @ha: Pointer to host adapter structure.
- * @renew_ddb_list: Indicates what to do with the adapter's ddb list
- * after adapter recovery has completed.
- * 0=preserve ddb list, 1=destroy and rebuild ddb list
*
* This routine parforms all of the steps necessary to initialize the adapter.
*
**/
-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
- uint8_t renew_ddb_list)
+int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
{
int status = QLA_ERROR;
- int8_t ip_address[IP_ADDR_LEN] = {0} ;
ha->eeprom_cmd_data = 0;
@@ -1288,47 +841,9 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
if (status == QLA_ERROR)
goto exit_init_hba;
- /*
- * FW is waiting to get an IP address from DHCP server: Skip building
- * the ddb_list and wait for DHCP lease acquired aen to come in
- * followed by 0x8014 aen" to trigger the tgt discovery process.
- */
- if (ha->firmware_state & FW_STATE_CONFIGURING_IP)
- goto exit_init_online;
-
- /* Skip device discovery if ip and subnet is zero */
- if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
- memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
- goto exit_init_online;
-
- if (renew_ddb_list == PRESERVE_DDB_LIST) {
- /*
- * We want to preserve lun states (i.e. suspended, etc.)
- * for recovery initiated by the driver. So just update
- * the device states for the existing ddb_list.
- */
- qla4xxx_reinitialize_ddb_list(ha);
- } else if (renew_ddb_list == REBUILD_DDB_LIST) {
- /*
- * We want to build the ddb_list from scratch during
- * driver initialization and recovery initiated by the
- * INT_HBA_RESET IOCTL.
- */
- status = qla4xxx_initialize_ddb_list(ha);
- if (status == QLA_ERROR) {
- DEBUG2(printk("%s(%ld) Error occurred during build"
- "ddb list\n", __func__, ha->host_no));
- goto exit_init_hba;
- }
-
- }
- if (!ha->tot_ddbs) {
- DEBUG2(printk("scsi%ld: Failed to initialize devices or none "
- "present in Firmware device database\n",
- ha->host_no));
- }
+ if (is_reset == RESET_ADAPTER)
+ qla4xxx_build_ddb_list(ha, is_reset);
-exit_init_online:
set_bit(AF_ONLINE, &ha->flags);
exit_init_hba:
if (is_qla8022(ha) && (status == QLA_ERROR)) {
@@ -1342,59 +857,160 @@ exit_init_hba:
return status;
}
-/**
- * qla4xxx_add_device_dynamically - ddb addition due to an AEN
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- *
- * This routine processes adds a device as a result of an 8014h AEN.
- **/
-static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index)
+int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ struct ddb_entry *ddb_entry, uint32_t state)
{
- struct ddb_entry * ddb_entry;
- uint32_t new_tgt;
+ uint32_t old_fw_ddb_device_state;
+ int status = QLA_ERROR;
- /* First allocate a device structure */
- ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
- if (ddb_entry == NULL) {
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: Unable to allocate memory to add "
- "fw_ddb_index %d\n", ha->host_no, fw_ddb_index));
- return;
- }
+ old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: DDB - old state = 0x%x, new state = 0x%x for "
+ "index [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
- if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
- /* Target has been bound to a new fw_ddb_index */
- qla4xxx_free_ddb(ha, ddb_entry);
- ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
- if (ddb_entry == NULL) {
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: Unable to allocate memory"
- " to add fw_ddb_index %d\n",
- ha->host_no, fw_ddb_index));
- return;
+ ddb_entry->fw_ddb_device_state = state;
+
+ switch (old_fw_ddb_device_state) {
+ case DDB_DS_LOGIN_IN_PROCESS:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ case DDB_DS_DISCOVERY:
+ ddb_entry->unblock_sess(ddb_entry->sess);
+ qla4xxx_update_session_conn_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ case DDB_DS_NO_CONNECTION_ACTIVE:
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_FREE);
+ status = QLA_SUCCESS;
+ break;
}
+ break;
+ case DDB_DS_SESSION_ACTIVE:
+ switch (state) {
+ case DDB_DS_SESSION_FAILED:
+ /*
+ * iscsi_session failure will cause userspace to
+ * stop the connection which in turn would block the
+ * iscsi_session and start relogin
+ */
+ iscsi_session_failure(ddb_entry->sess->dd_data,
+ ISCSI_ERR_CONN_FAILED);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_NO_CONNECTION_ACTIVE:
+ clear_bit(fw_ddb_index, ha->ddb_idx_map);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ case DDB_DS_SESSION_FAILED:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ case DDB_DS_DISCOVERY:
+ ddb_entry->unblock_sess(ddb_entry->sess);
+ qla4xxx_update_session_conn_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ iscsi_session_failure(ddb_entry->sess->dd_data,
+ ISCSI_ERR_CONN_FAILED);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ default:
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
+ __func__));
+ break;
}
- if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
- QLA_ERROR) {
- ha->fw_ddb_index_map[fw_ddb_index] =
- (struct ddb_entry *)INVALID_ENTRY;
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: failed to add new device at index "
- "[%d]\n Unable to retrieve fw ddb entry\n",
- ha->host_no, fw_ddb_index));
- qla4xxx_free_ddb(ha, ddb_entry);
- return;
- }
+ return status;
+}
+
+void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry)
+{
+ /*
+ * This triggers a relogin. After the relogin_timer
+ * expires, the relogin gets scheduled. We must wait a
+ * minimum amount of time since receiving an 0x8014 AEN
+ * with failed device_state or a logout response before
+ * we can issue another relogin.
+ *
+ * Firmware pads this timeout: (time2wait +1).
+ * Driver retry to login should be longer than F/W.
+ * Otherwise F/W will fail
+ * set_ddb() mbx cmd with 0x4005 since it still
+ * counting down its time2wait.
+ */
+ atomic_set(&ddb_entry->relogin_timer, 0);
+ atomic_set(&ddb_entry->retry_relogin_timer,
+ ddb_entry->default_time2wait + 4);
+
+}
+
+int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ struct ddb_entry *ddb_entry, uint32_t state)
+{
+ uint32_t old_fw_ddb_device_state;
+ int status = QLA_ERROR;
- if (qla4xxx_add_sess(ddb_entry)) {
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: failed to add new device at index "
- "[%d]\n Unable to add connection and session\n",
- ha->host_no, fw_ddb_index));
- qla4xxx_free_ddb(ha, ddb_entry);
+ old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: DDB - old state = 0x%x, new state = 0x%x for "
+ "index [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
+
+ ddb_entry->fw_ddb_device_state = state;
+
+ switch (old_fw_ddb_device_state) {
+ case DDB_DS_LOGIN_IN_PROCESS:
+ case DDB_DS_NO_CONNECTION_ACTIVE:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ ddb_entry->unblock_sess(ddb_entry->sess);
+ qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ iscsi_block_session(ddb_entry->sess);
+ if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
+ qla4xxx_arm_relogin_timer(ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ case DDB_DS_SESSION_ACTIVE:
+ switch (state) {
+ case DDB_DS_SESSION_FAILED:
+ iscsi_block_session(ddb_entry->sess);
+ if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
+ qla4xxx_arm_relogin_timer(ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ case DDB_DS_SESSION_FAILED:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ ddb_entry->unblock_sess(ddb_entry->sess);
+ qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
+ qla4xxx_arm_relogin_timer(ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ default:
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
+ __func__));
+ break;
}
+ return status;
}
/**
@@ -1405,92 +1021,103 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha,
*
* This routine processes a Decive Database Changed AEN Event.
**/
-int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
- uint32_t state, uint32_t conn_err)
+int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
+ uint32_t fw_ddb_index,
+ uint32_t state, uint32_t conn_err)
{
- struct ddb_entry * ddb_entry;
+ struct ddb_entry *ddb_entry;
+ int status = QLA_ERROR;
/* check for out of range index */
if (fw_ddb_index >= MAX_DDB_ENTRIES)
- return QLA_ERROR;
+ goto exit_ddb_event;
/* Get the corresponging ddb entry */
ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
/* Device does not currently exist in our database. */
if (ddb_entry == NULL) {
- if (state == DDB_DS_SESSION_ACTIVE)
- qla4xxx_add_device_dynamically(ha, fw_ddb_index);
- return QLA_SUCCESS;
+ ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
+ __func__, fw_ddb_index);
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE)
+ clear_bit(fw_ddb_index, ha->ddb_idx_map);
+
+ goto exit_ddb_event;
}
- /* Device already exists in our database. */
- DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
- "index [%d]\n", ha->host_no, __func__,
- ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
+ ddb_entry->ddb_change(ha, fw_ddb_index, ddb_entry, state);
- ddb_entry->fw_ddb_device_state = state;
- /* Device is back online. */
- if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) &&
- (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) {
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- atomic_set(&ddb_entry->relogin_retry_count, 0);
- atomic_set(&ddb_entry->relogin_timer, 0);
- clear_bit(DF_RELOGIN, &ddb_entry->flags);
- iscsi_unblock_session(ddb_entry->sess);
- iscsi_session_event(ddb_entry->sess,
- ISCSI_KEVENT_CREATE_SESSION);
- /*
- * Change the lun state to READY in case the lun TIMEOUT before
- * the device came back.
- */
- } else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) {
- /* Device went away, mark device missing */
- if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
- "ddb_entry 0x%p sess 0x%p conn 0x%p\n",
- __func__, ddb_entry,
- ddb_entry->sess, ddb_entry->conn));
- qla4xxx_mark_device_missing(ha, ddb_entry);
- }
+exit_ddb_event:
+ return status;
+}
- /*
- * Relogin if device state changed to a not active state.
- * However, do not relogin if a RELOGIN is in process, or
- * we are not allowed to relogin to this DDB.
- */
- if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
- !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
- qla4_is_relogin_allowed(ha, conn_err)) {
- /*
- * This triggers a relogin. After the relogin_timer
- * expires, the relogin gets scheduled. We must wait a
- * minimum amount of time since receiving an 0x8014 AEN
- * with failed device_state or a logout response before
- * we can issue another relogin.
- */
- /* Firmware pads this timeout: (time2wait +1).
- * Driver retry to login should be longer than F/W.
- * Otherwise F/W will fail
- * set_ddb() mbx cmd with 0x4005 since it still
- * counting down its time2wait.
- */
- atomic_set(&ddb_entry->relogin_timer, 0);
- atomic_set(&ddb_entry->retry_relogin_timer,
- ddb_entry->default_time2wait + 4);
- DEBUG(printk("scsi%ld: %s: ddb[%d] "
- "initiate relogin after %d seconds\n",
- ha->host_no, __func__,
- ddb_entry->fw_ddb_index,
- ddb_entry->default_time2wait + 4));
- } else {
- DEBUG(printk("scsi%ld: %s: ddb[%d] "
- "relogin not initiated, state = %d, "
- "ddb_entry->flags = 0x%lx\n",
- ha->host_no, __func__,
- ddb_entry->fw_ddb_index,
- ddb_entry->fw_ddb_device_state,
- ddb_entry->flags));
- }
+/**
+ * qla4xxx_login_flash_ddb - Login to target (DDB)
+ * @cls_session: Pointer to the session to login
+ *
+ * This routine logins to the target.
+ * Issues setddb and conn open mbx
+ **/
+void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_dma;
+ uint32_t mbx_sts = 0;
+ int ret;
+
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ if (!test_bit(AF_LINK_UP, &ha->flags))
+ return;
+
+ if (ddb_entry->ddb_type != FLASH_DDB) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Skipping login to non FLASH DB"));
+ goto exit_login;
}
- return QLA_SUCCESS;
+
+ fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
+ &fw_ddb_dma);
+ if (fw_ddb_entry == NULL) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
+ goto exit_login;
+ }
+
+ if (ddb_entry->fw_ddb_index == INVALID_ENTRY) {
+ ret = qla4xxx_get_ddb_index(ha, &ddb_entry->fw_ddb_index);
+ if (ret == QLA_ERROR)
+ goto exit_login;
+
+ ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
+ ha->tot_ddbs++;
+ }
+
+ memcpy(fw_ddb_entry, &ddb_entry->fw_ddb_entry,
+ sizeof(struct dev_db_entry));
+ ddb_entry->sess->target_id = ddb_entry->fw_ddb_index;
+
+ ret = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
+ fw_ddb_dma, &mbx_sts);
+ if (ret == QLA_ERROR) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Set DDB failed\n"));
+ goto exit_login;
+ }
+
+ ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+ ret = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);
+ if (ret == QLA_ERROR) {
+ ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,
+ sess->targetname);
+ goto exit_login;
+ }
+
+exit_login:
+ if (fw_ddb_entry)
+ dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
}
+
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 75fcd82..4106693 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -313,10 +313,8 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
cmd_entry->hdr.entryType = ET_COMMAND;
cmd_entry->handle = cpu_to_le32(index);
cmd_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
- cmd_entry->connection_id = cpu_to_le16(ddb_entry->connection_id);
int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
- cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd));
memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
@@ -381,3 +379,69 @@ queuing_error:
return QLA_ERROR;
}
+int qla4xxx_send_passthru0(struct iscsi_task *task)
+{
+ struct passthru0 *passthru_iocb;
+ struct iscsi_session *sess = task->conn->session;
+ struct ddb_entry *ddb_entry = sess->dd_data;
+ struct scsi_qla_host *ha = ddb_entry->ha;
+ struct ql4_task_data *task_data = task->dd_data;
+ uint16_t ctrl_flags = 0;
+ unsigned long flags;
+ int ret = QLA_ERROR;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ task_data->iocb_req_cnt = 1;
+ /* Put the IOCB on the request queue */
+ if (!qla4xxx_space_in_req_ring(ha, task_data->iocb_req_cnt))
+ goto queuing_error;
+
+ passthru_iocb = (struct passthru0 *) ha->request_ptr;
+
+ memset(passthru_iocb, 0, sizeof(struct passthru0));
+ passthru_iocb->hdr.entryType = ET_PASSTHRU0;
+ passthru_iocb->hdr.systemDefined = SD_ISCSI_PDU;
+ passthru_iocb->hdr.entryCount = task_data->iocb_req_cnt;
+ passthru_iocb->handle = task->itt;
+ passthru_iocb->target = cpu_to_le16(ddb_entry->fw_ddb_index);
+ passthru_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
+
+ /* Setup the out & in DSDs */
+ if (task_data->req_len) {
+ memcpy((uint8_t *)task_data->req_buffer +
+ sizeof(struct iscsi_hdr), task->data, task->data_count);
+ ctrl_flags |= PT_FLAG_SEND_BUFFER;
+ passthru_iocb->out_dsd.base.addrLow =
+ cpu_to_le32(LSDW(task_data->req_dma));
+ passthru_iocb->out_dsd.base.addrHigh =
+ cpu_to_le32(MSDW(task_data->req_dma));
+ passthru_iocb->out_dsd.count =
+ cpu_to_le32(task->data_count +
+ sizeof(struct iscsi_hdr));
+ }
+ if (task_data->resp_len) {
+ passthru_iocb->in_dsd.base.addrLow =
+ cpu_to_le32(LSDW(task_data->resp_dma));
+ passthru_iocb->in_dsd.base.addrHigh =
+ cpu_to_le32(MSDW(task_data->resp_dma));
+ passthru_iocb->in_dsd.count =
+ cpu_to_le32(task_data->resp_len);
+ }
+
+ ctrl_flags |= (PT_FLAG_ISCSI_PDU | PT_FLAG_WAIT_4_RESPONSE);
+ passthru_iocb->control_flags = cpu_to_le16(ctrl_flags);
+
+ /* Update the request pointer */
+ qla4xxx_advance_req_ring_ptr(ha);
+ wmb();
+
+ /* Track IOCB used */
+ ha->iocb_cnt += task_data->iocb_req_cnt;
+ ha->req_q_count -= task_data->iocb_req_cnt;
+ ha->isp_ops->queue_iocb(ha);
+ ret = QLA_SUCCESS;
+
+queuing_error:
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return ret;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 0e72921..827e930 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -224,8 +224,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
* I/O to this device. We should get a ddb state change
* AEN soon.
*/
- if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
- qla4xxx_mark_device_missing(ha, ddb_entry);
+ if (iscsi_is_session_online(ddb_entry->sess))
+ qla4xxx_mark_device_missing(ddb_entry->sess);
break;
case SCS_DATA_UNDERRUN:
@@ -306,8 +306,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
* send I/O to this device. We should get a ddb
* state change AEN soon.
*/
- if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
- qla4xxx_mark_device_missing(ha, ddb_entry);
+ if (iscsi_is_session_online(ddb_entry->sess))
+ qla4xxx_mark_device_missing(ddb_entry->sess);
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
break;
@@ -341,6 +341,51 @@ status_entry_exit:
}
/**
+ * qla4xxx_passthru_status_entry - processes passthru status IOCBs (0x3C)
+ * @ha: Pointer to host adapter structure.
+ * @sts_entry: Pointer to status entry structure.
+ **/
+static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha,
+ struct passthru_status *sts_entry)
+{
+ struct iscsi_task *task;
+ struct ddb_entry *ddb_entry;
+ struct ql4_task_data *task_data;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_conn *conn;
+ itt_t itt;
+ uint32_t fw_ddb_index;
+
+ itt = sts_entry->handle;
+ fw_ddb_index = le32_to_cpu(sts_entry->target);
+
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
+
+ if (ddb_entry == NULL) {
+ ql4_printk(KERN_ERR, ha, "%s: Invalid target index = 0x%x\n",
+ __func__, sts_entry->target);
+ return;
+ }
+
+ cls_conn = ddb_entry->conn;
+ conn = cls_conn->dd_data;
+ spin_lock(&conn->session->lock);
+ task = iscsi_itt_to_task(conn, itt);
+ spin_unlock(&conn->session->lock);
+
+ if (task == NULL) {
+ ql4_printk(KERN_ERR, ha, "%s: Task is NULL\n", __func__);
+ return;
+ }
+
+ task_data = task->dd_data;
+ memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status));
+ ha->req_q_count += task_data->iocb_req_cnt;
+ ha->iocb_cnt -= task_data->iocb_req_cnt;
+ queue_work(ha->task_wq, &task_data->task_work);
+}
+
+/**
* qla4xxx_process_response_queue - process response queue completions
* @ha: Pointer to host adapter structure.
*
@@ -375,6 +420,14 @@ void qla4xxx_process_response_queue(struct scsi_qla_host *ha)
break;
case ET_PASSTHRU_STATUS:
+ if (sts_entry->hdr.systemDefined == SD_ISCSI_PDU)
+ qla4xxx_passthru_status_entry(ha,
+ (struct passthru_status *)sts_entry);
+ else
+ ql4_printk(KERN_ERR, ha,
+ "%s: Invalid status received\n",
+ __func__);
+
break;
case ET_STATUS_CONTINUATION:
@@ -566,6 +619,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
(mbox_sts[2] == ACB_STATE_VALID))
set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED))
+ complete(&ha->disable_acb_comp);
break;
case MBOX_ASTS_MAC_ADDRESS_CHANGED:
@@ -1009,23 +1064,23 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
switch (mbox_sts[0]) {
case MBOX_ASTS_DATABASE_CHANGED:
- if (process_aen == FLUSH_DDB_CHANGED_AENS) {
+ switch (process_aen) {
+ case FLUSH_DDB_CHANGED_AENS:
DEBUG2(printk("scsi%ld: AEN[%d] %04x, index "
"[%d] state=%04x FLUSHED!\n",
ha->host_no, ha->aen_out,
mbox_sts[0], mbox_sts[2],
mbox_sts[3]));
break;
+ case PROCESS_ALL_AENS:
+ default:
+ /* Specific device. */
+ if (mbox_sts[1] == 1)
+ qla4xxx_process_ddb_changed(ha,
+ mbox_sts[2], mbox_sts[3],
+ mbox_sts[4]);
+ break;
}
- case PROCESS_ALL_AENS:
- default:
- if (mbox_sts[1] == 0) { /* Global DB change. */
- qla4xxx_reinitialize_ddb_list(ha);
- } else if (mbox_sts[1] == 1) { /* Specific device. */
- qla4xxx_process_ddb_changed(ha, mbox_sts[2],
- mbox_sts[3], mbox_sts[4]);
- }
- break;
}
spin_lock_irqsave(&ha->hardware_lock, flags);
}
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index fce8289..c259378 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -41,6 +41,16 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
return status;
}
+ if (is_qla40XX(ha)) {
+ if (test_bit(AF_HA_REMOVAL, &ha->flags)) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
+ "prematurely completing mbx cmd as "
+ "adapter removal detected\n",
+ ha->host_no, __func__));
+ return status;
+ }
+ }
+
if (is_qla8022(ha)) {
if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
@@ -303,7 +313,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
return QLA_SUCCESS;
}
-static uint8_t
+uint8_t
qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
{
@@ -327,43 +337,69 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
static void
qla4xxx_update_local_ip(struct scsi_qla_host *ha,
- struct addr_ctrl_blk *init_fw_cb)
+ struct addr_ctrl_blk *init_fw_cb)
{
+ ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
+ ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
+ ha->ip_config.ipv4_addr_state =
+ le16_to_cpu(init_fw_cb->ipv4_addr_state);
+ ha->ip_config.eth_mtu_size =
+ le16_to_cpu(init_fw_cb->eth_mtu_size);
+ ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);
+
+ if (ha->acb_version == ACB_SUPPORTED) {
+ ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
+ ha->ip_config.ipv6_addl_options =
+ le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
+ }
+
/* Save IPv4 Address Info */
- memcpy(ha->ip_address, init_fw_cb->ipv4_addr,
- min(sizeof(ha->ip_address), sizeof(init_fw_cb->ipv4_addr)));
- memcpy(ha->subnet_mask, init_fw_cb->ipv4_subnet,
- min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->ipv4_subnet)));
- memcpy(ha->gateway, init_fw_cb->ipv4_gw_addr,
- min(sizeof(ha->gateway), sizeof(init_fw_cb->ipv4_gw_addr)));
+ memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
+ min(sizeof(ha->ip_config.ip_address),
+ sizeof(init_fw_cb->ipv4_addr)));
+ memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
+ min(sizeof(ha->ip_config.subnet_mask),
+ sizeof(init_fw_cb->ipv4_subnet)));
+ memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
+ min(sizeof(ha->ip_config.gateway),
+ sizeof(init_fw_cb->ipv4_gw_addr)));
+
+ ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);
if (is_ipv6_enabled(ha)) {
/* Save IPv6 Address */
- ha->ipv6_link_local_state = init_fw_cb->ipv6_lnk_lcl_addr_state;
- ha->ipv6_addr0_state = init_fw_cb->ipv6_addr0_state;
- ha->ipv6_addr1_state = init_fw_cb->ipv6_addr1_state;
- ha->ipv6_default_router_state = init_fw_cb->ipv6_dflt_rtr_state;
- ha->ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
- ha->ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
-
- memcpy(&ha->ipv6_link_local_addr.in6_u.u6_addr8[8],
- init_fw_cb->ipv6_if_id,
- min(sizeof(ha->ipv6_link_local_addr)/2,
- sizeof(init_fw_cb->ipv6_if_id)));
- memcpy(&ha->ipv6_addr0, init_fw_cb->ipv6_addr0,
- min(sizeof(ha->ipv6_addr0),
- sizeof(init_fw_cb->ipv6_addr0)));
- memcpy(&ha->ipv6_addr1, init_fw_cb->ipv6_addr1,
- min(sizeof(ha->ipv6_addr1),
- sizeof(init_fw_cb->ipv6_addr1)));
- memcpy(&ha->ipv6_default_router_addr,
- init_fw_cb->ipv6_dflt_rtr_addr,
- min(sizeof(ha->ipv6_default_router_addr),
- sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
+ ha->ip_config.ipv6_link_local_state =
+ le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state);
+ ha->ip_config.ipv6_addr0_state =
+ le16_to_cpu(init_fw_cb->ipv6_addr0_state);
+ ha->ip_config.ipv6_addr1_state =
+ le16_to_cpu(init_fw_cb->ipv6_addr1_state);
+ ha->ip_config.ipv6_default_router_state =
+ le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state);
+ ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
+ ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
+
+ memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
+ init_fw_cb->ipv6_if_id,
+ min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
+ sizeof(init_fw_cb->ipv6_if_id)));
+ memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
+ min(sizeof(ha->ip_config.ipv6_addr0),
+ sizeof(init_fw_cb->ipv6_addr0)));
+ memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
+ min(sizeof(ha->ip_config.ipv6_addr1),
+ sizeof(init_fw_cb->ipv6_addr1)));
+ memcpy(&ha->ip_config.ipv6_default_router_addr,
+ init_fw_cb->ipv6_dflt_rtr_addr,
+ min(sizeof(ha->ip_config.ipv6_default_router_addr),
+ sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
+ ha->ip_config.ipv6_vlan_tag =
+ be16_to_cpu(init_fw_cb->ipv6_vlan_tag);
+ ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);
}
}
-static uint8_t
+uint8_t
qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
uint32_t *mbox_cmd,
uint32_t *mbox_sts,
@@ -383,20 +419,14 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
/* Save some info in adapter structure. */
ha->acb_version = init_fw_cb->acb_version;
ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
- ha->tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
- ha->ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
- ha->ipv4_addr_state = le16_to_cpu(init_fw_cb->ipv4_addr_state);
ha->heartbeat_interval = init_fw_cb->hb_interval;
memcpy(ha->name_string, init_fw_cb->iscsi_name,
min(sizeof(ha->name_string),
sizeof(init_fw_cb->iscsi_name)));
+ ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout);
/*memcpy(ha->alias, init_fw_cb->Alias,
min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
- if (ha->acb_version == ACB_SUPPORTED) {
- ha->ipv6_options = init_fw_cb->ipv6_opts;
- ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
- }
qla4xxx_update_local_ip(ha, init_fw_cb);
return QLA_SUCCESS;
@@ -462,10 +492,11 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
- /* Set bit for "serialize task mgmt" all other bits need to be zero */
init_fw_cb->add_fw_options = 0;
init_fw_cb->add_fw_options |=
- __constant_cpu_to_le16(SERIALIZE_TASK_MGMT);
+ __constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
+ init_fw_cb->add_fw_options |=
+ __constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
!= QLA_SUCCESS) {
@@ -691,19 +722,38 @@ exit_get_fwddb:
return status;
}
+int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_OPEN;
+ mbox_cmd[1] = fw_ddb_index;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+ &mbox_sts[0]);
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
+ __func__, status, mbox_sts[0], mbox_sts[1]));
+ return status;
+}
+
/**
* qla4xxx_set_fwddb_entry - sets a ddb entry.
* @ha: Pointer to host adapter structure.
* @fw_ddb_index: Firmware's device database index
- * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL.
+ * @fw_ddb_entry_dma: dma address of ddb entry
+ * @mbx_sts: mailbox 0 to be returned or NULL
*
* This routine initializes or updates the adapter's device database
- * entry for the specified device. It also triggers a login for the
- * specified device. Therefore, it may also be used as a secondary
- * login routine when a NULL pointer is specified for the fw_ddb_entry.
+ * entry for the specified device.
**/
int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
- dma_addr_t fw_ddb_entry_dma)
+ dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -722,13 +772,41 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
mbox_cmd[4] = sizeof(struct dev_db_entry);
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
- &mbox_sts[0]);
+ &mbox_sts[0]);
+ if (mbx_sts)
+ *mbx_sts = mbox_sts[0];
DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
return status;
}
+int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry, int options)
+{
+ int status;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+ mbox_cmd[1] = ddb_entry->fw_ddb_index;
+ mbox_cmd[3] = options;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
+ "failed sts %04X %04X", __func__,
+ mbox_sts[0], mbox_sts[1]));
+ }
+
+ return status;
+}
+
/**
* qla4xxx_get_crash_record - retrieves crash record.
* @ha: Pointer to host adapter structure.
@@ -805,7 +883,6 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
uint32_t max_event_log_entries;
uint8_t i;
-
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_cmd));
@@ -1104,7 +1181,7 @@ exit_about_fw:
return status;
}
-static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
+static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
dma_addr_t dma_addr)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
@@ -1114,6 +1191,7 @@ static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
memset(&mbox_sts, 0, sizeof(mbox_sts));
mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
+ mbox_cmd[1] = options;
mbox_cmd[2] = LSDW(dma_addr);
mbox_cmd[3] = MSDW(dma_addr);
@@ -1126,8 +1204,10 @@ static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
return QLA_SUCCESS;
}
-static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
+int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,
+ uint32_t *mbx_sts)
{
+ int status;
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -1135,75 +1215,646 @@ static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
memset(&mbox_sts, 0, sizeof(mbox_sts));
mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
- mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
+ mbox_cmd[1] = ddb_index;
- if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
- *ddb_index = mbox_sts[2];
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
+ __func__, mbox_sts[0]));
+ }
+
+ *mbx_sts = mbox_sts[0];
+ return status;
+}
+
+int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)
+{
+ int status;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
+ mbox_cmd[1] = ddb_index;
+
+ status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
+ __func__, mbox_sts[0]));
+ }
+
+ return status;
+}
+
+int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+ uint32_t offset, uint32_t length, uint32_t options)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
+ mbox_cmd[1] = LSDW(dma_addr);
+ mbox_cmd[2] = MSDW(dma_addr);
+ mbox_cmd[3] = offset;
+ mbox_cmd[4] = length;
+ mbox_cmd[5] = options;
+
+ status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
+ "failed w/ status %04X, mbx1 %04X\n",
+ __func__, mbox_sts[0], mbox_sts[1]));
+ }
+ return status;
+}
+
+int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
+{
+ uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
+ uint32_t dev_db_end_offset;
+ int status = QLA_ERROR;
+
+ memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
+
+ dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
+ dev_db_end_offset = FLASH_OFFSET_DB_END;
+
+ if (dev_db_start_offset > dev_db_end_offset) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s:Invalid DDB index %d", __func__,
+ ddb_index));
+ goto exit_bootdb_failed;
+ }
+
+ if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
+ sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
+ "failed\n", ha->host_no, __func__);
+ goto exit_bootdb_failed;
+ }
+
+ if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
+ status = QLA_SUCCESS;
+
+exit_bootdb_failed:
+ return status;
+}
+
+int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
+ uint16_t idx)
+{
+ int ret = 0;
+ int rval = QLA_ERROR;
+ uint32_t offset = 0, chap_size;
+ struct ql4_chap_table *chap_table;
+ dma_addr_t chap_dma;
+
+ chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
+ if (chap_table == NULL) {
+ ret = -ENOMEM;
+ goto exit_get_chap;
+ }
+
+ chap_size = sizeof(struct ql4_chap_table);
+ memset(chap_table, 0, chap_size);
+
+ if (is_qla40XX(ha))
+ offset = FLASH_CHAP_OFFSET | (idx * chap_size);
+ else {
+ offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
+ /* flt_chap_size is CHAP table size for both ports
+ * so divide it by 2 to calculate the offset for second port
+ */
+ if (ha->port_num == 1)
+ offset += (ha->hw.flt_chap_size / 2);
+ offset += (idx * chap_size);
+ }
+
+ rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
+ if (rval != QLA_SUCCESS) {
+ ret = -EINVAL;
+ goto exit_get_chap;
+ }
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
+ __le16_to_cpu(chap_table->cookie)));
+
+ if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
+ ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
+ goto exit_get_chap;
+ }
+
+ strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
+
+exit_get_chap:
+ dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
+ return ret;
+}
+
+static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
+ char *password, uint16_t idx, int bidi)
+{
+ int ret = 0;
+ int rval = QLA_ERROR;
+ uint32_t offset = 0;
+ struct ql4_chap_table *chap_table;
+ dma_addr_t chap_dma;
+
+ chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
+ if (chap_table == NULL) {
+ ret = -ENOMEM;
+ goto exit_set_chap;
+ }
+
+ memset(chap_table, 0, sizeof(struct ql4_chap_table));
+ if (bidi)
+ chap_table->flags |= BIT_6; /* peer */
+ else
+ chap_table->flags |= BIT_7; /* local */
+ chap_table->secret_len = strlen(password);
+ strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
+ strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
+ chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
+ offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table));
+ rval = qla4xxx_set_flash(ha, chap_dma, offset,
+ sizeof(struct ql4_chap_table),
+ FLASH_OPT_RMW_COMMIT);
+
+ if (rval == QLA_SUCCESS && ha->chap_list) {
+ /* Update ha chap_list cache */
+ memcpy((struct ql4_chap_table *)ha->chap_list + idx,
+ chap_table, sizeof(struct ql4_chap_table));
+ }
+ dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
+ if (rval != QLA_SUCCESS)
+ ret = -EINVAL;
+
+exit_set_chap:
+ return ret;
+}
+
+/**
+ * qla4xxx_get_chap_index - Get chap index given username and secret
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be searched
+ * @password: CHAP password to be searched
+ * @bidi: Is this a BIDI CHAP
+ * @chap_index: CHAP index to be returned
+ *
+ * Match the username and password in the chap_list, return the index if a
+ * match is found. If a match is not found then add the entry in FLASH and
+ * return the index at which entry is written in the FLASH.
+ **/
+static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
+ char *password, int bidi, uint16_t *chap_index)
+{
+ int i, rval;
+ int free_index = -1;
+ int found_index = 0;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return QLA_ERROR;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
+ free_index = i;
+ continue;
+ }
+ if (bidi) {
+ if (chap_table->flags & BIT_7)
+ continue;
} else {
- DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
- ha->host_no, __func__, mbox_sts[0]));
- return QLA_ERROR;
+ if (chap_table->flags & BIT_6)
+ continue;
+ }
+ if (!strncmp(chap_table->secret, password,
+ MAX_CHAP_SECRET_LEN) &&
+ !strncmp(chap_table->name, username,
+ MAX_CHAP_NAME_LEN)) {
+ *chap_index = i;
+ found_index = 1;
+ break;
}
- } else {
- *ddb_index = MAX_PRST_DEV_DB_ENTRIES;
}
- return QLA_SUCCESS;
+ /* If chap entry is not present and a free index is available then
+ * write the entry in flash
+ */
+ if (!found_index && free_index != -1) {
+ rval = qla4xxx_set_chap(ha, username, password,
+ free_index, bidi);
+ if (!rval) {
+ *chap_index = free_index;
+ found_index = 1;
+ }
+ }
+
+ mutex_unlock(&ha->chap_sem);
+
+ if (found_index)
+ return QLA_SUCCESS;
+ return QLA_ERROR;
+}
+
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
+ uint16_t fw_ddb_index,
+ uint16_t connection_id,
+ uint16_t option)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+ mbox_cmd[1] = fw_ddb_index;
+ mbox_cmd[2] = connection_id;
+ mbox_cmd[3] = option;
+
+ status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
+ "option %04x failed w/ status %04X %04X\n",
+ __func__, option, mbox_sts[0], mbox_sts[1]));
+ }
+ return status;
}
+int qla4xxx_disable_acb(struct scsi_qla_host *ha)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
-int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
+
+ status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
+ "failed w/ status %04X %04X %04X", __func__,
+ mbox_sts[0], mbox_sts[1], mbox_sts[2]));
+ }
+ return status;
+}
+
+int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
+ uint32_t acb_type, uint32_t len)
{
- struct dev_db_entry *fw_ddb_entry;
- dma_addr_t fw_ddb_entry_dma;
- uint32_t ddb_index;
- int ret_val = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+ mbox_cmd[0] = MBOX_CMD_GET_ACB;
+ mbox_cmd[1] = acb_type;
+ mbox_cmd[2] = LSDW(acb_dma);
+ mbox_cmd[3] = MSDW(acb_dma);
+ mbox_cmd[4] = len;
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
+ status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
+ "failed w/ status %04X\n", __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ uint32_t *mbox_sts, dma_addr_t acb_dma)
+{
+ int status = QLA_SUCCESS;
+
+ memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
+ memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
+ mbox_cmd[0] = MBOX_CMD_SET_ACB;
+ mbox_cmd[1] = 0; /* Primary ACB */
+ mbox_cmd[2] = LSDW(acb_dma);
+ mbox_cmd[3] = MSDW(acb_dma);
+ mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
+
+ status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB "
+ "failed w/ status %04X\n", __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry,
+ struct iscsi_cls_conn *cls_conn,
+ uint32_t *mbx_sts)
+{
+ struct dev_db_entry *fw_ddb_entry;
+ struct iscsi_conn *conn;
+ struct iscsi_session *sess;
+ struct qla_conn *qla_conn;
+ struct sockaddr *dst_addr;
+ dma_addr_t fw_ddb_entry_dma;
+ int status = QLA_SUCCESS;
+ int rval = 0;
+ struct sockaddr_in *addr;
+ struct sockaddr_in6 *addr6;
+ char *ip;
+ uint16_t iscsi_opts = 0;
+ uint32_t options = 0;
+ uint16_t idx;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
&fw_ddb_entry_dma, GFP_KERNEL);
if (!fw_ddb_entry) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
- ret_val = QLA_ERROR;
- goto exit_send_tgts_no_free;
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer.\n",
+ __func__));
+ rval = -ENOMEM;
+ goto exit_set_param_no_free;
}
- ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma);
- if (ret_val != QLA_SUCCESS)
- goto exit_send_tgts;
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ sess = conn->session;
+ dst_addr = &qla_conn->qla_ep->dst_addr;
- ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index);
- if (ret_val != QLA_SUCCESS)
- goto exit_send_tgts;
+ if (dst_addr->sa_family == AF_INET6)
+ options |= IPV6_DEFAULT_DDB_ENTRY;
- memset(fw_ddb_entry->iscsi_alias, 0,
- sizeof(fw_ddb_entry->iscsi_alias));
+ status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
+ if (status == QLA_ERROR) {
+ rval = -EINVAL;
+ goto exit_set_param;
+ }
+
+ iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
+ memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
- memset(fw_ddb_entry->iscsi_name, 0,
- sizeof(fw_ddb_entry->iscsi_name));
+ memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));
+
+ if (sess->targetname != NULL) {
+ memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
+ min(strlen(sess->targetname),
+ sizeof(fw_ddb_entry->iscsi_name)));
+ }
memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
- memset(fw_ddb_entry->tgt_addr, 0,
- sizeof(fw_ddb_entry->tgt_addr));
+ memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));
+
+ fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;
+
+ if (dst_addr->sa_family == AF_INET) {
+ addr = (struct sockaddr_in *)dst_addr;
+ ip = (char *)&addr->sin_addr;
+ memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);
+ fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Destination Address [%pI4]: index [%d]\n",
+ __func__, fw_ddb_entry->ip_addr,
+ ddb_entry->fw_ddb_index));
+ } else if (dst_addr->sa_family == AF_INET6) {
+ addr6 = (struct sockaddr_in6 *)dst_addr;
+ ip = (char *)&addr6->sin6_addr;
+ memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);
+ fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));
+ fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Destination Address [%pI6]: index [%d]\n",
+ __func__, fw_ddb_entry->ip_addr,
+ ddb_entry->fw_ddb_index));
+ } else {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Failed to get IP Address\n",
+ __func__);
+ rval = -EINVAL;
+ goto exit_set_param;
+ }
+
+ /* CHAP */
+ if (sess->username != NULL && sess->password != NULL) {
+ if (strlen(sess->username) && strlen(sess->password)) {
+ iscsi_opts |= BIT_7;
+
+ rval = qla4xxx_get_chap_index(ha, sess->username,
+ sess->password,
+ LOCAL_CHAP, &idx);
+ if (rval)
+ goto exit_set_param;
+
+ fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);
+ }
+ }
+
+ if (sess->username_in != NULL && sess->password_in != NULL) {
+ /* Check if BIDI CHAP */
+ if (strlen(sess->username_in) && strlen(sess->password_in)) {
+ iscsi_opts |= BIT_4;
+
+ rval = qla4xxx_get_chap_index(ha, sess->username_in,
+ sess->password_in,
+ BIDI_CHAP, &idx);
+ if (rval)
+ goto exit_set_param;
+ }
+ }
+
+ if (sess->initial_r2t_en)
+ iscsi_opts |= BIT_10;
+
+ if (sess->imm_data_en)
+ iscsi_opts |= BIT_11;
+
+ fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);
+
+ if (conn->max_recv_dlength)
+ fw_ddb_entry->iscsi_max_rcv_data_seg_len =
+ __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
+
+ if (sess->max_r2t)
+ fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
+
+ if (sess->first_burst)
+ fw_ddb_entry->iscsi_first_burst_len =
+ __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS));
+
+ if (sess->max_burst)
+ fw_ddb_entry->iscsi_max_burst_len =
+ __constant_cpu_to_le16((sess->max_burst / BYTE_UNITS));
- fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
- fw_ddb_entry->port = cpu_to_le16(ntohs(port));
+ if (sess->time2wait)
+ fw_ddb_entry->iscsi_def_time2wait =
+ cpu_to_le16(sess->time2wait);
- fw_ddb_entry->ip_addr[0] = *ip;
- fw_ddb_entry->ip_addr[1] = *(ip + 1);
- fw_ddb_entry->ip_addr[2] = *(ip + 2);
- fw_ddb_entry->ip_addr[3] = *(ip + 3);
+ if (sess->time2retain)
+ fw_ddb_entry->iscsi_def_time2retain =
+ cpu_to_le16(sess->time2retain);
- ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
+ status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
+ fw_ddb_entry_dma, mbx_sts);
-exit_send_tgts:
+ if (status != QLA_SUCCESS)
+ rval = -EINVAL;
+exit_set_param:
dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
fw_ddb_entry, fw_ddb_entry_dma);
-exit_send_tgts_no_free:
- return ret_val;
+exit_set_param_no_free:
+ return rval;
}
+int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
+ uint16_t stats_size, dma_addr_t stats_dma)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
+ memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
+ mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;
+ mbox_cmd[1] = fw_ddb_index;
+ mbox_cmd[2] = LSDW(stats_dma);
+ mbox_cmd[3] = MSDW(stats_dma);
+ mbox_cmd[4] = stats_size;
+
+ status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "%s: MBOX_CMD_GET_MANAGEMENT_DATA "
+ "failed w/ status %04X\n", __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
+ uint32_t ip_idx, uint32_t *sts)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+ mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;
+ mbox_cmd[1] = acb_idx;
+ mbox_cmd[2] = ip_idx;
+
+ status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: "
+ "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
+ "status %04X\n", __func__, mbox_sts[0]));
+ }
+ memcpy(sts, mbox_sts, sizeof(mbox_sts));
+ return status;
+}
+
+int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_GET_NVRAM;
+ mbox_cmd[1] = LSDW(nvram_dma);
+ mbox_cmd[2] = MSDW(nvram_dma);
+ mbox_cmd[3] = offset;
+ mbox_cmd[4] = size;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "status %04X\n", ha->host_no, __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_SET_NVRAM;
+ mbox_cmd[1] = LSDW(nvram_dma);
+ mbox_cmd[2] = MSDW(nvram_dma);
+ mbox_cmd[3] = offset;
+ mbox_cmd[4] = size;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "status %04X\n", ha->host_no, __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
+ uint32_t region, uint32_t field0,
+ uint32_t field1)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;
+ mbox_cmd[3] = region;
+ mbox_cmd[4] = field0;
+ mbox_cmd[5] = field1;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "status %04X\n", ha->host_no, __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index b4b859b..7851f31 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -156,6 +156,27 @@ u16 rd_nvram_word(struct scsi_qla_host * ha, int offset)
return val;
}
+u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset)
+{
+ u16 val = 0;
+ u8 rval = 0;
+ int index = 0;
+
+ if (offset & 0x1)
+ index = (offset - 1) / 2;
+ else
+ index = offset / 2;
+
+ val = le16_to_cpu(rd_nvram_word(ha, index));
+
+ if (offset & 0x1)
+ rval = (u8)((val & 0xff00) >> 8);
+ else
+ rval = (u8)((val & 0x00ff));
+
+ return rval;
+}
+
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha)
{
int status = QLA_ERROR;
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index fdfe27b..f484ff4 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -2015,11 +2015,19 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
hw->flt_region_boot = start;
break;
case FLT_REG_FW_82:
+ case FLT_REG_FW_82_1:
hw->flt_region_fw = start;
break;
case FLT_REG_BOOTLOAD_82:
hw->flt_region_bootload = start;
break;
+ case FLT_REG_ISCSI_PARAM:
+ hw->flt_iscsi_param = start;
+ break;
+ case FLT_REG_ISCSI_CHAP:
+ hw->flt_region_chap = start;
+ hw->flt_chap_size = le32_to_cpu(region->size);
+ break;
}
}
goto done;
@@ -2032,6 +2040,9 @@ no_flash_data:
hw->flt_region_boot = FA_BOOT_CODE_ADDR_82;
hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82;
hw->flt_region_fw = FA_RISC_CODE_ADDR_82;
+ hw->flt_region_chap = FA_FLASH_ISCSI_CHAP;
+ hw->flt_chap_size = FA_FLASH_CHAP_SIZE;
+
done:
DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x "
"boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt,
@@ -2258,10 +2269,16 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
}
/* Save M.A.C. address & serial_number */
+ ha->port_num = sys_info->port_num;
memcpy(ha->my_mac, &sys_info->mac_addr[0],
min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr)));
memcpy(ha->serial_number, &sys_info->serial_number,
min(sizeof(ha->serial_number), sizeof(sys_info->serial_number)));
+ memcpy(ha->model_name, &sys_info->board_id_str,
+ min(sizeof(ha->model_name), sizeof(sys_info->board_id_str)));
+ ha->phy_port_cnt = sys_info->phys_port_cnt;
+ ha->phy_port_num = sys_info->port_num;
+ ha->iscsi_pci_func_cnt = sys_info->iscsi_pci_func_cnt;
DEBUG2(printk("scsi%ld: %s: "
"mac %02x:%02x:%02x:%02x:%02x:%02x "
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index f2364ec..4169c8b 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -6,6 +6,9 @@
*/
#include <linux/moduleparam.h>
#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/iscsi_boot_sysfs.h>
+#include <linux/inet.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
@@ -29,6 +32,13 @@ static struct kmem_cache *srb_cachep;
/*
* Module parameter information and variables
*/
+int ql4xdisablesysfsboot = 1;
+module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ql4xdisablesysfsboot,
+ "Set to disable exporting boot targets to sysfs\n"
+ " 0 - Export boot targets\n"
+ " 1 - Do not export boot targets (Default)");
+
int ql4xdontresethba = 0;
module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ql4xdontresethba,
@@ -61,8 +71,9 @@ static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
MODULE_PARM_DESC(ql4xsess_recovery_tmo,
"Target Session Recovery Timeout.\n"
- " Default: 30 sec.");
+ " Default: 120 sec.");
+static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
/*
* SCSI host template entry points
*/
@@ -71,18 +82,41 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
/*
* iSCSI template entry points
*/
-static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
- enum iscsi_tgt_dscvr type, uint32_t enable,
- struct sockaddr *dst_addr);
static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
enum iscsi_param param, char *buf);
-static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
- enum iscsi_param param, char *buf);
static int qla4xxx_host_get_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf);
-static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+static int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data,
+ uint32_t len);
+static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+ enum iscsi_param_type param_type,
+ int param, char *buf);
static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
-
+static struct iscsi_endpoint *qla4xxx_ep_connect(struct Scsi_Host *shost,
+ struct sockaddr *dst_addr,
+ int non_blocking);
+static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);
+static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep);
+static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,
+ enum iscsi_param param, char *buf);
+static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
+static struct iscsi_cls_conn *
+qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx);
+static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn,
+ uint64_t transport_fd, int is_leading);
+static void qla4xxx_conn_destroy(struct iscsi_cls_conn *conn);
+static struct iscsi_cls_session *
+qla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ uint16_t qdepth, uint32_t initial_cmdsn);
+static void qla4xxx_session_destroy(struct iscsi_cls_session *sess);
+static void qla4xxx_task_work(struct work_struct *wdata);
+static int qla4xxx_alloc_pdu(struct iscsi_task *, uint8_t);
+static int qla4xxx_task_xmit(struct iscsi_task *);
+static void qla4xxx_task_cleanup(struct iscsi_task *);
+static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session);
+static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ struct iscsi_stats *stats);
/*
* SCSI host template entry points
*/
@@ -94,7 +128,8 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
static int qla4xxx_slave_alloc(struct scsi_device *device);
static int qla4xxx_slave_configure(struct scsi_device *device);
static void qla4xxx_slave_destroy(struct scsi_device *sdev);
-static void qla4xxx_scan_start(struct Scsi_Host *shost);
+static mode_t ql4_attr_is_visible(int param_type, int param);
+static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
QLA82XX_LEGACY_INTR_CONFIG;
@@ -115,9 +150,6 @@ static struct scsi_host_template qla4xxx_driver_template = {
.slave_alloc = qla4xxx_slave_alloc,
.slave_destroy = qla4xxx_slave_destroy,
- .scan_finished = iscsi_scan_finished,
- .scan_start = qla4xxx_scan_start,
-
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
@@ -125,56 +157,394 @@ static struct scsi_host_template qla4xxx_driver_template = {
.max_sectors = 0xFFFF,
.shost_attrs = qla4xxx_host_attrs,
+ .host_reset = qla4xxx_host_reset,
+ .vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
};
static struct iscsi_transport qla4xxx_iscsi_transport = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
- .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
- CAP_DATA_PATH_OFFLOAD,
- .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_TARGET_ALIAS,
- .host_param_mask = ISCSI_HOST_HWADDRESS |
- ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME,
- .tgt_dscvr = qla4xxx_tgt_dscvr,
+ .caps = CAP_TEXT_NEGO |
+ CAP_DATA_PATH_OFFLOAD | CAP_HDRDGST |
+ CAP_DATADGST | CAP_LOGIN_OFFLOAD |
+ CAP_MULTI_R2T,
+ .attr_is_visible = ql4_attr_is_visible,
+ .create_session = qla4xxx_session_create,
+ .destroy_session = qla4xxx_session_destroy,
+ .start_conn = qla4xxx_conn_start,
+ .create_conn = qla4xxx_conn_create,
+ .bind_conn = qla4xxx_conn_bind,
+ .stop_conn = iscsi_conn_stop,
+ .destroy_conn = qla4xxx_conn_destroy,
+ .set_param = iscsi_set_param,
.get_conn_param = qla4xxx_conn_get_param,
- .get_session_param = qla4xxx_sess_get_param,
+ .get_session_param = iscsi_session_get_param,
+ .get_ep_param = qla4xxx_get_ep_param,
+ .ep_connect = qla4xxx_ep_connect,
+ .ep_poll = qla4xxx_ep_poll,
+ .ep_disconnect = qla4xxx_ep_disconnect,
+ .get_stats = qla4xxx_conn_get_stats,
+ .send_pdu = iscsi_conn_send_pdu,
+ .xmit_task = qla4xxx_task_xmit,
+ .cleanup_task = qla4xxx_task_cleanup,
+ .alloc_pdu = qla4xxx_alloc_pdu,
+
.get_host_param = qla4xxx_host_get_param,
- .session_recovery_timedout = qla4xxx_recovery_timedout,
+ .set_iface_param = qla4xxx_iface_set_param,
+ .get_iface_param = qla4xxx_get_iface_param,
+ .bsg_request = qla4xxx_bsg_request,
};
static struct scsi_transport_template *qla4xxx_scsi_transport;
-static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
+static mode_t ql4_attr_is_visible(int param_type, int param)
{
- struct iscsi_cls_session *session;
- struct ddb_entry *ddb_entry;
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_TARGET_ALIAS:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_IFACE_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_NET_PARAM:
+ switch (param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ case ISCSI_NET_PARAM_IPV4_GW:
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ case ISCSI_NET_PARAM_IPV6_ROUTER:
+ case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+ case ISCSI_NET_PARAM_VLAN_ID:
+ case ISCSI_NET_PARAM_VLAN_PRIORITY:
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ case ISCSI_NET_PARAM_MTU:
+ case ISCSI_NET_PARAM_PORT:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
- session = starget_to_session(scsi_target(sc->device));
- ddb_entry = session->dd_data;
+ return 0;
+}
- /* if we are not logged in then the LLD is going to clean up the cmd */
- if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
- return BLK_EH_RESET_TIMER;
- else
- return BLK_EH_NOT_HANDLED;
+static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+ enum iscsi_param_type param_type,
+ int param, char *buf)
+{
+ struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ int len = -ENOSYS;
+
+ if (param_type != ISCSI_NET_PARAM)
+ return -ENOSYS;
+
+ switch (param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask);
+ break;
+ case ISCSI_NET_PARAM_IPV4_GW:
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway);
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv4_options &
+ IPOPT_IPV4_PROTOCOL_ENABLE) ?
+ "enabled" : "disabled");
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_options &
+ IPV6_OPT_IPV6_PROTOCOL_ENABLE) ?
+ "enabled" : "disabled");
+ break;
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ?
+ "dhcp" : "static");
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ if (iface->iface_num == 0)
+ len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0);
+ if (iface->iface_num == 1)
+ len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1);
+ break;
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+ len = sprintf(buf, "%pI6\n",
+ &ha->ip_config.ipv6_link_local_addr);
+ break;
+ case ISCSI_NET_PARAM_IPV6_ROUTER:
+ len = sprintf(buf, "%pI6\n",
+ &ha->ip_config.ipv6_default_router_addr);
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_addl_options &
+ IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ?
+ "nd" : "static");
+ break;
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_addl_options &
+ IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ?
+ "auto" : "static");
+ break;
+ case ISCSI_NET_PARAM_VLAN_ID:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%d\n",
+ (ha->ip_config.ipv4_vlan_tag &
+ ISCSI_MAX_VLAN_ID));
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%d\n",
+ (ha->ip_config.ipv6_vlan_tag &
+ ISCSI_MAX_VLAN_ID));
+ break;
+ case ISCSI_NET_PARAM_VLAN_PRIORITY:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%d\n",
+ ((ha->ip_config.ipv4_vlan_tag >> 13) &
+ ISCSI_MAX_VLAN_PRIORITY));
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%d\n",
+ ((ha->ip_config.ipv6_vlan_tag >> 13) &
+ ISCSI_MAX_VLAN_PRIORITY));
+ break;
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv4_options &
+ IPOPT_VLAN_TAGGING_ENABLE) ?
+ "enabled" : "disabled");
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_options &
+ IPV6_OPT_VLAN_TAGGING_ENABLE) ?
+ "enabled" : "disabled");
+ break;
+ case ISCSI_NET_PARAM_MTU:
+ len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size);
+ break;
+ case ISCSI_NET_PARAM_PORT:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%d\n", ha->ip_config.ipv4_port);
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%d\n", ha->ip_config.ipv6_port);
+ break;
+ default:
+ len = -ENOSYS;
+ }
+
+ return len;
}
-static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
+static struct iscsi_endpoint *
+qla4xxx_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+ int non_blocking)
{
- struct ddb_entry *ddb_entry = session->dd_data;
- struct scsi_qla_host *ha = ddb_entry->ha;
+ int ret;
+ struct iscsi_endpoint *ep;
+ struct qla_endpoint *qla_ep;
+ struct scsi_qla_host *ha;
+ struct sockaddr_in *addr;
+ struct sockaddr_in6 *addr6;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ if (!shost) {
+ ret = -ENXIO;
+ printk(KERN_ERR "%s: shost is NULL\n",
+ __func__);
+ return ERR_PTR(ret);
+ }
+
+ ha = iscsi_host_priv(shost);
- if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
- atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+ ep = iscsi_create_endpoint(sizeof(struct qla_endpoint));
+ if (!ep) {
+ ret = -ENOMEM;
+ return ERR_PTR(ret);
+ }
- DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
- "of (%d) secs exhausted, marking device DEAD.\n",
- ha->host_no, __func__, ddb_entry->fw_ddb_index,
- ddb_entry->sess->recovery_tmo));
+ qla_ep = ep->dd_data;
+ memset(qla_ep, 0, sizeof(struct qla_endpoint));
+ if (dst_addr->sa_family == AF_INET) {
+ memcpy(&qla_ep->dst_addr, dst_addr, sizeof(struct sockaddr_in));
+ addr = (struct sockaddr_in *)&qla_ep->dst_addr;
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI4\n", __func__,
+ (char *)&addr->sin_addr));
+ } else if (dst_addr->sa_family == AF_INET6) {
+ memcpy(&qla_ep->dst_addr, dst_addr,
+ sizeof(struct sockaddr_in6));
+ addr6 = (struct sockaddr_in6 *)&qla_ep->dst_addr;
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI6\n", __func__,
+ (char *)&addr6->sin6_addr));
}
+
+ qla_ep->host = shost;
+
+ return ep;
+}
+
+static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+ struct qla_endpoint *qla_ep;
+ struct scsi_qla_host *ha;
+ int ret = 0;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ qla_ep = ep->dd_data;
+ ha = to_qla_host(qla_ep->host);
+
+ if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags))
+ ret = 1;
+
+ return ret;
+}
+
+static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep)
+{
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ iscsi_destroy_endpoint(ep);
+}
+
+static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,
+ enum iscsi_param param,
+ char *buf)
+{
+ struct qla_endpoint *qla_ep = ep->dd_data;
+ struct sockaddr *dst_addr;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+
+ switch (param) {
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ if (!qla_ep)
+ return -ENOTCONN;
+
+ dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
+ if (!dst_addr)
+ return -ENOTCONN;
+
+ return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+ &qla_ep->dst_addr, param, buf);
+ default:
+ return -ENOSYS;
+ }
+}
+
+static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ struct iscsi_stats *stats)
+{
+ struct iscsi_session *sess;
+ struct iscsi_cls_session *cls_sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ struct ql_iscsi_stats *ql_iscsi_stats;
+ int stats_size;
+ int ret;
+ dma_addr_t iscsi_stats_dma;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+
+ cls_sess = iscsi_conn_to_session(cls_conn);
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats));
+ /* Allocate memory */
+ ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size,
+ &iscsi_stats_dma, GFP_KERNEL);
+ if (!ql_iscsi_stats) {
+ ql4_printk(KERN_ERR, ha,
+ "Unable to allocate memory for iscsi stats\n");
+ goto exit_get_stats;
+ }
+
+ ret = qla4xxx_get_mgmt_data(ha, ddb_entry->fw_ddb_index, stats_size,
+ iscsi_stats_dma);
+ if (ret != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha,
+ "Unable to retreive iscsi stats\n");
+ goto free_stats;
+ }
+
+ /* octets */
+ stats->txdata_octets = le64_to_cpu(ql_iscsi_stats->tx_data_octets);
+ stats->rxdata_octets = le64_to_cpu(ql_iscsi_stats->rx_data_octets);
+ /* xmit pdus */
+ stats->noptx_pdus = le32_to_cpu(ql_iscsi_stats->tx_nopout_pdus);
+ stats->scsicmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_cmd_pdus);
+ stats->tmfcmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_tmf_cmd_pdus);
+ stats->login_pdus = le32_to_cpu(ql_iscsi_stats->tx_login_cmd_pdus);
+ stats->text_pdus = le32_to_cpu(ql_iscsi_stats->tx_text_cmd_pdus);
+ stats->dataout_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_write_pdus);
+ stats->logout_pdus = le32_to_cpu(ql_iscsi_stats->tx_logout_cmd_pdus);
+ stats->snack_pdus = le32_to_cpu(ql_iscsi_stats->tx_snack_req_pdus);
+ /* recv pdus */
+ stats->noprx_pdus = le32_to_cpu(ql_iscsi_stats->rx_nopin_pdus);
+ stats->scsirsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_resp_pdus);
+ stats->tmfrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_tmf_resp_pdus);
+ stats->textrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_text_resp_pdus);
+ stats->datain_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_read_pdus);
+ stats->logoutrsp_pdus =
+ le32_to_cpu(ql_iscsi_stats->rx_logout_resp_pdus);
+ stats->r2t_pdus = le32_to_cpu(ql_iscsi_stats->rx_r2t_pdus);
+ stats->async_pdus = le32_to_cpu(ql_iscsi_stats->rx_async_pdus);
+ stats->rjt_pdus = le32_to_cpu(ql_iscsi_stats->rx_reject_pdus);
+
+free_stats:
+ dma_free_coherent(&ha->pdev->dev, stats_size, ql_iscsi_stats,
+ iscsi_stats_dma);
+exit_get_stats:
+ return;
+}
+
+static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
+{
+ struct iscsi_cls_session *session;
+ struct iscsi_session *sess;
+ unsigned long flags;
+ enum blk_eh_timer_return ret = BLK_EH_NOT_HANDLED;
+
+ session = starget_to_session(scsi_target(sc->device));
+ sess = session->dd_data;
+
+ spin_lock_irqsave(&session->lock, flags);
+ if (session->state == ISCSI_SESSION_FAILED)
+ ret = BLK_EH_RESET_TIMER;
+ spin_unlock_irqrestore(&session->lock, flags);
+
+ return ret;
}
static int qla4xxx_host_get_param(struct Scsi_Host *shost,
@@ -188,9 +558,7 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);
break;
case ISCSI_HOST_PARAM_IPADDRESS:
- len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
- ha->ip_address[1], ha->ip_address[2],
- ha->ip_address[3]);
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
break;
case ISCSI_HOST_PARAM_INITIATOR_NAME:
len = sprintf(buf, "%s\n", ha->name_string);
@@ -202,154 +570,1094 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
return len;
}
-static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
- enum iscsi_param param, char *buf)
+static void qla4xxx_create_ipv4_iface(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry = sess->dd_data;
- int len;
+ if (ha->iface_ipv4)
+ return;
- switch (param) {
- case ISCSI_PARAM_TARGET_NAME:
- len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
- ddb_entry->iscsi_name);
+ /* IPv4 */
+ ha->iface_ipv4 = iscsi_create_iface(ha->host,
+ &qla4xxx_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV4, 0, 0);
+ if (!ha->iface_ipv4)
+ ql4_printk(KERN_ERR, ha, "Could not create IPv4 iSCSI "
+ "iface0.\n");
+}
+
+static void qla4xxx_create_ipv6_iface(struct scsi_qla_host *ha)
+{
+ if (!ha->iface_ipv6_0)
+ /* IPv6 iface-0 */
+ ha->iface_ipv6_0 = iscsi_create_iface(ha->host,
+ &qla4xxx_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV6, 0,
+ 0);
+ if (!ha->iface_ipv6_0)
+ ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "
+ "iface0.\n");
+
+ if (!ha->iface_ipv6_1)
+ /* IPv6 iface-1 */
+ ha->iface_ipv6_1 = iscsi_create_iface(ha->host,
+ &qla4xxx_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV6, 1,
+ 0);
+ if (!ha->iface_ipv6_1)
+ ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "
+ "iface1.\n");
+}
+
+static void qla4xxx_create_ifaces(struct scsi_qla_host *ha)
+{
+ if (ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE)
+ qla4xxx_create_ipv4_iface(ha);
+
+ if (ha->ip_config.ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE)
+ qla4xxx_create_ipv6_iface(ha);
+}
+
+static void qla4xxx_destroy_ipv4_iface(struct scsi_qla_host *ha)
+{
+ if (ha->iface_ipv4) {
+ iscsi_destroy_iface(ha->iface_ipv4);
+ ha->iface_ipv4 = NULL;
+ }
+}
+
+static void qla4xxx_destroy_ipv6_iface(struct scsi_qla_host *ha)
+{
+ if (ha->iface_ipv6_0) {
+ iscsi_destroy_iface(ha->iface_ipv6_0);
+ ha->iface_ipv6_0 = NULL;
+ }
+ if (ha->iface_ipv6_1) {
+ iscsi_destroy_iface(ha->iface_ipv6_1);
+ ha->iface_ipv6_1 = NULL;
+ }
+}
+
+static void qla4xxx_destroy_ifaces(struct scsi_qla_host *ha)
+{
+ qla4xxx_destroy_ipv4_iface(ha);
+ qla4xxx_destroy_ipv6_iface(ha);
+}
+
+static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
+ struct iscsi_iface_param_info *iface_param,
+ struct addr_ctrl_blk *init_fw_cb)
+{
+ /*
+ * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.
+ * iface_num 1 is valid only for IPv6 Addr.
+ */
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ if (iface_param->iface_num & 0x1)
+ /* IPv6 Addr 1 */
+ memcpy(init_fw_cb->ipv6_addr1, iface_param->value,
+ sizeof(init_fw_cb->ipv6_addr1));
+ else
+ /* IPv6 Addr 0 */
+ memcpy(init_fw_cb->ipv6_addr0, iface_param->value,
+ sizeof(init_fw_cb->ipv6_addr0));
break;
- case ISCSI_PARAM_TPGT:
- len = sprintf(buf, "%u\n", ddb_entry->tpgt);
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+ if (iface_param->iface_num & 0x1)
+ break;
+ memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8],
+ sizeof(init_fw_cb->ipv6_if_id));
break;
- case ISCSI_PARAM_TARGET_ALIAS:
- len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
- ddb_entry->iscsi_alias);
+ case ISCSI_NET_PARAM_IPV6_ROUTER:
+ if (iface_param->iface_num & 0x1)
+ break;
+ memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value,
+ sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)
+ init_fw_cb->ipv6_addtl_opts &=
+ cpu_to_le16(
+ ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
+ else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)
+ init_fw_cb->ipv6_addtl_opts |=
+ cpu_to_le16(
+ IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
+ else
+ ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
+ "IPv6 addr\n");
+ break;
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ if (iface_param->value[0] ==
+ ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)
+ init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(
+ IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
+ else if (iface_param->value[0] ==
+ ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)
+ init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(
+ ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
+ else
+ ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
+ "IPv6 linklocal addr\n");
+ break;
+ case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)
+ memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,
+ sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {
+ init_fw_cb->ipv6_opts |=
+ cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);
+ qla4xxx_create_ipv6_iface(ha);
+ } else {
+ init_fw_cb->ipv6_opts &=
+ cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &
+ 0xFFFF);
+ qla4xxx_destroy_ipv6_iface(ha);
+ }
+ break;
+ case ISCSI_NET_PARAM_VLAN_TAG:
+ if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
+ break;
+ init_fw_cb->ipv6_vlan_tag =
+ cpu_to_be16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ if (iface_param->value[0] == ISCSI_VLAN_ENABLE)
+ init_fw_cb->ipv6_opts |=
+ cpu_to_le16(IPV6_OPT_VLAN_TAGGING_ENABLE);
+ else
+ init_fw_cb->ipv6_opts &=
+ cpu_to_le16(~IPV6_OPT_VLAN_TAGGING_ENABLE);
+ break;
+ case ISCSI_NET_PARAM_MTU:
+ init_fw_cb->eth_mtu_size =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_PORT:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ init_fw_cb->ipv6_port =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
break;
default:
- return -ENOSYS;
+ ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",
+ iface_param->param);
+ break;
}
+}
- return len;
+static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
+ struct iscsi_iface_param_info *iface_param,
+ struct addr_ctrl_blk *init_fw_cb)
+{
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ memcpy(init_fw_cb->ipv4_addr, iface_param->value,
+ sizeof(init_fw_cb->ipv4_addr));
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ memcpy(init_fw_cb->ipv4_subnet, iface_param->value,
+ sizeof(init_fw_cb->ipv4_subnet));
+ break;
+ case ISCSI_NET_PARAM_IPV4_GW:
+ memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value,
+ sizeof(init_fw_cb->ipv4_gw_addr));
+ break;
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
+ init_fw_cb->ipv4_tcp_opts |=
+ cpu_to_le16(TCPOPT_DHCP_ENABLE);
+ else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
+ init_fw_cb->ipv4_tcp_opts &=
+ cpu_to_le16(~TCPOPT_DHCP_ENABLE);
+ else
+ ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {
+ init_fw_cb->ipv4_ip_opts |=
+ cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE);
+ qla4xxx_create_ipv4_iface(ha);
+ } else {
+ init_fw_cb->ipv4_ip_opts &=
+ cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE &
+ 0xFFFF);
+ qla4xxx_destroy_ipv4_iface(ha);
+ }
+ break;
+ case ISCSI_NET_PARAM_VLAN_TAG:
+ if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
+ break;
+ init_fw_cb->ipv4_vlan_tag =
+ cpu_to_be16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ if (iface_param->value[0] == ISCSI_VLAN_ENABLE)
+ init_fw_cb->ipv4_ip_opts |=
+ cpu_to_le16(IPOPT_VLAN_TAGGING_ENABLE);
+ else
+ init_fw_cb->ipv4_ip_opts &=
+ cpu_to_le16(~IPOPT_VLAN_TAGGING_ENABLE);
+ break;
+ case ISCSI_NET_PARAM_MTU:
+ init_fw_cb->eth_mtu_size =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_PORT:
+ init_fw_cb->ipv4_port =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",
+ iface_param->param);
+ break;
+ }
}
-static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+static void
+qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
+{
+ struct addr_ctrl_blk_def *acb;
+ acb = (struct addr_ctrl_blk_def *)init_fw_cb;
+ memset(acb->reserved1, 0, sizeof(acb->reserved1));
+ memset(acb->reserved2, 0, sizeof(acb->reserved2));
+ memset(acb->reserved3, 0, sizeof(acb->reserved3));
+ memset(acb->reserved4, 0, sizeof(acb->reserved4));
+ memset(acb->reserved5, 0, sizeof(acb->reserved5));
+ memset(acb->reserved6, 0, sizeof(acb->reserved6));
+ memset(acb->reserved7, 0, sizeof(acb->reserved7));
+ memset(acb->reserved8, 0, sizeof(acb->reserved8));
+ memset(acb->reserved9, 0, sizeof(acb->reserved9));
+ memset(acb->reserved10, 0, sizeof(acb->reserved10));
+ memset(acb->reserved11, 0, sizeof(acb->reserved11));
+ memset(acb->reserved12, 0, sizeof(acb->reserved12));
+ memset(acb->reserved13, 0, sizeof(acb->reserved13));
+ memset(acb->reserved14, 0, sizeof(acb->reserved14));
+ memset(acb->reserved15, 0, sizeof(acb->reserved15));
+}
+
+static int
+qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
+{
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ int rval = 0;
+ struct iscsi_iface_param_info *iface_param = NULL;
+ struct addr_ctrl_blk *init_fw_cb = NULL;
+ dma_addr_t init_fw_cb_dma;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ uint32_t rem = len;
+ struct nlattr *attr;
+
+ init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk),
+ &init_fw_cb_dma, GFP_KERNEL);
+ if (!init_fw_cb) {
+ ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {
+ ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);
+ rval = -EIO;
+ goto exit_init_fw_cb;
+ }
+
+ nla_for_each_attr(attr, data, len, rem) {
+ iface_param = nla_data(attr);
+
+ if (iface_param->param_type != ISCSI_NET_PARAM)
+ continue;
+
+ switch (iface_param->iface_type) {
+ case ISCSI_IFACE_TYPE_IPV4:
+ switch (iface_param->iface_num) {
+ case 0:
+ qla4xxx_set_ipv4(ha, iface_param, init_fw_cb);
+ break;
+ default:
+ /* Cannot have more than one IPv4 interface */
+ ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface "
+ "number = %d\n",
+ iface_param->iface_num);
+ break;
+ }
+ break;
+ case ISCSI_IFACE_TYPE_IPV6:
+ switch (iface_param->iface_num) {
+ case 0:
+ case 1:
+ qla4xxx_set_ipv6(ha, iface_param, init_fw_cb);
+ break;
+ default:
+ /* Cannot have more than two IPv6 interface */
+ ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface "
+ "number = %d\n",
+ iface_param->iface_num);
+ break;
+ }
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
+ break;
+ }
+ }
+
+ init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
+
+ rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,
+ sizeof(struct addr_ctrl_blk),
+ FLASH_OPT_RMW_COMMIT);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",
+ __func__);
+ rval = -EIO;
+ goto exit_init_fw_cb;
+ }
+
+ qla4xxx_disable_acb(ha);
+
+ qla4xxx_initcb_to_acb(init_fw_cb);
+
+ rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",
+ __func__);
+ rval = -EIO;
+ goto exit_init_fw_cb;
+ }
+
+ memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
+ qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,
+ init_fw_cb_dma);
+
+exit_init_fw_cb:
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
+ init_fw_cb, init_fw_cb_dma);
+
+ return rval;
+}
+
+static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,
enum iscsi_param param, char *buf)
{
- struct iscsi_cls_session *session;
- struct ddb_entry *ddb_entry;
- int len;
+ struct iscsi_conn *conn;
+ struct qla_conn *qla_conn;
+ struct sockaddr *dst_addr;
+ int len = 0;
- session = iscsi_dev_to_session(conn->dev.parent);
- ddb_entry = session->dd_data;
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ dst_addr = &qla_conn->qla_ep->dst_addr;
switch (param) {
case ISCSI_PARAM_CONN_PORT:
- len = sprintf(buf, "%hu\n", ddb_entry->port);
- break;
case ISCSI_PARAM_CONN_ADDRESS:
- /* TODO: what are the ipv6 bits */
- len = sprintf(buf, "%pI4\n", &ddb_entry->ip_addr);
- break;
+ return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+ dst_addr, param, buf);
default:
- return -ENOSYS;
+ return iscsi_conn_get_param(cls_conn, param, buf);
}
return len;
+
+}
+
+int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index)
+{
+ uint32_t mbx_sts = 0;
+ uint16_t tmp_ddb_index;
+ int ret;
+
+get_ddb_index:
+ tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
+
+ if (tmp_ddb_index >= MAX_DDB_ENTRIES) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Free DDB index not available\n"));
+ ret = QLA_ERROR;
+ goto exit_get_ddb_index;
+ }
+
+ if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map))
+ goto get_ddb_index;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Found a free DDB index at %d\n", tmp_ddb_index));
+ ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts);
+ if (ret == QLA_ERROR) {
+ if (mbx_sts == MBOX_STS_COMMAND_ERROR) {
+ ql4_printk(KERN_INFO, ha,
+ "DDB index = %d not available trying next\n",
+ tmp_ddb_index);
+ goto get_ddb_index;
+ }
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Free FW DDB not available\n"));
+ }
+
+ *ddb_index = tmp_ddb_index;
+
+exit_get_ddb_index:
+ return ret;
+}
+
+static int qla4xxx_match_ipaddress(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry,
+ char *existing_ipaddr,
+ char *user_ipaddr)
+{
+ uint8_t dst_ipaddr[IPv6_ADDR_LEN];
+ char formatted_ipaddr[DDB_IPADDR_LEN];
+ int status = QLA_SUCCESS, ret = 0;
+
+ if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) {
+ ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,
+ '\0', NULL);
+ if (ret == 0) {
+ status = QLA_ERROR;
+ goto out_match;
+ }
+ ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr);
+ } else {
+ ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,
+ '\0', NULL);
+ if (ret == 0) {
+ status = QLA_ERROR;
+ goto out_match;
+ }
+ ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr);
+ }
+
+ if (strcmp(existing_ipaddr, formatted_ipaddr))
+ status = QLA_ERROR;
+
+out_match:
+ return status;
}
-static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
- enum iscsi_tgt_dscvr type, uint32_t enable,
- struct sockaddr *dst_addr)
+static int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha,
+ struct iscsi_cls_conn *cls_conn)
{
+ int idx = 0, max_ddbs, rval;
+ struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
+ struct iscsi_session *sess, *existing_sess;
+ struct iscsi_conn *conn, *existing_conn;
+ struct ddb_entry *ddb_entry;
+
+ sess = cls_sess->dd_data;
+ conn = cls_conn->dd_data;
+
+ if (sess->targetname == NULL ||
+ conn->persistent_address == NULL ||
+ conn->persistent_port == 0)
+ return QLA_ERROR;
+
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
+
+ for (idx = 0; idx < max_ddbs; idx++) {
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
+ if (ddb_entry == NULL)
+ continue;
+
+ if (ddb_entry->ddb_type != FLASH_DDB)
+ continue;
+
+ existing_sess = ddb_entry->sess->dd_data;
+ existing_conn = ddb_entry->conn->dd_data;
+
+ if (existing_sess->targetname == NULL ||
+ existing_conn->persistent_address == NULL ||
+ existing_conn->persistent_port == 0)
+ continue;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "IQN = %s User IQN = %s\n",
+ existing_sess->targetname,
+ sess->targetname));
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "IP = %s User IP = %s\n",
+ existing_conn->persistent_address,
+ conn->persistent_address));
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Port = %d User Port = %d\n",
+ existing_conn->persistent_port,
+ conn->persistent_port));
+
+ if (strcmp(existing_sess->targetname, sess->targetname))
+ continue;
+ rval = qla4xxx_match_ipaddress(ha, ddb_entry,
+ existing_conn->persistent_address,
+ conn->persistent_address);
+ if (rval == QLA_ERROR)
+ continue;
+ if (existing_conn->persistent_port != conn->persistent_port)
+ continue;
+ break;
+ }
+
+ if (idx == max_ddbs)
+ return QLA_ERROR;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Match found in fwdb sessions\n"));
+ return QLA_SUCCESS;
+}
+
+static struct iscsi_cls_session *
+qla4xxx_session_create(struct iscsi_endpoint *ep,
+ uint16_t cmds_max, uint16_t qdepth,
+ uint32_t initial_cmdsn)
+{
+ struct iscsi_cls_session *cls_sess;
struct scsi_qla_host *ha;
- struct sockaddr_in *addr;
- struct sockaddr_in6 *addr6;
+ struct qla_endpoint *qla_ep;
+ struct ddb_entry *ddb_entry;
+ uint16_t ddb_index;
+ struct iscsi_session *sess;
+ struct sockaddr *dst_addr;
+ int ret;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ if (!ep) {
+ printk(KERN_ERR "qla4xxx: missing ep.\n");
+ return NULL;
+ }
+
+ qla_ep = ep->dd_data;
+ dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
+ ha = to_qla_host(qla_ep->host);
+
+ ret = qla4xxx_get_ddb_index(ha, &ddb_index);
+ if (ret == QLA_ERROR)
+ return NULL;
+
+ cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host,
+ cmds_max, sizeof(struct ddb_entry),
+ sizeof(struct ql4_task_data),
+ initial_cmdsn, ddb_index);
+ if (!cls_sess)
+ return NULL;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->fw_ddb_index = ddb_index;
+ ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
+ ddb_entry->ha = ha;
+ ddb_entry->sess = cls_sess;
+ ddb_entry->unblock_sess = qla4xxx_unblock_ddb;
+ ddb_entry->ddb_change = qla4xxx_ddb_change;
+ cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
+ ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
+ ha->tot_ddbs++;
+
+ return cls_sess;
+}
+
+static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ unsigned long flags;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ qla4xxx_free_ddb(ha, ddb_entry);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ iscsi_session_teardown(cls_sess);
+}
+
+static struct iscsi_cls_conn *
+qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx)
+{
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn),
+ conn_idx);
+ if (!cls_conn)
+ return NULL;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->conn = cls_conn;
+
+ return cls_conn;
+}
+
+static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn,
+ uint64_t transport_fd, int is_leading)
+{
+ struct iscsi_conn *conn;
+ struct qla_conn *qla_conn;
+ struct iscsi_endpoint *ep;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+
+ if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+ return -EINVAL;
+ ep = iscsi_lookup_endpoint(transport_fd);
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ qla_conn->qla_ep = ep->dd_data;
+ return 0;
+}
+
+static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
+{
+ struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ uint32_t mbx_sts = 0;
int ret = 0;
+ int status = QLA_SUCCESS;
- ha = (struct scsi_qla_host *) shost->hostdata;
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
- switch (type) {
- case ISCSI_TGT_DSCVR_SEND_TARGETS:
- if (dst_addr->sa_family == AF_INET) {
- addr = (struct sockaddr_in *)dst_addr;
- if (qla4xxx_send_tgts(ha, (char *)&addr->sin_addr,
- addr->sin_port) != QLA_SUCCESS)
- ret = -EIO;
- } else if (dst_addr->sa_family == AF_INET6) {
- /*
- * TODO: fix qla4xxx_send_tgts
- */
- addr6 = (struct sockaddr_in6 *)dst_addr;
- if (qla4xxx_send_tgts(ha, (char *)&addr6->sin6_addr,
- addr6->sin6_port) != QLA_SUCCESS)
- ret = -EIO;
- } else
- ret = -ENOSYS;
- break;
- default:
- ret = -ENOSYS;
+ /* Check if we have matching FW DDB, if yes then do not
+ * login to this target. This could cause target to logout previous
+ * connection
+ */
+ ret = qla4xxx_match_fwdb_session(ha, cls_conn);
+ if (ret == QLA_SUCCESS) {
+ ql4_printk(KERN_INFO, ha,
+ "Session already exist in FW.\n");
+ ret = -EEXIST;
+ goto exit_conn_start;
+ }
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ ret = -ENOMEM;
+ goto exit_conn_start;
}
+
+ ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts);
+ if (ret) {
+ /* If iscsid is stopped and started then no need to do
+ * set param again since ddb state will be already
+ * active and FW does not allow set ddb to an
+ * active session.
+ */
+ if (mbx_sts)
+ if (ddb_entry->fw_ddb_device_state ==
+ DDB_DS_SESSION_ACTIVE) {
+ ddb_entry->unblock_sess(ddb_entry->sess);
+ goto exit_set_param;
+ }
+
+ ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n",
+ __func__, ddb_entry->fw_ddb_index);
+ goto exit_conn_start;
+ }
+
+ status = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);
+ if (status == QLA_ERROR) {
+ ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,
+ sess->targetname);
+ ret = -EINVAL;
+ goto exit_conn_start;
+ }
+
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE)
+ ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+
+ DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state));
+
+exit_set_param:
+ ret = 0;
+
+exit_conn_start:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
return ret;
}
-void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
+static void qla4xxx_conn_destroy(struct iscsi_cls_conn *cls_conn)
{
- if (!ddb_entry->sess)
- return;
+ struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
+ struct iscsi_session *sess;
+ struct scsi_qla_host *ha;
+ struct ddb_entry *ddb_entry;
+ int options;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
- if (ddb_entry->conn) {
- atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
- iscsi_remove_session(ddb_entry->sess);
+ options = LOGOUT_OPTION_CLOSE_SESSION;
+ if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR)
+ ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);
+}
+
+static void qla4xxx_task_work(struct work_struct *wdata)
+{
+ struct ql4_task_data *task_data;
+ struct scsi_qla_host *ha;
+ struct passthru_status *sts;
+ struct iscsi_task *task;
+ struct iscsi_hdr *hdr;
+ uint8_t *data;
+ uint32_t data_len;
+ struct iscsi_conn *conn;
+ int hdr_len;
+ itt_t itt;
+
+ task_data = container_of(wdata, struct ql4_task_data, task_work);
+ ha = task_data->ha;
+ task = task_data->task;
+ sts = &task_data->sts;
+ hdr_len = sizeof(struct iscsi_hdr);
+
+ DEBUG3(printk(KERN_INFO "Status returned\n"));
+ DEBUG3(qla4xxx_dump_buffer(sts, 64));
+ DEBUG3(printk(KERN_INFO "Response buffer"));
+ DEBUG3(qla4xxx_dump_buffer(task_data->resp_buffer, 64));
+
+ conn = task->conn;
+
+ switch (sts->completionStatus) {
+ case PASSTHRU_STATUS_COMPLETE:
+ hdr = (struct iscsi_hdr *)task_data->resp_buffer;
+ /* Assign back the itt in hdr, until we use the PREASSIGN_TAG */
+ itt = sts->handle;
+ hdr->itt = itt;
+ data = task_data->resp_buffer + hdr_len;
+ data_len = task_data->resp_len - hdr_len;
+ iscsi_complete_pdu(conn, hdr, data, data_len);
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha, "Passthru failed status = 0x%x\n",
+ sts->completionStatus);
+ break;
}
- iscsi_free_session(ddb_entry->sess);
+ return;
}
-int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+static int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
{
- int err;
+ struct ql4_task_data *task_data;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ int hdr_len;
- ddb_entry->sess->recovery_tmo = ql4xsess_recovery_tmo;
+ sess = task->conn->session;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+ task_data = task->dd_data;
+ memset(task_data, 0, sizeof(struct ql4_task_data));
- err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
- if (err) {
- DEBUG2(printk(KERN_ERR "Could not add session.\n"));
- return err;
+ if (task->sc) {
+ ql4_printk(KERN_INFO, ha,
+ "%s: SCSI Commands not implemented\n", __func__);
+ return -EINVAL;
}
- ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0, 0);
- if (!ddb_entry->conn) {
- iscsi_remove_session(ddb_entry->sess);
- DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
- return -ENOMEM;
+ hdr_len = sizeof(struct iscsi_hdr);
+ task_data->ha = ha;
+ task_data->task = task;
+
+ if (task->data_count) {
+ task_data->data_dma = dma_map_single(&ha->pdev->dev, task->data,
+ task->data_count,
+ PCI_DMA_TODEVICE);
}
- /* finally ready to go */
- iscsi_unblock_session(ddb_entry->sess);
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
+ __func__, task->conn->max_recv_dlength, hdr_len));
+
+ task_data->resp_len = task->conn->max_recv_dlength + hdr_len;
+ task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev,
+ task_data->resp_len,
+ &task_data->resp_dma,
+ GFP_ATOMIC);
+ if (!task_data->resp_buffer)
+ goto exit_alloc_pdu;
+
+ task_data->req_len = task->data_count + hdr_len;
+ task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev,
+ task_data->req_len,
+ &task_data->req_dma,
+ GFP_ATOMIC);
+ if (!task_data->req_buffer)
+ goto exit_alloc_pdu;
+
+ task->hdr = task_data->req_buffer;
+
+ INIT_WORK(&task_data->task_work, qla4xxx_task_work);
+
return 0;
+
+exit_alloc_pdu:
+ if (task_data->resp_buffer)
+ dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
+ task_data->resp_buffer, task_data->resp_dma);
+
+ if (task_data->req_buffer)
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
+ task_data->req_buffer, task_data->req_dma);
+ return -ENOMEM;
}
-struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
+static void qla4xxx_task_cleanup(struct iscsi_task *task)
{
+ struct ql4_task_data *task_data;
+ struct iscsi_session *sess;
struct ddb_entry *ddb_entry;
- struct iscsi_cls_session *sess;
-
- sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport,
- sizeof(struct ddb_entry));
- if (!sess)
- return NULL;
+ struct scsi_qla_host *ha;
+ int hdr_len;
+ hdr_len = sizeof(struct iscsi_hdr);
+ sess = task->conn->session;
ddb_entry = sess->dd_data;
- memset(ddb_entry, 0, sizeof(*ddb_entry));
- ddb_entry->ha = ha;
- ddb_entry->sess = sess;
- return ddb_entry;
+ ha = ddb_entry->ha;
+ task_data = task->dd_data;
+
+ if (task->data_count) {
+ dma_unmap_single(&ha->pdev->dev, task_data->data_dma,
+ task->data_count, PCI_DMA_TODEVICE);
+ }
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
+ __func__, task->conn->max_recv_dlength, hdr_len));
+
+ dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
+ task_data->resp_buffer, task_data->resp_dma);
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
+ task_data->req_buffer, task_data->req_dma);
+ return;
+}
+
+static int qla4xxx_task_xmit(struct iscsi_task *task)
+{
+ struct scsi_cmnd *sc = task->sc;
+ struct iscsi_session *sess = task->conn->session;
+ struct ddb_entry *ddb_entry = sess->dd_data;
+ struct scsi_qla_host *ha = ddb_entry->ha;
+
+ if (!sc)
+ return qla4xxx_send_passthru0(task);
+
+ ql4_printk(KERN_INFO, ha, "%s: scsi cmd xmit not implemented\n",
+ __func__);
+ return -ENOSYS;
+}
+
+static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ struct iscsi_cls_session *cls_sess,
+ struct iscsi_cls_conn *cls_conn)
+{
+ int buflen = 0;
+ struct iscsi_session *sess;
+ struct iscsi_conn *conn;
+ char ip_addr[DDB_IPADDR_LEN];
+ uint16_t options = 0;
+
+ sess = cls_sess->dd_data;
+ conn = cls_conn->dd_data;
+
+ conn->max_recv_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
+
+ conn->max_xmit_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
+
+ sess->initial_r2t_en =
+ (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options));
+
+ sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
+
+ sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options));
+
+ sess->first_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
+
+ sess->max_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
+
+ sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
+
+ sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
+
+ conn->persistent_port = le16_to_cpu(fw_ddb_entry->port);
+
+ sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ if (options & DDB_OPT_IPV6_DEVICE)
+ sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr);
+ else
+ sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr);
+
+ iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME,
+ (char *)fw_ddb_entry->iscsi_name, buflen);
+ iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME,
+ (char *)ha->name_string, buflen);
+ iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS,
+ (char *)ip_addr, buflen);
+}
+
+void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry)
+{
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_cls_conn *cls_conn;
+ uint32_t ddb_state;
+ dma_addr_t fw_ddb_entry_dma;
+ struct dev_db_entry *fw_ddb_entry;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ goto exit_session_conn_fwddb_param;
+ }
+
+ if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
+ fw_ddb_entry_dma, NULL, NULL, &ddb_state,
+ NULL, NULL, NULL) == QLA_ERROR) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "get_ddb_entry for fw_ddb_index %d\n",
+ ha->host_no, __func__,
+ ddb_entry->fw_ddb_index));
+ goto exit_session_conn_fwddb_param;
+ }
+
+ cls_sess = ddb_entry->sess;
+
+ cls_conn = ddb_entry->conn;
+
+ /* Update params */
+ qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
+
+exit_session_conn_fwddb_param:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
}
-static void qla4xxx_scan_start(struct Scsi_Host *shost)
+void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry)
{
- struct scsi_qla_host *ha = shost_priv(shost);
- struct ddb_entry *ddb_entry, *ddbtemp;
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_session *sess;
+ struct iscsi_conn *conn;
+ uint32_t ddb_state;
+ dma_addr_t fw_ddb_entry_dma;
+ struct dev_db_entry *fw_ddb_entry;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ goto exit_session_conn_param;
+ }
- /* finish setup of sessions that were already setup in firmware */
- list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
- if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
- qla4xxx_add_sess(ddb_entry);
+ if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
+ fw_ddb_entry_dma, NULL, NULL, &ddb_state,
+ NULL, NULL, NULL) == QLA_ERROR) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "get_ddb_entry for fw_ddb_index %d\n",
+ ha->host_no, __func__,
+ ddb_entry->fw_ddb_index));
+ goto exit_session_conn_param;
}
+
+ cls_sess = ddb_entry->sess;
+ sess = cls_sess->dd_data;
+
+ cls_conn = ddb_entry->conn;
+ conn = cls_conn->dd_data;
+
+ /* Update timers after login */
+ ddb_entry->default_relogin_timeout =
+ le16_to_cpu(fw_ddb_entry->def_timeout);
+ ddb_entry->default_time2wait =
+ le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
+
+ /* Update params */
+ conn->max_recv_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
+
+ conn->max_xmit_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
+
+ sess->initial_r2t_en =
+ (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options));
+
+ sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
+
+ sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options));
+
+ sess->first_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
+
+ sess->max_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
+
+ sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
+
+ sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
+
+ sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+
+ memcpy(sess->initiatorname, ha->name_string,
+ min(sizeof(ha->name_string), sizeof(sess->initiatorname)));
+
+exit_session_conn_param:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
}
/*
@@ -376,25 +1684,15 @@ static void qla4xxx_stop_timer(struct scsi_qla_host *ha)
}
/***
- * qla4xxx_mark_device_missing - mark a device as missing.
- * @ha: Pointer to host adapter structure.
+ * qla4xxx_mark_device_missing - blocks the session
+ * @cls_session: Pointer to the session to be blocked
* @ddb_entry: Pointer to device database entry
*
* This routine marks a device missing and close connection.
**/
-void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry)
+void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session)
{
- if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) {
- atomic_set(&ddb_entry->state, DDB_STATE_MISSING);
- DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n",
- ha->host_no, ddb_entry->fw_ddb_index));
- } else
- DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no,
- ddb_entry->fw_ddb_index))
-
- iscsi_block_session(ddb_entry->sess);
- iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_block_session(cls_session);
}
/**
@@ -405,10 +1703,7 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
**/
void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry, *ddbtemp;
- list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
- qla4xxx_mark_device_missing(ha, ddb_entry);
- }
+ iscsi_host_for_each_session(ha->host, qla4xxx_mark_device_missing);
}
static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
@@ -495,20 +1790,13 @@ static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto qc_fail_command;
}
- if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
- if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
- cmd->result = DID_NO_CONNECT << 16;
- goto qc_fail_command;
- }
- return SCSI_MLQUEUE_TARGET_BUSY;
- }
-
if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
!test_bit(AF_ONLINE, &ha->flags) ||
+ !test_bit(AF_LINK_UP, &ha->flags) ||
test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))
goto qc_host_busy;
@@ -563,6 +1851,16 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
ha->srb_mempool = NULL;
+ if (ha->chap_dma_pool)
+ dma_pool_destroy(ha->chap_dma_pool);
+
+ if (ha->chap_list)
+ vfree(ha->chap_list);
+ ha->chap_list = NULL;
+
+ if (ha->fw_ddb_dma_pool)
+ dma_pool_destroy(ha->fw_ddb_dma_pool);
+
/* release io space registers */
if (is_qla8022(ha)) {
if (ha->nx_pcibase)
@@ -636,6 +1934,25 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
goto mem_alloc_error_exit;
}
+ ha->chap_dma_pool = dma_pool_create("ql4_chap", &ha->pdev->dev,
+ CHAP_DMA_BLOCK_SIZE, 8, 0);
+
+ if (ha->chap_dma_pool == NULL) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s: chap_dma_pool allocation failed..\n", __func__);
+ goto mem_alloc_error_exit;
+ }
+
+ ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev,
+ DDB_DMA_BLOCK_SIZE, 8, 0);
+
+ if (ha->fw_ddb_dma_pool == NULL) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s: fw_ddb_dma_pool allocation failed..\n",
+ __func__);
+ goto mem_alloc_error_exit;
+ }
+
return QLA_SUCCESS;
mem_alloc_error_exit:
@@ -747,16 +2064,71 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
}
}
+void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ if (!(ddb_entry->ddb_type == FLASH_DDB))
+ return;
+
+ if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
+ !iscsi_is_session_online(cls_sess)) {
+ if (atomic_read(&ddb_entry->retry_relogin_timer) !=
+ INVALID_ENTRY) {
+ if (atomic_read(&ddb_entry->retry_relogin_timer) ==
+ 0) {
+ atomic_set(&ddb_entry->retry_relogin_timer,
+ INVALID_ENTRY);
+ set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
+ set_bit(DF_RELOGIN, &ddb_entry->flags);
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: index [%d] login device\n",
+ __func__, ddb_entry->fw_ddb_index));
+ } else
+ atomic_dec(&ddb_entry->retry_relogin_timer);
+ }
+ }
+
+ /* Wait for relogin to timeout */
+ if (atomic_read(&ddb_entry->relogin_timer) &&
+ (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
+ /*
+ * If the relogin times out and the device is
+ * still NOT ONLINE then try and relogin again.
+ */
+ if (!iscsi_is_session_online(cls_sess)) {
+ /* Reset retry relogin timer */
+ atomic_inc(&ddb_entry->relogin_retry_count);
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: index[%d] relogin timed out-retrying"
+ " relogin (%d), retry (%d)\n", __func__,
+ ddb_entry->fw_ddb_index,
+ atomic_read(&ddb_entry->relogin_retry_count),
+ ddb_entry->default_time2wait + 4));
+ set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
+ atomic_set(&ddb_entry->retry_relogin_timer,
+ ddb_entry->default_time2wait + 4);
+ }
+ }
+}
+
/**
* qla4xxx_timer - checks every second for work to do.
* @ha: Pointer to host adapter structure.
**/
static void qla4xxx_timer(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry, *dtemp;
int start_dpc = 0;
uint16_t w;
+ iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb);
+
/* If we are in the middle of AER/EEH processing
* skip any processing and reschedule the timer
*/
@@ -773,69 +2145,6 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
qla4_8xxx_watchdog(ha);
}
- /* Search for relogin's to time-out and port down retry. */
- list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
- /* Count down time between sending relogins */
- if (adapter_up(ha) &&
- !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
- atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
- if (atomic_read(&ddb_entry->retry_relogin_timer) !=
- INVALID_ENTRY) {
- if (atomic_read(&ddb_entry->retry_relogin_timer)
- == 0) {
- atomic_set(&ddb_entry->
- retry_relogin_timer,
- INVALID_ENTRY);
- set_bit(DPC_RELOGIN_DEVICE,
- &ha->dpc_flags);
- set_bit(DF_RELOGIN, &ddb_entry->flags);
- DEBUG2(printk("scsi%ld: %s: ddb [%d]"
- " login device\n",
- ha->host_no, __func__,
- ddb_entry->fw_ddb_index));
- } else
- atomic_dec(&ddb_entry->
- retry_relogin_timer);
- }
- }
-
- /* Wait for relogin to timeout */
- if (atomic_read(&ddb_entry->relogin_timer) &&
- (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
- /*
- * If the relogin times out and the device is
- * still NOT ONLINE then try and relogin again.
- */
- if (atomic_read(&ddb_entry->state) !=
- DDB_STATE_ONLINE &&
- ddb_entry->fw_ddb_device_state ==
- DDB_DS_SESSION_FAILED) {
- /* Reset retry relogin timer */
- atomic_inc(&ddb_entry->relogin_retry_count);
- DEBUG2(printk("scsi%ld: ddb [%d] relogin"
- " timed out-retrying"
- " relogin (%d)\n",
- ha->host_no,
- ddb_entry->fw_ddb_index,
- atomic_read(&ddb_entry->
- relogin_retry_count))
- );
- start_dpc++;
- DEBUG(printk("scsi%ld:%d:%d: ddb [%d] "
- "initiate relogin after"
- " %d seconds\n",
- ha->host_no, ddb_entry->bus,
- ddb_entry->target,
- ddb_entry->fw_ddb_index,
- ddb_entry->default_time2wait + 4)
- );
-
- atomic_set(&ddb_entry->retry_relogin_timer,
- ddb_entry->default_time2wait + 4);
- }
- }
- }
-
if (!is_qla8022(ha)) {
/* Check for heartbeat interval. */
if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&
@@ -1081,6 +2390,22 @@ void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)
clear_bit(AF_INIT_DONE, &ha->flags);
}
+static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED;
+
+ if (ddb_entry->ddb_type == FLASH_DDB)
+ iscsi_block_session(ddb_entry->sess);
+ else
+ iscsi_session_failure(cls_session->dd_data,
+ ISCSI_ERR_CONN_FAILED);
+}
+
/**
* qla4xxx_recover_adapter - recovers adapter after a fatal error
* @ha: Pointer to host adapter structure.
@@ -1093,11 +2418,14 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
/* Stall incoming I/O until we are done */
scsi_block_requests(ha->host);
clear_bit(AF_ONLINE, &ha->flags);
+ clear_bit(AF_LINK_UP, &ha->flags);
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__));
set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
+ iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
+
if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
reset_chip = 1;
@@ -1160,7 +2488,7 @@ recover_ha_init_adapter:
/* NOTE: AF_ONLINE flag set upon successful completion of
* qla4xxx_initialize_adapter */
- status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
+ status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
}
/* Retry failed adapter initialization, if necessary
@@ -1225,27 +2553,125 @@ recover_ha_init_adapter:
return status;
}
-static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
+static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session)
{
- struct ddb_entry *ddb_entry, *dtemp;
-
- list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
- if ((atomic_read(&ddb_entry->state) == DDB_STATE_MISSING) ||
- (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD)) {
- if (ddb_entry->fw_ddb_device_state ==
- DDB_DS_SESSION_ACTIVE) {
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
- " marked ONLINE\n", ha->host_no, __func__,
- ddb_entry->fw_ddb_index);
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
- iscsi_unblock_session(ddb_entry->sess);
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+ if (!iscsi_is_session_online(cls_session)) {
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+ ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
+ " unblock session\n", ha->host_no, __func__,
+ ddb_entry->fw_ddb_index);
+ iscsi_unblock_session(ddb_entry->sess);
+ } else {
+ /* Trigger relogin */
+ if (ddb_entry->ddb_type == FLASH_DDB) {
+ if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
+ qla4xxx_arm_relogin_timer(ddb_entry);
} else
- qla4xxx_relogin_device(ha, ddb_entry);
+ iscsi_session_failure(cls_session->dd_data,
+ ISCSI_ERR_CONN_FAILED);
}
}
}
+int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+ ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
+ " unblock session\n", ha->host_no, __func__,
+ ddb_entry->fw_ddb_index);
+
+ iscsi_unblock_session(ddb_entry->sess);
+
+ /* Start scan target */
+ if (test_bit(AF_ONLINE, &ha->flags)) {
+ ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
+ " start scan\n", ha->host_no, __func__,
+ ddb_entry->fw_ddb_index);
+ scsi_queue_work(ha->host, &ddb_entry->sess->scan_work);
+ }
+ return QLA_SUCCESS;
+}
+
+int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+ ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
+ " unblock user space session\n", ha->host_no, __func__,
+ ddb_entry->fw_ddb_index);
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
+
+ return QLA_SUCCESS;
+}
+
+static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
+{
+ iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices);
+}
+
+static void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
+{
+ uint16_t relogin_timer;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ relogin_timer = max(ddb_entry->default_relogin_timeout,
+ (uint16_t)RELOGIN_TOV);
+ atomic_set(&ddb_entry->relogin_timer, relogin_timer);
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no,
+ ddb_entry->fw_ddb_index, relogin_timer));
+
+ qla4xxx_login_flash_ddb(cls_sess);
+}
+
+static void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ if (!(ddb_entry->ddb_type == FLASH_DDB))
+ return;
+
+ if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
+ !iscsi_is_session_online(cls_sess)) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "relogin issued\n"));
+ qla4xxx_relogin_flash_ddb(cls_sess);
+ }
+}
+
void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
{
if (ha->dpc_thread)
@@ -1267,7 +2693,6 @@ static void qla4xxx_do_dpc(struct work_struct *work)
{
struct scsi_qla_host *ha =
container_of(work, struct scsi_qla_host, dpc_work);
- struct ddb_entry *ddb_entry, *dtemp;
int status = QLA_ERROR;
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
@@ -1347,6 +2772,12 @@ dpc_post_reset_ha:
if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
qla4xxx_get_dhcp_ip_address(ha);
+ /* ---- relogin device? --- */
+ if (adapter_up(ha) &&
+ test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
+ iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin);
+ }
+
/* ---- link change? --- */
if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
if (!test_bit(AF_LINK_UP, &ha->flags)) {
@@ -1359,35 +2790,14 @@ dpc_post_reset_ha:
* fatal error recovery. Therefore, the driver must
* manually relogin to devices when recovering from
* connection failures, logouts, expired KATO, etc. */
-
- qla4xxx_relogin_all_devices(ha);
- }
- }
-
- /* ---- relogin device? --- */
- if (adapter_up(ha) &&
- test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
- list_for_each_entry_safe(ddb_entry, dtemp,
- &ha->ddb_list, list) {
- if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
- atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
- qla4xxx_relogin_device(ha, ddb_entry);
-
- /*
- * If mbx cmd times out there is no point
- * in continuing further.
- * With large no of targets this can hang
- * the system.
- */
- if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
- printk(KERN_WARNING "scsi%ld: %s: "
- "need to reset hba\n",
- ha->host_no, __func__);
- break;
- }
+ if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) {
+ qla4xxx_build_ddb_list(ha, ha->is_reset);
+ iscsi_host_for_each_session(ha->host,
+ qla4xxx_login_flash_ddb);
+ } else
+ qla4xxx_relogin_all_devices(ha);
}
}
-
}
/**
@@ -1410,6 +2820,10 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
if (ha->dpc_thread)
destroy_workqueue(ha->dpc_thread);
+ /* Kill the kernel thread for this host */
+ if (ha->task_wq)
+ destroy_workqueue(ha->task_wq);
+
/* Put firmware in known state */
ha->isp_ops->reset_firmware(ha);
@@ -1601,6 +3015,1106 @@ uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
}
+static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ char *str = buf;
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_ETH_FLAGS:
+ rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
+ break;
+ case ISCSI_BOOT_ETH_INDEX:
+ rc = sprintf(str, "0\n");
+ break;
+ case ISCSI_BOOT_ETH_MAC:
+ rc = sysfs_format_mac(str, ha->my_mac,
+ MAC_ADDR_LEN);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
+static mode_t qla4xxx_eth_get_attr_visibility(void *data, int type)
+{
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_ETH_FLAGS:
+ case ISCSI_BOOT_ETH_MAC:
+ case ISCSI_BOOT_ETH_INDEX:
+ rc = S_IRUGO;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static ssize_t qla4xxx_show_boot_ini_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ char *str = buf;
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_INI_INITIATOR_NAME:
+ rc = sprintf(str, "%s\n", ha->name_string);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
+static mode_t qla4xxx_ini_get_attr_visibility(void *data, int type)
+{
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_INI_INITIATOR_NAME:
+ rc = S_IRUGO;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static ssize_t
+qla4xxx_show_boot_tgt_info(struct ql4_boot_session_info *boot_sess, int type,
+ char *buf)
+{
+ struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
+ char *str = buf;
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_TGT_NAME:
+ rc = sprintf(buf, "%s\n", (char *)&boot_sess->target_name);
+ break;
+ case ISCSI_BOOT_TGT_IP_ADDR:
+ if (boot_sess->conn_list[0].dest_ipaddr.ip_type == 0x1)
+ rc = sprintf(buf, "%pI4\n",
+ &boot_conn->dest_ipaddr.ip_address);
+ else
+ rc = sprintf(str, "%pI6\n",
+ &boot_conn->dest_ipaddr.ip_address);
+ break;
+ case ISCSI_BOOT_TGT_PORT:
+ rc = sprintf(str, "%d\n", boot_conn->dest_port);
+ break;
+ case ISCSI_BOOT_TGT_CHAP_NAME:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.target_chap_name_length,
+ (char *)&boot_conn->chap.target_chap_name);
+ break;
+ case ISCSI_BOOT_TGT_CHAP_SECRET:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.target_secret_length,
+ (char *)&boot_conn->chap.target_secret);
+ break;
+ case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.intr_chap_name_length,
+ (char *)&boot_conn->chap.intr_chap_name);
+ break;
+ case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.intr_secret_length,
+ (char *)&boot_conn->chap.intr_secret);
+ break;
+ case ISCSI_BOOT_TGT_FLAGS:
+ rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
+ break;
+ case ISCSI_BOOT_TGT_NIC_ASSOC:
+ rc = sprintf(str, "0\n");
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
+static ssize_t qla4xxx_show_boot_tgt_pri_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_pri_sess);
+
+ return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
+}
+
+static ssize_t qla4xxx_show_boot_tgt_sec_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_sec_sess);
+
+ return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
+}
+
+static mode_t qla4xxx_tgt_get_attr_visibility(void *data, int type)
+{
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_TGT_NAME:
+ case ISCSI_BOOT_TGT_IP_ADDR:
+ case ISCSI_BOOT_TGT_PORT:
+ case ISCSI_BOOT_TGT_CHAP_NAME:
+ case ISCSI_BOOT_TGT_CHAP_SECRET:
+ case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+ case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+ case ISCSI_BOOT_TGT_NIC_ASSOC:
+ case ISCSI_BOOT_TGT_FLAGS:
+ rc = S_IRUGO;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static void qla4xxx_boot_release(void *data)
+{
+ struct scsi_qla_host *ha = data;
+
+ scsi_host_put(ha->host);
+}
+
+static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
+{
+ dma_addr_t buf_dma;
+ uint32_t addr, pri_addr, sec_addr;
+ uint32_t offset;
+ uint16_t func_num;
+ uint8_t val;
+ uint8_t *buf = NULL;
+ size_t size = 13 * sizeof(uint8_t);
+ int ret = QLA_SUCCESS;
+
+ func_num = PCI_FUNC(ha->pdev->devfn);
+
+ ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n",
+ __func__, ha->pdev->device, func_num);
+
+ if (is_qla40XX(ha)) {
+ if (func_num == 1) {
+ addr = NVRAM_PORT0_BOOT_MODE;
+ pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;
+ sec_addr = NVRAM_PORT0_BOOT_SEC_TGT;
+ } else if (func_num == 3) {
+ addr = NVRAM_PORT1_BOOT_MODE;
+ pri_addr = NVRAM_PORT1_BOOT_PRI_TGT;
+ sec_addr = NVRAM_PORT1_BOOT_SEC_TGT;
+ } else {
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ /* Check Boot Mode */
+ val = rd_nvram_byte(ha, addr);
+ if (!(val & 0x07)) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Failed Boot options : 0x%x\n",
+ __func__, val));
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ /* get primary valid target index */
+ val = rd_nvram_byte(ha, pri_addr);
+ if (val & BIT_7)
+ ddb_index[0] = (val & 0x7f);
+
+ /* get secondary valid target index */
+ val = rd_nvram_byte(ha, sec_addr);
+ if (val & BIT_7)
+ ddb_index[1] = (val & 0x7f);
+
+ } else if (is_qla8022(ha)) {
+ buf = dma_alloc_coherent(&ha->pdev->dev, size,
+ &buf_dma, GFP_KERNEL);
+ if (!buf) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ if (ha->port_num == 0)
+ offset = BOOT_PARAM_OFFSET_PORT0;
+ else if (ha->port_num == 1)
+ offset = BOOT_PARAM_OFFSET_PORT1;
+ else {
+ ret = QLA_ERROR;
+ goto exit_boot_info_free;
+ }
+ addr = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_iscsi_param * 4) +
+ offset;
+ if (qla4xxx_get_flash(ha, buf_dma, addr,
+ 13 * sizeof(uint8_t)) != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
+ "failed\n", ha->host_no, __func__));
+ ret = QLA_ERROR;
+ goto exit_boot_info_free;
+ }
+ /* Check Boot Mode */
+ if (!(buf[1] & 0x07)) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Failed: Boot options : 0x%x\n",
+ buf[1]));
+ ret = QLA_ERROR;
+ goto exit_boot_info_free;
+ }
+
+ /* get primary valid target index */
+ if (buf[2] & BIT_7)
+ ddb_index[0] = buf[2] & 0x7f;
+
+ /* get secondary valid target index */
+ if (buf[11] & BIT_7)
+ ddb_index[1] = buf[11] & 0x7f;
+ } else {
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary target ID %d, Secondary"
+ " target ID %d\n", __func__, ddb_index[0],
+ ddb_index[1]));
+
+ ha->pri_ddb_idx = ddb_index[0];
+ ha->sec_ddb_idx = ddb_index[1];
+
+exit_boot_info_free:
+ dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);
+exit_boot_info:
+ return ret;
+}
+
+/**
+ * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be returned
+ * @password: CHAP password to be returned
+ *
+ * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP
+ * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/.
+ * So from the CHAP cache find the first BIDI CHAP entry and set it
+ * to the boot record in sysfs.
+ **/
+static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
+ char *password)
+{
+ int i, ret = -EINVAL;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return ret;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ continue;
+ }
+
+ if (chap_table->flags & BIT_7) /* local */
+ continue;
+
+ if (!(chap_table->flags & BIT_6)) /* Not BIDI */
+ continue;
+
+ strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ ret = 0;
+ break;
+ }
+ mutex_unlock(&ha->chap_sem);
+
+ return ret;
+}
+
+
+static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
+ struct ql4_boot_session_info *boot_sess,
+ uint16_t ddb_index)
+{
+ struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
+ struct dev_db_entry *fw_ddb_entry;
+ dma_addr_t fw_ddb_entry_dma;
+ uint16_t idx;
+ uint16_t options;
+ int ret = QLA_SUCCESS;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer.\n",
+ __func__));
+ ret = QLA_ERROR;
+ return ret;
+ }
+
+ if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry,
+ fw_ddb_entry_dma, ddb_index)) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Flash DDB read Failed\n", __func__));
+ ret = QLA_ERROR;
+ goto exit_boot_target;
+ }
+
+ /* Update target name and IP from DDB */
+ memcpy(boot_sess->target_name, fw_ddb_entry->iscsi_name,
+ min(sizeof(boot_sess->target_name),
+ sizeof(fw_ddb_entry->iscsi_name)));
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ if (options & DDB_OPT_IPV6_DEVICE) {
+ memcpy(&boot_conn->dest_ipaddr.ip_address,
+ &fw_ddb_entry->ip_addr[0], IPv6_ADDR_LEN);
+ } else {
+ boot_conn->dest_ipaddr.ip_type = 0x1;
+ memcpy(&boot_conn->dest_ipaddr.ip_address,
+ &fw_ddb_entry->ip_addr[0], IP_ADDR_LEN);
+ }
+
+ boot_conn->dest_port = le16_to_cpu(fw_ddb_entry->port);
+
+ /* update chap information */
+ idx = __le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
+
+ if (BIT_7 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "Setting chap\n"));
+
+ ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
+ target_chap_name,
+ (char *)&boot_conn->chap.target_secret,
+ idx);
+ if (ret) {
+ ql4_printk(KERN_ERR, ha, "Failed to set chap\n");
+ ret = QLA_ERROR;
+ goto exit_boot_target;
+ }
+
+ boot_conn->chap.target_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
+ boot_conn->chap.target_secret_length = QL4_CHAP_MAX_SECRET_LEN;
+ }
+
+ if (BIT_4 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));
+
+ ret = qla4xxx_get_bidi_chap(ha,
+ (char *)&boot_conn->chap.intr_chap_name,
+ (char *)&boot_conn->chap.intr_secret);
+
+ if (ret) {
+ ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");
+ ret = QLA_ERROR;
+ goto exit_boot_target;
+ }
+
+ boot_conn->chap.intr_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
+ boot_conn->chap.intr_secret_length = QL4_CHAP_MAX_SECRET_LEN;
+ }
+
+exit_boot_target:
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+ return ret;
+}
+
+static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
+{
+ uint16_t ddb_index[2];
+ int ret = QLA_ERROR;
+ int rval;
+
+ memset(ddb_index, 0, sizeof(ddb_index));
+ ddb_index[0] = 0xffff;
+ ddb_index[1] = 0xffff;
+ ret = get_fw_boot_info(ha, ddb_index);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Failed to set boot info.\n", __func__));
+ return ret;
+ }
+
+ if (ql4xdisablesysfsboot)
+ return QLA_SUCCESS;
+
+ if (ddb_index[0] == 0xffff)
+ goto sec_target;
+
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
+ ddb_index[0]);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
+ "primary target\n", __func__));
+ } else
+ ret = QLA_SUCCESS;
+
+sec_target:
+ if (ddb_index[1] == 0xffff)
+ goto exit_get_boot_info;
+
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
+ ddb_index[1]);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
+ "secondary target\n", __func__));
+ } else
+ ret = QLA_SUCCESS;
+
+exit_get_boot_info:
+ return ret;
+}
+
+static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
+{
+ struct iscsi_boot_kobj *boot_kobj;
+
+ if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS)
+ return QLA_ERROR;
+
+ if (ql4xdisablesysfsboot) {
+ ql4_printk(KERN_INFO, ha,
+ "%s: syfsboot disabled - driver will trigger login"
+ "and publish session for discovery .\n", __func__);
+ return QLA_SUCCESS;
+ }
+
+
+ ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no);
+ if (!ha->boot_kset)
+ goto kset_free;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_target(ha->boot_kset, 0, ha,
+ qla4xxx_show_boot_tgt_pri_info,
+ qla4xxx_tgt_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_target(ha->boot_kset, 1, ha,
+ qla4xxx_show_boot_tgt_sec_info,
+ qla4xxx_tgt_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_initiator(ha->boot_kset, 0, ha,
+ qla4xxx_show_boot_ini_info,
+ qla4xxx_ini_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_ethernet(ha->boot_kset, 0, ha,
+ qla4xxx_show_boot_eth_info,
+ qla4xxx_eth_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ return QLA_SUCCESS;
+
+put_host:
+ scsi_host_put(ha->host);
+kset_free:
+ iscsi_boot_destroy_kset(ha->boot_kset);
+ return -ENOMEM;
+}
+
+
+/**
+ * qla4xxx_create chap_list - Create CHAP list from FLASH
+ * @ha: pointer to adapter structure
+ *
+ * Read flash and make a list of CHAP entries, during login when a CHAP entry
+ * is received, it will be checked in this list. If entry exist then the CHAP
+ * entry index is set in the DDB. If CHAP entry does not exist in this list
+ * then a new entry is added in FLASH in CHAP table and the index obtained is
+ * used in the DDB.
+ **/
+static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)
+{
+ int rval = 0;
+ uint8_t *chap_flash_data = NULL;
+ uint32_t offset;
+ dma_addr_t chap_dma;
+ uint32_t chap_size = 0;
+
+ if (is_qla40XX(ha))
+ chap_size = MAX_CHAP_ENTRIES_40XX *
+ sizeof(struct ql4_chap_table);
+ else /* Single region contains CHAP info for both
+ * ports which is divided into half for each port.
+ */
+ chap_size = ha->hw.flt_chap_size / 2;
+
+ chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size,
+ &chap_dma, GFP_KERNEL);
+ if (!chap_flash_data) {
+ ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n");
+ return;
+ }
+ if (is_qla40XX(ha))
+ offset = FLASH_CHAP_OFFSET;
+ else {
+ offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
+ if (ha->port_num == 1)
+ offset += chap_size;
+ }
+
+ rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
+ if (rval != QLA_SUCCESS)
+ goto exit_chap_list;
+
+ if (ha->chap_list == NULL)
+ ha->chap_list = vmalloc(chap_size);
+ if (ha->chap_list == NULL) {
+ ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n");
+ goto exit_chap_list;
+ }
+
+ memcpy(ha->chap_list, chap_flash_data, chap_size);
+
+exit_chap_list:
+ dma_free_coherent(&ha->pdev->dev, chap_size,
+ chap_flash_data, chap_dma);
+}
+
+static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,
+ struct ql4_tuple_ddb *tddb)
+{
+ struct scsi_qla_host *ha;
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_session *sess;
+ struct iscsi_conn *conn;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ ha = ddb_entry->ha;
+ cls_sess = ddb_entry->sess;
+ sess = cls_sess->dd_data;
+ cls_conn = ddb_entry->conn;
+ conn = cls_conn->dd_data;
+
+ tddb->tpgt = sess->tpgt;
+ tddb->port = conn->persistent_port;
+ strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
+ strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
+}
+
+static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
+ struct ql4_tuple_ddb *tddb)
+{
+ uint16_t options = 0;
+
+ tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+ memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
+ min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name)));
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ if (options & DDB_OPT_IPV6_DEVICE)
+ sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr);
+ else
+ sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
+
+ tddb->port = le16_to_cpu(fw_ddb_entry->port);
+}
+
+static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
+ struct ql4_tuple_ddb *old_tddb,
+ struct ql4_tuple_ddb *new_tddb)
+{
+ if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))
+ return QLA_ERROR;
+
+ if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr))
+ return QLA_ERROR;
+
+ if (old_tddb->port != new_tddb->port)
+ return QLA_ERROR;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]",
+ old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr,
+ old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt,
+ new_tddb->ip_addr, new_tddb->iscsi_name));
+
+ return QLA_SUCCESS;
+}
+
+static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry)
+{
+ struct ddb_entry *ddb_entry;
+ struct ql4_tuple_ddb *fw_tddb = NULL;
+ struct ql4_tuple_ddb *tmp_tddb = NULL;
+ int idx;
+ int ret = QLA_ERROR;
+
+ fw_tddb = vzalloc(sizeof(*fw_tddb));
+ if (!fw_tddb) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "Memory Allocation failed.\n"));
+ ret = QLA_SUCCESS;
+ goto exit_check;
+ }
+
+ tmp_tddb = vzalloc(sizeof(*tmp_tddb));
+ if (!tmp_tddb) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "Memory Allocation failed.\n"));
+ ret = QLA_SUCCESS;
+ goto exit_check;
+ }
+
+ qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
+
+ for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
+ if (ddb_entry == NULL)
+ continue;
+
+ qla4xxx_get_param_ddb(ddb_entry, tmp_tddb);
+ if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
+ ret = QLA_SUCCESS; /* found */
+ goto exit_check;
+ }
+ }
+
+exit_check:
+ if (fw_tddb)
+ vfree(fw_tddb);
+ if (tmp_tddb)
+ vfree(tmp_tddb);
+ return ret;
+}
+
+static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
+ struct list_head *list_nt,
+ struct dev_db_entry *fw_ddb_entry)
+{
+ struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
+ struct ql4_tuple_ddb *fw_tddb = NULL;
+ struct ql4_tuple_ddb *tmp_tddb = NULL;
+ int ret = QLA_ERROR;
+
+ fw_tddb = vzalloc(sizeof(*fw_tddb));
+ if (!fw_tddb) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "Memory Allocation failed.\n"));
+ ret = QLA_SUCCESS;
+ goto exit_check;
+ }
+
+ tmp_tddb = vzalloc(sizeof(*tmp_tddb));
+ if (!tmp_tddb) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "Memory Allocation failed.\n"));
+ ret = QLA_SUCCESS;
+ goto exit_check;
+ }
+
+ qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
+
+ list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
+ qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb);
+ if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
+ ret = QLA_SUCCESS; /* found */
+ goto exit_check;
+ }
+ }
+
+exit_check:
+ if (fw_tddb)
+ vfree(fw_tddb);
+ if (tmp_tddb)
+ vfree(tmp_tddb);
+ return ret;
+}
+
+static void qla4xxx_free_nt_list(struct list_head *list_nt)
+{
+ struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
+
+ /* Free up the normaltargets list */
+ list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
+ list_del_init(&nt_ddb_idx->list);
+ vfree(nt_ddb_idx);
+ }
+
+}
+
+static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry)
+{
+ struct iscsi_endpoint *ep;
+ struct sockaddr_in *addr;
+ struct sockaddr_in6 *addr6;
+ struct sockaddr *dst_addr;
+ char *ip;
+
+ /* TODO: need to destroy on unload iscsi_endpoint*/
+ dst_addr = vmalloc(sizeof(*dst_addr));
+ if (!dst_addr)
+ return NULL;
+
+ if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
+ dst_addr->sa_family = AF_INET6;
+ addr6 = (struct sockaddr_in6 *)dst_addr;
+ ip = (char *)&addr6->sin6_addr;
+ memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);
+ addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port));
+
+ } else {
+ dst_addr->sa_family = AF_INET;
+ addr = (struct sockaddr_in *)dst_addr;
+ ip = (char *)&addr->sin_addr;
+ memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN);
+ addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port));
+ }
+
+ ep = qla4xxx_ep_connect(ha->host, dst_addr, 0);
+ vfree(dst_addr);
+ return ep;
+}
+
+static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
+{
+ if (ql4xdisablesysfsboot)
+ return QLA_SUCCESS;
+ if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx)
+ return QLA_ERROR;
+ return QLA_SUCCESS;
+}
+
+static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry)
+{
+ ddb_entry->ddb_type = FLASH_DDB;
+ ddb_entry->fw_ddb_index = INVALID_ENTRY;
+ ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
+ ddb_entry->ha = ha;
+ ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb;
+ ddb_entry->ddb_change = qla4xxx_flash_ddb_change;
+
+ atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
+ atomic_set(&ddb_entry->relogin_timer, 0);
+ atomic_set(&ddb_entry->relogin_retry_count, 0);
+
+ ddb_entry->default_relogin_timeout =
+ le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
+ ddb_entry->default_time2wait =
+ le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
+}
+
+static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
+{
+ uint32_t idx = 0;
+ uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */
+ uint32_t sts[MBOX_REG_COUNT];
+ uint32_t ip_state;
+ unsigned long wtime;
+ int ret;
+
+ wtime = jiffies + (HZ * IP_CONFIG_TOV);
+ do {
+ for (idx = 0; idx < IP_ADDR_COUNT; idx++) {
+ if (ip_idx[idx] == -1)
+ continue;
+
+ ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts);
+
+ if (ret == QLA_ERROR) {
+ ip_idx[idx] = -1;
+ continue;
+ }
+
+ ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Waiting for IP state for idx = %d, state = 0x%x\n",
+ ip_idx[idx], ip_state));
+ if (ip_state == IP_ADDRSTATE_UNCONFIGURED ||
+ ip_state == IP_ADDRSTATE_INVALID ||
+ ip_state == IP_ADDRSTATE_PREFERRED ||
+ ip_state == IP_ADDRSTATE_DEPRICATED ||
+ ip_state == IP_ADDRSTATE_DISABLING)
+ ip_idx[idx] = -1;
+
+ }
+
+ /* Break if all IP states checked */
+ if ((ip_idx[0] == -1) &&
+ (ip_idx[1] == -1) &&
+ (ip_idx[2] == -1) &&
+ (ip_idx[3] == -1))
+ break;
+ schedule_timeout_uninterruptible(HZ);
+ } while (time_after(wtime, jiffies));
+}
+
+void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
+{
+ int max_ddbs;
+ int ret;
+ uint32_t idx = 0, next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+ uint16_t conn_id;
+ struct dev_db_entry *fw_ddb_entry;
+ struct ddb_entry *ddb_entry = NULL;
+ dma_addr_t fw_ddb_dma;
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_session *sess;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_endpoint *ep;
+ uint16_t cmds_max = 32, tmo = 0;
+ uint32_t initial_cmdsn = 0;
+ struct list_head list_st, list_nt; /* List of sendtargets */
+ struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
+ int fw_idx_size;
+ unsigned long wtime;
+ struct qla_ddb_index *nt_ddb_idx;
+
+ if (!test_bit(AF_LINK_UP, &ha->flags)) {
+ set_bit(AF_BUILD_DDB_LIST, &ha->flags);
+ ha->is_reset = is_reset;
+ return;
+ }
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
+
+ fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
+ &fw_ddb_dma);
+ if (fw_ddb_entry == NULL) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
+ goto exit_ddb_list;
+ }
+
+ INIT_LIST_HEAD(&list_st);
+ INIT_LIST_HEAD(&list_nt);
+ fw_idx_size = sizeof(struct qla_ddb_index);
+
+ for (idx = 0; idx < max_ddbs; idx = next_idx) {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
+ fw_ddb_dma, NULL,
+ &next_idx, &state, &conn_err,
+ NULL, &conn_id);
+ if (ret == QLA_ERROR)
+ break;
+
+ if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
+ goto continue_next_st;
+
+ /* Check if ST, add to the list_st */
+ if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
+ goto continue_next_st;
+
+ st_ddb_idx = vzalloc(fw_idx_size);
+ if (!st_ddb_idx)
+ break;
+
+ st_ddb_idx->fw_ddb_idx = idx;
+
+ list_add_tail(&st_ddb_idx->list, &list_st);
+continue_next_st:
+ if (next_idx == 0)
+ break;
+ }
+
+ /* Before issuing conn open mbox, ensure all IPs states are configured
+ * Note, conn open fails if IPs are not configured
+ */
+ qla4xxx_wait_for_ip_configuration(ha);
+
+ /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
+ list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
+ qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
+ }
+
+ /* Wait to ensure all sendtargets are done for min 12 sec wait */
+ tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Default time to wait for build ddb %d\n", tmo));
+
+ wtime = jiffies + (HZ * tmo);
+ do {
+ list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
+ list) {
+ ret = qla4xxx_get_fwddb_entry(ha,
+ st_ddb_idx->fw_ddb_idx,
+ NULL, 0, NULL, &next_idx,
+ &state, &conn_err, NULL,
+ NULL);
+ if (ret == QLA_ERROR)
+ continue;
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED) {
+ list_del_init(&st_ddb_idx->list);
+ vfree(st_ddb_idx);
+ }
+ }
+ schedule_timeout_uninterruptible(HZ / 10);
+ } while (time_after(wtime, jiffies));
+
+ /* Free up the sendtargets list */
+ list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
+ list_del_init(&st_ddb_idx->list);
+ vfree(st_ddb_idx);
+ }
+
+ for (idx = 0; idx < max_ddbs; idx = next_idx) {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
+ fw_ddb_dma, NULL,
+ &next_idx, &state, &conn_err,
+ NULL, &conn_id);
+ if (ret == QLA_ERROR)
+ break;
+
+ if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
+ goto continue_next_nt;
+
+ /* Check if NT, then add to list it */
+ if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
+ goto continue_next_nt;
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Adding DDB to session = 0x%x\n",
+ idx));
+ if (is_reset == INIT_ADAPTER) {
+ nt_ddb_idx = vmalloc(fw_idx_size);
+ if (!nt_ddb_idx)
+ break;
+
+ nt_ddb_idx->fw_ddb_idx = idx;
+
+ memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
+ sizeof(struct dev_db_entry));
+
+ if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
+ fw_ddb_entry) == QLA_SUCCESS) {
+ vfree(nt_ddb_idx);
+ goto continue_next_nt;
+ }
+ list_add_tail(&nt_ddb_idx->list, &list_nt);
+ } else if (is_reset == RESET_ADAPTER) {
+ if (qla4xxx_is_session_exists(ha,
+ fw_ddb_entry) == QLA_SUCCESS)
+ goto continue_next_nt;
+ }
+
+ /* Create session object, with INVALID_ENTRY,
+ * the targer_id would get set when we issue the login
+ */
+ cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
+ ha->host, cmds_max,
+ sizeof(struct ddb_entry),
+ sizeof(struct ql4_task_data),
+ initial_cmdsn, INVALID_ENTRY);
+ if (!cls_sess)
+ goto exit_ddb_list;
+
+ /*
+ * iscsi_session_setup increments the driver reference
+ * count which wouldn't let the driver to be unloaded.
+ * so calling module_put function to decrement the
+ * reference count.
+ **/
+ module_put(qla4xxx_iscsi_transport.owner);
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->sess = cls_sess;
+
+ cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
+ memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
+ sizeof(struct dev_db_entry));
+
+ qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
+
+ cls_conn = iscsi_conn_setup(cls_sess,
+ sizeof(struct qla_conn),
+ conn_id);
+ if (!cls_conn)
+ goto exit_ddb_list;
+
+ ddb_entry->conn = cls_conn;
+
+ /* Setup ep, for displaying attributes in sysfs */
+ ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
+ if (ep) {
+ ep->conn = cls_conn;
+ cls_conn->ep = ep;
+ } else {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "Unable to get ep\n"));
+ }
+
+ /* Update sess/conn params */
+ qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
+ cls_conn);
+
+ if (is_reset == RESET_ADAPTER) {
+ iscsi_block_session(cls_sess);
+ /* Use the relogin path to discover new devices
+ * by short-circuting the logic of setting
+ * timer to relogin - instead set the flags
+ * to initiate login right away.
+ */
+ set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
+ set_bit(DF_RELOGIN, &ddb_entry->flags);
+ }
+ }
+continue_next_nt:
+ if (next_idx == 0)
+ break;
+ }
+exit_ddb_list:
+ qla4xxx_free_nt_list(&list_nt);
+ if (fw_ddb_entry)
+ dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+
+ qla4xxx_free_ddb_index(ha);
+}
+
+
/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
@@ -1624,7 +4138,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (pci_enable_device(pdev))
return -1;
- host = scsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha));
+ host = iscsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha), 0);
if (host == NULL) {
printk(KERN_WARNING
"qla4xxx: Couldn't allocate host from scsi layer!\n");
@@ -1632,7 +4146,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
}
/* Clear our data area */
- ha = (struct scsi_qla_host *) host->hostdata;
+ ha = to_qla_host(host);
memset(ha, 0, sizeof(*ha));
/* Save the information from PCI BIOS. */
@@ -1675,11 +4189,12 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
qla4xxx_config_dma_addressing(ha);
/* Initialize lists and spinlocks. */
- INIT_LIST_HEAD(&ha->ddb_list);
INIT_LIST_HEAD(&ha->free_srb_q);
mutex_init(&ha->mbox_sem);
+ mutex_init(&ha->chap_sem);
init_completion(&ha->mbx_intr_comp);
+ init_completion(&ha->disable_acb_comp);
spin_lock_init(&ha->hardware_lock);
@@ -1692,6 +4207,27 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
goto probe_failed;
}
+ host->cmd_per_lun = 3;
+ host->max_channel = 0;
+ host->max_lun = MAX_LUNS - 1;
+ host->max_id = MAX_TARGETS;
+ host->max_cmd_len = IOCB_MAX_CDB_LEN;
+ host->can_queue = MAX_SRBS ;
+ host->transportt = qla4xxx_scsi_transport;
+
+ ret = scsi_init_shared_tag_map(host, MAX_SRBS);
+ if (ret) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s: scsi_init_shared_tag_map failed\n", __func__);
+ goto probe_failed;
+ }
+
+ pci_set_drvdata(pdev, ha);
+
+ ret = scsi_add_host(host, &pdev->dev);
+ if (ret)
+ goto probe_failed;
+
if (is_qla8022(ha))
(void) qla4_8xxx_get_flash_info(ha);
@@ -1700,7 +4236,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
* firmware
* NOTE: interrupts enabled upon successful completion
*/
- status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
+ status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
while ((!test_bit(AF_ONLINE, &ha->flags)) &&
init_retry_count++ < MAX_INIT_RETRIES) {
@@ -1721,7 +4257,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)
continue;
- status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
+ status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
}
if (!test_bit(AF_ONLINE, &ha->flags)) {
@@ -1736,24 +4272,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
qla4_8xxx_idc_unlock(ha);
}
ret = -ENODEV;
- goto probe_failed;
+ goto remove_host;
}
- host->cmd_per_lun = 3;
- host->max_channel = 0;
- host->max_lun = MAX_LUNS - 1;
- host->max_id = MAX_TARGETS;
- host->max_cmd_len = IOCB_MAX_CDB_LEN;
- host->can_queue = MAX_SRBS ;
- host->transportt = qla4xxx_scsi_transport;
-
- ret = scsi_init_shared_tag_map(host, MAX_SRBS);
- if (ret) {
- ql4_printk(KERN_WARNING, ha,
- "scsi_init_shared_tag_map failed\n");
- goto probe_failed;
- }
-
/* Startup the kernel thread for this host adapter. */
DEBUG2(printk("scsi: %s: Starting kernel thread for "
"qla4xxx_dpc\n", __func__));
@@ -1762,10 +4283,18 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (!ha->dpc_thread) {
ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n");
ret = -ENODEV;
- goto probe_failed;
+ goto remove_host;
}
INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
+ sprintf(buf, "qla4xxx_%lu_task", ha->host_no);
+ ha->task_wq = alloc_workqueue(buf, WQ_MEM_RECLAIM, 1);
+ if (!ha->task_wq) {
+ ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n");
+ ret = -ENODEV;
+ goto remove_host;
+ }
+
/* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc
* (which is called indirectly by qla4xxx_initialize_adapter),
* so that irqs will be registered after crbinit but before
@@ -1776,7 +4305,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (ret) {
ql4_printk(KERN_WARNING, ha, "Failed to reserve "
"interrupt %d already in use.\n", pdev->irq);
- goto probe_failed;
+ goto remove_host;
}
}
@@ -1788,21 +4317,29 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
set_bit(AF_INIT_DONE, &ha->flags);
- pci_set_drvdata(pdev, ha);
-
- ret = scsi_add_host(host, &pdev->dev);
- if (ret)
- goto probe_failed;
-
printk(KERN_INFO
" QLogic iSCSI HBA Driver version: %s\n"
" QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
ha->patch_number, ha->build_number);
- scsi_scan_host(host);
+
+ if (qla4xxx_setup_boot_info(ha))
+ ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
+ __func__);
+
+ /* Perform the build ddb list and login to each */
+ qla4xxx_build_ddb_list(ha, INIT_ADAPTER);
+ iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb);
+
+ qla4xxx_create_chap_list(ha);
+
+ qla4xxx_create_ifaces(ha);
return 0;
+remove_host:
+ scsi_remove_host(ha->host);
+
probe_failed:
qla4xxx_free_adapter(ha);
@@ -1854,6 +4391,38 @@ static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
}
}
+static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha)
+{
+ struct ddb_entry *ddb_entry;
+ int options;
+ int idx;
+
+ for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
+
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
+ if ((ddb_entry != NULL) &&
+ (ddb_entry->ddb_type == FLASH_DDB)) {
+
+ options = LOGOUT_OPTION_CLOSE_SESSION;
+ if (qla4xxx_session_logout_ddb(ha, ddb_entry, options)
+ == QLA_ERROR)
+ ql4_printk(KERN_ERR, ha, "%s: Logout failed\n",
+ __func__);
+
+ qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
+ /*
+ * we have decremented the reference count of the driver
+ * when we setup the session to have the driver unload
+ * to be seamless without actually destroying the
+ * session
+ **/
+ try_module_get(qla4xxx_iscsi_transport.owner);
+ iscsi_destroy_endpoint(ddb_entry->conn->ep);
+ qla4xxx_free_ddb(ha, ddb_entry);
+ iscsi_session_teardown(ddb_entry->sess);
+ }
+ }
+}
/**
* qla4xxx_remove_adapter - calback function to remove adapter.
* @pci_dev: PCI device pointer
@@ -1867,8 +4436,13 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
if (!is_qla8022(ha))
qla4xxx_prevent_other_port_reinit(ha);
- /* remove devs from iscsi_sessions to scsi_devices */
- qla4xxx_free_ddb_list(ha);
+ /* destroy iface from sysfs */
+ qla4xxx_destroy_ifaces(ha);
+
+ if ((!ql4xdisablesysfsboot) && ha->boot_kset)
+ iscsi_boot_destroy_kset(ha->boot_kset);
+
+ qla4xxx_destroy_fw_ddb_session(ha);
scsi_remove_host(ha->host);
@@ -1907,10 +4481,15 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
static int qla4xxx_slave_alloc(struct scsi_device *sdev)
{
- struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
- struct ddb_entry *ddb = sess->dd_data;
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb;
int queue_depth = QL4_DEF_QDEPTH;
+ cls_sess = starget_to_session(sdev->sdev_target);
+ sess = cls_sess->dd_data;
+ ddb = sess->dd_data;
+
sdev->hostdata = ddb;
sdev->tagged_supported = 1;
@@ -2248,7 +4827,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
int return_status = FAILED;
struct scsi_qla_host *ha;
- ha = (struct scsi_qla_host *) cmd->device->host->hostdata;
+ ha = to_qla_host(cmd->device->host);
if (ql4xdontresethba) {
DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
@@ -2284,6 +4863,110 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
return return_status;
}
+static int qla4xxx_context_reset(struct scsi_qla_host *ha)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ struct addr_ctrl_blk_def *acb = NULL;
+ uint32_t acb_len = sizeof(struct addr_ctrl_blk_def);
+ int rval = QLA_SUCCESS;
+ dma_addr_t acb_dma;
+
+ acb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk_def),
+ &acb_dma, GFP_KERNEL);
+ if (!acb) {
+ ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",
+ __func__);
+ rval = -ENOMEM;
+ goto exit_port_reset;
+ }
+
+ memset(acb, 0, acb_len);
+
+ rval = qla4xxx_get_acb(ha, acb_dma, PRIMARI_ACB, acb_len);
+ if (rval != QLA_SUCCESS) {
+ rval = -EIO;
+ goto exit_free_acb;
+ }
+
+ rval = qla4xxx_disable_acb(ha);
+ if (rval != QLA_SUCCESS) {
+ rval = -EIO;
+ goto exit_free_acb;
+ }
+
+ wait_for_completion_timeout(&ha->disable_acb_comp,
+ DISABLE_ACB_TOV * HZ);
+
+ rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);
+ if (rval != QLA_SUCCESS) {
+ rval = -EIO;
+ goto exit_free_acb;
+ }
+
+exit_free_acb:
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk_def),
+ acb, acb_dma);
+exit_port_reset:
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s %s\n", __func__,
+ rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));
+ return rval;
+}
+
+static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
+{
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ int rval = QLA_SUCCESS;
+
+ if (ql4xdontresethba) {
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n",
+ __func__));
+ rval = -EPERM;
+ goto exit_host_reset;
+ }
+
+ rval = qla4xxx_wait_for_hba_online(ha);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unable to reset host "
+ "adapter\n", __func__));
+ rval = -EIO;
+ goto exit_host_reset;
+ }
+
+ if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
+ goto recover_adapter;
+
+ switch (reset_type) {
+ case SCSI_ADAPTER_RESET:
+ set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ break;
+ case SCSI_FIRMWARE_RESET:
+ if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
+ if (is_qla8022(ha))
+ /* set firmware context reset */
+ set_bit(DPC_RESET_HA_FW_CONTEXT,
+ &ha->dpc_flags);
+ else {
+ rval = qla4xxx_context_reset(ha);
+ goto exit_host_reset;
+ }
+ }
+ break;
+ }
+
+recover_adapter:
+ rval = qla4xxx_recover_adapter(ha);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n",
+ __func__));
+ rval = -EIO;
+ }
+
+exit_host_reset:
+ return rval;
+}
+
/* PCI AER driver recovers from all correctable errors w/o
* driver intervention. For uncorrectable errors PCI AER
* driver calls the following device driver's callbacks
@@ -2360,7 +5043,8 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
if (test_bit(AF_ONLINE, &ha->flags)) {
clear_bit(AF_ONLINE, &ha->flags);
- qla4xxx_mark_all_devices_missing(ha);
+ clear_bit(AF_LINK_UP, &ha->flags);
+ iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
}
@@ -2407,7 +5091,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
qla4_8xxx_idc_unlock(ha);
clear_bit(AF_FW_RECOVERY, &ha->flags);
- rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
+ rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
qla4_8xxx_idc_lock(ha);
if (rval != QLA_SUCCESS) {
@@ -2443,8 +5127,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
QLA82XX_DEV_READY)) {
clear_bit(AF_FW_RECOVERY, &ha->flags);
- rval = qla4xxx_initialize_adapter(ha,
- PRESERVE_DDB_LIST);
+ rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
if (rval == QLA_SUCCESS) {
ret = qla4xxx_request_irqs(ha);
if (ret) {
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 6104928..5254e57 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.02.00-k7"
+#define QLA4XXX_DRIVER_VERSION "5.02.00-k9"
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index d92fe40..6b349e3 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -3000,7 +3000,11 @@ sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task
if ((target == -1 || cp->target == target) &&
(lun == -1 || cp->lun == lun) &&
(task == -1 || cp->tag == task)) {
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
sym_set_cam_status(cp->cmd, DID_SOFT_ERROR);
+#else
+ sym_set_cam_status(cp->cmd, DID_REQUEUE);
+#endif
sym_remque(&cp->link_ccbq);
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
}
diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h
index b7cf220..1d5cfe8 100644
--- a/drivers/sfi/sfi_core.h
+++ b/drivers/sfi/sfi_core.h
@@ -55,6 +55,9 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+#include <linux/sysfs.h>
+
struct sfi_table_key{
char *sig;
char *oem_id;
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
index 24e6cec..67e272a 100644
--- a/drivers/sh/Makefile
+++ b/drivers/sh/Makefile
@@ -7,3 +7,11 @@ obj-$(CONFIG_HAVE_CLK) += clk/
obj-$(CONFIG_MAPLE) += maple/
obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_GENERIC_GPIO) += pfc.o
+
+#
+# For the moment we only use this framework for ARM-based SH/R-Mobile
+# platforms and generic SH. SH-based SH-Mobile platforms are still using
+# an older framework that is pending up-porting, at which point this
+# special casing can go away.
+#
+obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index 7e9c399..db257a3 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -25,7 +25,6 @@
#include <linux/seq_file.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/debugfs.h>
#include <linux/cpufreq.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>
@@ -34,6 +33,9 @@ static LIST_HEAD(clock_list);
static DEFINE_SPINLOCK(clock_lock);
static DEFINE_MUTEX(clock_list_sem);
+/* clock disable operations are not passed on to hardware during boot */
+static int allow_disable;
+
void clk_rate_table_build(struct clk *clk,
struct cpufreq_frequency_table *freq_table,
int nr_freqs,
@@ -170,6 +172,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
return clk_rate_round_helper(&div_range_round);
}
+static long clk_rate_mult_range_iter(unsigned int pos,
+ struct clk_rate_round_data *rounder)
+{
+ return clk_get_rate(rounder->arg) * pos;
+}
+
+long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min,
+ unsigned int mult_max, unsigned long rate)
+{
+ struct clk_rate_round_data mult_range_round = {
+ .min = mult_min,
+ .max = mult_max,
+ .func = clk_rate_mult_range_iter,
+ .arg = clk_get_parent(clk),
+ .rate = rate,
+ };
+
+ return clk_rate_round_helper(&mult_range_round);
+}
+
int clk_rate_table_find(struct clk *clk,
struct cpufreq_frequency_table *freq_table,
unsigned long rate)
@@ -202,9 +224,6 @@ int clk_reparent(struct clk *child, struct clk *parent)
list_add(&child->sibling, &parent->children);
child->parent = parent;
- /* now do the debugfs renaming to reattach the child
- to the proper parent */
-
return 0;
}
@@ -228,7 +247,7 @@ static void __clk_disable(struct clk *clk)
return;
if (!(--clk->usecount)) {
- if (likely(clk->ops && clk->ops->disable))
+ if (likely(allow_disable && clk->ops && clk->ops->disable))
clk->ops->disable(clk);
if (likely(clk->parent))
__clk_disable(clk->parent);
@@ -393,7 +412,7 @@ int clk_register(struct clk *clk)
{
int ret;
- if (clk == NULL || IS_ERR(clk))
+ if (IS_ERR_OR_NULL(clk))
return -EINVAL;
/*
@@ -662,88 +681,24 @@ static int __init clk_syscore_init(void)
subsys_initcall(clk_syscore_init);
#endif
-/*
- * debugfs support to trace clock tree hierarchy and attributes
- */
-static struct dentry *clk_debugfs_root;
-
-static int clk_debugfs_register_one(struct clk *c)
-{
- int err;
- struct dentry *d, *child, *child_tmp;
- struct clk *pa = c->parent;
- char s[255];
- char *p = s;
-
- p += sprintf(p, "%p", c);
- d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
- if (!d)
- return -ENOMEM;
- c->dentry = d;
-
- d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- return 0;
-
-err_out:
- d = c->dentry;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(c->dentry);
- return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
+static int __init clk_late_init(void)
{
- int err;
- struct clk *pa = c->parent;
-
- if (pa && !pa->dentry) {
- err = clk_debugfs_register(pa);
- if (err)
- return err;
- }
+ unsigned long flags;
+ struct clk *clk;
- if (!c->dentry) {
- err = clk_debugfs_register_one(c);
- if (err)
- return err;
- }
- return 0;
-}
+ /* disable all clocks with zero use count */
+ mutex_lock(&clock_list_sem);
+ spin_lock_irqsave(&clock_lock, flags);
-static int __init clk_debugfs_init(void)
-{
- struct clk *c;
- struct dentry *d;
- int err;
+ list_for_each_entry(clk, &clock_list, node)
+ if (!clk->usecount && clk->ops && clk->ops->disable)
+ clk->ops->disable(clk);
- d = debugfs_create_dir("clock", NULL);
- if (!d)
- return -ENOMEM;
- clk_debugfs_root = d;
+ /* from now on allow clock disable operations */
+ allow_disable = 1;
- list_for_each_entry(c, &clock_list, node) {
- err = clk_debugfs_register(c);
- if (err)
- goto err_out;
- }
+ spin_unlock_irqrestore(&clock_lock, flags);
+ mutex_unlock(&clock_list_sem);
return 0;
-err_out:
- debugfs_remove_recursive(clk_debugfs_root);
- return err;
}
-late_initcall(clk_debugfs_init);
+late_initcall(clk_late_init);
diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c
index f33e2dd..7b246ef 100644
--- a/drivers/sh/intc/chip.c
+++ b/drivers/sh/intc/chip.c
@@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
!defined(CONFIG_CPU_SUBTYPE_SH7709)
[IRQ_TYPE_LEVEL_HIGH] = VALID(3),
#endif
+#if defined(CONFIG_ARM) /* all recent SH-Mobile / R-Mobile ARM support this */
+ [IRQ_TYPE_EDGE_BOTH] = VALID(4),
+#endif
};
static int intc_set_type(struct irq_data *data, unsigned int type)
@@ -199,11 +202,16 @@ static int intc_set_type(struct irq_data *data, unsigned int type)
if (!value)
return -EINVAL;
+ value &= ~SENSE_VALID_FLAG;
+
ihp = intc_find_irq(d->sense, d->nr_sense, irq);
if (ihp) {
+ /* PINT has 2-bit sense registers, should fail on EDGE_BOTH */
+ if (value >= (1 << _INTC_WIDTH(ihp->handle)))
+ return -EINVAL;
+
addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
- intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle,
- value & ~SENSE_VALID_FLAG);
+ intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
}
return 0;
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index c6ca115..8b7a141 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -22,6 +22,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/interrupt.h>
#include <linux/sh_intc.h>
#include <linux/sysdev.h>
@@ -29,6 +30,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/radix-tree.h>
+#include <linux/export.h>
#include "internals.h"
LIST_HEAD(intc_list);
diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
index a3677c9..5fea1ee 100644
--- a/drivers/sh/intc/dynamic.c
+++ b/drivers/sh/intc/dynamic.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/bitmap.h>
#include <linux/spinlock.h>
+#include <linux/module.h>
#include "internals.h" /* only for activate_irq() damage.. */
/*
diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c
index e32304b..56bf933 100644
--- a/drivers/sh/intc/userimask.c
+++ b/drivers/sh/intc/userimask.c
@@ -13,6 +13,7 @@
#include <linux/sysdev.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/stat.h>
#include <asm/sizes.h>
#include "internals.h"
diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c
index 1e6e2d0..c7ec49f 100644
--- a/drivers/sh/intc/virq.c
+++ b/drivers/sh/intc/virq.c
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/radix-tree.h>
#include <linux/spinlock.h>
+#include <linux/export.h>
#include "internals.h"
static struct intc_map_entry intc_irq_xlate[NR_IRQS];
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 1e20604..bec81c2 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -20,6 +20,7 @@
#include <linux/maple.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <asm/cacheflush.h>
#include <asm/dma.h>
#include <asm/io.h>
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index 75934e3..e67fe17 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -217,7 +217,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
if (!r_width)
break;
- for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) {
+ for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) {
if (config_reg->enum_ids[n] == enum_id) {
*crp = config_reg;
*indexp = n;
@@ -577,6 +577,32 @@ static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
sh_gpio_set_value(chip_to_pinmux(chip), offset, value);
}
+static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct pinmux_info *gpioc = chip_to_pinmux(chip);
+ pinmux_enum_t enum_id;
+ pinmux_enum_t *enum_ids;
+ int i, k, pos;
+
+ pos = 0;
+ enum_id = 0;
+ while (1) {
+ pos = get_gpio_enum_id(gpioc, offset, pos, &enum_id);
+ if (pos <= 0 || !enum_id)
+ break;
+
+ for (i = 0; i < gpioc->gpio_irq_size; i++) {
+ enum_ids = gpioc->gpio_irq[i].enum_ids;
+ for (k = 0; enum_ids[k]; k++) {
+ if (enum_ids[k] == enum_id)
+ return gpioc->gpio_irq[i].irq;
+ }
+ }
+ }
+
+ return -ENOSYS;
+}
+
int register_pinmux(struct pinmux_info *pip)
{
struct gpio_chip *chip = &pip->chip;
@@ -592,6 +618,7 @@ int register_pinmux(struct pinmux_info *pip)
chip->get = sh_gpio_get;
chip->direction_output = sh_gpio_direction_output;
chip->set = sh_gpio_set;
+ chip->to_irq = sh_gpio_to_irq;
WARN_ON(pip->first_gpio != 0); /* needs testing */
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
index 744d3f6..bad7ba5 100644
--- a/drivers/ssb/b43_pci_bridge.c
+++ b/drivers/ssb/b43_pci_bridge.c
@@ -5,12 +5,13 @@
* because of its small size we include it in the SSB core
* instead of creating a standalone module.
*
- * Copyright 2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/pci.h>
+#include <linux/module.h>
#include <linux/ssb/ssb.h>
#include "ssb_private.h"
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 06d15b6..e9d2ca1 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -3,13 +3,14 @@
* Broadcom ChipCommon core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_regs.h>
+#include <linux/export.h>
#include <linux/pci.h>
#include "ssb_private.h"
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 305ade7..e5a2e0e 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -2,7 +2,7 @@
* Sonics Silicon Backplane
* Broadcom ChipCommon Power Management Unit driver
*
- * Copyright 2009, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2009, Michael Buesch <m@bues.ch>
* Copyright 2007, Broadcom Corporation
*
* Licensed under the GNU/GPL. See COPYING for details.
@@ -12,6 +12,7 @@
#include <linux/ssb/ssb_regs.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "ssb_private.h"
@@ -417,9 +418,9 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
u32 min_msk = 0, max_msk = 0;
unsigned int i;
const struct pmu_res_updown_tab_entry *updown_tab = NULL;
- unsigned int updown_tab_size;
+ unsigned int updown_tab_size = 0;
const struct pmu_res_depend_tab_entry *depend_tab = NULL;
- unsigned int depend_tab_size;
+ unsigned int depend_tab_size = 0;
switch (bus->chip_id) {
case 0x4312:
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index c3e1d3e6..dc47f30 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -3,7 +3,7 @@
* Broadcom EXTIF core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
* Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
* Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
*
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
index 5ba92a2..f30ea68 100644
--- a/drivers/ssb/driver_gige.c
+++ b/drivers/ssb/driver_gige.c
@@ -3,13 +3,14 @@
* Broadcom Gigabit Ethernet core driver
*
* Copyright 2008, Broadcom Corporation
- * Copyright 2008, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_gige.h>
+#include <linux/export.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/slab.h>
@@ -106,8 +107,9 @@ void gige_pcicfg_write32(struct ssb_gige *dev,
gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
}
-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int reg, int size, u32 *val)
+static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 *val)
{
struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
unsigned long flags;
@@ -136,8 +138,9 @@ static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int reg, int size, u32 val)
+static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 val)
{
struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
unsigned long flags;
@@ -166,7 +169,8 @@ static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+static int __devinit ssb_gige_probe(struct ssb_device *sdev,
+ const struct ssb_device_id *id)
{
struct ssb_gige *dev;
u32 base, tmslow, tmshigh;
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 97efce1..ced5015 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -3,7 +3,7 @@
* Broadcom MIPS core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index c828151..520e828 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -3,13 +3,14 @@
* Broadcom PCI-core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/ssb/ssb.h>
#include <linux/pci.h>
+#include <linux/export.h>
#include <linux/delay.h>
#include <linux/ssb/ssb_embedded.h>
@@ -314,7 +315,7 @@ int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return ssb_mips_irq(extpci_core->dev) + 2;
}
-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
{
u32 val;
@@ -379,7 +380,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
register_pci_controller(&ssb_pcicore_controller);
}
-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
+static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
{
struct ssb_bus *bus = pc->dev->bus;
u16 chipid_top;
@@ -412,7 +413,7 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
* Workarounds.
**************************************************/
-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
{
u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
@@ -514,7 +515,7 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
* Generic and Clientmode operation code.
**************************************************/
-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
{
struct ssb_device *pdev = pc->dev;
struct ssb_bus *bus = pdev->bus;
@@ -533,7 +534,7 @@ static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
}
}
-void ssb_pcicore_init(struct ssb_pcicore *pc)
+void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
{
struct ssb_device *dev = pc->dev;
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index a0e0d24..9ef124f 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -3,11 +3,12 @@
* Embedded systems support code
*
* Copyright 2005-2008, Broadcom Corporation
- * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/export.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/ssb/ssb_driver_pci.h>
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index f8a13f8..bb6317f 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -3,7 +3,7 @@
* Subsystem core
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_regs.h>
#include <linux/ssb/ssb_driver_gige.h>
@@ -557,7 +558,7 @@ error:
}
/* Needs ssb_buses_lock() */
-static int ssb_attach_queued_buses(void)
+static int __devinit ssb_attach_queued_buses(void)
{
struct ssb_bus *bus, *n;
int err = 0;
@@ -768,9 +769,9 @@ out:
return err;
}
-static int ssb_bus_register(struct ssb_bus *bus,
- ssb_invariants_func_t get_invariants,
- unsigned long baseaddr)
+static int __devinit ssb_bus_register(struct ssb_bus *bus,
+ ssb_invariants_func_t get_invariants,
+ unsigned long baseaddr)
{
int err;
@@ -851,8 +852,8 @@ err_disable_xtal:
}
#ifdef CONFIG_SSB_PCIHOST
-int ssb_bus_pcibus_register(struct ssb_bus *bus,
- struct pci_dev *host_pci)
+int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus,
+ struct pci_dev *host_pci)
{
int err;
@@ -875,9 +876,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register);
#endif /* CONFIG_SSB_PCIHOST */
#ifdef CONFIG_SSB_PCMCIAHOST
-int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
- struct pcmcia_device *pcmcia_dev,
- unsigned long baseaddr)
+int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+ struct pcmcia_device *pcmcia_dev,
+ unsigned long baseaddr)
{
int err;
@@ -897,8 +898,9 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
#ifdef CONFIG_SSB_SDIOHOST
-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
- unsigned int quirks)
+int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
+ struct sdio_func *func,
+ unsigned int quirks)
{
int err;
@@ -918,9 +920,9 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
-int ssb_bus_ssbbus_register(struct ssb_bus *bus,
- unsigned long baseaddr,
- ssb_invariants_func_t get_invariants)
+int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus,
+ unsigned long baseaddr,
+ ssb_invariants_func_t get_invariants)
{
int err;
@@ -1001,8 +1003,8 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
switch (plltype) {
case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
if (m & SSB_CHIPCO_CLK_T6_MMASK)
- return SSB_CHIPCO_CLK_T6_M0;
- return SSB_CHIPCO_CLK_T6_M1;
+ return SSB_CHIPCO_CLK_T6_M1;
+ return SSB_CHIPCO_CLK_T6_M0;
case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
@@ -1259,13 +1261,34 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
}
EXPORT_SYMBOL(ssb_device_disable);
+/* Some chipsets need routing known for PCIe and 64-bit DMA */
+static bool ssb_dma_translation_special_bit(struct ssb_device *dev)
+{
+ u16 chip_id = dev->bus->chip_id;
+
+ if (dev->id.coreid == SSB_DEV_80211) {
+ return (chip_id == 0x4322 || chip_id == 43221 ||
+ chip_id == 43231 || chip_id == 43222);
+ }
+
+ return 0;
+}
+
u32 ssb_dma_translation(struct ssb_device *dev)
{
switch (dev->bus->bustype) {
case SSB_BUSTYPE_SSB:
return 0;
case SSB_BUSTYPE_PCI:
- return SSB_PCI_DMA;
+ if (pci_is_pcie(dev->bus->host_pci) &&
+ ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) {
+ return SSB_PCIE_DMA_H32;
+ } else {
+ if (ssb_dma_translation_special_bit(dev))
+ return SSB_PCIE_DMA_H32;
+ else
+ return SSB_PCI_DMA;
+ }
default:
__ssb_dma_not_implemented(dev);
}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 7ad4858..34c3bab 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -1,7 +1,7 @@
/*
* Sonics Silicon Backplane PCI-Hostbus related functions.
*
- * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
@@ -734,12 +734,9 @@ out_free:
static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
struct ssb_boardinfo *bi)
{
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
- &bi->vendor);
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
- &bi->type);
- pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
- &bi->rev);
+ bi->vendor = bus->host_pci->subsystem_vendor;
+ bi->type = bus->host_pci->subsystem_device;
+ bi->rev = bus->host_pci->revision;
}
int ssb_pci_get_invariants(struct ssb_bus *bus,
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index f6c8c81..af5448f 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -6,12 +6,13 @@
* Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
- * Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+ * Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/pci.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/ssb/ssb.h>
@@ -53,8 +54,8 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
# define ssb_pcihost_resume NULL
#endif /* CONFIG_PM */
-static int ssb_pcihost_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int __devinit ssb_pcihost_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
struct ssb_bus *ssb;
int err = -ENOMEM;
@@ -110,7 +111,7 @@ static void ssb_pcihost_remove(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
}
-int ssb_pcihost_register(struct pci_driver *driver)
+int __devinit ssb_pcihost_register(struct pci_driver *driver)
{
driver->probe = ssb_pcihost_probe;
driver->remove = ssb_pcihost_remove;
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index f853379..c821c6b 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -3,7 +3,7 @@
* PCMCIA-Hostbus related functions
*
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 45e5bab..3e84487 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -2,7 +2,7 @@
* Sonics Silicon Backplane
* Bus scanning
*
- * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2007 Michael Buesch <m@bues.ch>
* Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
@@ -310,8 +310,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
} else {
if (bus->bustype == SSB_BUSTYPE_PCI) {
bus->chip_id = pcidev_to_chipid(bus->host_pci);
- pci_read_config_byte(bus->host_pci, PCI_REVISION_ID,
- &bus->chip_rev);
+ bus->chip_rev = bus->host_pci->revision;
bus->chip_package = 0;
} else {
bus->chip_id = 0x4710;
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index 65a6080..63fd709 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -6,7 +6,7 @@
*
* Based on drivers/ssb/pcmcia.c
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 45ff0e3..80d366f 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -2,7 +2,7 @@
* Sonics Silicon Backplane
* Common SPROM support routines
*
- * Copyright (C) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2008 Michael Buesch <m@bues.ch>
* Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 867dbf1..391b768 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -34,7 +34,7 @@ static int bcm_char_open(struct inode *inode, struct file * filp)
/* Store the Adapter structure */
filp->private_data = pTarang;
- /*Start Queuing the control response Packets*/
+ /* Start Queuing the control response Packets */
atomic_inc(&Adapter->ApplicationRunning);
nonseekable_open(inode, filp);
@@ -84,7 +84,7 @@ static int bcm_char_release(struct inode *inode, struct file *filp)
up(&Adapter->RxAppControlQueuelock);
- /*Stop Queuing the control response Packets*/
+ /* Stop Queuing the control response Packets */
atomic_dec(&Adapter->ApplicationRunning);
kfree(pTarang);
@@ -100,8 +100,8 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
PPER_TARANG_DATA pTarang = filp->private_data;
PMINI_ADAPTER Adapter = pTarang->Adapter;
struct sk_buff *Packet = NULL;
- ssize_t PktLen = 0;
- int wait_ret_val = 0;
+ ssize_t PktLen = 0;
+ int wait_ret_val = 0;
unsigned long ret = 0;
wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue,
@@ -157,1942 +157,1825 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
{
PPER_TARANG_DATA pTarang = filp->private_data;
void __user *argp = (void __user *)arg;
- PMINI_ADAPTER Adapter = pTarang->Adapter;
- INT Status = STATUS_FAILURE;
+ PMINI_ADAPTER Adapter = pTarang->Adapter;
+ INT Status = STATUS_FAILURE;
int timeout = 0;
- IOCTL_BUFFER IoBuffer;
+ IOCTL_BUFFER IoBuffer;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
- if(_IOC_TYPE(cmd) != BCM_IOCTL)
+ if (_IOC_TYPE(cmd) != BCM_IOCTL)
return -EFAULT;
- if(_IOC_DIR(cmd) & _IOC_READ)
+ if (_IOC_DIR(cmd) & _IOC_READ)
Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
- Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
+ Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
- Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
- if(Status)
+ if (Status)
return -EFAULT;
- if(Adapter->device_removed)
- {
+ if (Adapter->device_removed)
return -EFAULT;
- }
- if(FALSE == Adapter->fw_download_done)
- {
- switch (cmd)
- {
- case IOCTL_MAC_ADDR_REQ:
- case IOCTL_LINK_REQ:
- case IOCTL_CM_REQUEST:
- case IOCTL_SS_INFO_REQ:
- case IOCTL_SEND_CONTROL_MESSAGE:
- case IOCTL_IDLE_REQ:
- case IOCTL_BCM_GPIO_SET_REQUEST:
- case IOCTL_BCM_GPIO_STATUS_REQUEST:
- return -EACCES;
- default:
- break;
+ if (FALSE == Adapter->fw_download_done) {
+ switch (cmd) {
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ:
+ case IOCTL_BCM_GPIO_SET_REQUEST:
+ case IOCTL_BCM_GPIO_STATUS_REQUEST:
+ return -EACCES;
+ default:
+ break;
}
}
Status = vendorextnIoctl(Adapter, cmd, arg);
- if(Status != CONTINUE_COMMON_PATH )
- return Status;
+ if (Status != CONTINUE_COMMON_PATH)
+ return Status;
+
+ switch (cmd) {
+ /* Rdms for Swin Idle... */
+ case IOCTL_BCM_REGISTER_READ_PRIVATE: {
+ RDM_BUFFER sRdmBuffer = {0};
+ PCHAR temp_buff;
+ UINT Bufflen;
+ u16 temp_value;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- switch(cmd){
- // Rdms for Swin Idle...
- case IOCTL_BCM_REGISTER_READ_PRIVATE:
- {
- RDM_BUFFER sRdmBuffer = {0};
- PCHAR temp_buff;
- UINT Bufflen;
+ if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+ return -EINVAL;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- if (IoBuffer.InputLength > sizeof(sRdmBuffer))
- return -EINVAL;
+ if (IoBuffer.OutputLength > USHRT_MAX ||
+ IoBuffer.OutputLength == 0) {
+ return -EINVAL;
+ }
- if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ Bufflen = IoBuffer.OutputLength;
+ temp_value = 4 - (Bufflen % 4);
+ Bufflen += temp_value % 4;
- /* FIXME: need to restrict BuffLen */
- Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4;
- temp_buff = kmalloc(Bufflen, GFP_KERNEL);
- if(!temp_buff)
- return -ENOMEM;
+ temp_buff = kmalloc(Bufflen, GFP_KERNEL);
+ if (!temp_buff)
+ return -ENOMEM;
- Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
- (PUINT)temp_buff, Bufflen);
- if(Status == STATUS_SUCCESS)
- {
- if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
- Status = -EFAULT;
- }
-
- kfree(temp_buff);
- break;
+ Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
+ (PUINT)temp_buff, Bufflen);
+ if (Status == STATUS_SUCCESS) {
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
+ Status = -EFAULT;
}
- case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
- {
- WRM_BUFFER sWrmBuffer = {0};
- UINT uiTempVar=0;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ kfree(temp_buff);
+ break;
+ }
- if (IoBuffer.InputLength > sizeof(sWrmBuffer))
- return -EINVAL;
+ case IOCTL_BCM_REGISTER_WRITE_PRIVATE: {
+ WRM_BUFFER sWrmBuffer = {0};
+ UINT uiTempVar = 0;
+ /* Copy Ioctl Buffer structure */
- /* Get WrmBuffer structure */
- if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+ return -EINVAL;
- uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
- if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
- ((uiTempVar == EEPROM_REJECT_REG_1)||
+ /* Get WrmBuffer structure */
+ if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
(uiTempVar == EEPROM_REJECT_REG_2) ||
(uiTempVar == EEPROM_REJECT_REG_3) ||
- (uiTempVar == EEPROM_REJECT_REG_4)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
- return -EFAULT;
- }
- Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
- (PUINT)sWrmBuffer.Data, sizeof(ULONG));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"WRM Done\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
- Status = -EFAULT;
- }
- break;
+ (uiTempVar == EEPROM_REJECT_REG_4))) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ return -EFAULT;
}
- case IOCTL_BCM_REGISTER_READ:
- case IOCTL_BCM_EEPROM_REGISTER_READ:
- {
- RDM_BUFFER sRdmBuffer = {0};
- PCHAR temp_buff = NULL;
- UINT uiTempVar = 0;
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n");
- return -EACCES;
- }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sizeof(ULONG));
- if (IoBuffer.InputLength > sizeof(sRdmBuffer))
- return -EINVAL;
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ break;
+ }
- if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ case IOCTL_BCM_REGISTER_READ:
+ case IOCTL_BCM_EEPROM_REGISTER_READ: {
+ RDM_BUFFER sRdmBuffer = {0};
+ PCHAR temp_buff = NULL;
+ UINT uiTempVar = 0;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n");
+ return -EACCES;
+ }
- /* FIXME: don't trust user supplied length */
- temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
- if(!temp_buff)
- return STATUS_FAILURE;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
- ((ULONG)sRdmBuffer.Register & 0x3))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n",
- (int)sRdmBuffer.Register);
- return -EINVAL;
- }
+ if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+ return -EINVAL;
+
+ if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ /* FIXME: don't trust user supplied length */
+ temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
+ if (!temp_buff)
+ return STATUS_FAILURE;
- uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
- Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register,
- (PUINT)temp_buff, IoBuffer.OutputLength);
- if(Status == STATUS_SUCCESS)
- if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
- Status = -EFAULT;
+ if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+ ((ULONG)sRdmBuffer.Register & 0x3)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n",
+ (int)sRdmBuffer.Register);
kfree(temp_buff);
- break;
+ return -EINVAL;
}
- case IOCTL_BCM_REGISTER_WRITE:
- case IOCTL_BCM_EEPROM_REGISTER_WRITE:
- {
- WRM_BUFFER sWrmBuffer = {0};
- UINT uiTempVar=0;
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n");
- return -EACCES;
- }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
+ Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);
- if (IoBuffer.InputLength > sizeof(sWrmBuffer))
- return -EINVAL;
+ if (Status == STATUS_SUCCESS)
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
+ Status = -EFAULT;
- /* Get WrmBuffer structure */
- if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ kfree(temp_buff);
+ break;
+ }
+ case IOCTL_BCM_REGISTER_WRITE:
+ case IOCTL_BCM_EEPROM_REGISTER_WRITE: {
+ WRM_BUFFER sWrmBuffer = {0};
+ UINT uiTempVar = 0;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n");
+ return -EACCES;
+ }
- if( (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
- ((ULONG)sWrmBuffer.Register & 0x3) )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n",
- (int)sWrmBuffer.Register);
- return -EINVAL;
- }
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+ return -EINVAL;
- uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
- if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
- ((uiTempVar == EEPROM_REJECT_REG_1)||
+ /* Get WrmBuffer structure */
+ if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+ ((ULONG)sWrmBuffer.Register & 0x3)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register);
+ return -EINVAL;
+ }
+
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
(uiTempVar == EEPROM_REJECT_REG_2) ||
(uiTempVar == EEPROM_REJECT_REG_3) ||
(uiTempVar == EEPROM_REJECT_REG_4)) &&
- (cmd == IOCTL_BCM_REGISTER_WRITE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ (cmd == IOCTL_BCM_REGISTER_WRITE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
return -EFAULT;
- }
+ }
- Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
- (PUINT)sWrmBuffer.Data, sWrmBuffer.Length);
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
- Status = -EFAULT;
- }
+ Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sWrmBuffer.Length);
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ break;
+ }
+ case IOCTL_BCM_GPIO_SET_REQUEST: {
+ UCHAR ucResetValue[4];
+ UINT value = 0;
+ UINT uiBit = 0;
+ UINT uiOperation = 0;
+
+ GPIO_INFO gpio_info = {0};
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode");
+ return -EACCES;
+ }
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_info))
+ return -EINVAL;
+
+ if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiBit = gpio_info.uiGpioNumber;
+ uiOperation = gpio_info.uiGpioValue;
+ value = (1<<uiBit);
+
+ if (IsReqGpioIsLedInNVM(Adapter, value) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!", value);
+ Status = -EINVAL;
break;
}
- case IOCTL_BCM_GPIO_SET_REQUEST:
- {
- UCHAR ucResetValue[4];
- UINT value =0;
- UINT uiBit = 0;
- UINT uiOperation = 0;
-
- GPIO_INFO gpio_info = {0};
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode");
- return -EACCES;
- }
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_info))
- return -EINVAL;
- if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
- uiBit = gpio_info.uiGpioNumber;
- uiOperation = gpio_info.uiGpioValue;
- value= (1<<uiBit);
+ /* Set - setting 1 */
+ if (uiOperation) {
+ /* Set the gpio output register */
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, (PUINT)(&value), sizeof(UINT));
- if(IsReqGpioIsLedInNVM(Adapter,value) ==FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",value);
- Status = -EINVAL;
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to set the %dth GPIO\n", uiBit);
+ break;
+ }
+ } else {
+ /* Set the gpio output register */
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)(&value), sizeof(UINT));
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to clear the %dth GPIO\n", uiBit);
break;
}
+ }
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
- if(uiOperation)//Set - setting 1
- {
- //Set the gpio output register
- Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG ,
- (PUINT)(&value), sizeof(UINT));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to set the %dth GPIO \n",uiBit);
- break;
- }
- }
- else//Unset - setting 0
- {
- //Set the gpio output register
- Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG ,
- (PUINT)(&value), sizeof(UINT));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO bit\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to clear the %dth GPIO \n",uiBit);
- break;
- }
- }
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "GPIO_MODE_REGISTER read failed");
+ break;
+ }
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
- (PUINT)ucResetValue, sizeof(UINT));
- if (STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO_MODE_REGISTER read failed");
- break;
- }
- //Set the gpio mode register to output
- *(UINT*)ucResetValue |= (1<<uiBit);
- Status = wrmaltWithLock(Adapter,GPIO_MODE_REGISTER ,
+ /* Set the gpio mode register to output */
+ *(UINT *)ucResetValue |= (1<<uiBit);
+ Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
(PUINT)ucResetValue, sizeof(UINT));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO to output Mode\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n");
- break;
- }
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO to output Mode\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n");
+ break;
}
- break;
- case BCM_LED_THREAD_STATE_CHANGE_REQ:
- {
- USER_THREAD_REQ threadReq = { 0 };
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"User made LED thread InActive");
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode");
- Status = -EACCES;
- break;
- }
+ }
+ break;
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ case BCM_LED_THREAD_STATE_CHANGE_REQ: {
+ USER_THREAD_REQ threadReq = {0};
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive");
- if (IoBuffer.InputLength > sizeof(threadReq))
- return -EINVAL;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode");
+ Status = -EACCES;
+ break;
+ }
- //if LED thread is running(Actively or Inactively) set it state to make inactive
- if(Adapter->LEDInfo.led_thread_running)
- {
- if(threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Activating thread req");
- Adapter->DriverState = LED_THREAD_ACTIVE;
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DeActivating Thread req.....");
- Adapter->DriverState = LED_THREAD_INACTIVE;
- }
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- //signal thread.
- wake_up(&Adapter->LEDInfo.notify_led_event);
+ if (IoBuffer.InputLength > sizeof(threadReq))
+ return -EINVAL;
+
+ if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+ /* if LED thread is running(Actively or Inactively) set it state to make inactive */
+ if (Adapter->LEDInfo.led_thread_running) {
+ if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Activating thread req");
+ Adapter->DriverState = LED_THREAD_ACTIVE;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DeActivating Thread req.....");
+ Adapter->DriverState = LED_THREAD_INACTIVE;
}
+
+ /* signal thread. */
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
- break;
- case IOCTL_BCM_GPIO_STATUS_REQUEST:
- {
- ULONG uiBit = 0;
- UCHAR ucRead[4];
- GPIO_INFO gpio_info = {0};
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- return -EACCES;
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_info))
- return -EINVAL;
- if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
- uiBit = gpio_info.uiGpioNumber;
- //Set the gpio output register
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
- (PUINT)ucRead, sizeof(UINT));
- if(Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
- return Status;
- }
+ }
+ break;
- }
- break;
- case IOCTL_BCM_GPIO_MULTI_REQUEST:
- {
- UCHAR ucResetValue[4];
- GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
- PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
-
- memset( pgpio_multi_info, 0, MAX_IDX * sizeof( GPIO_MULTI_INFO));
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- return -EINVAL;
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_multi_info))
- return -EINVAL;
- if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ case IOCTL_BCM_GPIO_STATUS_REQUEST: {
+ ULONG uiBit = 0;
+ UCHAR ucRead[4];
+ GPIO_INFO gpio_info = {0};
- if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap);
- Status = -EINVAL;
- break;
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EACCES;
- /* Set the gpio output register */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if( ( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
- ( pgpio_multi_info[WIMAX_IDX].uiGPIOCommand))
- {
- /* Set 1's in GPIO OUTPUT REGISTER */
- *(UINT*) ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
- pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
- pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
+ if (IoBuffer.InputLength > sizeof(gpio_info))
+ return -EINVAL;
- if( *(UINT*) ucResetValue)
- Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_SET_REG , (PUINT) ucResetValue, sizeof(ULONG));
+ if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- if( Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
- return Status;
- }
+ uiBit = gpio_info.uiGpioNumber;
+
+ /* Set the gpio output register */
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+ (PUINT)ucRead, sizeof(UINT));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
+ return Status;
+ }
+ }
+ break;
- /* Clear to 0's in GPIO OUTPUT REGISTER */
- *(UINT*) ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
- pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
- ( ~( pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
+ case IOCTL_BCM_GPIO_MULTI_REQUEST: {
+ UCHAR ucResetValue[4];
+ GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
+ PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
- if( *(UINT*) ucResetValue)
- Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_CLR_REG , (PUINT) ucResetValue, sizeof(ULONG));
+ memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO));
- if( Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed." );
- return Status;
- }
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EINVAL;
- if( pgpio_multi_info[WIMAX_IDX].uiGPIOMask)
- {
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if(Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM to GPIO_PIN_STATE_REGISTER Failed.");
- return Status;
- }
+ if (IoBuffer.InputLength > sizeof(gpio_multi_info))
+ return -EINVAL;
- pgpio_multi_info[WIMAX_IDX].uiGPIOValue = ( *(UINT*)ucResetValue &
- pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
- }
+ if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status);
- break;
- }
- }
+ if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
+ Status = -EINVAL;
break;
- case IOCTL_BCM_GPIO_MODE_REQUEST:
- {
- UCHAR ucResetValue[4];
- GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
- PGPIO_MULTI_MODE pgpio_multi_mode = ( PGPIO_MULTI_MODE) gpio_multi_mode;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- return -EINVAL;
+ /* Set the gpio output register */
+ if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
+ (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
+ /* Set 1's in GPIO OUTPUT REGISTER */
+ *(UINT *)ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
- return -EINVAL;
- if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ if (*(UINT *) ucResetValue)
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG,
+ (PUINT)ucResetValue, sizeof(ULONG));
- Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT));
- if( STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Read of GPIO_MODE_REGISTER failed");
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
return Status;
}
- //Validating the request
- if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)== FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap);
- Status = -EINVAL;
- break;
- }
+ /* Clear to 0's in GPIO OUTPUT REGISTER */
+ *(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
- if( pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)
- {
- /* write all OUT's (1's) */
- *( UINT*) ucResetValue |= ( pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
- /* write all IN's (0's) */
- *( UINT*) ucResetValue &= ~( ( ~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
-
- /* Currently implemented return the modes of all GPIO's
- * else needs to bit AND with mask
- * */
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT*)ucResetValue;
-
- Status = wrmaltWithLock( Adapter, GPIO_MODE_REGISTER , ( PUINT) ucResetValue, sizeof( ULONG));
- if( Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM to GPIO_MODE_REGISTER Done");
- }
- else
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to GPIO_MODE_REGISTER Failed");
- Status = -EFAULT;
- break;
- }
- }
- else /* if uiGPIOMask is 0 then return mode register configuration */
- {
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *( UINT*) ucResetValue;
+ if (*(UINT *) ucResetValue)
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
+ return Status;
}
- Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status);
- break;
+ }
+
+ if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed.");
+ return Status;
}
+
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
}
- break;
- case IOCTL_MAC_ADDR_REQ:
- case IOCTL_LINK_REQ:
- case IOCTL_CM_REQUEST:
- case IOCTL_SS_INFO_REQ:
- case IOCTL_SEND_CONTROL_MESSAGE:
- case IOCTL_IDLE_REQ:
- {
- PVOID pvBuffer=NULL;
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed while copying Content to IOBufer for user space err:%d", Status);
+ break;
+ }
+ }
+ break;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ case IOCTL_BCM_GPIO_MODE_REQUEST: {
+ UCHAR ucResetValue[4];
+ GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
+ PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode;
- /* FIXME: don't accept any length from user */
- pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
- if(!pvBuffer)
- return -ENOMEM;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EINVAL;
- if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- {
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
+ return -EINVAL;
+
+ if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
+ return Status;
+ }
+
+ /* Validating the request */
+ if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
+ Status = -EINVAL;
+ break;
+ }
+
+ if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
+ /* write all OUT's (1's) */
+ *(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* write all IN's (0's) */
+ *(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* Currently implemented return the modes of all GPIO's
+ * else needs to bit AND with mask
+ */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+
+ Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG));
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "WRM to GPIO_MODE_REGISTER Done");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM to GPIO_MODE_REGISTER Failed");
Status = -EFAULT;
- kfree(pvBuffer);
break;
}
+ } else {
+/* if uiGPIOMask is 0 then return mode register configuration */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+ }
- down(&Adapter->LowPowerModeSync);
- Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
- !Adapter->bPreparingForLowPowerMode,
- (1 * HZ));
- if(Status == -ERESTARTSYS)
- goto cntrlEnd;
-
- if(Adapter->bPreparingForLowPowerMode)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Preparing Idle Mode is still True - Hence Rejecting control message\n");
- Status = STATUS_FAILURE ;
- goto cntrlEnd ;
- }
- Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
- cntrlEnd:
- up(&Adapter->LowPowerModeSync);
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed while copying Content to IOBufer for user space err:%d", Status);
+ break;
+ }
+ }
+ break;
+
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ: {
+ PVOID pvBuffer = NULL;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength < sizeof(struct link_request))
+ return -EINVAL;
+
+ if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE)
+ return -EINVAL;
+
+ pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
+ if (!pvBuffer)
+ return -ENOMEM;
+
+ if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
+ Status = -EFAULT;
kfree(pvBuffer);
break;
}
- case IOCTL_BCM_BUFFER_DOWNLOAD_START:
- {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ;
- if(NVMAccess)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
- return -EACCES;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
- if(!down_trylock(&Adapter->fw_download_sema))
- {
- Adapter->bBinDownloaded=FALSE;
- Adapter->fw_download_process_pid=current->pid;
- Adapter->bCfgDownloaded=FALSE;
- Adapter->fw_download_done=FALSE;
- netif_carrier_off(Adapter->dev);
- netif_stop_queue(Adapter->dev);
- Status = reset_card_proc(Adapter);
- if(Status)
- {
- pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
- }
- mdelay(10);
- }
- else
- {
- Status = -EBUSY;
+ down(&Adapter->LowPowerModeSync);
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
+ !Adapter->bPreparingForLowPowerMode,
+ (1 * HZ));
+ if (Status == -ERESTARTSYS)
+ goto cntrlEnd;
+
+ if (Adapter->bPreparingForLowPowerMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Preparing Idle Mode is still True - Hence Rejecting control message\n");
+ Status = STATUS_FAILURE;
+ goto cntrlEnd;
+ }
+ Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
+
+cntrlEnd:
+ up(&Adapter->LowPowerModeSync);
+ kfree(pvBuffer);
+ break;
+ }
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD_START: {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ Adapter->bBinDownloaded = FALSE;
+ Adapter->fw_download_process_pid = current->pid;
+ Adapter->bCfgDownloaded = FALSE;
+ Adapter->fw_download_done = FALSE;
+ netif_carrier_off(Adapter->dev);
+ netif_stop_queue(Adapter->dev);
+ Status = reset_card_proc(Adapter);
+ if (Status) {
+ pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
}
- up(&Adapter->NVMRdmWrmLock);
- break;
+ mdelay(10);
+ } else {
+ Status = -EBUSY;
}
- case IOCTL_BCM_BUFFER_DOWNLOAD:
- {
- FIRMWARE_INFO *psFwInfo = NULL;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
- do{
- if(!down_trylock(&Adapter->fw_download_sema))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n");
- Status=-EINVAL;
- break;
- }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD: {
+ FIRMWARE_INFO *psFwInfo = NULL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+ do {
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Invalid way to download buffer. Use Start and then call this!!!\n");
+ Status = -EINVAL;
+ break;
+ }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n",
- IoBuffer.InputLength);
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO))
- return -EINVAL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length for FW DLD is : %lx\n", IoBuffer.InputLength);
- psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
- if(!psFwInfo)
- return -ENOMEM;
+ if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO))
+ return -EINVAL;
- if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
+ if (!psFwInfo)
+ return -ENOMEM;
- if(!psFwInfo->pvMappedFirmwareAddress ||
- (psFwInfo->u32FirmwareLength == 0))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
- psFwInfo->u32FirmwareLength);
- Status = -EINVAL;
- break;
- }
- Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
- if(Status != STATUS_SUCCESS)
- {
- if(psFwInfo->u32StartingAddress==CONFIG_BEGIN_ADDR)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
- }
- //up(&Adapter->fw_download_sema);
+ if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
- Adapter->DriverState = DRIVER_INIT;
- Adapter->LEDInfo.bLedInitDone = FALSE;
- wake_up(&Adapter->LEDInfo.notify_led_event);
- }
- }
- break ;
- }while(0);
+ if (!psFwInfo->pvMappedFirmwareAddress ||
+ (psFwInfo->u32FirmwareLength == 0)) {
- if(Status != STATUS_SUCCESS)
- up(&Adapter->fw_download_sema);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
- kfree(psFwInfo);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
+ psFwInfo->u32FirmwareLength);
+ Status = -EINVAL;
break;
}
- case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
- {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
- if(NVMAccess)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " FW download blocked as EEPROM Read/Write is in progress\n");
- up(&Adapter->fw_download_sema);
- return -EACCES;
- }
- if(down_trylock(&Adapter->fw_download_sema))
- {
- Adapter->bBinDownloaded=TRUE;
- Adapter->bCfgDownloaded=TRUE;
- atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
-
- Adapter->CurrNumRecvDescs=0;
- Adapter->downloadDDR = 0;
-
- //setting the Mips to Run
- Status = run_card_proc(Adapter);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
- }
+
+ Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
+
+ if (Status != STATUS_SUCCESS) {
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
else
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Firm Download Over...\n");
- mdelay(10);
- /* Wait for MailBox Interrupt */
- if(StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
- }
- timeout = 5*HZ;
- Adapter->waiting_to_fw_download_done = FALSE;
- wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
- Adapter->waiting_to_fw_download_done, timeout);
- Adapter->fw_download_process_pid=INVALID_PID;
- Adapter->fw_download_done=TRUE;
- atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
- Adapter->CurrNumRecvDescs = 0;
- Adapter->PrevNumRecvDescs = 0;
- atomic_set(&Adapter->cntrlpktCnt,0);
- Adapter->LinkUpStatus = 0;
- Adapter->LinkStatus = 0;
-
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
- Adapter->DriverState = FW_DOWNLOAD_DONE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
+
+ /* up(&Adapter->fw_download_sema); */
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = DRIVER_INIT;
+ Adapter->LEDInfo.bLedInitDone = FALSE;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
+ }
+ break;
- if(!timeout)
- {
- Status = -ENODEV;
- }
+ } while (0);
+
+ if (Status != STATUS_SUCCESS)
+ up(&Adapter->fw_download_sema);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
+ kfree(psFwInfo);
+ break;
+ }
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "FW download blocked as EEPROM Read/Write is in progress\n");
+ up(&Adapter->fw_download_sema);
+ return -EACCES;
+ }
+
+ if (down_trylock(&Adapter->fw_download_sema)) {
+ Adapter->bBinDownloaded = TRUE;
+ Adapter->bCfgDownloaded = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->downloadDDR = 0;
+
+ /* setting the Mips to Run */
+ Status = run_card_proc(Adapter);
+
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "Firm Download Over...\n");
}
- else
- {
- Status = -EINVAL;
+
+ mdelay(10);
+
+ /* Wait for MailBox Interrupt */
+ if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
+
+ timeout = 5*HZ;
+ Adapter->waiting_to_fw_download_done = FALSE;
+ wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
+ Adapter->waiting_to_fw_download_done, timeout);
+ Adapter->fw_download_process_pid = INVALID_PID;
+ Adapter->fw_download_done = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = FW_DOWNLOAD_DONE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
+
+ if (!timeout)
+ Status = -ENODEV;
+ } else {
+ Status = -EINVAL;
}
- case IOCTL_BE_BUCKET_SIZE:
- Status = 0;
- if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
- Status = -EFAULT;
- break;
- case IOCTL_RTPS_BUCKET_SIZE:
- Status = 0;
- if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+
+ case IOCTL_BE_BUCKET_SIZE:
+ Status = 0;
+ if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
+ Status = -EFAULT;
+ break;
+
+ case IOCTL_RTPS_BUCKET_SIZE:
+ Status = 0;
+ if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
+ Status = -EFAULT;
+ break;
+
+ case IOCTL_CHIP_RESET: {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+
+ down(&Adapter->RxAppControlQueuelock);
+ Status = reset_card_proc(Adapter);
+ flushAllAppQ();
+ up(&Adapter->RxAppControlQueuelock);
+ up(&Adapter->NVMRdmWrmLock);
+ ResetCounters(Adapter);
+ break;
+ }
+
+ case IOCTL_QOS_THRESHOLD: {
+ USHORT uiLoopIndex;
+
+ Status = 0;
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+ if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
+ (unsigned long __user *)arg)) {
Status = -EFAULT;
- break;
- case IOCTL_CHIP_RESET:
- {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
- if(NVMAccess)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
- return -EACCES;
+ break;
}
- down(&Adapter->RxAppControlQueuelock);
- Status = reset_card_proc(Adapter);
- flushAllAppQ();
- up(&Adapter->RxAppControlQueuelock);
- up(&Adapter->NVMRdmWrmLock);
- ResetCounters(Adapter);
- break;
}
- case IOCTL_QOS_THRESHOLD:
- {
- USHORT uiLoopIndex;
+ break;
+ }
- Status = 0;
- for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
- if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
- (unsigned long __user *)arg)) {
- Status = -EFAULT;
- break;
- }
- }
- break;
+ case IOCTL_DUMP_PACKET_INFO:
+ DumpPackInfo(Adapter);
+ DumpPhsRules(&Adapter->stBCMPhsContext);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_GET_PACK_INFO:
+ if (copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES))
+ return -EFAULT;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_SWITCH_TRANSFER_MODE: {
+ UINT uiData = 0;
+ if (copy_from_user(&uiData, argp, sizeof(UINT)))
+ return -EFAULT;
+
+ if (uiData) {
+ /* Allow All Packets */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
+ Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
+ } else {
+ /* Allow IP only Packets */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
}
+ Status = STATUS_SUCCESS;
+ break;
+ }
- case IOCTL_DUMP_PACKET_INFO:
+ case IOCTL_BCM_GET_DRIVER_VERSION: {
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- DumpPackInfo(Adapter);
- DumpPhsRules(&Adapter->stBCMPhsContext);
- Status = STATUS_SUCCESS;
- break;
+ if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength))
+ return -EFAULT;
+ Status = STATUS_SUCCESS;
+ break;
+ }
- case IOCTL_GET_PACK_INFO:
- if(copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES))
- return -EFAULT;
- Status = STATUS_SUCCESS;
+ case IOCTL_BCM_GET_CURRENT_STATUS: {
+ LINK_STATE link_state;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
+ Status = -EFAULT;
break;
- case IOCTL_BCM_SWITCH_TRANSFER_MODE:
- {
- UINT uiData = 0;
- if(copy_from_user(&uiData, argp, sizeof(UINT)))
- return -EFAULT;
+ }
- if(uiData) /* Allow All Packets */
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
- Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
- }
- else /* Allow IP only Packets */
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
- Adapter->TransferMode = IP_PACKET_ONLY_MODE;
- }
- Status = STATUS_SUCCESS;
+ if (IoBuffer.OutputLength != sizeof(link_state)) {
+ Status = -EINVAL;
break;
}
- case IOCTL_BCM_GET_DRIVER_VERSION:
- {
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ memset(&link_state, 0, sizeof(link_state));
+ link_state.bIdleMode = Adapter->IdleMode;
+ link_state.bShutdownMode = Adapter->bShutStatus;
+ link_state.ucLinkStatus = Adapter->LinkStatus;
- if(copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength))
- return -EFAULT;
- Status = STATUS_SUCCESS;
+ if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
+ Status = -EFAULT;
break;
}
- case IOCTL_BCM_GET_CURRENT_STATUS:
- {
- LINK_STATE link_state;
+ Status = STATUS_SUCCESS;
+ break;
+ }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
- Status = -EFAULT;
- break;
- }
- if (IoBuffer.OutputLength != sizeof(link_state)) {
- Status = -EINVAL;
- break;
- }
+ case IOCTL_BCM_SET_MAC_TRACING: {
+ UINT tracing_flag;
- memset(&link_state, 0, sizeof(link_state));
- link_state.bIdleMode = Adapter->IdleMode;
- link_state.bShutdownMode = Adapter->bShutStatus;
- link_state.ucLinkStatus = Adapter->LinkStatus;
+ /* copy ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if (copy_to_user(IoBuffer.OutputBuffer, &link_state,
- min_t(size_t, sizeof(link_state), IoBuffer.OutputLength)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
- Status = -EFAULT;
- break;
- }
- Status = STATUS_SUCCESS;
- break;
+ if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
+ return -EFAULT;
+
+ if (tracing_flag)
+ Adapter->pTarangs->MacTracingEnabled = TRUE;
+ else
+ Adapter->pTarangs->MacTracingEnabled = FALSE;
+ break;
+ }
+
+ case IOCTL_BCM_GET_DSX_INDICATION: {
+ ULONG ulSFId = 0;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Mismatch req: %lx needed is =0x%zx!!!",
+ IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
+ return -EINVAL;
}
- case IOCTL_BCM_SET_MAC_TRACING:
- {
- UINT tracing_flag;
-
- /* copy ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
-
- if(copy_from_user(&tracing_flag,IoBuffer.InputBuffer,sizeof(UINT)))
- return -EFAULT;
-
- if (tracing_flag)
- Adapter->pTarangs->MacTracingEnabled = TRUE;
- else
- Adapter->pTarangs->MacTracingEnabled = FALSE;
- break;
- }
- case IOCTL_BCM_GET_DSX_INDICATION:
- {
- ULONG ulSFId=0;
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,
- "Mismatch req: %lx needed is =0x%zx!!!",
- IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
- return -EINVAL;
- }
+ if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
+ return -EFAULT;
- if(copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId);
+ get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case IOCTL_BCM_GET_HOST_MIBS: {
+ PVOID temp_buff;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId );
- get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
- Status=STATUS_SUCCESS;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length Check failed %lu %zd\n",
+ IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS));
+ return -EINVAL;
}
- break;
- case IOCTL_BCM_GET_HOST_MIBS:
- {
- PVOID temp_buff;
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
+ temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL);
+ if (!temp_buff)
+ return STATUS_FAILURE;
- if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,
- "Length Check failed %lu %zd\n",
- IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS));
- return -EINVAL;
- }
+ Status = ProcessGetHostMibs(Adapter, temp_buff);
+ GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
- /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
- temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL);
- if(!temp_buff)
- return STATUS_FAILURE;
+ if (Status != STATUS_FAILURE)
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS)))
+ Status = -EFAULT;
- Status = ProcessGetHostMibs(Adapter, temp_buff);
- GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
+ kfree(temp_buff);
+ break;
+ }
- if (Status != STATUS_FAILURE)
- if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS)))
- Status = -EFAULT;
+ case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
+ if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ }
- kfree(temp_buff);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_BULK_WRM: {
+ PBULKWRM_BUFFER pBulkBuffer;
+ UINT uiTempVar = 0;
+ PCHAR pvBuffer = NULL;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
+ Status = -EACCES;
break;
}
- case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
- if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE==Adapter->IdleMode))
- {
- Adapter->usIdleModePattern = ABORT_IDLE_MODE;
- Adapter->bWakeUpDevice = TRUE;
- wake_up(&Adapter->process_rx_cntrlpkt);
- }
- Status = STATUS_SUCCESS;
- break;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- case IOCTL_BCM_BULK_WRM:
- {
- PBULKWRM_BUFFER pBulkBuffer;
- UINT uiTempVar=0;
- PCHAR pvBuffer = NULL;
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
- Status = -EACCES;
- break;
- }
+ /* FIXME: restrict length */
+ pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
+ if (!pvBuffer)
+ return -ENOMEM;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ /* Get WrmBuffer structure */
+ if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
+ kfree(pvBuffer);
+ Status = -EFAULT;
+ break;
+ }
- /* FIXME: restrict length */
- pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
- if(!pvBuffer)
- return -ENOMEM;
-
- /* Get WrmBuffer structure */
- if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- {
- kfree(pvBuffer);
- Status = -EFAULT;
- break;
- }
+ pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
- pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
+ if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
+ ((ULONG)pBulkBuffer->Register & 0x3)) {
+ kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
+ Status = -EINVAL;
+ break;
+ }
- if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
- ((ULONG)pBulkBuffer->Register & 0x3))
- {
- kfree(pvBuffer);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register);
- Status = -EINVAL;
- break;
- }
+ uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)) &&
+ (cmd == IOCTL_BCM_REGISTER_WRITE)) {
+ kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ Status = -EFAULT;
+ break;
+ }
- uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
- if(!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE)
- && ((uiTempVar == EEPROM_REJECT_REG_1)||
- (uiTempVar == EEPROM_REJECT_REG_2) ||
- (uiTempVar == EEPROM_REJECT_REG_3) ||
- (uiTempVar == EEPROM_REJECT_REG_4)) &&
- (cmd == IOCTL_BCM_REGISTER_WRITE))
- {
- kfree(pvBuffer);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n");
- Status = -EFAULT;
- break;
- }
+ if (pBulkBuffer->SwapEndian == FALSE)
+ Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+ else
+ Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
- if(pBulkBuffer->SwapEndian == FALSE)
- Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
- else
- Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+ if (Status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
- if(Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
- }
+ kfree(pvBuffer);
+ break;
+ }
- kfree(pvBuffer);
- break;
- }
+ case IOCTL_BCM_GET_NVM_SIZE:
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- case IOCTL_BCM_GET_NVM_SIZE:
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
return -EFAULT;
+ }
- if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) {
- if(copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
- return -EFAULT;
- }
- Status = STATUS_SUCCESS ;
- break;
+ Status = STATUS_SUCCESS;
+ break;
- case IOCTL_BCM_CAL_INIT :
+ case IOCTL_BCM_CAL_INIT: {
+ UINT uiSectorSize = 0 ;
+ if (Adapter->eNVMType == NVM_FLASH) {
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- {
- UINT uiSectorSize = 0 ;
- if(Adapter->eNVMType == NVM_FLASH)
- {
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
+ return -EFAULT;
- if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
+ if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
+ sizeof(UINT)))
+ return -EFAULT;
+ } else {
+ if (IsFlash2x(Adapter)) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, sizeof(UINT)))
return -EFAULT;
-
- if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE))
- {
- if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
- sizeof(UINT)))
- return -EFAULT;
- }
- else
- {
- if(IsFlash2x(Adapter))
- {
- if (copy_to_user(IoBuffer.OutputBuffer,
- &Adapter->uiSectorSize ,
- sizeof(UINT)))
- return -EFAULT;
- }
- else
- {
- if((TRUE == Adapter->bShutStatus) ||
- (TRUE == Adapter->IdleMode))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle/Shutdown Mode\n");
- return -EACCES;
- }
-
- Adapter->uiSectorSize = uiSectorSize ;
- BcmUpdateSectorSize(Adapter,Adapter->uiSectorSize);
- }
+ } else {
+ if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n");
+ return -EACCES;
}
- Status = STATUS_SUCCESS ;
- }
- else
- {
- Status = STATUS_FAILURE;
+
+ Adapter->uiSectorSize = uiSectorSize;
+ BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize);
}
}
- break;
- case IOCTL_BCM_SET_DEBUG :
-#ifdef DEBUG
- {
- USER_BCM_DBG_STATE sUserDebugState;
-
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG );
+ Status = STATUS_SUCCESS;
+ } else {
+ Status = STATUS_FAILURE;
+ }
+ }
+ break;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ case IOCTL_BCM_SET_DEBUG:
+#ifdef DEBUG
+ {
+ USER_BCM_DBG_STATE sUserDebugState;
- if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+ if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)))
+ return -EFAULT;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
sUserDebugState.OnOff, sUserDebugState.Type);
- //sUserDebugState.Subtype <<= 1;
- sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
-
- // Update new 'DebugState' in the Adapter
- Adapter->stDebugState.type |= sUserDebugState.Type;
- /* Subtype: A bitmap of 32 bits for Subtype per Type.
- * Valid indexes in 'subtype' array: 1,2,4,8
- * corresponding to valid Type values. Hence we can use the 'Type' field
- * as the index value, ignoring the array entries 0,3,5,6,7 !
- */
- if (sUserDebugState.OnOff)
- Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
- else
- Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
-
- BCM_SHOW_DEBUG_BITMAP(Adapter);
+ /* sUserDebugState.Subtype <<= 1; */
+ sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
+
+ /* Update new 'DebugState' in the Adapter */
+ Adapter->stDebugState.type |= sUserDebugState.Type;
+ /* Subtype: A bitmap of 32 bits for Subtype per Type.
+ * Valid indexes in 'subtype' array: 1,2,4,8
+ * corresponding to valid Type values. Hence we can use the 'Type' field
+ * as the index value, ignoring the array entries 0,3,5,6,7 !
+ */
+ if (sUserDebugState.OnOff)
+ Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
+ else
+ Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
- }
+ BCM_SHOW_DEBUG_BITMAP(Adapter);
+ }
#endif
+ break;
+
+ case IOCTL_BCM_NVM_READ:
+ case IOCTL_BCM_NVM_WRITE: {
+ NVM_READWRITE stNVMReadWrite;
+ PUCHAR pReadData = NULL;
+ ULONG ulDSDMagicNumInUsrBuff = 0;
+ struct timeval tv0, tv1;
+ memset(&tv0, 0, sizeof(struct timeval));
+ memset(&tv1, 0, sizeof(struct timeval));
+ if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
+ Status = -EFAULT;
break;
- case IOCTL_BCM_NVM_READ:
- case IOCTL_BCM_NVM_WRITE:
- {
- NVM_READWRITE stNVMReadWrite;
- PUCHAR pReadData = NULL;
- ULONG ulDSDMagicNumInUsrBuff = 0;
- struct timeval tv0, tv1;
- memset(&tv0,0,sizeof(struct timeval));
- memset(&tv1,0,sizeof(struct timeval));
- if((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0))
- {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
- Status = -EFAULT;
- break;
- }
+ }
- if(IsFlash2x(Adapter))
- {
- if((Adapter->eActiveDSD != DSD0) &&
- (Adapter->eActiveDSD != DSD1) &&
- (Adapter->eActiveDSD != DSD2))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"No DSD is active..hence NVM Command is blocked");
- return STATUS_FAILURE ;
- }
- }
+ if (IsFlash2x(Adapter)) {
+ if ((Adapter->eActiveDSD != DSD0) &&
+ (Adapter->eActiveDSD != DSD1) &&
+ (Adapter->eActiveDSD != DSD2)) {
- /* Copy Ioctl Buffer structure */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked");
+ return STATUS_FAILURE ;
+ }
+ }
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if(copy_from_user(&stNVMReadWrite,
- (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
- sizeof(NVM_READWRITE)))
- return -EFAULT;
+ if (copy_from_user(&stNVMReadWrite,
+ (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
+ sizeof(NVM_READWRITE)))
+ return -EFAULT;
- //
- // Deny the access if the offset crosses the cal area limit.
- //
- if((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize)
- {
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset ,
-// stNVMReadWrite.uiNumBytes);
- Status = STATUS_FAILURE;
- break;
- }
+ /*
+ * Deny the access if the offset crosses the cal area limit.
+ */
- pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
- if(!pReadData)
- return -ENOMEM;
+ if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) {
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */
+ Status = STATUS_FAILURE;
+ break;
+ }
- if(copy_from_user(pReadData, stNVMReadWrite.pBuffer,
- stNVMReadWrite.uiNumBytes))
- {
- Status = -EFAULT;
- kfree(pReadData);
- break;
- }
+ pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
+ if (!pReadData)
+ return -ENOMEM;
- do_gettimeofday(&tv0);
- if(IOCTL_BCM_NVM_READ == cmd)
- {
- down(&Adapter->NVMRdmWrmLock);
+ if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) {
+ Status = -EFAULT;
+ kfree(pReadData);
+ break;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return -EACCES;
- }
+ do_gettimeofday(&tv0);
+ if (IOCTL_BCM_NVM_READ == cmd) {
+ down(&Adapter->NVMRdmWrmLock);
- Status = BeceemNVMRead(Adapter, (PUINT)pReadData,
- stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
-
- up(&Adapter->NVMRdmWrmLock);
-
- if(Status != STATUS_SUCCESS)
- {
- kfree(pReadData);
- return Status;
- }
- if(copy_to_user(stNVMReadWrite.pBuffer,pReadData, stNVMReadWrite.uiNumBytes))
- {
- kfree(pReadData);
- Status = -EFAULT;
- }
- }
- else
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- down(&Adapter->NVMRdmWrmLock);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return -EACCES;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return -EACCES;
- }
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
+ up(&Adapter->NVMRdmWrmLock);
- Adapter->bHeaderChangeAllowed = TRUE ;
- if(IsFlash2x(Adapter))
- {
- /*
- New Requirement:-
- DSD section updation will be allowed in two case:-
- 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
- 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
- corrupted then user space program first modify the DSD header with valid DSD sig so
- that this as well as further write may be worthwhile.
-
- This restriction has been put assuming that if DSD sig is corrupted, DSD
- data won't be considered valid.
-
-
- */
- Status = BcmFlash2xCorruptSig(Adapter,Adapter->eActiveDSD);
- if(Status != STATUS_SUCCESS)
- {
- if(( (stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize ) ||
- (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input..");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return Status;
- }
-
- ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
- if(ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input..");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return Status;
- }
- }
- }
- Status = BeceemNVMWrite(Adapter, (PUINT )pReadData,
- stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
- if(IsFlash2x(Adapter))
- BcmFlash2xWriteSig(Adapter,Adapter->eActiveDSD);
+ if (Status != STATUS_SUCCESS) {
+ kfree(pReadData);
+ return Status;
+ }
- Adapter->bHeaderChangeAllowed = FALSE ;
+ if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) {
+ kfree(pReadData);
+ Status = -EFAULT;
+ }
+ } else {
+ down(&Adapter->NVMRdmWrmLock);
- up(&Adapter->NVMRdmWrmLock);
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return -EACCES;
+ }
- if(Status != STATUS_SUCCESS)
- {
+ Adapter->bHeaderChangeAllowed = TRUE;
+ if (IsFlash2x(Adapter)) {
+ /*
+ * New Requirement:-
+ * DSD section updation will be allowed in two case:-
+ * 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
+ * 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
+ * corrupted then user space program first modify the DSD header with valid DSD sig so
+ * that this as well as further write may be worthwhile.
+ *
+ * This restriction has been put assuming that if DSD sig is corrupted, DSD
+ * data won't be considered valid.
+ */
+
+ Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD);
+ if (Status != STATUS_SUCCESS) {
+ if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) ||
+ (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return Status;
+ }
+
+ ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
+ if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
kfree(pReadData);
return Status;
}
}
- do_gettimeofday(&tv1);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n",(tv1.tv_sec - tv0.tv_sec)*1000 +(tv1.tv_usec - tv0.tv_usec)/1000);
+ }
+
+ Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
+ if (IsFlash2x(Adapter))
+ BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
+
+ Adapter->bHeaderChangeAllowed = FALSE;
+ up(&Adapter->NVMRdmWrmLock);
+ if (Status != STATUS_SUCCESS) {
kfree(pReadData);
- Status = STATUS_SUCCESS;
+ return Status;
}
- break;
- case IOCTL_BCM_FLASH2X_SECTION_READ :
- {
-
- FLASH2X_READWRITE sFlash2xRead = {0};
- PUCHAR pReadBuff = NULL ;
- UINT NOB = 0;
- UINT BuffSize = 0;
- UINT ReadBytes = 0;
- UINT ReadOffset = 0;
- void __user *OutPutBuff;
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ do_gettimeofday(&tv1);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000);
- //Reading FLASH 2.x READ structure
- if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE)))
- return -EFAULT;
+ kfree(pReadData);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case IOCTL_BCM_FLASH2X_SECTION_READ: {
+ FLASH2X_READWRITE sFlash2xRead = {0};
+ PUCHAR pReadBuff = NULL ;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT ReadBytes = 0;
+ UINT ReadOffset = 0;
+ void __user *OutPutBuff;
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%x" ,sFlash2xRead.offset);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xRead.numOfBytes);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xRead.bVerify);
+ /* Reading FLASH 2.x READ structure */
+ if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
+ return -EFAULT;
- //This was internal to driver for raw read. now it has ben exposed to user space app.
- if(validateFlash2xReadWrite(Adapter,&sFlash2xRead) == FALSE)
- return STATUS_FAILURE ;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify);
- NOB = sFlash2xRead.numOfBytes;
- if(NOB > Adapter->uiSectorSize )
- BuffSize = Adapter->uiSectorSize;
- else
- BuffSize = NOB ;
+ /* This was internal to driver for raw read. now it has ben exposed to user space app. */
+ if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == FALSE)
+ return STATUS_FAILURE;
- ReadOffset = sFlash2xRead.offset ;
- OutPutBuff = IoBuffer.OutputBuffer;
+ NOB = sFlash2xRead.numOfBytes;
+ if (NOB > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB;
+ ReadOffset = sFlash2xRead.offset ;
+ OutPutBuff = IoBuffer.OutputBuffer;
+ pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
- pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
- if(pReadBuff == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
- return -ENOMEM;
- }
- down(&Adapter->NVMRdmWrmLock);
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadBuff);
- return -EACCES;
- }
+ if (pReadBuff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
+ return -ENOMEM;
+ }
+ down(&Adapter->NVMRdmWrmLock);
- while(NOB)
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if(NOB > Adapter->uiSectorSize )
- ReadBytes = Adapter->uiSectorSize;
- else
- ReadBytes = NOB;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EACCES;
+ }
+ while (NOB) {
+ if (NOB > Adapter->uiSectorSize)
+ ReadBytes = Adapter->uiSectorSize;
+ else
+ ReadBytes = NOB;
- //Reading the data from Flash 2.x
+ /* Reading the data from Flash 2.x */
+ Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status);
+ break;
+ }
- Status = BcmFlash2xBulkRead(Adapter,(PUINT)pReadBuff,sFlash2xRead.Section,ReadOffset,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Flash 2x read err with Status :%d", Status);
- break ;
- }
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes);
-
- Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status);
- break;
- }
- NOB = NOB - ReadBytes;
- if(NOB)
- {
- ReadOffset = ReadOffset + ReadBytes ;
- OutPutBuff = OutPutBuff + ReadBytes ;
- }
+ Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status);
+ break;
+ }
+ NOB = NOB - ReadBytes;
+ if (NOB) {
+ ReadOffset = ReadOffset + ReadBytes;
+ OutPutBuff = OutPutBuff + ReadBytes ;
+ }
+ }
- }
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadBuff);
-
- }
- break ;
- case IOCTL_BCM_FLASH2X_SECTION_WRITE :
- {
- FLASH2X_READWRITE sFlash2xWrite = {0};
- PUCHAR pWriteBuff;
- void __user *InputAddr;
- UINT NOB = 0;
- UINT BuffSize = 0;
- UINT WriteOffset = 0;
- UINT WriteBytes = 0;
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ }
+ break;
+
+ case IOCTL_BCM_FLASH2X_SECTION_WRITE: {
+ FLASH2X_READWRITE sFlash2xWrite = {0};
+ PUCHAR pWriteBuff;
+ void __user *InputAddr;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT WriteOffset = 0;
+ UINT WriteBytes = 0;
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- //First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite
- Adapter->bAllDSDWriteAllow = FALSE;
+ /* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */
+ Adapter->bAllDSDWriteAllow = FALSE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- //Reading FLASH 2.x READ structure
- if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
- return -EFAULT;
+ /* Reading FLASH 2.x READ structure */
+ if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
+ return -EFAULT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify);
- if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) &&
- (sFlash2xWrite.Section != VSA2) )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Only VSA write is allowed");
- return -EINVAL;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify);
+
+ if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed");
+ return -EINVAL;
+ }
- if(validateFlash2xReadWrite(Adapter,&sFlash2xWrite) == FALSE)
- return STATUS_FAILURE ;
+ if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == FALSE)
+ return STATUS_FAILURE;
- InputAddr = sFlash2xWrite.pDataBuff;
- WriteOffset = sFlash2xWrite.offset ;
- NOB = sFlash2xWrite.numOfBytes;
+ InputAddr = sFlash2xWrite.pDataBuff;
+ WriteOffset = sFlash2xWrite.offset;
+ NOB = sFlash2xWrite.numOfBytes;
- if(NOB > Adapter->uiSectorSize )
- BuffSize = Adapter->uiSectorSize;
- else
- BuffSize = NOB ;
+ if (NOB > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB ;
- pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
- if(pWriteBuff == NULL)
- return -ENOMEM;
+ pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
+ if (pWriteBuff == NULL)
+ return -ENOMEM;
- //extracting the remainder of the given offset.
- WriteBytes = Adapter->uiSectorSize ;
- if(WriteOffset % Adapter->uiSectorSize)
- WriteBytes =Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
- if(NOB < WriteBytes)
+ /* extracting the remainder of the given offset. */
+ WriteBytes = Adapter->uiSectorSize;
+ if (WriteOffset % Adapter->uiSectorSize)
+ WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
+
+ if (NOB < WriteBytes)
+ WriteBytes = NOB;
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ return -EACCES;
+ }
+
+ BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section);
+ do {
+ Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status);
+ break;
+ }
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
+
+ /* Writing the data from Flash 2.x */
+ Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify);
+
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
+ break;
+ }
+
+ NOB = NOB - WriteBytes;
+ if (NOB) {
+ WriteOffset = WriteOffset + WriteBytes;
+ InputAddr = InputAddr + WriteBytes;
+ if (NOB > Adapter->uiSectorSize)
+ WriteBytes = Adapter->uiSectorSize;
+ else
WriteBytes = NOB;
+ }
+ } while (NOB > 0);
- down(&Adapter->NVMRdmWrmLock);
+ BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section);
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ }
+ break;
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pWriteBuff);
- return -EACCES;
- }
+ case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: {
+ PFLASH2X_BITMAP psFlash2xBitMap;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
- BcmFlash2xCorruptSig(Adapter,sFlash2xWrite.Section);
- do
- {
- Status = copy_from_user(pWriteBuff,InputAddr,WriteBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status);
- break ;
- }
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes);
- //Writing the data from Flash 2.x
- Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pWriteBuff,sFlash2xWrite.Section,WriteOffset,WriteBytes,sFlash2xWrite.bVerify);
-
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status);
- break ;
- }
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- NOB = NOB - WriteBytes;
- if(NOB)
- {
- WriteOffset = WriteOffset + WriteBytes ;
- InputAddr = InputAddr + WriteBytes ;
- if(NOB > Adapter->uiSectorSize )
- WriteBytes = Adapter->uiSectorSize;
- else
- WriteBytes = NOB;
- }
+ if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
+ return -EINVAL;
+ psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
+ if (psFlash2xBitMap == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available");
+ return -ENOMEM;
+ }
- } while(NOB > 0);
- BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section);
- up(&Adapter->NVMRdmWrmLock);
- kfree(pWriteBuff);
- }
- break ;
- case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP :
- {
+ /* Reading the Flash Sectio Bit map */
+ down(&Adapter->NVMRdmWrmLock);
- PFLASH2X_BITMAP psFlash2xBitMap;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(psFlash2xBitMap);
+ return -EACCES;
+ }
- if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
- return -EINVAL;
+ BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
+ up(&Adapter->NVMRdmWrmLock);
+ if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)))
+ Status = -EFAULT;
- psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
- if(psFlash2xBitMap == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available");
- return -ENOMEM ;
- }
- //Reading the Flash Sectio Bit map
- down(&Adapter->NVMRdmWrmLock);
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(psFlash2xBitMap);
- return -EACCES;
- }
+ kfree(psFlash2xBitMap);
+ }
+ break;
- BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
- up(&Adapter->NVMRdmWrmLock);
- if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)))
- Status = -EFAULT;
-
- kfree(psFlash2xBitMap);
- }
- break ;
- case IOCTL_BCM_SET_ACTIVE_SECTION :
- {
- FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ case IOCTL_BCM_SET_ACTIVE_SECTION: {
+ FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- return Status;
- }
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
- return Status;
- }
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return Status;
+ }
- down(&Adapter->NVMRdmWrmLock);
+ Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+ return Status;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- return -EACCES;
- }
+ down(&Adapter->NVMRdmWrmLock);
- Status = BcmSetActiveSection(Adapter,eFlash2xSectionVal);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed to make it's priority Highest. Status %d", Status);
- }
- up(&Adapter->NVMRdmWrmLock);
- }
- break ;
- case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION :
- {
- //Right Now we are taking care of only DSD
- Adapter->bAllDSDWriteAllow = FALSE ;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
-
- Status = STATUS_SUCCESS ;
- }
- break ;
- case IOCTL_BCM_COPY_SECTION :
- {
- FLASH2X_COPY_SECTION sCopySectStrut = {0};
- Status = STATUS_SUCCESS;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called");
-
- Adapter->bAllDSDWriteAllow = FALSE ;
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
- return Status;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
- Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
- return Status;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
+ Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal);
+ if (Status)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status);
+ up(&Adapter->NVMRdmWrmLock);
+ }
+ break;
- if(IsSectionExistInFlash(Adapter,sCopySectStrut.SrcSection) == FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
- return -EINVAL;
- }
+ case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: {
+ /* Right Now we are taking care of only DSD */
+ Adapter->bAllDSDWriteAllow = FALSE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
+ Status = STATUS_SUCCESS;
+ }
+ break;
- if(IsSectionExistInFlash(Adapter,sCopySectStrut.DstSection) == FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
- return -EINVAL;
- }
+ case IOCTL_BCM_COPY_SECTION: {
+ FLASH2X_COPY_SECTION sCopySectStrut = {0};
+ Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called");
- if(sCopySectStrut.SrcSection == sCopySectStrut.DstSection)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Source and Destination section should be different");
- return -EINVAL;
- }
+ Adapter->bAllDSDWriteAllow = FALSE;
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- down(&Adapter->NVMRdmWrmLock);
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
+ return Status;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- return -EACCES;
- }
+ Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
+ return Status;
+ }
- if(sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2)
- {
- if(IsNonCDLessDevice(Adapter))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is Non-CDLess hence won't have ISO !!");
- Status = -EINVAL ;
- }
- else if(sCopySectStrut.numOfBytes == 0)
- {
- Status = BcmCopyISO(Adapter,sCopySectStrut);
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Partial Copy of ISO section is not Allowed..");
- Status = STATUS_FAILURE ;
- }
- up(&Adapter->NVMRdmWrmLock);
- return Status;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
- Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
- sCopySectStrut.DstSection,sCopySectStrut.offset,sCopySectStrut.numOfBytes);
- up(&Adapter->NVMRdmWrmLock);
- }
- break ;
- case IOCTL_BCM_GET_FLASH_CS_INFO :
- {
- Status = STATUS_SUCCESS;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
-
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- break;
- }
- if(Adapter->eNVMType != NVM_FLASH)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Connected device does not have flash");
- Status = -EINVAL;
- break;
- }
- if(IsFlash2x(Adapter) == TRUE)
- {
+ if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
+ return -EINVAL;
+ }
- if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO))
- return -EINVAL;
+ if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
+ return -EINVAL;
+ }
- if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)))
- return -EFAULT;
- }
- else
- {
- if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO))
- return -EINVAL;
+ if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different");
+ return -EINVAL;
+ }
- if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)))
- return -EFAULT;
+ down(&Adapter->NVMRdmWrmLock);
- }
- }
- break ;
- case IOCTL_BCM_SELECT_DSD :
- {
- UINT SectOfset = 0;
- FLASH2X_SECTION_VAL eFlash2xSectionVal;
- eFlash2xSectionVal = NO_SECTION_VAL ;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_SELECT_DSD Called");
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- return Status;
- }
- Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
- return Status;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal);
- if((eFlash2xSectionVal != DSD0) &&
- (eFlash2xSectionVal != DSD1) &&
- (eFlash2xSectionVal != DSD2) )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Passed section<%x> is not DSD section", eFlash2xSectionVal);
- return STATUS_FAILURE ;
- }
+ if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) {
+ if (IsNonCDLessDevice(Adapter)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!");
+ Status = -EINVAL;
+ } else if (sCopySectStrut.numOfBytes == 0) {
+ Status = BcmCopyISO(Adapter, sCopySectStrut);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed..");
+ Status = STATUS_FAILURE;
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+ }
- SectOfset= BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal);
- if(SectOfset == INVALID_OFFSET)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal);
- return -EINVAL;
- }
+ Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
+ sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes);
+ up(&Adapter->NVMRdmWrmLock);
+ }
+ break;
- Adapter->bAllDSDWriteAllow = TRUE ;
-
- Adapter->ulFlashCalStart = SectOfset ;
- Adapter->eActiveDSD = eFlash2xSectionVal;
- }
- Status = STATUS_SUCCESS ;
- break;
-
- case IOCTL_BCM_NVM_RAW_READ :
- {
-
- NVM_READWRITE stNVMRead;
- INT NOB ;
- INT BuffSize ;
- INT ReadOffset = 0;
- UINT ReadBytes = 0 ;
- PUCHAR pReadBuff;
- void __user *OutPutBuff;
-
- if(Adapter->eNVMType != NVM_FLASH)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"NVM TYPE is not Flash ");
- return -EINVAL ;
- }
+ case IOCTL_BCM_GET_FLASH_CS_INFO: {
+ Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
- Status = -EFAULT;
- break;
- }
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ break;
+ }
- if(copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,sizeof(NVM_READWRITE)))
- return -EFAULT;
+ if (Adapter->eNVMType != NVM_FLASH) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash");
+ Status = -EINVAL;
+ break;
+ }
- NOB = stNVMRead.uiNumBytes;
- //In Raw-Read max Buff size : 64MB
+ if (IsFlash2x(Adapter) == TRUE) {
+ if (IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO))
+ return -EINVAL;
- if(NOB > DEFAULT_BUFF_SIZE)
- BuffSize = DEFAULT_BUFF_SIZE;
- else
- BuffSize = NOB ;
+ if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)))
+ return -EFAULT;
+ } else {
+ if (IoBuffer.OutputLength < sizeof(FLASH_CS_INFO))
+ return -EINVAL;
- ReadOffset = stNVMRead.uiOffset;
- OutPutBuff = stNVMRead.pBuffer;
+ if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)))
+ return -EFAULT;
+ }
+ }
+ break;
- pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
- if(pReadBuff == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
- Status = -ENOMEM;
- break;
- }
- down(&Adapter->NVMRdmWrmLock);
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- kfree(pReadBuff);
- up(&Adapter->NVMRdmWrmLock);
- return -EACCES;
- }
+ case IOCTL_BCM_SELECT_DSD: {
+ UINT SectOfset = 0;
+ FLASH2X_SECTION_VAL eFlash2xSectionVal;
+ eFlash2xSectionVal = NO_SECTION_VAL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called");
- Adapter->bFlashRawRead = TRUE ;
- while(NOB)
- {
- if(NOB > DEFAULT_BUFF_SIZE )
- ReadBytes = DEFAULT_BUFF_SIZE;
- else
- ReadBytes = NOB;
-
- //Reading the data from Flash 2.x
- Status = BeceemNVMRead(Adapter,(PUINT)pReadBuff,ReadOffset,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status);
- break;
- }
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff,ReadBytes);
-
- Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status);
- break;
- }
- NOB = NOB - ReadBytes;
- if(NOB)
- {
- ReadOffset = ReadOffset + ReadBytes ;
- OutPutBuff = OutPutBuff + ReadBytes ;
- }
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return Status;
+ }
+ Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+ return Status;
+ }
- }
- Adapter->bFlashRawRead = FALSE ;
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadBuff);
- break ;
- }
-
- case IOCTL_BCM_CNTRLMSG_MASK:
- {
- ULONG RxCntrlMsgBitMask = 0 ;
-
- /* Copy Ioctl Buffer structure */
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space");
- Status = -EFAULT;
- break;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal);
+ if ((eFlash2xSectionVal != DSD0) &&
+ (eFlash2xSectionVal != DSD1) &&
+ (eFlash2xSectionVal != DSD2)) {
- if (IoBuffer.InputLength != sizeof(unsigned long)) {
- Status = -EINVAL;
- break;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal);
+ return STATUS_FAILURE;
+ }
- Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space");
- Status = -EFAULT;
- break;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
- pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask ;
- }
- break;
- case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
- {
- DEVICE_DRIVER_INFO DevInfo;
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
-
- DevInfo.MaxRDMBufferSize = BUFFER_4K;
- DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
- DevInfo.u32RxAlignmentCorrection = 0;
- DevInfo.u32NVMType = Adapter->eNVMType;
- DevInfo.u32InterfaceType = BCM_USB;
-
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
+ if (SectOfset == INVALID_OFFSET) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal);
+ return -EINVAL;
+ }
- if(IoBuffer.OutputLength < sizeof(DevInfo))
- return -EINVAL;
+ Adapter->bAllDSDWriteAllow = TRUE;
+ Adapter->ulFlashCalStart = SectOfset;
+ Adapter->eActiveDSD = eFlash2xSectionVal;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_NVM_RAW_READ: {
+ NVM_READWRITE stNVMRead;
+ INT NOB ;
+ INT BuffSize ;
+ INT ReadOffset = 0;
+ UINT ReadBytes = 0 ;
+ PUCHAR pReadBuff;
+ void __user *OutPutBuff;
+
+ if (Adapter->eNVMType != NVM_FLASH) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash");
+ return -EINVAL;
+ }
- if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
- return -EFAULT;
- }
- break ;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
+ Status = -EFAULT;
+ break;
+ }
- case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
- {
- ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
+ if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE)))
+ return -EFAULT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+ NOB = stNVMRead.uiNumBytes;
+ /* In Raw-Read max Buff size : 64MB */
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (NOB > DEFAULT_BUFF_SIZE)
+ BuffSize = DEFAULT_BUFF_SIZE;
+ else
+ BuffSize = NOB;
- if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
- return -EINVAL;
+ ReadOffset = stNVMRead.uiOffset;
+ OutPutBuff = stNVMRead.pBuffer;
- stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
+ pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
+ if (pReadBuff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
+ Status = -ENOMEM;
+ break;
+ }
+ down(&Adapter->NVMRdmWrmLock);
- if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)))
- return -EFAULT;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ kfree(pReadBuff);
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ Adapter->bFlashRawRead = TRUE;
+
+ while (NOB) {
+ if (NOB > DEFAULT_BUFF_SIZE)
+ ReadBytes = DEFAULT_BUFF_SIZE;
+ else
+ ReadBytes = NOB;
+
+ /* Reading the data from Flash 2.x */
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
+ break;
}
+
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
+
+ Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status);
+ break;
+ }
+ NOB = NOB - ReadBytes;
+ if (NOB) {
+ ReadOffset = ReadOffset + ReadBytes;
+ OutPutBuff = OutPutBuff + ReadBytes;
+ }
+ }
+ Adapter->bFlashRawRead = FALSE;
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ break;
+ }
+
+ case IOCTL_BCM_CNTRLMSG_MASK: {
+ ULONG RxCntrlMsgBitMask = 0;
+
+ /* Copy Ioctl Buffer structure */
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
+ Status = -EFAULT;
break;
+ }
- case IOCTL_CLOSE_NOTIFICATION:
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_CLOSE_NOTIFICATION");
+ if (IoBuffer.InputLength != sizeof(unsigned long)) {
+ Status = -EINVAL;
break;
+ }
- default:
- pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
- Status = STATUS_FAILURE;
+ Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space");
+ Status = -EFAULT;
break;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
+ pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
+ }
+ break;
+
+ case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: {
+ DEVICE_DRIVER_INFO DevInfo;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
+ memset(&DevInfo, 0, sizeof(DevInfo));
+ DevInfo.MaxRDMBufferSize = BUFFER_4K;
+ DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+ DevInfo.u32RxAlignmentCorrection = 0;
+ DevInfo.u32NVMType = Adapter->eNVMType;
+ DevInfo.u32InterfaceType = BCM_USB;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(DevInfo))
+ return -EINVAL;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
+ return -EFAULT;
+ }
+ break;
+
+ case IOCTL_BCM_TIME_SINCE_NET_ENTRY: {
+ ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
+ return -EINVAL;
+
+ stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)))
+ return -EFAULT;
+ }
+ break;
+
+ case IOCTL_CLOSE_NOTIFICATION:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_CLOSE_NOTIFICATION");
+ break;
+
+ default:
+ pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
+ Status = STATUS_FAILURE;
+ break;
}
return Status;
}
@@ -2107,8 +1990,6 @@ static const struct file_operations bcm_fops = {
.llseek = no_llseek,
};
-extern struct class *bcm_class;
-
int register_control_device_interface(PMINI_ADAPTER Adapter)
{
@@ -2122,8 +2003,8 @@ int register_control_device_interface(PMINI_ADAPTER Adapter)
}
Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL,
- MKDEV(Adapter->major, 0),
- Adapter, DEV_NAME);
+ MKDEV(Adapter->major, 0),
+ Adapter, DEV_NAME);
if (IS_ERR(Adapter->pstCreatedClassDevice)) {
pr_err(DRV_NAME ": class device create failed\n");
@@ -2141,3 +2022,4 @@ void unregister_control_device_interface(PMINI_ADAPTER Adapter)
unregister_chrdev(Adapter->major, DEV_NAME);
}
}
+
diff --git a/drivers/staging/bcm/Debug.h b/drivers/staging/bcm/Debug.h
index 3138729..420382d 100644
--- a/drivers/staging/bcm/Debug.h
+++ b/drivers/staging/bcm/Debug.h
@@ -131,7 +131,7 @@ DriverEntry.c, bcmfwup.c, ChipDetectTask.c, HaltnReset.c, InterfaceDDR.c */
// TODO - put PHS_SEND in Tx PHS_RECEIVE in Rx path ?
#define PHS_SEND (OTHERS<<16)
-#define PHS_RECIEVE (OTHERS<<17)
+#define PHS_RECEIVE (OTHERS<<17)
#define PHS_MODULE (OTHERS<<18)
#define INTF_INIT (OTHERS<<19)
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index df64acb..bcd86bb 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -1,204 +1,183 @@
#include "headers.h"
-
-int InterfaceFileDownload( PVOID arg,
- struct file *flp,
- unsigned int on_chip_loc)
+int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
{
- // unsigned int reg=0;
- mm_segment_t oldfs={0};
- int errno=0, len=0 /*,is_config_file = 0*/;
- loff_t pos=0;
+ /* unsigned int reg = 0; */
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0; /* ,is_config_file = 0 */
+ loff_t pos = 0;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
- //PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter;
- char *buff=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
-
- if(!buff)
- {
- return -ENOMEM;
- }
- while(1)
- {
- oldfs=get_fs(); set_fs(get_ds());
- len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
- set_fs(oldfs);
- if(len<=0)
- {
- if(len<0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
- errno=len;
- }
- else
- {
- errno = 0;
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
- }
- break;
- }
- //BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, buff, MAX_TRANSFER_CTRL_BYTE_USB);
- errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len) ;
- if(errno)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed! status: %d", errno);
- break;
+ /* PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; */
+ char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+
+ if (!buff)
+ return -ENOMEM;
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff,
+ MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ if (len <= 0) {
+ if (len < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, MP_INIT,
+ DBG_LVL_ALL, "len < 0");
+ errno = len;
+ } else {
+ errno = 0;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, MP_INIT,
+ DBG_LVL_ALL,
+ "Got end of file!");
+ }
+ break;
}
- on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB;
- }/* End of for(;;)*/
+ /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
+ * DBG_LVL_ALL, buff,
+ * MAX_TRANSFER_CTRL_BYTE_USB);
+ */
+ errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
+ if (errno) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "WRM Failed! status: %d", errno);
+ break;
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ }
kfree(buff);
- return errno;
+ return errno;
}
-int InterfaceFileReadbackFromChip( PVOID arg,
- struct file *flp,
- unsigned int on_chip_loc)
+int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc)
{
- char *buff, *buff_readback;
- unsigned int reg=0;
- mm_segment_t oldfs={0};
- int errno=0, len=0, is_config_file = 0;
- loff_t pos=0;
- static int fw_down = 0;
- INT Status = STATUS_SUCCESS;
+ char *buff, *buff_readback;
+ unsigned int reg = 0;
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0, is_config_file = 0;
+ loff_t pos = 0;
+ static int fw_down;
+ INT Status = STATUS_SUCCESS;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
- buff=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
- buff_readback=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
- if(!buff || !buff_readback)
- {
- kfree(buff);
- kfree(buff_readback);
+ buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
+ buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
+ if (!buff || !buff_readback) {
+ kfree(buff);
+ kfree(buff_readback);
- return -ENOMEM;
- }
+ return -ENOMEM;
+ }
- is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR)? 1:0;
+ is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
- while(1)
- {
- oldfs=get_fs(); set_fs(get_ds());
- len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
- set_fs(oldfs);
- fw_down++;
- if(len<=0)
- {
- if(len<0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
- errno=len;
- }
- else
- {
- errno = 0;
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
- }
- break;
- }
-
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ fw_down++;
+
+ if (len <= 0) {
+ if (len < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
+ errno = len;
+ } else {
+ errno = 0;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
+ }
+ break;
+ }
Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
- if(Status)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
+ if (Status) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
goto exit;
}
reg++;
- if((len-sizeof(unsigned int))<4)
- {
- if(memcmp(buff_readback, buff, len))
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT,DBG_LVL_ALL,"Length is: %d",len);
+ if ((len-sizeof(unsigned int)) < 4) {
+ if (memcmp(buff_readback, buff, len)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len);
Status = -EIO;
goto exit;
- }
- }
- else
- {
- len-=4;
- while(len)
- {
- if(*(unsigned int*)&buff_readback[len] != *(unsigned int *)&buff[len])
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
+ }
+ } else {
+ len -= 4;
+
+ while (len) {
+ if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
Status = -EIO;
goto exit;
- }
- len-=4;
- }
- }
- on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB;
- }/* End of while(1)*/
+ }
+ len -= 4;
+ }
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ } /* End of while(1) */
+
exit:
- kfree(buff);
- kfree(buff_readback);
+ kfree(buff);
+ kfree(buff_readback);
return Status;
}
-static int bcm_download_config_file(PMINI_ADAPTER Adapter,
- FIRMWARE_INFO *psFwInfo)
+static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
{
int retval = STATUS_SUCCESS;
B_UINT32 value = 0;
- if(Adapter->pstargetparams == NULL)
- {
- if((Adapter->pstargetparams =
- kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL)
- {
- return -ENOMEM;
- }
- }
- if(psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
- {
- return -EIO;
+ if (Adapter->pstargetparams == NULL) {
+ Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL)
+ return -ENOMEM;
}
- retval = copy_from_user(Adapter->pstargetparams,
- psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
- if(retval)
- {
+
+ if (psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
+ return -EIO;
+
+ retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
+ if (retval) {
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
return -EFAULT;
}
+
/* Parse the structure and then Download the Firmware */
beceem_parse_target_struct(Adapter);
- //Initializing the NVM.
+ /* Initializing the NVM. */
BcmInitNVM(Adapter);
+ retval = InitLedSettings(Adapter);
- retval = InitLedSettings (Adapter);
-
- if(retval)
- {
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
return retval;
}
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->LEDInfo.bLedInitDone = FALSE;
Adapter->DriverState = DRIVER_INIT;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = FW_DOWNLOAD;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
/* Initialize the DDR Controller */
retval = ddr_init(Adapter);
- if(retval)
- {
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
+ if (retval) {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
return retval;
}
@@ -206,197 +185,166 @@ static int bcm_download_config_file(PMINI_ADAPTER Adapter,
wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
- if(Adapter->eNVMType == NVM_FLASH)
- {
+ if (Adapter->eNVMType == NVM_FLASH) {
retval = PropagateCalParamsFromFlashToMemory(Adapter);
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"propagaion of cal param failed with status :%d", retval);
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval);
return retval;
}
}
+ retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(STARGETPARAMS), CONFIG_BEGIN_ADDR);
- retval =buffDnldVerify(Adapter,(PUCHAR)Adapter->pstargetparams,sizeof(STARGETPARAMS),CONFIG_BEGIN_ADDR);
-
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
- }
+ if (retval)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
else
Adapter->bCfgDownloaded = TRUE;
-
return retval;
}
-static int bcm_compare_buff_contents(unsigned char *readbackbuff,
- unsigned char *buff,unsigned int len)
+
+static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
{
int retval = STATUS_SUCCESS;
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- if((len-sizeof(unsigned int))<4)
- {
- if(memcmp(readbackbuff , buff, len))
- {
- retval=-EINVAL;
- }
- }
- else
- {
- len-=4;
- while(len)
- {
- if(*(unsigned int*)&readbackbuff[len] !=
- *(unsigned int *)&buff[len])
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
- retval=-EINVAL;
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if ((len-sizeof(unsigned int)) < 4) {
+ if (memcmp(readbackbuff , buff, len))
+ retval = -EINVAL;
+ } else {
+ len -= 4;
+
+ while (len) {
+ if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
+ retval = -EINVAL;
break;
}
- len-=4;
+ len -= 4;
}
}
return retval;
}
+
int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
{
int retval = STATUS_SUCCESS;
PUCHAR buff = NULL;
- /* Config File is needed for the Driver to download the Config file and
- Firmware. Check for the Config file to be first to be sent from the
- Application
- */
- atomic_set (&Adapter->uiMBupdate, FALSE);
- if(!Adapter->bCfgDownloaded &&
- psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR)
- {
- /*Can't Download Firmware.*/
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Download the config File first\n");
+ /* Config File is needed for the Driver to download the Config file and
+ * Firmware. Check for the Config file to be first to be sent from the
+ * Application
+ */
+ atomic_set(&Adapter->uiMBupdate, FALSE);
+ if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
+ /* Can't Download Firmware. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
return -EINVAL;
}
/* If Config File, Finish the DDR Settings and then Download CFG File */
- if(psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
- {
- retval = bcm_download_config_file (Adapter, psFwInfo);
- }
- else
- {
-
- buff = kzalloc(psFwInfo->u32FirmwareLength,GFP_KERNEL);
- if(buff==NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Failed in allocation memory");
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
+ retval = bcm_download_config_file(Adapter, psFwInfo);
+ } else {
+ buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
+ if (buff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory");
return -ENOMEM;
}
- retval = copy_from_user(buff,psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
- if(retval != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
+
+ retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
retval = -EFAULT;
- goto error ;
+ goto error;
}
retval = buffDnldVerify(Adapter,
buff,
psFwInfo->u32FirmwareLength,
psFwInfo->u32StartingAddress);
- if(retval != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"f/w download failed status :%d", retval);
+
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval);
goto error;
}
}
+
error:
kfree(buff);
return retval;
}
-static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength,
- ULONG u32StartingAddress)
+static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
{
-
- unsigned int len = 0;
+ unsigned int len = 0;
int retval = STATUS_SUCCESS;
len = u32FirmwareLength;
- while(u32FirmwareLength)
- {
- len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
- retval = wrm (Adapter, u32StartingAddress, mappedbuffer, len);
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
+ while (u32FirmwareLength) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
+
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
break;
}
- u32StartingAddress += len;
- u32FirmwareLength -= len;
- mappedbuffer +=len;
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
}
return retval;
-
}
-static INT buffRdbkVerify(PMINI_ADAPTER Adapter,
- PUCHAR mappedbuffer, UINT u32FirmwareLength,
- ULONG u32StartingAddress)
+static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
{
UINT len = u32FirmwareLength;
INT retval = STATUS_SUCCESS;
- PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB,GFP_KERNEL);
+ PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
- if(NULL == readbackbuff)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
+ if (NULL == readbackbuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
return -ENOMEM;
}
- while (u32FirmwareLength && !retval)
- {
- len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ while (u32FirmwareLength && !retval) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ retval = rdm(Adapter, u32StartingAddress, readbackbuff, len);
- retval = rdm (Adapter, u32StartingAddress, readbackbuff, len);
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d" ,retval);
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
break;
}
- if (STATUS_SUCCESS != (retval = bcm_compare_buff_contents (readbackbuff, mappedbuffer, len)))
- {
+ retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
+ if (STATUS_SUCCESS != retval)
break;
- }
- u32StartingAddress += len;
- u32FirmwareLength -= len;
- mappedbuffer +=len;
- }/* end of while (u32FirmwareLength && !retval) */
+
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
+
+ } /* end of while (u32FirmwareLength && !retval) */
kfree(readbackbuff);
return retval;
}
-INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
- unsigned long u32StartingAddress)
+INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress)
{
INT status = STATUS_SUCCESS;
- status = buffDnld(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress);
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer download failed");
+ status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed");
goto error;
}
- status= buffRdbkVerify(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress);
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer readback verifier failed");
+ status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed");
goto error;
}
error:
return status;
}
-
-
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index d78d5ef..3582535 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -4,10 +4,12 @@ static struct usb_device_id InterfaceUsbtable[] = {
{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) },
- { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SM250) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SYM) },
{ USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) },
{ USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) },
{ USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_TU25) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_226) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_326) },
{ }
};
MODULE_DEVICE_TABLE(usb, InterfaceUsbtable);
@@ -139,8 +141,7 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE);
}
-static int
-usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
int retval;
@@ -281,8 +282,9 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
int i = 0;
for (i = 0; i < MAXIMUM_USB_TCB; i++) {
- if ((psIntfAdapter->asUsbTcb[i].urb =
- usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
+ psIntfAdapter->asUsbTcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbTcb[i].urb == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Tx urb for index %d\n", i);
return -ENOMEM;
@@ -290,14 +292,17 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
}
for (i = 0; i < MAXIMUM_USB_RCB; i++) {
- if ((psIntfAdapter->asUsbRcb[i].urb =
- usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
+ psIntfAdapter->asUsbRcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbRcb[i].urb == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Rx urb for index %d\n", i);
return -ENOMEM;
}
- if ((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
- kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL) {
+
+ psIntfAdapter->asUsbRcb[i].urb->transfer_buffer = kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbRcb[i].urb->transfer_buffer == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Rx buffer for index %d\n", i);
return -ENOMEM;
@@ -389,32 +394,32 @@ static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descripto
static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd));
+ return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd));
+ return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd);
}
static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd));
+ return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd));
+ return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd);
}
static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd));
+ return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd));
+ return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
}
static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
@@ -462,7 +467,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
if (bBcm16 == TRUE) {
/* selecting alternate setting one as a default setting for High Speed modem. */
if (psIntfAdapter->bHighSpeedDevice)
- retval= usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1);
+ retval = usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1);
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
"BCM16 is applicable on this dongle\n");
if (retval || (psIntfAdapter->bHighSpeedDevice == FALSE)) {
@@ -497,7 +502,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
if ((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
/* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
UINT _uiData = ntohl(EP2_CFG_INT);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
"Reverting Bulk to INT as it is in Full Speed mode.\n");
BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter, (PUCHAR)&_uiData, 0x136, 4, TRUE);
}
@@ -579,7 +584,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
psIntfAdapter->sIntrOut.int_out_size = buffer_size;
psIntfAdapter->sIntrOut.int_out_endpointAddr = endpoint->bEndpointAddress;
psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval;
- psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size, GFP_KERNEL);
+ psIntfAdapter->sIntrOut.int_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!psIntfAdapter->sIntrOut.int_out_buffer) {
dev_err(&psIntfAdapter->udev->dev,
"could not allocate interrupt_out_buffer\n");
@@ -641,8 +646,8 @@ static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message)
static int InterfaceResume(struct usb_interface *intf)
{
PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf);
- mdelay(100);
+ mdelay(100);
psIntfAdapter->bSuspended = FALSE;
StartInterruptUrb(psIntfAdapter);
diff --git a/drivers/staging/bcm/InterfaceInit.h b/drivers/staging/bcm/InterfaceInit.h
index 058315a..6fa4f09 100644
--- a/drivers/staging/bcm/InterfaceInit.h
+++ b/drivers/staging/bcm/InterfaceInit.h
@@ -8,10 +8,11 @@
#define BCM_USB_PRODUCT_ID_T3 0x0300
#define BCM_USB_PRODUCT_ID_T3B 0x0210
#define BCM_USB_PRODUCT_ID_T3L 0x0220
-#define BCM_USB_PRODUCT_ID_SM250 0xbccd
#define BCM_USB_PRODUCT_ID_SYM 0x15E
#define BCM_USB_PRODUCT_ID_1901 0xe017
-#define BCM_USB_PRODUCT_ID_226 0x0132
+#define BCM_USB_PRODUCT_ID_226 0x0132 /* not sure if this is valid */
+#define BCM_USB_PRODUCT_ID_ZTE_226 0x172
+#define BCM_USB_PRODUCT_ID_ZTE_326 0x173 /* ZTE AX326 */
#define BCM_USB_PRODUCT_ID_ZTE_TU25 0x0007
#define BCM_USB_MINOR_BASE 192
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
index a51185b..61f878b 100644
--- a/drivers/staging/bcm/InterfaceMisc.c
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -1,246 +1,219 @@
#include "headers.h"
-INT
-InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
- UINT addr,
- PVOID buff,
- INT len)
+INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
int retval = 0;
- USHORT usRetries = 0 ;
- if(psIntfAdapter == NULL )
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL");
- return -EINVAL ;
+ USHORT usRetries = 0;
+
+ if (psIntfAdapter == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
+ return -EINVAL;
}
- if(psIntfAdapter->psAdapter->device_removed == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed");
+ if (psIntfAdapter->psAdapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
return -ENODEV;
}
- if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus");
+ if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus");
return -EACCES;
}
- if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed..");
+ if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
return -EACCES;
}
- psIntfAdapter->psAdapter->DeviceAccess = TRUE ;
+ psIntfAdapter->psAdapter->DeviceAccess = TRUE;
+
do {
retval = usb_control_msg(psIntfAdapter->udev,
- usb_rcvctrlpipe(psIntfAdapter->udev,0),
- 0x02,
- 0xC2,
- (addr & 0xFFFF),
- ((addr >> 16) & 0xFFFF),
- buff,
- len,
- 5000);
-
- usRetries++ ;
- if(-ENODEV == retval)
- {
- psIntfAdapter->psAdapter->device_removed =TRUE;
+ usb_rcvctrlpipe(psIntfAdapter->udev, 0),
+ 0x02,
+ 0xC2,
+ (addr & 0xFFFF),
+ ((addr >> 16) & 0xFFFF),
+ buff,
+ len,
+ 5000);
+
+ usRetries++;
+ if (-ENODEV == retval) {
+ psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
- }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) );
+ } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
- if(retval < 0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
- return retval;
- }
- else
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
- return STATUS_SUCCESS;
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries);
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ return retval;
+ } else {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ return STATUS_SUCCESS;
}
}
-INT
-InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
- UINT addr,
- PVOID buff,
- INT len)
+INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
int retval = 0;
- USHORT usRetries = 0 ;
+ USHORT usRetries = 0;
- if(psIntfAdapter == NULL )
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
+ if (psIntfAdapter == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
return -EINVAL;
}
- if(psIntfAdapter->psAdapter->device_removed == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed");
+ if (psIntfAdapter->psAdapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
return -ENODEV;
}
- if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus...");
+ if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus...");
return -EACCES;
}
- if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed..");
+ if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
return -EACCES;
}
- psIntfAdapter->psAdapter->DeviceAccess = TRUE ;
- do{
+
+ psIntfAdapter->psAdapter->DeviceAccess = TRUE;
+
+ do {
retval = usb_control_msg(psIntfAdapter->udev,
- usb_sndctrlpipe(psIntfAdapter->udev,0),
- 0x01,
- 0x42,
- (addr & 0xFFFF),
- ((addr >> 16) & 0xFFFF),
- buff,
- len,
- 5000);
-
- usRetries++ ;
- if(-ENODEV == retval)
- {
- psIntfAdapter->psAdapter->device_removed = TRUE ;
+ usb_sndctrlpipe(psIntfAdapter->udev, 0),
+ 0x01,
+ 0x42,
+ (addr & 0xFFFF),
+ ((addr >> 16) & 0xFFFF),
+ buff,
+ len,
+ 5000);
+
+ usRetries++;
+ if (-ENODEV == retval) {
+ psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
- }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES));
+ } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
- if(retval < 0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return retval;
- }
- else
- {
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
+ } else {
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
return STATUS_SUCCESS;
-
}
-
}
-INT
-BcmRDM(PVOID arg,
- UINT addr,
- PVOID buff,
- INT len)
+INT BcmRDM(PVOID arg,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
}
-INT
-BcmWRM(PVOID arg,
- UINT addr,
- PVOID buff,
- INT len)
+INT BcmWRM(PVOID arg,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
}
-
-
INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
{
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
- INT status = STATUS_SUCCESS ;
+ INT status = STATUS_SUCCESS;
/*
- usb_clear_halt - tells device to clear endpoint halt/stall condition
- @dev: device whose endpoint is halted
- @pipe: endpoint "pipe" being cleared
- @ Context: !in_interrupt ()
-
- usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
- This is used to clear halt conditions for bulk and interrupt endpoints only.
- Control and isochronous endpoints never halts.
-
- Any URBs queued for such an endpoint should normally be unlinked by the driver
- before clearing the halt condition.
-
- */
-
- //Killing all the submitted urbs to different end points.
+ * usb_clear_halt - tells device to clear endpoint halt/stall condition
+ * @dev: device whose endpoint is halted
+ * @pipe: endpoint "pipe" being cleared
+ * @ Context: !in_interrupt ()
+ *
+ * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
+ * This is used to clear halt conditions for bulk and interrupt endpoints only.
+ * Control and isochronous endpoints never halts.
+ *
+ * Any URBs queued for such an endpoint should normally be unlinked by the driver
+ * before clearing the halt condition.
+ *
+ */
+
+ /* Killing all the submitted urbs to different end points. */
Bcm_kill_all_URBs(psIntfAdapter);
+ /* clear the halted/stalled state for every end point */
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
- //clear the halted/stalled state for every end point
- status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sIntrIn.int_in_pipe);
- if(status != STATUS_SUCCESS)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
- status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkIn.bulk_in_pipe);
- if(status != STATUS_SUCCESS)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
- status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkOut.bulk_out_pipe);
- if(status != STATUS_SUCCESS)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
-
- return status ;
+ return status;
}
-
VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
{
struct urb *tempUrb = NULL;
UINT i;
- /**
- * usb_kill_urb - cancel a transfer request and wait for it to finish
- * @urb: pointer to URB describing a previously submitted request,
- * returns nothing as it is void returned API.
- *
- * This routine cancels an in-progress request. It is guaranteed that
- * upon return all completion handlers will have finished and the URB
- * will be totally idle and available for reuse
-
- * This routine may not be used in an interrupt context (such as a bottom
- * half or a completion handler), or when holding a spinlock, or in other
- * situations where the caller can't schedule().
- *
- **/
+ /*
+ * usb_kill_urb - cancel a transfer request and wait for it to finish
+ * @urb: pointer to URB describing a previously submitted request,
+ * returns nothing as it is void returned API.
+ *
+ * This routine cancels an in-progress request. It is guaranteed that
+ * upon return all completion handlers will have finished and the URB
+ * will be totally idle and available for reuse
+ *
+ * This routine may not be used in an interrupt context (such as a bottom
+ * half or a completion handler), or when holding a spinlock, or in other
+ * situations where the caller can't schedule().
+ *
+ */
/* Cancel submitted Interrupt-URB's */
- if(psIntfAdapter->psInterruptUrb != NULL)
- {
- if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
- usb_kill_urb(psIntfAdapter->psInterruptUrb);
+ if (psIntfAdapter->psInterruptUrb != NULL) {
+ if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
+ usb_kill_urb(psIntfAdapter->psInterruptUrb);
}
/* Cancel All submitted TX URB's */
- for(i = 0; i < MAXIMUM_USB_TCB; i++)
- {
+ for (i = 0; i < MAXIMUM_USB_TCB; i++) {
tempUrb = psIntfAdapter->asUsbTcb[i].urb;
- if(tempUrb)
- {
- if(tempUrb->status == -EINPROGRESS)
+ if (tempUrb) {
+ if (tempUrb->status == -EINPROGRESS)
usb_kill_urb(tempUrb);
}
}
- for(i = 0; i < MAXIMUM_USB_RCB; i++)
- {
+ for (i = 0; i < MAXIMUM_USB_RCB; i++) {
tempUrb = psIntfAdapter->asUsbRcb[i].urb;
- if(tempUrb)
- {
- if(tempUrb->status == -EINPROGRESS)
- usb_kill_urb(tempUrb);
+ if (tempUrb) {
+ if (tempUrb->status == -EINPROGRESS)
+ usb_kill_urb(tempUrb);
}
}
@@ -253,13 +226,12 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
VOID putUsbSuspend(struct work_struct *work)
{
- PS_INTERFACE_ADAPTER psIntfAdapter = NULL ;
- struct usb_interface *intf = NULL ;
- psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork);
- intf=psIntfAdapter->interface ;
+ PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
+ struct usb_interface *intf = NULL;
+ psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
+ intf = psIntfAdapter->interface;
- if(psIntfAdapter->bSuspended == FALSE)
+ if (psIntfAdapter->bSuspended == FALSE)
usb_autopm_put_interface(intf);
-
}
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c
index 806ef5d..d495828 100644
--- a/drivers/staging/bcm/InterfaceRx.c
+++ b/drivers/staging/bcm/InterfaceRx.c
@@ -157,7 +157,7 @@ static void read_bulk_callback(struct urb *urb)
{
/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
skb_pull(skb, ETH_HLEN);
- PHSRecieve(Adapter, pLeader->Vcid, skb, &skb->len,
+ PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
NULL,bHeaderSupressionEnabled);
if(!Adapter->PackInfo[QueueIndex].bEthCSSupport)
@@ -229,7 +229,7 @@ static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb)
/*
Function: InterfaceRx
-Description: This is the hardware specific Function for Recieveing
+Description: This is the hardware specific Function for Receiving
data packet/control packets from the device.
Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context
diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h
index feb3515..46ed99c 100644
--- a/drivers/staging/bcm/Macros.h
+++ b/drivers/staging/bcm/Macros.h
@@ -1,17 +1,17 @@
/*************************************
-* Macros.h
+* Macros.h
**************************************/
-#ifndef __MACROS_H__
+#ifndef __MACROS_H__
#define __MACROS_H__
-#define TX_TIMER_PERIOD 10 //10 msec
+#define TX_TIMER_PERIOD 10 /*10 msec*/
#define MAX_CLASSIFIERS 100
-//#define MAX_CLASSIFIERS_PER_SF 20
+/* #define MAX_CLASSIFIERS_PER_SF 20 */
#define MAX_TARGET_DSX_BUFFERS 24
-#define MAX_CNTRL_PKTS 100
-#define MAX_DATA_PKTS 200
-#define MAX_ETH_SIZE 1536
+#define MAX_CNTRL_PKTS 100
+#define MAX_DATA_PKTS 200
+#define MAX_ETH_SIZE 1536
#define MAX_CNTL_PKT_SIZE 2048
#define MTU_SIZE 1400
@@ -20,102 +20,102 @@
#define MAC_ADDR_REGISTER 0xbf60d000
-///////////Quality of Service///////////////////////////
-#define NO_OF_QUEUES 17
-#define HiPriority NO_OF_QUEUES-1
-#define LowPriority 0
-#define BE 2
-#define rtPS 4
-#define ERTPS 5
-#define UGS 6
-
-#define BE_BUCKET_SIZE 1024*1024*100 //32kb
-#define rtPS_BUCKET_SIZE 1024*1024*100 //8kb
-#define MAX_ALLOWED_RATE 1024*1024*100
-#define TX_PACKET_THRESHOLD 10
-#define XSECONDS 1*HZ
-#define DSC_ACTIVATE_REQUEST 248
-#define QUEUE_DEPTH_OFFSET 0x1fc01000
-#define MAX_DEVICE_DESC_SIZE 2040
-#define MAX_CTRL_QUEUE_LEN 100
-#define MAX_APP_QUEUE_LEN 200
-#define MAX_LATENCY_ALLOWED 0xFFFFFFFF
-#define DEFAULT_UG_INTERVAL 250
-#define DEFAULT_UGI_FACTOR 4
-
-#define DEFAULT_PERSFCOUNT 60
-#define MAX_CONNECTIONS 10
-#define MAX_CLASS_NAME_LENGTH 32
-
-#define ETH_LENGTH_OF_ADDRESS 6
-#define MAX_MULTICAST_ADDRESSES 32
-#define IP_LENGTH_OF_ADDRESS 4
-
-#define IP_PACKET_ONLY_MODE 0
-#define ETH_PACKET_TUNNELING_MODE 1
-
-////////////Link Request//////////////
-#define SET_MAC_ADDRESS_REQUEST 0
-#define SYNC_UP_REQUEST 1
-#define SYNCED_UP 2
-#define LINK_UP_REQUEST 3
-#define LINK_CONNECTED 4
-#define SYNC_UP_NOTIFICATION 2
-#define LINK_UP_NOTIFICATION 4
+/* Quality of Service */
+#define NO_OF_QUEUES 17
+#define HiPriority (NO_OF_QUEUES-1)
+#define LowPriority 0
+#define BE 2
+#define rtPS 4
+#define ERTPS 5
+#define UGS 6
+
+#define BE_BUCKET_SIZE (1024*1024*100) /* 32kb */
+#define rtPS_BUCKET_SIZE (1024*1024*100) /* 8kb */
+#define MAX_ALLOWED_RATE (1024*1024*100)
+#define TX_PACKET_THRESHOLD 10
+#define XSECONDS (1*HZ)
+#define DSC_ACTIVATE_REQUEST 248
+#define QUEUE_DEPTH_OFFSET 0x1fc01000
+#define MAX_DEVICE_DESC_SIZE 2040
+#define MAX_CTRL_QUEUE_LEN 100
+#define MAX_APP_QUEUE_LEN 200
+#define MAX_LATENCY_ALLOWED 0xFFFFFFFF
+#define DEFAULT_UG_INTERVAL 250
+#define DEFAULT_UGI_FACTOR 4
+
+#define DEFAULT_PERSFCOUNT 60
+#define MAX_CONNECTIONS 10
+#define MAX_CLASS_NAME_LENGTH 32
+
+#define ETH_LENGTH_OF_ADDRESS 6
+#define MAX_MULTICAST_ADDRESSES 32
+#define IP_LENGTH_OF_ADDRESS 4
+
+#define IP_PACKET_ONLY_MODE 0
+#define ETH_PACKET_TUNNELING_MODE 1
+
+/* Link Request */
+#define SET_MAC_ADDRESS_REQUEST 0
+#define SYNC_UP_REQUEST 1
+#define SYNCED_UP 2
+#define LINK_UP_REQUEST 3
+#define LINK_CONNECTED 4
+#define SYNC_UP_NOTIFICATION 2
+#define LINK_UP_NOTIFICATION 4
#define LINK_NET_ENTRY 0x0002
-#define HMC_STATUS 0x0004
+#define HMC_STATUS 0x0004
#define LINK_UP_CONTROL_REQ 0x83
#define STATS_POINTER_REQ_STATUS 0x86
#define NETWORK_ENTRY_REQ_PAYLOAD 198
-#define LINK_DOWN_REQ_PAYLOAD 226
+#define LINK_DOWN_REQ_PAYLOAD 226
#define SYNC_UP_REQ_PAYLOAD 228
-#define STATISTICS_POINTER_REQ 237
+#define STATISTICS_POINTER_REQ 237
#define LINK_UP_REQ_PAYLOAD 245
#define LINK_UP_ACK 246
#define STATS_MSG_SIZE 4
#define INDEX_TO_DATA 4
-#define GO_TO_IDLE_MODE_PAYLOAD 210
-#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211
-#define IDLE_MODE_SF_UPDATE_MSG 187
+#define GO_TO_IDLE_MODE_PAYLOAD 210
+#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211
+#define IDLE_MODE_SF_UPDATE_MSG 187
-#define SKB_RESERVE_ETHERNET_HEADER 16
-#define SKB_RESERVE_PHS_BYTES 32
+#define SKB_RESERVE_ETHERNET_HEADER 16
+#define SKB_RESERVE_PHS_BYTES 32
-#define IP_PACKET_ONLY_MODE 0
-#define ETH_PACKET_TUNNELING_MODE 1
+#define IP_PACKET_ONLY_MODE 0
+#define ETH_PACKET_TUNNELING_MODE 1
-#define ETH_CS_802_3 1
-#define ETH_CS_802_1Q_VLAN 3
-#define IPV4_CS 1
-#define IPV6_CS 2
-#define ETH_CS_MASK 0x3f
+#define ETH_CS_802_3 1
+#define ETH_CS_802_1Q_VLAN 3
+#define IPV4_CS 1
+#define IPV6_CS 2
+#define ETH_CS_MASK 0x3f
/** \brief Validity bit maps for TLVs in packet classification rule */
-#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0
-#define PKT_CLASSIFICATION_VLANID_VALID 1
+#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0
+#define PKT_CLASSIFICATION_VLANID_VALID 1
#ifndef MIN
-#define MIN(_a, _b) ((_a) < (_b)? (_a): (_b))
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
/*Leader related terms */
-#define LEADER_STATUS 0x00
-#define LEADER_STATUS_TCP_ACK 0x1
-#define LEADER_SIZE sizeof(LEADER)
-#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND)
-#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND)
-#define CM_REQUEST_SIZE LEADER_SIZE + sizeof(stLocalSFChangeRequest)
-#define IDLE_REQ_SIZE sizeof(PACKETTOSEND)
+#define LEADER_STATUS 0x00
+#define LEADER_STATUS_TCP_ACK 0x1
+#define LEADER_SIZE sizeof(LEADER)
+#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND)
+#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND)
+#define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest))
+#define IDLE_REQ_SIZE sizeof(PACKETTOSEND)
-#define MAX_TRANSFER_CTRL_BYTE_USB 2 * 1024
+#define MAX_TRANSFER_CTRL_BYTE_USB (2*1024)
#define GET_MAILBOX1_REG_REQUEST 0x87
#define GET_MAILBOX1_REG_RESPONSE 0x67
@@ -124,40 +124,40 @@
#define TRANSMIT_NETWORK_DATA 0x00
#define RECEIVED_NETWORK_DATA 0x20
-#define CM_RESPONSES 0xA0
-#define STATUS_RSP 0xA1
-#define LINK_CONTROL_RESP 0xA2
-#define IDLE_MODE_STATUS 0xA3
-#define STATS_POINTER_RESP 0xA6
-#define MGMT_MSG_INFO_SW_STATUS 0xA7
-#define AUTH_SS_HOST_MSG 0xA8
-
-#define CM_DSA_ACK_PAYLOAD 247
-#define CM_DSC_ACK_PAYLOAD 248
-#define CM_DSD_ACK_PAYLOAD 249
-#define CM_DSDEACTVATE 250
-#define TOTAL_MASKED_ADDRESS_IN_BYTES 32
-
-#define MAC_REQ 0
-#define LINK_RESP 1
-#define RSSI_INDICATION 2
-
-#define SS_INFO 4
-#define STATISTICS_INFO 5
-#define CM_INDICATION 6
-#define PARAM_RESP 7
-#define BUFFER_1K 1024
-#define BUFFER_2K BUFFER_1K*2
-#define BUFFER_4K BUFFER_2K*2
-#define BUFFER_8K BUFFER_4K*2
-#define BUFFER_16K BUFFER_8K*2
-#define DOWNLINK_DIR 0
-#define UPLINK_DIR 1
-
-#define BCM_SIGNATURE "BECEEM"
-
-
-#define GPIO_OUTPUT_REGISTER 0x0F00003C
+#define CM_RESPONSES 0xA0
+#define STATUS_RSP 0xA1
+#define LINK_CONTROL_RESP 0xA2
+#define IDLE_MODE_STATUS 0xA3
+#define STATS_POINTER_RESP 0xA6
+#define MGMT_MSG_INFO_SW_STATUS 0xA7
+#define AUTH_SS_HOST_MSG 0xA8
+
+#define CM_DSA_ACK_PAYLOAD 247
+#define CM_DSC_ACK_PAYLOAD 248
+#define CM_DSD_ACK_PAYLOAD 249
+#define CM_DSDEACTVATE 250
+#define TOTAL_MASKED_ADDRESS_IN_BYTES 32
+
+#define MAC_REQ 0
+#define LINK_RESP 1
+#define RSSI_INDICATION 2
+
+#define SS_INFO 4
+#define STATISTICS_INFO 5
+#define CM_INDICATION 6
+#define PARAM_RESP 7
+#define BUFFER_1K 1024
+#define BUFFER_2K (BUFFER_1K*2)
+#define BUFFER_4K (BUFFER_2K*2)
+#define BUFFER_8K (BUFFER_4K*2)
+#define BUFFER_16K (BUFFER_8K*2)
+#define DOWNLINK_DIR 0
+#define UPLINK_DIR 1
+
+#define BCM_SIGNATURE "BECEEM"
+
+
+#define GPIO_OUTPUT_REGISTER 0x0F00003C
#define BCM_GPIO_OUTPUT_SET_REG 0x0F000040
#define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044
#define GPIO_MODE_REGISTER 0x0F000034
@@ -165,44 +165,43 @@
typedef struct _LINK_STATE {
- UCHAR ucLinkStatus;
- UCHAR bIdleMode;
- UCHAR bShutdownMode;
-}LINK_STATE, *PLINK_STATE;
+ UCHAR ucLinkStatus;
+ UCHAR bIdleMode;
+ UCHAR bShutdownMode;
+} LINK_STATE, *PLINK_STATE;
enum enLinkStatus {
- WAIT_FOR_SYNC = 1,
- PHY_SYNC_ACHIVED = 2,
- LINKUP_IN_PROGRESS = 3,
- LINKUP_DONE = 4,
- DREG_RECIEVED = 5,
- LINK_STATUS_RESET_RECIEVED = 6,
- PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7,
- LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8,
- COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW =9
+ WAIT_FOR_SYNC = 1,
+ PHY_SYNC_ACHIVED = 2,
+ LINKUP_IN_PROGRESS = 3,
+ LINKUP_DONE = 4,
+ DREG_RECEIVED = 5,
+ LINK_STATUS_RESET_RECEIVED = 6,
+ PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7,
+ LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8,
+ COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW = 9
};
-typedef enum _E_PHS_DSC_ACTION
-{
- eAddPHSRule=0,
+typedef enum _E_PHS_DSC_ACTION {
+ eAddPHSRule = 0,
eSetPHSRule,
eDeletePHSRule,
eDeleteAllPHSRules
-}E_PHS_DSC_ACTION;
+} E_PHS_DSC_ACTION;
-#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 // Host to Mac
-#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 // Mac to Host
-#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 //0b000010000
-#define MINIMUM_PENDING_DESCRIPTORS 5
+#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 /* Host to Mac */
+#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 /* Mac to Host */
+#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 /* 0b000010000 */
+#define MINIMUM_PENDING_DESCRIPTORS 5
#define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC
#define SHUTDOWN_ACK_FROM_DRIVER 0x1
#define SHUTDOWN_NACK_FROM_DRIVER 0x2
-#define LINK_SYNC_UP_SUBTYPE 0x0001
-#define LINK_SYNC_DOWN_SUBTYPE 0x0001
+#define LINK_SYNC_UP_SUBTYPE 0x0001
+#define LINK_SYNC_DOWN_SUBTYPE 0x0001
@@ -226,9 +225,9 @@ typedef enum _E_PHS_DSC_ACTION
#define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10)
-#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN)
+#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN)
#define AUTO_LINKUP_ENABLE 0x2
-#define AUTO_SYNC_DISABLE 0x1
+#define AUTO_SYNC_DISABLE 0x1
#define AUTO_FIRM_DOWNLOAD 0x1
#define SETTLE_DOWN_TIME 50
@@ -242,9 +241,9 @@ typedef enum _E_PHS_DSC_ACTION
#define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3
#define IDLE_MODE_PAYLOAD_LENGTH 8
-#define IP_HEADER(Buffer) ((IPHeaderFormat*)(Buffer))
-#define IPV4 4
-#define IP_VERSION(byte) (((byte&0xF0)>>4))
+#define IP_HEADER(Buffer) ((IPHeaderFormat *)(Buffer))
+#define IPV4 4
+#define IP_VERSION(byte) (((byte&0xF0)>>4))
#define SET_MAC_ADDRESS 193
#define SET_MAC_ADDRESS_RESPONSE 236
@@ -263,15 +262,15 @@ typedef enum _E_PHS_DSC_ACTION
#define INVALID_QUEUE_INDEX NO_OF_QUEUES
-#define INVALID_PID (pid_t)-1
-#define DDR_80_MHZ 0
-#define DDR_100_MHZ 1
-#define DDR_120_MHZ 2 // Additional Frequency for T3LP
-#define DDR_133_MHZ 3
-#define DDR_140_MHZ 4 // Not Used (Reserved for future)
-#define DDR_160_MHZ 5 // Additional Frequency for T3LP
-#define DDR_180_MHZ 6 // Not Used (Reserved for future)
-#define DDR_200_MHZ 7 // Not Used (Reserved for future)
+#define INVALID_PID ((pid_t)-1)
+#define DDR_80_MHZ 0
+#define DDR_100_MHZ 1
+#define DDR_120_MHZ 2 /* Additional Frequency for T3LP */
+#define DDR_133_MHZ 3
+#define DDR_140_MHZ 4 /* Not Used (Reserved for future) */
+#define DDR_160_MHZ 5 /* Additional Frequency for T3LP */
+#define DDR_180_MHZ 6 /* Not Used (Reserved for future) */
+#define DDR_200_MHZ 7 /* Not Used (Reserved for future) */
#define MIPS_200_MHZ 0
#define MIPS_160_MHZ 1
@@ -291,27 +290,27 @@ typedef enum _E_PHS_DSC_ACTION
#define EEPROM_REJECT_REG_3 0x0f003008
#define EEPROM_REJECT_REG_4 0x0f003020
#define EEPROM_REJECT_MASK 0x0fffffff
-#define VSG_MODE 0x3
+#define VSG_MODE 0x3
/* Idle Mode Related Registers */
#define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C
-#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC
+#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC
-#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e
-#define DEVICE_INT_OUT_EP_REG0 0x0F011870
-#define DEVICE_INT_OUT_EP_REG1 0x0F011874
+#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e
+#define DEVICE_INT_OUT_EP_REG0 0x0F011870
+#define DEVICE_INT_OUT_EP_REG1 0x0F011874
#define BIN_FILE "/lib/firmware/macxvi200.bin"
#define CFG_FILE "/lib/firmware/macxvi.cfg"
#define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128
-#define MIN_VAL(x,y) ((x)<(y)?(x):(y))
+#define MIN_VAL(x, y) ((x) < (y) ? (x) : (y))
#define MAC_ADDRESS_SIZE 6
#define EEPROM_COMMAND_Q_REG 0x0F003018
#define EEPROM_READ_DATA_Q_REG 0x0F003020
-#define CHIP_ID_REG 0x0F000000
-#define GPIO_MODE_REG 0x0F000034
-#define GPIO_OUTPUT_REG 0x0F00003C
-#define WIMAX_MAX_ALLOWED_RATE 1024*1024*50
+#define CHIP_ID_REG 0x0F000000
+#define GPIO_MODE_REG 0x0F000034
+#define GPIO_OUTPUT_REG 0x0F00003C
+#define WIMAX_MAX_ALLOWED_RATE (1024*1024*50)
#define T3 0xbece0300
#define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400
@@ -319,31 +318,29 @@ typedef enum _E_PHS_DSC_ACTION
#define RWM_READ 0
#define RWM_WRITE 1
-#define T3LPB 0xbece3300
-#define BCS220_2 0xbece3311
-#define BCS220_2BC 0xBECE3310
-#define BCS250_BC 0xbece3301
-#define BCS220_3 0xbece3321
+#define T3LPB 0xbece3300
+#define BCS220_2 0xbece3311
+#define BCS220_2BC 0xBECE3310
+#define BCS250_BC 0xbece3301
+#define BCS220_3 0xbece3321
-#define HPM_CONFIG_LDO145 0x0F000D54
-#define HPM_CONFIG_MSW 0x0F000D58
+#define HPM_CONFIG_LDO145 0x0F000D54
+#define HPM_CONFIG_MSW 0x0F000D58
#define T3B 0xbece0310
-typedef enum eNVM_TYPE
-{
+typedef enum eNVM_TYPE {
NVM_AUTODETECT = 0,
NVM_EEPROM,
NVM_FLASH,
NVM_UNKNOWN
-}NVM_TYPE;
+} NVM_TYPE;
-typedef enum ePMU_MODES
-{
+typedef enum ePMU_MODES {
HYBRID_MODE_7C = 0,
INTERNAL_MODE_6 = 1,
HYBRID_MODE_6 = 2
-}PMU_MODE;
+} PMU_MODE;
#define MAX_RDM_WRM_RETIRES 1
@@ -360,4 +357,4 @@ enum eAbortPattern {
#define SKB_CB_LATENCY_OFFSET 1
#define SKB_CB_TCPACK_OFFSET 2
-#endif //__MACROS_H__
+#endif /* __MACROS_H__ */
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index c5003b6..e9f29d5 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -1,113 +1,94 @@
#include "headers.h"
-static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path,
- unsigned int loc);
+static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc);
static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter);
-static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer);
+static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer);
static int bcm_parse_target_params(PMINI_ADAPTER Adapter);
-static void beceem_protocol_reset (PMINI_ADAPTER Adapter);
+static void beceem_protocol_reset(PMINI_ADAPTER Adapter);
static VOID default_wimax_protocol_initialize(PMINI_ADAPTER Adapter)
{
+ UINT uiLoopIndex;
- UINT uiLoopIndex;
-
- for(uiLoopIndex=0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++)
- {
- Adapter->PackInfo[uiLoopIndex].uiThreshold=TX_PACKET_THRESHOLD;
- Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate=MAX_ALLOWED_RATE;
- Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize=20*1024*1024;
- }
-
- Adapter->BEBucketSize=BE_BUCKET_SIZE;
- Adapter->rtPSBucketSize=rtPS_BUCKET_SIZE;
- Adapter->LinkStatus=SYNC_UP_REQUEST;
- Adapter->TransferMode=IP_PACKET_ONLY_MODE;
- Adapter->usBestEffortQueueIndex=-1;
- return;
-}
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) {
+ Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD;
+ Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate = MAX_ALLOWED_RATE;
+ Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize = 20*1024*1024;
+ }
+ Adapter->BEBucketSize = BE_BUCKET_SIZE;
+ Adapter->rtPSBucketSize = rtPS_BUCKET_SIZE;
+ Adapter->LinkStatus = SYNC_UP_REQUEST;
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
+ Adapter->usBestEffortQueueIndex = -1;
+ return;
+}
-INT
-InitAdapter(PMINI_ADAPTER psAdapter)
+INT InitAdapter(PMINI_ADAPTER psAdapter)
{
- int i = 0;
- INT Status = STATUS_SUCCESS ;
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
+ int i = 0;
+ INT Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
- if(psAdapter == NULL)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL");
+ if (psAdapter == NULL) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL");
return -EINVAL;
}
- sema_init(&psAdapter->NVMRdmWrmLock,1);
-// psAdapter->ulFlashCalStart = FLASH_AUTO_INIT_BASE_ADDR;
-
+ sema_init(&psAdapter->NVMRdmWrmLock, 1);
sema_init(&psAdapter->rdmwrmsync, 1);
spin_lock_init(&psAdapter->control_queue_lock);
spin_lock_init(&psAdapter->txtransmitlock);
- sema_init(&psAdapter->RxAppControlQueuelock, 1);
-// sema_init(&psAdapter->data_packet_queue_lock, 1);
- sema_init(&psAdapter->fw_download_sema, 1);
- sema_init(&psAdapter->LowPowerModeSync,1);
-
- // spin_lock_init(&psAdapter->sleeper_lock);
-
- for(i=0;i<NO_OF_QUEUES; i++)
- spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock);
- i=0;
-
- init_waitqueue_head(&psAdapter->process_rx_cntrlpkt);
- init_waitqueue_head(&psAdapter->tx_packet_wait_queue);
- init_waitqueue_head(&psAdapter->process_read_wait_queue);
- init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue);
- init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue);
+ sema_init(&psAdapter->RxAppControlQueuelock, 1);
+ sema_init(&psAdapter->fw_download_sema, 1);
+ sema_init(&psAdapter->LowPowerModeSync, 1);
+
+ for (i = 0; i < NO_OF_QUEUES; i++)
+ spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock);
+ i = 0;
+
+ init_waitqueue_head(&psAdapter->process_rx_cntrlpkt);
+ init_waitqueue_head(&psAdapter->tx_packet_wait_queue);
+ init_waitqueue_head(&psAdapter->process_read_wait_queue);
+ init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue);
+ init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue);
psAdapter->waiting_to_fw_download_done = TRUE;
- //init_waitqueue_head(&psAdapter->device_wake_queue);
- psAdapter->fw_download_done=FALSE;
-
+ psAdapter->fw_download_done = FALSE;
default_wimax_protocol_initialize(psAdapter);
- for (i=0;i<MAX_CNTRL_PKTS;i++)
- {
+ for (i = 0; i < MAX_CNTRL_PKTS; i++) {
psAdapter->txctlpacket[i] = kmalloc(MAX_CNTL_PKT_SIZE, GFP_KERNEL);
- if(!psAdapter->txctlpacket[i])
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i);
+ if (!psAdapter->txctlpacket[i]) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i);
return -ENOMEM;
}
}
- if(AllocAdapterDsxBuffer(psAdapter))
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers");
+
+ if (AllocAdapterDsxBuffer(psAdapter)) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers");
return -EINVAL;
}
- //Initialize PHS interface
- if(phs_init(&psAdapter->stBCMPhsContext,psAdapter)!=0)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __FUNCTION__, __LINE__);
+ /* Initialize PHS interface */
+ if (phs_init(&psAdapter->stBCMPhsContext, psAdapter) != 0) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __func__, __LINE__);
return -ENOMEM;
}
Status = BcmAllocFlashCSStructure(psAdapter);
- if(Status)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Memory Allocation for Flash structure failed");
- return Status ;
+ if (Status) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Memory Allocation for Flash structure failed");
+ return Status;
}
Status = vendorextnInit(psAdapter);
- if(STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Vendor Init Failed");
- return Status ;
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Vendor Init Failed");
+ return Status;
}
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised");
-
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised");
return STATUS_SUCCESS;
}
@@ -115,42 +96,37 @@ InitAdapter(PMINI_ADAPTER psAdapter)
VOID AdapterFree(PMINI_ADAPTER Adapter)
{
int count;
-
beceem_protocol_reset(Adapter);
-
vendorextnExit(Adapter);
- if(Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler))
- kthread_stop (Adapter->control_packet_handler);
+ if (Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler))
+ kthread_stop(Adapter->control_packet_handler);
- if(Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread))
- kthread_stop (Adapter->transmit_packet_thread);
+ if (Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread))
+ kthread_stop(Adapter->transmit_packet_thread);
wake_up(&Adapter->process_read_wait_queue);
- if(Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY))
- kthread_stop (Adapter->LEDInfo.led_cntrl_threadid);
+ if (Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY))
+ kthread_stop(Adapter->LEDInfo.led_cntrl_threadid);
unregister_networkdev(Adapter);
/* FIXME: use proper wait_event and refcounting */
- while(atomic_read(&Adapter->ApplicationRunning))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n",atomic_read(&Adapter->ApplicationRunning));
+ while (atomic_read(&Adapter->ApplicationRunning)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n", atomic_read(&Adapter->ApplicationRunning));
msleep(100);
}
unregister_control_device_interface(Adapter);
-
kfree(Adapter->pstargetparams);
- for (count =0;count < MAX_CNTRL_PKTS;count++)
+ for (count = 0; count < MAX_CNTRL_PKTS; count++)
kfree(Adapter->txctlpacket[count]);
FreeAdapterDsxBuffer(Adapter);
-
kfree(Adapter->pvInterfaceAdapter);
- //Free the PHS Interface
+ /* Free the PHS Interface */
PhsCleanup(&Adapter->stBCMPhsContext);
BcmDeAllocFlashCSStructure(Adapter);
@@ -160,20 +136,18 @@ VOID AdapterFree(PMINI_ADAPTER Adapter)
static int create_worker_threads(PMINI_ADAPTER psAdapter)
{
- // Rx Control Packets Processing
+ /* Rx Control Packets Processing */
psAdapter->control_packet_handler = kthread_run((int (*)(void *))
control_packet_handler, psAdapter, "%s-rx", DRV_NAME);
- if(IS_ERR(psAdapter->control_packet_handler))
- {
+ if (IS_ERR(psAdapter->control_packet_handler)) {
pr_notice(DRV_NAME ": could not create control thread\n");
return PTR_ERR(psAdapter->control_packet_handler);
}
- // Tx Thread
+ /* Tx Thread */
psAdapter->transmit_packet_thread = kthread_run((int (*)(void *))
tx_pkt_handler, psAdapter, "%s-tx", DRV_NAME);
- if(IS_ERR (psAdapter->transmit_packet_thread))
- {
+ if (IS_ERR(psAdapter->transmit_packet_thread)) {
pr_notice(DRV_NAME ": could not creat transmit thread\n");
kthread_stop(psAdapter->control_packet_handler);
return PTR_ERR(psAdapter->transmit_packet_thread);
@@ -183,275 +157,248 @@ static int create_worker_threads(PMINI_ADAPTER psAdapter)
static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path)
{
- struct file *flp=NULL;
- mm_segment_t oldfs;
- oldfs=get_fs();
+ struct file *flp = NULL;
+ mm_segment_t oldfs;
+ oldfs = get_fs();
set_fs(get_ds());
- flp=filp_open(path, O_RDONLY, S_IRWXU);
- set_fs(oldfs);
- if(IS_ERR(flp))
- {
- pr_err(DRV_NAME "Unable To Open File %s, err %ld",
- path, PTR_ERR(flp));
- flp = NULL;
- }
-
- if(Adapter->device_removed)
- flp = NULL;
-
- return flp;
-}
+ flp = filp_open(path, O_RDONLY, S_IRWXU);
+ set_fs(oldfs);
+ if (IS_ERR(flp)) {
+ pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp));
+ flp = NULL;
+ }
+ if (Adapter->device_removed)
+ flp = NULL;
-static int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */
- const char *path, /**< path to image file */
- unsigned int loc /**< Download Address on the chip*/
- )
+ return flp;
+}
+
+/* Arguments:
+ * Logical Adapter
+ * Path to image file
+ * Download Address on the chip
+ */
+static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc)
{
- int errorno=0;
- struct file *flp=NULL;
- mm_segment_t oldfs;
- struct timeval tv={0};
-
- flp=open_firmware_file(Adapter, path);
- if(!flp)
- {
- errorno = -ENOENT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path);
- goto exit_download;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path,(unsigned long)flp->f_dentry->d_inode->i_size, loc);
- do_gettimeofday(&tv);
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) +
- (tv.tv_usec/1000)));
- if(Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error\
- %x!!!", -EIO);
- errorno=-EIO;
- goto exit_download;
- }
- oldfs=get_fs();set_fs(get_ds());
- vfs_llseek(flp, 0, 0);
- set_fs(oldfs);
- if(Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter,
- flp, loc))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!");
- errorno=-EIO;
- goto exit_download;
- }
+ int errorno = 0;
+ struct file *flp = NULL;
+ mm_segment_t oldfs;
+ struct timeval tv = {0};
+
+ flp = open_firmware_file(Adapter, path);
+ if (!flp) {
+ errorno = -ENOENT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path);
+ goto exit_download;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)flp->f_dentry->d_inode->i_size, loc);
+ do_gettimeofday(&tv);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)));
+ if (Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error %x!!!", -EIO);
+ errorno = -EIO;
+ goto exit_download;
+ }
+ oldfs = get_fs();
+ set_fs(get_ds());
+ vfs_llseek(flp, 0, 0);
+ set_fs(oldfs);
+ if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!");
+ errorno = -EIO;
+ goto exit_download;
+ }
exit_download:
- oldfs=get_fs();set_fs(get_ds());
- if(flp && !(IS_ERR(flp)))
- filp_close(flp, current->files);
- set_fs(oldfs);
+ oldfs = get_fs();
+ set_fs(get_ds());
+ if (flp && !(IS_ERR(flp)))
+ filp_close(flp, current->files);
+ set_fs(oldfs);
- return errorno;
+ return errorno;
}
/**
-@ingroup ctrl_pkt_functions
-This function copies the contents of given buffer
-to the control packet and queues it for transmission.
-@note Do not acquire the spinock, as it it already acquired.
-@return SUCCESS/FAILURE.
-*/
-INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
- PVOID ioBuffer/**<Control Packet Buffer*/
- )
+ * @ingroup ctrl_pkt_functions
+ * This function copies the contents of given buffer
+ * to the control packet and queues it for transmission.
+ * @note Do not acquire the spinock, as it it already acquired.
+ * @return SUCCESS/FAILURE.
+ * Arguments:
+ * Logical Adapter
+ * Control Packet Buffer
+ */
+INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer)
{
- PLEADER pLeader=NULL;
- INT Status=0;
- unsigned char *ctrl_buff=NULL;
- UINT pktlen=0;
- PLINK_REQUEST pLinkReq = NULL;
- PUCHAR pucAddIndication = NULL;
-
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>");
- if(!ioBuffer)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Got Null Buffer\n");
+ PLEADER pLeader = NULL;
+ INT Status = 0;
+ unsigned char *ctrl_buff = NULL;
+ UINT pktlen = 0;
+ PLINK_REQUEST pLinkReq = NULL;
+ PUCHAR pucAddIndication = NULL;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>");
+ if (!ioBuffer) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got Null Buffer\n");
return -EINVAL;
}
pLinkReq = (PLINK_REQUEST)ioBuffer;
- pLeader=(PLEADER)ioBuffer; //ioBuffer Contains sw_Status and Payload
+ pLeader = (PLEADER)ioBuffer; /* ioBuffer Contains sw_Status and Payload */
- if(Adapter->bShutStatus == TRUE &&
+ if (Adapter->bShutStatus == TRUE &&
pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD &&
- pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)
- {
- //Got sync down in SHUTDOWN..we could not process this.
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n");
+ pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE) {
+
+ /* Got sync down in SHUTDOWN..we could not process this. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n");
return STATUS_FAILURE;
}
- if((pLeader->Status == LINK_UP_CONTROL_REQ) &&
+ if ((pLeader->Status == LINK_UP_CONTROL_REQ) &&
((pLinkReq->szData[0] == LINK_UP_REQ_PAYLOAD &&
- (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) ||//Sync Up Command
- pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) //Net Entry Command
- {
- if(Adapter->LinkStatus > PHY_SYNC_ACHIVED)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"LinkStatus is Greater than PHY_SYN_ACHIEVED");
+ (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) || /* Sync Up Command */
+ pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) /* Net Entry Command */ {
+
+ if (Adapter->LinkStatus > PHY_SYNC_ACHIVED) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "LinkStatus is Greater than PHY_SYN_ACHIEVED");
return STATUS_FAILURE;
}
- if(TRUE == Adapter->bShutStatus)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
- if(Adapter->bTriedToWakeUpFromlowPowerMode == FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Waking up for the First Time..\n");
- Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; // change it to 1 for current support.
+
+ if (TRUE == Adapter->bShutStatus) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
+ if (Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n");
+ Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; /* change it to 1 for current support. */
Adapter->bWakeUpDevice = TRUE;
wake_up(&Adapter->process_rx_cntrlpkt);
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->bShutStatus, (5 * HZ));
- Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
- !Adapter->bShutStatus, (5 * HZ));
-
- if(Status == -ERESTARTSYS)
+ if (Status == -ERESTARTSYS)
return Status;
- if(Adapter->bShutStatus)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n");
+ if (Adapter->bShutStatus) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n");
return STATUS_FAILURE;
}
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Wakeup has been tried already...\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Wakeup has been tried already...\n");
}
}
-
}
- if(TRUE == Adapter->IdleMode)
- {
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence \n");
- if(pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
- pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ )
- {
- if((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0]==LINK_DOWN_REQ_PAYLOAD))
- {
- if((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Link Down Sent in Idle Mode\n");
- Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN;//LINK DOWN sent in Idle Mode
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n");
+ if (TRUE == Adapter->IdleMode) {
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */
+ if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
+ pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) {
+
+ if ((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD)) {
+ if ((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Link Down Sent in Idle Mode\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN; /* LINK DOWN sent in Idle Mode */
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n");
Adapter->usIdleModePattern = ABORT_IDLE_REG;
}
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n");
- Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
}
/*Setting bIdleMode_tx_from_host to TRUE to indicate LED control thread to represent
- the wake up from idlemode is from host*/
- //Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE;
+ * the wake up from idlemode is from host
+ */
+ /* Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE; */
Adapter->bWakeUpDevice = TRUE;
wake_up(&Adapter->process_rx_cntrlpkt);
-
-
- if(LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0])
- {
- // We should not send DREG message down while in idlemode.
+ /* We should not send DREG message down while in idlemode. */
+ if (LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0])
return STATUS_SUCCESS;
- }
- Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
- !Adapter->IdleMode, (5 * HZ));
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->IdleMode, (5 * HZ));
- if(Status == -ERESTARTSYS)
+ if (Status == -ERESTARTSYS)
return Status;
- if(Adapter->IdleMode)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n");
+ if (Adapter->IdleMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n");
return STATUS_FAILURE;
}
- }
- else
+ } else {
return STATUS_SUCCESS;
+ }
}
- //The Driver has to send control messages with a particular VCID
- pLeader->Vcid = VCID_CONTROL_PACKET;//VCID for control packet.
+
+ /* The Driver has to send control messages with a particular VCID */
+ pLeader->Vcid = VCID_CONTROL_PACKET; /* VCID for control packet. */
/* Allocate skb for Control Packet */
pktlen = pLeader->PLength;
ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS];
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
- atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
- if(ctrl_buff)
- {
- if(pLeader)
- {
- if((pLeader->Status == 0x80) ||
- (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ))
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
+ atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
+ if (ctrl_buff) {
+ if (pLeader) {
+ if ((pLeader->Status == 0x80) ||
+ (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
/*
- //Restructure the DSX message to handle Multiple classifier Support
- // Write the Service Flow param Structures directly to the target
- //and embed the pointers in the DSX messages sent to target.
- */
- //Lets store the current length of the control packet we are transmitting
+ * Restructure the DSX message to handle Multiple classifier Support
+ * Write the Service Flow param Structures directly to the target
+ * and embed the pointers in the DSX messages sent to target.
+ */
+ /* Lets store the current length of the control packet we are transmitting */
pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
pktlen = pLeader->PLength;
- Status = StoreCmControlResponseMessage(Adapter,pucAddIndication, &pktlen);
- if(Status != 1)
- {
- ClearTargetDSXBuffer(Adapter,((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
+ Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
+ if (Status != 1) {
+ ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
return STATUS_FAILURE;
}
/*
- //update the leader to use the new length
- //The length of the control packet is length of message being sent + Leader length
- */
+ * update the leader to use the new length
+ * The length of the control packet is length of message being sent + Leader length
+ */
pLeader->PLength = pktlen;
}
}
+
+ if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
+ return -EINVAL;
+
memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
- *(PLEADER)ctrl_buff=*pLeader;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
+ *(PLEADER)ctrl_buff = *pLeader;
memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
- /*Update the statistics counters */
+ /* Update the statistics counters */
spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
- Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost+=pLeader->PLength;
+ Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
atomic_inc(&Adapter->TotalPacketCount);
spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
-
Adapter->PackInfo[HiPriority].bValid = TRUE;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
- Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
- Adapter->PackInfo[HiPriority].bValid);
- Status=STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
+ Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
+ Adapter->PackInfo[HiPriority].bValid);
+ Status = STATUS_SUCCESS;
/*Queue the packet for transmission */
atomic_inc(&Adapter->index_wr_txcntrlpkt);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Calling transmit_packets");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
atomic_set(&Adapter->TxPktAvail, 1);
wake_up(&Adapter->tx_packet_wait_queue);
+ } else {
+ Status = -ENOMEM;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
}
- else
- {
- Status=-ENOMEM;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
- }
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
return Status;
}
@@ -460,33 +407,30 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
* Function - SendStatisticsPointerRequest()
*
* Description - This function builds and forwards the Statistics
-* Pointer Request control Packet.
+* Pointer Request control Packet.
*
* Parameters - Adapter : Pointer to Adapter structure.
-* - pstStatisticsPtrRequest : Pointer to link request.
+* - pstStatisticsPtrRequest : Pointer to link request.
*
* Returns - None.
*****************************************************************/
-static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter,
- PLINK_REQUEST pstStatisticsPtrRequest)
+static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, PLINK_REQUEST pstStatisticsPtrRequest)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>");
pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS;
- pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG);//minimum 4 bytes
+ pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG); /* minimum 4 bytes */
pstStatisticsPtrRequest->szData[0] = STATISTICS_POINTER_REQ;
-
- CopyBufferToControlPacket(Adapter,pstStatisticsPtrRequest);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<=====");
+ CopyBufferToControlPacket(Adapter, pstStatisticsPtrRequest);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<=====");
return;
}
#endif
-
/******************************************************************
* Function - LinkMessage()
*
* Description - This function builds the Sync-up and Link-up request
-* packet messages depending on the device Link status.
+* packet messages depending on the device Link status.
*
* Parameters - Adapter: Pointer to the Adapter structure.
*
@@ -494,102 +438,90 @@ static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter,
*******************************************************************/
VOID LinkMessage(PMINI_ADAPTER Adapter)
{
- PLINK_REQUEST pstLinkRequest=NULL;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
- if(Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup)
- {
+ PLINK_REQUEST pstLinkRequest = NULL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
+ if (Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) {
pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
- if(!pstLinkRequest)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
+ if (!pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
return;
}
- //sync up request...
- Adapter->LinkStatus = WAIT_FOR_SYNC;// current link status
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
- pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD;
- pstLinkRequest->szData[1]=LINK_SYNC_UP_SUBTYPE;
- pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ;
- pstLinkRequest->Leader.PLength=sizeof(ULONG);
+ /* sync up request... */
+ Adapter->LinkStatus = WAIT_FOR_SYNC; /* current link status */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
+ pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD;
+ pstLinkRequest->szData[1] = LINK_SYNC_UP_SUBTYPE;
+ pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ;
+ pstLinkRequest->Leader.PLength = sizeof(ULONG);
Adapter->bSyncUpRequestSent = TRUE;
- }
- else if(Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp)
- {
+
+ } else if (Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) {
pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
- if(!pstLinkRequest)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
+ if (!pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
return;
}
- //LINK_UP_REQUEST
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
- pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD;
- pstLinkRequest->szData[1]=LINK_NET_ENTRY;
- pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ;
- pstLinkRequest->Leader.PLength=sizeof(ULONG);
- }
- if(pstLinkRequest)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket");
+ /* LINK_UP_REQUEST */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
+ pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD;
+ pstLinkRequest->szData[1] = LINK_NET_ENTRY;
+ pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ;
+ pstLinkRequest->Leader.PLength = sizeof(ULONG);
+ }
+ if (pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket");
CopyBufferToControlPacket(Adapter, pstLinkRequest);
kfree(pstLinkRequest);
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <=====");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <=====");
return;
}
-
/**********************************************************************
* Function - StatisticsResponse()
*
* Description - This function handles the Statistics response packet.
*
* Parameters - Adapter : Pointer to the Adapter structure.
-* - pvBuffer: Starting address of Statistic response data.
+* - pvBuffer: Starting address of Statistic response data.
*
* Returns - None.
************************************************************************/
-VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer)
+VOID StatisticsResponse(PMINI_ADAPTER Adapter, PVOID pvBuffer)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>",__FUNCTION__);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__);
Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====",__FUNCTION__);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__);
return;
}
-
/**********************************************************************
* Function - LinkControlResponseMessage()
*
* Description - This function handles the Link response packets.
*
* Parameters - Adapter : Pointer to the Adapter structure.
-* - pucBuffer: Starting address of Link response data.
+* - pucBuffer: Starting address of Link response data.
*
* Returns - None.
***********************************************************************/
-VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer)
+VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
- if(*pucBuffer==LINK_UP_ACK)
- {
- switch(*(pucBuffer+1))
- {
- case PHY_SYNC_ACHIVED: //SYNCed UP
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED");
+ if (*pucBuffer == LINK_UP_ACK) {
+ switch (*(pucBuffer+1)) {
+ case PHY_SYNC_ACHIVED: /* SYNCed UP */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED");
- if(Adapter->LinkStatus == LINKUP_DONE)
- {
+ if (Adapter->LinkStatus == LINKUP_DONE)
beceem_protocol_reset(Adapter);
- }
- Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ;
- Adapter->LinkStatus=PHY_SYNC_ACHIVED;
+ Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
+ Adapter->LinkStatus = PHY_SYNC_ACHIVED;
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = NO_NETWORK_ENTRY;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
@@ -597,161 +529,145 @@ VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer)
LinkMessage(Adapter);
break;
- case LINKUP_DONE:
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE");
- Adapter->LinkStatus=LINKUP_DONE;
- Adapter->bPHSEnabled = *(pucBuffer+3);
- Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x \n",Adapter->bPHSEnabled);
- if((FALSE == Adapter->bShutStatus)&&
- (FALSE == Adapter->IdleMode))
- {
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
- Adapter->DriverState = NORMAL_OPERATION;
- wake_up(&Adapter->LEDInfo.notify_led_event);
- }
+ case LINKUP_DONE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE");
+ Adapter->LinkStatus = LINKUP_DONE;
+ Adapter->bPHSEnabled = *(pucBuffer+3);
+ Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x\n", Adapter->bPHSEnabled);
+
+ if ((FALSE == Adapter->bShutStatus) && (FALSE == Adapter->IdleMode)) {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = NORMAL_OPERATION;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
- LinkMessage(Adapter);
- break;
- case WAIT_FOR_SYNC:
+ }
+ LinkMessage(Adapter);
+ break;
- /*
- * Driver to ignore the DREG_RECEIVED
- * WiMAX Application should handle this Message
- */
- //Adapter->liTimeSinceLastNetEntry = 0;
- Adapter->LinkUpStatus = 0;
- Adapter->LinkStatus = 0;
- Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ;
- Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
- Adapter->IdleMode = FALSE;
- beceem_protocol_reset(Adapter);
+ case WAIT_FOR_SYNC:
+ /*
+ * Driver to ignore the DREG_RECEIVED
+ * WiMAX Application should handle this Message
+ */
+ /* Adapter->liTimeSinceLastNetEntry = 0; */
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+ Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
+ Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
+ Adapter->IdleMode = FALSE;
+ beceem_protocol_reset(Adapter);
- break;
- case LINK_SHUTDOWN_REQ_FROM_FIRMWARE:
- case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW:
- {
- HandleShutDownModeRequest(Adapter, pucBuffer);
- }
- break;
- default:
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x",*(pucBuffer+1));
- break;
+ break;
+ case LINK_SHUTDOWN_REQ_FROM_FIRMWARE:
+ case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW:
+ {
+ HandleShutDownModeRequest(Adapter, pucBuffer);
}
- }
- else if(SET_MAC_ADDRESS_RESPONSE==*pucBuffer)
- {
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x", *(pucBuffer + 1));
+ break;
+ }
+ } else if (SET_MAC_ADDRESS_RESPONSE == *pucBuffer) {
PUCHAR puMacAddr = (pucBuffer + 1);
- Adapter->LinkStatus=SYNC_UP_REQUEST;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP");
+ Adapter->LinkStatus = SYNC_UP_REQUEST;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP");
LinkMessage(Adapter);
memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE);
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====",__FUNCTION__);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====", __func__);
return;
}
void SendIdleModeResponse(PMINI_ADAPTER Adapter)
{
- INT status = 0, NVMAccess = 0,lowPwrAbortMsg = 0;
+ INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
struct timeval tv;
- CONTROL_MESSAGE stIdleResponse = {{0}};
+ CONTROL_MESSAGE stIdleResponse = {{0} };
memset(&tv, 0, sizeof(tv));
- stIdleResponse.Leader.Status = IDLE_MESSAGE;
+ stIdleResponse.Leader.Status = IDLE_MESSAGE;
stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH;
stIdleResponse.szData[0] = GO_TO_IDLE_MODE_PAYLOAD;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL," ============>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, " ============>");
/*********************************
- **down_trylock -
- ** if [ semaphore is available ]
- ** acquire semaphone and return value 0 ;
- ** else
- ** return non-zero value ;
- **
- ***********************************/
+ *down_trylock -
+ * if [ semaphore is available ]
+ * acquire semaphone and return value 0 ;
+ * else
+ * return non-zero value ;
+ *
+ ***********************************/
NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync);
- lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync);
+ if ((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) &&
+ (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) {
- if((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) &&
- (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) )
- {
- if(!NVMAccess)
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
- stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on.
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!");
+ stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!");
Adapter->bPreparingForLowPowerMode = FALSE;
- }
- else
- {
- stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; //2;//Idle ACK
+ } else {
+ stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; /* 2; Idle ACK */
Adapter->StatisticsPointer = 0;
/* Wait for the LED to TURN OFF before sending ACK response */
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
INT iRetVal = 0;
/* Wake the LED Thread with IDLEMODE_ENTER State */
Adapter->DriverState = LOWPOWER_MODE_ENTER;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld",jiffies);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld", jiffies);
wake_up(&Adapter->LEDInfo.notify_led_event);
/* Wait for 1 SEC for LED to OFF */
- iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, \
- Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
-
+ iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
/* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */
- if(iRetVal <= 0)
- {
- stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on.
+ if (iRetVal <= 0) {
+ stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
Adapter->DriverState = NORMAL_OPERATION;
wake_up(&Adapter->LEDInfo.notify_led_event);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!");
}
}
- if(stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"ACKING IDLE MODE !!!!!!!!!");
+
+ if (stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "ACKING IDLE MODE !!!!!!!!!");
down(&Adapter->rdmwrmsync);
Adapter->bPreparingForLowPowerMode = TRUE;
up(&Adapter->rdmwrmsync);
- //Killing all URBS.
- if(Adapter->bDoSuspend == TRUE)
+ /* Killing all URBS. */
+ if (Adapter->bDoSuspend == TRUE)
Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
-
- }
- else
- {
+ } else {
Adapter->bPreparingForLowPowerMode = FALSE;
}
- if(!NVMAccess)
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
-
}
- status = CopyBufferToControlPacket(Adapter,&stIdleResponse);
- if((status != STATUS_SUCCESS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"fail to send the Idle mode Request \n");
+
+ status = CopyBufferToControlPacket(Adapter, &stIdleResponse);
+ if ((status != STATUS_SUCCESS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n");
Adapter->bPreparingForLowPowerMode = FALSE;
StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
}
do_gettimeofday(&tv);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
-
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
/******************************************************************
@@ -765,307 +681,264 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter)
*******************************************************************/
VOID DumpPackInfo(PMINI_ADAPTER Adapter)
{
-
- UINT uiLoopIndex = 0;
+ UINT uiLoopIndex = 0;
UINT uiIndex = 0;
UINT uiClsfrIndex = 0;
S_CLASSIFIER_RULE *pstClassifierEntry = NULL;
- for(uiLoopIndex=0;uiLoopIndex<NO_OF_QUEUES;uiLoopIndex++)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"*********** Showing Details Of Queue %d***** ******",uiLoopIndex);
- if(FALSE == Adapter->PackInfo[uiLoopIndex].bValid)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid is FALSE for %X index\n",uiLoopIndex);
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "*********** Showing Details Of Queue %d***** ******", uiLoopIndex);
+ if (FALSE == Adapter->PackInfo[uiLoopIndex].bValid) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid is FALSE for %X index\n", uiLoopIndex);
continue;
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," Dumping SF Rule Entry For SFID %lX \n",Adapter->PackInfo[uiLoopIndex].ulSFID);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," ucDirection %X \n",Adapter->PackInfo[uiLoopIndex].ucDirection);
- if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv6 Service Flow \n");
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " Dumping SF Rule Entry For SFID %lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " ucDirection %X\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
+
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv6 Service Flow\n");
else
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv4 Service Flow \n");
- }
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," SF Traffic Priority %X \n",Adapter->PackInfo[uiLoopIndex].u8TrafficPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv4 Service Flow\n");
- for(uiClsfrIndex=0;uiClsfrIndex<MAX_CLASSIFIERS;uiClsfrIndex++)
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SF Traffic Priority %X\n", Adapter->PackInfo[uiLoopIndex].u8TrafficPriority);
+
+ for (uiClsfrIndex = 0; uiClsfrIndex < MAX_CLASSIFIERS; uiClsfrIndex++) {
pstClassifierEntry = &Adapter->astClassifierTable[uiClsfrIndex];
- if(!pstClassifierEntry->bUsed)
+ if (!pstClassifierEntry->bUsed)
continue;
- if(pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID)
+ if (pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID)
continue;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n",uiClsfrIndex,pstClassifierEntry->uiClassifierRuleIndex);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n",uiClsfrIndex,pstClassifierEntry->usVCID_Value);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n",uiClsfrIndex,pstClassifierEntry->bProtocolValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n",uiClsfrIndex,pstClassifierEntry->bTOSValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bDestIpValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bSrcIpValid);
-
-
- for(uiIndex=0;uiIndex<MAX_PORT_RANGE;uiIndex++)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeLo:%X\n",pstClassifierEntry->usSrcPortRangeLo[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeHi:%X\n",pstClassifierEntry->usSrcPortRangeHi[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeLo:%X\n",pstClassifierEntry->usDestPortRangeLo[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeHi:%X\n",pstClassifierEntry->usDestPortRangeHi[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n", uiClsfrIndex, pstClassifierEntry->uiClassifierRuleIndex);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n", uiClsfrIndex, pstClassifierEntry->usVCID_Value);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n", uiClsfrIndex, pstClassifierEntry->bProtocolValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n", uiClsfrIndex, pstClassifierEntry->bTOSValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bDestIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bSrcIpValid);
+
+ for (uiIndex = 0; uiIndex < MAX_PORT_RANGE; uiIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeLo:%X\n", pstClassifierEntry->usSrcPortRangeLo[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeHi:%X\n", pstClassifierEntry->usSrcPortRangeHi[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeLo:%X\n", pstClassifierEntry->usDestPortRangeLo[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeHi:%X\n", pstClassifierEntry->usDestPortRangeHi[uiIndex]);
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," \tucIPSourceAddressLength : 0x%x\n",pstClassifierEntry->ucIPSourceAddressLength);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucIPDestinationAddressLength : 0x%x\n",pstClassifierEntry->ucIPDestinationAddressLength);
- for(uiIndex=0;uiIndex<pstClassifierEntry->ucIPSourceAddressLength;uiIndex++)
- {
- if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpAddr :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPSourceAddressLength : 0x%x\n", pstClassifierEntry->ucIPSourceAddressLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPDestinationAddressLength : 0x%x\n", pstClassifierEntry->ucIPDestinationAddressLength);
+ for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPSourceAddressLength; uiIndex++) {
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpAddr :\n");
DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpMask :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpMask :\n");
DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask);
- }
- else
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpAddr:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpMask:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpAddr:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpMask:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]);
}
}
- for(uiIndex=0;uiIndex<pstClassifierEntry->ucIPDestinationAddressLength;uiIndex++)
- {
- if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpAddr :\n");
+
+ for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPDestinationAddressLength; uiIndex++) {
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpAddr :\n");
DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Addr);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpMask :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpMask :\n");
DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Mask);
-
- }
- else
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpAddr:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpMask:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpAddr:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpMask:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]);
}
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucProtocol:0x%X\n",pstClassifierEntry->ucProtocol[0]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tu8ClassifierRulePriority:%X\n",pstClassifierEntry->u8ClassifierRulePriority);
-
-
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucProtocol:0x%X\n", pstClassifierEntry->ucProtocol[0]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tu8ClassifierRulePriority:%X\n", pstClassifierEntry->u8ClassifierRulePriority);
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ulSFID:%lX\n",Adapter->PackInfo[uiLoopIndex].ulSFID);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"usVCID_Value:%X\n",Adapter->PackInfo[uiLoopIndex].usVCID_Value);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"PhsEnabled: 0x%X\n",Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThreshold:%X\n",Adapter->PackInfo[uiLoopIndex].uiThreshold);
-
-
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid:%X\n",Adapter->PackInfo[uiLoopIndex].bValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bActive:%X\n",Adapter->PackInfo[uiLoopIndex].bActive);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"u8QueueType:%X\n",Adapter->PackInfo[uiLoopIndex].u8QueueType);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxBucketSize:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPerSFTxResourceCount:%X\n",atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount));
- //DumpDebug(DUMP_INFO,(" bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport));
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentBytesOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentPacketsOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentBytes);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentPackets);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentDrainRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThisPeriodSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liDrainCalculated:%llX\n",Adapter->PackInfo[uiLoopIndex].liDrainCalculated);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentTokenCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liLastUpdateTokenAt:%llX\n",Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxAllowedRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPendedLast:%X\n",Adapter->PackInfo[uiLoopIndex].uiPendedLast);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"NumOfPacketsSent:%X\n",Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n",Adapter->PackInfo[uiLoopIndex].uiMaxLatency);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n",Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]);
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes);
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes);
-// DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount));
- }
-
- for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++)
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aRxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aRxPktSizeHist[uiLoopIndex]);
-
- for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++)
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aTxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aTxPktSizeHist[uiLoopIndex]);
-
-
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ulSFID:%lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "usVCID_Value:%X\n", Adapter->PackInfo[uiLoopIndex].usVCID_Value);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "PhsEnabled: 0x%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThreshold:%X\n", Adapter->PackInfo[uiLoopIndex].uiThreshold);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid:%X\n", Adapter->PackInfo[uiLoopIndex].bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bActive:%X\n", Adapter->PackInfo[uiLoopIndex].bActive);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "u8QueueType:%X\n", Adapter->PackInfo[uiLoopIndex].u8QueueType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxBucketSize:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPerSFTxResourceCount:%X\n", atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount));
+ /* DumpDebug(DUMP_INFO,("bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport)); */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentBytesOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentPacketsOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentPackets);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentDrainRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThisPeriodSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liDrainCalculated:%llX\n", Adapter->PackInfo[uiLoopIndex].liDrainCalculated);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentTokenCount:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liLastUpdateTokenAt:%llX\n", Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxAllowedRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPendedLast:%X\n", Adapter->PackInfo[uiLoopIndex].uiPendedLast);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "NumOfPacketsSent:%X\n", Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n", Adapter->PackInfo[uiLoopIndex].uiMaxLatency);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n", Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]);
+/* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
+ * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes);
+ * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes);
+ * DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount));
+ */
+ }
+
+ for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aRxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aRxPktSizeHist[uiLoopIndex]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aTxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aTxPktSizeHist[uiLoopIndex]);
return;
-
-
}
int reset_card_proc(PMINI_ADAPTER ps_adapter)
{
int retval = STATUS_SUCCESS;
-
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
unsigned int value = 0, uiResetValue = 0;
- psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter)) ;
-
+ psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter));
ps_adapter->bDDRInitDone = FALSE;
- if(ps_adapter->chip_id >= T3LPB)
- {
- //SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before
- rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value));
- rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value));
+ if (ps_adapter->chip_id >= T3LPB) {
+ /* SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before */
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
- //making bit[6...5] same as was before f/w download. this setting force the h/w to
- //re-populated the SP RAM area with the string descriptor .
- value = value | (ps_adapter->syscfgBefFwDld & 0x00000060) ;
+ /* making bit[6...5] same as was before f/w download. this setting force the h/w to */
+ /* re-populated the SP RAM area with the string descriptor. */
+ value = value | (ps_adapter->syscfgBefFwDld & 0x00000060);
wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
}
- //killing all submitted URBs.
- psIntfAdapter->psAdapter->StopAllXaction = TRUE ;
+ /* killing all submitted URBs. */
+ psIntfAdapter->psAdapter->StopAllXaction = TRUE;
Bcm_kill_all_URBs(psIntfAdapter);
/* Reset the UMA-B Device */
- if(ps_adapter->chip_id >= T3LPB)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B \n");
+ if (ps_adapter->chip_id >= T3LPB) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B\n");
retval = usb_reset_device(psIntfAdapter->udev);
+ psIntfAdapter->psAdapter->StopAllXaction = FALSE;
- psIntfAdapter->psAdapter->StopAllXaction = FALSE ;
-
- if(retval != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval);
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval);
goto err_exit;
}
+
if (ps_adapter->chip_id == BCS220_2 ||
ps_adapter->chip_id == BCS220_2BC ||
ps_adapter->chip_id == BCS250_BC ||
- ps_adapter->chip_id == BCS220_3)
- {
- retval = rdmalt(ps_adapter,HPM_CONFIG_LDO145, &value, sizeof(value));
- if( retval < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval);
+ ps_adapter->chip_id == BCS220_3) {
+
+ retval = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
goto err_exit;
}
- //setting 0th bit
+ /* setting 0th bit */
value |= (1<<0);
retval = wrmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
- if( retval < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
}
-
- }
- else
- {
- retval = rdmalt(ps_adapter,0x0f007018, &value, sizeof(value));
- if( retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval);
+ } else {
+ retval = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
goto err_exit;
}
- value&=(~(1<<16));
- retval= wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value)) ;
- if( retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ value &= (~(1<<16));
+ retval = wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
- // Toggling the GPIO 8, 9
+ /* Toggling the GPIO 8, 9 */
value = 0;
retval = wrmalt(ps_adapter, GPIO_OUTPUT_REGISTER, &value, sizeof(value));
- if(retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
value = 0x300;
- retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value)) ;
- if(retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
mdelay(50);
}
- //ps_adapter->downloadDDR = false;
-
- if(ps_adapter->bFlashBoot)
- {
- //In flash boot mode MIPS state register has reverse polarity.
- // So just or with setting bit 30.
- //Make the MIPS in Reset state.
+ /* ps_adapter->downloadDDR = false; */
+ if (ps_adapter->bFlashBoot) {
+ /* In flash boot mode MIPS state register has reverse polarity.
+ * So just or with setting bit 30.
+ * Make the MIPS in Reset state.
+ */
rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue));
-
- uiResetValue |=(1<<30);
+ uiResetValue |= (1<<30);
wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue));
}
- if(ps_adapter->chip_id >= T3LPB)
- {
+ if (ps_adapter->chip_id >= T3LPB) {
uiResetValue = 0;
- //
- // WA for SYSConfig Issue.
- // Read SYSCFG Twice to make it writable.
- //
+ /*
+ * WA for SYSConfig Issue.
+ * Read SYSCFG Twice to make it writable.
+ */
rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));
- if(uiResetValue & (1<<4))
- {
+ if (uiResetValue & (1<<4)) {
uiResetValue = 0;
- rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));//2nd read to make it writable.
+ rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); /* 2nd read to make it writable. */
uiResetValue &= (~(1<<4));
- wrmalt(ps_adapter,SYS_CFG, &uiResetValue, sizeof(uiResetValue));
+ wrmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));
}
-
}
uiResetValue = 0;
wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue));
-err_exit :
- psIntfAdapter->psAdapter->StopAllXaction = FALSE ;
+err_exit:
+ psIntfAdapter->psAdapter->StopAllXaction = FALSE;
return retval;
}
-int run_card_proc(PMINI_ADAPTER ps_adapter )
+int run_card_proc(PMINI_ADAPTER ps_adapter)
{
- unsigned int value=0;
+ unsigned int value = 0;
{
-
- if(rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__);
+ if (rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
return STATUS_FAILURE;
}
- if(ps_adapter->bFlashBoot)
- {
-
- value&=(~(1<<30));
- }
+ if (ps_adapter->bFlashBoot)
+ value &= (~(1<<30));
else
- {
- value |=(1<<30);
- }
+ value |= (1<<30);
- if(wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__);
+ if (wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
return STATUS_FAILURE;
}
}
@@ -1074,104 +947,87 @@ int run_card_proc(PMINI_ADAPTER ps_adapter )
int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter)
{
-
int status;
UINT value = 0;
/*
- * Create the threads first and then download the
- * Firm/DDR Settings..
- */
-
+ * Create the threads first and then download the
+ * Firm/DDR Settings..
+ */
status = create_worker_threads(ps_adapter);
- if (status<0)
+ if (status < 0)
return status;
- /*
- * For Downloading the Firm, parse the cfg file first.
- */
- status = bcm_parse_target_params (ps_adapter);
- if(status){
+ status = bcm_parse_target_params(ps_adapter);
+ if (status)
return status;
- }
- if(ps_adapter->chip_id >= T3LPB)
- {
- rdmalt(ps_adapter, SYS_CFG, &value, sizeof (value));
- ps_adapter->syscfgBefFwDld = value ;
- if((value & 0x60)== 0)
- {
+ if (ps_adapter->chip_id >= T3LPB) {
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ ps_adapter->syscfgBefFwDld = value;
+
+ if ((value & 0x60) == 0)
ps_adapter->bFlashBoot = TRUE;
- }
}
reset_card_proc(ps_adapter);
- //Initializing the NVM.
+ /* Initializing the NVM. */
BcmInitNVM(ps_adapter);
status = ddr_init(ps_adapter);
- if(status)
- {
+ if (status) {
pr_err(DRV_NAME "ddr_init Failed\n");
return status;
}
/* Download cfg file */
status = buffDnldVerify(ps_adapter,
- (PUCHAR)ps_adapter->pstargetparams,
- sizeof(STARGETPARAMS),
- CONFIG_BEGIN_ADDR);
- if(status)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file");
+ (PUCHAR)ps_adapter->pstargetparams,
+ sizeof(STARGETPARAMS),
+ CONFIG_BEGIN_ADDR);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file");
goto OUT;
}
- if(register_networkdev(ps_adapter))
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed.");
+ if (register_networkdev(ps_adapter)) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed.");
return -EIO;
}
- if(FALSE == ps_adapter->AutoFirmDld)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n");
- //If Auto f/w download is disable, register the control interface,
- //register the control interface after the mailbox.
- if(register_control_device_interface(ps_adapter) < 0)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed.");
+ if (FALSE == ps_adapter->AutoFirmDld) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n");
+ /* If Auto f/w download is disable, register the control interface, */
+ /* register the control interface after the mailbox. */
+ if (register_control_device_interface(ps_adapter) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed.");
return -EIO;
}
-
return STATUS_SUCCESS;
}
/*
- * Do the LED Settings here. It will be used by the Firmware Download
- * Thread.
- */
+ * Do the LED Settings here. It will be used by the Firmware Download
+ * Thread.
+ */
/*
- * 1. If the LED Settings fails, do not stop and do the Firmware download.
- * 2. This init would happened only if the cfg file is present, else
- * call from the ioctl context.
- */
-
- status = InitLedSettings (ps_adapter);
+ * 1. If the LED Settings fails, do not stop and do the Firmware download.
+ * 2. This init would happened only if the cfg file is present, else
+ * call from the ioctl context.
+ */
- if(status)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0,"INIT LED FAILED\n");
+ status = InitLedSettings(ps_adapter);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "INIT LED FAILED\n");
return status;
}
- if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
ps_adapter->DriverState = DRIVER_INIT;
wake_up(&ps_adapter->LEDInfo.notify_led_event);
}
- if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
ps_adapter->DriverState = FW_DOWNLOAD;
wake_up(&ps_adapter->LEDInfo.notify_led_event);
}
@@ -1180,37 +1036,32 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter)
wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
- if(ps_adapter->eNVMType == NVM_FLASH)
- {
+ if (ps_adapter->eNVMType == NVM_FLASH) {
status = PropagateCalParamsFromFlashToMemory(ps_adapter);
- if(status)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propagation of Cal param failed .." );
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Propagation of Cal param failed ..");
goto OUT;
}
}
/* Download Firmare */
- if ((status = BcmFileDownload( ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR)))
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present... \n");
+ status = BcmFileDownload(ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR);
+ if (status != 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present...\n");
goto OUT;
}
status = run_card_proc(ps_adapter);
- if(status)
- {
- BCM_DEBUG_PRINT (ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n");
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n");
goto OUT;
}
-
ps_adapter->fw_download_done = TRUE;
mdelay(10);
OUT:
- if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
ps_adapter->DriverState = FW_DOWNLOAD_DONE;
wake_up(&ps_adapter->LEDInfo.notify_led_event);
}
@@ -1218,41 +1069,39 @@ OUT:
return status;
}
-
static int bcm_parse_target_params(PMINI_ADAPTER Adapter)
{
- struct file *flp=NULL;
- mm_segment_t oldfs={0};
+ struct file *flp = NULL;
+ mm_segment_t oldfs = {0};
char *buff;
int len = 0;
- loff_t pos = 0;
+ loff_t pos = 0;
- buff=kmalloc(BUFFER_1K, GFP_KERNEL);
- if(!buff)
- {
+ buff = kmalloc(BUFFER_1K, GFP_KERNEL);
+ if (!buff)
return -ENOMEM;
- }
- if((Adapter->pstargetparams =
- kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL)
- {
+
+ Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL) {
kfree(buff);
return -ENOMEM;
}
- flp=open_firmware_file(Adapter, CFG_FILE);
- if(!flp) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE \n", CFG_FILE);
+
+ flp = open_firmware_file(Adapter, CFG_FILE);
+ if (!flp) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE\n", CFG_FILE);
kfree(buff);
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
return -ENOENT;
}
- oldfs=get_fs(); set_fs(get_ds());
- len=vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos);
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos);
set_fs(oldfs);
- if(len != sizeof(STARGETPARAMS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Mismatch in Target Param Structure!\n");
+ if (len != sizeof(STARGETPARAMS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n");
kfree(buff);
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
@@ -1266,122 +1115,97 @@ static int bcm_parse_target_params(PMINI_ADAPTER Adapter)
* Values in Adapter->pstargetparams are in network byte order
*/
memcpy(Adapter->pstargetparams, buff, sizeof(STARGETPARAMS));
- kfree (buff);
+ kfree(buff);
beceem_parse_target_struct(Adapter);
return STATUS_SUCCESS;
}
void beceem_parse_target_struct(PMINI_ADAPTER Adapter)
{
- UINT uiHostDrvrCfg6 =0, uiEEPROMFlag = 0;
+ UINT uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
- if(ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE)
- {
+ if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) {
pr_info(DRV_NAME ": AutoSyncup is Disabled\n");
Adapter->AutoSyncup = FALSE;
- }
- else
- {
+ } else {
pr_info(DRV_NAME ": AutoSyncup is Enabled\n");
- Adapter->AutoSyncup = TRUE;
+ Adapter->AutoSyncup = TRUE;
}
- if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE)
- {
+ if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) {
pr_info(DRV_NAME ": Enabling autolink up");
Adapter->AutoLinkUp = TRUE;
- }
- else
- {
+ } else {
pr_info(DRV_NAME ": Disabling autolink up");
Adapter->AutoLinkUp = FALSE;
}
- // Setting the DDR Setting..
- Adapter->DDRSetting =
- (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >>8)&0x0F;
- Adapter->ulPowerSaveMode =
- (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F;
-
+ /* Setting the DDR Setting.. */
+ Adapter->DDRSetting = (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >> 8)&0x0F;
+ Adapter->ulPowerSaveMode = (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F;
pr_info(DRV_NAME ": DDR Setting: %x\n", Adapter->DDRSetting);
pr_info(DRV_NAME ": Power Save Mode: %lx\n", Adapter->ulPowerSaveMode);
- if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD)
- {
- pr_info(DRV_NAME ": Enabling Auto Firmware Download\n");
- Adapter->AutoFirmDld = TRUE;
- }
- else
- {
- pr_info(DRV_NAME ": Disabling Auto Firmware Download\n");
- Adapter->AutoFirmDld = FALSE;
- }
+ if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) {
+ pr_info(DRV_NAME ": Enabling Auto Firmware Download\n");
+ Adapter->AutoFirmDld = TRUE;
+ } else {
+ pr_info(DRV_NAME ": Disabling Auto Firmware Download\n");
+ Adapter->AutoFirmDld = FALSE;
+ }
uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6);
Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01;
- pr_info(DRV_NAME ": MIPSConfig : 0x%X\n",Adapter->bMipsConfig);
- //used for backward compatibility.
+ pr_info(DRV_NAME ": MIPSConfig : 0x%X\n", Adapter->bMipsConfig);
+ /* used for backward compatibility. */
Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01;
-
- Adapter->PmuMode= (uiHostDrvrCfg6 >> 24 ) & 0x03;
+ Adapter->PmuMode = (uiHostDrvrCfg6 >> 24) & 0x03;
pr_info(DRV_NAME ": PMU MODE: %x", Adapter->PmuMode);
- if((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT ) & (0x01))
- {
- Adapter->bDoSuspend = TRUE;
- pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile");
- }
+ if ((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT) & (0x01)) {
+ Adapter->bDoSuspend = TRUE;
+ pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile");
+ }
uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag);
- pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n",uiEEPROMFlag);
+ pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n", uiEEPROMFlag);
Adapter->eNVMType = (NVM_TYPE)((uiEEPROMFlag>>4)&0x3);
-
Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1;
-
Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4));
+ Adapter->bSectorSizeOverride = (bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1;
- Adapter->bSectorSizeOverride =(bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1;
-
- if(ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) &0x01)
+ if (ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x01)
Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE;
- if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
+ if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
doPowerAutoCorrection(Adapter);
-
}
static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter)
{
UINT reporting_mode;
- reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) &0x02 ;
+ reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02;
psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1);
- if(reporting_mode == TRUE)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"can't do suspen/resume as reporting mode is enable");
+ if (reporting_mode == TRUE) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "can't do suspen/resume as reporting mode is enable");
psAdapter->bDoSuspend = FALSE;
}
- if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB))
- {
- //If reporting mode is enable, switch PMU to PMC
+ if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) {
+ /* If reporting mode is enable, switch PMU to PMC */
{
psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING;
- psAdapter->bDoSuspend =FALSE;
-
+ psAdapter->bDoSuspend = FALSE;
}
- //clearing space bit[15..12]
+ /* clearing space bit[15..12] */
psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12)));
- //placing the power save mode option
+ /* placing the power save mode option */
psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12));
-
- }
- else if (psAdapter->bIsAutoCorrectEnabled == FALSE)
- {
-
- // remove the autocorrect disable bit set before dumping.
+ } else if (psAdapter->bIsAutoCorrectEnabled == FALSE) {
+ /* remove the autocorrect disable bit set before dumping. */
psAdapter->ulPowerSaveMode &= ~(1 << 3);
psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15));
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode);
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode);
}
}
@@ -1392,182 +1216,160 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress)
unsigned int temp = 0;
unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL);
- if(!pucmacaddr)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n");
+ if (!pucmacaddr) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n");
return NULL;
}
dwAddress |= 0x5b000000;
- status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG,
- (PUINT)&dwAddress, sizeof(UINT));
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n");
+ status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG, (PUINT)&dwAddress, sizeof(UINT));
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n");
kfree(pucmacaddr);
pucmacaddr = NULL;
goto OUT;
}
- for(i=0;i<MAC_ADDRESS_SIZE;i++)
- {
- status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp,sizeof(temp));
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n");
+
+ for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
+ status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp));
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n");
kfree(pucmacaddr);
pucmacaddr = NULL;
goto OUT;
}
pucmacaddr[i] = temp & 0xff;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"%x \n", pucmacaddr[i]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "%x\n", pucmacaddr[i]);
}
OUT:
return pucmacaddr;
}
#endif
-
static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
{
UINT uiIndex = 0;
- if(RWM_WRITE == rwFlag) {
- for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) {
+ if (RWM_WRITE == rwFlag) {
+ for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]);
- }
} else {
- for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) {
+ for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]);
- }
}
}
-#define CACHE_ADDRESS_MASK 0x80000000
-#define UNCACHE_ADDRESS_MASK 0xa0000000
+#define CACHE_ADDRESS_MASK 0x80000000
+#define UNCACHE_ADDRESS_MASK 0xa0000000
int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
- INT uiRetVal =0;
-
- uiRetVal = Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
- uiAddress, pucBuff, sSize);
-
- if(uiRetVal < 0)
- return uiRetVal;
-
- return uiRetVal;
+ return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
+ uiAddress, pucBuff, sSize);
}
+
int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
int iRetVal;
iRetVal = Adapter->interface_wrm(Adapter->pvInterfaceAdapter,
- uiAddress, pucBuff, sSize);
-
-
+ uiAddress, pucBuff, sSize);
return iRetVal;
}
-int wrmalt (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
convertEndian(RWM_WRITE, pucBuff, size);
return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
}
-int rdmalt (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
- INT uiRetVal =0;
+ INT uiRetVal = 0;
- uiRetVal = rdm(Adapter,uiAddress,(PUCHAR)pucBuff,size);
+ uiRetVal = rdm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
convertEndian(RWM_READ, (PUINT)pucBuff, size);
return uiRetVal;
}
-
int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
- INT status = STATUS_SUCCESS ;
+ INT status = STATUS_SUCCESS;
down(&Adapter->rdmwrmsync);
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
status = -EACCES;
goto exit;
}
- status =wrm(Adapter, uiAddress, pucBuff, sSize);
-
+ status = wrm(Adapter, uiAddress, pucBuff, sSize);
exit:
up(&Adapter->rdmwrmsync);
- return status ;
+ return status;
}
-int wrmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
int iRetVal = STATUS_SUCCESS;
down(&Adapter->rdmwrmsync);
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
iRetVal = -EACCES;
goto exit;
}
- iRetVal = wrmalt(Adapter,uiAddress,pucBuff,size);
-
+ iRetVal = wrmalt(Adapter, uiAddress, pucBuff, size);
exit:
up(&Adapter->rdmwrmsync);
return iRetVal;
}
-int rdmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
- INT uiRetVal =STATUS_SUCCESS;
+ INT uiRetVal = STATUS_SUCCESS;
down(&Adapter->rdmwrmsync);
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
uiRetVal = -EACCES;
goto exit;
}
- uiRetVal = rdmalt(Adapter,uiAddress, pucBuff, size);
-
+ uiRetVal = rdmalt(Adapter, uiAddress, pucBuff, size);
exit:
up(&Adapter->rdmwrmsync);
return uiRetVal;
}
-
static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter)
{
- int clear_abort_pattern = 0,Status = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
- //target has woken up From Shut Down
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
- Status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
+ int clear_abort_pattern = 0, Status = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
+ /* target has woken up From Shut Down */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
+ Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
return;
}
- if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
- {
+
+ if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
msleep(100);
InterfaceHandleShutdownModeWakeup(Adapter);
msleep(100);
}
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = NO_NETWORK_ENTRY;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
@@ -1575,55 +1377,49 @@ static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter)
Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
Adapter->bShutStatus = FALSE;
wake_up(&Adapter->lowpower_mode_wait_queue);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
}
static VOID SendShutModeResponse(PMINI_ADAPTER Adapter)
{
- CONTROL_MESSAGE stShutdownResponse;
- UINT NVMAccess = 0,lowPwrAbortMsg = 0;
+ CONTROL_MESSAGE stShutdownResponse;
+ UINT NVMAccess = 0, lowPwrAbortMsg = 0;
UINT Status = 0;
- memset (&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE));
+ memset(&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE));
stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ;
- stShutdownResponse.Leader.PLength = 8;//8 bytes;
+ stShutdownResponse.Leader.PLength = 8; /* 8 bytes; */
stShutdownResponse.szData[0] = LINK_UP_ACK;
stShutdownResponse.szData[1] = LINK_SHUTDOWN_REQ_FROM_FIRMWARE;
/*********************************
- **down_trylock -
- ** if [ semaphore is available ]
- ** acquire semaphone and return value 0 ;
- ** else
- ** return non-zero value ;
- **
- ***********************************/
+ * down_trylock -
+ * if [ semaphore is available ]
+ * acquire semaphone and return value 0 ;
+ * else
+ * return non-zero value ;
+ *
+ ***********************************/
NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync);
- lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync);
-
-
- if(NVMAccess || lowPwrAbortMsg|| atomic_read(&Adapter->TotalPacketCount))
- {
- if(!NVMAccess)
+ if (NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) {
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n");
- stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on.
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n");
+ stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
Adapter->bPreparingForLowPowerMode = FALSE;
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n");
- stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER;//ShutDown ACK
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n");
+ stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER; /* ShutDown ACK */
/* Wait for the LED to TURN OFF before sending ACK response */
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
INT iRetVal = 0;
/* Wake the LED Thread with LOWPOWER_MODE_ENTER State */
@@ -1631,237 +1427,200 @@ static VOID SendShutModeResponse(PMINI_ADAPTER Adapter)
wake_up(&Adapter->LEDInfo.notify_led_event);
/* Wait for 1 SEC for LED to OFF */
- iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent,\
- Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
+ iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
/* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */
- if(iRetVal <= 0)
- {
- stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on.
-
+ if (iRetVal <= 0) {
+ stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
Adapter->DriverState = NO_NETWORK_ENTRY;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
}
- if(stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ACKING SHUTDOWN MODE !!!!!!!!!");
+ if (stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ACKING SHUTDOWN MODE !!!!!!!!!");
down(&Adapter->rdmwrmsync);
Adapter->bPreparingForLowPowerMode = TRUE;
up(&Adapter->rdmwrmsync);
- //Killing all URBS.
- if(Adapter->bDoSuspend == TRUE)
+ /* Killing all URBS. */
+ if (Adapter->bDoSuspend == TRUE)
Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
- }
- else
- {
+ } else {
Adapter->bPreparingForLowPowerMode = FALSE;
}
- if(!NVMAccess)
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
}
- Status = CopyBufferToControlPacket(Adapter,&stShutdownResponse);
- if((Status != STATUS_SUCCESS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"fail to send the Idle mode Request \n");
- Adapter->bPreparingForLowPowerMode = FALSE;
+ Status = CopyBufferToControlPacket(Adapter, &stShutdownResponse);
+ if ((Status != STATUS_SUCCESS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "fail to send the Idle mode Request\n");
+ Adapter->bPreparingForLowPowerMode = FALSE;
StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
}
}
-
-static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer)
+static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer)
{
B_UINT32 uiResetValue = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
- if(*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW)
- {
+ if (*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW) {
HandleShutDownModeWakeup(Adapter);
- }
- else if(*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)
- {
- //Target wants to go to Shut Down Mode
- //InterfacePrepareForShutdown(Adapter);
- if(Adapter->chip_id == BCS220_2 ||
- Adapter->chip_id == BCS220_2BC ||
- Adapter->chip_id == BCS250_BC ||
- Adapter->chip_id == BCS220_3)
- {
- rdmalt(Adapter,HPM_CONFIG_MSW, &uiResetValue, 4);
+ } else if (*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) {
+ /* Target wants to go to Shut Down Mode */
+ /* InterfacePrepareForShutdown(Adapter); */
+ if (Adapter->chip_id == BCS220_2 ||
+ Adapter->chip_id == BCS220_2BC ||
+ Adapter->chip_id == BCS250_BC ||
+ Adapter->chip_id == BCS220_3) {
+
+ rdmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4);
uiResetValue |= (1<<17);
wrmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4);
}
SendShutModeResponse(Adapter);
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
return;
-
}
VOID ResetCounters(PMINI_ADAPTER Adapter)
{
-
- beceem_protocol_reset(Adapter);
-
+ beceem_protocol_reset(Adapter);
Adapter->CurrNumRecvDescs = 0;
- Adapter->PrevNumRecvDescs = 0;
- Adapter->LinkUpStatus = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ Adapter->LinkUpStatus = 0;
Adapter->LinkStatus = 0;
- atomic_set(&Adapter->cntrlpktCnt,0);
- atomic_set (&Adapter->TotalPacketCount,0);
- Adapter->fw_download_done=FALSE;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ atomic_set(&Adapter->TotalPacketCount, 0);
+ Adapter->fw_download_done = FALSE;
Adapter->LinkStatus = 0;
- Adapter->AutoLinkUp = FALSE;
+ Adapter->AutoLinkUp = FALSE;
Adapter->IdleMode = FALSE;
Adapter->bShutStatus = FALSE;
-
}
-S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIP)
+
+S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIP)
{
- UINT uiIndex=0;
- for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++)
- {
- if((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIP)&&
+ UINT uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIP) &&
!Adapter->astFragmentedPktClassifierTable[uiIndex].bOutOfOrderFragment)
+
return Adapter->astFragmentedPktClassifierTable[uiIndex].pstMatchedClassifierEntry;
}
return NULL;
}
-void AddFragIPClsEntry(PMINI_ADAPTER Adapter,PS_FRAGMENTED_PACKET_INFO psFragPktInfo)
+void AddFragIPClsEntry(PMINI_ADAPTER Adapter, PS_FRAGMENTED_PACKET_INFO psFragPktInfo)
{
- UINT uiIndex=0;
- for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++)
- {
- if(!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)
- {
- memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex],psFragPktInfo,sizeof(S_FRAGMENTED_PACKET_INFO));
+ UINT uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) {
+ memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(S_FRAGMENTED_PACKET_INFO));
break;
}
}
-
}
-void DelFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIp)
+void DelFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIp)
{
- UINT uiIndex=0;
- for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++)
- {
- if((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIp))
- memset(&Adapter->astFragmentedPktClassifierTable[uiIndex],0,sizeof(S_FRAGMENTED_PACKET_INFO));
+ UINT uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIp))
+
+ memset(&Adapter->astFragmentedPktClassifierTable[uiIndex], 0, sizeof(S_FRAGMENTED_PACKET_INFO));
}
}
-void update_per_cid_rx (PMINI_ADAPTER Adapter)
+void update_per_cid_rx(PMINI_ADAPTER Adapter)
{
- UINT qindex = 0;
+ UINT qindex = 0;
- if((jiffies - Adapter->liDrainCalculated) < XSECONDS)
+ if ((jiffies - Adapter->liDrainCalculated) < XSECONDS)
return;
- for(qindex = 0; qindex < HiPriority; qindex++)
- {
- if(Adapter->PackInfo[qindex].ucDirection == 0)
- {
+ for (qindex = 0; qindex < HiPriority; qindex++) {
+ if (Adapter->PackInfo[qindex].ucDirection == 0) {
Adapter->PackInfo[qindex].uiCurrentRxRate =
(Adapter->PackInfo[qindex].uiCurrentRxRate +
- Adapter->PackInfo[qindex].uiThisPeriodRxBytes)/2;
+ Adapter->PackInfo[qindex].uiThisPeriodRxBytes) / 2;
Adapter->PackInfo[qindex].uiThisPeriodRxBytes = 0;
- }
- else
- {
+ } else {
Adapter->PackInfo[qindex].uiCurrentDrainRate =
(Adapter->PackInfo[qindex].uiCurrentDrainRate +
- Adapter->PackInfo[qindex].uiThisPeriodSentBytes)/2;
-
- Adapter->PackInfo[qindex].uiThisPeriodSentBytes=0;
+ Adapter->PackInfo[qindex].uiThisPeriodSentBytes) / 2;
+ Adapter->PackInfo[qindex].uiThisPeriodSentBytes = 0;
}
}
- Adapter->liDrainCalculated=jiffies;
+ Adapter->liDrainCalculated = jiffies;
}
-void update_per_sf_desc_cnts( PMINI_ADAPTER Adapter)
+
+void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter)
{
INT iIndex = 0;
u32 uibuff[MAX_TARGET_DSX_BUFFERS];
- if(!atomic_read (&Adapter->uiMBupdate))
+ if (!atomic_read(&Adapter->uiMBupdate))
return;
- if(rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
+ if (rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
return;
}
- for(iIndex = 0;iIndex < HiPriority; iIndex++)
- {
- if(Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection)
- {
- if(Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS)
- {
+
+ for (iIndex = 0; iIndex < HiPriority; iIndex++) {
+ if (Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection) {
+ if (Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS)
atomic_set(&Adapter->PackInfo[iIndex].uiPerSFTxResourceCount, uibuff[Adapter->PackInfo[iIndex].usVCID_Value]);
- }
else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x \n",
- Adapter->PackInfo[iIndex].usVCID_Value);
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x\n", Adapter->PackInfo[iIndex].usVCID_Value);
}
}
- atomic_set (&Adapter->uiMBupdate, FALSE);
+ atomic_set(&Adapter->uiMBupdate, FALSE);
}
void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex)
{
- struct sk_buff* PacketToDrop=NULL;
- struct net_device_stats* netstats = &Adapter->dev->stats;
-
+ struct sk_buff *PacketToDrop = NULL;
+ struct net_device_stats *netstats = &Adapter->dev->stats;
spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
- while(Adapter->PackInfo[iQIndex].FirstTxQueue &&
- atomic_read(&Adapter->TotalPacketCount))
- {
+ while (Adapter->PackInfo[iQIndex].FirstTxQueue && atomic_read(&Adapter->TotalPacketCount)) {
PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
- if(PacketToDrop && PacketToDrop->len)
- {
+ if (PacketToDrop && PacketToDrop->len) {
netstats->tx_dropped++;
- DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, \
- Adapter->PackInfo[iQIndex].LastTxQueue);
-
+ DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, Adapter->PackInfo[iQIndex].LastTxQueue);
Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= PacketToDrop->len;
- //Adding dropped statistics
+ /* Adding dropped statistics */
Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len;
Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
-
dev_kfree_skb(PacketToDrop);
atomic_dec(&Adapter->TotalPacketCount);
}
}
spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
-
}
-static void beceem_protocol_reset (PMINI_ADAPTER Adapter)
+static void beceem_protocol_reset(PMINI_ADAPTER Adapter)
{
int i;
-
if (netif_msg_link(Adapter))
pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name);
@@ -1870,32 +1629,22 @@ static void beceem_protocol_reset (PMINI_ADAPTER Adapter)
Adapter->IdleMode = FALSE;
Adapter->LinkUpStatus = FALSE;
- ClearTargetDSXBuffer(Adapter,0, TRUE);
- //Delete All Classifier Rules
+ ClearTargetDSXBuffer(Adapter, 0, TRUE);
+ /* Delete All Classifier Rules */
- for(i = 0;i<HiPriority;i++)
- {
- DeleteAllClassifiersForSF(Adapter,i);
- }
+ for (i = 0; i < HiPriority; i++)
+ DeleteAllClassifiersForSF(Adapter, i);
flush_all_queues(Adapter);
- if(Adapter->TimerActive == TRUE)
+ if (Adapter->TimerActive == TRUE)
Adapter->TimerActive = FALSE;
- memset(Adapter->astFragmentedPktClassifierTable, 0,
- sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES);
+ memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES);
- for(i = 0;i<HiPriority;i++)
- {
- //resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF.
- // It is same between MIBs and SF.
- memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable,
- 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS));
+ for (i = 0; i < HiPriority; i++) {
+ /* resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. */
+ /* It is same between MIBs and SF. */
+ memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS));
}
}
-
-
-
-
-
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index d1ca191..4aa2b71 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -209,7 +209,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter,
return STATUS_SUCCESS;
}
-int PHSRecieve(PMINI_ADAPTER Adapter,
+int PHSReceive(PMINI_ADAPTER Adapter,
USHORT usVcid,
struct sk_buff *packet,
UINT *punPacketLen,
@@ -223,7 +223,7 @@ int PHSRecieve(PMINI_ADAPTER Adapter,
UINT TotalBytesAdded = 0;
if(!bHeaderSuppressionEnabled)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
return ulPhsStatus;
}
@@ -238,7 +238,7 @@ int PHSRecieve(PMINI_ADAPTER Adapter,
&nTotalsupressedPktHdrBytes,
&nStandardPktHdrLen);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
nTotalsupressedPktHdrBytes,nStandardPktHdrLen);
if(ulPhsStatus != STATUS_PHS_COMPRESSED)
@@ -786,14 +786,14 @@ ULONG PhsDeCompress(IN void* pvContext,
if(pDeviceExtension == NULL)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Invalid Device Extension\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
return ERR_PHS_INVALID_DEVICE_EXETENSION;
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Restoring header \n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n");
phsi = *((unsigned char *)(pvInputBuffer));
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x \n",phsi);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
if(phsi == UNCOMPRESSED_PACKET )
{
return STATUS_PHS_NOCOMPRESSION;
@@ -804,7 +804,7 @@ ULONG PhsDeCompress(IN void* pvContext,
uiVcid,&pstServiceFlowEntry);
if(nSFIndex == PHS_INVALID_TABLE_INDEX)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
return ERR_SF_MATCH_FAIL;
}
@@ -1417,7 +1417,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
int in_buf_len = *header_size-1;
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
in_buf++;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"====>\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"====>\n");
*header_size = 0;
if((decomp_phs_rules == NULL ))
@@ -1425,7 +1425,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
tmp_memb = decomp_phs_rules;
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
+ //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
//*header_size = tmp_memb->u8PHSFLength;
phss = tmp_memb->u8PHSS;
phsf = tmp_memb->u8PHSF;
@@ -1433,7 +1433,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
if(phss > MAX_PHS_LENGTHS)
phss = MAX_PHS_LENGTHS;
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
+ //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
while((phss > 0) && (size < in_buf_len))
{
bit = ((*phsm << i)& SUPPRESS);
@@ -1441,13 +1441,13 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
if(bit == SUPPRESS)
{
*out_buf = *phsf;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d",
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d",
phss,*phsf,*out_buf);
}
else
{
*out_buf = *in_buf;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d",
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d",
phss,*in_buf,*out_buf);
in_buf++;
size++;
diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h
index 0dd05a7..c629585 100644
--- a/drivers/staging/bcm/PHSModule.h
+++ b/drivers/staging/bcm/PHSModule.h
@@ -9,7 +9,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter,
PUINT PacketLen,
UCHAR bEthCSSupport);
-int PHSRecieve(PMINI_ADAPTER Adapter,
+int PHSReceive(PMINI_ADAPTER Adapter,
USHORT usVcid,
struct sk_buff *packet,
UINT *punPacketLen,
diff --git a/drivers/staging/bcm/headers.h b/drivers/staging/bcm/headers.h
index 1148e5e..da47db8 100644
--- a/drivers/staging/bcm/headers.h
+++ b/drivers/staging/bcm/headers.h
@@ -20,25 +20,22 @@
#include <linux/file.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
-#include <net/ip.h>
#include <linux/wait.h>
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
-
-#include <linux/version.h>
#include <linux/stddef.h>
-#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/unistd.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
-#include <asm/uaccess.h>
#include <linux/kthread.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/usb.h>
+#include <asm/uaccess.h>
+#include <net/ip.h>
#include "Typedefs.h"
#include "Version.h"
@@ -61,7 +58,6 @@
#include "Queue.h"
#include "vendorspecificextn.h"
-
#include "InterfaceMacros.h"
#include "InterfaceAdapter.h"
#include "InterfaceIsr.h"
@@ -78,4 +74,6 @@
#define DRV_VERSION VER_FILEVERSION_STR
#define PFX DRV_NAME " "
+extern struct class *bcm_class;
+
#endif
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index 4da5b7b..3de0daf 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -4013,7 +4013,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
@@ -4026,7 +4027,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy = ISOLength;
@@ -4143,7 +4145,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
@@ -4156,7 +4159,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy = ISOLength;
@@ -4257,6 +4261,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
}
+out:
kfree(Buff);
return Status;
diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c
index fc5d07a..63c966a 100644
--- a/drivers/staging/bcm/sort.c
+++ b/drivers/staging/bcm/sort.c
@@ -1,4 +1,5 @@
#include "headers.h"
+#include <linux/sort.h>
/*
* File Name: sort.c
@@ -10,54 +11,42 @@
* Copyright (c) 2007 Beceem Communications Pvt. Ltd
*/
+static int compare_packet_info(void const *a, void const *b)
+{
+ PacketInfo const *pa = a;
+ PacketInfo const *pb = b;
+
+ if (!pa->bValid || !pb->bValid)
+ return 0;
+
+ return pa->u8TrafficPriority - pb->u8TrafficPriority;
+}
+
VOID SortPackInfo(PMINI_ADAPTER Adapter)
{
- UINT nIndex1;
- UINT nIndex2;
-
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=======");
-
- for(nIndex1 = 0; nIndex1 < NO_OF_QUEUES -2 ; nIndex1++)
- {
- for(nIndex2 = nIndex1 + 1 ; nIndex2 < NO_OF_QUEUES -1 ; nIndex2++)
- {
- if(Adapter->PackInfo[nIndex1].bValid && Adapter->PackInfo[nIndex2].bValid)
- {
- if(Adapter->PackInfo[nIndex2].u8TrafficPriority <
- Adapter->PackInfo[nIndex1].u8TrafficPriority)
- {
- PacketInfo stTemppackInfo = Adapter->PackInfo[nIndex2];
- Adapter->PackInfo[nIndex2] = Adapter->PackInfo[nIndex1];
- Adapter->PackInfo[nIndex1] = stTemppackInfo;
-
- }
- }
- }
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "<=======");
+
+ sort(Adapter->PackInfo, NO_OF_QUEUES, sizeof(PacketInfo),
+ compare_packet_info, NULL);
+}
+
+static int compare_classifiers(void const *a, void const *b)
+{
+ S_CLASSIFIER_RULE const *pa = a;
+ S_CLASSIFIER_RULE const *pb = b;
+
+ if (!pa->bUsed || !pb->bUsed)
+ return 0;
+
+ return pa->u8ClassifierRulePriority - pb->u8ClassifierRulePriority;
}
VOID SortClassifiers(PMINI_ADAPTER Adapter)
{
- UINT nIndex1;
- UINT nIndex2;
-
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=======");
-
- for(nIndex1 = 0; nIndex1 < MAX_CLASSIFIERS -1 ; nIndex1++)
- {
- for(nIndex2 = nIndex1 + 1 ; nIndex2 < MAX_CLASSIFIERS ; nIndex2++)
- {
- if(Adapter->astClassifierTable[nIndex1].bUsed && Adapter->astClassifierTable[nIndex2].bUsed)
- {
- if(Adapter->astClassifierTable[nIndex2].u8ClassifierRulePriority <
- Adapter->astClassifierTable[nIndex1].u8ClassifierRulePriority)
- {
- S_CLASSIFIER_RULE stTempClassifierRule = Adapter->astClassifierTable[nIndex2];
- Adapter->astClassifierTable[nIndex2] = Adapter->astClassifierTable[nIndex1];
- Adapter->astClassifierTable[nIndex1] = stTempClassifierRule;
-
- }
- }
- }
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "<=======");
+
+ sort(Adapter->astClassifierTable, MAX_CLASSIFIERS,
+ sizeof(S_CLASSIFIER_RULE), compare_classifiers, NULL);
}
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 727b207..da26630 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -842,6 +842,16 @@ config COMEDI_DT3000
To compile this driver as a module, choose M here: the module will be
called dt3000.
+config COMEDI_DYNA_PCI10XX
+ tristate "Dynalog PCI DAQ series support"
+ default N
+ ---help---
+ Enable support for Dynalog PCI DAQ series
+ PCI-1050
+
+ To compile this driver as a module, choose M here: the module will be
+ called dyna_pci10xx.
+
config COMEDI_UNIOXX5
tristate "Fastwel UNIOxx-5 analog and digital io board support"
default N
@@ -1235,11 +1245,10 @@ config COMEDI_DT9812
called dt9812.
config COMEDI_USBDUX
- tristate "ITL USBDUX support"
+ tristate "ITL USB-DUX-D support"
default N
---help---
- Enable support for the University of Stirling USB DAQ and INCITE
- Technology Limited driver
+ Enable support for the Incite Technology Ltd USB-DUX-D Board
To compile this driver as a module, choose M here: the module will be
called usbdux.
@@ -1249,12 +1258,21 @@ config COMEDI_USBDUXFAST
select COMEDI_FC
default N
---help---
- Enable support for the University of Stirling USB-DUXfast and INCITE
- Technology Limited driver
+ Enable support for the Incite Technology Ltd USB-DUXfast Board
To compile this driver as a module, choose M here: the module will be
called usbduxfast.
+config COMEDI_USBDUXSIGMA
+ tristate "ITL USB-DUXsigma support"
+ select COMEDI_FC
+ default N
+ ---help---
+ Enable support for the Incite Technology Ltd USB-DUXsigma Board
+
+ To compile this driver as a module, choose M here: the module will be
+ called usbduxsigma.
+
config COMEDI_VMK80XX
tristate "Velleman VM110/VM140 USB Board support"
default N
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index 6c900e2..14ea35a 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -514,12 +514,16 @@
return 0x1 + pfi_channel;
else
return 0xb + pfi_channel;
- } static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) {
+ }
+
+ static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel)
+ {
if (rtsi_channel < 7)
return 0xb + rtsi_channel;
else
return 0x1b;
}
+
/* mode bits for NI general-purpose counters, set with
* INSN_CONFIG_SET_COUNTER_MODE */
#define NI_GPCT_COUNTING_MODE_SHIFT 16
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index 41a7a62..a8a0c0f 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -271,7 +271,7 @@ static int compat_cmd(struct file *file, unsigned long arg)
{
struct comedi_cmd __user *cmd;
struct comedi32_cmd_struct __user *cmd32;
- int rc;
+ int rc, err;
cmd32 = compat_ptr(arg);
cmd = compat_alloc_user_space(sizeof(*cmd));
@@ -280,7 +280,15 @@ static int compat_cmd(struct file *file, unsigned long arg)
if (rc)
return rc;
- return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+ rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+ if (rc == -EAGAIN) {
+ /* Special case: copy cmd back to user. */
+ err = put_compat_cmd(cmd32, cmd);
+ if (err)
+ rc = err;
+ }
+
+ return rc;
}
/* Handle 32-bit COMEDI_CMDTEST ioctl. */
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 40b40ed..7e42190 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -101,7 +101,7 @@ static int do_insn_ioctl(struct comedi_device *dev,
static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd,
void *file);
-extern void do_become_nonbusy(struct comedi_device *dev,
+static void do_become_nonbusy(struct comedi_device *dev,
struct comedi_subdevice *s);
static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
@@ -679,7 +679,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
}
insns =
- kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL);
+ kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL);
if (!insns) {
DPRINTK("kmalloc failed\n");
ret = -ENOMEM;
@@ -1078,22 +1078,19 @@ static int do_cmd_ioctl(struct comedi_device *dev,
DPRINTK("subdevice busy\n");
return -EBUSY;
}
- s->busy = file;
/* make sure channel/gain list isn't too long */
if (user_cmd.chanlist_len > s->len_chanlist) {
DPRINTK("channel/gain list too long %u > %d\n",
user_cmd.chanlist_len, s->len_chanlist);
- ret = -EINVAL;
- goto cleanup;
+ return -EINVAL;
}
/* make sure channel/gain list isn't too short */
if (user_cmd.chanlist_len < 1) {
DPRINTK("channel/gain list too short %u < 1\n",
user_cmd.chanlist_len);
- ret = -EINVAL;
- goto cleanup;
+ return -EINVAL;
}
async->cmd = user_cmd;
@@ -1103,8 +1100,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
if (!async->cmd.chanlist) {
DPRINTK("allocation failed\n");
- ret = -ENOMEM;
- goto cleanup;
+ return -ENOMEM;
}
if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist,
@@ -1156,6 +1152,9 @@ static int do_cmd_ioctl(struct comedi_device *dev,
comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
+ /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
+ * comedi_read() or comedi_write() */
+ s->busy = file;
ret = s->do_cmd(dev, s);
if (ret == 0)
return 0;
@@ -1298,10 +1297,10 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
s->lock = file;
spin_unlock_irqrestore(&s->spin_lock, flags);
+#if 0
if (ret < 0)
return ret;
-#if 0
if (s->lock_f)
ret = s->lock_f(dev, s);
#endif
@@ -1658,6 +1657,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
if (count == 0) {
+ mutex_lock(&dev->mutex);
if (comedi_get_subdevice_runflags(s) &
SRF_ERROR) {
retval = -EPIPE;
@@ -1665,6 +1665,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
retval = 0;
}
do_become_nonbusy(dev, s);
+ mutex_unlock(&dev->mutex);
}
break;
}
@@ -1779,6 +1780,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
if (n == 0) {
if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ mutex_lock(&dev->mutex);
do_become_nonbusy(dev, s);
if (comedi_get_subdevice_runflags(s) &
SRF_ERROR) {
@@ -1786,6 +1788,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
} else {
retval = 0;
}
+ mutex_unlock(&dev->mutex);
break;
}
if (file->f_flags & O_NONBLOCK) {
@@ -1823,9 +1826,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
buf += n;
break; /* makes device work like a pipe */
}
- if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING)) &&
- async->buf_read_count - async->buf_write_count == 0) {
- do_become_nonbusy(dev, s);
+ if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING))) {
+ mutex_lock(&dev->mutex);
+ if (async->buf_read_count - async->buf_write_count == 0)
+ do_become_nonbusy(dev, s);
+ mutex_unlock(&dev->mutex);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&async->wait_head, &wait);
@@ -2240,9 +2245,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
return -EBUSY;
}
info->device->minor = i;
- csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL,
- MKDEV(COMEDI_MAJOR, i), NULL,
- hardware_device, "comedi%i", i);
+ csdev = device_create(comedi_class, hardware_device,
+ MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
if (!IS_ERR(csdev))
info->device->class_dev = csdev;
dev_set_drvdata(csdev, info);
@@ -2358,10 +2362,9 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
return -EBUSY;
}
s->minor = i;
- csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev,
- MKDEV(COMEDI_MAJOR, i), NULL, NULL,
- "comedi%i_subd%i", dev->minor,
- (int)(s - dev->subdevices));
+ csdev = device_create(comedi_class, dev->class_dev,
+ MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
+ dev->minor, (int)(s - dev->subdevices));
if (!IS_ERR(csdev))
s->class_dev = csdev;
dev_set_drvdata(csdev, info);
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 5f2745e..00d3c65 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -61,9 +61,6 @@
#define COMEDI_NUM_BOARD_MINORS 0x30
#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
-#define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
- device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
-
struct comedi_subdevice {
struct comedi_device *device;
int type;
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index f9b0286..538b568 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -502,7 +502,11 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
}
if (i == n_pages) {
async->prealloc_buf =
+#ifdef PAGE_KERNEL_NOCACHE
vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
+#else
+ vmap(pages, n_pages, VM_MAP, PAGE_KERNEL);
+#endif
}
vfree(pages);
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 354fb7d..170da60 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_COMEDI_AMPLC_PCI224) += amplc_pci224.o
obj-$(CONFIG_COMEDI_AMPLC_PCI230) += amplc_pci230.o
obj-$(CONFIG_COMEDI_CONTEC_PCI_DIO) += contec_pci_dio.o
obj-$(CONFIG_COMEDI_DT3000) += dt3000.o
+obj-$(CONFIG_COMEDI_DYNA_PCI10XX) += dyna_pci10xx.o
obj-$(CONFIG_COMEDI_UNIOXX5) += unioxx5.o
obj-$(CONFIG_COMEDI_GSC_HPDI) += gsc_hpdi.o
obj-$(CONFIG_COMEDI_ICP_MULTI) += icp_multi.o
@@ -125,6 +126,7 @@ obj-$(CONFIG_COMEDI_QUATECH_DAQP_CS) += quatech_daqp_cs.o
obj-$(CONFIG_COMEDI_DT9812) += dt9812.o
obj-$(CONFIG_COMEDI_USBDUX) += usbdux.o
obj-$(CONFIG_COMEDI_USBDUXFAST) += usbduxfast.o
+obj-$(CONFIG_COMEDI_USBDUXSIGMA) += usbduxsigma.o
obj-$(CONFIG_COMEDI_VMK80XX) += vmk80xx.o
# Comedi NI drivers
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 6cf19ed..6fb7594 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -58,8 +58,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/gfp.h>
+#include <linux/io.h>
#include "../../comedidev.h"
-#include <asm/io.h>
#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
#include <asm/i387.h>
#endif
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 08b71d9..f17654e 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -67,6 +67,7 @@ Configuration options:
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include "amcc_s5933.h"
#include "8253.h"
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index da2b75b..672538e 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -414,6 +414,7 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ unsigned int val;
int n, chan, range, ofs;
chan = CR_CHAN(insn->chanspec);
@@ -429,11 +430,14 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
ofs = PCI171x_DA1;
}
+ val = devpriv->ao_data[chan];
- for (n = 0; n < insn->n; n++)
- outw(data[n], dev->iobase + ofs);
+ for (n = 0; n < insn->n; n++) {
+ val = data[n];
+ outw(val, dev->iobase + ofs);
+ }
- devpriv->ao_data[chan] = data[n];
+ devpriv->ao_data[chan] = val;
return n;
@@ -582,6 +586,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ unsigned int val;
int n, rangereg, chan;
chan = CR_CHAN(insn->chanspec);
@@ -591,13 +596,15 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
outb(rangereg, dev->iobase + PCI1720_RANGE);
devpriv->da_ranges = rangereg;
}
+ val = devpriv->ao_data[chan];
for (n = 0; n < insn->n; n++) {
- outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
+ val = data[n];
+ outw(val, dev->iobase + PCI1720_DA0 + (chan << 1));
outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */
}
- devpriv->ao_data[chan] = data[n];
+ devpriv->ao_data[chan] = val;
return n;
}
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 1b56821..29455a8 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -234,7 +234,7 @@ static int pci1723_insn_read_ao(struct comedi_device *dev,
int n, chan;
chan = CR_CHAN(insn->chanspec);
- DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() ----- \n");
+ DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() -----\n");
for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_data[chan];
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index d23799b..69334f6 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -422,7 +422,7 @@ struct pci_dio_private {
unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */
};
-static struct pci_dio_private *pci_priv = NULL; /* list of allocated cards */
+static struct pci_dio_private *pci_priv; /* list of allocated cards */
#define devpriv ((struct pci_dio_private *)dev->private)
#define this_board ((const struct dio_boardtype *)dev->board_ptr)
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index e0ac825..11cdaf2 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -343,7 +343,7 @@ static int c6xdigio_pwmo_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
+ printk(KERN_DEBUG "c6xdigio_pwmo_insn_read %x\n", insn->n);
return insn->n;
}
@@ -439,9 +439,9 @@ static int c6xdigio_attach(struct comedi_device *dev,
struct comedi_subdevice *s;
iobase = it->options[0];
- printk("comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase);
+ printk(KERN_DEBUG "comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase);
if (!request_region(iobase, C6XDIGIO_SIZE, "c6xdigio")) {
- printk("comedi%d: I/O port conflict\n", dev->minor);
+ printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
return -EIO;
}
dev->iobase = iobase;
@@ -456,9 +456,10 @@ static int c6xdigio_attach(struct comedi_device *dev,
irq = it->options[1];
if (irq > 0)
- printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
+ printk(KERN_DEBUG "comedi%d: irq = %u ignored\n",
+ dev->minor, irq);
else if (irq == 0)
- printk("comedi%d: no irq\n", dev->minor);
+ printk(KERN_DEBUG "comedi%d: no irq\n", dev->minor);
s = dev->subdevices + 0;
/* pwm output subdevice */
@@ -503,7 +504,7 @@ static int c6xdigio_detach(struct comedi_device *dev)
{
/* board_halt(dev); may not need this */
- printk("comedi%d: c6xdigio: remove\n", dev->minor);
+ printk(KERN_DEBUG "comedi%d: c6xdigio: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, C6XDIGIO_SIZE);
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 8a1b8a7..e171c56 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -370,7 +370,8 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* step 2: make sure trigger sources are unique and
+ * mutually compatible */
/* note that mutual compatibility is not an issue here */
if (cmd->scan_begin_src != TRIG_TIMER &&
@@ -508,7 +509,7 @@ static int das16cs_ao_winsn(struct comedi_device *dev,
else
status1 |= 0x0008;
-/* printk("0x%04x\n",status1);*/
+/* printk("0x%04x\n",status1);*/
outw(status1, dev->iobase + 4);
udelay(1);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 1e32419..c651c76 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -424,6 +424,29 @@ static const struct comedi_lrange ai_ranges_64xx = {
}
};
+static const uint8_t ai_range_code_64xx[8] = {
+ 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */
+ 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */
+};
+
+/* analog input ranges for 64-Mx boards */
+static const struct comedi_lrange ai_ranges_64_mx = {
+ 7, {
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ BIP_RANGE(0.625),
+ UNI_RANGE(5),
+ UNI_RANGE(2.5),
+ UNI_RANGE(1.25)
+ }
+};
+
+static const uint8_t ai_range_code_64_mx[7] = {
+ 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */
+ 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */
+};
+
/* analog input ranges for 60xx boards */
static const struct comedi_lrange ai_ranges_60xx = {
4,
@@ -435,6 +458,10 @@ static const struct comedi_lrange ai_ranges_60xx = {
}
};
+static const uint8_t ai_range_code_60xx[4] = {
+ 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */
+};
+
/* analog input ranges for 6030, etc boards */
static const struct comedi_lrange ai_ranges_6030 = {
14,
@@ -456,6 +483,11 @@ static const struct comedi_lrange ai_ranges_6030 = {
}
};
+static const uint8_t ai_range_code_6030[14] = {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */
+ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */
+};
+
/* analog input ranges for 6052, etc boards */
static const struct comedi_lrange ai_ranges_6052 = {
15,
@@ -478,6 +510,11 @@ static const struct comedi_lrange ai_ranges_6052 = {
}
};
+static const uint8_t ai_range_code_6052[15] = {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */
+ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */
+};
+
/* analog input ranges for 4020 board */
static const struct comedi_lrange ai_ranges_4020 = {
2,
@@ -562,6 +599,7 @@ struct pcidas64_board {
int ai_bits; /* analog input resolution */
int ai_speed; /* fastest conversion period in ns */
const struct comedi_lrange *ai_range_table;
+ const uint8_t *ai_range_code;
int ao_nchan; /* number of analog out channels */
int ao_bits; /* analog output resolution */
int ao_scan_speed; /* analog output speed (for a scan, not conversion) */
@@ -620,6 +658,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
.ai_range_table = &ai_ranges_64xx,
+ .ai_range_code = ai_range_code_64xx,
.ao_range_table = &ao_ranges_64xx,
.ao_range_code = ao_range_code_64xx,
.ai_fifo = &ai_fifo_64xx,
@@ -636,6 +675,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
.ai_range_table = &ai_ranges_64xx,
+ .ai_range_code = ai_range_code_64xx,
.ao_range_table = &ao_ranges_64xx,
.ao_range_code = ao_range_code_64xx,
.ai_fifo = &ai_fifo_64xx,
@@ -651,7 +691,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_bits = 16,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ao_range_table = &ao_ranges_64xx,
.ao_range_code = ao_range_code_64xx,
.ai_fifo = &ai_fifo_64xx,
@@ -667,7 +708,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_bits = 16,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ao_range_table = &ao_ranges_64xx,
.ao_range_code = ao_range_code_64xx,
.ai_fifo = &ai_fifo_64xx,
@@ -683,7 +725,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_bits = 16,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ao_range_table = &ao_ranges_64xx,
.ao_range_code = ao_range_code_64xx,
.ai_fifo = &ai_fifo_64xx,
@@ -699,6 +742,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_bits = 16,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ao_range_table = &ao_ranges_60xx,
.ao_range_code = ao_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
@@ -715,6 +759,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 100000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ao_range_table = &ao_ranges_60xx,
.ao_range_code = ao_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
@@ -730,6 +775,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 100000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ao_range_table = &ao_ranges_60xx,
.ao_range_code = ao_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
@@ -746,6 +792,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 100000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ao_range_table = &ao_ranges_60xx,
.ao_range_code = ao_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
@@ -762,6 +809,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 10000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6030,
+ .ai_range_code = ai_range_code_6030,
.ao_range_table = &ao_ranges_6030,
.ao_range_code = ao_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
@@ -778,6 +826,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 10000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6030,
+ .ai_range_code = ai_range_code_6030,
.ao_range_table = &ao_ranges_6030,
.ao_range_code = ao_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
@@ -792,6 +841,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 0,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6030,
+ .ai_range_code = ai_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
.has_8255 = 0,
},
@@ -804,6 +854,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 0,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6030,
+ .ai_range_code = ai_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
.has_8255 = 0,
},
@@ -817,6 +868,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 0,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
.has_8255 = 0,
},
@@ -831,6 +883,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 100000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ao_range_table = &ao_ranges_60xx,
.ao_range_code = ao_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
@@ -847,6 +900,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 100000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_60xx,
+ .ai_range_code = ai_range_code_60xx,
.ao_range_table = &ao_ranges_60xx,
.ao_range_code = ao_range_code_60xx,
.ai_fifo = &ai_fifo_60xx,
@@ -863,6 +917,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 1000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6052,
+ .ai_range_code = ai_range_code_6052,
.ao_range_table = &ao_ranges_6030,
.ao_range_code = ao_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
@@ -879,6 +934,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 3333,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6052,
+ .ai_range_code = ai_range_code_6052,
.ao_range_table = &ao_ranges_6030,
.ao_range_code = ao_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
@@ -895,6 +951,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 1000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6052,
+ .ai_range_code = ai_range_code_6052,
.ao_range_table = &ao_ranges_6030,
.ao_range_code = ao_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
@@ -911,6 +968,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 1000,
.layout = LAYOUT_60XX,
.ai_range_table = &ai_ranges_6052,
+ .ai_range_code = ai_range_code_6052,
.ao_range_table = &ao_ranges_6030,
.ao_range_code = ao_range_code_6030,
.ai_fifo = &ai_fifo_60xx,
@@ -943,6 +1001,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
.ai_range_table = &ai_ranges_64xx,
+ .ai_range_code = ai_range_code_64xx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -955,7 +1014,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 0,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -968,7 +1028,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 0,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -981,7 +1042,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 0,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -994,7 +1056,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 2,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -1007,7 +1070,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 2,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -1020,7 +1084,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
.ao_nchan = 2,
.ao_scan_speed = 10000,
.layout = LAYOUT_64XX,
- .ai_range_table = &ai_ranges_64xx,
+ .ai_range_table = &ai_ranges_64_mx,
+ .ai_range_code = ai_range_code_64_mx,
.ai_fifo = ai_fifo_64xx,
.has_8255 = 1,
},
@@ -1258,45 +1323,7 @@ module_exit(driver_cb_pcidas_cleanup_module);
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
unsigned int range_index)
{
- const struct comedi_krange *range =
- &board(dev)->ai_range_table->range[range_index];
- unsigned int bits = 0;
-
- switch (range->max) {
- case 10000000:
- bits = 0x000;
- break;
- case 5000000:
- bits = 0x100;
- break;
- case 2000000:
- case 2500000:
- bits = 0x200;
- break;
- case 1000000:
- case 1250000:
- bits = 0x300;
- break;
- case 500000:
- bits = 0x400;
- break;
- case 200000:
- case 250000:
- bits = 0x500;
- break;
- case 100000:
- bits = 0x600;
- break;
- case 50000:
- bits = 0x700;
- break;
- default:
- comedi_error(dev, "bug! in ai_range_bits_6xxx");
- break;
- }
- if (range->min == 0)
- bits += 0x900;
- return bits;
+ return board(dev)->ai_range_code[range_index] << 8;
}
static unsigned int hw_revision(const struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 79477a5..b3c9c8f 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -56,10 +56,6 @@ struct pcidio_board {
const char *name; /* name of the board */
int dev_id;
int n_8255; /* number of 8255 chips on board */
-
- /* indices of base address regions */
- int pcicontroler_badrindex;
- int dioregs_badrindex;
};
static const struct pcidio_board pcidio_boards[] = {
@@ -67,22 +63,16 @@ static const struct pcidio_board pcidio_boards[] = {
.name = "pci-dio24",
.dev_id = 0x0028,
.n_8255 = 1,
- .pcicontroler_badrindex = 1,
- .dioregs_badrindex = 2,
},
{
.name = "pci-dio24h",
.dev_id = 0x0014,
.n_8255 = 1,
- .pcicontroler_badrindex = 1,
- .dioregs_badrindex = 2,
},
{
.name = "pci-dio48h",
.dev_id = 0x000b,
.n_8255 = 2,
- .pcicontroler_badrindex = 0,
- .dioregs_badrindex = 1,
},
};
@@ -244,10 +234,15 @@ found:
("cb_pcidio: failed to enable PCI device and request regions\n");
return -EIO;
}
- devpriv->dio_reg_base
- =
+ /*
+ * Use PCI BAR 2 region if non-zero length, else use PCI BAR 1 region.
+ * PCI BAR 1 is only used for older PCI-DIO48H boards. At some point
+ * the PCI-DIO48H was redesigned to use the same PCI interface chip
+ * (and same PCI BAR region) as the other boards.
+ */
+ devpriv->dio_reg_base =
pci_resource_start(devpriv->pci_dev,
- pcidio_boards[index].dioregs_badrindex);
+ (pci_resource_len(pcidev, 2) ? 2 : 1));
/*
* Allocate the subdevice structures. alloc_subdevice() is a
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 966b693..a48fe88 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -385,7 +385,7 @@ static const struct das08_board_struct das08_boards[] = {
.ai = das08_ai_rinsn,
.ai_nbits = 16,
.ai_pg = das08_pg_none,
- .ai_encoding = das08_encode12,
+ .ai_encoding = das08_encode16,
.ao = das08jr_ao_winsn,
.ao_nbits = 16,
.di = das08jr_di_rbits,
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 60c2b12..a6df30b 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -102,6 +102,7 @@ TODO:
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include "../comedidev.h"
#include <linux/ioport.h>
@@ -198,7 +199,7 @@ static void das1800_flush_dma(struct comedi_device *dev,
struct comedi_subdevice *s);
static void das1800_flush_dma_channel(struct comedi_device *dev,
struct comedi_subdevice *s,
- unsigned int channel, uint16_t * buffer);
+ unsigned int channel, uint16_t *buffer);
static void das1800_handle_fifo_half_full(struct comedi_device *dev,
struct comedi_subdevice *s);
static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
@@ -1050,9 +1051,8 @@ static void munge_data(struct comedi_device *dev, uint16_t * array,
/* convert to unsigned type if we are in a bipolar mode */
if (!unipolar) {
- for (i = 0; i < num_elements; i++) {
+ for (i = 0; i < num_elements; i++)
array[i] = munge_bipolar_sample(dev, array[i]);
- }
}
}
@@ -1060,7 +1060,7 @@ static void munge_data(struct comedi_device *dev, uint16_t * array,
* Assumes dma lock is held */
static void das1800_flush_dma_channel(struct comedi_device *dev,
struct comedi_subdevice *s,
- unsigned int channel, uint16_t * buffer)
+ unsigned int channel, uint16_t *buffer)
{
unsigned int num_bytes, num_samples;
struct comedi_cmd *cmd = &s->async->cmd;
@@ -1153,7 +1153,8 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
break;
dpnt = inw(dev->iobase + DAS1800_FIFO);
/* convert to unsigned type if we are in a bipolar mode */
- if (!unipolar) ;
+ if (!unipolar)
+ ;
dpnt = munge_bipolar_sample(dev, dpnt);
cfc_write_to_buffer(s, dpnt);
if (cmd->stop_src == TRIG_COUNT)
@@ -1364,9 +1365,8 @@ static int control_a_bits(struct comedi_cmd cmd)
int control_a;
control_a = FFEN; /* enable fifo */
- if (cmd.stop_src == TRIG_EXT) {
+ if (cmd.stop_src == TRIG_EXT)
control_a |= ATEN;
- }
switch (cmd.start_src) {
case TRIG_EXT:
control_a |= TGEN | CGSL;
@@ -1443,9 +1443,8 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
&(cmd.convert_arg),
cmd.
flags & TRIG_ROUND_MASK);
- if (das1800_set_frequency(dev) < 0) {
+ if (das1800_set_frequency(dev) < 0)
return -1;
- }
}
break;
case TRIG_TIMER: /* in burst mode */
@@ -1454,9 +1453,8 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
&(devpriv->divisor2),
&(cmd.scan_begin_arg),
cmd.flags & TRIG_ROUND_MASK);
- if (das1800_set_frequency(dev) < 0) {
+ if (das1800_set_frequency(dev) < 0)
return -1;
- }
break;
default:
break;
@@ -1553,11 +1551,10 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
* (because dma in handler is unsafe at hard real-time priority) */
- if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
+ if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT))
devpriv->irq_dma_bits &= ~DMA_ENABLED;
- } else {
+ else
devpriv->irq_dma_bits |= devpriv->dma_bits;
- }
/* interrupt on end of conversion for TRIG_WAKE_EOS */
if (cmd.flags & TRIG_WAKE_EOS) {
/* interrupt fifo not empty */
@@ -1567,9 +1564,8 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
devpriv->irq_dma_bits |= FIMD;
}
/* determine how many conversions we need */
- if (cmd.stop_src == TRIG_COUNT) {
+ if (cmd.stop_src == TRIG_COUNT)
devpriv->count = cmd.stop_arg * cmd.chanlist_len;
- }
das1800_cancel(dev, s);
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 00a285c..e3adb38 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -61,6 +61,7 @@ Notes:
#include <linux/gfp.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <asm/dma.h>
#include "comedi_fc.h"
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index c192b71..32e675e 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -69,6 +69,7 @@ TRIG_WAKE_EOS
#include "../comedidev.h"
#include <linux/ioport.h>
+#include <linux/io.h>
#include <asm/dma.h>
#include "8253.h"
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 3330b3d..647c228 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -268,8 +268,9 @@ static const struct ni_board_struct ni_boards[] = {
}
};
-static const int ni_irqpin[] =
- { -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7 };
+static const int ni_irqpin[] = {
+ -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
+};
#define interrupt_pin(a) (ni_irqpin[(a)])
@@ -279,7 +280,10 @@ static const int ni_irqpin[] =
struct ni_private {
struct pnp_dev *isapnp_dev;
- NI_PRIVATE_COMMON};
+ NI_PRIVATE_COMMON
+
+};
+
#define devpriv ((struct ni_private *)dev->private)
/* How we access registers */
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 2672629..e242012 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -51,7 +51,7 @@ IRQ is assigned but not used.
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-static struct pcmcia_device *pcmcia_cur_dev = NULL;
+static struct pcmcia_device *pcmcia_cur_dev;
#define DIO700_SIZE 8 /* size of io region used by board */
@@ -381,11 +381,11 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#endif
break;
default:
- printk("bug! couldn't determine board type\n");
+ printk(KERN_ERR "bug! couldn't determine board type\n");
return -EINVAL;
break;
}
- printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
+ printk(KERN_ERR "comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
thisboard->name, iobase);
#ifdef incomplete
if (irq)
@@ -396,7 +396,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk("\n");
if (iobase == 0) {
- printk("io base address is zero!\n");
+ printk(KERN_ERR "io base address is zero!\n");
return -EINVAL;
}
@@ -421,7 +421,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int dio700_detach(struct comedi_device *dev)
{
- printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
+ printk(KERN_ERR "comedi%d: ni_daq_700: cs-remove\n", dev->minor);
if (dev->subdevices)
subdev_700_cleanup(dev, dev->subdevices + 0);
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 897359d7..0517a23 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -78,6 +78,7 @@ NI manuals:
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include "../comedidev.h"
#include <linux/delay.h>
@@ -212,8 +213,10 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
static irqreturn_t labpc_interrupt(int irq, void *d);
static int labpc_drain_fifo(struct comedi_device *dev);
+#ifdef CONFIG_ISA_DMA_API
static void labpc_drain_dma(struct comedi_device *dev);
static void handle_isa_dma(struct comedi_device *dev);
+#endif
static void labpc_drain_dregs(struct comedi_device *dev);
static int labpc_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd);
@@ -237,9 +240,11 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
-static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_ISA_DMA_API
+static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
+#endif
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
static int labpc_find_device(struct comedi_device *dev, int bus, int slot);
#endif
static int labpc_dio_mem_callback(int dir, int port, int data,
@@ -456,7 +461,7 @@ static const struct labpc_board_struct labpc_boards[] = {
.ai_scan_up = 0,
.memory_mapped_io = 0,
},
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
{
.name = "pci-1200",
.device_id = 0x161,
@@ -500,14 +505,14 @@ static struct comedi_driver driver_labpc = {
.offset = sizeof(struct labpc_board_struct),
};
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)},
{0}
};
MODULE_DEVICE_TABLE(pci, labpc_pci_table);
-#endif /* CONFIG_COMEDI_PCI */
+#endif /* CONFIG_COMEDI_PCI_DRIVERS */
static inline int labpc_counter_load(struct comedi_device *dev,
unsigned long base_address,
@@ -526,7 +531,10 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
{
struct comedi_subdevice *s;
int i;
- unsigned long dma_flags, isr_flags;
+ unsigned long isr_flags;
+#ifdef CONFIG_ISA_DMA_API
+ unsigned long dma_flags;
+#endif
short lsb, msb;
printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor,
@@ -586,6 +594,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
}
dev->irq = irq;
+#ifdef CONFIG_ISA_DMA_API
/* grab dma channel */
if (dma_chan > 3) {
printk(KERN_ERR " invalid dma channel %u\n", dma_chan);
@@ -609,6 +618,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
release_dma_lock(dma_flags);
}
+#endif
dev->board_name = thisboard->name;
@@ -712,7 +722,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase = 0;
unsigned int irq = 0;
unsigned int dma_chan = 0;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
int retval;
#endif
@@ -723,12 +733,18 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* get base address, irq etc. based on bustype */
switch (thisboard->bustype) {
case isa_bustype:
+#ifdef CONFIG_ISA_DMA_API
iobase = it->options[0];
irq = it->options[1];
dma_chan = it->options[2];
+#else
+ printk(KERN_ERR " this driver has not been built with ISA DMA "
+ "support.\n");
+ return -EINVAL;
+#endif
break;
case pci_bustype:
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
retval = labpc_find_device(dev, it->options[0], it->options[1]);
if (retval < 0)
return retval;
@@ -758,7 +774,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* adapted from ni_pcimio for finding mite based boards (pc-1200) */
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
{
struct mite_struct *mite;
@@ -796,15 +812,17 @@ int labpc_common_detach(struct comedi_device *dev)
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 2);
+#ifdef CONFIG_ISA_DMA_API
/* only free stuff if it has been allocated by _attach */
kfree(devpriv->dma_buffer);
if (devpriv->dma_chan)
free_dma(devpriv->dma_chan);
+#endif
if (dev->irq)
free_irq(dev->irq, dev);
if (thisboard->bustype == isa_bustype && dev->iobase)
release_region(dev->iobase, LABPC_SIZE);
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
if (devpriv->mite)
mite_unsetup(devpriv->mite);
#endif
@@ -1134,7 +1152,9 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
int channel, range, aref;
+#ifdef CONFIG_ISA_DMA_API
unsigned long irq_flags;
+#endif
int ret;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
@@ -1181,6 +1201,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->write_byte(INIT_A1_BITS,
dev->iobase + COUNTER_A_CONTROL_REG);
+#ifdef CONFIG_ISA_DMA_API
/* figure out what method we will use to transfer data */
if (devpriv->dma_chan && /* need a dma channel allocated */
/*
@@ -1192,7 +1213,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
thisboard->bustype == isa_bustype) {
xfer = isa_dma_transfer;
/* pc-plus has no fifo-half full interrupt */
- } else if (thisboard->register_layout == labpc_1200_layout &&
+ } else
+#endif
+ if (thisboard->register_layout == labpc_1200_layout &&
/* wake-end-of-scan should interrupt on fifo not empty */
(cmd->flags & TRIG_WAKE_EOS) == 0 &&
/* make sure we are taking more than just a few points */
@@ -1303,6 +1326,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
labpc_clear_adc_fifo(dev);
+#ifdef CONFIG_ISA_DMA_API
/* set up dma transfer */
if (xfer == isa_dma_transfer) {
irq_flags = claim_dma_lock();
@@ -1326,6 +1350,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT;
} else
devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT;
+#endif
/* enable error interrupts */
devpriv->command3_bits |= ERR_INTR_EN_BIT;
@@ -1428,6 +1453,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
+#ifdef CONFIG_ISA_DMA_API
if (devpriv->current_transfer == isa_dma_transfer) {
/*
* if a dma terminal count of external stop trigger
@@ -1439,6 +1465,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
handle_isa_dma(dev);
}
} else
+#endif
labpc_drain_fifo(dev);
if (devpriv->status1_bits & TIMER_BIT) {
@@ -1511,6 +1538,7 @@ static int labpc_drain_fifo(struct comedi_device *dev)
return 0;
}
+#ifdef CONFIG_ISA_DMA_API
static void labpc_drain_dma(struct comedi_device *dev)
{
struct comedi_subdevice *s = dev->read_subdev;
@@ -1573,13 +1601,16 @@ static void handle_isa_dma(struct comedi_device *dev)
/* clear dma tc interrupt */
devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
}
+#endif
/* makes sure all data acquired by board is transferred to comedi (used
* when acquisition is terminated by stop_src == TRIG_EXT). */
static void labpc_drain_dregs(struct comedi_device *dev)
{
+#ifdef CONFIG_ISA_DMA_API
if (devpriv->current_transfer == isa_dma_transfer)
labpc_drain_dma(dev);
+#endif
labpc_drain_fifo(dev);
}
@@ -1771,6 +1802,7 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
return 1;
}
+#ifdef CONFIG_ISA_DMA_API
/* utility function that suggests a dma transfer size in bytes */
static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
{
@@ -1794,6 +1826,7 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
return size;
}
+#endif
/* figures out what counter values to use based on command */
static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
@@ -2107,7 +2140,7 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel,
devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
}
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
static int __devinit driver_labpc_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 8dd3a01..045a4c0 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -688,7 +688,7 @@ static void ni_pcidio_print_status(unsigned int flags)
static void debug_int(struct comedi_device *dev)
{
int a, b;
- static int n_int = 0;
+ static int n_int;
struct timeval tv;
do_gettimeofday(&tv);
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 9148abd..9fee2f2 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -1021,7 +1021,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
@@ -1040,7 +1040,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
@@ -1076,7 +1076,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 32,
.caldac = {caldac_none},
.has_8255 = 0,
@@ -1095,7 +1095,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 32,
.caldac = {caldac_none},
.has_8255 = 0,
@@ -1131,7 +1131,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_628x_ao,
.reg_type = ni_reg_628x,
.ao_unipolar = 1,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
@@ -1150,7 +1150,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_628x_ao,
.reg_type = ni_reg_628x,
.ao_unipolar = 1,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
@@ -1186,7 +1186,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_628x_ao,
.reg_type = ni_reg_628x,
.ao_unipolar = 1,
- .ao_speed = 357,
+ .ao_speed = 350,
.num_p0_dio_channels = 32,
.caldac = {caldac_none},
.has_8255 = 0,
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 09ff472..6fc7464 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -114,6 +114,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/io.h>
#include <asm/dma.h>
#include "8253.h"
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 8f3fc6e..0b9bee3 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -38,6 +38,7 @@ Configuration Options:
#include <linux/mc146818rtc.h>
#include <linux/gfp.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <asm/dma.h>
#include "8253.h"
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 8933e50..b45a9bd 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -104,6 +104,7 @@ A word or two about DMA. Driver support DMA operations at two ways:
#include <linux/mc146818rtc.h>
#include <linux/gfp.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <asm/dma.h>
#include "8253.h"
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index f2e88e5..3ad04aa 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -371,7 +371,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
iobase = it->options[0];
irq[0] = it->options[1];
- printk("comedi%d: %s: io: %lx ", dev->minor, driver.driver_name,
+ printk(KERN_INFO "comedi%d: %s: io: %lx ", dev->minor, driver.driver_name,
iobase);
dev->iobase = iobase;
@@ -379,7 +379,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!iobase || !request_region(iobase,
thisboard->total_iosize,
driver.driver_name)) {
- printk("I/O port conflict\n");
+ printk(KERN_ERR "I/O port conflict\n");
return -EIO;
}
@@ -394,7 +394,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* convenient macro defined in comedidev.h.
*/
if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
- printk("cannot allocate private data structure\n");
+ printk(KERN_ERR "cannot allocate private data structure\n");
return -ENOMEM;
}
@@ -417,7 +417,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private),
GFP_KERNEL);
if (!devpriv->sprivs) {
- printk("cannot allocate subdevice private data structures\n");
+ printk(KERN_ERR "cannot allocate subdevice private data structures\n");
return -ENOMEM;
}
/*
@@ -427,7 +427,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO)
*/
if (alloc_subdevices(dev, n_subdevs) < 0) {
- printk("cannot allocate subdevice data structures\n");
+ printk(KERN_ERR "cannot allocate subdevice data structures\n");
return -ENOMEM;
}
@@ -557,14 +557,14 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
*/
if (irq[0]) {
- printk("irq: %u ", irq[0]);
+ printk(KERN_DEBUG "irq: %u ", irq[0]);
if (thisboard->dio_num_asics == 2 && irq[1])
- printk("second ASIC irq: %u ", irq[1]);
+ printk(KERN_DEBUG "second ASIC irq: %u ", irq[1]);
} else {
- printk("(IRQ mode disabled) ");
+ printk(KERN_INFO "(IRQ mode disabled) ");
}
- printk("attached\n");
+ printk(KERN_INFO "attached\n");
return 1;
}
@@ -581,7 +581,7 @@ static int pcmmio_detach(struct comedi_device *dev)
{
int i;
- printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name);
+ printk(KERN_INFO "comedi%d: %s: remove\n", dev->minor, driver.driver_name);
if (dev->iobase)
release_region(dev->iobase, thisboard->total_iosize);
@@ -622,7 +622,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("write mask: %08x data: %08x\n", data[0], data[1]);
+ printk(KERN_DEBUG "write mask: %08x data: %08x\n", data[0], data[1]);
#endif
s->state = 0;
@@ -644,9 +644,9 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
printk
- ("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ",
- byte_no, (unsigned)write_mask_byte, (unsigned)data_byte,
- offset, ioaddr, (unsigned)byte);
+ (KERN_DEBUG "byte %d wmb %02x db %02x offset %02d io %04x,"
+ " data_in %02x ", byte_no, (unsigned)write_mask_byte,
+ (unsigned)data_byte, offset, ioaddr, (unsigned)byte);
#endif
if (write_mask_byte) {
@@ -663,7 +663,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
}
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("data_out_byte %02x\n", (unsigned)byte);
+ printk(KERN_DEBUG "data_out_byte %02x\n", (unsigned)byte);
#endif
/* save the digital input lines for this byte.. */
s->state |= ((unsigned int)byte) << offset;
@@ -674,7 +674,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("s->state %08x data_out %08x\n", s->state, data[1]);
+ printk(KERN_DEBUG "s->state %08x data_out %08x\n", s->state, data[1]);
#endif
return 2;
@@ -886,7 +886,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
* with commands..
*/
printk
- ("PCMMIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n",
+ (KERN_DEBUG "got edge detect interrupt %d asic %d which_chans: %06x\n",
irq, asic, triggered);
for (s = dev->subdevices + 2;
s < dev->subdevices + dev->n_subdevices;
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index b2c2c89..6c25bd3 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -464,13 +464,13 @@ static int pcmuio_detach(struct comedi_device *dev)
if (dev->iobase)
release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics);
- for (i = 0; i < MAX_ASICS; ++i) {
- if (devpriv->asics[i].irq)
- free_irq(devpriv->asics[i].irq, dev);
- }
-
- if (devpriv && devpriv->sprivs)
+ if (devpriv) {
+ for (i = 0; i < MAX_ASICS; ++i) {
+ if (devpriv->asics[i].irq)
+ free_irq(devpriv->asics[i].irq, dev);
+ }
kfree(devpriv->sprivs);
+ }
return 0;
}
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 7f09ed7..1384419 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -29,8 +29,8 @@ Status: Works. Only tested on DM7520-8. Not SMP safe.
Configuration options:
[0] - PCI bus of device (optional)
- If bus/slot is not specified, the first available PCI
- device will be used.
+ If bus / slot is not specified, the first available PCI
+ device will be used.
[1] - PCI slot of device (optional)
*/
/*
@@ -186,7 +186,7 @@ Configuration options:
| PLX_DEMAND_MODE_BIT)
#define DMA_TRANSFER_BITS (\
-/* descriptors in PCI memory*/ PLX_DESC_IN_PCI_BIT \
+/* descriptors in PCI memory*/ PLX_DESC_IN_PCI_BIT \
/* interrupt at end of block */ | PLX_INTR_TERM_COUNT \
/* from board to PCI */ | PLX_XFER_LOCAL_TO_PCI)
@@ -869,7 +869,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Show board configuration */
- printk("%s:", dev->board_name);
+ printk(KERN_INFO "%s:", dev->board_name);
/*
* Allocate the subdevice structures. alloc_subdevice() is a
@@ -958,7 +958,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
}
dev->irq = devpriv->pci_dev->irq;
- printk("( irq=%u )", dev->irq);
+ printk(KERN_INFO "( irq=%u )", dev->irq);
ret = rtd520_probe_fifo_depth(dev);
if (ret < 0)
@@ -1026,7 +1026,8 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
RtdDma0Mode(dev, DMA_MODE_BITS);
- RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source */
+ /* set DMA trigger source */
+ RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);
} else {
printk(KERN_INFO "( no IRQ->no DMA )");
}
@@ -1202,11 +1203,13 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev,
CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
} else if (range < thisboard->rangeUniStart) { /* second batch are +-10 */
r |= 0x100; /* +-10 range */
- r |= ((range - thisboard->range10Start) & 0x7) << 4; /* gain */
+ /* gain */
+ r |= ((range - thisboard->range10Start) & 0x7) << 4;
CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
} else { /* last batch is +10 */
r |= 0x200; /* +10 range */
- r |= ((range - thisboard->rangeUniStart) & 0x7) << 4; /* gain */
+ /* gain */
+ r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;
CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
}
@@ -1336,7 +1339,8 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
/*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
d = d >> 3; /* low 3 bits are marker lines */
if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0))
- data[n] = d + 2048; /* convert to comedi unsigned data */
+ /* convert to comedi unsigned data */
+ data[n] = d + 2048;
else
data[n] = d;
}
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index ebfce33..ade2202 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -38,7 +38,7 @@ Status: in development
#include <linux/sched.h>
#include <linux/slab.h>
-#include <asm/termios.h>
+#include <linux/termios.h>
#include <asm/ioctls.h>
#include <linux/serial.h>
#include <linux/poll.h>
@@ -192,9 +192,8 @@ static int tty_read(struct file *f, int timeout)
elapsed =
(1000000 * (now.tv_sec - start.tv_sec) +
now.tv_usec - start.tv_usec);
- if (elapsed > timeout) {
+ if (elapsed > timeout)
break;
- }
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(((timeout -
elapsed) * HZ) / 10000);
@@ -204,9 +203,8 @@ static int tty_read(struct file *f, int timeout)
unsigned char ch;
f->f_pos = 0;
- if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) {
+ if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1)
result = ch;
- }
}
} else {
/* Device does not support poll, busy wait */
@@ -215,9 +213,8 @@ static int tty_read(struct file *f, int timeout)
unsigned char ch;
retries++;
- if (retries >= timeout) {
+ if (retries >= timeout)
break;
- }
f->f_pos = 0;
if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) {
@@ -329,7 +326,7 @@ static struct serial_data serial_read(struct file *f, int timeout)
length++;
if (data < 0) {
- printk("serial2002 error\n");
+ printk(KERN_ERR "serial2002 error\n");
break;
} else if (data & 0x80) {
result.value = (result.value << 7) | (data & 0x7f);
@@ -402,7 +399,7 @@ static int serial_2002_open(struct comedi_device *dev)
devpriv->tty = filp_open(port, O_RDWR, 0);
if (IS_ERR(devpriv->tty)) {
result = (int)PTR_ERR(devpriv->tty);
- printk("serial_2002: file open error = %d\n", result);
+ printk(KERN_ERR "serial_2002: file open error = %d\n", result);
} else {
struct config_t {
@@ -516,9 +513,8 @@ static int serial_2002_open(struct comedi_device *dev)
}
break;
}
- if (sign) {
+ if (sign)
min = -min;
- }
cur_config[channel].min
= min;
}
@@ -557,9 +553,8 @@ static int serial_2002_open(struct comedi_device *dev)
}
break;
}
- if (sign) {
+ if (sign)
max = -max;
- }
cur_config[channel].max
= max;
}
@@ -622,9 +617,8 @@ static int serial_2002_open(struct comedi_device *dev)
int j, chan;
for (chan = 0, j = 0; j < 32; j++) {
- if (c[j].kind == kind) {
+ if (c[j].kind == kind)
chan++;
- }
}
s = &dev->subdevices[i];
s->n_chan = chan;
@@ -649,9 +643,8 @@ static int serial_2002_open(struct comedi_device *dev)
}
for (chan = 0, j = 0; j < 32; j++) {
if (c[j].kind == kind) {
- if (mapping) {
+ if (mapping)
mapping[chan] = j;
- }
if (range) {
range[j].length = 1;
range[j].range.min =
@@ -704,9 +697,8 @@ err_alloc_configs:
static void serial_2002_close(struct comedi_device *dev)
{
- if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) {
+ if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0))
filp_close(devpriv->tty, 0);
- }
}
static int serial2002_di_rinsn(struct comedi_device *dev,
@@ -723,9 +715,8 @@ static int serial2002_di_rinsn(struct comedi_device *dev,
poll_digital(devpriv->tty, chan);
while (1) {
read = serial_read(devpriv->tty, 1000);
- if (read.kind != is_digital || read.index == chan) {
+ if (read.kind != is_digital || read.index == chan)
break;
- }
}
data[n] = read.value;
}
@@ -765,9 +756,8 @@ static int serial2002_ai_rinsn(struct comedi_device *dev,
poll_channel(devpriv->tty, chan);
while (1) {
read = serial_read(devpriv->tty, 1000);
- if (read.kind != is_channel || read.index == chan) {
+ if (read.kind != is_channel || read.index == chan)
break;
- }
}
data[n] = read.value;
}
@@ -801,9 +791,8 @@ static int serial2002_ao_rinsn(struct comedi_device *dev,
int n;
int chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++) {
+ for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_readback[chan];
- }
return n;
}
@@ -822,9 +811,8 @@ static int serial2002_ei_rinsn(struct comedi_device *dev,
poll_channel(devpriv->tty, chan);
while (1) {
read = serial_read(devpriv->tty, 1000);
- if (read.kind != is_channel || read.index == chan) {
+ if (read.kind != is_channel || read.index == chan)
break;
- }
}
data[n] = read.value;
}
@@ -838,9 +826,8 @@ static int serial2002_attach(struct comedi_device *dev,
printk("comedi%d: serial2002: ", dev->minor);
dev->board_name = thisboard->name;
- if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) {
+ if (alloc_private(dev, sizeof(struct serial2002_private)) < 0)
return -ENOMEM;
- }
dev->open = serial_2002_open;
dev->close = serial_2002_close;
devpriv->port = it->options[0];
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 526de2e..0316780 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -251,11 +251,11 @@ static int dnp_dio_insn_bits(struct comedi_device *dev,
/* on return, data[1] contains the value of the digital input lines. */
outb(PADR, CSCIR);
- data[0] = inb(CSCDR);
+ data[1] = inb(CSCDR);
outb(PBDR, CSCIR);
- data[0] += inb(CSCDR) << 8;
+ data[1] += inb(CSCDR) << 8;
outb(PCDR, CSCIR);
- data[0] += ((inb(CSCDR) & 0xF0) << 12);
+ data[1] += ((inb(CSCDR) & 0xF0) << 12);
return 2;
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index 598884e..89e62aa 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -75,8 +75,10 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
/* 'private' structure for each subdevice */
struct unioxx5_subd_priv {
int usp_iobase;
- unsigned char usp_module_type[12]; /* 12 modules. each can be 70L or 73L */
- unsigned char usp_extra_data[12][4]; /* for saving previous written value for analog modules */
+ /* 12 modules. each can be 70L or 73L */
+ unsigned char usp_module_type[12];
+ /* for saving previous written value for analog modules */
+ unsigned char usp_extra_data[12][4];
unsigned char usp_prev_wr_val[3]; /* previous written value */
unsigned char usp_prev_cn_val[3]; /* previous channel value */
};
@@ -169,7 +171,7 @@ static int unioxx5_attach(struct comedi_device *dev,
return -1;
}
- printk("attached\n");
+ printk(KERN_INFO "attached\n");
return 0;
}
@@ -181,7 +183,8 @@ static int unioxx5_subdev_read(struct comedi_device *dev,
int channel, type;
channel = CR_CHAN(insn->chanspec);
- type = usp->usp_module_type[channel / 2]; /* defining module type(analog or digital) */
+ /* defining module type(analog or digital) */
+ type = usp->usp_module_type[channel / 2];
if (type == MODULE_DIGITAL) {
if (!__unioxx5_digital_read(usp, data, channel, dev->minor))
@@ -202,7 +205,8 @@ static int unioxx5_subdev_write(struct comedi_device *dev,
int channel, type;
channel = CR_CHAN(insn->chanspec);
- type = usp->usp_module_type[channel / 2]; /* defining module type(analog or digital) */
+ /* defining module type(analog or digital) */
+ type = usp->usp_module_type[channel / 2];
if (type == MODULE_DIGITAL) {
if (!__unioxx5_digital_write(usp, data, channel, dev->minor))
@@ -261,9 +265,12 @@ static int unioxx5_insn_config(struct comedi_device *dev,
* change channel type on input or output) *
\* */
outb(1, usp->usp_iobase + 0);
- outb(flags, usp->usp_iobase + channel_offset); /* changes type of _one_ channel */
- outb(0, usp->usp_iobase + 0); /* sets channels bank to 0(allows directly input/output) */
- usp->usp_prev_cn_val[channel_offset - 1] = flags; /* saves written value */
+ /* changes type of _one_ channel */
+ outb(flags, usp->usp_iobase + channel_offset);
+ /* sets channels bank to 0(allows directly input/output) */
+ outb(0, usp->usp_iobase + 0);
+ /* saves written value */
+ usp->usp_prev_cn_val[channel_offset - 1] = flags;
return 0;
}
@@ -304,14 +311,15 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
}
usp->usp_iobase = subdev_iobase;
- printk("comedi%d: |", minor);
+ printk(KERN_INFO "comedi%d: |", minor);
/* defining modules types */
for (i = 0; i < 12; i++) {
to = 10000;
__unioxx5_analog_config(usp, i * 2);
- outb(i + 1, subdev_iobase + 5); /* sends channel number to card */
+ /* sends channel number to card */
+ outb(i + 1, subdev_iobase + 5);
outb('H', subdev_iobase + 6); /* requests EEPROM world */
while (!(inb(subdev_iobase + 0) & TxBE))
; /* waits while writting will be allowed */
@@ -346,9 +354,10 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
subdev->range_table = &range_digital;
subdev->insn_read = unioxx5_subdev_read;
subdev->insn_write = unioxx5_subdev_write;
- subdev->insn_config = unioxx5_insn_config; /* for digital modules only!!! */
+ /* for digital modules only!!! */
+ subdev->insn_config = unioxx5_insn_config;
- printk("subdevice configured\n");
+ printk(KERN_INFO "subdevice configured\n");
return 0;
}
@@ -367,7 +376,8 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
return 0;
}
- val = usp->usp_prev_wr_val[channel_offset - 1]; /* getting previous written value */
+ /* getting previous written value */
+ val = usp->usp_prev_wr_val[channel_offset - 1];
if (*data)
val |= mask;
@@ -375,7 +385,8 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
val &= ~mask;
outb(val, usp->usp_iobase + channel_offset);
- usp->usp_prev_wr_val[channel_offset - 1] = val; /* saving new written value */
+ /* saving new written value */
+ usp->usp_prev_wr_val[channel_offset - 1] = val;
return 1;
}
@@ -399,7 +410,6 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
if (channel_offset > 1)
channel -= 2 << channel_offset; /* this operation is created for correct readed value to 0 or 1 */
-
*data >>= channel;
return 1;
}
@@ -444,7 +454,8 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);
/* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
- outb(module + 1, usp->usp_iobase + 5); /* sending module number to card(1 .. 12) */
+ /* sending module number to card(1 .. 12) */
+ outb(module + 1, usp->usp_iobase + 5);
outb('W', usp->usp_iobase + 6); /* sends (W)rite command to module */
/* sending for bytes to module(one byte per cycle iteration) */
@@ -475,7 +486,8 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
}
__unioxx5_analog_config(usp, channel);
- outb(module_no + 1, usp->usp_iobase + 5); /* sends module number to card(1 .. 12) */
+ /* sends module number to card(1 .. 12) */
+ outb(module_no + 1, usp->usp_iobase + 5);
outb('V', usp->usp_iobase + 6); /* sends to module (V)erify command */
control = inb(usp->usp_iobase); /* get control register byte */
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 1d09bfa..bf62e0d 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -1465,6 +1465,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
dev_err(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ao_inttrig: invalid trignum\n",
dev->minor);
+ up(&this_usbduxsub->sem);
return -EINVAL;
}
if (!(this_usbduxsub->ao_cmd_running)) {
@@ -1935,11 +1936,8 @@ static int usbdux_pwm_cancel(struct comedi_device *dev,
dev_dbg(&this_usbduxsub->interface->dev,
"comedi %d: sending pwm off command to the usb device.\n",
dev->minor);
- res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
- if (res < 0)
- return res;
- return res;
+ return send_dux_commands(this_usbduxsub, SENDPWMOFF);
}
static void usbduxsub_pwm_irq(struct urb *urb)
@@ -2674,6 +2672,7 @@ static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0) {
dev_err(&udev->interface->dev,
"comedi%d: error alloc space for subdev\n", dev->minor);
+ up(&udev->sem);
up(&start_stop_sem);
return ret;
}
diff --git a/drivers/staging/crystalhd/bc_dts_defs.h b/drivers/staging/crystalhd/bc_dts_defs.h
index 778e76a..fde5b06 100644
--- a/drivers/staging/crystalhd/bc_dts_defs.h
+++ b/drivers/staging/crystalhd/bc_dts_defs.h
@@ -84,7 +84,7 @@ enum BC_SW_OPTIONS {
BC_OPT_LINK_OUT_ENCRYPT = BC_BIT(29),
};
-struct BC_REG_CONFIG{
+struct BC_REG_CONFIG {
uint32_t DbgOptions;
};
@@ -391,7 +391,7 @@ struct BC_PIC_INFO_BLOCK {
* ProcOut Info *
*------------------------------------------------------*/
/* Optional flags for ProcOut Interface.*/
-enum POUT_OPTIONAL_IN_FLAGS_{
+enum POUT_OPTIONAL_IN_FLAGS_ {
/* Flags from App to Device */
BC_POUT_FLAGS_YV12 = 0x01, /* Copy Data in YV12 format */
BC_POUT_FLAGS_STRIDE = 0x02, /* Stride size is valid. */
diff --git a/drivers/staging/crystalhd/bc_dts_glob_lnx.h b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
index 80b7a73..bbe5119 100644
--- a/drivers/staging/crystalhd/bc_dts_glob_lnx.h
+++ b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
@@ -175,7 +175,7 @@ struct BC_DEC_YUV_BUFFS {
uint32_t RefCnt;
};
-enum DECOUT_COMPLETION_FLAGS{
+enum DECOUT_COMPLETION_FLAGS {
COMP_FLAG_NO_INFO = 0x00,
COMP_FLAG_FMT_CHANGE = 0x01,
COMP_FLAG_PIB_VALID = 0x02,
@@ -184,7 +184,7 @@ enum DECOUT_COMPLETION_FLAGS{
COMP_FLAG_DATA_BOT = 0x10,
};
-struct BC_DEC_OUT_BUFF{
+struct BC_DEC_OUT_BUFF {
struct BC_DEC_YUV_BUFFS OutPutBuffs;
struct BC_PIC_INFO_BLOCK PibInfo;
uint32_t Flags;
@@ -289,7 +289,7 @@ struct crystalhd_ioctl_data {
struct crystalhd_ioctl_data *next; /* List/Fifo management */
};
-enum crystalhd_kmod_ver{
+enum crystalhd_kmod_ver {
crystalhd_kmod_major = 0,
crystalhd_kmod_minor = 9,
crystalhd_kmod_rev = 27,
diff --git a/drivers/staging/crystalhd/bc_dts_types.h b/drivers/staging/crystalhd/bc_dts_types.h
index d2131e7..1085a91 100644
--- a/drivers/staging/crystalhd/bc_dts_types.h
+++ b/drivers/staging/crystalhd/bc_dts_types.h
@@ -25,32 +25,7 @@
#ifndef _BC_DTS_TYPES_H_
#define _BC_DTS_TYPES_H_
-#ifdef __LINUX_USER__ /* Don't include these for KERNEL.. */
#include <stdint.h>
-#endif
-
-#ifndef PVOID
-typedef void *PVOID;
-#endif
-
-#ifndef BOOL
-typedef int BOOL;
-#endif
-
-#if defined(__KERNEL__) || defined(__LINUX_USER__)
-
-#ifdef __LINUX_USER__ /* Don't include these for KERNEL */
-typedef uint32_t ULONG;
-typedef int32_t LONG;
-typedef void *HANDLE;
-#ifndef VOID
-typedef void VOID;
-#endif
-typedef void *LPVOID;
-typedef uint32_t DWORD;
-typedef uint32_t UINT32;
-typedef uint32_t *LPDWORD;
-typedef unsigned char *PUCHAR;
#ifndef TRUE
#define TRUE 1
@@ -62,36 +37,4 @@ typedef unsigned char *PUCHAR;
#define TEXT
-#else
-
-/* For Kernel usage.. */
-#endif
-
-#else
-
-#ifndef uint64_t
-typedef struct _uint64_t {
- uint32_t low_dw;
- uint32_t hi_dw;
-} uint64_t;
#endif
-
-#ifndef int32_t
-typedef signed long int32_t;
-#endif
-
-#ifndef uint32_t
-typedef unsigned long uint32_t;
-#endif
-
-#ifndef uint16_t
-typedef unsigned short uint16_t;
-#endif
-
-#ifndef uint8_t
-typedef unsigned char uint8_t;
-#endif
-#endif
-
-#endif
-
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.h b/drivers/staging/crystalhd/crystalhd_cmds.h
index 1013029..f0a2796 100644
--- a/drivers/staging/crystalhd/crystalhd_cmds.h
+++ b/drivers/staging/crystalhd/crystalhd_cmds.h
@@ -36,7 +36,7 @@
#include "crystalhd_misc.h"
#include "crystalhd_hw.h"
-enum crystalhd_state{
+enum crystalhd_state {
BC_LINK_INVALID = 0x00,
BC_LINK_INIT = 0x01,
BC_LINK_CAP_EN = 0x02,
diff --git a/drivers/staging/crystalhd/crystalhd_fw_if.h b/drivers/staging/crystalhd/crystalhd_fw_if.h
index 77560d4..9e2831e 100644
--- a/drivers/staging/crystalhd/crystalhd_fw_if.h
+++ b/drivers/staging/crystalhd/crystalhd_fw_if.h
@@ -31,33 +31,33 @@
/* User Data Header */
struct user_data {
- struct user_data *next;
- uint32_t type;
- uint32_t size;
+ struct user_data *next;
+ uint32_t type;
+ uint32_t size;
};
/*------------------------------------------------------*
* MPEG Extension to the PPB *
*------------------------------------------------------*/
struct ppb_mpeg {
- uint32_t to_be_defined;
- uint32_t valid;
+ uint32_t to_be_defined;
+ uint32_t valid;
- /* Always valid, defaults to picture size if no
- sequence display extension in the stream. */
- uint32_t display_horizontal_size;
- uint32_t display_vertical_size;
+ /* Always valid, defaults to picture size if no
+ sequence display extension in the stream. */
+ uint32_t display_horizontal_size;
+ uint32_t display_vertical_size;
- /* MPEG_VALID_PANSCAN
- Offsets are a copy values from the MPEG stream. */
- uint32_t offset_count;
- int32_t horizontal_offset[3];
- int32_t vertical_offset[3];
+ /* MPEG_VALID_PANSCAN
+ Offsets are a copy values from the MPEG stream. */
+ uint32_t offset_count;
+ int32_t horizontal_offset[3];
+ int32_t vertical_offset[3];
- /* MPEG_VALID_USERDATA
- User data is in the form of a linked list. */
- int32_t userDataSize;
- struct user_data *userData;
+ /* MPEG_VALID_USERDATA
+ User data is in the form of a linked list. */
+ int32_t userDataSize;
+ struct user_data *userData;
};
@@ -66,25 +66,25 @@ struct ppb_mpeg {
* VC1 Extension to the PPB *
*------------------------------------------------------*/
struct ppb_vc1 {
- uint32_t to_be_defined;
- uint32_t valid;
-
- /* Always valid, defaults to picture size if no
- sequence display extension in the stream. */
- uint32_t display_horizontal_size;
- uint32_t display_vertical_size;
-
- /* VC1 pan scan windows */
- uint32_t num_panscan_windows;
- int32_t ps_horiz_offset[4];
- int32_t ps_vert_offset[4];
- int32_t ps_width[4];
- int32_t ps_height[4];
-
- /* VC1_VALID_USERDATA
- User data is in the form of a linked list. */
- int32_t userDataSize;
- struct user_data *userData;
+ uint32_t to_be_defined;
+ uint32_t valid;
+
+ /* Always valid, defaults to picture size if no
+ sequence display extension in the stream. */
+ uint32_t display_horizontal_size;
+ uint32_t display_vertical_size;
+
+ /* VC1 pan scan windows */
+ uint32_t num_panscan_windows;
+ int32_t ps_horiz_offset[4];
+ int32_t ps_vert_offset[4];
+ int32_t ps_width[4];
+ int32_t ps_height[4];
+
+ /* VC1_VALID_USERDATA
+ User data is in the form of a linked list. */
+ int32_t userDataSize;
+ struct user_data *userData;
};
@@ -105,145 +105,145 @@ struct ppb_vc1 {
#define MAX_FGT_VALUE_INTERVAL (256)
struct fgt_sei {
- struct fgt_sei *next;
- unsigned char model_values[3][MAX_FGT_VALUE_INTERVAL][MAX_FGT_MODEL_VALUE];
- unsigned char upper_bound[3][MAX_FGT_VALUE_INTERVAL];
- unsigned char lower_bound[3][MAX_FGT_VALUE_INTERVAL];
-
- unsigned char cancel_flag; /* Cancel flag: 1 no film grain. */
- unsigned char model_id; /* Model id. */
-
- /* +unused SE based on Thomson spec */
- unsigned char color_desc_flag; /* Separate color descrition flag. */
- unsigned char bit_depth_luma; /* Bit depth luma minus 8. */
- unsigned char bit_depth_chroma; /* Bit depth chroma minus 8. */
- unsigned char full_range_flag; /* Full range flag. */
- unsigned char color_primaries; /* Color primaries. */
- unsigned char transfer_charact; /* Transfer characteristics. */
- unsigned char matrix_coeff; /*< Matrix coefficients. */
- /* -unused SE based on Thomson spec */
-
- unsigned char blending_mode_id; /* Blending mode. */
- unsigned char log2_scale_factor; /* Log2 scale factor (2-7). */
- unsigned char comp_flag[3]; /* Components [0,2] parameters present flag. */
- unsigned char num_intervals_minus1[3]; /* Number of intensity level intervals. */
- unsigned char num_model_values[3]; /* Number of model values. */
- uint16_t repetition_period; /* Repetition period (0-16384) */
+ struct fgt_sei *next;
+ unsigned char model_values[3][MAX_FGT_VALUE_INTERVAL][MAX_FGT_MODEL_VALUE];
+ unsigned char upper_bound[3][MAX_FGT_VALUE_INTERVAL];
+ unsigned char lower_bound[3][MAX_FGT_VALUE_INTERVAL];
+
+ unsigned char cancel_flag; /* Cancel flag: 1 no film grain. */
+ unsigned char model_id; /* Model id. */
+
+ /* +unused SE based on Thomson spec */
+ unsigned char color_desc_flag; /* Separate color descrition flag. */
+ unsigned char bit_depth_luma; /* Bit depth luma minus 8. */
+ unsigned char bit_depth_chroma; /* Bit depth chroma minus 8. */
+ unsigned char full_range_flag; /* Full range flag. */
+ unsigned char color_primaries; /* Color primaries. */
+ unsigned char transfer_charact; /* Transfer characteristics. */
+ unsigned char matrix_coeff; /*< Matrix coefficients. */
+ /* -unused SE based on Thomson spec */
+
+ unsigned char blending_mode_id; /* Blending mode. */
+ unsigned char log2_scale_factor; /* Log2 scale factor (2-7). */
+ unsigned char comp_flag[3]; /* Components [0,2] parameters present flag. */
+ unsigned char num_intervals_minus1[3]; /* Number of intensity level intervals. */
+ unsigned char num_model_values[3]; /* Number of model values. */
+ uint16_t repetition_period; /* Repetition period (0-16384) */
};
struct ppb_h264 {
- /* 'valid' specifies which fields (or sets of
- * fields) below are valid. If the corresponding
- * bit in 'valid' is NOT set then that field(s)
- * is (are) not initialized. */
- uint32_t valid;
-
- int32_t poc_top; /* POC for Top Field/Frame */
- int32_t poc_bottom; /* POC for Bottom Field */
- uint32_t idr_pic_id;
-
- /* H264_VALID_PANSCAN */
- uint32_t pan_scan_count;
- int32_t pan_scan_left[3];
- int32_t pan_scan_right[3];
- int32_t pan_scan_top[3];
- int32_t pan_scan_bottom[3];
-
- /* H264_VALID_CT_TYPE */
- uint32_t ct_type_count;
- uint32_t ct_type[3];
-
- /* H264_VALID_SPS_CROP */
- int32_t sps_crop_left;
- int32_t sps_crop_right;
- int32_t sps_crop_top;
- int32_t sps_crop_bottom;
-
- /* H264_VALID_VUI */
- uint32_t chroma_top;
- uint32_t chroma_bottom;
-
- /* H264_VALID_USER */
- uint32_t user_data_size;
- struct user_data *user_data;
-
- /* H264 VALID FGT */
- struct fgt_sei *pfgt;
+ /* 'valid' specifies which fields (or sets of
+ * fields) below are valid. If the corresponding
+ * bit in 'valid' is NOT set then that field(s)
+ * is (are) not initialized. */
+ uint32_t valid;
+
+ int32_t poc_top; /* POC for Top Field/Frame */
+ int32_t poc_bottom; /* POC for Bottom Field */
+ uint32_t idr_pic_id;
+
+ /* H264_VALID_PANSCAN */
+ uint32_t pan_scan_count;
+ int32_t pan_scan_left[3];
+ int32_t pan_scan_right[3];
+ int32_t pan_scan_top[3];
+ int32_t pan_scan_bottom[3];
+
+ /* H264_VALID_CT_TYPE */
+ uint32_t ct_type_count;
+ uint32_t ct_type[3];
+
+ /* H264_VALID_SPS_CROP */
+ int32_t sps_crop_left;
+ int32_t sps_crop_right;
+ int32_t sps_crop_top;
+ int32_t sps_crop_bottom;
+
+ /* H264_VALID_VUI */
+ uint32_t chroma_top;
+ uint32_t chroma_bottom;
+
+ /* H264_VALID_USER */
+ uint32_t user_data_size;
+ struct user_data *user_data;
+
+ /* H264 VALID FGT */
+ struct fgt_sei *pfgt;
};
struct ppb {
- /* Common fields. */
- uint32_t picture_number; /* Ordinal display number */
- uint32_t video_buffer; /* Video (picbuf) number */
- uint32_t video_address; /* Address of picbuf Y */
- uint32_t video_address_uv; /* Address of picbuf UV */
- uint32_t video_stripe; /* Picbuf stripe */
- uint32_t video_width; /* Picbuf width */
- uint32_t video_height; /* Picbuf height */
-
- uint32_t channel_id; /* Decoder channel ID */
- uint32_t status; /* reserved */
- uint32_t width; /* pixels */
- uint32_t height; /* pixels */
- uint32_t chroma_format; /* see above */
- uint32_t pulldown; /* see above */
- uint32_t flags; /* see above */
- uint32_t pts; /* 32 LSBs of PTS */
- uint32_t protocol; /* protocolXXX (above) */
-
- uint32_t frame_rate; /* see above */
- uint32_t matrix_coeff; /* see above */
- uint32_t aspect_ratio; /* see above */
- uint32_t colour_primaries; /* see above */
- uint32_t transfer_char; /* see above */
- uint32_t pcr_offset; /* 45kHz if PCR type; else 27MHz */
- uint32_t n_drop; /* Number of pictures to be dropped */
-
- uint32_t custom_aspect_ratio_width_height;
- /* upper 16-bits is Y and lower 16-bits is X */
-
- uint32_t picture_tag; /* Indexing tag from BUD packets */
- uint32_t picture_done_payload;
- uint32_t picture_meta_payload;
- uint32_t reserved[1];
-
- /* Protocol-specific extensions. */
- union {
- struct ppb_h264 h264;
- struct ppb_mpeg mpeg;
- struct ppb_vc1 vc1;
- } other;
+ /* Common fields. */
+ uint32_t picture_number; /* Ordinal display number */
+ uint32_t video_buffer; /* Video (picbuf) number */
+ uint32_t video_address; /* Address of picbuf Y */
+ uint32_t video_address_uv; /* Address of picbuf UV */
+ uint32_t video_stripe; /* Picbuf stripe */
+ uint32_t video_width; /* Picbuf width */
+ uint32_t video_height; /* Picbuf height */
+
+ uint32_t channel_id; /* Decoder channel ID */
+ uint32_t status; /* reserved */
+ uint32_t width; /* pixels */
+ uint32_t height; /* pixels */
+ uint32_t chroma_format; /* see above */
+ uint32_t pulldown; /* see above */
+ uint32_t flags; /* see above */
+ uint32_t pts; /* 32 LSBs of PTS */
+ uint32_t protocol; /* protocolXXX (above) */
+
+ uint32_t frame_rate; /* see above */
+ uint32_t matrix_coeff; /* see above */
+ uint32_t aspect_ratio; /* see above */
+ uint32_t colour_primaries; /* see above */
+ uint32_t transfer_char; /* see above */
+ uint32_t pcr_offset; /* 45kHz if PCR type; else 27MHz */
+ uint32_t n_drop; /* Number of pictures to be dropped */
+
+ uint32_t custom_aspect_ratio_width_height;
+ /* upper 16-bits is Y and lower 16-bits is X */
+
+ uint32_t picture_tag; /* Indexing tag from BUD packets */
+ uint32_t picture_done_payload;
+ uint32_t picture_meta_payload;
+ uint32_t reserved[1];
+
+ /* Protocol-specific extensions. */
+ union {
+ struct ppb_h264 h264;
+ struct ppb_mpeg mpeg;
+ struct ppb_vc1 vc1;
+ } other;
};
struct c011_pib {
- uint32_t bFormatChange;
- uint32_t resolution;
- uint32_t channelId;
- uint32_t ppbPtr;
- int32_t ptsStcOffset;
- uint32_t zeroPanscanValid;
- uint32_t dramOutBufAddr;
- uint32_t yComponent;
- struct ppb ppb;
+ uint32_t bFormatChange;
+ uint32_t resolution;
+ uint32_t channelId;
+ uint32_t ppbPtr;
+ int32_t ptsStcOffset;
+ uint32_t zeroPanscanValid;
+ uint32_t dramOutBufAddr;
+ uint32_t yComponent;
+ struct ppb ppb;
};
struct dec_rsp_channel_start_video {
- uint32_t command;
- uint32_t sequence;
- uint32_t status;
- uint32_t picBuf;
- uint32_t picRelBuf;
- uint32_t picInfoDeliveryQ;
- uint32_t picInfoReleaseQ;
- uint32_t channelStatus;
- uint32_t userDataDeliveryQ;
- uint32_t userDataReleaseQ;
- uint32_t transportStreamCaptureAddr;
- uint32_t asyncEventQ;
+ uint32_t command;
+ uint32_t sequence;
+ uint32_t status;
+ uint32_t picBuf;
+ uint32_t picRelBuf;
+ uint32_t picInfoDeliveryQ;
+ uint32_t picInfoReleaseQ;
+ uint32_t channelStatus;
+ uint32_t userDataDeliveryQ;
+ uint32_t userDataReleaseQ;
+ uint32_t transportStreamCaptureAddr;
+ uint32_t asyncEventQ;
};
@@ -251,112 +251,112 @@ struct dec_rsp_channel_start_video {
/* host commands */
enum c011_ts_cmd {
- eCMD_TS_GET_NEXT_PIC = 0x7376F100, /* debug get next picture */
- eCMD_TS_GET_LAST_PIC = 0x7376F102, /* debug get last pic status */
- eCMD_TS_READ_WRITE_MEM = 0x7376F104, /* debug read write memory */
-
- /* New API commands */
- /* General commands */
- eCMD_C011_INIT = eCMD_C011_CMD_BASE + 0x01,
- eCMD_C011_RESET = eCMD_C011_CMD_BASE + 0x02,
- eCMD_C011_SELF_TEST = eCMD_C011_CMD_BASE + 0x03,
- eCMD_C011_GET_VERSION = eCMD_C011_CMD_BASE + 0x04,
- eCMD_C011_GPIO = eCMD_C011_CMD_BASE + 0x05,
- eCMD_C011_DEBUG_SETUP = eCMD_C011_CMD_BASE + 0x06,
-
- /* Decoding commands */
- eCMD_C011_DEC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x100,
- eCMD_C011_DEC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x101,
- eCMD_C011_DEC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x102,
- eCMD_C011_DEC_CHAN_STATUS = eCMD_C011_CMD_BASE + 0x103,
- eCMD_C011_DEC_CHAN_FLUSH = eCMD_C011_CMD_BASE + 0x104,
- eCMD_C011_DEC_CHAN_TRICK_PLAY = eCMD_C011_CMD_BASE + 0x105,
- eCMD_C011_DEC_CHAN_TS_PIDS = eCMD_C011_CMD_BASE + 0x106,
- eCMD_C011_DEC_CHAN_PS_STREAM_ID = eCMD_C011_CMD_BASE + 0x107,
- eCMD_C011_DEC_CHAN_INPUT_PARAMS = eCMD_C011_CMD_BASE + 0x108,
- eCMD_C011_DEC_CHAN_VIDEO_OUTPUT = eCMD_C011_CMD_BASE + 0x109,
- eCMD_C011_DEC_CHAN_OUTPUT_FORMAT = eCMD_C011_CMD_BASE + 0x10A,
- eCMD_C011_DEC_CHAN_SCALING_FILTERS = eCMD_C011_CMD_BASE + 0x10B,
- eCMD_C011_DEC_CHAN_OSD_MODE = eCMD_C011_CMD_BASE + 0x10D,
- eCMD_C011_DEC_CHAN_DROP = eCMD_C011_CMD_BASE + 0x10E,
- eCMD_C011_DEC_CHAN_RELEASE = eCMD_C011_CMD_BASE + 0x10F,
- eCMD_C011_DEC_CHAN_STREAM_SETTINGS = eCMD_C011_CMD_BASE + 0x110,
- eCMD_C011_DEC_CHAN_PAUSE_OUTPUT = eCMD_C011_CMD_BASE + 0x111,
- eCMD_C011_DEC_CHAN_CHANGE = eCMD_C011_CMD_BASE + 0x112,
- eCMD_C011_DEC_CHAN_SET_STC = eCMD_C011_CMD_BASE + 0x113,
- eCMD_C011_DEC_CHAN_SET_PTS = eCMD_C011_CMD_BASE + 0x114,
- eCMD_C011_DEC_CHAN_CC_MODE = eCMD_C011_CMD_BASE + 0x115,
- eCMD_C011_DEC_CREATE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x116,
- eCMD_C011_DEC_COPY_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x117,
- eCMD_C011_DEC_DELETE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x118,
- eCMD_C011_DEC_CHAN_SET_DECYPTION = eCMD_C011_CMD_BASE + 0x119,
- eCMD_C011_DEC_CHAN_START_VIDEO = eCMD_C011_CMD_BASE + 0x11A,
- eCMD_C011_DEC_CHAN_STOP_VIDEO = eCMD_C011_CMD_BASE + 0x11B,
- eCMD_C011_DEC_CHAN_PIC_CAPTURE = eCMD_C011_CMD_BASE + 0x11C,
- eCMD_C011_DEC_CHAN_PAUSE = eCMD_C011_CMD_BASE + 0x11D,
- eCMD_C011_DEC_CHAN_PAUSE_STATE = eCMD_C011_CMD_BASE + 0x11E,
- eCMD_C011_DEC_CHAN_SET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x11F,
- eCMD_C011_DEC_CHAN_GET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x120,
- eCMD_C011_DEC_CHAN_SET_FF_RATE = eCMD_C011_CMD_BASE + 0x121,
- eCMD_C011_DEC_CHAN_GET_FF_RATE = eCMD_C011_CMD_BASE + 0x122,
- eCMD_C011_DEC_CHAN_FRAME_ADVANCE = eCMD_C011_CMD_BASE + 0x123,
- eCMD_C011_DEC_CHAN_SET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x124,
- eCMD_C011_DEC_CHAN_GET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x125,
- eCMD_C011_DEC_CHAN_FILL_PIC_BUF = eCMD_C011_CMD_BASE + 0x126,
- eCMD_C011_DEC_CHAN_SET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x127,
- eCMD_C011_DEC_CHAN_GET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x128,
- eCMD_C011_DEC_CHAN_SET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x129,
- eCMD_C011_DEC_CHAN_GET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x12A,
- eCMD_C011_DEC_CHAN_REVERSE_FIELD_STATUS = eCMD_C011_CMD_BASE + 0x12B,
- eCMD_C011_DEC_CHAN_I_PICTURE_FOUND = eCMD_C011_CMD_BASE + 0x12C,
- eCMD_C011_DEC_CHAN_SET_PARAMETER = eCMD_C011_CMD_BASE + 0x12D,
- eCMD_C011_DEC_CHAN_SET_USER_DATA_MODE = eCMD_C011_CMD_BASE + 0x12E,
- eCMD_C011_DEC_CHAN_SET_PAUSE_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x12F,
- eCMD_C011_DEC_CHAN_SET_SLOW_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x130,
- eCMD_C011_DEC_CHAN_SET_FF_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x131,
- eCMD_C011_DEC_CHAN_SET_DISPLAY_TIMING_MODE = eCMD_C011_CMD_BASE + 0x132,
- eCMD_C011_DEC_CHAN_SET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x133,
- eCMD_C011_DEC_CHAN_GET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x134,
- eCMD_C011_DEC_CHAN_SET_REVERSE_FIELD = eCMD_C011_CMD_BASE + 0x135,
- eCMD_C011_DEC_CHAN_STREAM_OPEN = eCMD_C011_CMD_BASE + 0x136,
- eCMD_C011_DEC_CHAN_SET_PCR_PID = eCMD_C011_CMD_BASE + 0x137,
- eCMD_C011_DEC_CHAN_SET_VID_PID = eCMD_C011_CMD_BASE + 0x138,
- eCMD_C011_DEC_CHAN_SET_PAN_SCAN_MODE = eCMD_C011_CMD_BASE + 0x139,
- eCMD_C011_DEC_CHAN_START_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x140,
- eCMD_C011_DEC_CHAN_STOP_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x141,
- eCMD_C011_DEC_CHAN_SET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x142,
- eCMD_C011_DEC_CHAN_GET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x143,
- eCMD_C011_DEC_CHAN_SET_HOST_TRICK_MODE = eCMD_C011_CMD_BASE + 0x144,
- eCMD_C011_DEC_CHAN_SET_OPERATION_MODE = eCMD_C011_CMD_BASE + 0x145,
- eCMD_C011_DEC_CHAN_DISPLAY_PAUSE_UNTO_PTS = eCMD_C011_CMD_BASE + 0x146,
- eCMD_C011_DEC_CHAN_SET_PTS_STC_DIFF_THRESHOLD = eCMD_C011_CMD_BASE + 0x147,
- eCMD_C011_DEC_CHAN_SEND_COMPRESSED_BUF = eCMD_C011_CMD_BASE + 0x148,
- eCMD_C011_DEC_CHAN_SET_CLIPPING = eCMD_C011_CMD_BASE + 0x149,
- eCMD_C011_DEC_CHAN_SET_PARAMETERS_FOR_HARD_RESET_INTERRUPT_TO_HOST
- = eCMD_C011_CMD_BASE + 0x150,
-
- /* Decoder RevD commands */
- eCMD_C011_DEC_CHAN_SET_CSC = eCMD_C011_CMD_BASE + 0x180, /* color space conversion */
- eCMD_C011_DEC_CHAN_SET_RANGE_REMAP = eCMD_C011_CMD_BASE + 0x181,
- eCMD_C011_DEC_CHAN_SET_FGT = eCMD_C011_CMD_BASE + 0x182,
- /* Note: 0x183 not implemented yet in Rev D main */
- eCMD_C011_DEC_CHAN_SET_LASTPICTURE_PADDING = eCMD_C011_CMD_BASE + 0x183,
-
- /* Decoder 7412 commands (7412-only) */
- eCMD_C011_DEC_CHAN_SET_CONTENT_KEY = eCMD_C011_CMD_BASE + 0x190,
- eCMD_C011_DEC_CHAN_SET_SESSION_KEY = eCMD_C011_CMD_BASE + 0x191,
- eCMD_C011_DEC_CHAN_FMT_CHANGE_ACK = eCMD_C011_CMD_BASE + 0x192,
-
- eCMD_C011_DEC_CHAN_CUSTOM_VIDOUT = eCMD_C011_CMD_BASE + 0x1FF,
-
- /* Encoding commands */
- eCMD_C011_ENC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x200,
- eCMD_C011_ENC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x201,
- eCMD_C011_ENC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x202,
- eCMD_C011_ENC_CHAN_CONTROL = eCMD_C011_CMD_BASE + 0x203,
- eCMD_C011_ENC_CHAN_STATISTICS = eCMD_C011_CMD_BASE + 0x204,
-
- eNOTIFY_C011_ENC_CHAN_EVENT = eCMD_C011_CMD_BASE + 0x210,
+ eCMD_TS_GET_NEXT_PIC = 0x7376F100, /* debug get next picture */
+ eCMD_TS_GET_LAST_PIC = 0x7376F102, /* debug get last pic status */
+ eCMD_TS_READ_WRITE_MEM = 0x7376F104, /* debug read write memory */
+
+ /* New API commands */
+ /* General commands */
+ eCMD_C011_INIT = eCMD_C011_CMD_BASE + 0x01,
+ eCMD_C011_RESET = eCMD_C011_CMD_BASE + 0x02,
+ eCMD_C011_SELF_TEST = eCMD_C011_CMD_BASE + 0x03,
+ eCMD_C011_GET_VERSION = eCMD_C011_CMD_BASE + 0x04,
+ eCMD_C011_GPIO = eCMD_C011_CMD_BASE + 0x05,
+ eCMD_C011_DEBUG_SETUP = eCMD_C011_CMD_BASE + 0x06,
+
+ /* Decoding commands */
+ eCMD_C011_DEC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x100,
+ eCMD_C011_DEC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x101,
+ eCMD_C011_DEC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x102,
+ eCMD_C011_DEC_CHAN_STATUS = eCMD_C011_CMD_BASE + 0x103,
+ eCMD_C011_DEC_CHAN_FLUSH = eCMD_C011_CMD_BASE + 0x104,
+ eCMD_C011_DEC_CHAN_TRICK_PLAY = eCMD_C011_CMD_BASE + 0x105,
+ eCMD_C011_DEC_CHAN_TS_PIDS = eCMD_C011_CMD_BASE + 0x106,
+ eCMD_C011_DEC_CHAN_PS_STREAM_ID = eCMD_C011_CMD_BASE + 0x107,
+ eCMD_C011_DEC_CHAN_INPUT_PARAMS = eCMD_C011_CMD_BASE + 0x108,
+ eCMD_C011_DEC_CHAN_VIDEO_OUTPUT = eCMD_C011_CMD_BASE + 0x109,
+ eCMD_C011_DEC_CHAN_OUTPUT_FORMAT = eCMD_C011_CMD_BASE + 0x10A,
+ eCMD_C011_DEC_CHAN_SCALING_FILTERS = eCMD_C011_CMD_BASE + 0x10B,
+ eCMD_C011_DEC_CHAN_OSD_MODE = eCMD_C011_CMD_BASE + 0x10D,
+ eCMD_C011_DEC_CHAN_DROP = eCMD_C011_CMD_BASE + 0x10E,
+ eCMD_C011_DEC_CHAN_RELEASE = eCMD_C011_CMD_BASE + 0x10F,
+ eCMD_C011_DEC_CHAN_STREAM_SETTINGS = eCMD_C011_CMD_BASE + 0x110,
+ eCMD_C011_DEC_CHAN_PAUSE_OUTPUT = eCMD_C011_CMD_BASE + 0x111,
+ eCMD_C011_DEC_CHAN_CHANGE = eCMD_C011_CMD_BASE + 0x112,
+ eCMD_C011_DEC_CHAN_SET_STC = eCMD_C011_CMD_BASE + 0x113,
+ eCMD_C011_DEC_CHAN_SET_PTS = eCMD_C011_CMD_BASE + 0x114,
+ eCMD_C011_DEC_CHAN_CC_MODE = eCMD_C011_CMD_BASE + 0x115,
+ eCMD_C011_DEC_CREATE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x116,
+ eCMD_C011_DEC_COPY_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x117,
+ eCMD_C011_DEC_DELETE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x118,
+ eCMD_C011_DEC_CHAN_SET_DECYPTION = eCMD_C011_CMD_BASE + 0x119,
+ eCMD_C011_DEC_CHAN_START_VIDEO = eCMD_C011_CMD_BASE + 0x11A,
+ eCMD_C011_DEC_CHAN_STOP_VIDEO = eCMD_C011_CMD_BASE + 0x11B,
+ eCMD_C011_DEC_CHAN_PIC_CAPTURE = eCMD_C011_CMD_BASE + 0x11C,
+ eCMD_C011_DEC_CHAN_PAUSE = eCMD_C011_CMD_BASE + 0x11D,
+ eCMD_C011_DEC_CHAN_PAUSE_STATE = eCMD_C011_CMD_BASE + 0x11E,
+ eCMD_C011_DEC_CHAN_SET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x11F,
+ eCMD_C011_DEC_CHAN_GET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x120,
+ eCMD_C011_DEC_CHAN_SET_FF_RATE = eCMD_C011_CMD_BASE + 0x121,
+ eCMD_C011_DEC_CHAN_GET_FF_RATE = eCMD_C011_CMD_BASE + 0x122,
+ eCMD_C011_DEC_CHAN_FRAME_ADVANCE = eCMD_C011_CMD_BASE + 0x123,
+ eCMD_C011_DEC_CHAN_SET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x124,
+ eCMD_C011_DEC_CHAN_GET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x125,
+ eCMD_C011_DEC_CHAN_FILL_PIC_BUF = eCMD_C011_CMD_BASE + 0x126,
+ eCMD_C011_DEC_CHAN_SET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x127,
+ eCMD_C011_DEC_CHAN_GET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x128,
+ eCMD_C011_DEC_CHAN_SET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x129,
+ eCMD_C011_DEC_CHAN_GET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x12A,
+ eCMD_C011_DEC_CHAN_REVERSE_FIELD_STATUS = eCMD_C011_CMD_BASE + 0x12B,
+ eCMD_C011_DEC_CHAN_I_PICTURE_FOUND = eCMD_C011_CMD_BASE + 0x12C,
+ eCMD_C011_DEC_CHAN_SET_PARAMETER = eCMD_C011_CMD_BASE + 0x12D,
+ eCMD_C011_DEC_CHAN_SET_USER_DATA_MODE = eCMD_C011_CMD_BASE + 0x12E,
+ eCMD_C011_DEC_CHAN_SET_PAUSE_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x12F,
+ eCMD_C011_DEC_CHAN_SET_SLOW_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x130,
+ eCMD_C011_DEC_CHAN_SET_FF_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x131,
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_TIMING_MODE = eCMD_C011_CMD_BASE + 0x132,
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x133,
+ eCMD_C011_DEC_CHAN_GET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x134,
+ eCMD_C011_DEC_CHAN_SET_REVERSE_FIELD = eCMD_C011_CMD_BASE + 0x135,
+ eCMD_C011_DEC_CHAN_STREAM_OPEN = eCMD_C011_CMD_BASE + 0x136,
+ eCMD_C011_DEC_CHAN_SET_PCR_PID = eCMD_C011_CMD_BASE + 0x137,
+ eCMD_C011_DEC_CHAN_SET_VID_PID = eCMD_C011_CMD_BASE + 0x138,
+ eCMD_C011_DEC_CHAN_SET_PAN_SCAN_MODE = eCMD_C011_CMD_BASE + 0x139,
+ eCMD_C011_DEC_CHAN_START_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x140,
+ eCMD_C011_DEC_CHAN_STOP_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x141,
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x142,
+ eCMD_C011_DEC_CHAN_GET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x143,
+ eCMD_C011_DEC_CHAN_SET_HOST_TRICK_MODE = eCMD_C011_CMD_BASE + 0x144,
+ eCMD_C011_DEC_CHAN_SET_OPERATION_MODE = eCMD_C011_CMD_BASE + 0x145,
+ eCMD_C011_DEC_CHAN_DISPLAY_PAUSE_UNTO_PTS = eCMD_C011_CMD_BASE + 0x146,
+ eCMD_C011_DEC_CHAN_SET_PTS_STC_DIFF_THRESHOLD = eCMD_C011_CMD_BASE + 0x147,
+ eCMD_C011_DEC_CHAN_SEND_COMPRESSED_BUF = eCMD_C011_CMD_BASE + 0x148,
+ eCMD_C011_DEC_CHAN_SET_CLIPPING = eCMD_C011_CMD_BASE + 0x149,
+ eCMD_C011_DEC_CHAN_SET_PARAMETERS_FOR_HARD_RESET_INTERRUPT_TO_HOST
+ = eCMD_C011_CMD_BASE + 0x150,
+
+ /* Decoder RevD commands */
+ eCMD_C011_DEC_CHAN_SET_CSC = eCMD_C011_CMD_BASE + 0x180, /* color space conversion */
+ eCMD_C011_DEC_CHAN_SET_RANGE_REMAP = eCMD_C011_CMD_BASE + 0x181,
+ eCMD_C011_DEC_CHAN_SET_FGT = eCMD_C011_CMD_BASE + 0x182,
+ /* Note: 0x183 not implemented yet in Rev D main */
+ eCMD_C011_DEC_CHAN_SET_LASTPICTURE_PADDING = eCMD_C011_CMD_BASE + 0x183,
+
+ /* Decoder 7412 commands (7412-only) */
+ eCMD_C011_DEC_CHAN_SET_CONTENT_KEY = eCMD_C011_CMD_BASE + 0x190,
+ eCMD_C011_DEC_CHAN_SET_SESSION_KEY = eCMD_C011_CMD_BASE + 0x191,
+ eCMD_C011_DEC_CHAN_FMT_CHANGE_ACK = eCMD_C011_CMD_BASE + 0x192,
+
+ eCMD_C011_DEC_CHAN_CUSTOM_VIDOUT = eCMD_C011_CMD_BASE + 0x1FF,
+
+ /* Encoding commands */
+ eCMD_C011_ENC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x200,
+ eCMD_C011_ENC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x201,
+ eCMD_C011_ENC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x202,
+ eCMD_C011_ENC_CHAN_CONTROL = eCMD_C011_CMD_BASE + 0x203,
+ eCMD_C011_ENC_CHAN_STATISTICS = eCMD_C011_CMD_BASE + 0x204,
+
+ eNOTIFY_C011_ENC_CHAN_EVENT = eCMD_C011_CMD_BASE + 0x210,
};
diff --git a/drivers/staging/crystalhd/crystalhd_misc.h b/drivers/staging/crystalhd/crystalhd_misc.h
index 382078e..4d61723 100644
--- a/drivers/staging/crystalhd/crystalhd_misc.h
+++ b/drivers/staging/crystalhd/crystalhd_misc.h
@@ -205,12 +205,12 @@ enum _chd_log_levels {
#define BCMLOG_ENTER \
if (g_linklog_level & BCMLOG_ENTER_LEAVE) { \
- printk("Entered %s\n", __func__); \
+ printk(KERN_DEBUG "Entered %s\n", __func__); \
}
#define BCMLOG_LEAVE \
if (g_linklog_level & BCMLOG_ENTER_LEAVE) { \
- printk("Leaving %s\n", __func__); \
+ printk(KERN_DEBUG "Leaving %s\n", __func__); \
}
#define BCMLOG(trace, fmt, args...) \
@@ -221,7 +221,7 @@ if (g_linklog_level & trace) { \
#define BCMLOG_ERR(fmt, args...) \
do { \
if (g_linklog_level & BCMLOG_ERROR) { \
- printk("*ERR*:%s:%d: "fmt, __FILE__, __LINE__, ##args); \
+ printk(KERN_ERR "*ERR*:%s:%d: "fmt, __FILE__, __LINE__, ##args); \
} \
} while (0);
diff --git a/drivers/staging/cxt1e1/Kconfig b/drivers/staging/cxt1e1/Kconfig
index 73430ef..947f42a6 100644
--- a/drivers/staging/cxt1e1/Kconfig
+++ b/drivers/staging/cxt1e1/Kconfig
@@ -6,8 +6,7 @@ config CXT1E1
channelized stream WAN adapter card which contains a HDLC/Transparent
mode controller.
- If you want to compile this driver as a module
- say M here and read <file:Documentation/modules.txt>.
+ If you want to compile this driver as a module say M here.
The module will be called 'cxt1e1'.
If unsure, say N.
diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c
index 9ced08f..911c0e4 100644
--- a/drivers/staging/cxt1e1/linux.c
+++ b/drivers/staging/cxt1e1/linux.c
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/netdevice.h>
+#include <linux/module.h>
#include <linux/hdlc.h>
#include <linux/if_arp.h>
#include <linux/init.h>
@@ -1017,13 +1018,7 @@ c4_add_dev (hdw_info_t * hi, int brdno, unsigned long f0, unsigned long f1,
**************************************************************/
if (request_irq (irq0, &c4_linux_interrupt,
-#if defined(SBE_ISR_TASKLET)
- IRQF_DISABLED | IRQF_SHARED,
-#elif defined(SBE_ISR_IMMEDIATE)
- IRQF_DISABLED | IRQF_SHARED,
-#elif defined(SBE_ISR_INLINE)
IRQF_SHARED,
-#endif
ndev->name, ndev))
{
pr_warning("%s: MUSYCC could not get irq: %d\n", ndev->name, irq0);
diff --git a/drivers/staging/cxt1e1/sbecom_inline_linux.h b/drivers/staging/cxt1e1/sbecom_inline_linux.h
index 501a331..9ea2c0c 100644
--- a/drivers/staging/cxt1e1/sbecom_inline_linux.h
+++ b/drivers/staging/cxt1e1/sbecom_inline_linux.h
@@ -43,82 +43,17 @@
*/
-#if defined (__FreeBSD__) || defined (__NetBSD__)
-#include <sys/types.h>
-#else
#include <linux/types.h>
-#include <linux/version.h>
-#if defined(CONFIG_SMP) && ! defined(__SMP__)
-#define __SMP__
-#endif
-#if defined(CONFIG_MODVERSIONS) && defined(MODULE) && ! defined(MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <config/modversions.h>
-#endif
#include <linux/module.h>
-#endif
-#endif
-
#include <linux/kernel.h> /* resolves kmalloc references */
#include <linux/skbuff.h> /* resolves skb references */
#include <linux/netdevice.h> /* resolves dev_kree_skb_any */
#include <asm/byteorder.h> /* resolves cpu_to_le32 */
-#if 0
-
-/*** PORT POINT WARNING
- ***
- *** Under Linux 2.6 it has been found that compiler is re-ordering
- *** in-lined pci_write_32() functions to the detrement of correct
- *** hardware setup. Therefore, inlining of PCI accesses has been
- *** de-implemented, and subroutine calls have been implemented.
- ***/
-
-static inline u_int32_t
-pci_read_32 (u_int32_t *p)
-{
-#ifdef FLOW_DEBUG
- u_int32_t v;
-
- FLUSH_PCI_READ ();
- v = le32_to_cpu (*p);
- if (cxt1e1_log_level >= LOG_DEBUG)
- pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
- return v;
-#else
- FLUSH_PCI_READ (); /* */
- return le32_to_cpu (*p);
-#endif
-}
-
-static inline void
-pci_write_32 (u_int32_t *p, u_int32_t v)
-{
-#ifdef FLOW_DEBUG
- if (cxt1e1_log_level >= LOG_DEBUG)
- pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
-#endif
- *p = cpu_to_le32 (v);
- FLUSH_PCI_WRITE (); /* This routine is called from routines
- * which do multiple register writes
- * which themselves need flushing between
- * writes in order to guarantee write
- * ordering. It is less code-cumbersome
- * to flush here-in then to investigate
- * and code the many other register
- * writing routines. */
-}
-#else
/* forward reference */
u_int32_t pci_read_32 (u_int32_t *p);
void pci_write_32 (u_int32_t *p, u_int32_t v);
-#endif
-
/*
* system dependent callbacks
diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c
index c0adae1..afbf544 100644
--- a/drivers/staging/echo/echo.c
+++ b/drivers/staging/echo/echo.c
@@ -276,7 +276,6 @@ error_oom:
kfree(ec);
return NULL;
}
-
EXPORT_SYMBOL_GPL(oslec_create);
void oslec_free(struct oslec_state *ec)
@@ -290,14 +289,12 @@ void oslec_free(struct oslec_state *ec)
kfree(ec->snapshot);
kfree(ec);
}
-
EXPORT_SYMBOL_GPL(oslec_free);
void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
{
ec->adaption_mode = adaption_mode;
}
-
EXPORT_SYMBOL_GPL(oslec_adaption_mode);
void oslec_flush(struct oslec_state *ec)
@@ -324,14 +321,12 @@ void oslec_flush(struct oslec_state *ec)
ec->curr_pos = ec->taps - 1;
ec->Pstates = 0;
}
-
EXPORT_SYMBOL_GPL(oslec_flush);
void oslec_snapshot(struct oslec_state *ec)
{
memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
}
-
EXPORT_SYMBOL_GPL(oslec_snapshot);
/* Dual Path Echo Canceller */
@@ -406,7 +401,7 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
/* efficient "out with the old and in with the new" algorithm so
we don't have to recalculate over the whole block of
samples. */
- new = (int)tx *(int)tx;
+ new = (int)tx * (int)tx;
old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
(int)ec->fir_state.history[ec->fir_state.curr_pos];
ec->Pstates +=
@@ -603,7 +598,6 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
return (int16_t) ec->clean_nlp << 1;
}
-
EXPORT_SYMBOL_GPL(oslec_update);
/* This function is separated from the echo canceller is it is usually called
@@ -628,7 +622,7 @@ EXPORT_SYMBOL_GPL(oslec_update);
giving very clean DC removal.
*/
-int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx)
+int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
{
int tmp, tmp1;
@@ -657,7 +651,6 @@ int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx)
return tx;
}
-
EXPORT_SYMBOL_GPL(oslec_hpf_tx);
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
deleted file mode 100644
index e2321a4..0000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-device "ft1000_cs"
- class "network" module "ft1000","ft1000_cs"
-
-card "flarion FT1000"
- manfid 0x02cc, 0x0100
- bind "ft1000_cs"
-
-card "flarion FT1000"
- manfid 0x02cc, 0x1000
- bind "ft1000_cs"
-
-card "flarion FT1000"
- manfid 0x02cc, 0x1300
- bind "ft1000_cs"
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
index 61e1cfc..adb436e 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
@@ -1,409 +1,99 @@
-//---------------------------------------------------------------------------
-// FT1000 driver for Flarion Flash OFDM NIC Device
-//
-// Copyright (C) 2002 Flarion Technologies, All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or (at your option) any
-// later version. This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details. You should have received a copy of the GNU General Public
-// License along with this program; if not, write to the
-// Free Software Foundation, Inc., 59 Temple Place -
-// Suite 330, Boston, MA 02111-1307, USA.
-//---------------------------------------------------------------------------
-//
-// File: ft1000.h
-//
-// Description: Common structures and defines
-//
-// History:
-// 8/29/02 Whc Ported to Linux.
-// 7/19/04 Whc Drop packet and cmd msg with pseudo header
-// checksum
-// 10/27/04 Whc Added dynamic downloading of test image.
-// 01/11/04 Whc Added support for Magnemite ASIC
-//
-//---------------------------------------------------------------------------
+/*---------------------------------------------------------------------------
+ FT1000 driver for Flarion Flash OFDM NIC Device
+
+ Copyright (C) 2002 Flarion Technologies, All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your option) any
+ later version. This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details. You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place -
+ Suite 330, Boston, MA 02111-1307, USA.
+---------------------------------------------------------------------------
+ Description: Common structures and defines
+---------------------------------------------------------------------------*/
#ifndef _FT1000H_
#define _FT1000H_
-
-#define FT1000_DRV_VER 0x01010300
-
-#define DSPVERSZ 4
-#define HWSERNUMSZ 16
-#define SKUSZ 20
-#define EUISZ 8
-#define MODESZ 2
-#define CALVERSZ 2
-#define CALDATESZ 6
-
-// Pseudo Header structure
-typedef struct _PSEUDO_HDR
-{
- unsigned short length; // length of msg body
- unsigned char source; // hardware source id
- // Host = 0x10
- // Dsp = 0x20
- unsigned char destination; // hardware destination id (refer to source)
- unsigned char portdest; // software destination port id
- // Host = 0x00
- // Applicaton Broadcast = 0x10
- // Network Stack = 0x20
- // Dsp OAM = 0x80
- // Dsp Airlink = 0x90
- // Dsp Loader = 0xa0
- // Dsp MIP = 0xb0
- unsigned char portsrc; // software source port id (refer to portdest)
- unsigned short sh_str_id; // not used
- unsigned char control; // not used
- unsigned char rsvd1;
- unsigned char seq_num; // message sequence number
- unsigned char rsvd2;
- unsigned short qos_class; // not used
- unsigned short checksum; // pseudo header checksum
-} __attribute__ ((packed)) PSEUDO_HDR, *PPSEUDO_HDR;
-
-// Definitions to maintain compatibility between other platforms
-#define UCHAR u8
-#define USHORT u16
-#define ULONG u32
-#define BOOLEAN u8
-#define PULONG u32 *
-#define PUSHORT u16 *
-#define PUCHAR u8 *
-#define PCHAR u8 *
-#define UINT u32
-
-#define ELECTRABUZZ_ID 0 // ASIC ID for Electrabuzz
-#define MAGNEMITE_ID 0x1a01 // ASIC ID for Magnemite
-
-// MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE
-#define FT1000_REG_DPRAM_ADDR 0x000E // DPADR - Dual Port Ram Indirect Address Register
-#define FT1000_REG_SUP_CTRL 0x0020 // HCTR - Host Control Register
-#define FT1000_REG_SUP_STAT 0x0022 // HSTAT - Host Status Register
-#define FT1000_REG_RESET 0x0024 // HCTR - Host Control Register
-#define FT1000_REG_SUP_ISR 0x0026 // HISR - Host Interrupt Status Register
-#define FT1000_REG_SUP_IMASK 0x0028 // HIMASK - Host Interrupt Mask
-#define FT1000_REG_DOORBELL 0x002a // DBELL - Door Bell Register
-#define FT1000_REG_ASIC_ID 0x002e // ASICID - ASIC Identification Number
- // (Electrabuzz=0 Magnemite=0x1A01)
-
-// MEMORY MAP FOR ELECTRABUZZ ASIC
-
-#define FT1000_REG_UFIFO_STAT 0x0000 // UFSR - Uplink FIFO status register
-#define FT1000_REG_UFIFO_BEG 0x0002 // UFBR - Uplink FIFO beginning register
-#define FT1000_REG_UFIFO_MID 0x0004 // UFMR - Uplink FIFO middle register
-#define FT1000_REG_UFIFO_END 0x0006 // UFER - Uplink FIFO end register
-#define FT1000_REG_DFIFO_STAT 0x0008 // DFSR - Downlink FIFO status register
-#define FT1000_REG_DFIFO 0x000A // DFR - Downlink FIFO Register
-#define FT1000_REG_DPRAM_DATA 0x000C // DPRAM - Dual Port Indirect Data Register
-#define FT1000_REG_WATERMARK 0x0010 // WMARK - Watermark Register
-
-// MEMORY MAP FOR MAGNEMITE
-#define FT1000_REG_MAG_UFDR 0x0000 // UFDR - Uplink FIFO Data Register (32-bits)
-#define FT1000_REG_MAG_UFDRL 0x0000 // UFDRL - Uplink FIFO Data Register low-word (16-bits)
-#define FT1000_REG_MAG_UFDRH 0x0002 // UFDRH - Uplink FIFO Data Register high-word (16-bits)
-#define FT1000_REG_MAG_UFER 0x0004 // UFER - Uplink FIFO End Register
-#define FT1000_REG_MAG_UFSR 0x0006 // UFSR - Uplink FIFO Status Register
-#define FT1000_REG_MAG_DFR 0x0008 // DFR - Downlink FIFO Register (32-bits)
-#define FT1000_REG_MAG_DFRL 0x0008 // DFRL - Downlink FIFO Register low-word (16-bits)
-#define FT1000_REG_MAG_DFRH 0x000a // DFRH - Downlink FIFO Register high-word (16-bits)
-#define FT1000_REG_MAG_DFSR 0x000c // DFSR - Downlink FIFO Status Register
-#define FT1000_REG_MAG_DPDATA 0x0010 // DPDATA - Dual Port RAM Indirect Data Register (32-bits)
-#define FT1000_REG_MAG_DPDATAL 0x0010 // DPDATAL - Dual Port RAM Indirect Data Register low-word (16-bits)
-#define FT1000_REG_MAG_DPDATAH 0x0012 // DPDATAH - Dual Port RAM Indirect Data Register high-word (16-bits)
-#define FT1000_REG_MAG_WATERMARK 0x002c // WMARK - Watermark Register
-
-// Reserved Dual Port RAM offsets for Electrabuzz
-#define FT1000_DPRAM_TX_BASE 0x0002 // Host to PC Card Messaging Area
-#define FT1000_DPRAM_RX_BASE 0x0800 // PC Card to Host Messaging Area
-#define FT1000_FIFO_LEN 0x7FC // total length for DSP FIFO tracking
-#define FT1000_HI_HO 0x7FE // heartbeat with HI/HO
-#define FT1000_DSP_STATUS 0xFFE // dsp status - non-zero is a request to reset dsp
-#define FT1000_DSP_LED 0xFFA // dsp led status for PAD device
-#define FT1000_DSP_CON_STATE 0xFF8 // DSP Connection Status Info
-#define FT1000_DPRAM_FEFE 0x002 // location for dsp ready indicator
-#define FT1000_DSP_TIMER0 0x1FF0 // Timer Field from Basestation
-#define FT1000_DSP_TIMER1 0x1FF2 // Timer Field from Basestation
-#define FT1000_DSP_TIMER2 0x1FF4 // Timer Field from Basestation
-#define FT1000_DSP_TIMER3 0x1FF6 // Timer Field from Basestation
-
-// Reserved Dual Port RAM offsets for Magnemite
-#define FT1000_DPRAM_MAG_TX_BASE 0x0000 // Host to PC Card Messaging Area
-#define FT1000_DPRAM_MAG_RX_BASE 0x0200 // PC Card to Host Messaging Area
-#define FT1000_MAG_FIFO_LEN 0x1FF // total length for DSP FIFO tracking
-#define FT1000_MAG_FIFO_LEN_INDX 0x1 // low-word index
-#define FT1000_MAG_HI_HO 0x1FF // heartbeat with HI/HO
-#define FT1000_MAG_HI_HO_INDX 0x0 // high-word index
-#define FT1000_MAG_DSP_LED 0x3FE // dsp led status for PAD device
-#define FT1000_MAG_DSP_LED_INDX 0x0 // dsp led status for PAD device
-
-#define FT1000_MAG_DSP_CON_STATE 0x3FE // DSP Connection Status Info
-#define FT1000_MAG_DSP_CON_STATE_INDX 0x1 // DSP Connection Status Info
-
-#define FT1000_MAG_DPRAM_FEFE 0x000 // location for dsp ready indicator
-#define FT1000_MAG_DPRAM_FEFE_INDX 0x0 // location for dsp ready indicator
-
-#define FT1000_MAG_DSP_TIMER0 0x3FC // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER0_INDX 0x1
-
-#define FT1000_MAG_DSP_TIMER1 0x3FC // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER1_INDX 0x0
-
-#define FT1000_MAG_DSP_TIMER2 0x3FD // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER2_INDX 0x1
-
-#define FT1000_MAG_DSP_TIMER3 0x3FD // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER3_INDX 0x0
-
-#define FT1000_MAG_TOTAL_LEN 0x200
-#define FT1000_MAG_TOTAL_LEN_INDX 0x1
-
-#define FT1000_MAG_PH_LEN 0x200
-#define FT1000_MAG_PH_LEN_INDX 0x0
-
-#define FT1000_MAG_PORT_ID 0x201
-#define FT1000_MAG_PORT_ID_INDX 0x0
-
-#define HOST_INTF_LE 0x0 // Host interface little endian mode
-#define HOST_INTF_BE 0x1 // Host interface big endian mode
-
-// PC Card to Host Doorbell assignments
-#define FT1000_DB_DPRAM_RX 0x0001 // this value indicates that DSP has
- // data for host in DPRAM
-#define FT1000_ASIC_RESET_REQ 0x0004 // DSP requesting host to reset the ASIC
-#define FT1000_DSP_ASIC_RESET 0x0008 // DSP indicating host that it will reset the ASIC
-#define FT1000_DB_COND_RESET 0x0010 // DSP request for a card reset.
-
-// Host to PC Card Doorbell assignments
-#define FT1000_DB_DPRAM_TX 0x0100 // this value indicates that host has
- // data for DSP in DPRAM.
-#define FT1000_ASIC_RESET_DSP 0x0400 // Responds to FT1000_ASIC_RESET_REQ
-#define FT1000_DB_HB 0x1000 // Indicates that supervisor
- // has a heartbeat message for DSP.
-
-#define FT1000_DPRAM_BASE 0x0000 // Dual Port RAM starting offset
-
-#define hi 0x6869 // PC Card heartbeat values
-#define ho 0x686f // PC Card heartbeat values
-
-// Magnemite specific defines
-#define hi_mag 0x6968 // Byte swap hi to avoid additional system call
-#define ho_mag 0x6f68 // Byte swap ho to avoid additional system call
-
-//
-// Bit field definitions for Host Interrupt Status Register
-//
-// Indicate the cause of an interrupt.
-//
-#define ISR_EMPTY 0x00 // no bits set
-#define ISR_DOORBELL_ACK 0x01 // Doorbell acknowledge from DSP
-#define ISR_DOORBELL_PEND 0x02 // Doorbell pending from DSP
-#define ISR_RCV 0x04 // Packet available in Downlink FIFO
-#define ISR_WATERMARK 0x08 // Watermark requirements satisfied
-
-// Bit field definition for Host Interrupt Mask
-#define ISR_MASK_NONE 0x0000 // no bits set
-#define ISR_MASK_DOORBELL_ACK 0x0001 // Doorbell acknowledge mask
-#define ISR_MASK_DOORBELL_PEND 0x0002 // Doorbell pending mask
-#define ISR_MASK_RCV 0x0004 // Downlink Packet available mask
-#define ISR_MASK_WATERMARK 0x0008 // Watermark interrupt mask
-#define ISR_MASK_ALL 0xffff // Mask all interrupts
-
-// Bit field definition for Host Control Register
-#define DSP_RESET_BIT 0x0001 // Bit field to control dsp reset state
- // (0 = out of reset 1 = reset)
-#define ASIC_RESET_BIT 0x0002 // Bit field to control ASIC reset state
- // (0 = out of reset 1 = reset)
-
-// Default interrupt mask (Enable Doorbell pending and Packet available interrupts)
-#define ISR_DEFAULT_MASK 0x7ff9
-
-// Application specific IDs
-#define DSPID 0x20
-#define HOSTID 0x10
-#define DSPAIRID 0x90
-#define DRIVERID 0x00
-#define NETWORKID 0x20
-
-// Size of DPRAM Message
-#define MAX_CMD_SQSIZE 1780
-
-#define ENET_MAX_SIZE 1514
-#define ENET_HEADER_SIZE 14
-
-#define SLOWQ_TYPE 0
-#define FASTQ_TYPE 1
-
-#define MAX_DSP_SESS_REC 1024
-
-#define DSP_QID_OFFSET 4
-#define PSEUDOSZ 16
-#define PSEUDOSZWRD 8
-
-// Maximum number of occurrence of pseudo header errors before resetting PC Card.
-#define MAX_PH_ERR 300
-
-// Driver message types
-#define MEDIA_STATE 0x0010
-#define TIME_UPDATE 0x0020
-#define DSP_PROVISION 0x0030
-#define DSP_INIT_MSG 0x0050
-#define DSP_HIBERNATE 0x0060
-
-#define DSP_STORE_INFO 0x0070
-#define DSP_GET_INFO 0x0071
-#define GET_DRV_ERR_RPT_MSG 0x0073
-#define RSP_DRV_ERR_RPT_MSG 0x0074
-
-// Driver Error Messages for DSP
-#define DSP_HB_INFO 0x7ef0
-#define DSP_FIFO_INFO 0x7ef1
-#define DSP_CONDRESET_INFO 0x7ef2
-#define DSP_CMDLEN_INFO 0x7ef3
-#define DSP_CMDPHCKSUM_INFO 0x7ef4
-#define DSP_PKTPHCKSUM_INFO 0x7ef5
-#define DSP_PKTLEN_INFO 0x7ef6
-#define DSP_USER_RESET 0x7ef7
-#define FIFO_FLUSH_MAXLIMIT 0x7ef8
-#define FIFO_FLUSH_BADCNT 0x7ef9
-#define FIFO_ZERO_LEN 0x7efa
-
-#define HOST_QID_OFFSET 5
-#define QTYPE_OFFSET 13
-
-#define SUCCESS 0x00
-#define FAILURE 0x01
-#define TRUE 0x1
-#define FALSE 0x0
-
-#define MAX_NUM_APP 6
-
-#define MAXIMUM_ASIC_HB_CNT 15
-
-typedef struct _DRVMSG {
- PSEUDO_HDR pseudo;
- u16 type;
- u16 length;
- u8 data[0];
-} __attribute__ ((packed)) DRVMSG, *PDRVMSG;
-
-typedef struct _MEDIAMSG {
- PSEUDO_HDR pseudo;
- u16 type;
- u16 length;
- u16 state;
- u32 ip_addr;
- u32 net_mask;
- u32 gateway;
- u32 dns_1;
- u32 dns_2;
-} __attribute__ ((packed)) MEDIAMSG, *PMEDIAMSG;
-
-typedef struct _TIMEMSG {
- PSEUDO_HDR pseudo;
- u16 type;
- u16 length;
- u8 timeval[8];
-} __attribute__ ((packed)) TIMEMSG, *PTIMEMSG;
-
-typedef struct _DSPINITMSG {
- PSEUDO_HDR pseudo;
- u16 type;
- u16 length;
- u8 DspVer[DSPVERSZ]; // DSP version number
- u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
- u8 Sku[SKUSZ]; // SKU
- u8 eui64[EUISZ]; // EUI64
- u8 ProductMode[MODESZ]; // Product Mode (Market/Production)
- u8 RfCalVer[CALVERSZ]; // Rf Calibration version
- u8 RfCalDate[CALDATESZ]; // Rf Calibration date
-} __attribute__ ((packed)) DSPINITMSG, *PDSPINITMSG;
-
-typedef struct _DSPHIBERNATE {
- PSEUDO_HDR pseudo;
- u16 type;
- u16 length;
- u32 timeout;
- u16 sess_info[0];
-} DSPHIBERNATE, *PDSPHIBERNATE;
-
-typedef struct _APP_INFO_BLOCK
-{
- u32 fileobject; // Application's file object
- u16 app_id; // Application id
-} APP_INFO_BLOCK, *PAPP_INFO_BLOCK;
-
-typedef struct _PROV_RECORD {
- struct list_head list;
- u8 *pprov_data;
-} PROV_RECORD, *PPROV_RECORD;
-
-typedef struct _FT1000_INFO {
- struct net_device_stats stats;
- u16 DrvErrNum;
- u16 AsicID;
- int ASICResetNum;
- int DspAsicReset;
- int PktIntfErr;
- int DSPResetNum;
- int NumIOCTLBufs;
- int IOCTLBufLvl;
- int DeviceCreated;
- int CardReady;
- int DspHibernateFlag;
- int DSPReady;
- u8 DeviceName[15];
- int DeviceMajor;
- int registered;
- int mediastate;
- u16 packetseqnum;
- u8 squeseqnum; // sequence number on slow queue
- spinlock_t dpram_lock;
- u16 CurrentInterruptEnableMask;
- int InterruptsEnabled;
- u16 fifo_cnt;
- u8 DspVer[DSPVERSZ]; // DSP version number
- u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
- u8 Sku[SKUSZ]; // SKU
- u8 eui64[EUISZ]; // EUI64
- time_t ConTm; // Connection Time
- u16 LedStat;
- u16 ConStat;
- u16 ProgConStat;
- u8 ProductMode[MODESZ];
- u8 RfCalVer[CALVERSZ];
- u8 RfCalDate[CALDATESZ];
- u16 DSP_TIME[4];
- struct list_head prov_list;
- int appcnt;
- APP_INFO_BLOCK app_info[MAX_NUM_APP];
- u16 DSPInfoBlklen;
- u16 DrvMsgPend;
+#include "../ft1000.h"
+
+#define FT1000_DRV_VER 0x01010300
+
+#define FT1000_DPRAM_BASE 0x0000 /* Dual Port RAM starting offset */
+
+/* Maximum number of occurrence of pseudo header errors before resetting PC Card. */
+#define MAX_PH_ERR 300
+
+#define SUCCESS 0x00
+#define FAILURE 0x01
+
+struct ft1000_info {
+ struct net_device_stats stats;
+ u16 DrvErrNum;
+ u16 AsicID;
+ int PktIntfErr;
+ int CardReady;
+ int registered;
+ int mediastate;
+ u16 packetseqnum;
+ u8 squeseqnum; /* sequence number on slow queue */
+ spinlock_t dpram_lock;
+ u16 fifo_cnt;
+ u8 DspVer[DSPVERSZ]; /* DSP version number */
+ u8 HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
+ u8 Sku[SKUSZ]; /* SKU */
+ u8 eui64[EUISZ]; /* EUI64 */
+ time_t ConTm; /* Connection Time */
+ u16 LedStat;
+ u16 ConStat;
+ u16 ProgConStat;
+ u8 ProductMode[MODESZ];
+ u8 RfCalVer[CALVERSZ];
+ u8 RfCalDate[CALDATESZ];
+ u16 DSP_TIME[4];
+ struct list_head prov_list;
+ u16 DSPInfoBlklen;
int (*ft1000_reset)(void *);
- void *link;
- u16 DSPInfoBlk[MAX_DSP_SESS_REC];
- union {
- u16 Rec[MAX_DSP_SESS_REC];
- u32 MagRec[MAX_DSP_SESS_REC/2];
- } DSPSess;
+ void *link;
+ u16 DSPInfoBlk[MAX_DSP_SESS_REC];
+ union {
+ u16 Rec[MAX_DSP_SESS_REC];
+ u32 MagRec[MAX_DSP_SESS_REC/2];
+ } DSPSess;
struct proc_dir_entry *proc_ft1000;
char netdevname[IFNAMSIZ];
-} FT1000_INFO, *PFT1000_INFO;
+};
+
+struct pcmcia_device;
+struct net_device;
+extern struct net_device *init_ft1000_card(struct pcmcia_device *link,
+ void *ft1000_reset);
+extern void stop_ft1000_card(struct net_device *dev);
+extern int card_download(struct net_device *dev, const u8 *pFileStart,
+ size_t FileLength);
+extern void ft1000InitProc(struct net_device *dev);
+extern void ft1000CleanupProc(struct net_device *dev);
+
+extern u16 ft1000_read_dpram(struct net_device *dev, int offset);
+extern void card_bootload(struct net_device *dev);
+extern u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index);
+extern u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
+void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value);
-typedef struct _DPRAM_BLK {
- struct list_head list;
- u16 *pbuffer;
-} __attribute__ ((packed)) DPRAM_BLK, *PDPRAM_BLK;
+/* Read the value of a given ASIC register. */
+static inline u16 ft1000_read_reg(struct net_device *dev, u16 offset)
+{
+ return inw(dev->base_addr + offset);
+}
-extern u16 ft1000_read_dpram (struct net_device *dev, int offset);
-extern void card_bootload(struct net_device *dev);
-extern u16 ft1000_read_dpram_mag_16 (struct net_device *dev, int offset, int Index);
-extern u32 ft1000_read_dpram_mag_32 (struct net_device *dev, int offset);
-void ft1000_write_dpram_mag_32 (struct net_device *dev, int offset, u32 value);
+/* Set the value of a given ASIC register. */
+static inline void ft1000_write_reg(struct net_device *dev, u16 offset, u16 value)
+{
+ outw(value, dev->base_addr + offset);
+}
-#endif // _FT1000H_
+#endif
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
index 68ea035..f376ca4 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
@@ -29,153 +29,54 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
/*====================================================================*/
-/* Module parameters */
-
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
MODULE_AUTHOR("Wai Chan");
MODULE_DESCRIPTION("FT1000 PCMCIA driver");
MODULE_LICENSE("GPL");
-/* Newer, simpler way of listing specific interrupts */
-
-/* The old way: bit map of interrupts to choose from */
-/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
-
-/*
- All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
- you do not define PCMCIA_DEBUG at all, all the debug code will be
- left out. If you compile with PCMCIA_DEBUG=0, the debug code will
- be present but disabled.
-*/
-#ifdef FT_DEBUG
-#define DEBUG(n, args...) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
-
/*====================================================================*/
-struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset);
-void stop_ft1000_card(struct net_device *);
-
static int ft1000_config(struct pcmcia_device *link);
-static void ft1000_release(struct pcmcia_device *link);
-
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void ft1000_detach(struct pcmcia_device *link);
-static int ft1000_attach(struct pcmcia_device *link);
+static int ft1000_attach(struct pcmcia_device *link);
-typedef struct local_info_t {
- struct pcmcia_device *link;
- struct net_device *dev;
-} local_info_t;
-
-#define MAX_ASIC_RESET_CNT 10
-#define COR_DEFAULT 0x55
+#include "ft1000.h"
/*====================================================================*/
-static void ft1000_reset(struct pcmcia_device * link)
+static void ft1000_reset(struct pcmcia_device *link)
{
pcmcia_reset_card(link->socket);
}
-/*======================================================================
-
-
-======================================================================*/
-
static int ft1000_attach(struct pcmcia_device *link)
{
-
- local_info_t *local;
-
- DEBUG(0, "ft1000_cs: ft1000_attach()\n");
-
- local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
- if (!local) {
- return -ENOMEM;
- }
- local->link = link;
-
- link->priv = local;
- local->dev = NULL;
-
+ link->priv = NULL;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return ft1000_config(link);
-
-} /* ft1000_attach */
-
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
+}
static void ft1000_detach(struct pcmcia_device *link)
{
- struct net_device *dev = ((local_info_t *) link->priv)->dev;
-
- DEBUG(0, "ft1000_cs: ft1000_detach(0x%p)\n", link);
-
- if (link == NULL) {
- DEBUG(0,"ft1000_cs:ft1000_detach: Got a NULL pointer\n");
- return;
- }
+ struct net_device *dev = link->priv;
- if (dev) {
+ if (dev)
stop_ft1000_card(dev);
- }
pcmcia_disable_device(link);
-
- /* This points to the parent local_info_t struct */
free_netdev(dev);
+}
-} /* ft1000_detach */
-
-/*======================================================================
-
- Check if the io window is configured
-
-======================================================================*/
-int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
+static int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
{
-
return pcmcia_request_io(link);
-} /* ft1000_confcheck */
+}
/*======================================================================
@@ -187,7 +88,7 @@ int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
static int ft1000_config(struct pcmcia_device *link)
{
- int ret;
+ int ret;
dev_dbg(&link->dev, "ft1000_cs: ft1000_config(0x%p)\n", link);
@@ -205,9 +106,8 @@ static int ft1000_config(struct pcmcia_device *link)
goto failed;
}
- ((local_info_t *) link->priv)->dev = init_ft1000_card(link,
- &ft1000_reset);
- if (((local_info_t *) link->priv)->dev == NULL) {
+ link->priv = init_ft1000_card(link, &ft1000_reset);
+ if (!link->priv) {
printk(KERN_INFO "ft1000: Could not register as network device\n");
goto failed;
}
@@ -216,57 +116,13 @@ static int ft1000_config(struct pcmcia_device *link)
return 0;
failed:
- ft1000_release(link);
+ pcmcia_disable_device(link);
return -ENODEV;
-
-} /* ft1000_config */
-
-/*======================================================================
-
- After a card is removed, ft1000_release() will unregister the
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
-static void ft1000_release(struct pcmcia_device * link)
-{
-
- DEBUG(0, "ft1000_cs: ft1000_release(0x%p)\n", link);
-
- /*
- If the device is currently in use, we won't release until it
- is actually closed, because until then, we can't be sure that
- no one will try to access the device or its data structures.
- */
-
- /*
- In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
- */
- kfree((local_info_t *) link->priv);
- /* Don't bother checking to see if these succeed or not */
-
- pcmcia_disable_device(link);
-} /* ft1000_release */
-
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received.
-
- When a CARD_REMOVAL event is received, we immediately set a
- private flag to block future accesses to this device. All the
- functions that actually access the device should check this flag
- to make sure the card is still present.
-
-======================================================================*/
+}
static int ft1000_suspend(struct pcmcia_device *link)
{
- struct net_device *dev = ((local_info_t *) link->priv)->dev;
-
- DEBUG(1, "ft1000_cs: ft1000_event(0x%06x)\n", event);
+ struct net_device *dev = link->priv;
if (link->open)
netif_device_detach(dev);
@@ -275,13 +131,9 @@ static int ft1000_suspend(struct pcmcia_device *link)
static int ft1000_resume(struct pcmcia_device *link)
{
-/* struct net_device *dev = link->priv;
- */
return 0;
}
-
-
/*====================================================================*/
static const struct pcmcia_device_id ft1000_ids[] = {
@@ -294,26 +146,22 @@ static const struct pcmcia_device_id ft1000_ids[] = {
MODULE_DEVICE_TABLE(pcmcia, ft1000_ids);
static struct pcmcia_driver ft1000_cs_driver = {
- .owner = THIS_MODULE,
- .drv = {
- .name = "ft1000_cs",
- },
- .probe = ft1000_attach,
- .remove = ft1000_detach,
+ .owner = THIS_MODULE,
+ .name = "ft1000_cs",
+ .probe = ft1000_attach,
+ .remove = ft1000_detach,
.id_table = ft1000_ids,
- .suspend = ft1000_suspend,
- .resume = ft1000_resume,
+ .suspend = ft1000_suspend,
+ .resume = ft1000_resume,
};
static int __init init_ft1000_cs(void)
{
- DEBUG(0, "ft1000_cs: loading\n");
return pcmcia_register_driver(&ft1000_cs_driver);
}
static void __exit exit_ft1000_cs(void)
{
- DEBUG(0, "ft1000_cs: unloading\n");
pcmcia_unregister_driver(&ft1000_cs_driver);
}
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
deleted file mode 100644
index 0b63f05..0000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//---------------------------------------------------------------------------
-// FT1000 driver for Flarion Flash OFDM NIC Device
-//
-// Copyright (C) 2002 Flarion Technologies, All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or (at your option) any
-// later version. This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details. You should have received a copy of the GNU General Public
-// License along with this program; if not, write to the
-// Free Software Foundation, Inc., 59 Temple Place -
-// Suite 330, Boston, MA 02111-1307, USA.
-//---------------------------------------------------------------------------
-//
-// File: ft1000_dev.h
-//
-// Description: Register definitions and bit masks for the FT1000 NIC
-//
-// History:
-// 2/5/02 Ivan Bohannon Written.
-// 8/29/02 Whc Ported to Linux.
-//
-//---------------------------------------------------------------------------
-#ifndef _FT1000_DEVH_
-#define _FT1000_DEVH_
-
-//---------------------------------------------------------------------------
-//
-// Function: ft1000_read_reg
-// Description: This function will read the value of a given ASIC register.
-// Input:
-// dev - device structure
-// offset - ASIC register offset
-// Output:
-// data - ASIC register value
-//
-//---------------------------------------------------------------------------
-static inline u16 ft1000_read_reg (struct net_device *dev, u16 offset) {
- u16 data = 0;
-
- data = inw(dev->base_addr + offset);
-
- return (data);
-}
-
-//---------------------------------------------------------------------------
-//
-// Function: ft1000_write_reg
-// Description: This function will set the value for a given ASIC register.
-// Input:
-// dev - device structure
-// offset - ASIC register offset
-// value - value to write
-// Output:
-// None.
-//
-//---------------------------------------------------------------------------
-static inline void ft1000_write_reg (struct net_device *dev, u16 offset, u16 value) {
- outw (value, dev->base_addr + offset);
-}
-
-#endif // _FT1000_DEVH_
-
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
index fb375ea..f8b8e71 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
@@ -34,7 +34,6 @@
#include <asm/uaccess.h>
#include <linux/vmalloc.h>
-#include "ft1000_dev.h"
#include "ft1000.h"
#include "boot.h"
@@ -87,26 +86,14 @@
#define STATE_DONE_PROV 0x06
#define STATE_DONE_FILE 0x07
-USHORT get_handshake(struct net_device *dev, USHORT expected_value);
-void put_handshake(struct net_device *dev, USHORT handshake_value);
-USHORT get_request_type(struct net_device *dev);
+u16 get_handshake(struct net_device *dev, u16 expected_value);
+void put_handshake(struct net_device *dev, u16 handshake_value);
+u16 get_request_type(struct net_device *dev);
long get_request_value(struct net_device *dev);
void put_request_value(struct net_device *dev, long lvalue);
-USHORT hdr_checksum(PPSEUDO_HDR pHdr);
+u16 hdr_checksum(struct pseudo_hdr *pHdr);
-typedef struct _DSP_FILE_HDR {
- u32 build_date;
- u32 dsp_coff_date;
- u32 loader_code_address;
- u32 loader_code_size;
- u32 loader_code_end;
- u32 dsp_code_address;
- u32 dsp_code_size;
- u32 dsp_code_end;
- u32 reserved[8];
-} __attribute__ ((packed)) DSP_FILE_HDR, *PDSP_FILE_HDR;
-
-typedef struct _DSP_FILE_HDR_5 {
+struct dsp_file_hdr {
u32 version_id; // Version ID of this image format.
u32 package_id; // Package ID of code release.
u32 build_date; // Date/time stamp when file was built.
@@ -118,18 +105,9 @@ typedef struct _DSP_FILE_HDR_5 {
u32 version_data_offset; // Offset were scrambled version data begins.
u32 version_data_size; // Size, in words, of scrambled version data.
u32 nDspImages; // Number of DSP images in file.
-} __attribute__ ((packed)) DSP_FILE_HDR_5, *PDSP_FILE_HDR_5;
-
-typedef struct _DSP_IMAGE_INFO {
- u32 coff_date; // Date/time when DSP Coff image was built.
- u32 begin_offset; // Offset in file where image begins.
- u32 end_offset; // Offset in file where image begins.
- u32 run_address; // On chip Start address of DSP code.
- u32 image_size; // Size of image.
- u32 version; // Embedded version # of DSP code.
-} __attribute__ ((packed)) DSP_IMAGE_INFO, *PDSP_IMAGE_INFO;
+} __attribute__ ((packed));
-typedef struct _DSP_IMAGE_INFO_V6 {
+struct dsp_image_info {
u32 coff_date; // Date/time when DSP Coff image was built.
u32 begin_offset; // Offset in file where image begins.
u32 end_offset; // Offset in file where image begins.
@@ -138,20 +116,20 @@ typedef struct _DSP_IMAGE_INFO_V6 {
u32 version; // Embedded version # of DSP code.
unsigned short checksum; // Dsp File checksum
unsigned short pad1;
-} __attribute__ ((packed)) DSP_IMAGE_INFO_V6, *PDSP_IMAGE_INFO_V6;
+} __attribute__ ((packed));
void card_bootload(struct net_device *dev)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
unsigned long flags;
- PULONG pdata;
- UINT size;
- UINT i;
- ULONG templong;
+ u32 *pdata;
+ u32 size;
+ u32 i;
+ u32 templong;
DEBUG(0, "card_bootload is called\n");
- pdata = (PULONG) bootimage;
+ pdata = (u32 *) bootimage;
size = sizeof(bootimage);
// check for odd word
@@ -172,11 +150,11 @@ void card_bootload(struct net_device *dev)
spin_unlock_irqrestore(&info->dpram_lock, flags);
}
-USHORT get_handshake(struct net_device *dev, USHORT expected_value)
+u16 get_handshake(struct net_device *dev, u16 expected_value)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
- USHORT handshake;
- ULONG tempx;
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+ u16 handshake;
+ u32 tempx;
int loopcnt;
loopcnt = 0;
@@ -190,7 +168,7 @@ USHORT get_handshake(struct net_device *dev, USHORT expected_value)
tempx =
ntohl(ft1000_read_dpram_mag_32
(dev, DWNLD_MAG_HANDSHAKE_LOC));
- handshake = (USHORT) tempx;
+ handshake = (u16) tempx;
}
if ((handshake == expected_value)
@@ -207,27 +185,27 @@ USHORT get_handshake(struct net_device *dev, USHORT expected_value)
}
-void put_handshake(struct net_device *dev, USHORT handshake_value)
+void put_handshake(struct net_device *dev, u16 handshake_value)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
- ULONG tempx;
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+ u32 tempx;
if (info->AsicID == ELECTRABUZZ_ID) {
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
DWNLD_HANDSHAKE_LOC);
ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, handshake_value); /* Handshake */
} else {
- tempx = (ULONG) handshake_value;
+ tempx = (u32) handshake_value;
tempx = ntohl(tempx);
ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx); /* Handshake */
}
}
-USHORT get_request_type(struct net_device *dev)
+u16 get_request_type(struct net_device *dev)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
- USHORT request_type;
- ULONG tempx;
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+ u16 request_type;
+ u32 tempx;
if (info->AsicID == ELECTRABUZZ_ID) {
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, DWNLD_TYPE_LOC);
@@ -235,7 +213,7 @@ USHORT get_request_type(struct net_device *dev)
} else {
tempx = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_TYPE_LOC);
tempx = ntohl(tempx);
- request_type = (USHORT) tempx;
+ request_type = (u16) tempx;
}
return request_type;
@@ -244,9 +222,9 @@ USHORT get_request_type(struct net_device *dev)
long get_request_value(struct net_device *dev)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
long value;
- USHORT w_val;
+ u16 w_val;
if (info->AsicID == ELECTRABUZZ_ID) {
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
@@ -273,19 +251,19 @@ long get_request_value(struct net_device *dev)
void put_request_value(struct net_device *dev, long lvalue)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
- USHORT size;
- ULONG tempx;
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+ u16 size;
+ u32 tempx;
if (info->AsicID == ELECTRABUZZ_ID) {
- size = (USHORT) (lvalue >> 16);
+ size = (u16) (lvalue >> 16);
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
DWNLD_SIZE_MSW_LOC);
ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
- size = (USHORT) (lvalue);
+ size = (u16) (lvalue);
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
DWNLD_SIZE_LSW_LOC);
@@ -298,10 +276,10 @@ void put_request_value(struct net_device *dev, long lvalue)
}
-USHORT hdr_checksum(PPSEUDO_HDR pHdr)
+u16 hdr_checksum(struct pseudo_hdr *pHdr)
{
- USHORT *usPtr = (USHORT *) pHdr;
- USHORT chksum;
+ u16 *usPtr = (u16 *) pHdr;
+ u16 chksum;
chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
@@ -309,32 +287,30 @@ USHORT hdr_checksum(PPSEUDO_HDR pHdr)
return chksum;
}
-int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
+int card_download(struct net_device *dev, const u8 *pFileStart,
+ size_t FileLength)
{
- FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
+ struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
int Status = SUCCESS;
- USHORT DspWordCnt = 0;
- UINT uiState;
- USHORT handshake;
- PPSEUDO_HDR pHdr;
- USHORT usHdrLength;
- PDSP_FILE_HDR pFileHdr;
+ u32 uiState;
+ u16 handshake;
+ struct pseudo_hdr *pHdr;
+ u16 usHdrLength;
long word_length;
- USHORT request;
- USHORT temp;
- PPROV_RECORD pprov_record;
- PUCHAR pbuffer;
- PDSP_FILE_HDR_5 pFileHdr5;
- PDSP_IMAGE_INFO pDspImageInfo = NULL;
- PDSP_IMAGE_INFO_V6 pDspImageInfoV6 = NULL;
+ u16 request;
+ u16 temp;
+ struct prov_record *pprov_record;
+ u8 *pbuffer;
+ struct dsp_file_hdr *pFileHdr5;
+ struct dsp_image_info *pDspImageInfoV6 = NULL;
long requested_version;
- BOOLEAN bGoodVersion = 0;
- PDRVMSG pMailBoxData;
- USHORT *pUsData = NULL;
- USHORT *pUsFile = NULL;
- UCHAR *pUcFile = NULL;
- UCHAR *pBootEnd = NULL;
- UCHAR *pCodeEnd = NULL;
+ bool bGoodVersion = 0;
+ struct drv_msg *pMailBoxData;
+ u16 *pUsData = NULL;
+ u16 *pUsFile = NULL;
+ u8 *pUcFile = NULL;
+ u8 *pBootEnd = NULL;
+ u8 *pCodeEnd = NULL;
int imageN;
long file_version;
long loader_code_address = 0;
@@ -345,36 +321,22 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
unsigned long templong;
unsigned long image_chksum = 0;
- //
- // Get version id of file, at first 4 bytes of file, for newer files.
- //
file_version = *(long *)pFileStart;
+ if (file_version != 6) {
+ printk(KERN_ERR "ft1000: unsupported firmware version %ld\n", file_version);
+ Status = FAILURE;
+ }
uiState = STATE_START_DWNLD;
- pFileHdr = (PDSP_FILE_HDR) pFileStart;
- pFileHdr5 = (PDSP_FILE_HDR_5) pFileStart;
-
- switch (file_version) {
- case 5:
- case 6:
- pUsFile =
- (USHORT *) ((long)pFileStart + pFileHdr5->loader_offset);
- pUcFile =
- (UCHAR *) ((long)pFileStart + pFileHdr5->loader_offset);
+ pFileHdr5 = (struct dsp_file_hdr *) pFileStart;
- pBootEnd =
- (UCHAR *) ((long)pFileStart + pFileHdr5->loader_code_end);
-
- loader_code_address = pFileHdr5->loader_code_address;
- loader_code_size = pFileHdr5->loader_code_size;
- bGoodVersion = FALSE;
- break;
-
- default:
- Status = FAILURE;
- break;
- }
+ pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->loader_offset);
+ pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->loader_offset);
+ pBootEnd = (u8 *) ((long)pFileStart + pFileHdr5->loader_code_end);
+ loader_code_address = pFileHdr5->loader_code_address;
+ loader_code_size = pFileHdr5->loader_code_size;
+ bGoodVersion = false;
while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) {
@@ -411,8 +373,8 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
break;
case REQUEST_DONE_BL:
/* Reposition ptrs to beginning of code section */
- pUsFile = (USHORT *) ((long)pBootEnd);
- pUcFile = (UCHAR *) ((long)pBootEnd);
+ pUsFile = (u16 *) ((long)pBootEnd);
+ pUcFile = (u8 *) ((long)pBootEnd);
uiState = STATE_CODE_DWNLD;
break;
case REQUEST_CODE_SEGMENT:
@@ -432,45 +394,24 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
// Provide mutual exclusive access while reading ASIC registers.
spin_lock_irqsave(&info->dpram_lock,
flags);
- if (file_version == 5) {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_ADDR,
- DWNLD_PS_HDR_LOC);
-
- for (; word_length > 0; word_length--) { /* In words */
- //temp = *pUsFile;
- //temp = RtlUshortByteSwap(temp);
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_DATA,
- *pUsFile);
- pUsFile++;
- pUcFile += 2;
- DspWordCnt++;
- }
- } else {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
+ /*
+ * Position ASIC DPRAM auto-increment pointer.
+ */
+ outw(DWNLD_MAG_PS_HDR_LOC,
+ dev->base_addr +
+ FT1000_REG_DPRAM_ADDR);
+ if (word_length & 0x01)
+ word_length++;
+ word_length = word_length / 2;
+
+ for (; word_length > 0; word_length--) { /* In words */
+ templong = *pUsFile++;
+ templong |=
+ (*pUsFile++ << 16);
+ pUcFile += 4;
+ outl(templong,
dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01) {
- word_length++;
- }
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsFile++;
- templong |=
- (*pUsFile++ << 16);
- pUcFile += 4;
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
+ FT1000_REG_MAG_DPDATAL);
}
spin_unlock_irqrestore(&info->
dpram_lock,
@@ -520,24 +461,8 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
break;
case REQUEST_DONE_CL:
/* Reposition ptrs to beginning of provisioning section */
- switch (file_version) {
- case 5:
- case 6:
- pUsFile =
- (USHORT *) ((long)pFileStart
- +
- pFileHdr5->
- commands_offset);
- pUcFile =
- (UCHAR *) ((long)pFileStart
- +
- pFileHdr5->
- commands_offset);
- break;
- default:
- Status = FAILURE;
- break;
- }
+ pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->commands_offset);
+ pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->commands_offset);
uiState = STATE_DONE_DWNLD;
break;
case REQUEST_CODE_SEGMENT:
@@ -558,45 +483,24 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
Status = FAILURE;
break;
}
- if (file_version == 5) {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_ADDR,
- DWNLD_PS_HDR_LOC);
-
- for (; word_length > 0; word_length--) { /* In words */
- //temp = *pUsFile;
- //temp = RtlUshortByteSwap(temp);
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_DATA,
- *pUsFile);
- pUsFile++;
- pUcFile += 2;
- DspWordCnt++;
- }
- } else {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
+ /*
+ * Position ASIC DPRAM auto-increment pointer.
+ */
+ outw(DWNLD_MAG_PS_HDR_LOC,
+ dev->base_addr +
+ FT1000_REG_DPRAM_ADDR);
+ if (word_length & 0x01)
+ word_length++;
+ word_length = word_length / 2;
+
+ for (; word_length > 0; word_length--) { /* In words */
+ templong = *pUsFile++;
+ templong |=
+ (*pUsFile++ << 16);
+ pUcFile += 4;
+ outl(templong,
dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01) {
- word_length++;
- }
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsFile++;
- templong |=
- (*pUsFile++ << 16);
- pUcFile += 4;
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
+ FT1000_REG_MAG_DPDATAL);
}
break;
@@ -606,9 +510,9 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
(long)(info->DSPInfoBlklen + 1) / 2;
put_request_value(dev, word_length);
pMailBoxData =
- (PDRVMSG) & info->DSPInfoBlk[0];
+ (struct drv_msg *) & info->DSPInfoBlk[0];
pUsData =
- (USHORT *) & pMailBoxData->data[0];
+ (u16 *) & pMailBoxData->data[0];
// Provide mutual exclusive access while reading ASIC registers.
spin_lock_irqsave(&info->dpram_lock,
flags);
@@ -658,51 +562,32 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
pFileHdr5->version_data_size;
put_request_value(dev, word_length);
pUsFile =
- (USHORT *) ((long)pFileStart +
+ (u16 *) ((long)pFileStart +
pFileHdr5->
version_data_offset);
// Provide mutual exclusive access while reading ASIC registers.
spin_lock_irqsave(&info->dpram_lock,
flags);
- if (file_version == 5) {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_ADDR,
- DWNLD_PS_HDR_LOC);
-
- for (; word_length > 0; word_length--) { /* In words */
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_DATA,
- *pUsFile
- /*temp */
- );
- pUsFile++;
- }
- } else {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
+ /*
+ * Position ASIC DPRAM auto-increment pointer.
+ */
+ outw(DWNLD_MAG_PS_HDR_LOC,
+ dev->base_addr +
+ FT1000_REG_DPRAM_ADDR);
+ if (word_length & 0x01)
+ word_length++;
+ word_length = word_length / 2;
+
+ for (; word_length > 0; word_length--) { /* In words */
+ templong =
+ ntohs(*pUsFile++);
+ temp =
+ ntohs(*pUsFile++);
+ templong |=
+ (temp << 16);
+ outl(templong,
dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01) {
- word_length++;
- }
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong =
- ntohs(*pUsFile++);
- temp =
- ntohs(*pUsFile++);
- templong |=
- (temp << 16);
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
+ FT1000_REG_MAG_DPDATAL);
}
spin_unlock_irqrestore(&info->
dpram_lock,
@@ -710,120 +595,71 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
break;
case REQUEST_CODE_BY_VERSION:
- bGoodVersion = FALSE;
+ bGoodVersion = false;
requested_version =
get_request_value(dev);
- if (file_version == 5) {
- pDspImageInfo =
- (PDSP_IMAGE_INFO) ((long)
- pFileStart
- +
- sizeof
- (DSP_FILE_HDR_5));
- for (imageN = 0;
- imageN <
- pFileHdr5->nDspImages;
- imageN++) {
- if (pDspImageInfo->
- version ==
- requested_version) {
- bGoodVersion =
- TRUE;
- pUsFile =
- (USHORT
- *) ((long)
- pFileStart
- +
- pDspImageInfo->
- begin_offset);
- pUcFile =
- (UCHAR
- *) ((long)
- pFileStart
- +
- pDspImageInfo->
- begin_offset);
- pCodeEnd =
- (UCHAR
- *) ((long)
- pFileStart
- +
- pDspImageInfo->
- end_offset);
- run_address =
- pDspImageInfo->
- run_address;
- run_size =
- pDspImageInfo->
- image_size;
- break;
- }
- pDspImageInfo++;
- }
- } else {
- pDspImageInfoV6 =
- (PDSP_IMAGE_INFO_V6) ((long)
- pFileStart
- +
- sizeof
- (DSP_FILE_HDR_5));
- for (imageN = 0;
- imageN <
- pFileHdr5->nDspImages;
- imageN++) {
- temp = (USHORT)
- (pDspImageInfoV6->
- version);
- templong = temp;
- temp = (USHORT)
- (pDspImageInfoV6->
- version >> 16);
- templong |=
- (temp << 16);
- if (templong ==
- requested_version) {
- bGoodVersion =
- TRUE;
- pUsFile =
- (USHORT
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- begin_offset);
- pUcFile =
- (UCHAR
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- begin_offset);
- pCodeEnd =
- (UCHAR
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- end_offset);
- run_address =
- pDspImageInfoV6->
- run_address;
- run_size =
- pDspImageInfoV6->
- image_size;
- image_chksum =
- (ULONG)
- pDspImageInfoV6->
- checksum;
- DEBUG(0,
- "ft1000_dnld: image_chksum = 0x%8x\n",
- (unsigned
- int)
- image_chksum);
- break;
- }
- pDspImageInfoV6++;
+ pDspImageInfoV6 =
+ (struct dsp_image_info *) ((long)
+ pFileStart
+ +
+ sizeof
+ (struct dsp_file_hdr));
+ for (imageN = 0;
+ imageN <
+ pFileHdr5->nDspImages;
+ imageN++) {
+ temp = (u16)
+ (pDspImageInfoV6->
+ version);
+ templong = temp;
+ temp = (u16)
+ (pDspImageInfoV6->
+ version >> 16);
+ templong |=
+ (temp << 16);
+ if (templong ==
+ requested_version) {
+ bGoodVersion =
+ true;
+ pUsFile =
+ (u16
+ *) ((long)
+ pFileStart
+ +
+ pDspImageInfoV6->
+ begin_offset);
+ pUcFile =
+ (u8
+ *) ((long)
+ pFileStart
+ +
+ pDspImageInfoV6->
+ begin_offset);
+ pCodeEnd =
+ (u8
+ *) ((long)
+ pFileStart
+ +
+ pDspImageInfoV6->
+ end_offset);
+ run_address =
+ pDspImageInfoV6->
+ run_address;
+ run_size =
+ pDspImageInfoV6->
+ image_size;
+ image_chksum =
+ (u32)
+ pDspImageInfoV6->
+ checksum;
+ DEBUG(0,
+ "ft1000_dnld: image_chksum = 0x%8x\n",
+ (unsigned
+ int)
+ image_chksum);
+ break;
}
+ pDspImageInfoV6++;
}
if (!bGoodVersion) {
/*
@@ -852,7 +688,7 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
break;
}
- pHdr = (PPSEUDO_HDR) pUsFile;
+ pHdr = (struct pseudo_hdr *) pUsFile;
if (pHdr->portdest == 0x80 /* DspOAM */
&& (pHdr->portsrc == 0x00 /* Driver */
@@ -872,7 +708,7 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
case STATE_SECTION_PROV:
- pHdr = (PPSEUDO_HDR) pUcFile;
+ pHdr = (struct pseudo_hdr *) pUcFile;
if (pHdr->checksum == hdr_checksum(pHdr)) {
if (pHdr->portdest != 0x80 /* Dsp OAM */ ) {
@@ -883,15 +719,15 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
// Get buffer for provisioning data
pbuffer =
- kmalloc((usHdrLength + sizeof(PSEUDO_HDR)),
+ kmalloc((usHdrLength + sizeof(struct pseudo_hdr)),
GFP_ATOMIC);
if (pbuffer) {
memcpy(pbuffer, (void *)pUcFile,
- (UINT) (usHdrLength +
- sizeof(PSEUDO_HDR)));
+ (u32) (usHdrLength +
+ sizeof(struct pseudo_hdr)));
// link provisioning data
pprov_record =
- kmalloc(sizeof(PROV_RECORD),
+ kmalloc(sizeof(struct prov_record),
GFP_ATOMIC);
if (pprov_record) {
pprov_record->pprov_data =
@@ -901,8 +737,8 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
&info->prov_list);
// Move to next entry if available
pUcFile =
- (UCHAR *) ((unsigned long) pUcFile +
- (unsigned long) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR));
+ (u8 *) ((unsigned long) pUcFile +
+ (unsigned long) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
if ((unsigned long) (pUcFile) -
(unsigned long) (pFileStart) >=
(unsigned long) FileLength) {
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
index 830822f..b3d743a 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
@@ -54,19 +54,13 @@
#endif
#include <linux/delay.h>
-#include "ft1000_dev.h"
#include "ft1000.h"
-int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength);
-
-void ft1000InitProc(struct net_device *dev);
-void ft1000CleanupProc(struct net_device *dev);
-
-const struct firmware *fw_entry;
+static const struct firmware *fw_entry;
static void ft1000_hbchk(u_long data);
static struct timer_list poll_timer = {
- function:ft1000_hbchk
+ .function = ft1000_hbchk
};
static u16 cmdbuffer[1024];
@@ -89,40 +83,6 @@ MODULE_SUPPORTED_DEVICE("FT1000");
//---------------------------------------------------------------------------
//
-// Function: ft1000_asic_read
-// Description: This function will retrieve the value of a specific ASIC
-// register.
-// Input:
-// dev - network device structure
-// offset - ASIC register to read
-// Output:
-// value - value of ASIC register
-//
-//---------------------------------------------------------------------------
-inline u16 ft1000_asic_read(struct net_device *dev, u16 offset)
-{
- return (ft1000_read_reg(dev, offset));
-}
-
-//---------------------------------------------------------------------------
-//
-// Function: ft1000_asic_write
-// Description: This function will set the value of a specific ASIC
-// register.
-// Input:
-// dev - network device structure
-// value - value to set ASIC register
-// Output:
-// none
-//
-//---------------------------------------------------------------------------
-inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value)
-{
- ft1000_write_reg(dev, offset, value);
-}
-
-//---------------------------------------------------------------------------
-//
// Function: ft1000_read_fifo_len
// Description: This function will read the ASIC Uplink FIFO status register
// which will return the number of bytes remaining in the Uplink FIFO.
@@ -136,7 +96,7 @@ inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value)
//---------------------------------------------------------------------------
static inline u16 ft1000_read_fifo_len(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
if (info->AsicID == ELECTRABUZZ_ID) {
return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
@@ -159,7 +119,7 @@ static inline u16 ft1000_read_fifo_len(struct net_device *dev)
//---------------------------------------------------------------------------
u16 ft1000_read_dpram(struct net_device * dev, int offset)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
unsigned long flags;
u16 data;
@@ -188,7 +148,7 @@ u16 ft1000_read_dpram(struct net_device * dev, int offset)
static inline void ft1000_write_dpram(struct net_device *dev,
int offset, u16 value)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
unsigned long flags;
// Provide mutual exclusive access while reading ASIC registers.
@@ -212,7 +172,7 @@ static inline void ft1000_write_dpram(struct net_device *dev,
//---------------------------------------------------------------------------
u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
unsigned long flags;
u16 data;
@@ -246,7 +206,7 @@ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
int offset, u16 value, int Index)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
unsigned long flags;
// Provide mutual exclusive access while reading ASIC registers.
@@ -274,7 +234,7 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
//---------------------------------------------------------------------------
u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
unsigned long flags;
u32 data;
@@ -302,7 +262,7 @@ u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
//---------------------------------------------------------------------------
void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
unsigned long flags;
// Provide mutual exclusive access while reading ASIC registers.
@@ -324,17 +284,14 @@ void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
//---------------------------------------------------------------------------
static void ft1000_enable_interrupts(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
u16 tempword;
DEBUG(1, "ft1000_hw:ft1000_enable_interrupts()\n");
- ft1000_write_reg(dev, FT1000_REG_SUP_IMASK,
- info->CurrentInterruptEnableMask);
+ ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_DEFAULT_MASK);
tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
DEBUG(1,
"ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n",
tempword);
- info->InterruptsEnabled = TRUE;
}
//---------------------------------------------------------------------------
@@ -349,7 +306,6 @@ static void ft1000_enable_interrupts(struct net_device *dev)
//---------------------------------------------------------------------------
static void ft1000_disable_interrupts(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
u16 tempword;
DEBUG(1, "ft1000_hw: ft1000_disable_interrupts()\n");
@@ -358,7 +314,6 @@ static void ft1000_disable_interrupts(struct net_device *dev)
DEBUG(1,
"ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n",
tempword);
- info->InterruptsEnabled = FALSE;
}
//---------------------------------------------------------------------------
@@ -374,13 +329,12 @@ static void ft1000_disable_interrupts(struct net_device *dev)
//---------------------------------------------------------------------------
static void ft1000_reset_asic(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 tempword;
DEBUG(1, "ft1000_hw:ft1000_reset_asic called\n");
(*info->ft1000_reset) (info->link);
- info->ASICResetNum++;
// Let's use the register provided by the Magnemite ASIC to reset the
// ASIC and DSP.
@@ -412,17 +366,17 @@ static void ft1000_reset_asic(struct net_device *dev)
// Input:
// dev - device structure
// Output:
-// status - FALSE (card reset fail)
-// TRUE (card reset successful)
+// status - false (card reset fail)
+// true (card reset successful)
//
//---------------------------------------------------------------------------
static int ft1000_reset_card(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 tempword;
int i;
unsigned long flags;
- PPROV_RECORD ptr;
+ struct prov_record *ptr;
DEBUG(1, "ft1000_hw:ft1000_reset_card called.....\n");
@@ -437,7 +391,7 @@ static int ft1000_reset_card(struct net_device *dev)
while (list_empty(&info->prov_list) == 0) {
DEBUG(0,
"ft1000_hw:ft1000_reset_card:deleting provisioning record\n");
- ptr = list_entry(info->prov_list.next, PROV_RECORD, list);
+ ptr = list_entry(info->prov_list.next, struct prov_record, list);
list_del(&ptr->list);
kfree(ptr->pprov_data);
kfree(ptr);
@@ -457,14 +411,12 @@ static int ft1000_reset_card(struct net_device *dev)
if (ft1000_card_present == 1) {
spin_lock_irqsave(&info->dpram_lock, flags);
if (info->AsicID == ELECTRABUZZ_ID) {
- if (info->DspHibernateFlag == 0) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC; i++) {
- info->DSPSess.Rec[i] =
- ft1000_read_reg(dev,
- FT1000_REG_DPRAM_DATA);
- }
+ ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
+ FT1000_DPRAM_RX_BASE);
+ for (i = 0; i < MAX_DSP_SESS_REC; i++) {
+ info->DSPSess.Rec[i] =
+ ft1000_read_reg(dev,
+ FT1000_REG_DPRAM_DATA);
}
} else {
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
@@ -482,8 +434,6 @@ static int ft1000_reset_card(struct net_device *dev)
//reset ASIC
ft1000_reset_asic(dev);
- info->DSPResetNum++;
-
DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n");
if (info->AsicID == MAGNEMITE_ID) {
@@ -517,7 +467,7 @@ static int ft1000_reset_card(struct net_device *dev)
if (i == 50) {
DEBUG(0,
"ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n");
- return FALSE;
+ return false;
}
} else {
@@ -528,7 +478,7 @@ static int ft1000_reset_card(struct net_device *dev)
if (card_download(dev, fw_entry->data, fw_entry->size)) {
DEBUG(1, "card download unsuccessful\n");
- return FALSE;
+ return false;
} else {
DEBUG(1, "card download successful\n");
}
@@ -564,7 +514,7 @@ static int ft1000_reset_card(struct net_device *dev)
// poll_timer.data = (u_long)dev;
// add_timer(&poll_timer);
- return TRUE;
+ return true;
}
@@ -576,8 +526,8 @@ static int ft1000_reset_card(struct net_device *dev)
// Input:
// dev - device structure
// Output:
-// status - FALSE (device is not present)
-// TRUE (device is present)
+// status - false (device is not present)
+// true (device is present)
//
//---------------------------------------------------------------------------
static int ft1000_chkcard(struct net_device *dev)
@@ -590,7 +540,7 @@ static int ft1000_chkcard(struct net_device *dev)
if (tempword == 0) {
DEBUG(1,
"ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
- return FALSE;
+ return false;
}
// The system will return the value of 0xffff for the version register
// if the device is not present.
@@ -598,9 +548,9 @@ static int ft1000_chkcard(struct net_device *dev)
if (tempword == 0xffff) {
DEBUG(1,
"ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
@@ -619,8 +569,8 @@ static void ft1000_hbchk(u_long data)
{
struct net_device *dev = (struct net_device *)data;
- FT1000_INFO *info;
- USHORT tempword;
+ struct ft1000_info *info;
+ u16 tempword;
info = netdev_priv(dev);
@@ -833,14 +783,14 @@ static void ft1000_hbchk(u_long data)
// Output:
//
//---------------------------------------------------------------------------
-void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
+static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
int i;
u16 tempword;
unsigned long flags;
- size += PSEUDOSZ;
+ size += sizeof(struct pseudo_hdr);
// check for odd byte and increment to 16-bit word align value
if ((size & 0x0001)) {
size++;
@@ -918,9 +868,10 @@ void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qt
// = 1 (successful)
//
//---------------------------------------------------------------------------
-BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 *pnxtph)
+static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer,
+ int maxsz, u16 *pnxtph)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 size;
u16 *ppseudohdr;
int i;
@@ -928,18 +879,18 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16
unsigned long flags;
if (info->AsicID == ELECTRABUZZ_ID) {
- size = ( ft1000_read_dpram(dev, *pnxtph) ) + PSEUDOSZ;
+ size = ( ft1000_read_dpram(dev, *pnxtph) ) + sizeof(struct pseudo_hdr);
} else {
size =
ntohs(ft1000_read_dpram_mag_16
(dev, FT1000_MAG_PH_LEN,
- FT1000_MAG_PH_LEN_INDX)) + PSEUDOSZ;
+ FT1000_MAG_PH_LEN_INDX)) + sizeof(struct pseudo_hdr);
}
if (size > maxsz) {
DEBUG(1,
"FT1000:ft1000_receive_cmd:Invalid command length = %d\n",
size);
- return FALSE;
+ return false;
} else {
ppseudohdr = (u16 *) pbuffer;
spin_lock_irqsave(&info->dpram_lock, flags);
@@ -994,9 +945,9 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16
DEBUG(1,
"FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n");
// Drop this message
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
}
@@ -1011,19 +962,19 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16
// none
//
//---------------------------------------------------------------------------
-void ft1000_proc_drvmsg(struct net_device *dev)
+static void ft1000_proc_drvmsg(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 msgtype;
u16 tempword;
- PMEDIAMSG pmediamsg;
- PDSPINITMSG pdspinitmsg;
- PDRVMSG pdrvmsg;
+ struct media_msg *pmediamsg;
+ struct dsp_init_msg *pdspinitmsg;
+ struct drv_msg *pdrvmsg;
u16 len;
u16 i;
- PPROV_RECORD ptr;
- PPSEUDO_HDR ppseudo_hdr;
- PUSHORT pmsg;
+ struct prov_record *ptr;
+ struct pseudo_hdr *ppseudo_hdr;
+ u16 *pmsg;
struct timeval tv;
union {
u8 byte[2];
@@ -1039,7 +990,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) {
// Get the message type which is total_len + PSEUDO header + msgtype + message body
- pdrvmsg = (PDRVMSG) & cmdbuffer[0];
+ pdrvmsg = (struct drv_msg *) & cmdbuffer[0];
msgtype = ntohs(pdrvmsg->type);
DEBUG(1, "Command message type = 0x%x\n", msgtype);
switch (msgtype) {
@@ -1062,12 +1013,12 @@ void ft1000_proc_drvmsg(struct net_device *dev)
}
ptr =
list_entry(info->prov_list.next,
- PROV_RECORD, list);
+ struct prov_record, list);
len = *(u16 *) ptr->pprov_data;
len = htons(len);
- pmsg = (PUSHORT) ptr->pprov_data;
- ppseudo_hdr = (PPSEUDO_HDR) pmsg;
+ pmsg = (u16 *) ptr->pprov_data;
+ ppseudo_hdr = (struct pseudo_hdr *) pmsg;
// Insert slow queue sequence number
ppseudo_hdr->seq_num = info->squeseqnum++;
ppseudo_hdr->portsrc = 0;
@@ -1091,7 +1042,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
info->CardReady = 1;
break;
case MEDIA_STATE:
- pmediamsg = (PMEDIAMSG) & cmdbuffer[0];
+ pmediamsg = (struct media_msg *) & cmdbuffer[0];
if (info->ProgConStat != 0xFF) {
if (pmediamsg->state) {
DEBUG(1, "Media is up\n");
@@ -1123,7 +1074,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
}
break;
case DSP_INIT_MSG:
- pdspinitmsg = (PDSPINITMSG) & cmdbuffer[0];
+ pdspinitmsg = (struct dsp_init_msg *) & cmdbuffer[0];
memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
DEBUG(1, "DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
info->DspVer[0], info->DspVer[1], info->DspVer[2],
@@ -1140,7 +1091,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
dev->dev_addr[5] = info->eui64[7];
if (ntohs(pdspinitmsg->length) ==
- (sizeof(DSPINITMSG) - 20)) {
+ (sizeof(struct dsp_init_msg) - 20)) {
memcpy(info->ProductMode,
pdspinitmsg->ProductMode, MODESZ);
memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
@@ -1157,7 +1108,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
tempword = ntohs(pdrvmsg->length);
info->DSPInfoBlklen = tempword;
if (tempword < (MAX_DSP_SESS_REC - 4)) {
- pmsg = (PUSHORT) & pdrvmsg->data[0];
+ pmsg = (u16 *) & pdrvmsg->data[0];
for (i = 0; i < ((tempword + 1) / 2); i++) {
DEBUG(1,
"FT1000:drivermsg:dsp info data = 0x%x\n",
@@ -1169,7 +1120,6 @@ void ft1000_proc_drvmsg(struct net_device *dev)
case DSP_GET_INFO:
DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n");
// copy dsp info block to dsp
- info->DrvMsgPend = 1;
// allow any outstanding ioctl to finish
mdelay(10);
tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
@@ -1185,8 +1135,8 @@ void ft1000_proc_drvmsg(struct net_device *dev)
if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
// Put message into Slow Queue
// Form Pseudo header
- pmsg = (PUSHORT) info->DSPInfoBlk;
- ppseudo_hdr = (PPSEUDO_HDR) pmsg;
+ pmsg = (u16 *) info->DSPInfoBlk;
+ ppseudo_hdr = (struct pseudo_hdr *) pmsg;
ppseudo_hdr->length =
htons(info->DSPInfoBlklen + 4);
ppseudo_hdr->source = 0x10;
@@ -1210,15 +1160,13 @@ void ft1000_proc_drvmsg(struct net_device *dev)
info->DSPInfoBlk[8] = 0x7200;
info->DSPInfoBlk[9] =
htons(info->DSPInfoBlklen);
- ft1000_send_cmd (dev, (PUSHORT)info->DSPInfoBlk, (USHORT)(info->DSPInfoBlklen+4), 0);
+ ft1000_send_cmd (dev, (u16 *)info->DSPInfoBlk, (u16)(info->DSPInfoBlklen+4), 0);
}
- info->DrvMsgPend = 0;
break;
case GET_DRV_ERR_RPT_MSG:
DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
// copy driver error message to dsp
- info->DrvMsgPend = 1;
// allow any outstanding ioctl to finish
mdelay(10);
tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
@@ -1234,8 +1182,8 @@ void ft1000_proc_drvmsg(struct net_device *dev)
if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
// Put message into Slow Queue
// Form Pseudo header
- pmsg = (PUSHORT) & tempbuffer[0];
- ppseudo_hdr = (PPSEUDO_HDR) pmsg;
+ pmsg = (u16 *) & tempbuffer[0];
+ ppseudo_hdr = (struct pseudo_hdr *) pmsg;
ppseudo_hdr->length = htons(0x0012);
ppseudo_hdr->source = 0x10;
ppseudo_hdr->destination = 0x20;
@@ -1255,7 +1203,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
for (i=1; i<7; i++) {
ppseudo_hdr->checksum ^= *pmsg++;
}
- pmsg = (PUSHORT) & tempbuffer[16];
+ pmsg = (u16 *) & tempbuffer[16];
*pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
*pmsg++ = htons(0x000e);
*pmsg++ = htons(info->DSP_TIME[0]);
@@ -1270,10 +1218,9 @@ void ft1000_proc_drvmsg(struct net_device *dev)
*pmsg++ = convert.wrd;
*pmsg++ = htons(info->DrvErrNum);
- ft1000_send_cmd (dev, (PUSHORT)&tempbuffer[0], (USHORT)(0x0012), 0);
+ ft1000_send_cmd (dev, (u16 *)&tempbuffer[0], (u16)(0x0012), 0);
info->DrvErrNum = 0;
}
- info->DrvMsgPend = 0;
break;
default:
@@ -1294,9 +1241,9 @@ void ft1000_proc_drvmsg(struct net_device *dev)
// SUCCESS
//
//---------------------------------------------------------------------------
-int ft1000_parse_dpram_msg(struct net_device *dev)
+static int ft1000_parse_dpram_msg(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 doorbell;
u16 portid;
u16 nxtph;
@@ -1340,13 +1287,11 @@ int ft1000_parse_dpram_msg(struct net_device *dev)
ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
HOST_INTF_BE);
}
- info->DspAsicReset = 0;
}
if (doorbell & FT1000_DSP_ASIC_RESET) {
DEBUG(0,
"FT1000:ft1000_parse_dpram_msg: Got a dsp ASIC reset message\n");
- info->DspAsicReset = 1;
ft1000_write_reg(dev, FT1000_REG_DOORBELL,
FT1000_DSP_ASIC_RESET);
udelay(200);
@@ -1368,7 +1313,7 @@ int ft1000_parse_dpram_msg(struct net_device *dev)
}
DEBUG(1, "FT1000:ft1000_parse_dpram_msg:total length = %d\n",
total_len);
- if ((total_len < MAX_CMD_SQSIZE) && (total_len > PSEUDOSZ)) {
+ if ((total_len < MAX_CMD_SQSIZE) && (total_len > sizeof(struct pseudo_hdr))) {
total_len += nxtph;
cnt = 0;
// ft1000_read_reg will return a value that needs to be byteswap
@@ -1453,7 +1398,7 @@ int ft1000_parse_dpram_msg(struct net_device *dev)
//---------------------------------------------------------------------------
static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 i;
u32 templong;
u16 tempword;
@@ -1597,10 +1542,10 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
// SUCCESS
//
//---------------------------------------------------------------------------
-int ft1000_copy_up_pkt(struct net_device *dev)
+static int ft1000_copy_up_pkt(struct net_device *dev)
{
u16 tempword;
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 len;
struct sk_buff *skb;
u16 i;
@@ -1715,7 +1660,7 @@ int ft1000_copy_up_pkt(struct net_device *dev)
tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
*pbuffer++ = (u8) (tempword >> 8);
*pbuffer++ = (u8) tempword;
- if (ft1000_chkcard(dev) == FALSE) {
+ if (ft1000_chkcard(dev) == false) {
kfree_skb(skb);
return FAILURE;
}
@@ -1785,13 +1730,13 @@ int ft1000_copy_up_pkt(struct net_device *dev)
// SUCCESS
//
//---------------------------------------------------------------------------
-int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
+static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
union {
- PSEUDO_HDR blk;
- u16 buff[sizeof(PSEUDO_HDR) >> 1];
- u8 buffc[sizeof(PSEUDO_HDR)];
+ struct pseudo_hdr blk;
+ u16 buff[sizeof(struct pseudo_hdr) >> 1];
+ u8 buffc[sizeof(struct pseudo_hdr)];
} pseudo;
int i;
u32 *plong;
@@ -1947,7 +1892,7 @@ int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
static struct net_device_stats *ft1000_stats(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
return (&info->stats);
}
@@ -1971,7 +1916,7 @@ static int ft1000_open(struct net_device *dev)
static int ft1000_close(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
DEBUG(0, "ft1000_hw: ft1000_close()\n");
@@ -1993,7 +1938,7 @@ static int ft1000_close(struct net_device *dev)
static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u8 *pdata;
DEBUG(1, "ft1000_hw: ft1000_start_xmit()\n");
@@ -2030,7 +1975,7 @@ static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- FT1000_INFO *info = netdev_priv(dev);
+ struct ft1000_info *info = netdev_priv(dev);
u16 tempword;
u16 inttype;
int cnt;
@@ -2042,7 +1987,7 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
- if (ft1000_chkcard(dev) == FALSE) {
+ if (ft1000_chkcard(dev) == false) {
ft1000_disable_interrupts(dev);
return IRQ_HANDLED;
}
@@ -2095,8 +2040,8 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
void stop_ft1000_card(struct net_device *dev)
{
- FT1000_INFO *info = netdev_priv(dev);
- PPROV_RECORD ptr;
+ struct ft1000_info *info = netdev_priv(dev);
+ struct prov_record *ptr;
// int cnt;
DEBUG(0, "ft1000_hw: stop_ft1000_card()\n");
@@ -2108,7 +2053,7 @@ void stop_ft1000_card(struct net_device *dev)
// Make sure we free any memory reserve for provisioning
while (list_empty(&info->prov_list) == 0) {
- ptr = list_entry(info->prov_list.next, PROV_RECORD, list);
+ ptr = list_entry(info->prov_list.next, struct prov_record, list);
list_del(&ptr->list);
kfree(ptr->pprov_data);
kfree(ptr);
@@ -2130,7 +2075,7 @@ void stop_ft1000_card(struct net_device *dev)
static void ft1000_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- FT1000_INFO *ft_info;
+ struct ft1000_info *ft_info;
ft_info = netdev_priv(dev);
snprintf(info->driver, 32, "ft1000");
@@ -2142,7 +2087,7 @@ static void ft1000_get_drvinfo(struct net_device *dev,
static u32 ft1000_get_link(struct net_device *dev)
{
- FT1000_INFO *info;
+ struct ft1000_info *info;
info = netdev_priv(dev);
return info->mediastate;
}
@@ -2153,9 +2098,9 @@ static const struct ethtool_ops ops = {
};
struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset)
+ void *ft1000_reset)
{
- FT1000_INFO *info;
+ struct ft1000_info *info;
struct net_device *dev;
static const struct net_device_ops ft1000ops = // Slavius 21.10.2009 due to kernel changes
@@ -2180,7 +2125,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
return NULL;
}
- dev = alloc_etherdev(sizeof(FT1000_INFO));
+ dev = alloc_etherdev(sizeof(struct ft1000_info));
if (!dev) {
printk(KERN_ERR "ft1000: failed to allocate etherdev\n");
return NULL;
@@ -2189,7 +2134,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
SET_NETDEV_DEV(dev, &link->dev);
info = netdev_priv(dev);
- memset(info, 0, sizeof(FT1000_INFO));
+ memset(info, 0, sizeof(struct ft1000_info));
DEBUG(1, "address of dev = 0x%8x\n", (u32) dev);
DEBUG(1, "address of dev info = 0x%8x\n", (u32) info);
@@ -2199,16 +2144,11 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
spin_lock_init(&info->dpram_lock);
info->DrvErrNum = 0;
- info->ASICResetNum = 0;
info->registered = 1;
info->link = link;
info->ft1000_reset = ft1000_reset;
info->mediastate = 0;
info->fifo_cnt = 0;
- info->DeviceCreated = FALSE;
- info->DeviceMajor = 0;
- info->CurrentInterruptEnableMask = ISR_DEFAULT_MASK;
- info->InterruptsEnabled = FALSE;
info->CardReady = 0;
info->DSP_TIME[0] = 0;
info->DSP_TIME[1] = 0;
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
index bdfb1ae..7faeada 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
@@ -22,6 +22,7 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
+#include <asm/io.h>
#include <asm/uaccess.h>
#include "ft1000.h"
@@ -47,13 +48,13 @@
} \
len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i])
-int ft1000ReadProc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int ft1000ReadProc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
struct net_device *dev;
int len;
int i;
- FT1000_INFO *info;
+ struct ft1000_info *info;
char *status[] =
{ "Idle (Disconnect)", "Searching", "Active (Connected)",
"Waiting for L2", "Sleep", "No Coverage", "", ""
@@ -75,16 +76,14 @@ int ft1000ReadProc(char *page, char **start, off_t off,
/* Wrap-around */
if (info->AsicID == ELECTRABUZZ_ID) {
- if (info->DspHibernateFlag == 0) {
- if (info->ProgConStat != 0xFF) {
- info->LedStat =
- ft1000_read_dpram(dev, FT1000_DSP_LED);
- info->ConStat =
- ft1000_read_dpram(dev,
- FT1000_DSP_CON_STATE);
- } else {
- info->ConStat = 0xf;
- }
+ if (info->ProgConStat != 0xFF) {
+ info->LedStat =
+ ft1000_read_dpram(dev, FT1000_DSP_LED);
+ info->ConStat =
+ ft1000_read_dpram(dev,
+ FT1000_DSP_CON_STATE);
+ } else {
+ info->ConStat = 0xf;
}
} else {
if (info->ProgConStat != 0xFF) {
@@ -172,7 +171,7 @@ static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
void *ptr)
{
struct net_device *dev = ptr;
- FT1000_INFO *info;
+ struct ft1000_info *info;
info = netdev_priv(dev);
@@ -193,7 +192,7 @@ static struct notifier_block ft1000_netdev_notifier = {
void ft1000InitProc(struct net_device *dev)
{
- FT1000_INFO *info;
+ struct ft1000_info *info;
info = netdev_priv(dev);
@@ -206,7 +205,7 @@ void ft1000InitProc(struct net_device *dev)
void ft1000CleanupProc(struct net_device *dev)
{
- FT1000_INFO *info;
+ struct ft1000_info *info;
info = netdev_priv(dev);
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
index b0a4211..aaf44c3 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
@@ -485,7 +485,7 @@ void card_send_command(struct ft1000_device *ft1000dev, void *ptempbuffer,
DEBUG("card_send_command: enter card_send_command... size=%d\n", size);
- commandbuf = (unsigned char *)kmalloc(size + 2, GFP_KERNEL);
+ commandbuf = kmalloc(size + 2, GFP_KERNEL);
memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size);
ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
@@ -671,7 +671,6 @@ static int ft1000_reset_card(struct net_device *dev)
return TRUE;
}
-#ifdef HAVE_NET_DEVICE_OPS
static const struct net_device_ops ftnet_ops =
{
.ndo_open = &ft1000_open,
@@ -679,7 +678,6 @@ static const struct net_device_ops ftnet_ops =
.ndo_start_xmit = &ft1000_start_xmit,
.ndo_get_stats = &ft1000_netdev_stats,
};
-#endif
//---------------------------------------------------------------------------
@@ -764,14 +762,7 @@ int init_ft1000_netdev(struct ft1000_device *ft1000dev)
INIT_LIST_HEAD(&pInfo->nodes.list);
-#ifdef HAVE_NET_DEVICE_OPS
netdev->netdev_ops = &ftnet_ops;
-#else
- netdev->hard_start_xmit = &ft1000_start_xmit;
- netdev->get_stats = &ft1000_netdev_stats;
- netdev->open = &ft1000_open;
- netdev->stop = &ft1000_close;
-#endif
ft1000dev->net = netdev;
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
index 6a8a196..3f4207f 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
@@ -26,38 +26,6 @@
#ifndef _FT1000IOCTLH_
#define _FT1000IOCTLH_
-#define DSPVERSZ 4
-#define HWSERNUMSZ 16
-#define SKUSZ 20
-#define EUISZ 8
-#define CALVERSZ 2
-#define CALDATESZ 6
-
-#define MAX_DNLD_BLKSZ 1024
-
-// Standard Flarion Pseudo header
-struct pseudo_hdr {
- unsigned short length; //length of msg body
- unsigned char source; //source address (0x10=Host 0x20=DSP)
- unsigned char destination; //destination address (refer to source address)
- unsigned char portdest; //destination port id
- // 0x00=Driver
- // 0x10=Application Broadcast
- // 0x20=Network Stack
- // 0x80=Dsp OAM
- // 0x90=Dsp Airlink
- // 0xa0=Dsp Loader
- // 0xb0=Dsp MIP
- unsigned char portsrc; //source port id (refer to portdest)
- unsigned short sh_str_id; //stream id (Not applicable on Mobile)
- unsigned char control; //stream id (Not applicable on Mobile)
- unsigned char rsvd1; //reserved
- unsigned char seq_num; //sequence number
- unsigned char rsvd2; //reserved
- unsigned short qos_class; //Quality of Service class (Not applicable on Mobile)
- unsigned short checksum; //Pseudo header checksum
-} __attribute__ ((packed));
-
typedef struct _IOCTL_GET_VER
{
unsigned long drv_ver;
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
index 0b30020..51c0847 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
@@ -2,81 +2,18 @@
#define _FT1000_USB_H_
/*Jim*/
+#include "../ft1000.h"
#include "ft1000_ioctl.h"
#define FT1000_DRV_VER 0x01010403
-#define MODESZ 2
#define MAX_NUM_APP 6
#define MAX_MSG_LIMIT 200
#define NUM_OF_FREE_BUFFERS 1500
-// Driver message types
-#define MEDIA_STATE 0x0010
-#define DSP_PROVISION 0x0030
-#define DSP_INIT_MSG 0x0050
-#define DSP_STORE_INFO 0x0070
-#define DSP_GET_INFO 0x0071
-#define GET_DRV_ERR_RPT_MSG 0x0073
-#define RSP_DRV_ERR_RPT_MSG 0x0074
-
-
-// Size of DPRAM Command
-#define MAX_CMD_SQSIZE 1780
-#define SLOWQ_TYPE 0
#define PSEUDOSZ 16
-#define DSP_QID_OFFSET 4
-
-
-// MEMORY MAP FOR ELECTRABUZZ ASIC
-#define FT1000_REG_DFIFO_STAT 0x0008 // Downlink FIFO status register
-#define FT1000_REG_DPRAM_DATA 0x000C // DPRAM VALUE in DPRAM ADDR
-
-#define FT1000_DSP_LED 0xFFA // dsp led status for PAD device
-
-#define FT1000_MAG_DSP_LED 0x3FE // dsp led status for PAD device
-#define FT1000_MAG_DSP_LED_INDX 0x1 // dsp led status for PAD device
#define SUCCESS 0x00
-
-#define DRIVERID 0x00
-
-// Driver Error Messages for DSP
-#define DSP_CONDRESET_INFO 0x7ef2
-#define DSP_HB_INFO 0x7ef0
-
-// Magnemite specific defines
-#define hi_mag 0x6968 // Byte swap hi to avoid additional system call
-#define ho_mag 0x6f68 // Byte swap ho to avoid additional system call
-
-
-
-struct media_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u16 state;
- u32 ip_addr;
- u32 net_mask;
- u32 gateway;
- u32 dns_1;
- u32 dns_2;
-} __attribute__ ((packed));
-
-struct dsp_init_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u8 DspVer[DSPVERSZ]; // DSP version number
- u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
- u8 Sku[SKUSZ]; // SKU
- u8 eui64[EUISZ]; // EUI64
- u8 ProductMode[MODESZ]; // Product Mode (Market/Production)
- u8 RfCalVer[CALVERSZ]; // Rf Calibration version
- u8 RfCalDate[CALDATESZ]; // Rf Calibration date
-} __attribute__ ((packed));
-
-
struct app_info_block {
u32 nTxMsg; // DPRAM msg sent to DSP with app_id
u32 nRxMsg; // DPRAM msg rcv from dsp with app_id
@@ -90,11 +27,6 @@ struct app_info_block {
struct list_head app_sqlist; // link list of msgs for applicaton on slow queue
} __attribute__((packed));
-struct prov_record {
- struct list_head list;
- u8 *pprov_data;
-};
-
/*end of Jim*/
#define DEBUG(args...) printk(KERN_INFO args)
@@ -108,350 +40,25 @@ struct prov_record {
#define LARGE_TIMEOUT 5000
-#define MAX_DSP_SESS_REC 1024
-
-#define MAX_NUM_CARDS 32
-
-#define DSPVERSZ 4
-#define HWSERNUMSZ 16
-#define SKUSZ 20
-#define EUISZ 8
-#define CALVERSZ 2
-#define CALDATESZ 6
-#define MODESZ 2
-
-#define DSPID 0x20
-#define HOSTID 0x10
-
-#define DSPOAM 0x80
-#define DSPAIRID 0x90
-
-#define DRIVERID 0x00
-#define FMM 0x10
-#define NETWORKID 0x20
-#define AUTOLNCHID 0x30
-#define DSPLPBKID 0x40
-
#define DSPBCMSGID 0x10
-#define ENET_MAX_SIZE 1514
-#define ENET_HEADER_SIZE 14
-
-
-#define CIS_NET_ADDR_OFFSET 0xff0
-
-// MAGNEMITE specific
-
-#define FT1000_REG_MAG_UFDR 0x0000 // Uplink FIFO Data Register.
-
-#define FT1000_REG_MAG_UFDRL 0x0000 // Uplink FIFO Data Register low-word.
-
-#define FT1000_REG_MAG_UFDRH 0x0002 // Uplink FIFO Data Register high-word.
-
-#define FT1000_REG_MAG_UFER 0x0004 // Uplink FIFO End Register
-
-#define FT1000_REG_MAG_UFSR 0x0006 // Uplink FIFO Status Register
-
-#define FT1000_REG_MAG_DFR 0x0008 // Downlink FIFO Register
-
-#define FT1000_REG_MAG_DFRL 0x0008 // Downlink FIFO Register low-word
-
-#define FT1000_REG_MAG_DFRH 0x000a // Downlink FIFO Register high-word
-
-#define FT1000_REG_MAG_DFSR 0x000c // Downlink FIFO Status Register
-
-#define FT1000_REG_MAG_DPDATA 0x0010 // Dual Port RAM Indirect Data Register
-
-#define FT1000_REG_MAG_DPDATAL 0x0010 // Dual Port RAM Indirect Data Register low-word
-
-#define FT1000_REG_MAG_DPDATAH 0x0012 // Dual Port RAM Indirect Data Register high-word
-
-#define FT1000_REG_MAG_WATERMARK 0x002c // Supv. Control Reg. LLC register
-
-#define FT1000_REG_MAG_VERSION 0x0030 // LLC Version LLC register
-
-
-
-// Common
-
-#define FT1000_REG_DPRAM_ADDR 0x000E // DPRAM ADDRESS when card in IO mode
-
-#define FT1000_REG_SUP_CTRL 0x0020 // Supv. Control Reg. LLC register
-
-#define FT1000_REG_SUP_STAT 0x0022 // Supv. Status Reg LLC register
-
-#define FT1000_REG_RESET 0x0024 // Reset Reg LLC register
-
-#define FT1000_REG_SUP_ISR 0x0026 // Supv ISR LLC register
-
-#define FT1000_REG_SUP_IMASK 0x0028 // Supervisor Interrupt Mask LLC register
-
-#define FT1000_REG_DOORBELL 0x002a // Door Bell Reg LLC register
-
-#define FT1000_REG_ASIC_ID 0x002e // ASIC Identification Number
-
- // (Electrabuzz=0 Magnemite=TBD)
-
-
-
-// DSP doorbells
-
-#define FT1000_DB_DPRAM_RX 0x0001 // this value indicates that DSP has
-
- // data for host in DPRAM SlowQ
-
-#define FT1000_DB_DNLD_RX 0x0002 // Downloader handshake doorbell
-
-#define FT1000_ASIC_RESET_REQ 0x0004
-
-#define FT1000_DSP_ASIC_RESET 0x0008
-
-
-
-#define FT1000_DB_COND_RESET 0x0010
-
-
-
-// Host doorbells
-
-#define FT1000_DB_DPRAM_TX 0x0100 // this value indicates that host has
-
- // data for DSP in DPRAM.
-
-#define FT1000_DB_DNLD_TX 0x0200 // Downloader handshake doorbell
-
-#define FT1000_ASIC_RESET_DSP 0x0400
-
-#define FT1000_DB_HB 0x1000 // this value indicates that supervisor
-
-
-
-// Electrabuzz specific DPRAM mapping // has a heartbeat message for DSP.
-
-#define FT1000_DPRAM_BASE 0x1000 // 0x0000 to 0x07FF DPRAM 2Kx16 - R/W from PCMCIA or DSP
-
-#define FT1000_DPRAM_TX_BASE 0x1002 // TX AREA (SlowQ)
-
-#define FT1000_DPRAM_RX_BASE 0x1800 // RX AREA (SlowQ)
-
-#define FT1000_DPRAM_SIZE 0x1000 // 4K bytes
-
-
-
-#define FT1000_DRV_DEBUG 0x17E0 // Debug area for driver
-
-#define FT1000_FIFO_LEN 0x17FC // total length for DSP FIFO tracking
-
-#define FT1000_HI_HO 0x17FE // heartbeat with HI/HO
-
-#define FT1000_DSP_STATUS 0x1FFE // dsp status - non-zero is a request to reset dsp
-
-
-
-#define FT1000_DSP_CON_STATE 0x1FF8 // DSP Connection Status Info
-
-#define FT1000_DSP_LEDS 0x1FFA // DSP LEDS for rcv pwr strength, Rx data, Tx data
-
-#define DSP_TIMESTAMP 0x1FFC // dsp timestamp
-
-#define DSP_TIMESTAMP_DIFF 0x1FFA // difference of dsp timestamp in DPRAM and Pseudo header.
-
-
-
-#define FT1000_DPRAM_FEFE 0x1002 // Dsp Downloader handshake location
-
-
-
-#define FT1000_DSP_TIMER0 0x1FF0
-
-#define FT1000_DSP_TIMER1 0x1FF2
-
-#define FT1000_DSP_TIMER2 0x1FF4
-
-#define FT1000_DSP_TIMER3 0x1FF6
-
-
+/* Electrabuzz specific DPRAM mapping */
+/* this is used by ft1000_usb driver - isn't that a bug? */
+#undef FT1000_DPRAM_RX_BASE
+#define FT1000_DPRAM_RX_BASE 0x1800 /* RX AREA (SlowQ) */
// MEMORY MAP FOR MAGNEMITE
-
-#define FT1000_DPRAM_MAG_TX_BASE 0x0000 // TX AREA (SlowQ)
-
-#define FT1000_DPRAM_MAG_RX_BASE 0x0200 // RX AREA (SlowQ)
-
-
-
-#define FT1000_MAG_FIFO_LEN 0x1FF // total length for DSP FIFO tracking
-
-#define FT1000_MAG_FIFO_LEN_INDX 0x1 // low-word index
-
-#define FT1000_MAG_HI_HO 0x1FF // heartbeat with HI/HO
-
-#define FT1000_MAG_HI_HO_INDX 0x0 // high-word index
-
-#define FT1000_MAG_DSP_LEDS 0x3FE // dsp led status for PAD device
-
-#define FT1000_MAG_DSP_LEDS_INDX 0x1 // dsp led status for PAD device
-
-
-
-#define FT1000_MAG_DSP_CON_STATE 0x3FE // DSP Connection Status Info
-
-#define FT1000_MAG_DSP_CON_STATE_INDX 0x0 // DSP Connection Status Info
-
-
-
-#define FT1000_MAG_DPRAM_FEFE 0x000 // location for dsp ready indicator
-
-#define FT1000_MAG_DPRAM_FEFE_INDX 0x0 // location for dsp ready indicator
-
-
-
-#define FT1000_MAG_DSP_TIMER0 0x3FC
-
-#define FT1000_MAG_DSP_TIMER0_INDX 0x1
-
-
-
-#define FT1000_MAG_DSP_TIMER1 0x3FC
-
-#define FT1000_MAG_DSP_TIMER1_INDX 0x0
-
-
-
-#define FT1000_MAG_DSP_TIMER2 0x3FD
-
-#define FT1000_MAG_DSP_TIMER2_INDX 0x1
-
-
-
-#define FT1000_MAG_DSP_TIMER3 0x3FD
-
-#define FT1000_MAG_DSP_TIMER3_INDX 0x0
-
-
-
-#define FT1000_MAG_TOTAL_LEN 0x200
-
-#define FT1000_MAG_TOTAL_LEN_INDX 0x1
-
-
-
-#define FT1000_MAG_PH_LEN 0x200
-
-#define FT1000_MAG_PH_LEN_INDX 0x0
-
-
-
-#define FT1000_MAG_PORT_ID 0x201
-
-#define FT1000_MAG_PORT_ID_INDX 0x0
-
-
-
-//
-
-// Constants for the FT1000_REG_SUP_ISR
-
-//
-
-// Indicate the cause of an interrupt.
-
-//
-
-// SUPERVISOR ISR BIT MAPS
-
-
-
-#define ISR_EMPTY (u8)0x00 // no bits set in ISR
-
-#define ISR_DOORBELL_ACK (u8)0x01 // the doorbell i sent has been received.
-
-#define ISR_DOORBELL_PEND (u8)0x02 // doorbell for me
-
-#define ISR_RCV (u8)0x04 // packet received with no errors
-
-#define ISR_WATERMARK (u8)0x08 //
-
-
-
-// Interrupt mask register defines
-
-// note these are different from the ISR BIT MAPS.
-
-#define ISR_MASK_NONE 0x0000
-
-#define ISR_MASK_DOORBELL_ACK 0x0001
-
-#define ISR_MASK_DOORBELL_PEND 0x0002
-
-#define ISR_MASK_RCV 0x0004
-
-#define ISR_MASK_WATERMARK 0x0008 // Normally we will only mask the watermark interrupt when we want to enable interrupts.
-
-#define ISR_MASK_ALL 0xffff
-
-
-
-#define HOST_INTF_LE 0x0000 // Host interface little endian
-
-#define HOST_INTF_BE 0x0001 // Host interface big endian
-
-
-
-#define ISR_DEFAULT_MASK 0x7ff9
-
-
-
-#define hi 0x6869
-
-#define ho 0x686f
-
-
-
-#define FT1000_ASIC_RESET 0x80 // COR value for soft reset to PCMCIA core
-
-#define FT1000_ASIC_BITS 0x51 // Bits set in COR register under normal operation
-
-#define FT1000_ASIC_MAG_BITS 0x55 // Bits set in COR register under normal operation
-
-
-
-#define FT1000_COR_OFFSET 0x100
-
-
-
-#define ELECTRABUZZ_ID 0 // ASIC ID for ELECTRABUZZ
-
-#define MAGNEMITE_ID 0x1a01 // ASIC ID for MAGNEMITE
-
-
+/* the indexes are swapped comparing to PCMCIA - is it OK or a bug? */
+#undef FT1000_MAG_DSP_LED_INDX
+#define FT1000_MAG_DSP_LED_INDX 0x1 /* dsp led status for PAD device */
+#undef FT1000_MAG_DSP_CON_STATE_INDX
+#define FT1000_MAG_DSP_CON_STATE_INDX 0x0 /* DSP Connection Status Info */
// Maximum times trying to get ASIC out of reset
-
#define MAX_ASIC_RESET_CNT 20
-
-
-#define DSP_RESET_BIT 0x1
-
-#define ASIC_RESET_BIT 0x2
-
-#define DSP_UNENCRYPTED 0x4
-
-#define DSP_ENCRYPTED 0x8
-
-#define EFUSE_MEM_DISABLE 0x0040
-
-
#define MAX_BUF_SIZE 4096
-struct drv_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u8 data[0];
-} __attribute__ ((packed));
-
struct ft1000_device
{
struct usb_device *dev;
diff --git a/drivers/staging/iio/addac/Kconfig b/drivers/staging/iio/addac/Kconfig
index 9847baf..698a897 100644
--- a/drivers/staging/iio/addac/Kconfig
+++ b/drivers/staging/iio/addac/Kconfig
@@ -1,10 +1,11 @@
#
# ADDAC drivers
#
-comment "Analog digital bi-direction convertors"
+menu "Analog digital bi-direction converters"
config ADT7316
tristate "Analog Devices ADT7316/7/8 ADT7516/7/9 temperature sensor, ADC and DAC driver"
+ depends on GENERIC_GPIO
help
Say yes here to build support for Analog Devices ADT7316, ADT7317, ADT7318
and ADT7516, ADT7517, ADT7519 temperature sensors, ADC and DAC.
@@ -23,3 +24,5 @@ config ADT7316_I2C
help
Say yes here to build I2C bus support for Analog Devices ADT7316/7/8
and ADT7516/7/9.
+
+endmenu
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index 52d1ea3..07d718e 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include "adt7316.h"
@@ -109,7 +110,7 @@ static int __devinit adt7316_i2c_probe(struct i2c_client *client,
static int __devexit adt7316_i2c_remove(struct i2c_client *client)
{
- return adt7316_remove(&client->dev);;
+ return adt7316_remove(&client->dev);
}
static const struct i2c_device_id adt7316_i2c_id[] = {
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 7097deb..8df2470 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/rtc.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -174,7 +175,6 @@
*/
struct adt7316_chip_info {
- struct iio_dev *indio_dev;
struct adt7316_bus bus;
u16 ldac_pin;
u16 int_mask; /* 0x2f */
@@ -204,7 +204,7 @@ struct adt7316_chip_info {
#define ADT7316_TEMP_INT_MASK 0x1F
#define ADT7516_AIN_INT_MASK 0xE0
#define ADT7316_TEMP_AIN_INT_MASK \
- (ADT7316_TEMP_INT_MASK | ADT7316_TEMP_INT_MASK)
+ (ADT7316_TEMP_INT_MASK)
/*
* struct adt7316_chip_info - chip specifc information
@@ -220,7 +220,7 @@ static ssize_t adt7316_show_enabled(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN));
}
@@ -252,7 +252,7 @@ static ssize_t adt7316_store_enabled(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
int enable;
if (!memcmp(buf, "1", 1))
@@ -276,7 +276,7 @@ static ssize_t adt7316_show_select_ex_temp(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
return -EPERM;
@@ -290,7 +290,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config1;
int ret;
@@ -320,7 +320,7 @@ static ssize_t adt7316_show_mode(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE)
return sprintf(buf, "single_channel\n");
@@ -334,7 +334,7 @@ static ssize_t adt7316_store_mode(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -370,7 +370,7 @@ static ssize_t adt7316_show_ad_channel(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
return -EPERM;
@@ -409,7 +409,7 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
unsigned long data = 0;
int ret;
@@ -455,7 +455,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
return -EPERM;
@@ -477,7 +477,7 @@ static ssize_t adt7316_show_disable_averaging(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
!!(chip->config2 & ADT7316_DISABLE_AVERAGING));
@@ -489,7 +489,7 @@ static ssize_t adt7316_store_disable_averaging(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -516,7 +516,7 @@ static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
!!(chip->config2 & ADT7316_EN_SMBUS_TIMEOUT));
@@ -528,7 +528,7 @@ static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -557,7 +557,7 @@ static ssize_t adt7316_store_reset(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -580,7 +580,7 @@ static ssize_t adt7316_show_powerdown(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD));
}
@@ -591,7 +591,7 @@ static ssize_t adt7316_store_powerdown(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config1;
int ret;
@@ -618,7 +618,7 @@ static ssize_t adt7316_show_fast_ad_clock(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5));
}
@@ -629,7 +629,7 @@ static ssize_t adt7316_store_fast_ad_clock(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -656,7 +656,7 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) {
if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
@@ -674,7 +674,7 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -708,7 +708,7 @@ static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
return -EPERM;
@@ -723,7 +723,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -755,7 +755,7 @@ static ssize_t adt7316_show_enable_prop_DACA(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
!!(chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA));
@@ -767,7 +767,7 @@ static ssize_t adt7316_store_enable_prop_DACA(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -794,7 +794,7 @@ static ssize_t adt7316_show_enable_prop_DACB(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
!!(chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB));
@@ -806,7 +806,7 @@ static ssize_t adt7316_store_enable_prop_DACB(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -833,7 +833,7 @@ static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "0x%x\n",
chip->dac_config & ADT7316_DA_2VREF_CH_MASK);
@@ -845,7 +845,7 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
unsigned long data = 0;
int ret;
@@ -876,7 +876,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
return sprintf(buf, "manual\n");
@@ -900,7 +900,7 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
unsigned long data;
int ret;
@@ -934,7 +934,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)
return sprintf(buf, "0 - auto at any MSB DAC writing\n"
@@ -955,7 +955,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 ldac_config;
unsigned long data;
int ret;
@@ -994,7 +994,7 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
return -EPERM;
@@ -1009,7 +1009,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
int ret;
@@ -1039,7 +1039,7 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
return -EPERM;
@@ -1054,7 +1054,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
int ret;
@@ -1084,7 +1084,7 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
return sprintf(buf, "0x%x\n",
@@ -1101,7 +1101,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 ldac_config;
unsigned long data;
int ret;
@@ -1220,7 +1220,7 @@ static ssize_t adt7316_show_VDD(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf);
}
@@ -1231,7 +1231,7 @@ static ssize_t adt7316_show_in_temp(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf);
}
@@ -1243,7 +1243,7 @@ static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf);
}
@@ -1256,7 +1256,7 @@ static ssize_t adt7316_show_AIN2(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf);
}
@@ -1267,7 +1267,7 @@ static ssize_t adt7316_show_AIN3(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf);
}
@@ -1278,7 +1278,7 @@ static ssize_t adt7316_show_AIN4(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf);
}
@@ -1330,7 +1330,7 @@ static ssize_t adt7316_show_in_temp_offset(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf);
}
@@ -1341,7 +1341,7 @@ static ssize_t adt7316_store_in_temp_offset(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, len);
}
@@ -1355,7 +1355,7 @@ static ssize_t adt7316_show_ex_temp_offset(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf);
}
@@ -1366,7 +1366,7 @@ static ssize_t adt7316_store_ex_temp_offset(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, len);
}
@@ -1380,7 +1380,7 @@ static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip,
ADT7316_IN_ANALOG_TEMP_OFFSET, buf);
@@ -1392,7 +1392,7 @@ static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip,
ADT7316_IN_ANALOG_TEMP_OFFSET, buf, len);
@@ -1407,7 +1407,7 @@ static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip,
ADT7316_EX_ANALOG_TEMP_OFFSET, buf);
@@ -1419,7 +1419,7 @@ static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip,
ADT7316_EX_ANALOG_TEMP_OFFSET, buf, len);
@@ -1504,7 +1504,7 @@ static ssize_t adt7316_show_DAC_A(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 0, buf);
}
@@ -1515,7 +1515,7 @@ static ssize_t adt7316_store_DAC_A(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 0, buf, len);
}
@@ -1528,7 +1528,7 @@ static ssize_t adt7316_show_DAC_B(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 1, buf);
}
@@ -1539,7 +1539,7 @@ static ssize_t adt7316_store_DAC_B(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 1, buf, len);
}
@@ -1552,7 +1552,7 @@ static ssize_t adt7316_show_DAC_C(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 2, buf);
}
@@ -1563,7 +1563,7 @@ static ssize_t adt7316_store_DAC_C(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 2, buf, len);
}
@@ -1576,7 +1576,7 @@ static ssize_t adt7316_show_DAC_D(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 3, buf);
}
@@ -1587,7 +1587,7 @@ static ssize_t adt7316_store_DAC_D(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 3, buf, len);
}
@@ -1600,7 +1600,7 @@ static ssize_t adt7316_show_device_id(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 id;
int ret;
@@ -1618,7 +1618,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 id;
int ret;
@@ -1637,7 +1637,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 rev;
int ret;
@@ -1655,7 +1655,7 @@ static ssize_t adt7316_show_bus_type(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 stat;
int ret;
@@ -1765,7 +1765,7 @@ static const struct attribute_group adt7516_attribute_group = {
static irqreturn_t adt7316_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
- struct adt7316_chip_info *chip = iio_dev_get_devdata(indio_dev);
+ struct adt7316_chip_info *chip = iio_priv(indio_dev);
u8 stat1, stat2;
int ret;
s64 time;
@@ -1777,44 +1777,44 @@ static irqreturn_t adt7316_event_handler(int irq, void *private)
time = iio_get_time_ns();
if (stat1 & (1 << 0))
- iio_push_event(chip->indio_dev, 0,
+ iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
time);
if (stat1 & (1 << 1))
- iio_push_event(chip->indio_dev, 0,
+ iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
time);
if (stat1 & (1 << 2))
- iio_push_event(chip->indio_dev, 0,
+ iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
time);
if (stat1 & (1 << 3))
- iio_push_event(chip->indio_dev, 0,
+ iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
time);
if (stat1 & (1 << 5))
- iio_push_event(chip->indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_IN, 1,
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_EITHER),
time);
if (stat1 & (1 << 6))
- iio_push_event(chip->indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_IN, 2,
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_EITHER),
time);
if (stat1 & (1 << 7))
- iio_push_event(chip->indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_IN, 3,
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_EITHER),
time);
@@ -1822,8 +1822,8 @@ static irqreturn_t adt7316_event_handler(int irq, void *private)
ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT2, &stat2);
if (!ret) {
if (stat2 & ADT7316_INT_MASK2_VDD)
- iio_push_event(chip->indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_IN,
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
@@ -1841,7 +1841,7 @@ static ssize_t adt7316_show_int_mask(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "0x%x\n", chip->int_mask);
}
@@ -1855,7 +1855,7 @@ static ssize_t adt7316_set_int_mask(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
unsigned long data;
int ret;
u8 mask;
@@ -1895,7 +1895,7 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 val;
int data;
int ret;
@@ -1926,7 +1926,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
long data;
u8 val;
int ret;
@@ -1965,7 +1965,7 @@ static ssize_t adt7316_show_int_enabled(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN));
}
@@ -1976,7 +1976,7 @@ static ssize_t adt7316_set_int_enabled(struct device *dev,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config1;
int ret;
@@ -2064,6 +2064,7 @@ static struct attribute *adt7316_event_attributes[] = {
static struct attribute_group adt7316_event_attribute_group = {
.attrs = adt7316_event_attributes,
+ .name = "events",
};
static struct attribute *adt7516_event_attributes[] = {
@@ -2084,13 +2085,14 @@ static struct attribute *adt7516_event_attributes[] = {
static struct attribute_group adt7516_event_attribute_group = {
.attrs = adt7516_event_attributes,
+ .name = "events",
};
#ifdef CONFIG_PM
int adt7316_disable(struct device *dev)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return _adt7316_store_enabled(chip, 0);
}
@@ -2099,7 +2101,7 @@ EXPORT_SYMBOL(adt7316_disable);
int adt7316_enable(struct device *dev)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
+ struct adt7316_chip_info *chip = iio_priv(dev_info);
return _adt7316_store_enabled(chip, 1);
}
@@ -2108,14 +2110,12 @@ EXPORT_SYMBOL(adt7316_enable);
static const struct iio_info adt7316_info = {
.attrs = &adt7316_attribute_group,
- .num_interrupt_lines = 1,
.event_attrs = &adt7316_event_attribute_group,
.driver_module = THIS_MODULE,
};
static const struct iio_info adt7516_info = {
.attrs = &adt7516_attribute_group,
- .num_interrupt_lines = 1,
.event_attrs = &adt7516_event_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -2127,16 +2127,18 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
const char *name)
{
struct adt7316_chip_info *chip;
+ struct iio_dev *indio_dev;
unsigned short *adt7316_platform_data = dev->platform_data;
int ret = 0;
- chip = kzalloc(sizeof(struct adt7316_chip_info), GFP_KERNEL);
-
- if (chip == NULL)
- return -ENOMEM;
-
+ indio_dev = iio_allocate_device(sizeof(*chip));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ chip = iio_priv(indio_dev);
/* this is only used for device removal purposes */
- dev_set_drvdata(dev, chip);
+ dev_set_drvdata(dev, indio_dev);
chip->bus = *bus;
@@ -2157,24 +2159,13 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
chip->int_mask |= ADT7516_AIN_INT_MASK;
- chip->indio_dev = iio_allocate_device(0);
- if (chip->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_chip;
- }
-
- chip->indio_dev->dev.parent = dev;
+ indio_dev->dev.parent = dev;
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
- chip->indio_dev->info = &adt7516_info;
+ indio_dev->info = &adt7516_info;
else
- chip->indio_dev->info = &adt7316_info;
- chip->indio_dev->name = name;
- chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = iio_device_register(chip->indio_dev);
- if (ret)
- goto error_free_dev;
+ indio_dev->info = &adt7316_info;
+ indio_dev->name = name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
if (chip->bus.irq > 0) {
if (adt7316_platform_data[0])
@@ -2184,10 +2175,10 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
NULL,
&adt7316_event_handler,
chip->bus.irq_flags | IRQF_ONESHOT,
- chip->indio_dev->name,
- chip->indio_dev);
+ indio_dev->name,
+ indio_dev);
if (ret)
- goto error_unreg_dev;
+ goto error_free_dev;
if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH)
chip->config1 |= ADT7316_INT_POLARITY;
@@ -2205,36 +2196,33 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
goto error_unreg_irq;
}
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_unreg_irq;
+
dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n",
- chip->indio_dev->name);
+ indio_dev->name);
return 0;
error_unreg_irq:
- free_irq(chip->bus.irq, chip->indio_dev);
-error_unreg_dev:
- iio_device_unregister(chip->indio_dev);
+ free_irq(chip->bus.irq, indio_dev);
error_free_dev:
- iio_free_device(chip->indio_dev);
-error_free_chip:
- kfree(chip);
-
+ iio_free_device(indio_dev);
+error_ret:
return ret;
}
EXPORT_SYMBOL(adt7316_probe);
int __devexit adt7316_remove(struct device *dev)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct adt7316_chip_info *chip = iio_priv(indio_dev);
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
-
- dev_set_drvdata(dev, NULL);
+ iio_device_unregister(indio_dev);
if (chip->bus.irq)
- free_irq(chip->bus.irq, chip->indio_dev);
- iio_device_unregister(chip->indio_dev);
- iio_free_device(chip->indio_dev);
- kfree(chip);
+ free_irq(chip->bus.irq, indio_dev);
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig
index d5a5556..fac8549 100644
--- a/drivers/staging/iio/dac/Kconfig
+++ b/drivers/staging/iio/dac/Kconfig
@@ -1,14 +1,35 @@
#
# DAC drivers
#
-comment "Digital to analog convertors"
+menu "Digital to analog converters"
+
+config AD5064
+ tristate "Analog Devices AD5064/64-1/44/24 DAC driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5064, AD5064-1,
+ AD5044, AD5024 Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5064.
+
+config AD5360
+ tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5360, AD5361,
+ AD5362, AD5363, AD5370, AD5371, AD5373 multi-channel
+ Digital to Analog Converters (DAC).
+
+ To compile this driver as module choose M here: the module will be called
+ ad5360.
config AD5624R_SPI
tristate "Analog Devices AD5624/44/64R DAC spi driver"
depends on SPI
help
Say yes here to build support for Analog Devices AD5624R, AD5644R and
- AD5664R convertors (DAC). This driver uses the common SPI interface.
+ AD5664R converters (DAC). This driver uses the common SPI interface.
config AD5446
tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5542A/12A DAC SPI driver"
@@ -42,6 +63,17 @@ config AD5791
To compile this driver as a module, choose M here: the
module will be called ad5791.
+config AD5686
+ tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5686R, AD5685R,
+ AD5684R, AD5791 Voltage Output Digital to
+ Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5686.
+
config MAX517
tristate "Maxim MAX517/518/519 DAC driver"
depends on I2C && EXPERIMENTAL
@@ -51,3 +83,5 @@ config MAX517
This driver can also be built as a module. If so, the module
will be called max517.
+
+endmenu
diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile
index 83196de..07b6f5e 100644
--- a/drivers/staging/iio/dac/Makefile
+++ b/drivers/staging/iio/dac/Makefile
@@ -2,8 +2,11 @@
# Makefile for industrial I/O DAC drivers
#
+obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
+obj-$(CONFIG_AD5064) += ad5064.o
obj-$(CONFIG_AD5504) += ad5504.o
obj-$(CONFIG_AD5446) += ad5446.o
obj-$(CONFIG_AD5791) += ad5791.o
+obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_MAX517) += max517.o
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index 86cb08c..e1c204d 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -16,6 +16,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -67,8 +68,8 @@ static ssize_t ad5446_write(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
int ret;
long val;
@@ -81,11 +82,11 @@ static ssize_t ad5446_write(struct device *dev,
goto error_ret;
}
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
st->cached_val = val;
st->chip_info->store_sample(st, val);
ret = spi_sync(st->spi, &st->msg);
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
error_ret:
return ret ? ret : len;
@@ -97,21 +98,21 @@ static ssize_t ad5446_show_scale(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
/* Corresponds to Vref / 2^(bits) */
unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
}
-static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
+static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
static ssize_t ad5446_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
if (sysfs_streq(buf, "1kohm_to_gnd"))
st->pwr_down_mode = MODE_PWRDWN_1k;
@@ -128,8 +129,8 @@ static ssize_t ad5446_write_powerdown_mode(struct device *dev,
static ssize_t ad5446_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
@@ -140,8 +141,8 @@ static ssize_t ad5446_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
}
@@ -150,8 +151,8 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
unsigned long readin;
int ret;
@@ -162,7 +163,7 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev,
if (readin > 1)
ret = -EINVAL;
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
st->pwr_down = readin;
if (st->pwr_down)
@@ -171,28 +172,28 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev,
st->chip_info->store_sample(st, st->cached_val);
ret = spi_sync(st->spi, &st->msg);
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
-static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | S_IWUSR,
+static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR,
ad5446_read_powerdown_mode,
ad5446_write_powerdown_mode, 0);
-static IIO_CONST_ATTR(out_powerdown_mode_available,
+static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"1kohm_to_gnd 100kohm_to_gnd three_state");
-static IIO_DEVICE_ATTR(out0_powerdown, S_IRUGO | S_IWUSR,
+static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR,
ad5446_read_dac_powerdown,
ad5446_write_dac_powerdown, 0);
static struct attribute *ad5446_attributes[] = {
- &iio_dev_attr_out0_raw.dev_attr.attr,
- &iio_dev_attr_out_scale.dev_attr.attr,
- &iio_dev_attr_out0_powerdown.dev_attr.attr,
- &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
@@ -200,16 +201,18 @@ static mode_t ad5446_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5446_state *st = iio_priv(indio_dev);
mode_t mode = attr->mode;
if (!st->chip_info->store_pwr_down &&
- (attr == &iio_dev_attr_out0_powerdown.dev_attr.attr ||
- attr == &iio_dev_attr_out_powerdown_mode.dev_attr.attr ||
+ (attr == &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr ||
+ attr == &iio_dev_attr_out_voltage_powerdown_mode.
+ dev_attr.attr ||
attr ==
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr))
+ &iio_const_attr_out_voltage_powerdown_mode_available.
+ dev_attr.attr))
mode = 0;
return mode;
@@ -342,42 +345,37 @@ static const struct iio_info ad5446_info = {
static int __devinit ad5446_probe(struct spi_device *spi)
{
struct ad5446_state *st;
+ struct iio_dev *indio_dev;
+ struct regulator *reg;
int ret, voltage_uv = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
-
- st->reg = regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
+ reg = regulator_get(&spi->dev, "vcc");
+ if (!IS_ERR(reg)) {
+ ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
- voltage_uv = regulator_get_voltage(st->reg);
+ voltage_uv = regulator_get_voltage(reg);
}
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
+ goto error_disable_reg;
+ }
+ st = iio_priv(indio_dev);
st->chip_info =
&ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- spi_set_drvdata(spi, st);
-
+ spi_set_drvdata(spi, indio_dev);
+ st->reg = reg;
st->spi = spi;
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
-
/* Estabilish that the iio_dev is a child of the spi device */
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->name = spi_get_device_id(spi)->name;
- st->indio_dev->info = &ad5446_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad5446_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default message */
@@ -404,36 +402,36 @@ static int __devinit ad5446_probe(struct spi_device *spi)
"reference voltage unspecified\n");
}
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_device;
return 0;
error_free_device:
- iio_free_device(st->indio_dev);
+ iio_free_device(indio_dev);
error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ if (!IS_ERR(reg))
+ regulator_disable(reg);
error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
- kfree(st);
-error_ret:
+ if (!IS_ERR(reg))
+ regulator_put(reg);
+
return ret;
}
static int ad5446_remove(struct spi_device *spi)
{
- struct ad5446_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad5446_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
- kfree(st);
+ iio_free_device(indio_dev);
+
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index e6ffd2b..7118d65 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -33,7 +33,6 @@
/**
* struct ad5446_state - driver instance specific data
- * @indio_dev: the industrial I/O device
* @spi: spi_device
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
@@ -45,7 +44,6 @@
*/
struct ad5446_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
const struct ad5446_chip_info *chip_info;
struct regulator *reg;
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c
index ed029cd..60dd640 100644
--- a/drivers/staging/iio/dac/ad5504.c
+++ b/drivers/staging/iio/dac/ad5504.c
@@ -7,7 +7,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -15,6 +14,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -55,7 +55,7 @@ static ssize_t ad5504_write_dac(struct device *dev,
const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long readin;
int ret;
@@ -73,7 +73,7 @@ static ssize_t ad5504_read_dac(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
u16 val;
@@ -89,7 +89,7 @@ static ssize_t ad5504_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
const char mode[][14] = {"20kohm_to_gnd", "three_state"};
@@ -101,7 +101,7 @@ static ssize_t ad5504_write_powerdown_mode(struct device *dev,
const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
int ret;
if (sysfs_streq(buf, "20kohm_to_gnd"))
@@ -119,7 +119,7 @@ static ssize_t ad5504_read_dac_powerdown(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
return sprintf(buf, "%d\n",
@@ -133,7 +133,7 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev,
long readin;
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = strict_strtol(buf, 10, &readin);
@@ -162,16 +162,16 @@ static ssize_t ad5504_show_scale(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5504_state *st = iio_priv(indio_dev);
/* Corresponds to Vref / 2^(bits) */
unsigned int scale_uv = (st->vref_mv * 1000) >> AD5505_BITS;
return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
}
-static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5504_show_scale, NULL, 0);
+static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5504_show_scale, NULL, 0);
#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \
- IIO_DEVICE_ATTR(out##_num##_raw, \
+ IIO_DEVICE_ATTR(out_voltage##_num##_raw, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5504_read_dac,
@@ -183,17 +183,16 @@ static IIO_DEV_ATTR_OUT_RW_RAW(2, ad5504_read_dac,
static IIO_DEV_ATTR_OUT_RW_RAW(3, ad5504_read_dac,
ad5504_write_dac, AD5504_ADDR_DAC3);
-static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
+static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5504_read_powerdown_mode,
ad5504_write_powerdown_mode, 0);
-static IIO_CONST_ATTR(out_powerdown_mode_available,
+static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"20kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
- IIO_DEVICE_ATTR(out##_num##_powerdown, \
+ IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
-
static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 0);
static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5504_read_dac_powerdown,
@@ -204,17 +203,17 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 3);
static struct attribute *ad5504_attributes[] = {
- &iio_dev_attr_out0_raw.dev_attr.attr,
- &iio_dev_attr_out1_raw.dev_attr.attr,
- &iio_dev_attr_out2_raw.dev_attr.attr,
- &iio_dev_attr_out3_raw.dev_attr.attr,
- &iio_dev_attr_out0_powerdown.dev_attr.attr,
- &iio_dev_attr_out1_powerdown.dev_attr.attr,
- &iio_dev_attr_out2_powerdown.dev_attr.attr,
- &iio_dev_attr_out3_powerdown.dev_attr.attr,
- &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage3_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_voltage_scale.dev_attr.attr,
NULL,
};
@@ -223,11 +222,11 @@ static const struct attribute_group ad5504_attribute_group = {
};
static struct attribute *ad5501_attributes[] = {
- &iio_dev_attr_out0_raw.dev_attr.attr,
- &iio_dev_attr_out0_powerdown.dev_attr.attr,
- &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_voltage_scale.dev_attr.attr,
NULL,
};
@@ -246,12 +245,13 @@ static struct attribute *ad5504_ev_attributes[] = {
static struct attribute_group ad5504_ev_attribute_group = {
.attrs = ad5504_ev_attributes,
+ .name = "events",
};
static irqreturn_t ad5504_event_handler(int irq, void *private)
{
- iio_push_event(private, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP,
+ iio_push_event(private,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
@@ -262,14 +262,12 @@ static irqreturn_t ad5504_event_handler(int irq, void *private)
static const struct iio_info ad5504_info = {
.attrs = &ad5504_attribute_group,
- .num_interrupt_lines = 1,
.event_attrs = &ad5504_ev_attribute_group,
.driver_module = THIS_MODULE,
};
static const struct iio_info ad5501_info = {
.attrs = &ad5501_attribute_group,
- .num_interrupt_lines = 1,
.event_attrs = &ad5504_ev_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -277,26 +275,27 @@ static const struct iio_info ad5501_info = {
static int __devinit ad5504_probe(struct spi_device *spi)
{
struct ad5504_platform_data *pdata = spi->dev.platform_data;
+ struct iio_dev *indio_dev;
struct ad5504_state *st;
+ struct regulator *reg;
int ret, voltage_uv = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
-
- spi_set_drvdata(spi, st);
-
- st->reg = regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
+ reg = regulator_get(&spi->dev, "vcc");
+ if (!IS_ERR(reg)) {
+ ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
- voltage_uv = regulator_get_voltage(st->reg);
+ voltage_uv = regulator_get_voltage(reg);
}
+ spi_set_drvdata(spi, indio_dev);
+ st = iio_priv(indio_dev);
if (voltage_uv)
st->vref_mv = voltage_uv / 1000;
else if (pdata)
@@ -304,24 +303,15 @@ static int __devinit ad5504_probe(struct spi_device *spi)
else
dev_warn(&spi->dev, "reference voltage unspecified\n");
+ st->reg = reg;
st->spi = spi;
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->name = spi_get_device_id(st->spi)->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(st->spi)->name;
if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
- st->indio_dev->info = &ad5501_info;
+ indio_dev->info = &ad5501_info;
else
- st->indio_dev->info = &ad5504_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = iio_device_register(st->indio_dev);
- if (ret)
- goto error_free_dev;
+ indio_dev->info = &ad5504_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
if (spi->irq) {
ret = request_threaded_irq(spi->irq,
@@ -329,44 +319,45 @@ static int __devinit ad5504_probe(struct spi_device *spi)
&ad5504_event_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
spi_get_device_id(st->spi)->name,
- st->indio_dev);
+ indio_dev);
if (ret)
- goto error_unreg_iio_device;
+ goto error_disable_reg;
}
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_free_irq;
+
return 0;
-error_unreg_iio_device:
- iio_device_unregister(st->indio_dev);
-error_free_dev:
- iio_free_device(st->indio_dev);
+error_free_irq:
+ free_irq(spi->irq, indio_dev);
error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ if (!IS_ERR(reg))
+ regulator_disable(reg);
error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
+ if (!IS_ERR(reg))
+ regulator_put(reg);
- kfree(st);
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
static int __devexit ad5504_remove(struct spi_device *spi)
{
- struct ad5504_state *st = spi_get_drvdata(spi);
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad5504_state *st = iio_priv(indio_dev);
+ iio_device_unregister(indio_dev);
if (spi->irq)
- free_irq(spi->irq, st->indio_dev);
-
- iio_device_unregister(st->indio_dev);
+ free_irq(spi->irq, indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
-
- kfree(st);
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h
index 13ef353..85beb1d 100644
--- a/drivers/staging/iio/dac/ad5504.h
+++ b/drivers/staging/iio/dac/ad5504.h
@@ -41,7 +41,6 @@ struct ad5504_platform_data {
/**
* struct ad5446_state - driver instance specific data
- * @indio_dev: the industrial I/O device
* @us: spi_device
* @reg: supply regulator
* @vref_mv: actual reference voltage used
@@ -50,7 +49,6 @@ struct ad5504_platform_data {
*/
struct ad5504_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
struct regulator *reg;
unsigned short vref_mv;
diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h
index c16df4e..b71c6a0 100644
--- a/drivers/staging/iio/dac/ad5624r.h
+++ b/drivers/staging/iio/dac/ad5624r.h
@@ -53,7 +53,6 @@ struct ad5624r_chip_info {
*/
struct ad5624r_state {
- struct iio_dev *indio_dev;
struct spi_device *us;
const struct ad5624r_chip_info *chip_info;
struct regulator *reg;
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index c679981..8e81fce 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -7,7 +7,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -15,6 +14,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -49,7 +49,7 @@ static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
};
static int ad5624r_spi_write(struct spi_device *spi,
- u8 cmd, u8 addr, u16 val, u8 len)
+ u8 cmd, u8 addr, u16 val, u8 shift)
{
u32 data;
u8 msg[3];
@@ -62,7 +62,7 @@ static int ad5624r_spi_write(struct spi_device *spi,
* 14-, 12-bit input code followed by 0, 2, or 4 don't care bits,
* for the AD5664R, AD5644R, and AD5624R, respectively.
*/
- data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len));
+ data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift);
msg[0] = data >> 16;
msg[1] = data >> 8;
msg[2] = data;
@@ -77,7 +77,7 @@ static ssize_t ad5624r_write_dac(struct device *dev,
long readin;
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = strict_strtol(buf, 10, &readin);
@@ -94,7 +94,7 @@ static ssize_t ad5624r_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5624r_state *st = iio_priv(indio_dev);
char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
@@ -106,7 +106,7 @@ static ssize_t ad5624r_write_powerdown_mode(struct device *dev,
const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5624r_state *st = iio_priv(indio_dev);
int ret;
if (sysfs_streq(buf, "1kohm_to_gnd"))
@@ -126,7 +126,7 @@ static ssize_t ad5624r_read_dac_powerdown(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
return sprintf(buf, "%d\n",
@@ -140,7 +140,7 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
long readin;
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = strict_strtol(buf, 10, &readin);
@@ -166,28 +166,28 @@ static ssize_t ad5624r_show_scale(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5624r_state *st = iio_priv(indio_dev);
/* Corresponds to Vref / 2^(bits) */
unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
}
-static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5624r_show_scale, NULL, 0);
+static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5624r_show_scale, NULL, 0);
static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0);
static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1);
static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2);
static IIO_DEV_ATTR_OUT_RAW(3, ad5624r_write_dac, AD5624R_ADDR_DAC3);
-static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
+static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5624r_read_powerdown_mode,
ad5624r_write_powerdown_mode, 0);
-static IIO_CONST_ATTR(out_powerdown_mode_available,
+static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"1kohm_to_gnd 100kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
- IIO_DEVICE_ATTR(out##_num##_powerdown, \
+ IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5624r_read_dac_powerdown,
@@ -200,17 +200,17 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown,
ad5624r_write_dac_powerdown, 3);
static struct attribute *ad5624r_attributes[] = {
- &iio_dev_attr_out0_raw.dev_attr.attr,
- &iio_dev_attr_out1_raw.dev_attr.attr,
- &iio_dev_attr_out2_raw.dev_attr.attr,
- &iio_dev_attr_out3_raw.dev_attr.attr,
- &iio_dev_attr_out0_powerdown.dev_attr.attr,
- &iio_dev_attr_out1_powerdown.dev_attr.attr,
- &iio_dev_attr_out2_powerdown.dev_attr.attr,
- &iio_dev_attr_out3_powerdown.dev_attr.attr,
- &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage3_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_voltage_scale.dev_attr.attr,
NULL,
};
@@ -226,15 +226,15 @@ static const struct iio_info ad5624r_info = {
static int __devinit ad5624r_probe(struct spi_device *spi)
{
struct ad5624r_state *st;
+ struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- spi_set_drvdata(spi, st);
-
+ st = iio_priv(indio_dev);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
@@ -244,6 +244,7 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
voltage_uv = regulator_get_voltage(st->reg);
}
+ spi_set_drvdata(spi, indio_dev);
st->chip_info =
&ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
@@ -253,54 +254,46 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
st->vref_mv = st->chip_info->int_vref_mv;
st->us = spi;
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->name = spi_get_device_id(spi)->name;
- st->indio_dev->info = &ad5624r_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->indio_dev);
- if (ret)
- goto error_free_dev;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad5624r_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
!!voltage_uv, 16);
if (ret)
- goto error_free_dev;
+ goto error_disable_reg;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_disable_reg;
return 0;
-error_free_dev:
- iio_free_device(st->indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
-
- kfree(st);
+ iio_free_device(indio_dev);
error_ret:
+
return ret;
}
static int __devexit ad5624r_remove(struct spi_device *spi)
{
- struct ad5624r_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->indio_dev);
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad5624r_state *st = iio_priv(indio_dev);
+ iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
-
- kfree(st);
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c
index 4eda25c..6fbca8d 100644
--- a/drivers/staging/iio/dac/ad5791.c
+++ b/drivers/staging/iio/dac/ad5791.c
@@ -7,7 +7,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -15,6 +14,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -71,54 +71,29 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
return ret;
}
-static ssize_t ad5791_write_dac(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long readin;
- int ret;
-
- ret = strict_strtol(buf, 10, &readin);
- if (ret)
- return ret;
-
- readin += (1 << (st->chip_info->bits - 1));
- readin &= AD5791_RES_MASK(st->chip_info->bits);
- readin <<= st->chip_info->left_shift;
-
- ret = ad5791_spi_write(st->spi, this_attr->address, readin);
- return ret ? ret : len;
+#define AD5791_CHAN(bits, shift) { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .address = AD5791_ADDR_DAC0, \
+ .channel = 0, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED) | \
+ (1 << IIO_CHAN_INFO_OFFSET_SHARED), \
+ .scan_type = IIO_ST('u', bits, 24, shift) \
}
-static ssize_t ad5791_read_dac(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- int val;
-
- ret = ad5791_spi_read(st->spi, this_attr->address, &val);
- if (ret)
- return ret;
-
- val &= AD5791_DAC_MASK;
- val >>= st->chip_info->left_shift;
- val -= (1 << (st->chip_info->bits - 1));
-
- return sprintf(buf, "%d\n", val);
-}
+static const struct iio_chan_spec ad5791_channels[] = {
+ [ID_AD5760] = AD5791_CHAN(16, 4),
+ [ID_AD5780] = AD5791_CHAN(18, 2),
+ [ID_AD5781] = AD5791_CHAN(18, 2),
+ [ID_AD5791] = AD5791_CHAN(20, 0)
+};
static ssize_t ad5791_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5791_state *st = iio_priv(indio_dev);
const char mode[][14] = {"6kohm_to_gnd", "three_state"};
@@ -130,7 +105,7 @@ static ssize_t ad5791_write_powerdown_mode(struct device *dev,
const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5791_state *st = iio_priv(indio_dev);
int ret;
if (sysfs_streq(buf, "6kohm_to_gnd"))
@@ -148,7 +123,7 @@ static ssize_t ad5791_read_dac_powerdown(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5791_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
}
@@ -160,7 +135,7 @@ static ssize_t ad5791_write_dac_powerdown(struct device *dev,
long readin;
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ struct ad5791_state *st = iio_priv(indio_dev);
ret = strict_strtol(buf, 10, &readin);
if (ret)
@@ -183,58 +158,24 @@ static ssize_t ad5791_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
-static ssize_t ad5791_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5791_show_scale, NULL, 0);
-
-static ssize_t ad5791_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
-}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad5791_show_name, NULL, 0);
-
-#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \
- IIO_DEVICE_ATTR(out##_num##_raw, \
- S_IRUGO | S_IWUSR, _show, _store, _addr)
-
-static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5791_read_dac,
- ad5791_write_dac, AD5791_ADDR_DAC0);
-
-static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
+static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5791_read_powerdown_mode,
ad5791_write_powerdown_mode, 0);
-static IIO_CONST_ATTR(out_powerdown_mode_available,
+static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"6kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
- IIO_DEVICE_ATTR(out##_num##_powerdown, \
+ IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown,
ad5791_write_dac_powerdown, 0);
static struct attribute *ad5791_attributes[] = {
- &iio_dev_attr_out0_raw.dev_attr.attr,
- &iio_dev_attr_out0_powerdown.dev_attr.attr,
- &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_scale.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
@@ -263,31 +204,78 @@ static int ad5780_get_lin_comp(unsigned int span)
else
return AD5780_LINCOMP_10_20;
}
-
static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
[ID_AD5760] = {
- .bits = 16,
- .left_shift = 4,
.get_lin_comp = ad5780_get_lin_comp,
},
[ID_AD5780] = {
- .bits = 18,
- .left_shift = 2,
.get_lin_comp = ad5780_get_lin_comp,
},
[ID_AD5781] = {
- .bits = 18,
- .left_shift = 2,
.get_lin_comp = ad5791_get_lin_comp,
},
[ID_AD5791] = {
- .bits = 20,
- .left_shift = 0,
.get_lin_comp = ad5791_get_lin_comp,
},
};
+static int ad5791_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad5791_state *st = iio_priv(indio_dev);
+ u64 val64;
+ int ret;
+
+ switch (m) {
+ case 0:
+ ret = ad5791_spi_read(st->spi, chan->address, val);
+ if (ret)
+ return ret;
+ *val &= AD5791_DAC_MASK;
+ *val >>= chan->scan_type.shift;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ *val = 0;
+ *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case (1 << IIO_CHAN_INFO_OFFSET_SHARED):
+ val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
+ do_div(val64, st->vref_mv);
+ *val = -val64;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+
+};
+
+
+static int ad5791_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct ad5791_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case 0:
+ val &= AD5791_RES_MASK(chan->scan_type.realbits);
+ val <<= chan->scan_type.shift;
+
+ return ad5791_spi_write(st->spi, chan->address, val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct iio_info ad5791_info = {
+ .read_raw = &ad5791_read_raw,
+ .write_raw = &ad5791_write_raw,
.attrs = &ad5791_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -295,17 +283,16 @@ static const struct iio_info ad5791_info = {
static int __devinit ad5791_probe(struct spi_device *spi)
{
struct ad5791_platform_data *pdata = spi->dev.platform_data;
+ struct iio_dev *indio_dev;
struct ad5791_state *st;
int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
-
- spi_set_drvdata(spi, st);
-
+ st = iio_priv(indio_dev);
st->reg_vdd = regulator_get(&spi->dev, "vdd");
if (!IS_ERR(st->reg_vdd)) {
ret = regulator_enable(st->reg_vdd);
@@ -324,19 +311,25 @@ static int __devinit ad5791_probe(struct spi_device *spi)
neg_voltage_uv = regulator_get_voltage(st->reg_vss);
}
- if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd))
- st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000;
- else if (pdata)
- st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv;
- else
+ st->pwr_down = true;
+ st->spi = spi;
+
+ if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
+ st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
+ st->vref_neg_mv = neg_voltage_uv / 1000;
+ } else if (pdata) {
+ st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv;
+ st->vref_neg_mv = pdata->vref_neg_mv;
+ } else {
dev_warn(&spi->dev, "reference voltage unspecified\n");
+ }
ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
if (ret)
goto error_disable_reg_neg;
- st->chip_info =
- &ad5791_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+ st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi)
+ ->driver_data];
st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
@@ -348,28 +341,20 @@ static int __devinit ad5791_probe(struct spi_device *spi)
if (ret)
goto error_disable_reg_neg;
- st->pwr_down = true;
-
- st->spi = spi;
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg_neg;
- }
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->info = &ad5791_info;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = iio_device_register(st->indio_dev);
+ spi_set_drvdata(spi, indio_dev);
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &ad5791_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels
+ = &ad5791_channels[spi_get_device_id(spi)->driver_data];
+ indio_dev->num_channels = 1;
+ indio_dev->name = spi_get_device_id(st->spi)->name;
+ ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ goto error_disable_reg_neg;
return 0;
-error_free_dev:
- iio_free_device(st->indio_dev);
-
error_disable_reg_neg:
if (!IS_ERR(st->reg_vss))
regulator_disable(st->reg_vss);
@@ -382,18 +367,18 @@ error_put_reg_neg:
error_put_reg_pos:
if (!IS_ERR(st->reg_vdd))
regulator_put(st->reg_vdd);
-
- kfree(st);
+ iio_free_device(indio_dev);
error_ret:
+
return ret;
}
static int __devexit ad5791_remove(struct spi_device *spi)
{
- struct ad5791_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->indio_dev);
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad5791_state *st = iio_priv(indio_dev);
+ iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg_vdd)) {
regulator_disable(st->reg_vdd);
regulator_put(st->reg_vdd);
@@ -403,8 +388,7 @@ static int __devexit ad5791_remove(struct spi_device *spi)
regulator_disable(st->reg_vss);
regulator_put(st->reg_vss);
}
-
- kfree(st);
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h
index f09ad9a..fd7edbd 100644
--- a/drivers/staging/iio/dac/ad5791.h
+++ b/drivers/staging/iio/dac/ad5791.h
@@ -68,35 +68,31 @@ struct ad5791_platform_data {
/**
* struct ad5791_chip_info - chip specific information
- * @bits: accuracy of the DAC in bits
- * @left_shift: number of bits the datum must be shifted
* @get_lin_comp: function pointer to the device specific function
*/
struct ad5791_chip_info {
- u8 bits;
- u8 left_shift;
int (*get_lin_comp) (unsigned int span);
};
/**
* struct ad5791_state - driver instance specific data
- * @indio_dev: the industrial I/O device
* @us: spi_device
* @reg_vdd: positive supply regulator
* @reg_vss: negative supply regulator
* @chip_info: chip model specific constants
* @vref_mv: actual reference voltage used
+ * @vref_neg_mv: voltage of the negative supply
* @pwr_down_mode current power down mode
*/
struct ad5791_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
struct regulator *reg_vdd;
struct regulator *reg_vss;
const struct ad5791_chip_info *chip_info;
unsigned short vref_mv;
+ unsigned int vref_neg_mv;
unsigned ctrl;
unsigned pwr_down_mode;
bool pwr_down;
diff --git a/drivers/staging/iio/dac/dac.h b/drivers/staging/iio/dac/dac.h
index 1d82f35..0754d71 100644
--- a/drivers/staging/iio/dac/dac.h
+++ b/drivers/staging/iio/dac/dac.h
@@ -3,4 +3,4 @@
*/
#define IIO_DEV_ATTR_OUT_RAW(_num, _store, _addr) \
- IIO_DEVICE_ATTR(out##_num##_raw, S_IWUSR, NULL, _store, _addr)
+ IIO_DEVICE_ATTR(out_voltage##_num##_raw, S_IWUSR, NULL, _store, _addr)
diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c
index 2fe34d2..adfbd20 100644
--- a/drivers/staging/iio/dac/max517.c
+++ b/drivers/staging/iio/dac/max517.c
@@ -26,6 +26,7 @@
#include <linux/err.h>
#include "../iio.h"
+#include "../sysfs.h"
#include "dac.h"
#include "max517.h"
@@ -58,8 +59,8 @@ static ssize_t max517_set_value(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count, int channel)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max517_data *data = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct max517_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
u8 outbuf[4]; /* 1x or 2x command + value */
int outbuf_size = 0;
@@ -119,15 +120,16 @@ static ssize_t max517_set_value_both(struct device *dev,
{
return max517_set_value(dev, attr, buf, count, 3);
}
-static IIO_DEVICE_ATTR_NAMED(out1and2_raw, out1&2_raw, S_IWUSR, NULL,
- max517_set_value_both, -1);
+static IIO_DEVICE_ATTR_NAMED(out_voltage1and2_raw,
+ out_voltage1&2_raw, S_IWUSR, NULL,
+ max517_set_value_both, -1);
static ssize_t max517_show_scale(struct device *dev,
struct device_attribute *attr,
char *buf, int channel)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max517_data *data = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct max517_data *data = iio_priv(indio_dev);
/* Corresponds to Vref / 2^(bits) */
unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8;
@@ -140,7 +142,8 @@ static ssize_t max517_show_scale1(struct device *dev,
{
return max517_show_scale(dev, attr, buf, 1);
}
-static IIO_DEVICE_ATTR(out1_scale, S_IRUGO, max517_show_scale1, NULL, 0);
+static IIO_DEVICE_ATTR(out_voltage1_scale, S_IRUGO,
+ max517_show_scale1, NULL, 0);
static ssize_t max517_show_scale2(struct device *dev,
struct device_attribute *attr,
@@ -148,12 +151,13 @@ static ssize_t max517_show_scale2(struct device *dev,
{
return max517_show_scale(dev, attr, buf, 2);
}
-static IIO_DEVICE_ATTR(out2_scale, S_IRUGO, max517_show_scale2, NULL, 0);
+static IIO_DEVICE_ATTR(out_voltage2_scale, S_IRUGO,
+ max517_show_scale2, NULL, 0);
/* On MAX517 variant, we have one output */
static struct attribute *max517_attributes[] = {
- &iio_dev_attr_out1_raw.dev_attr.attr,
- &iio_dev_attr_out1_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_scale.dev_attr.attr,
NULL
};
@@ -163,11 +167,11 @@ static struct attribute_group max517_attribute_group = {
/* On MAX518 and MAX519 variant, we have two outputs */
static struct attribute *max518_attributes[] = {
- &iio_dev_attr_out1_raw.dev_attr.attr,
- &iio_dev_attr_out1_scale.dev_attr.attr,
- &iio_dev_attr_out2_raw.dev_attr.attr,
- &iio_dev_attr_out2_scale.dev_attr.attr,
- &iio_dev_attr_out1and2_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_raw.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_scale.dev_attr.attr,
+ &iio_dev_attr_out_voltage1and2_raw.dev_attr.attr,
NULL
};
@@ -203,35 +207,28 @@ static int max517_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max517_data *data;
+ struct iio_dev *indio_dev;
struct max517_platform_data *platform_data = client->dev.platform_data;
int err;
- data = kzalloc(sizeof(struct max517_data), GFP_KERNEL);
- if (!data) {
+ indio_dev = iio_allocate_device(sizeof(*data));
+ if (indio_dev == NULL) {
err = -ENOMEM;
goto exit;
}
-
- i2c_set_clientdata(client, data);
-
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
data->client = client;
- data->indio_dev = iio_allocate_device(0);
- if (data->indio_dev == NULL) {
- err = -ENOMEM;
- goto exit_free_data;
- }
-
/* establish that the iio_dev is a child of the i2c device */
- data->indio_dev->dev.parent = &client->dev;
+ indio_dev->dev.parent = &client->dev;
/* reduced attribute set for MAX517 */
if (id->driver_data == ID_MAX517)
- data->indio_dev->info = &max517_info;
+ indio_dev->info = &max517_info;
else
- data->indio_dev->info = &max518_info;
- data->indio_dev->dev_data = (void *)(data);
- data->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &max518_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
/*
* Reference voltage on MAX518 and default is 5V, else take vref_mv
@@ -244,7 +241,7 @@ static int max517_probe(struct i2c_client *client,
data->vref_mv[1] = platform_data->vref_mv[1];
}
- err = iio_device_register(data->indio_dev);
+ err = iio_device_register(indio_dev);
if (err)
goto exit_free_device;
@@ -253,19 +250,14 @@ static int max517_probe(struct i2c_client *client,
return 0;
exit_free_device:
- iio_free_device(data->indio_dev);
-exit_free_data:
- kfree(data);
+ iio_free_device(indio_dev);
exit:
return err;
}
static int max517_remove(struct i2c_client *client)
{
- struct max517_data *data = i2c_get_clientdata(client);
-
- iio_free_device(data->indio_dev);
- kfree(data);
+ iio_free_device(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/dds/Kconfig
index e07431d..93b7141 100644
--- a/drivers/staging/iio/dds/Kconfig
+++ b/drivers/staging/iio/dds/Kconfig
@@ -1,7 +1,7 @@
#
# Direct Digital Synthesis drivers
#
-comment "Direct Digital Synthesis"
+menu "Direct Digital Synthesis"
config AD5930
tristate "Analog Devices ad5930/5932 driver"
@@ -57,3 +57,5 @@ config AD9951
help
Say yes here to build support for Analog Devices DDS chip
ad9951, provides direct access via sysfs.
+
+endmenu
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c
index 490c363..f5e368b 100644
--- a/drivers/staging/iio/dds/ad5930.c
+++ b/drivers/staging/iio/dds/ad5930.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -35,7 +36,6 @@ struct ad5903_config {
struct ad5930_state {
struct mutex lock;
- struct iio_dev *idev;
struct spi_device *sdev;
};
@@ -49,7 +49,7 @@ static ssize_t ad5930_set_parameter(struct device *dev,
int ret;
struct ad5903_config *config = (struct ad5903_config *)buf;
struct iio_dev *idev = dev_get_drvdata(dev);
- struct ad5930_state *st = idev->dev_data;
+ struct ad5930_state *st = iio_priv(idev);
config->control = (config->control & ~value_mask);
config->incnum = (config->control & ~value_mask) | (1 << addr_shift);
@@ -83,42 +83,35 @@ static struct attribute *ad5930_attributes[] = {
};
static const struct attribute_group ad5930_attribute_group = {
- .name = DRV_NAME,
.attrs = ad5930_attributes,
};
static const struct iio_info ad5930_info = {
.attrs = &ad5930_attribute_group,
-
.driver_module = THIS_MODULE,
};
static int __devinit ad5930_probe(struct spi_device *spi)
{
struct ad5930_state *st;
+ struct iio_dev *idev;
int ret = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ idev = iio_allocate_device(sizeof(*st));
+ if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, idev);
+ st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
+ idev->dev.parent = &spi->dev;
+ idev->info = &ad5930_info;
+ idev->modes = INDIO_DIRECT_MODE;
- st->idev = iio_allocate_device(0);
- if (st->idev == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->idev->dev.parent = &spi->dev;
- st->idev->dev_data = (void *)(st);
- st->idev->info = &ad5930_info;
- st->idev->modes = INDIO_DIRECT_MODE;
-
- ret = iio_device_register(st->idev);
+ ret = iio_device_register(idev);
if (ret)
goto error_free_dev;
spi->max_speed_hz = 2000000;
@@ -129,19 +122,15 @@ static int __devinit ad5930_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(st->idev);
-error_free_st:
- kfree(st);
+ iio_free_device(idev);
error_ret:
return ret;
}
static int __devexit ad5930_remove(struct spi_device *spi)
{
- struct ad5930_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->idev);
- kfree(st);
+ iio_device_unregister(spi_get_drvdata(spi));
+ iio_free_device(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c
index e8fe142..9b4ff60 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/dds/ad9832.c
@@ -13,6 +13,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <asm/div64.h>
#include "../iio.h"
@@ -52,7 +53,7 @@ static int ad9832_write_frequency(struct ad9832_state *st,
((addr - 3) << ADD_SHIFT) |
((regval >> 0) & 0xFF));
- return spi_sync(st->spi, &st->freq_msg);;
+ return spi_sync(st->spi, &st->freq_msg);
}
static int ad9832_write_phase(struct ad9832_state *st,
@@ -76,8 +77,8 @@ static ssize_t ad9832_write(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9832_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad9832_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
long val;
@@ -86,7 +87,7 @@ static ssize_t ad9832_write(struct device *dev,
if (ret)
goto error_ret;
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
switch (this_attr->address) {
case AD9832_FREQ0HM:
case AD9832_FREQ1HM:
@@ -147,7 +148,7 @@ static ssize_t ad9832_write(struct device *dev,
default:
ret = -ENODEV;
}
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
error_ret:
return ret ? ret : len;
@@ -203,7 +204,9 @@ static const struct iio_info ad9832_info = {
static int __devinit ad9832_probe(struct spi_device *spi)
{
struct ad9832_platform_data *pdata = spi->dev.platform_data;
+ struct iio_dev *indio_dev;
struct ad9832_state *st;
+ struct regulator *reg;
int ret;
if (!pdata) {
@@ -211,35 +214,28 @@ static int __devinit ad9832_probe(struct spi_device *spi)
return -ENODEV;
}
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
-
- st->reg = regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
+ reg = regulator_get(&spi->dev, "vcc");
+ if (!IS_ERR(reg)) {
+ ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
}
- st->mclk = pdata->mclk;
-
- spi_set_drvdata(spi, st);
- st->spi = spi;
-
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
+ spi_set_drvdata(spi, indio_dev);
+ st = iio_priv(indio_dev);
+ st->reg = reg;
+ st->mclk = pdata->mclk;
+ st->spi = spi;
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->name = spi_get_device_id(spi)->name;
- st->indio_dev->info = &ad9832_info;
- st->indio_dev->dev_data = (void *) st;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad9832_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default messages */
@@ -310,35 +306,36 @@ static int __devinit ad9832_probe(struct spi_device *spi)
if (ret)
goto error_free_device;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_device;
return 0;
error_free_device:
- iio_free_device(st->indio_dev);
+ iio_free_device(indio_dev);
error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ if (!IS_ERR(reg))
+ regulator_disable(reg);
error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
- kfree(st);
-error_ret:
+ if (!IS_ERR(reg))
+ regulator_put(reg);
+
return ret;
}
static int __devexit ad9832_remove(struct spi_device *spi)
{
- struct ad9832_state *st = spi_get_drvdata(spi);
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad9832_state *st = iio_priv(indio_dev);
- iio_device_unregister(st->indio_dev);
+ iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
- kfree(st);
+ iio_free_device(indio_dev);
+
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/dds/ad9832.h
index 5d47454..c5b701f 100644
--- a/drivers/staging/iio/dds/ad9832.h
+++ b/drivers/staging/iio/dds/ad9832.h
@@ -57,7 +57,6 @@
/**
* struct ad9832_state - driver instance specific data
- * @indio_dev: the industrial I/O device
* @spi: spi_device
* @reg: supply regulator
* @mclk: external master clock
@@ -76,7 +75,6 @@
*/
struct ad9832_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
struct regulator *reg;
unsigned long mclk;
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c
index 0ebe8d5..c468f69 100644
--- a/drivers/staging/iio/dds/ad9834.c
+++ b/drivers/staging/iio/dds/ad9834.c
@@ -16,6 +16,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <asm/div64.h>
#include "../iio.h"
@@ -65,8 +66,8 @@ static ssize_t ad9834_write(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9834_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad9834_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
long val;
@@ -75,7 +76,7 @@ static ssize_t ad9834_write(struct device *dev,
if (ret)
goto error_ret;
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
switch (this_attr->address) {
case AD9834_REG_FREQ0:
case AD9834_REG_FREQ1:
@@ -133,7 +134,7 @@ static ssize_t ad9834_write(struct device *dev,
default:
ret = -ENODEV;
}
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
error_ret:
return ret ? ret : len;
@@ -144,13 +145,13 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9834_state *st = dev_info->dev_data;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad9834_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret = 0;
bool is_ad9833_7 = (st->devid == ID_AD9833) || (st->devid == ID_AD9837);
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
switch (this_attr->address) {
case 0:
@@ -193,7 +194,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
ret = spi_sync(st->spi, &st->msg);
}
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
@@ -202,8 +203,8 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9834_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad9834_state *st = iio_priv(indio_dev);
char *str;
if ((st->devid == ID_AD9833) || (st->devid == ID_AD9837))
@@ -224,8 +225,8 @@ static ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9834_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad9834_state *st = iio_priv(indio_dev);
char *str;
if (st->control & AD9834_MODE)
@@ -284,8 +285,8 @@ static mode_t ad9834_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9834_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad9834_state *st = iio_priv(indio_dev);
mode_t mode = attr->mode;
@@ -314,6 +315,8 @@ static int __devinit ad9834_probe(struct spi_device *spi)
{
struct ad9834_platform_data *pdata = spi->dev.platform_data;
struct ad9834_state *st;
+ struct iio_dev *indio_dev;
+ struct regulator *reg;
int ret;
if (!pdata) {
@@ -321,37 +324,28 @@ static int __devinit ad9834_probe(struct spi_device *spi)
return -ENODEV;
}
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
-
- st->reg = regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
+ reg = regulator_get(&spi->dev, "vcc");
+ if (!IS_ERR(reg)) {
+ ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
}
- st->mclk = pdata->mclk;
-
- spi_set_drvdata(spi, st);
-
- st->spi = spi;
- st->devid = spi_get_device_id(spi)->driver_data;
-
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
-
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->name = spi_get_device_id(spi)->name;
- st->indio_dev->info = &ad9834_info;
- st->indio_dev->dev_data = (void *) st;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ spi_set_drvdata(spi, indio_dev);
+ st = iio_priv(indio_dev);
+ st->mclk = pdata->mclk;
+ st->spi = spi;
+ st->devid = spi_get_device_id(spi)->driver_data;
+ st->reg = reg;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad9834_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default messages */
@@ -402,35 +396,35 @@ static int __devinit ad9834_probe(struct spi_device *spi)
if (ret)
goto error_free_device;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_device;
return 0;
error_free_device:
- iio_free_device(st->indio_dev);
+ iio_free_device(indio_dev);
error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ if (!IS_ERR(reg))
+ regulator_disable(reg);
error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
- kfree(st);
-error_ret:
+ if (!IS_ERR(reg))
+ regulator_put(reg);
return ret;
}
static int __devexit ad9834_remove(struct spi_device *spi)
{
- struct ad9834_state *st = spi_get_drvdata(spi);
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad9834_state *st = iio_priv(indio_dev);
- iio_device_unregister(st->indio_dev);
+ iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
- kfree(st);
+ iio_free_device(indio_dev);
+
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/dds/ad9834.h
index 2abd635..ed5ed8d 100644
--- a/drivers/staging/iio/dds/ad9834.h
+++ b/drivers/staging/iio/dds/ad9834.h
@@ -38,7 +38,6 @@
/**
* struct ad9834_state - driver instance specific data
- * @indio_dev: the industrial I/O device
* @spi: spi_device
* @reg: supply regulator
* @mclk: external master clock
@@ -52,7 +51,6 @@
*/
struct ad9834_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
struct regulator *reg;
unsigned int mclk;
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c
index b580d85..a14771b 100644
--- a/drivers/staging/iio/dds/ad9850.c
+++ b/drivers/staging/iio/dds/ad9850.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -30,7 +31,6 @@ struct ad9850_config {
struct ad9850_state {
struct mutex lock;
- struct iio_dev *idev;
struct spi_device *sdev;
};
@@ -44,7 +44,7 @@ static ssize_t ad9850_set_parameter(struct device *dev,
int ret;
struct ad9850_config *config = (struct ad9850_config *)buf;
struct iio_dev *idev = dev_get_drvdata(dev);
- struct ad9850_state *st = idev->dev_data;
+ struct ad9850_state *st = iio_priv(idev);
xfer.len = len;
xfer.tx_buf = config;
@@ -69,7 +69,6 @@ static struct attribute *ad9850_attributes[] = {
};
static const struct attribute_group ad9850_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9850_attributes,
};
@@ -81,30 +80,24 @@ static const struct iio_info ad9850_info = {
static int __devinit ad9850_probe(struct spi_device *spi)
{
struct ad9850_state *st;
+ struct iio_dev *idev;
int ret = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ idev = iio_allocate_device(sizeof(*st));
+ if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- spi_set_drvdata(spi, st);
-
+ spi_set_drvdata(spi, idev);
+ st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device(0);
- if (st->idev == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->idev->dev.parent = &spi->dev;
-
- st->idev->info = &ad9850_info;
- st->idev->dev_data = (void *)(st);
- st->idev->modes = INDIO_DIRECT_MODE;
+ idev->dev.parent = &spi->dev;
+ idev->info = &ad9850_info;
+ idev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->idev);
+ ret = iio_device_register(idev);
if (ret)
goto error_free_dev;
spi->max_speed_hz = 2000000;
@@ -115,19 +108,15 @@ static int __devinit ad9850_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(st->idev);
-error_free_st:
- kfree(st);
+ iio_free_device(idev);
error_ret:
return ret;
}
static int __devexit ad9850_remove(struct spi_device *spi)
{
- struct ad9850_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->idev);
- kfree(st);
+ iio_device_unregister(spi_get_drvdata(spi));
+ iio_free_device(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c
index 08020f9..cfceaa6 100644
--- a/drivers/staging/iio/dds/ad9852.c
+++ b/drivers/staging/iio/dds/ad9852.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -58,7 +59,6 @@ struct ad9852_config {
struct ad9852_state {
struct mutex lock;
- struct iio_dev *idev;
struct spi_device *sdev;
};
@@ -72,7 +72,7 @@ static ssize_t ad9852_set_parameter(struct device *dev,
int ret;
struct ad9852_config *config = (struct ad9852_config *)buf;
struct iio_dev *idev = dev_get_drvdata(dev);
- struct ad9852_state *st = idev->dev_data;
+ struct ad9852_state *st = iio_priv(idev);
xfer.len = 3;
xfer.tx_buf = &config->phajst0[0];
@@ -218,7 +218,6 @@ static struct attribute *ad9852_attributes[] = {
};
static const struct attribute_group ad9852_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9852_attributes,
};
@@ -230,30 +229,24 @@ static const struct iio_info ad9852_info = {
static int __devinit ad9852_probe(struct spi_device *spi)
{
struct ad9852_state *st;
+ struct iio_dev *idev;
int ret = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ idev = iio_allocate_device(sizeof(*st));
+ if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- spi_set_drvdata(spi, st);
-
+ st = iio_priv(idev);
+ spi_set_drvdata(spi, idev);
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device(0);
- if (st->idev == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->idev->dev.parent = &spi->dev;
+ idev->dev.parent = &spi->dev;
+ idev->info = &ad9852_info;
+ idev->modes = INDIO_DIRECT_MODE;
- st->idev->info = &ad9852_info;
- st->idev->dev_data = (void *)(st);
- st->idev->modes = INDIO_DIRECT_MODE;
-
- ret = iio_device_register(st->idev);
+ ret = iio_device_register(idev);
if (ret)
goto error_free_dev;
spi->max_speed_hz = 2000000;
@@ -261,22 +254,20 @@ static int __devinit ad9852_probe(struct spi_device *spi)
spi->bits_per_word = 8;
spi_setup(spi);
ad9852_init(st);
+
return 0;
error_free_dev:
- iio_free_device(st->idev);
-error_free_st:
- kfree(st);
+ iio_free_device(idev);
+
error_ret:
return ret;
}
static int __devexit ad9852_remove(struct spi_device *spi)
{
- struct ad9852_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->idev);
- kfree(st);
+ iio_device_unregister(spi_get_drvdata(spi));
+ iio_free_device(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c
index 97d75d7..da83d2b 100644
--- a/drivers/staging/iio/dds/ad9910.c
+++ b/drivers/staging/iio/dds/ad9910.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -110,7 +111,6 @@ struct ad9910_config {
struct ad9910_state {
struct mutex lock;
- struct iio_dev *idev;
struct spi_device *sdev;
};
@@ -124,7 +124,7 @@ static ssize_t ad9910_set_parameter(struct device *dev,
int ret;
struct ad9910_config *config = (struct ad9910_config *)buf;
struct iio_dev *idev = dev_get_drvdata(dev);
- struct ad9910_state *st = idev->dev_data;
+ struct ad9910_state *st = iio_priv(idev);
xfer.len = 5;
xfer.tx_buf = &config->auxdac[0];
@@ -353,7 +353,6 @@ static struct attribute *ad9910_attributes[] = {
};
static const struct attribute_group ad9910_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9910_attributes,
};
@@ -365,30 +364,24 @@ static const struct iio_info ad9910_info = {
static int __devinit ad9910_probe(struct spi_device *spi)
{
struct ad9910_state *st;
+ struct iio_dev *idev;
int ret = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ idev = iio_allocate_device(sizeof(*st));
+ if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- spi_set_drvdata(spi, st);
-
+ spi_set_drvdata(spi, idev);
+ st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device(0);
- if (st->idev == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->idev->dev.parent = &spi->dev;
-
- st->idev->info = &ad9910_info;
- st->idev->dev_data = (void *)(st);
- st->idev->modes = INDIO_DIRECT_MODE;
+ idev->dev.parent = &spi->dev;
+ idev->info = &ad9910_info;
+ idev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->idev);
+ ret = iio_device_register(idev);
if (ret)
goto error_free_dev;
spi->max_speed_hz = 2000000;
@@ -399,19 +392,15 @@ static int __devinit ad9910_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(st->idev);
-error_free_st:
- kfree(st);
+ iio_free_device(idev);
error_ret:
return ret;
}
static int __devexit ad9910_remove(struct spi_device *spi)
{
- struct ad9910_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->idev);
- kfree(st);
+ iio_device_unregister(spi_get_drvdata(spi));
+ iio_free_device(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c
index d4dfcd4..20c1825 100644
--- a/drivers/staging/iio/dds/ad9951.c
+++ b/drivers/staging/iio/dds/ad9951.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -51,7 +52,6 @@ struct ad9951_config {
struct ad9951_state {
struct mutex lock;
- struct iio_dev *idev;
struct spi_device *sdev;
};
@@ -65,7 +65,7 @@ static ssize_t ad9951_set_parameter(struct device *dev,
int ret;
struct ad9951_config *config = (struct ad9951_config *)buf;
struct iio_dev *idev = dev_get_drvdata(dev);
- struct ad9951_state *st = idev->dev_data;
+ struct ad9951_state *st = iio_priv(idev);
xfer.len = 3;
xfer.tx_buf = &config->asf[0];
@@ -162,7 +162,6 @@ static struct attribute *ad9951_attributes[] = {
};
static const struct attribute_group ad9951_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9951_attributes,
};
@@ -174,30 +173,25 @@ static const struct iio_info ad9951_info = {
static int __devinit ad9951_probe(struct spi_device *spi)
{
struct ad9951_state *st;
+ struct iio_dev *idev;
int ret = 0;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ idev = iio_allocate_device(sizeof(*st));
+ if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- spi_set_drvdata(spi, st);
-
+ spi_set_drvdata(spi, idev);
+ st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device(0);
- if (st->idev == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->idev->dev.parent = &spi->dev;
+ idev->dev.parent = &spi->dev;
- st->idev->info = &ad9951_info;
- st->idev->dev_data = (void *)(st);
- st->idev->modes = INDIO_DIRECT_MODE;
+ idev->info = &ad9951_info;
+ idev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->idev);
+ ret = iio_device_register(idev);
if (ret)
goto error_free_dev;
spi->max_speed_hz = 2000000;
@@ -208,19 +202,16 @@ static int __devinit ad9951_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(st->idev);
-error_free_st:
- kfree(st);
+ iio_free_device(idev);
+
error_ret:
return ret;
}
static int __devexit ad9951_remove(struct spi_device *spi)
{
- struct ad9951_state *st = spi_get_drvdata(spi);
-
- iio_device_unregister(st->idev);
- kfree(st);
+ iio_device_unregister(spi_get_drvdata(spi));
+ iio_free_device(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index e0e0144..2c2f47d 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -1,15 +1,17 @@
#
# IIO imu drivers configuration
#
-comment "Inertial measurement units"
+menu "Inertial measurement units"
config ADIS16400
tristate "Analog Devices ADIS16400 and similar IMU SPI driver"
depends on SPI
- select IIO_SW_RING if IIO_RING_BUFFER
- select IIO_TRIGGER if IIO_RING_BUFFER
+ select IIO_SW_RING if IIO_BUFFER
+ select IIO_TRIGGER if IIO_BUFFER
help
- Say yes here to build support for Analog Devices adis16300, adis16350,
- adis16354, adis16355, adis16360, adis16362, adis16364, adis16365,
- adis16400 and adis16405 triaxial inertial sensors (adis16400 series
- also have magnetometers).
+ Say yes here to build support for Analog Devices adis16300, adis16344,
+ adis16350, adis16354, adis16355, adis16360, adis16362, adis16364,
+ adis16365, adis16400 and adis16405 triaxial inertial sensors
+ (adis16400 series also have magnetometers).
+
+endmenu
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
index d46a691..3400a13 100644
--- a/drivers/staging/iio/imu/Makefile
+++ b/drivers/staging/iio/imu/Makefile
@@ -3,5 +3,5 @@
#
adis16400-y := adis16400_core.o
-adis16400-$(CONFIG_IIO_RING_BUFFER) += adis16400_ring.o adis16400_trigger.o
+adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
obj-$(CONFIG_ADIS16400) += adis16400.o
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index e87715b..f3546ee 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -41,6 +41,9 @@
#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
+#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */
+#define ADIS16300_ROLL_OUT 0x12 /* Y axis inclinometer output measurement */
+
/* Calibration parameters */
#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
@@ -181,7 +184,7 @@ int adis16400_set_irq(struct iio_dev *indio_dev, bool enable);
#define ADIS16300_SCAN_INCLI_X 12
#define ADIS16300_SCAN_INCLI_Y 13
-#ifdef CONFIG_IIO_RING_BUFFER
+#ifdef CONFIG_IIO_BUFFER
void adis16400_remove_trigger(struct iio_dev *indio_dev);
int adis16400_probe_trigger(struct iio_dev *indio_dev);
@@ -193,7 +196,7 @@ ssize_t adis16400_read_data_from_ring(struct device *dev,
int adis16400_configure_ring(struct iio_dev *indio_dev);
void adis16400_unconfigure_ring(struct iio_dev *indio_dev);
-#else /* CONFIG_IIO_RING_BUFFER */
+#else /* CONFIG_IIO_BUFFER */
static inline void adis16400_remove_trigger(struct iio_dev *indio_dev)
{
@@ -221,5 +224,5 @@ static inline void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
{
}
-#endif /* CONFIG_IIO_RING_BUFFER */
+#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16400_H_ */
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index fe89802..57cb92f 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -16,7 +16,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -25,21 +24,17 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "../ring_generic.h"
-#include "../accel/accel.h"
-#include "../adc/adc.h"
-#include "../gyro/gyro.h"
-#include "../magnetometer/magnet.h"
-
+#include "../buffer_generic.h"
#include "adis16400.h"
-#define DRIVER_NAME "adis16400"
-
enum adis16400_chip_variant {
ADIS16300,
+ ADIS16334,
ADIS16350,
ADIS16360,
ADIS16362,
@@ -48,19 +43,12 @@ enum adis16400_chip_variant {
ADIS16400,
};
-static int adis16400_check_status(struct iio_dev *indio_dev);
-
-/* At the moment the spi framework doesn't allow global setting of cs_change.
- * It's in the likely to be added comment at the top of spi.h.
- * This means that use cannot be made of spi_write etc.
- */
-
/**
* adis16400_spi_write_reg_8() - write single byte to a register
* @dev: device associated with child of actual device (iio_dev or iio_trig)
* @reg_address: the address of the register to be written
* @val: the value to write
- **/
+ */
static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev,
u8 reg_address,
u8 val)
@@ -84,7 +72,10 @@ static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev,
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: value to be written
- **/
+ *
+ * At the moment the spi framework doesn't allow global setting of cs_change.
+ * This means that use cannot be made of spi_write.
+ */
static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
u16 value)
@@ -126,6 +117,9 @@ static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev,
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: somewhere to pass back the value read
+ *
+ * At the moment the spi framework doesn't allow global setting of cs_change.
+ * This means that use cannot be made of spi_read.
**/
static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
@@ -150,8 +144,6 @@ static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev,
mutex_lock(&st->buf_lock);
st->tx[0] = ADIS16400_READ_REG(lower_reg_address);
st->tx[1] = 0;
- st->tx[2] = 0;
- st->tx[3] = 0;
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
@@ -240,23 +232,26 @@ static ssize_t adis16400_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ bool val;
+ int ret;
- if (len < 1)
- return -1;
- switch (buf[0]) {
- case '1':
- case 'y':
- case 'Y':
- return adis16400_reset(indio_dev);
+ ret = strtobool(buf, &val);
+ if (ret < 0)
+ return ret;
+ if (val) {
+ ret = adis16400_reset(dev_get_drvdata(dev));
+ if (ret < 0)
+ return ret;
}
- return -1;
+
+ return len;
}
int adis16400_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret;
u16 msc;
+
ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -289,24 +284,6 @@ static int adis16400_stop_device(struct iio_dev *indio_dev)
return ret;
}
-static int adis16400_self_test(struct iio_dev *indio_dev)
-{
- int ret;
- ret = adis16400_spi_write_reg_16(indio_dev,
- ADIS16400_MSC_CTRL,
- ADIS16400_MSC_CTRL_MEM_TEST);
- if (ret) {
- dev_err(&indio_dev->dev, "problem starting self test");
- goto err_ret;
- }
-
- msleep(ADIS16400_MTEST_DELAY);
- adis16400_check_status(indio_dev);
-
-err_ret:
- return ret;
-}
-
static int adis16400_check_status(struct iio_dev *indio_dev)
{
u16 status;
@@ -356,11 +333,28 @@ error_ret:
return ret;
}
+static int adis16400_self_test(struct iio_dev *indio_dev)
+{
+ int ret;
+ ret = adis16400_spi_write_reg_16(indio_dev,
+ ADIS16400_MSC_CTRL,
+ ADIS16400_MSC_CTRL_MEM_TEST);
+ if (ret) {
+ dev_err(&indio_dev->dev, "problem starting self test");
+ goto err_ret;
+ }
+
+ msleep(ADIS16400_MTEST_DELAY);
+ adis16400_check_status(indio_dev);
+
+err_ret:
+ return ret;
+}
+
static int adis16400_initial_setup(struct iio_dev *indio_dev)
{
int ret;
u16 prod_id, smp_prd;
- struct device *dev = &indio_dev->dev;
struct adis16400_state *st = iio_priv(indio_dev);
/* use low spi speed for init */
@@ -368,29 +362,26 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
st->us->mode = SPI_MODE_3;
spi_setup(st->us);
- /* Disable IRQ */
ret = adis16400_set_irq(indio_dev, false);
if (ret) {
- dev_err(dev, "disable irq failed");
+ dev_err(&indio_dev->dev, "disable irq failed");
goto err_ret;
}
- /* Do self test */
ret = adis16400_self_test(indio_dev);
if (ret) {
- dev_err(dev, "self test failure");
+ dev_err(&indio_dev->dev, "self test failure");
goto err_ret;
}
- /* Read status register to check the result */
ret = adis16400_check_status(indio_dev);
if (ret) {
adis16400_reset(indio_dev);
- dev_err(dev, "device not playing ball -> reset");
+ dev_err(&indio_dev->dev, "device not playing ball -> reset");
msleep(ADIS16400_STARTUP_DELAY);
ret = adis16400_check_status(indio_dev);
if (ret) {
- dev_err(dev, "giving up");
+ dev_err(&indio_dev->dev, "giving up");
goto err_ret;
}
}
@@ -401,10 +392,11 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
goto err_ret;
if ((prod_id & 0xF000) != st->variant->product_id)
- dev_warn(dev, "incorrect id");
+ dev_warn(&indio_dev->dev, "incorrect id");
- printk(KERN_INFO DRIVER_NAME ": prod_id 0x%04x at CS%d (irq %d)\n",
- prod_id, st->us->chip_select, st->us->irq);
+ dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n",
+ indio_dev->name, prod_id,
+ st->us->chip_select, st->us->irq);
}
/* use high spi speed if possible */
ret = adis16400_spi_read_reg_16(indio_dev,
@@ -414,15 +406,13 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
spi_setup(st->us);
}
-
err_ret:
-
return ret;
}
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16400_read_frequency,
- adis16400_write_frequency);
+ adis16400_read_frequency,
+ adis16400_write_frequency);
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0);
@@ -441,25 +431,29 @@ enum adis16400_chan {
magn_z,
temp,
temp0, temp1, temp2,
- in1
+ in1,
+ incli_x,
+ incli_y,
};
-static u8 adis16400_addresses[16][2] = {
- [in_supply] = { ADIS16400_SUPPLY_OUT, 0 },
+static u8 adis16400_addresses[17][2] = {
+ [in_supply] = { ADIS16400_SUPPLY_OUT },
[gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF },
[gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF },
[gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF },
[accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF },
[accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF },
[accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF },
- [magn_x] = { ADIS16400_XMAGN_OUT, 0 },
- [magn_y] = { ADIS16400_YMAGN_OUT, 0 },
- [magn_z] = { ADIS16400_ZMAGN_OUT, 0 },
- [temp] = { ADIS16400_TEMP_OUT, 0 },
+ [magn_x] = { ADIS16400_XMAGN_OUT },
+ [magn_y] = { ADIS16400_YMAGN_OUT },
+ [magn_z] = { ADIS16400_ZMAGN_OUT },
+ [temp] = { ADIS16400_TEMP_OUT },
[temp0] = { ADIS16350_XTEMP_OUT },
[temp1] = { ADIS16350_YTEMP_OUT },
[temp2] = { ADIS16350_ZTEMP_OUT },
- [in1] = { ADIS16400_AUX_ADC , 0 },
+ [in1] = { ADIS16400_AUX_ADC },
+ [incli_x] = { ADIS16300_PITCH_OUT },
+ [incli_y] = { ADIS16300_ROLL_OUT }
};
static int adis16400_write_raw(struct iio_dev *indio_dev,
@@ -469,6 +463,7 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
long mask)
{
int ret;
+
switch (mask) {
case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
mutex_lock(&indio_dev->mlock);
@@ -489,9 +484,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
long mask)
{
struct adis16400_state *st = iio_priv(indio_dev);
- int ret;
+ int ret, shift;
s16 val16;
- int shift;
switch (mask) {
case 0:
@@ -514,11 +508,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
case (1 << IIO_CHAN_INFO_SCALE_SHARED):
case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
switch (chan->type) {
- case IIO_GYRO:
+ case IIO_ANGL_VEL:
*val = 0;
*val2 = st->variant->gyro_scale_micro;
return IIO_VAL_INT_PLUS_MICRO;
- case IIO_IN:
+ case IIO_VOLTAGE:
*val = 0;
if (chan->channel == 0)
*val2 = 2418;
@@ -548,7 +542,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
if (ret)
return ret;
- val16 = ((val16 & 0xFFF) << 4) >> 4;
+ val16 = sign_extend32(val16, 11);
*val = val16;
return IIO_VAL_INT;
case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
@@ -562,135 +556,371 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
}
static struct iio_chan_spec adis16400_channels[] = {
- IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- in_supply, ADIS16400_SCAN_SUPPLY,
- IIO_ST('u', 14, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- magn_x, ADIS16400_SCAN_MAGN_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- magn_y, ADIS16400_SCAN_MAGN_Y, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- magn_z, ADIS16400_SCAN_MAGN_Z, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- temp, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0),
- IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- in1, ADIS16400_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in_supply,
+ .scan_index = ADIS16400_SCAN_SUPPLY,
+ .scan_type = IIO_ST('u', 14, 16, 0)
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_x,
+ .scan_index = ADIS16400_SCAN_GYRO_X,
+ .scan_type = IIO_ST('s', 14, 16, 0)
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_y,
+ .scan_index = ADIS16400_SCAN_GYRO_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_z,
+ .scan_index = ADIS16400_SCAN_GYRO_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_x,
+ .scan_index = ADIS16400_SCAN_ACC_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_y,
+ .scan_index = ADIS16400_SCAN_ACC_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_z,
+ .scan_index = ADIS16400_SCAN_ACC_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_MAGN,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = magn_x,
+ .scan_index = ADIS16400_SCAN_MAGN_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_MAGN,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = magn_y,
+ .scan_index = ADIS16400_SCAN_MAGN_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_MAGN,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = magn_z,
+ .scan_index = ADIS16400_SCAN_MAGN_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = temp,
+ .scan_index = ADIS16400_SCAN_TEMP,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in1,
+ .scan_index = ADIS16400_SCAN_ADC_0,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ },
IIO_CHAN_SOFT_TIMESTAMP(12)
};
static struct iio_chan_spec adis16350_channels[] = {
- IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 1, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 2, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 3, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 4, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 0, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 0, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, "x", 0, 0,
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, "y", 1, 0,
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16350_SCAN_TEMP_Y, IIO_ST('s', 12, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, "z", 2, 0,
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16350_SCAN_TEMP_Z, IIO_ST('s', 12, 16, 0), 0),
- IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in_supply,
+ .scan_index = ADIS16400_SCAN_SUPPLY,
+ .scan_type = IIO_ST('u', 12, 16, 0)
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_x,
+ .scan_index = ADIS16400_SCAN_GYRO_X,
+ .scan_type = IIO_ST('s', 14, 16, 0)
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_y,
+ .scan_index = ADIS16400_SCAN_GYRO_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_z,
+ .scan_index = ADIS16400_SCAN_GYRO_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_x,
+ .scan_index = ADIS16400_SCAN_ACC_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_y,
+ .scan_index = ADIS16400_SCAN_ACC_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_z,
+ .scan_index = ADIS16400_SCAN_ACC_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "x",
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = temp0,
+ .scan_index = ADIS16350_SCAN_TEMP_X,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 1,
+ .extend_name = "y",
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = temp1,
+ .scan_index = ADIS16350_SCAN_TEMP_Y,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 2,
+ .extend_name = "z",
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = temp2,
+ .scan_index = ADIS16350_SCAN_TEMP_Z,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in1,
+ .scan_index = ADIS16350_SCAN_ADC_0,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ },
IIO_CHAN_SOFT_TIMESTAMP(11)
};
static struct iio_chan_spec adis16300_channels[] = {
- IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 1, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 4, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 0, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 0, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0),
- IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
- 0, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 0, ADIS16300_SCAN_INCLI_X, IIO_ST('s', 13, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- 0, ADIS16300_SCAN_INCLI_Y, IIO_ST('s', 13, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in_supply,
+ .scan_index = ADIS16400_SCAN_SUPPLY,
+ .scan_type = IIO_ST('u', 12, 16, 0)
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_x,
+ .scan_index = ADIS16400_SCAN_GYRO_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_x,
+ .scan_index = ADIS16400_SCAN_ACC_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_y,
+ .scan_index = ADIS16400_SCAN_ACC_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_z,
+ .scan_index = ADIS16400_SCAN_ACC_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = temp,
+ .scan_index = ADIS16400_SCAN_TEMP,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in1,
+ .scan_index = ADIS16350_SCAN_ADC_0,
+ .scan_type = IIO_ST('s', 12, 16, 0),
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = incli_x,
+ .scan_index = ADIS16300_SCAN_INCLI_X,
+ .scan_type = IIO_ST('s', 13, 16, 0),
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = incli_y,
+ .scan_index = ADIS16300_SCAN_INCLI_Y,
+ .scan_type = IIO_ST('s', 13, 16, 0),
+ },
IIO_CHAN_SOFT_TIMESTAMP(14)
};
+static const struct iio_chan_spec adis16334_channels[] = {
+ {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_x,
+ .scan_index = ADIS16400_SCAN_GYRO_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_y,
+ .scan_index = ADIS16400_SCAN_GYRO_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = gyro_z,
+ .scan_index = ADIS16400_SCAN_GYRO_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_x,
+ .scan_index = ADIS16400_SCAN_ACC_X,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_y,
+ .scan_index = ADIS16400_SCAN_ACC_Y,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_z,
+ .scan_index = ADIS16400_SCAN_ACC_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .address = accel_z,
+ .scan_index = ADIS16400_SCAN_ACC_Z,
+ .scan_type = IIO_ST('s', 14, 16, 0),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(12)
+};
+
static struct attribute *adis16400_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
@@ -715,6 +945,16 @@ static struct adis16400_chip_info adis16400_chips[] = {
(1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) |
(1 << 14),
},
+ [ADIS16334] = {
+ .channels = adis16334_channels,
+ .num_channels = ARRAY_SIZE(adis16334_channels),
+ .gyro_scale_micro = 873,
+ .accel_scale_micro = 981,
+ .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
+ (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
+ (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
+ (1 << ADIS16400_SCAN_ACC_Z),
+ },
[ADIS16350] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
@@ -779,7 +1019,7 @@ static const struct iio_info adis16400_info = {
static int __devinit adis16400_probe(struct spi_device *spi)
{
- int ret, regdone = 0;
+ int ret;
struct adis16400_state *st;
struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
if (indio_dev == NULL) {
@@ -806,20 +1046,15 @@ static int __devinit adis16400_probe(struct spi_device *spi)
if (ret)
goto error_free_dev;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_unreg_ring_funcs;
- regdone = 1;
-
- ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
- st->variant->channels,
- st->variant->num_channels);
+ ret = iio_buffer_register(indio_dev,
+ st->variant->channels,
+ st->variant->num_channels);
if (ret) {
dev_err(&spi->dev, "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
- if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
+ if (spi->irq) {
ret = adis16400_probe_trigger(indio_dev);
if (ret)
goto error_uninitialize_ring;
@@ -829,20 +1064,21 @@ static int __devinit adis16400_probe(struct spi_device *spi)
ret = adis16400_initial_setup(indio_dev);
if (ret)
goto error_remove_trigger;
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_remove_trigger;
+
return 0;
error_remove_trigger:
- if (indio_dev->modes & INDIO_RING_TRIGGERED)
+ if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
adis16400_remove_trigger(indio_dev);
error_uninitialize_ring:
- iio_ring_buffer_unregister(indio_dev->ring);
+ iio_buffer_unregister(indio_dev);
error_unreg_ring_funcs:
adis16400_unconfigure_ring(indio_dev);
error_free_dev:
- if (regdone)
- iio_device_unregister(indio_dev);
- else
- iio_free_device(indio_dev);
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
@@ -853,14 +1089,15 @@ static int adis16400_remove(struct spi_device *spi)
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ iio_device_unregister(indio_dev);
ret = adis16400_stop_device(indio_dev);
if (ret)
goto err_ret;
adis16400_remove_trigger(indio_dev);
- iio_ring_buffer_unregister(indio_dev->ring);
+ iio_buffer_unregister(indio_dev);
adis16400_unconfigure_ring(indio_dev);
- iio_device_unregister(indio_dev);
+ iio_free_device(indio_dev);
return 0;
@@ -870,6 +1107,7 @@ err_ret:
static const struct spi_device_id adis16400_id[] = {
{"adis16300", ADIS16300},
+ {"adis16334", ADIS16334},
{"adis16350", ADIS16350},
{"adis16354", ADIS16350},
{"adis16355", ADIS16350},
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index 3612373..fd886bf 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -1,21 +1,14 @@
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/mutex.h>
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/bitops.h>
+#include <linux/export.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "../accel/accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16400.h"
/**
@@ -87,13 +80,13 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx)
int i, j = 0, ret;
struct spi_transfer *xfers;
- xfers = kzalloc(sizeof(*xfers)*indio_dev->ring->scan_count + 1,
+ xfers = kzalloc(sizeof(*xfers)*indio_dev->buffer->scan_count + 1,
GFP_KERNEL);
if (xfers == NULL)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(read_all_tx_array); i++)
- if (indio_dev->ring->scan_mask & (1 << i)) {
+ if (test_bit(i, indio_dev->buffer->scan_mask)) {
xfers[j].tx_buf = &read_all_tx_array[i];
xfers[j].bits_per_word = 16;
xfers[j].len = 2;
@@ -104,7 +97,7 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx)
xfers[j].len = 2;
spi_message_init(&msg);
- for (j = 0; j < indio_dev->ring->scan_count + 1; j++)
+ for (j = 0; j < indio_dev->buffer->scan_count + 1; j++)
spi_message_add_tail(&xfers[j], &msg);
ret = spi_sync(st->us, &msg);
@@ -119,13 +112,14 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx)
static irqreturn_t adis16400_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16400_state *st = iio_priv(indio_dev);
- struct iio_ring_buffer *ring = indio_dev->ring;
+ struct iio_buffer *ring = indio_dev->buffer;
int i = 0, j, ret = 0;
s16 *data;
size_t datasize = ring->access->get_bytes_per_datum(ring);
- unsigned long mask = ring->scan_mask;
+ /* Asumption that long is enough for maximum channels */
+ unsigned long mask = *ring->scan_mask;
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -144,7 +138,7 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx);
if (ret < 0)
goto err;
- for (; i < indio_dev->ring->scan_count; i++) {
+ for (; i < indio_dev->buffer->scan_count; i++) {
j = __ffs(mask);
mask &= ~(1 << j);
data[i] = be16_to_cpup(
@@ -155,7 +149,7 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access->store_to(indio_dev->ring, (u8 *) data, pf->timestamp);
+ ring->access->store_to(indio_dev->buffer, (u8 *) data, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
@@ -170,36 +164,32 @@ err:
void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->ring);
+ iio_sw_rb_free(indio_dev->buffer);
}
-static const struct iio_ring_setup_ops adis16400_ring_setup_ops = {
- .preenable = &iio_sw_ring_preenable,
- .postenable = &iio_triggered_ring_postenable,
- .predisable = &iio_triggered_ring_predisable,
+static const struct iio_buffer_setup_ops adis16400_ring_setup_ops = {
+ .preenable = &iio_sw_buffer_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
};
int adis16400_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16400_state *st = iio_priv(indio_dev);
- struct iio_ring_buffer *ring;
+ struct iio_buffer *ring;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
ret = -ENOMEM;
return ret;
}
- indio_dev->ring = ring;
+ indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
ring->access = &ring_sw_access_funcs;
ring->bpe = 2;
ring->scan_timestamp = true;
ring->setup_ops = &adis16400_ring_setup_ops;
ring->owner = THIS_MODULE;
- /* Set default scan mode */
- ring->scan_mask = st->variant->default_scan_mask;
- ring->scan_count = hweight_long(st->variant->default_scan_mask);
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16400_trigger_handler,
@@ -213,9 +203,9 @@ int adis16400_configure_ring(struct iio_dev *indio_dev)
goto error_iio_sw_rb_free;
}
- indio_dev->modes |= INDIO_RING_TRIGGERED;
+ indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
error_iio_sw_rb_free:
- iio_sw_rb_free(indio_dev->ring);
+ iio_sw_rb_free(indio_dev->buffer);
return ret;
}
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c
index c6ec41a..5bf0007 100644
--- a/drivers/staging/iio/imu/adis16400_trigger.c
+++ b/drivers/staging/iio/imu/adis16400_trigger.c
@@ -1,14 +1,9 @@
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
+#include <linux/export.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../trigger.h"
#include "adis16400.h"
@@ -24,13 +19,18 @@ static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16400_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16400_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16400_data_rdy_trigger_set_state,
+};
+
int adis16400_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
struct adis16400_state *st = iio_priv(indio_dev);
st->trig = iio_allocate_trigger("%s-dev%d",
- spi_get_device_id(st->us)->name,
+ indio_dev->name,
indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
@@ -45,9 +45,8 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev)
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state;
+ st->trig->ops = &adis16400_trigger_ops;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 46d62d1..e7e9159 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -1,7 +1,7 @@
-\#
+#
# Light sensors
#
-comment "Light sensors"
+menu "Light sensors"
config SENSORS_ISL29018
tristate "ISL 29018 light and proximity sensor"
@@ -30,3 +30,5 @@ config TSL2583
help
Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices.
Access ALS data via iio, sysfs.
+
+endmenu
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 4794ffd..9dc9e63 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -28,7 +28,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include "../iio.h"
-
+#include "../sysfs.h"
#define CONVERSION_TIME_MS 100
#define ISL29018_REG_ADD_COMMAND1 0x00
@@ -51,12 +51,16 @@
#define ISL29018_REG_ADD_DATA_LSB 0x02
#define ISL29018_REG_ADD_DATA_MSB 0x03
-#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB
+#define ISL29018_MAX_REGS (ISL29018_REG_ADD_DATA_MSB+1)
+
+#define ISL29018_REG_TEST 0x08
+#define ISL29018_TEST_SHIFT 0
+#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
struct isl29018_chip {
- struct iio_dev *indio_dev;
struct i2c_client *client;
struct mutex lock;
+ unsigned int lux_scale;
unsigned int range;
unsigned int adc_bit;
int prox_scheme;
@@ -66,22 +70,27 @@ struct isl29018_chip {
static int isl29018_write_data(struct i2c_client *client, u8 reg,
u8 val, u8 mask, u8 shift)
{
- u8 regval;
- int ret = 0;
- struct isl29018_chip *chip = i2c_get_clientdata(client);
-
- regval = chip->reg_cache[reg];
- regval &= ~mask;
- regval |= val << shift;
+ u8 regval = val;
+ int ret;
+ struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
+
+ /* don't cache or mask REG_TEST */
+ if (reg < ISL29018_MAX_REGS) {
+ regval = chip->reg_cache[reg];
+ regval &= ~mask;
+ regval |= val << shift;
+ }
ret = i2c_smbus_write_byte_data(client, reg, regval);
if (ret) {
dev_err(&client->dev, "Write to device fails status %x\n", ret);
- return ret;
+ } else {
+ /* don't update cache on err */
+ if (reg < ISL29018_MAX_REGS)
+ chip->reg_cache[reg] = regval;
}
- chip->reg_cache[reg] = regval;
- return 0;
+ return ret;
}
static int isl29018_set_range(struct i2c_client *client, unsigned long range,
@@ -158,7 +167,7 @@ static int isl29018_read_sensor_input(struct i2c_client *client, int mode)
static int isl29018_read_lux(struct i2c_client *client, int *lux)
{
int lux_data;
- struct isl29018_chip *chip = i2c_get_clientdata(client);
+ struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
lux_data = isl29018_read_sensor_input(client,
COMMMAND1_OPMODE_ALS_ONCE);
@@ -166,7 +175,7 @@ static int isl29018_read_lux(struct i2c_client *client, int *lux)
if (lux_data < 0)
return lux_data;
- *lux = (lux_data * chip->range) >> chip->adc_bit;
+ *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit;
return 0;
}
@@ -224,52 +233,13 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
return 0;
}
-static ssize_t get_sensor_data(struct device *dev, char *buf, int mode)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
- struct i2c_client *client = chip->client;
- int value = 0;
- int status;
-
- mutex_lock(&chip->lock);
- switch (mode) {
- case COMMMAND1_OPMODE_PROX_ONCE:
- status = isl29018_read_proximity_ir(client,
- chip->prox_scheme, &value);
- break;
-
- case COMMMAND1_OPMODE_ALS_ONCE:
- status = isl29018_read_lux(client, &value);
- break;
-
- case COMMMAND1_OPMODE_IR_ONCE:
- status = isl29018_read_ir(client, &value);
- break;
-
- default:
- dev_err(&client->dev, "Mode %d is not supported\n", mode);
- mutex_unlock(&chip->lock);
- return -EBUSY;
- }
- if (status < 0) {
- dev_err(&client->dev, "Error in Reading data");
- mutex_unlock(&chip->lock);
- return status;
- }
-
- mutex_unlock(&chip->lock);
-
- return sprintf(buf, "%d\n", value);
-}
-
/* Sysfs interface */
/* range */
static ssize_t show_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%u\n", chip->range);
}
@@ -278,7 +248,7 @@ static ssize_t store_range(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
struct i2c_client *client = chip->client;
int status;
unsigned long lval;
@@ -311,7 +281,7 @@ static ssize_t show_resolution(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%u\n", chip->adc_bit);
}
@@ -320,7 +290,7 @@ static ssize_t store_resolution(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
struct i2c_client *client = chip->client;
int status;
unsigned long lval;
@@ -351,7 +321,7 @@ static ssize_t show_prox_infrared_supression(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
/* return the "proximity scheme" i.e. if the chip does on chip
infrared supression (1 means perform on chip supression) */
@@ -362,7 +332,7 @@ static ssize_t store_prox_infrared_supression(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
unsigned long lval;
if (strict_strtoul(buf, 10, &lval))
@@ -381,27 +351,87 @@ static ssize_t store_prox_infrared_supression(struct device *dev,
return count;
}
-/* Read lux */
-static ssize_t show_lux(struct device *dev,
- struct device_attribute *devattr, char *buf)
+/* Channel IO */
+static int isl29018_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
{
- return get_sensor_data(dev, buf, COMMMAND1_OPMODE_ALS_ONCE);
-}
+ struct isl29018_chip *chip = iio_priv(indio_dev);
+ int ret = -EINVAL;
-/* Read ir */
-static ssize_t show_ir(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- return get_sensor_data(dev, buf, COMMMAND1_OPMODE_IR_ONCE);
+ mutex_lock(&chip->lock);
+ if (mask == (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) &&
+ chan->type == IIO_LIGHT) {
+ chip->lux_scale = val;
+ ret = 0;
+ }
+ mutex_unlock(&chip->lock);
+
+ return 0;
}
-/* Read nearest ir */
-static ssize_t show_proxim_ir(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static int isl29018_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
{
- return get_sensor_data(dev, buf, COMMMAND1_OPMODE_PROX_ONCE);
+ int ret = -EINVAL;
+ struct isl29018_chip *chip = iio_priv(indio_dev);
+ struct i2c_client *client = chip->client;
+
+ mutex_lock(&chip->lock);
+ switch (mask) {
+ case 0:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = isl29018_read_lux(client, val);
+ break;
+ case IIO_INTENSITY:
+ ret = isl29018_read_ir(client, val);
+ break;
+ case IIO_PROXIMITY:
+ ret = isl29018_read_proximity_ir(client,
+ chip->prox_scheme, val);
+ break;
+ default:
+ break;
+ }
+ if (!ret)
+ ret = IIO_VAL_INT;
+ break;
+ case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ if (chan->type == IIO_LIGHT) {
+ *val = chip->lux_scale;
+ ret = IIO_VAL_INT;
+ }
+ break;
+ default:
+ break;
+ }
+ mutex_unlock(&chip->lock);
+ return ret;
}
+static const struct iio_chan_spec isl29018_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .indexed = 1,
+ .channel = 0,
+ .processed_val = IIO_PROCESSED,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+ }, {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_IR,
+ }, {
+ /* Unindexed in current ABI. But perhaps it should be. */
+ .type = IIO_PROXIMITY,
+ }
+};
+
static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0);
static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000");
static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16");
@@ -411,9 +441,6 @@ static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression,
S_IRUGO | S_IWUSR,
show_prox_infrared_supression,
store_prox_infrared_supression, 0);
-static IIO_DEVICE_ATTR(illuminance0_input, S_IRUGO, show_lux, NULL, 0);
-static IIO_DEVICE_ATTR(intensity_infrared_raw, S_IRUGO, show_ir, NULL, 0);
-static IIO_DEVICE_ATTR(proximity_raw, S_IRUGO, show_proxim_ir, NULL, 0);
#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
#define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
@@ -423,9 +450,6 @@ static struct attribute *isl29018_attributes[] = {
ISL29018_DEV_ATTR(adc_resolution),
ISL29018_CONST_ATTR(adc_resolution_available),
ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_supression),
- ISL29018_DEV_ATTR(illuminance0_input),
- ISL29018_DEV_ATTR(intensity_infrared_raw),
- ISL29018_DEV_ATTR(proximity_raw),
NULL
};
@@ -435,13 +459,55 @@ static const struct attribute_group isl29108_group = {
static int isl29018_chip_init(struct i2c_client *client)
{
- struct isl29018_chip *chip = i2c_get_clientdata(client);
+ struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
int status;
int new_adc_bit;
unsigned int new_range;
memset(chip->reg_cache, 0, sizeof(chip->reg_cache));
+ /* Code added per Intersil Application Note 1534:
+ * When VDD sinks to approximately 1.8V or below, some of
+ * the part's registers may change their state. When VDD
+ * recovers to 2.25V (or greater), the part may thus be in an
+ * unknown mode of operation. The user can return the part to
+ * a known mode of operation either by (a) setting VDD = 0V for
+ * 1 second or more and then powering back up with a slew rate
+ * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
+ * conversions, clear the test registers, and then rewrite all
+ * registers to the desired values.
+ * ...
+ * FOR ISL29011, ISL29018, ISL29021, ISL29023
+ * 1. Write 0x00 to register 0x08 (TEST)
+ * 2. Write 0x00 to register 0x00 (CMD1)
+ * 3. Rewrite all registers to the desired values
+ *
+ * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
+ * the same thing EXCEPT the data sheet asks for a 1ms delay after
+ * writing the CMD1 register.
+ */
+ status = isl29018_write_data(client, ISL29018_REG_TEST, 0,
+ ISL29018_TEST_MASK, ISL29018_TEST_SHIFT);
+ if (status < 0) {
+ dev_err(&client->dev, "Failed to clear isl29018 TEST reg."
+ "(%d)\n", status);
+ return status;
+ }
+
+ /* See Intersil AN1534 comments above.
+ * "Operating Mode" (COMMAND1) register is reprogrammed when
+ * data is read from the device.
+ */
+ status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0,
+ 0xff, 0);
+ if (status < 0) {
+ dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg."
+ "(%d)\n", status);
+ return status;
+ }
+
+ msleep(1); /* per data sheet, page 10 */
+
/* set defaults */
status = isl29018_set_range(client, chip->range, &new_range);
if (status < 0) {
@@ -458,44 +524,45 @@ static int isl29018_chip_init(struct i2c_client *client)
static const struct iio_info isl29108_info = {
.attrs = &isl29108_group,
.driver_module = THIS_MODULE,
+ .read_raw = &isl29018_read_raw,
+ .write_raw = &isl29018_write_raw,
};
static int __devinit isl29018_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct isl29018_chip *chip;
+ struct iio_dev *indio_dev;
int err;
- chip = kzalloc(sizeof(struct isl29018_chip), GFP_KERNEL);
- if (!chip) {
- dev_err(&client->dev, "Memory allocation fails\n");
+ indio_dev = iio_allocate_device(sizeof(*chip));
+ if (indio_dev == NULL) {
+ dev_err(&client->dev, "iio allocation fails\n");
err = -ENOMEM;
goto exit;
}
+ chip = iio_priv(indio_dev);
- i2c_set_clientdata(client, chip);
+ i2c_set_clientdata(client, indio_dev);
chip->client = client;
mutex_init(&chip->lock);
+ chip->lux_scale = 1;
chip->range = 1000;
chip->adc_bit = 16;
err = isl29018_chip_init(client);
if (err)
- goto exit_free;
+ goto exit_iio_free;
- chip->indio_dev = iio_allocate_device(0);
- if (!chip->indio_dev) {
- dev_err(&client->dev, "iio allocation fails\n");
- goto exit_free;
- }
- chip->indio_dev->info = &isl29108_info;
- chip->indio_dev->name = id->name;
- chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->dev_data = (void *)(chip);
- chip->indio_dev->modes = INDIO_DIRECT_MODE;
- err = iio_device_register(chip->indio_dev);
+ indio_dev->info = &isl29108_info;
+ indio_dev->channels = isl29018_channels;
+ indio_dev->num_channels = ARRAY_SIZE(isl29018_channels);
+ indio_dev->name = id->name;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ err = iio_device_register(indio_dev);
if (err) {
dev_err(&client->dev, "iio registration fails\n");
goto exit_iio_free;
@@ -503,20 +570,18 @@ static int __devinit isl29018_probe(struct i2c_client *client,
return 0;
exit_iio_free:
- iio_free_device(chip->indio_dev);
-exit_free:
- kfree(chip);
+ iio_free_device(indio_dev);
exit:
return err;
}
static int __devexit isl29018_remove(struct i2c_client *client)
{
- struct isl29018_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
dev_dbg(&client->dev, "%s()\n", __func__);
- iio_device_unregister(chip->indio_dev);
- kfree(chip);
+ iio_device_unregister(indio_dev);
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 9cffa2e..7e984bc 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -31,13 +31,12 @@
#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/delay.h>
-#include <linux/platform_device.h>
#include <linux/pm.h>
-#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/slab.h>
#include "../iio.h"
+#include "../sysfs.h"
#include "tsl2563.h"
/* Use this many bits for fraction part. */
@@ -137,37 +136,14 @@ struct tsl2563_chip {
u32 data1;
};
-static int tsl2563_write(struct i2c_client *client, u8 reg, u8 value)
-{
- int ret;
- u8 buf[2];
-
- buf[0] = TSL2563_CMD | reg;
- buf[1] = value;
-
- ret = i2c_master_send(client, buf, sizeof(buf));
- return (ret == sizeof(buf)) ? 0 : ret;
-}
-
-static int tsl2563_read(struct i2c_client *client, u8 reg, void *buf, int len)
-{
- int ret;
- u8 cmd = TSL2563_CMD | reg;
-
- ret = i2c_master_send(client, &cmd, sizeof(cmd));
- if (ret != sizeof(cmd))
- return ret;
-
- return i2c_master_recv(client, buf, len);
-}
-
static int tsl2563_set_power(struct tsl2563_chip *chip, int on)
{
struct i2c_client *client = chip->client;
u8 cmd;
cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF;
- return tsl2563_write(client, TSL2563_REG_CTRL, cmd);
+ return i2c_smbus_write_byte_data(client,
+ TSL2563_CMD | TSL2563_REG_CTRL, cmd);
}
/*
@@ -178,36 +154,40 @@ static int tsl2563_get_power(struct tsl2563_chip *chip)
{
struct i2c_client *client = chip->client;
int ret;
- u8 val;
- ret = tsl2563_read(client, TSL2563_REG_CTRL, &val, sizeof(val));
- if (ret != sizeof(val))
+ ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_CTRL);
+ if (ret < 0)
return ret;
- return (val & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON;
+ return (ret & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON;
}
static int tsl2563_configure(struct tsl2563_chip *chip)
{
int ret;
- ret = tsl2563_write(chip->client, TSL2563_REG_TIMING,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_TIMING,
chip->gainlevel->gaintime);
if (ret)
goto error_ret;
- ret = tsl2563_write(chip->client, TSL2563_REG_HIGHLOW,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_HIGHLOW,
chip->high_thres & 0xFF);
if (ret)
goto error_ret;
- ret = tsl2563_write(chip->client, TSL2563_REG_HIGHHIGH,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_HIGHHIGH,
(chip->high_thres >> 8) & 0xFF);
if (ret)
goto error_ret;
- ret = tsl2563_write(chip->client, TSL2563_REG_LOWLOW,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_LOWLOW,
chip->low_thres & 0xFF);
if (ret)
goto error_ret;
- ret = tsl2563_write(chip->client, TSL2563_REG_LOWHIGH,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_LOWHIGH,
(chip->low_thres >> 8) & 0xFF);
/* Interrupt register is automatically written anyway if it is relevant
so is not here */
@@ -242,8 +222,8 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id)
struct i2c_client *client = chip->client;
int ret;
- ret = tsl2563_read(client, TSL2563_REG_ID, id, sizeof(*id));
- if (ret != sizeof(*id))
+ ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_ID);
+ if (ret < 0)
return ret;
return 0;
@@ -313,8 +293,9 @@ static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc)
(adc > chip->gainlevel->max) ?
chip->gainlevel++ : chip->gainlevel--;
- tsl2563_write(client, TSL2563_REG_TIMING,
- chip->gainlevel->gaintime);
+ i2c_smbus_write_byte_data(client,
+ TSL2563_CMD | TSL2563_REG_TIMING,
+ chip->gainlevel->gaintime);
tsl2563_wait_adc(chip);
tsl2563_wait_adc(chip);
@@ -327,7 +308,6 @@ static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc)
static int tsl2563_get_adc(struct tsl2563_chip *chip)
{
struct i2c_client *client = chip->client;
- u8 buf0[2], buf1[2];
u16 adc0, adc1;
int retry = 1;
int ret = 0;
@@ -350,19 +330,17 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip)
}
while (retry) {
- ret = tsl2563_read(client,
- TSL2563_REG_DATA0LOW,
- buf0, sizeof(buf0));
- if (ret != sizeof(buf0))
+ ret = i2c_smbus_read_word_data(client,
+ TSL2563_CMD | TSL2563_REG_DATA0LOW);
+ if (ret < 0)
goto out;
+ adc0 = ret;
- ret = tsl2563_read(client, TSL2563_REG_DATA1LOW,
- buf1, sizeof(buf1));
- if (ret != sizeof(buf1))
+ ret = i2c_smbus_read_word_data(client,
+ TSL2563_CMD | TSL2563_REG_DATA1LOW);
+ if (ret < 0)
goto out;
-
- adc0 = (buf0[1] << 8) + buf0[0];
- adc1 = (buf1[1] << 8) + buf1[0];
+ adc1 = ret;
retry = tsl2563_adjust_gainlevel(chip, adc0);
}
@@ -540,7 +518,8 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto error_ret;
}
error_ret:
@@ -549,19 +528,30 @@ error_ret:
}
static const struct iio_chan_spec tsl2563_channels[] = {
- IIO_CHAN(IIO_LIGHT, 0, 1, 1, NULL, 0, 0, 0, 0, 0, {}, 0),
- IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "both", 0,
- (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {},
- IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
- IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)),
- IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "ir", 1,
- (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {},
- 0)
+ {
+ .type = IIO_LIGHT,
+ .indexed = 1,
+ .channel = 0,
+ }, {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+ .event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING) |
+ IIO_EV_BIT(IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING)),
+ }, {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+ }
};
static int tsl2563_read_thresh(struct iio_dev *indio_dev,
- int event_code,
- int *val)
+ u64 event_code,
+ int *val)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
@@ -579,8 +569,8 @@ static int tsl2563_read_thresh(struct iio_dev *indio_dev,
return 0;
}
-static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev,
- int event_code,
+static int tsl2563_write_thresh(struct iio_dev *indio_dev,
+ u64 event_code,
int val)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
@@ -592,11 +582,13 @@ static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev,
else
address = TSL2563_REG_LOWLOW;
mutex_lock(&chip->lock);
- ret = tsl2563_write(chip->client, address, val & 0xFF);
+ ret = i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | address,
+ val & 0xFF);
if (ret)
goto error_ret;
- ret = tsl2563_write(chip->client, address + 1,
- (val >> 8) & 0xFF);
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | (address + 1),
+ (val >> 8) & 0xFF);
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
chip->high_thres = val;
else
@@ -612,23 +604,22 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
{
struct iio_dev *dev_info = private;
struct tsl2563_chip *chip = iio_priv(dev_info);
- u8 cmd = TSL2563_CMD | TSL2563_CLEARINT;
- iio_push_event(dev_info, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT,
+ iio_push_event(dev_info,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_EITHER),
iio_get_time_ns());
/* clear the interrupt and push the event */
- i2c_master_send(chip->client, &cmd, sizeof(cmd));
+ i2c_smbus_write_byte(chip->client, TSL2563_CMD | TSL2563_CLEARINT);
return IRQ_HANDLED;
}
static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
- int event_code,
- int state)
+ u64 event_code,
+ int state)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret = 0;
@@ -647,13 +638,17 @@ static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
if (ret)
goto out;
}
- ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_INT,
+ chip->intr);
chip->int_enabled = true;
}
if (!state && (chip->intr & 0x30)) {
chip->intr |= ~0x30;
- ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_INT,
+ chip->intr);
chip->int_enabled = false;
/* now the interrupt is not enabled, we can go to sleep */
schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
@@ -665,19 +660,18 @@ out:
}
static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev,
- int event_code)
+ u64 event_code)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
- u8 rxbuf;
int ret;
mutex_lock(&chip->lock);
- ret = tsl2563_read(chip->client, TSL2563_REG_INT,
- &rxbuf, sizeof(rxbuf));
+ ret = i2c_smbus_read_byte_data(chip->client,
+ TSL2563_CMD | TSL2563_REG_INT);
mutex_unlock(&chip->lock);
if (ret < 0)
goto error_ret;
- ret = !!(rxbuf & 0x30);
+ ret = !!(ret & 0x30);
error_ret:
return ret;
@@ -690,11 +684,12 @@ static struct i2c_driver tsl2563_i2c_driver;
static const struct iio_info tsl2563_info_no_irq = {
.driver_module = THIS_MODULE,
+ .read_raw = &tsl2563_read_raw,
+ .write_raw = &tsl2563_write_raw,
};
static const struct iio_info tsl2563_info = {
.driver_module = THIS_MODULE,
- .num_interrupt_lines = 1,
.read_raw = &tsl2563_read_raw,
.write_raw = &tsl2563_write_raw,
.read_event_value = &tsl2563_read_thresh,
@@ -711,7 +706,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
struct tsl2563_platform_data *pdata = client->dev.platform_data;
int err = 0;
int ret;
- u8 id;
+ u8 id = 0;
indio_dev = iio_allocate_device(sizeof(*chip));
if (!indio_dev)
@@ -757,9 +752,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
indio_dev->info = &tsl2563_info;
else
indio_dev->info = &tsl2563_info_no_irq;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto fail1;
if (client->irq) {
ret = request_threaded_irq(client->irq,
NULL,
@@ -778,12 +770,16 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
/* The interrupt cannot yet be enabled so this is fine without lock */
schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto fail3;
+
return 0;
fail3:
if (client->irq)
free_irq(client->irq, indio_dev);
fail2:
- iio_device_unregister(indio_dev);
+ iio_free_device(indio_dev);
fail1:
kfree(chip);
return err;
@@ -793,16 +789,20 @@ static int tsl2563_remove(struct i2c_client *client)
{
struct tsl2563_chip *chip = i2c_get_clientdata(client);
struct iio_dev *indio_dev = iio_priv_to_dev(chip);
+
+ iio_device_unregister(indio_dev);
if (!chip->int_enabled)
cancel_delayed_work(&chip->poweroff_work);
/* Ensure that interrupts are disabled - then flush any bottom halves */
chip->intr |= ~0x30;
- tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
+ i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | TSL2563_REG_INT,
+ chip->intr);
flush_scheduled_work();
tsl2563_set_power(chip, 0);
if (client->irq)
free_irq(client->irq, indio_dev);
- iio_device_unregister(indio_dev);
+
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index 5694610..80f77cf 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -27,6 +27,7 @@
#include <linux/mutex.h>
#include <linux/unistd.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#define TSL258X_MAX_DEVICE_REGS 32
@@ -68,7 +69,7 @@ enum {
TSL258X_CHIP_UNKNOWN = 0,
TSL258X_CHIP_WORKING = 1,
TSL258X_CHIP_SUSPENDED = 2
-} TSL258X_CHIP_WORKING_STATUS;
+};
/* Per-device data */
struct taos_als_info {
@@ -87,7 +88,6 @@ struct taos_settings {
struct tsl2583_chip {
struct mutex als_mutex;
struct i2c_client *client;
- struct iio_dev *iio_dev;
struct taos_als_info als_cur_info;
struct taos_settings taos_settings;
int als_time_scale;
@@ -114,7 +114,7 @@ struct taos_lux {
/* This structure is intentionally large to accommodate updates via sysfs. */
/* Sized to 11 = max 10 segments + 1 termination segment */
/* Assumption is is one and only one type of glass used */
-struct taos_lux taos_device_lux[11] = {
+static struct taos_lux taos_device_lux[11] = {
{ 9830, 8520, 15729 },
{ 12452, 10807, 23344 },
{ 14746, 6383, 11705 },
@@ -159,8 +159,7 @@ static void taos_defaults(struct tsl2583_chip *chip)
static int
taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
{
- int ret;
- int i;
+ int i, ret;
for (i = 0; i < len; i++) {
/* select register to write */
@@ -191,47 +190,47 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
* the array are then used along with the time scale factor array values, to
* calculate the lux.
*/
-static int taos_get_lux(struct i2c_client *client)
+static int taos_get_lux(struct iio_dev *indio_dev)
{
u16 ch0, ch1; /* separated ch0/ch1 data from device */
u32 lux; /* raw lux calculated from device data */
u32 ratio;
u8 buf[5];
struct taos_lux *p;
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int i, ret;
u32 ch0lux = 0;
u32 ch1lux = 0;
if (mutex_trylock(&chip->als_mutex) == 0) {
- dev_info(&client->dev, "taos_get_lux device is busy\n");
+ dev_info(&chip->client->dev, "taos_get_lux device is busy\n");
return chip->als_cur_info.lux; /* busy, so return LAST VALUE */
}
if (chip->taos_chip_status != TSL258X_CHIP_WORKING) {
/* device is not enabled */
- dev_err(&client->dev, "taos_get_lux device is not enabled\n");
+ dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n");
ret = -EBUSY ;
goto out_unlock;
}
- ret = taos_i2c_read(client, (TSL258X_CMD_REG), &buf[0], 1);
+ ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1);
if (ret < 0) {
- dev_err(&client->dev, "taos_get_lux failed to read CMD_REG\n");
+ dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n");
goto out_unlock;
}
/* is data new & valid */
if (!(buf[0] & TSL258X_STA_ADC_INTR)) {
- dev_err(&client->dev, "taos_get_lux data not valid\n");
+ dev_err(&chip->client->dev, "taos_get_lux data not valid\n");
ret = chip->als_cur_info.lux; /* return LAST VALUE */
goto out_unlock;
}
for (i = 0; i < 4; i++) {
int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i);
- ret = taos_i2c_read(client, reg, &buf[i], 1);
+ ret = taos_i2c_read(chip->client, reg, &buf[i], 1);
if (ret < 0) {
- dev_err(&client->dev, "taos_get_lux failed to read"
+ dev_err(&chip->client->dev, "taos_get_lux failed to read"
" register %x\n", reg);
goto out_unlock;
}
@@ -239,11 +238,12 @@ static int taos_get_lux(struct i2c_client *client)
/* clear status, really interrupt status (interrupts are off), but
* we use the bit anyway - don't forget 0x80 - this is a command*/
- ret = i2c_smbus_write_byte(client,
- (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | TSL258X_CMD_ALS_INT_CLR));
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN |
+ TSL258X_CMD_ALS_INT_CLR));
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_i2c_write_command failed in taos_get_lux, err = %d\n",
ret);
goto out_unlock; /* have no data, so return failure */
@@ -285,7 +285,7 @@ static int taos_get_lux(struct i2c_client *client)
/* note: lux is 31 bit max at this point */
if (ch1lux > ch0lux) {
- dev_dbg(&client->dev, "No Data - Return last value\n");
+ dev_dbg(&chip->client->dev, "No Data - Return last value\n");
ret = chip->als_cur_info.lux = 0;
goto out_unlock;
}
@@ -319,54 +319,56 @@ out_unlock:
* to derive actual lux).
* Return updated gain_trim value.
*/
-int taos_als_calibrate(struct i2c_client *client)
+static int taos_als_calibrate(struct iio_dev *indio_dev)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
u8 reg_val;
unsigned int gain_trim_val;
int ret;
int lux_val;
- ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL));
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed to reach the CNTRL register, ret=%d\n",
ret);
return ret;
}
- reg_val = i2c_smbus_read_byte(client);
+ reg_val = i2c_smbus_read_byte(chip->client);
if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON))
!= (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed: device not powered on with ADC enabled\n");
return -1;
}
- ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL));
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed to reach the STATUS register, ret=%d\n",
ret);
return ret;
}
- reg_val = i2c_smbus_read_byte(client);
+ reg_val = i2c_smbus_read_byte(chip->client);
if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed: STATUS - ADC not valid.\n");
return -ENODATA;
}
- lux_val = taos_get_lux(client);
+ lux_val = taos_get_lux(indio_dev);
if (lux_val < 0) {
- dev_err(&client->dev, "taos_als_calibrate failed to get lux\n");
+ dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n");
return lux_val;
}
gain_trim_val = (unsigned int) (((chip->taos_settings.als_cal_target)
* chip->taos_settings.als_gain_trim) / lux_val);
if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed: trim_val of %d is out of range\n",
gain_trim_val);
return -ENODATA;
@@ -380,21 +382,21 @@ int taos_als_calibrate(struct i2c_client *client)
* Turn the device on.
* Configuration must be set before calling this function.
*/
-static int taos_chip_on(struct i2c_client *client)
+static int taos_chip_on(struct iio_dev *indio_dev)
{
int i;
- int ret = 0;
+ int ret;
u8 *uP;
u8 utmp;
int als_count;
int als_time;
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
/* and make sure we're not already on */
if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
/* if forcing a register update - turn off, then on */
- dev_info(&client->dev, "device is already enabled\n");
- return -EINVAL;
+ dev_info(&chip->client->dev, "device is already enabled\n");
+ return -EINVAL;
}
/* determine als integration regster */
@@ -416,20 +418,21 @@ static int taos_chip_on(struct i2c_client *client)
/* TSL258x Specific power-on / adc enable sequence
* Power on the device 1st. */
utmp = TSL258X_CNTL_PWR_ON;
- ret = i2c_smbus_write_byte_data(client,
- TSL258X_CMD_REG | TSL258X_CNTRL, utmp);
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG | TSL258X_CNTRL, utmp);
if (ret < 0) {
- dev_err(&client->dev, "taos_chip_on failed on CNTRL reg.\n");
+ dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n");
return -1;
}
/* Use the following shadow copy for our delay before enabling ADC.
* Write all the registers. */
for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) {
- ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG + i,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG + i,
*uP++);
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_chip_on failed on reg %d.\n", i);
return -1;
}
@@ -439,10 +442,11 @@ static int taos_chip_on(struct i2c_client *client)
/* NOW enable the ADC
* initialize the desired mode of operation */
utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL;
- ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG | TSL258X_CNTRL,
utmp);
if (ret < 0) {
- dev_err(&client->dev, "taos_chip_on failed on 2nd CTRL reg.\n");
+ dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n");
return -1;
}
chip->taos_chip_status = TSL258X_CHIP_WORKING;
@@ -450,33 +454,26 @@ static int taos_chip_on(struct i2c_client *client)
return ret;
}
-static int taos_chip_off(struct i2c_client *client)
+static int taos_chip_off(struct iio_dev *indio_dev)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int ret;
/* turn device off */
chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
- ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG | TSL258X_CNTRL,
0x00);
return ret;
}
/* Sysfs Interface Functions */
-static ssize_t taos_device_id(struct device *dev,
-struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
-
- return sprintf(buf, "%s\n", chip->client->name);
-}
static ssize_t taos_power_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_chip_status);
}
@@ -485,16 +482,15 @@ static ssize_t taos_power_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
unsigned long value;
if (strict_strtoul(buf, 0, &value))
return -EINVAL;
if (value == 0)
- taos_chip_off(chip->client);
+ taos_chip_off(indio_dev);
else
- taos_chip_on(chip->client);
+ taos_chip_on(indio_dev);
return len;
}
@@ -503,7 +499,7 @@ static ssize_t taos_gain_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
char gain[4] = {0};
switch (chip->taos_settings.als_gain) {
@@ -528,7 +524,7 @@ static ssize_t taos_gain_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -565,7 +561,7 @@ static ssize_t taos_als_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_time);
}
@@ -574,7 +570,7 @@ static ssize_t taos_als_time_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -586,7 +582,7 @@ static ssize_t taos_als_time_store(struct device *dev,
if (value % 50)
return -EINVAL;
- chip->taos_settings.als_time = value;
+ chip->taos_settings.als_time = value;
return len;
}
@@ -602,7 +598,7 @@ static ssize_t taos_als_trim_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim);
}
@@ -611,7 +607,7 @@ static ssize_t taos_als_trim_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -627,7 +623,7 @@ static ssize_t taos_als_cal_target_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target);
}
@@ -636,7 +632,7 @@ static ssize_t taos_als_cal_target_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -651,27 +647,26 @@ static ssize_t taos_als_cal_target_store(struct device *dev,
static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
- int lux;
+ int ret;
- lux = taos_get_lux(chip->client);
+ ret = taos_get_lux(dev_get_drvdata(dev));
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%d\n", lux);
+ return sprintf(buf, "%d\n", ret);
}
static ssize_t taos_do_calibrate(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
unsigned long value;
if (strict_strtoul(buf, 0, &value))
return -EINVAL;
if (value == 1)
- taos_als_calibrate(chip->client);
+ taos_als_calibrate(indio_dev);
return len;
}
@@ -703,8 +698,8 @@ static ssize_t taos_luxtable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
- int value[ARRAY_SIZE(taos_device_lux)];
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
+ int value[ARRAY_SIZE(taos_device_lux)*3 + 1];
int n;
get_options(buf, ARRAY_SIZE(value), value);
@@ -725,18 +720,17 @@ static ssize_t taos_luxtable_store(struct device *dev,
}
if (chip->taos_chip_status == TSL258X_CHIP_WORKING)
- taos_chip_off(chip->client);
+ taos_chip_off(indio_dev);
/* Zero out the table */
memset(taos_device_lux, 0, sizeof(taos_device_lux));
memcpy(taos_device_lux, &value[1], (value[0] * 4));
- taos_chip_on(chip->client);
+ taos_chip_on(indio_dev);
return len;
}
-static DEVICE_ATTR(name, S_IRUGO, taos_device_id, NULL);
static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
taos_power_state_show, taos_power_state_store);
@@ -762,7 +756,6 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR,
taos_luxtable_show, taos_luxtable_store);
static struct attribute *sysfs_attrs_ctrl[] = {
- &dev_attr_name.attr,
&dev_attr_power_state.attr,
&dev_attr_illuminance0_calibscale.attr, /* Gain */
&dev_attr_illuminance0_calibscale_available.attr,
@@ -798,9 +791,10 @@ static const struct iio_info tsl2583_info = {
static int __devinit taos_probe(struct i2c_client *clientp,
const struct i2c_device_id *idp)
{
- int i, ret = 0;
+ int i, ret;
unsigned char buf[TSL258X_MAX_DEVICE_REGS];
- static struct tsl2583_chip *chip;
+ struct tsl2583_chip *chip;
+ struct iio_dev *indio_dev;
if (!i2c_check_functionality(clientp->adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -810,12 +804,15 @@ static int __devinit taos_probe(struct i2c_client *clientp,
return -EOPNOTSUPP;
}
- chip = kzalloc(sizeof(struct tsl2583_chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
+ indio_dev = iio_allocate_device(sizeof(*chip));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
+ dev_err(&clientp->dev, "iio allocation failed\n");
+ goto fail1;
+ }
+ chip = iio_priv(indio_dev);
chip->client = clientp;
- i2c_set_clientdata(clientp, chip);
+ i2c_set_clientdata(clientp, indio_dev);
mutex_init(&chip->als_mutex);
chip->taos_chip_status = TSL258X_CHIP_UNKNOWN;
@@ -827,14 +824,14 @@ static int __devinit taos_probe(struct i2c_client *clientp,
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
"reg failed in taos_probe(), err = %d\n", ret);
- goto fail1;
+ goto fail2;
}
ret = i2c_smbus_read_byte(clientp);
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_read_byte from "
"reg failed in taos_probe(), err = %d\n", ret);
- goto fail1;
+ goto fail2;
}
buf[i] = ret;
}
@@ -842,58 +839,50 @@ static int __devinit taos_probe(struct i2c_client *clientp,
if (!taos_tsl258x_device(buf)) {
dev_info(&clientp->dev, "i2c device found but does not match "
"expected id in taos_probe()\n");
- goto fail1;
+ goto fail2;
}
ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg "
"failed in taos_probe(), err = %d\n", ret);
- goto fail1;
- }
-
- chip->iio_dev = iio_allocate_device(0);
- if (!chip->iio_dev) {
- ret = -ENOMEM;
- dev_err(&clientp->dev, "iio allocation failed\n");
- goto fail1;
+ goto fail2;
}
- chip->iio_dev->info = &tsl2583_info;
- chip->iio_dev->dev.parent = &clientp->dev;
- chip->iio_dev->dev_data = (void *)(chip);
- chip->iio_dev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(chip->iio_dev);
+ indio_dev->info = &tsl2583_info;
+ indio_dev->dev.parent = &clientp->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = chip->client->name;
+ ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&clientp->dev, "iio registration failed\n");
- goto fail1;
+ goto fail2;
}
/* Load up the V2 defaults (these are hard coded defaults for now) */
taos_defaults(chip);
/* Make sure the chip is on */
- taos_chip_on(clientp);
+ taos_chip_on(indio_dev);
dev_info(&clientp->dev, "Light sensor found.\n");
-
return 0;
-
fail1:
- kfree(chip);
-
+ iio_free_device(indio_dev);
+fail2:
return ret;
}
static int taos_suspend(struct i2c_client *client, pm_message_t state)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int ret = 0;
mutex_lock(&chip->als_mutex);
if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
- ret = taos_chip_off(client);
+ ret = taos_chip_off(indio_dev);
chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
}
@@ -903,13 +892,14 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state)
static int taos_resume(struct i2c_client *client)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int ret = 0;
mutex_lock(&chip->als_mutex);
if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED)
- ret = taos_chip_on(client);
+ ret = taos_chip_on(indio_dev);
mutex_unlock(&chip->als_mutex);
return ret;
@@ -918,11 +908,9 @@ static int taos_resume(struct i2c_client *client)
static int __devexit taos_remove(struct i2c_client *client)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
-
- iio_device_unregister(chip->iio_dev);
+ iio_device_unregister(i2c_get_clientdata(client));
+ iio_free_device(i2c_get_clientdata(client));
- kfree(chip);
return 0;
}
diff --git a/drivers/staging/iio/meter/Kconfig b/drivers/staging/iio/meter/Kconfig
index 12e36e4..d290d27 100644
--- a/drivers/staging/iio/meter/Kconfig
+++ b/drivers/staging/iio/meter/Kconfig
@@ -1,7 +1,7 @@
#
# IIO meter drivers configuration
#
-comment "Active energy metering IC"
+menu "Active energy metering IC"
config ADE7753
tristate "Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver"
@@ -20,8 +20,8 @@ config ADE7754
config ADE7758
tristate "Analog Devices ADE7758 Poly Phase Multifunction Energy Metering IC Driver"
depends on SPI
- select IIO_TRIGGER if IIO_RING_BUFFER
- select IIO_SW_RING if IIO_RING_BUFFER
+ select IIO_TRIGGER if IIO_BUFFER
+ select IIO_SW_RING if IIO_BUFFER
help
Say yes here to build support for Analog Devices ADE7758 Polyphase
Multifunction Energy Metering IC with Per Phase Information Driver.
@@ -59,3 +59,5 @@ config ADE7854_SPI
To compile this driver as a module, choose M here: the
module will be called ade7854-spi.
+
+endmenu
diff --git a/drivers/staging/iio/meter/Makefile b/drivers/staging/iio/meter/Makefile
index 0cc7d51..de3863d 100644
--- a/drivers/staging/iio/meter/Makefile
+++ b/drivers/staging/iio/meter/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ADE7753) += ade7753.o
obj-$(CONFIG_ADE7754) += ade7754.o
ade7758-y := ade7758_core.o
-ade7758-$(CONFIG_IIO_RING_BUFFER) += ade7758_ring.o ade7758_trigger.o
+ade7758-$(CONFIG_IIO_BUFFER) += ade7758_ring.o ade7758_trigger.o
obj-$(CONFIG_ADE7758) += ade7758.o
obj-$(CONFIG_ADE7759) += ade7759.o
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 6c9c23f..940fef6 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -17,6 +16,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -29,7 +29,7 @@ static int ade7753_spi_write_reg_8(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7753_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7753_WRITE_REG(reg_address);
@@ -47,7 +47,7 @@ static int ade7753_spi_write_reg_16(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7753_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7753_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int ade7753_spi_read_reg_8(struct device *dev,
u8 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7753_state *st = iio_priv(indio_dev);
ssize_t ret;
ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address));
@@ -83,7 +83,7 @@ static int ade7753_spi_read_reg_16(struct device *dev,
u16 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7753_state *st = iio_priv(indio_dev);
ssize_t ret;
ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address));
@@ -105,7 +105,7 @@ static int ade7753_spi_read_reg_24(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7753_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -369,10 +369,11 @@ static int ade7753_stop_device(struct device *dev)
return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val);
}
-static int ade7753_initial_setup(struct ade7753_state *st)
+static int ade7753_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
+ struct device *dev = &indio_dev->dev;
+ struct ade7753_state *st = iio_priv(indio_dev);
/* use low spi speed for init */
st->us->mode = SPI_MODE_3;
@@ -397,9 +398,9 @@ static ssize_t ade7753_read_frequency(struct device *dev,
char *buf)
{
int ret, len = 0;
- u8 t;
+ u16 t;
int sps;
- ret = ade7753_spi_read_reg_8(dev, ADE7753_MODE, &t);
+ ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &t);
if (ret)
return ret;
@@ -416,7 +417,7 @@ static ssize_t ade7753_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7753_state *st = iio_priv(indio_dev);
unsigned long val;
int ret;
u16 reg, t;
@@ -452,8 +453,8 @@ out:
}
static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit);
-static IIO_CONST_ATTR(temp_offset, "-25 C");
-static IIO_CONST_ATTR(temp_scale, "0.67 C");
+static IIO_CONST_ATTR(in_temp_offset, "-25 C");
+static IIO_CONST_ATTR(in_temp_scale, "0.67 C");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ade7753_read_frequency,
@@ -464,9 +465,9 @@ static IIO_DEV_ATTR_RESET(ade7753_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
static struct attribute *ade7753_attributes[] = {
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
+ &iio_dev_attr_in_temp_raw.dev_attr.attr,
+ &iio_const_attr_in_temp_offset.dev_attr.attr,
+ &iio_const_attr_in_temp_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
@@ -511,63 +512,42 @@ static const struct iio_info ade7753_info = {
static int __devinit ade7753_probe(struct spi_device *spi)
{
- int ret, regdone = 0;
- struct ade7753_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
+ int ret;
+ struct ade7753_state *st;
+ struct iio_dev *indio_dev;
+
+ /* setup the industrialio driver allocated elements */
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
goto error_ret;
}
/* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADE7753_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADE7753_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
+ st = iio_priv(indio_dev);
st->us = spi;
mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
- st->indio_dev->name = spi->dev.driver->name;
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->info = &ade7753_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = spi->dev.driver->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &ade7753_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->indio_dev);
+ /* Get the device into a sane initial state */
+ ret = ade7753_initial_setup(indio_dev);
if (ret)
goto error_free_dev;
- regdone = 1;
- /* Get the device into a sane initial state */
- ret = ade7753_initial_setup(st);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_dev;
+
return 0;
error_free_dev:
- if (regdone)
- iio_device_unregister(st->indio_dev);
- else
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
+ iio_free_device(indio_dev);
+
error_ret:
return ret;
}
@@ -576,20 +556,15 @@ error_ret:
static int ade7753_remove(struct spi_device *spi)
{
int ret;
- struct ade7753_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+
+ iio_device_unregister(indio_dev);
ret = ade7753_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
- iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
-
- return 0;
-
+ iio_free_device(indio_dev);
err_ret:
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h
index 3b9c7f6..3f059d3 100644
--- a/drivers/staging/iio/meter/ade7753.h
+++ b/drivers/staging/iio/meter/ade7753.h
@@ -60,17 +60,15 @@
/**
* struct ade7753_state - device instance specific data
* @us: actual spi_device
- * @indio_dev: industrial I/O device structure
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct ade7753_state {
- struct spi_device *us;
- struct iio_dev *indio_dev;
- u8 *tx;
- u8 *rx;
- struct mutex buf_lock;
+ struct spi_device *us;
+ struct mutex buf_lock;
+ u8 tx[ADE7753_MAX_TX] ____cacheline_aligned;
+ u8 rx[ADE7753_MAX_RX];
};
#endif
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 378f2c8..33f0d32 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -17,6 +16,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -29,7 +29,7 @@ static int ade7754_spi_write_reg_8(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7754_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_WRITE_REG(reg_address);
@@ -47,7 +47,7 @@ static int ade7754_spi_write_reg_16(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7754_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7754_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int ade7754_spi_read_reg_8(struct device *dev,
u8 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7754_state *st = iio_priv(indio_dev);
int ret;
ret = spi_w8r8(st->us, ADE7754_READ_REG(reg_address));
@@ -83,7 +83,7 @@ static int ade7754_spi_read_reg_16(struct device *dev,
u16 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7754_state *st = iio_priv(indio_dev);
int ret;
ret = spi_w8r16(st->us, ADE7754_READ_REG(reg_address));
@@ -105,7 +105,7 @@ static int ade7754_spi_read_reg_24(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7754_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -388,10 +388,11 @@ static int ade7754_stop_device(struct device *dev)
return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
}
-static int ade7754_initial_setup(struct ade7754_state *st)
+static int ade7754_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
+ struct ade7754_state *st = iio_priv(indio_dev);
+ struct device *dev = &indio_dev->dev;
/* use low spi speed for init */
st->us->mode = SPI_MODE_3;
@@ -436,7 +437,7 @@ static ssize_t ade7754_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7754_state *st = iio_priv(indio_dev);
unsigned long val;
int ret;
u8 reg, t;
@@ -471,8 +472,8 @@ out:
return ret ? ret : len;
}
static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit);
-static IIO_CONST_ATTR(temp_offset, "129 C");
-static IIO_CONST_ATTR(temp_scale, "4 C");
+static IIO_CONST_ATTR(in_temp_offset, "129 C");
+static IIO_CONST_ATTR(in_temp_scale, "4 C");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ade7754_read_frequency,
@@ -483,9 +484,9 @@ static IIO_DEV_ATTR_RESET(ade7754_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000");
static struct attribute *ade7754_attributes[] = {
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
+ &iio_dev_attr_in_temp_raw.dev_attr.attr,
+ &iio_const_attr_in_temp_offset.dev_attr.attr,
+ &iio_const_attr_in_temp_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
@@ -534,63 +535,41 @@ static const struct iio_info ade7754_info = {
static int __devinit ade7754_probe(struct spi_device *spi)
{
- int ret, regdone = 0;
- struct ade7754_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
+ int ret;
+ struct ade7754_state *st;
+ struct iio_dev *indio_dev;
+
+ /* setup the industrialio driver allocated elements */
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
goto error_ret;
}
/* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADE7754_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADE7754_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
+ st = iio_priv(indio_dev);
st->us = spi;
mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
- st->indio_dev->name = spi->dev.driver->name;
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->info = &ade7754_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = spi->dev.driver->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &ade7754_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->indio_dev);
+ /* Get the device into a sane initial state */
+ ret = ade7754_initial_setup(indio_dev);
if (ret)
goto error_free_dev;
- regdone = 1;
-
- /* Get the device into a sane initial state */
- ret = ade7754_initial_setup(st);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_dev;
+
return 0;
error_free_dev:
- if (regdone)
- iio_device_unregister(st->indio_dev);
- else
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
+ iio_free_device(indio_dev);
+
error_ret:
return ret;
}
@@ -599,22 +578,18 @@ error_ret:
static int ade7754_remove(struct spi_device *spi)
{
int ret;
- struct ade7754_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ iio_device_unregister(indio_dev);
ret = ade7754_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
- iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
-
- return 0;
+ iio_free_device(indio_dev);
err_ret:
return ret;
+
}
static struct spi_driver ade7754_driver = {
diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h
index 0aa0522..6121125 100644
--- a/drivers/staging/iio/meter/ade7754.h
+++ b/drivers/staging/iio/meter/ade7754.h
@@ -78,17 +78,15 @@
/**
* struct ade7754_state - device instance specific data
* @us: actual spi_device
- * @indio_dev: industrial I/O device structure
+ * @buf_lock: mutex to protect tx and rx
* @tx: transmit buffer
* @rx: receive buffer
- * @buf_lock: mutex to protect tx and rx
**/
struct ade7754_state {
- struct spi_device *us;
- struct iio_dev *indio_dev;
- u8 *tx;
- u8 *rx;
- struct mutex buf_lock;
+ struct spi_device *us;
+ struct mutex buf_lock;
+ u8 tx[ADE7754_MAX_TX] ____cacheline_aligned;
+ u8 rx[ADE7754_MAX_RX];
};
#endif
diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h
index fd74e15..bdd1b05 100644
--- a/drivers/staging/iio/meter/ade7758.h
+++ b/drivers/staging/iio/meter/ade7758.h
@@ -122,7 +122,7 @@ struct ade7758_state {
u8 *tx;
u8 *rx;
struct mutex buf_lock;
- u32 available_scan_masks[AD7758_NUM_WAVESRC];
+ unsigned long available_scan_masks[AD7758_NUM_WAVESRC];
struct iio_chan_spec *ade7758_ring_channels;
struct spi_transfer ring_xfer[4];
struct spi_message ring_msg;
@@ -134,7 +134,7 @@ struct ade7758_state {
unsigned char tx_buf[8];
};
-#ifdef CONFIG_IIO_RING_BUFFER
+#ifdef CONFIG_IIO_BUFFER
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
@@ -150,8 +150,7 @@ ssize_t ade7758_read_data_from_ring(struct device *dev,
int ade7758_configure_ring(struct iio_dev *indio_dev);
void ade7758_unconfigure_ring(struct iio_dev *indio_dev);
-int ade7758_initialize_ring(struct iio_ring_buffer *ring);
-void ade7758_uninitialize_ring(struct iio_ring_buffer *ring);
+void ade7758_uninitialize_ring(struct iio_dev *indio_dev);
int ade7758_set_irq(struct device *dev, bool enable);
int ade7758_spi_write_reg_8(struct device *dev,
@@ -159,7 +158,7 @@ int ade7758_spi_write_reg_8(struct device *dev,
int ade7758_spi_read_reg_8(struct device *dev,
u8 reg_address, u8 *val);
-#else /* CONFIG_IIO_RING_BUFFER */
+#else /* CONFIG_IIO_BUFFER */
static inline void ade7758_remove_trigger(struct iio_dev *indio_dev)
{
@@ -180,9 +179,9 @@ static inline int ade7758_initialize_ring(struct iio_ring_buffer *ring)
{
return 0;
}
-static inline void ade7758_uninitialize_ring(struct iio_ring_buffer *ring)
+static inline void ade7758_uninitialize_ring(struct iio_dev *indio_dev)
{
}
-#endif /* CONFIG_IIO_RING_BUFFER */
+#endif /* CONFIG_IIO_BUFFER */
#endif
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 299b954..5a46d91 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -17,10 +16,11 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "../ring_generic.h"
+#include "../buffer_generic.h"
#include "meter.h"
#include "ade7758.h"
@@ -583,8 +583,8 @@ out:
}
static IIO_DEV_ATTR_TEMP_RAW(ade7758_read_8bit);
-static IIO_CONST_ATTR(temp_offset, "129 C");
-static IIO_CONST_ATTR(temp_scale, "4 C");
+static IIO_CONST_ATTR(in_temp_offset, "129 C");
+static IIO_CONST_ATTR(in_temp_scale, "4 C");
static IIO_DEV_ATTR_AWATTHR(ade7758_read_16bit,
ADE7758_AWATTHR);
@@ -614,9 +614,9 @@ static IIO_DEV_ATTR_RESET(ade7758_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255");
static struct attribute *ade7758_attributes[] = {
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
+ &iio_dev_attr_in_temp_raw.dev_attr.attr,
+ &iio_const_attr_in_temp_offset.dev_attr.attr,
+ &iio_const_attr_in_temp_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
@@ -662,63 +662,63 @@ static const struct attribute_group ade7758_attribute_group = {
};
static struct iio_chan_spec ade7758_channels[] = {
- IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 0, 0,
+ IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
0, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 0, 0,
+ IIO_CHAN(IIO_CURRENT, 0, 1, 0, NULL, 0, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
1, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 0, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent", 0, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
2, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 0, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "active", 0, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
3, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 0, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive", 0, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
4, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 1, 0,
+ IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
5, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 1, 0,
+ IIO_CHAN(IIO_CURRENT, 0, 1, 0, NULL, 1, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
6, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 1, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent", 1, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
7, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 1, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "active", 1, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
8, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 1, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive", 1, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
9, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 2, 0,
+ IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 2, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
10, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 2, 0,
+ IIO_CHAN(IIO_CURRENT, 0, 1, 0, NULL, 2, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
11, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 2, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent", 2, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
12, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 2, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "active", 2, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
13, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 2, 0,
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive", 2, 0,
(1 << IIO_CHAN_INFO_SCALE_SHARED),
AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
14, IIO_ST('s', 24, 32, 0), 0),
@@ -732,7 +732,7 @@ static const struct iio_info ade7758_info = {
static int __devinit ade7758_probe(struct spi_device *spi)
{
- int i, ret, regdone = 0;
+ int i, ret;
struct ade7758_state *st;
struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
@@ -766,7 +766,7 @@ static int __devinit ade7758_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
for (i = 0; i < AD7758_NUM_WAVESRC; i++)
- st->available_scan_masks[i] = 1 << i;
+ set_bit(i, &st->available_scan_masks[i]);
indio_dev->available_scan_masks = st->available_scan_masks;
@@ -774,14 +774,9 @@ static int __devinit ade7758_probe(struct spi_device *spi)
if (ret)
goto error_free_tx;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_unreg_ring_funcs;
- regdone = 1;
-
- ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
- &ade7758_channels[0],
- ARRAY_SIZE(ade7758_channels));
+ ret = iio_buffer_register(indio_dev,
+ &ade7758_channels[0],
+ ARRAY_SIZE(ade7758_channels));
if (ret) {
dev_err(&spi->dev, "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
@@ -795,16 +790,20 @@ static int __devinit ade7758_probe(struct spi_device *spi)
if (spi->irq) {
ret = ade7758_probe_trigger(indio_dev);
if (ret)
- goto error_remove_trigger;
+ goto error_uninitialize_ring;
}
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_remove_trigger;
+
return 0;
error_remove_trigger:
- if (indio_dev->modes & INDIO_RING_TRIGGERED)
+ if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
ade7758_remove_trigger(indio_dev);
error_uninitialize_ring:
- ade7758_uninitialize_ring(indio_dev->ring);
+ ade7758_uninitialize_ring(indio_dev);
error_unreg_ring_funcs:
ade7758_unconfigure_ring(indio_dev);
error_free_tx:
@@ -812,10 +811,7 @@ error_free_tx:
error_free_rx:
kfree(st->rx);
error_free_dev:
- if (regdone)
- iio_device_unregister(indio_dev);
- else
- iio_free_device(indio_dev);
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
@@ -826,18 +822,19 @@ static int ade7758_remove(struct spi_device *spi)
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
+ iio_device_unregister(indio_dev);
ret = ade7758_stop_device(&indio_dev->dev);
if (ret)
goto err_ret;
ade7758_remove_trigger(indio_dev);
- ade7758_uninitialize_ring(indio_dev->ring);
+ ade7758_uninitialize_ring(indio_dev);
ade7758_unconfigure_ring(indio_dev);
kfree(st->tx);
kfree(st->rx);
- iio_device_unregister(indio_dev);
- return 0;
+ iio_free_device(indio_dev);
+
err_ret:
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index b89b7f8..00fa2ac 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -5,24 +5,16 @@
*
* Licensed under the GPL-2.
*/
+#include <linux/export.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <asm/unaligned.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "../accel/accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "ade7758.h"
/**
@@ -69,8 +61,8 @@ out:
static irqreturn_t ade7758_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
- struct iio_ring_buffer *ring = indio_dev->ring;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct iio_buffer *ring = indio_dev->buffer;
struct ade7758_state *st = iio_priv(indio_dev);
s64 dat64[2];
u32 *dat32 = (u32 *)dat64;
@@ -100,14 +92,14 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
static int ade7758_ring_preenable(struct iio_dev *indio_dev)
{
struct ade7758_state *st = iio_priv(indio_dev);
- struct iio_ring_buffer *ring = indio_dev->ring;
+ struct iio_buffer *ring = indio_dev->buffer;
size_t d_size;
unsigned channel;
if (!ring->scan_count)
return -EINVAL;
- channel = __ffs(ring->scan_mask);
+ channel = find_first_bit(ring->scan_mask, indio_dev->masklength);
d_size = st->ade7758_ring_channels[channel].scan_type.storagebits / 8;
@@ -118,9 +110,9 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev)
d_size += sizeof(s64) - (d_size % sizeof(s64));
}
- if (indio_dev->ring->access->set_bytes_per_datum)
- indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
- d_size);
+ if (indio_dev->buffer->access->set_bytes_per_datum)
+ indio_dev->buffer->access->
+ set_bytes_per_datum(indio_dev->buffer, d_size);
ade7758_write_waveform_type(&indio_dev->dev,
st->ade7758_ring_channels[channel].address);
@@ -128,22 +120,16 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev)
return 0;
}
-static const struct iio_ring_setup_ops ade7758_ring_setup_ops = {
+static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = {
.preenable = &ade7758_ring_preenable,
- .postenable = &iio_triggered_ring_postenable,
- .predisable = &iio_triggered_ring_predisable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
};
void ade7758_unconfigure_ring(struct iio_dev *indio_dev)
{
- /* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->ring);
+ iio_sw_rb_free(indio_dev->buffer);
}
int ade7758_configure_ring(struct iio_dev *indio_dev)
@@ -151,16 +137,16 @@ int ade7758_configure_ring(struct iio_dev *indio_dev)
struct ade7758_state *st = iio_priv(indio_dev);
int ret = 0;
- indio_dev->ring = iio_sw_rb_allocate(indio_dev);
- if (!indio_dev->ring) {
+ indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ if (!indio_dev->buffer) {
ret = -ENOMEM;
return ret;
}
/* Effectively select the ring buffer implementation */
- indio_dev->ring->access = &ring_sw_access_funcs;
- indio_dev->ring->setup_ops = &ade7758_ring_setup_ops;
- indio_dev->ring->owner = THIS_MODULE;
+ indio_dev->buffer->access = &ring_sw_access_funcs;
+ indio_dev->buffer->setup_ops = &ade7758_ring_setup_ops;
+ indio_dev->buffer->owner = THIS_MODULE;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&ade7758_trigger_handler,
@@ -173,7 +159,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev)
goto error_iio_sw_rb_free;
}
- indio_dev->modes |= INDIO_RING_TRIGGERED;
+ indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS);
st->tx_buf[1] = 0;
@@ -211,11 +197,11 @@ int ade7758_configure_ring(struct iio_dev *indio_dev)
return 0;
error_iio_sw_rb_free:
- iio_sw_rb_free(indio_dev->ring);
+ iio_sw_rb_free(indio_dev->buffer);
return ret;
}
-void ade7758_uninitialize_ring(struct iio_ring_buffer *ring)
+void ade7758_uninitialize_ring(struct iio_dev *indio_dev)
{
- iio_ring_buffer_unregister(ring);
+ iio_buffer_unregister(indio_dev);
}
diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c
index a5c3248..b6569c7 100644
--- a/drivers/staging/iio/meter/ade7758_trigger.c
+++ b/drivers/staging/iio/meter/ade7758_trigger.c
@@ -7,16 +7,11 @@
*/
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
+#include <linux/export.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../trigger.h"
#include "ade7758.h"
@@ -57,6 +52,12 @@ static int ade7758_trig_try_reen(struct iio_trigger *trig)
return 0;
}
+static const struct iio_trigger_ops ade7758_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &ade7758_data_rdy_trigger_set_state,
+ .try_reenable = &ade7758_trig_try_reen,
+};
+
int ade7758_probe_trigger(struct iio_dev *indio_dev)
{
struct ade7758_state *st = iio_priv(indio_dev);
@@ -79,10 +80,8 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &ade7758_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &ade7758_data_rdy_trigger_set_state;
- st->trig->try_reenable = &ade7758_trig_try_reen;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index 730f6d9..b691f10 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -17,6 +16,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -29,7 +29,7 @@ static int ade7759_spi_write_reg_8(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7759_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7759_WRITE_REG(reg_address);
@@ -47,7 +47,7 @@ static int ade7759_spi_write_reg_16(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7759_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7759_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int ade7759_spi_read_reg_8(struct device *dev,
u8 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7759_state *st = iio_priv(indio_dev);
int ret;
ret = spi_w8r8(st->us, ADE7759_READ_REG(reg_address));
@@ -83,7 +83,7 @@ static int ade7759_spi_read_reg_16(struct device *dev,
u16 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7759_state *st = iio_priv(indio_dev);
int ret;
ret = spi_w8r16(st->us, ADE7759_READ_REG(reg_address));
@@ -105,7 +105,7 @@ static int ade7759_spi_read_reg_40(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7759_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -328,10 +328,11 @@ static int ade7759_stop_device(struct device *dev)
return ade7759_spi_write_reg_16(dev, ADE7759_MODE, val);
}
-static int ade7759_initial_setup(struct ade7759_state *st)
+static int ade7759_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
+ struct ade7759_state *st = iio_priv(indio_dev);
+ struct device *dev = &indio_dev->dev;
/* use low spi speed for init */
st->us->mode = SPI_MODE_3;
@@ -376,7 +377,7 @@ static ssize_t ade7759_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7759_state *st = iio_priv(indio_dev);
unsigned long val;
int ret;
u16 reg, t;
@@ -411,8 +412,8 @@ out:
return ret ? ret : len;
}
static IIO_DEV_ATTR_TEMP_RAW(ade7759_read_8bit);
-static IIO_CONST_ATTR(temp_offset, "70 C");
-static IIO_CONST_ATTR(temp_scale, "1 C");
+static IIO_CONST_ATTR(in_temp_offset, "70 C");
+static IIO_CONST_ATTR(in_temp_scale, "1 C");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ade7759_read_frequency,
@@ -423,9 +424,9 @@ static IIO_DEV_ATTR_RESET(ade7759_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
static struct attribute *ade7759_attributes[] = {
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
+ &iio_dev_attr_in_temp_raw.dev_attr.attr,
+ &iio_const_attr_in_temp_offset.dev_attr.attr,
+ &iio_const_attr_in_temp_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
@@ -458,62 +459,39 @@ static const struct iio_info ade7759_info = {
static int __devinit ade7759_probe(struct spi_device *spi)
{
int ret;
- struct ade7759_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
+ struct ade7759_state *st;
+ struct iio_dev *indio_dev;
+
+ /* setup the industrialio driver allocated elements */
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
goto error_ret;
}
/* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADE7759_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADE7759_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
+ st = iio_priv(indio_dev);
st->us = spi;
mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
-
- st->indio_dev->name = spi->dev.driver->name;
- st->indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi->dev.driver->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &ade7759_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- st->indio_dev->info = &ade7759_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = iio_device_register(st->indio_dev);
+ /* Get the device into a sane initial state */
+ ret = ade7759_initial_setup(indio_dev);
if (ret)
goto error_free_dev;
- /* Get the device into a sane initial state */
- ret = ade7759_initial_setup(st);
+ ret = iio_device_register(indio_dev);
if (ret)
- goto error_unreg_dev;
- return 0;
+ goto error_free_dev;
+ return 0;
-error_unreg_dev:
- iio_device_unregister(st->indio_dev);
error_free_dev:
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
@@ -522,19 +500,14 @@ error_ret:
static int ade7759_remove(struct spi_device *spi)
{
int ret;
- struct ade7759_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ iio_device_unregister(indio_dev);
ret = ade7759_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
- iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
-
- return 0;
+ iio_free_device(indio_dev);
err_ret:
return ret;
diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h
index cc76c2c..c81d23d 100644
--- a/drivers/staging/iio/meter/ade7759.h
+++ b/drivers/staging/iio/meter/ade7759.h
@@ -41,17 +41,15 @@
/**
* struct ade7759_state - device instance specific data
* @us: actual spi_device
- * @indio_dev: industrial I/O device structure
+ * @buf_lock: mutex to protect tx and rx
* @tx: transmit buffer
* @rx: receive buffer
- * @buf_lock: mutex to protect tx and rx
**/
struct ade7759_state {
- struct spi_device *us;
- struct iio_dev *indio_dev;
- u8 *tx;
- u8 *rx;
- struct mutex buf_lock;
+ struct spi_device *us;
+ struct mutex buf_lock;
+ u8 tx[ADE7759_MAX_TX] ____cacheline_aligned;
+ u8 rx[ADE7759_MAX_RX];
};
#endif
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index 4578e7b..cbca3fd 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#include "ade7854.h"
@@ -20,7 +21,7 @@ static int ade7854_i2c_write_reg_8(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -39,7 +40,7 @@ static int ade7854_i2c_write_reg_16(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -59,7 +60,7 @@ static int ade7854_i2c_write_reg_24(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -80,7 +81,7 @@ static int ade7854_i2c_write_reg_32(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -101,7 +102,7 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
u8 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->buf_lock);
@@ -127,7 +128,7 @@ static int ade7854_i2c_read_reg_16(struct device *dev,
u16 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->buf_lock);
@@ -153,7 +154,7 @@ static int ade7854_i2c_read_reg_24(struct device *dev,
u32 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->buf_lock);
@@ -179,7 +180,7 @@ static int ade7854_i2c_read_reg_32(struct device *dev,
u32 *val)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->buf_lock);
@@ -204,13 +205,14 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
- struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
- return ret;
- }
-
- i2c_set_clientdata(client, st);
+ struct ade7854_state *st;
+ struct iio_dev *indio_dev;
+
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+ st = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
st->read_reg_8 = ade7854_i2c_read_reg_8;
st->read_reg_16 = ade7854_i2c_read_reg_16;
st->read_reg_24 = ade7854_i2c_read_reg_24;
@@ -222,11 +224,9 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
st->i2c = client;
st->irq = client->irq;
- ret = ade7854_probe(st, &client->dev);
- if (ret) {
- kfree(st);
- return ret;
- }
+ ret = ade7854_probe(indio_dev, &client->dev);
+ if (ret)
+ iio_free_device(indio_dev);
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 84da8fb..cfa23ba 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#include "ade7854.h"
@@ -21,7 +22,7 @@ static int ade7854_spi_write_reg_8(struct device *dev,
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
.bits_per_word = 8,
@@ -49,7 +50,7 @@ static int ade7854_spi_write_reg_16(struct device *dev,
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
.bits_per_word = 8,
@@ -78,7 +79,7 @@ static int ade7854_spi_write_reg_24(struct device *dev,
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
.bits_per_word = 8,
@@ -108,7 +109,7 @@ static int ade7854_spi_write_reg_32(struct device *dev,
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
.bits_per_word = 8,
@@ -138,7 +139,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -180,7 +181,7 @@ static int ade7854_spi_read_reg_16(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -221,7 +222,7 @@ static int ade7854_spi_read_reg_24(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -263,7 +264,7 @@ static int ade7854_spi_read_reg_32(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -302,13 +303,14 @@ error_ret:
static int __devinit ade7854_spi_probe(struct spi_device *spi)
{
int ret;
- struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
- return ret;
- }
-
- spi_set_drvdata(spi, st);
+ struct ade7854_state *st;
+ struct iio_dev *indio_dev;
+
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+ st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
st->read_reg_8 = ade7854_spi_read_reg_8;
st->read_reg_16 = ade7854_spi_read_reg_16;
st->read_reg_24 = ade7854_spi_read_reg_24;
@@ -320,11 +322,10 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi)
st->irq = spi->irq;
st->spi = spi;
- ret = ade7854_probe(st, &spi->dev);
- if (ret) {
- kfree(st);
- return ret;
- }
+
+ ret = ade7854_probe(indio_dev, &spi->dev);
+ if (ret)
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index 44cd3ec..49c01c5 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -16,6 +15,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -29,7 +29,7 @@ static ssize_t ade7854_read_8bit(struct device *dev,
int ret;
u8 val = 0;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = st->read_reg_8(dev, this_attr->address, &val);
@@ -46,7 +46,7 @@ static ssize_t ade7854_read_16bit(struct device *dev,
int ret;
u16 val = 0;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = st->read_reg_16(dev, this_attr->address, &val);
@@ -63,7 +63,7 @@ static ssize_t ade7854_read_24bit(struct device *dev,
int ret;
u32 val;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = st->read_reg_24(dev, this_attr->address, &val);
@@ -81,7 +81,7 @@ static ssize_t ade7854_read_32bit(struct device *dev,
u32 val = 0;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
ret = st->read_reg_32(dev, this_attr->address, &val);
if (ret)
@@ -97,7 +97,7 @@ static ssize_t ade7854_write_8bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
long val;
@@ -118,7 +118,7 @@ static ssize_t ade7854_write_16bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
long val;
@@ -139,7 +139,7 @@ static ssize_t ade7854_write_24bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
long val;
@@ -160,7 +160,7 @@ static ssize_t ade7854_write_32bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
long val;
@@ -177,7 +177,7 @@ error_ret:
static int ade7854_reset(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
u16 val;
st->read_reg_16(dev, ADE7854_CONFIG, &val);
@@ -426,7 +426,7 @@ static IIO_DEV_ATTR_CVAHR(ade7854_read_32bit,
static int ade7854_set_irq(struct device *dev, bool enable)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7854_state *st = iio_priv(indio_dev);
int ret;
u32 irqen;
@@ -449,10 +449,10 @@ error_ret:
return ret;
}
-static int ade7854_initial_setup(struct ade7854_state *st)
+static int ade7854_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
+ struct device *dev = &indio_dev->dev;
/* Disable IRQ */
ret = ade7854_set_irq(dev, false);
@@ -556,68 +556,41 @@ static const struct iio_info ade7854_info = {
.driver_module = THIS_MODULE,
};
-int ade7854_probe(struct ade7854_state *st, struct device *dev)
+int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
{
int ret;
-
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADE7854_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADE7854_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
- mutex_init(&st->buf_lock);
+ struct ade7854_state *st = iio_priv(indio_dev);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device(0);
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
+ mutex_init(&st->buf_lock);
- st->indio_dev->dev.parent = dev;
- st->indio_dev->info = &ade7854_info;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->dev.parent = dev;
+ indio_dev->info = &ade7854_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_dev;
/* Get the device into a sane initial state */
- ret = ade7854_initial_setup(st);
+ ret = ade7854_initial_setup(indio_dev);
if (ret)
goto error_unreg_dev;
return 0;
error_unreg_dev:
- iio_device_unregister(st->indio_dev);
+ iio_device_unregister(indio_dev);
error_free_dev:
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
+ iio_free_device(indio_dev);
return ret;
}
EXPORT_SYMBOL(ade7854_probe);
-int ade7854_remove(struct ade7854_state *st)
+int ade7854_remove(struct iio_dev *indio_dev)
{
- struct iio_dev *indio_dev = st->indio_dev;
-
iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
+ iio_free_device(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h
index 79a2110..2c96e86 100644
--- a/drivers/staging/iio/meter/ade7854.h
+++ b/drivers/staging/iio/meter/ade7854.h
@@ -148,29 +148,29 @@
* struct ade7854_state - device instance specific data
* @spi: actual spi_device
* @indio_dev: industrial I/O device structure
+ * @buf_lock: mutex to protect tx and rx
* @tx: transmit buffer
* @rx: receive buffer
- * @buf_lock: mutex to protect tx and rx
**/
struct ade7854_state {
- struct spi_device *spi;
- struct i2c_client *i2c;
- struct iio_dev *indio_dev;
- u8 *tx;
- u8 *rx;
- int (*read_reg_8) (struct device *, u16, u8 *);
- int (*read_reg_16) (struct device *, u16, u16 *);
- int (*read_reg_24) (struct device *, u16, u32 *);
- int (*read_reg_32) (struct device *, u16, u32 *);
- int (*write_reg_8) (struct device *, u16, u8);
- int (*write_reg_16) (struct device *, u16, u16);
- int (*write_reg_24) (struct device *, u16, u32);
- int (*write_reg_32) (struct device *, u16, u32);
- int irq;
- struct mutex buf_lock;
+ struct spi_device *spi;
+ struct i2c_client *i2c;
+ int (*read_reg_8) (struct device *, u16, u8 *);
+ int (*read_reg_16) (struct device *, u16, u16 *);
+ int (*read_reg_24) (struct device *, u16, u32 *);
+ int (*read_reg_32) (struct device *, u16, u32 *);
+ int (*write_reg_8) (struct device *, u16, u8);
+ int (*write_reg_16) (struct device *, u16, u16);
+ int (*write_reg_24) (struct device *, u16, u32);
+ int (*write_reg_32) (struct device *, u16, u32);
+ int irq;
+ struct mutex buf_lock;
+ u8 tx[ADE7854_MAX_TX] ____cacheline_aligned;
+ u8 rx[ADE7854_MAX_RX];
+
};
-extern int ade7854_probe(struct ade7854_state *st, struct device *dev);
-extern int ade7854_remove(struct ade7854_state *st);
+extern int ade7854_probe(struct iio_dev *indio_dev, struct device *dev);
+extern int ade7854_remove(struct iio_dev *indio_dev);
#endif
diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
index c0c144a..ff9aaec 100644
--- a/drivers/staging/intel_sst/intel_sst.c
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -37,6 +37,7 @@
#include <linux/firmware.h>
#include <linux/miscdevice.h>
#include <linux/pm_runtime.h>
+#include <linux/module.h>
#include <asm/mrst.h>
#include "intel_sst.h"
#include "intel_sst_ioctl.h"
@@ -321,7 +322,7 @@ static int __devinit intel_sst_probe(struct pci_dev *pci,
if (ret) {
pr_err("couldn't register LPE device\n");
goto do_free_misc;
- }
+ }
} else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
u32 csr;
@@ -524,9 +525,11 @@ int intel_sst_resume(struct pci_dev *pci)
return 0;
}
-/* The runtime_suspend/resume is pretty much similar to the legacy suspend/resume with the noted exception below:
- * The PCI core takes care of taking the system through D3hot and restoring it back to D0 and so there is
- * no need to duplicate that here.
+/* The runtime_suspend/resume is pretty much similar to the legacy
+ * suspend/resume with the noted exception below:
+ * The PCI core takes care of taking the system through D3hot and
+ * restoring it back to D0 and so there is no need to duplicate
+ * that here.
*/
static int intel_sst_runtime_suspend(struct device *dev)
{
@@ -545,7 +548,10 @@ static int intel_sst_runtime_suspend(struct device *dev)
/* Move the SST state to Suspended */
mutex_lock(&sst_drv_ctx->sst_lock);
sst_drv_ctx->sst_state = SST_SUSPENDED;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
+
+ /* Only needed by Medfield */
+ if (sst_drv_ctx->pci_id != SST_MRST_PCI_ID)
+ sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
mutex_unlock(&sst_drv_ctx->sst_lock);
return 0;
}
diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c
index b8c7ddb..93b41a2 100644
--- a/drivers/staging/intel_sst/intel_sst_app_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_app_interface.c
@@ -430,8 +430,10 @@ static int snd_sst_fill_kernel_list(struct stream_info *stream,
return -ENOMEM;
if (copy_from_user((void *) &rar_handle,
iovec[index].iov_base,
- sizeof(__u32)))
+ sizeof(__u32))) {
+ kfree(stream_bufs);
return -EFAULT;
+ }
stream_bufs->addr = (char *)rar_handle;
stream_bufs->in_use = false;
stream_bufs->size = iovec[0].iov_len;
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
index f8e9da6..870981b 100644
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -420,6 +420,8 @@ struct intel_sst_drv {
unsigned int max_streams;
unsigned int *fw_cntx;
unsigned int fw_cntx_size;
+
+ unsigned int fw_downloaded;
};
extern struct intel_sst_drv *sst_drv_ctx;
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
index 1021477..22bd29c 100644
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -33,6 +33,7 @@
#include <linux/fs.h>
#include <linux/firmware.h>
#include <linux/pm_runtime.h>
+#include <linux/export.h>
#include "intel_sst.h"
#include "intel_sst_ioctl.h"
#include "intel_sst_fw_ipc.h"
@@ -53,6 +54,13 @@ int sst_download_fw(void)
if (sst_drv_ctx->sst_state != SST_UN_INIT)
return -EPERM;
+ /* Reload firmware is not needed for MRST */
+ if ( (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) && sst_drv_ctx->fw_downloaded) {
+ pr_debug("FW already downloaded, skip for MRST platform\n");
+ sst_drv_ctx->sst_state = SST_FW_RUNNING;
+ return 0;
+ }
+
snprintf(name, sizeof(name), "%s%04x%s", "fw_sst_",
sst_drv_ctx->pci_id, ".bin");
@@ -71,6 +79,9 @@ int sst_download_fw(void)
retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]);
if (retval)
pr_err("fw download failed %d\n" , retval);
+ else
+ sst_drv_ctx->fw_downloaded = 1;
+
end_restore:
release_firmware(fw_sst);
sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT;
diff --git a/drivers/staging/intel_sst/intel_sst_dsp.c b/drivers/staging/intel_sst/intel_sst_dsp.c
index a89e1ad..426d2b9 100644
--- a/drivers/staging/intel_sst/intel_sst_dsp.c
+++ b/drivers/staging/intel_sst/intel_sst_dsp.c
@@ -104,7 +104,7 @@ static int sst_start_mrst(void)
/**
* sst_start_medfield - Start the SST DSP processor
*
- * This starts the DSP in MRST platfroms
+ * This starts the DSP in Medfield platfroms
*/
static int sst_start_medfield(void)
{
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index 25656ad..492b660 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -27,6 +27,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/platform_device.h>
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 000378a..46ab55e 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -1090,7 +1090,7 @@ static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
if (intsts & 0x1) {
pr_debug("SST DBG:MAD headset detected\n");
/* send headset detect/undetect */
- present = (value == 0x1) ? 1 : 0;
+ present = (value == 0x1) ? 3 : 0;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADSET;
hp_automute(SND_JACK_HEADSET, present);
diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c
index 61db1f9..8e73983 100644
--- a/drivers/staging/line6/audio.c
+++ b/drivers/staging/line6/audio.c
@@ -11,6 +11,7 @@
#include <sound/core.h>
#include <sound/initval.h>
+#include <linux/export.h>
#include "driver.h"
#include "audio.h"
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
index 9d4c8a6..955c6de 100644
--- a/drivers/staging/line6/pcm.c
+++ b/drivers/staging/line6/pcm.c
@@ -88,10 +88,13 @@ static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
{
- unsigned long flags_old =
- __sync_fetch_and_or(&line6pcm->flags, channels);
- unsigned long flags_new = flags_old | channels;
- int err = 0;
+ unsigned long flags_old, flags_new;
+ int err;
+
+ do {
+ flags_old = ACCESS_ONCE(line6pcm->flags);
+ flags_new = flags_old | channels;
+ } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
#if LINE6_BACKUP_MONITOR_SIGNAL
if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) {
@@ -133,10 +136,8 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
line6pcm->prev_fsize = 0;
err = line6_submit_audio_in_all_urbs(line6pcm);
- if (err < 0) {
- __sync_fetch_and_and(&line6pcm->flags, ~channels);
- return err;
- }
+ if (err < 0)
+ goto fail;
}
if (((flags_old & MASK_PLAYBACK) == 0) &&
@@ -160,20 +161,29 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
line6pcm->count_out = 0;
err = line6_submit_audio_out_all_urbs(line6pcm);
- if (err < 0) {
- __sync_fetch_and_and(&line6pcm->flags, ~channels);
- return err;
- }
+ if (err < 0)
+ goto fail;
}
return 0;
+
+fail:
+ do {
+ flags_old = ACCESS_ONCE(line6pcm->flags);
+ flags_new = flags_old & ~channels;
+ } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
+
+ return err;
}
int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
{
- unsigned long flags_old =
- __sync_fetch_and_and(&line6pcm->flags, ~channels);
- unsigned long flags_new = flags_old & ~channels;
+ unsigned long flags_old, flags_new;
+
+ do {
+ flags_old = ACCESS_ONCE(line6pcm->flags);
+ flags_new = flags_old & ~channels;
+ } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
if (((flags_old & MASK_CAPTURE) != 0) &&
((flags_new & MASK_CAPTURE) == 0)) {
@@ -360,8 +370,11 @@ static int snd_line6_pcm_free(struct snd_device *device)
*/
static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
{
- if (substream->runtime && snd_pcm_running(substream))
+ if (substream->runtime && snd_pcm_running(substream)) {
+ snd_pcm_stream_lock_irq(substream);
snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+ snd_pcm_stream_unlock_irq(substream);
+ }
}
/*
diff --git a/drivers/staging/mei/Kconfig b/drivers/staging/mei/Kconfig
index 3f3f170..47d78a7 100644
--- a/drivers/staging/mei/Kconfig
+++ b/drivers/staging/mei/Kconfig
@@ -1,6 +1,6 @@
config INTEL_MEI
tristate "Intel Management Engine Interface (Intel MEI)"
- depends on X86 && PCI && EXPERIMENTAL
+ depends on X86 && PCI && EXPERIMENTAL && WATCHDOG_CORE
help
The Intel Management Engine (Intel ME) provides Manageability,
Security and Media services for system containing Intel chipsets.
diff --git a/drivers/staging/mei/TODO b/drivers/staging/mei/TODO
index 3b6a667..7d9a13b 100644
--- a/drivers/staging/mei/TODO
+++ b/drivers/staging/mei/TODO
@@ -1,14 +1,4 @@
TODO:
- - Create in-kernel Client API. Examples of in-kernel clients are watchdog and AMTHI.
- - ME Watchdog Driver to expose standard Linux watchdog interface
- - Rewrite AMTHI to use in-kernel client interface
- - Cleanup init and probe functions
- - Review BUG/BUG_ON usage
- - Cleanup and reorganize header files
- - Rewrite client data structure
- - Make state machine more readable
- - Add mei.txt with driver explanation and it's driver
- - Fix Kconfig
- Cleanup and split the timer function
Upon Unstaging:
- move mei.h to include/linux/mei.h
diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c
index 685fcf6..a78e63b 100644
--- a/drivers/staging/mei/init.c
+++ b/drivers/staging/mei/init.c
@@ -29,54 +29,29 @@ const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
0x81, 0x4c);
/**
- * mei_initialize_list - Sets up a queue list.
+ * mei_io_list_init - Sets up a queue list.
*
- * @list: An instance of our list structure
+ * @list: An instance io list structure
* @dev: the device structure
*/
-void mei_initialize_list(struct mei_io_list *list, struct mei_device *dev)
+void mei_io_list_init(struct mei_io_list *list)
{
/* initialize our queue list */
INIT_LIST_HEAD(&list->mei_cb.cb_list);
list->status = 0;
- list->device_extension = dev;
}
/**
- * mei_flush_queues - flushes queue lists belonging to cl.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- */
-void mei_flush_queues(struct mei_device *dev, struct mei_cl *cl)
-{
- int i;
-
- if (!dev || !cl)
- return;
-
- for (i = 0; i < MEI_IO_LISTS_NUMBER; i++) {
- dev_dbg(&dev->pdev->dev, "remove list entry belonging to cl\n");
- mei_flush_list(dev->io_list_array[i], cl);
- }
-}
-
-
-/**
- * mei_flush_list - removes list entry belonging to cl.
+ * mei_io_list_flush - removes list entry belonging to cl.
*
* @list: An instance of our list structure
* @cl: private data of the file object
*/
-void mei_flush_list(struct mei_io_list *list, struct mei_cl *cl)
+void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
{
- struct mei_cl *cl_tmp;
struct mei_cl_cb *cb_pos = NULL;
struct mei_cl_cb *cb_next = NULL;
- if (!list || !cl)
- return;
-
if (list->status != 0)
return;
@@ -86,14 +61,36 @@ void mei_flush_list(struct mei_io_list *list, struct mei_cl *cl)
list_for_each_entry_safe(cb_pos, cb_next,
&list->mei_cb.cb_list, cb_list) {
if (cb_pos) {
- cl_tmp = (struct mei_cl *)
- cb_pos->file_private;
- if (cl_tmp &&
- mei_fe_same_id(cl, cl_tmp))
+ struct mei_cl *cl_tmp;
+ cl_tmp = (struct mei_cl *)cb_pos->file_private;
+ if (mei_cl_cmp_id(cl, cl_tmp))
list_del(&cb_pos->cb_list);
}
}
}
+/**
+ * mei_cl_flush_queues - flushes queue lists belonging to cl.
+ *
+ * @dev: the device structure
+ * @cl: private data of the file object
+ */
+int mei_cl_flush_queues(struct mei_cl *cl)
+{
+ if (!cl || !cl->dev)
+ return -EINVAL;
+
+ dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
+ mei_io_list_flush(&cl->dev->read_list, cl);
+ mei_io_list_flush(&cl->dev->write_list, cl);
+ mei_io_list_flush(&cl->dev->write_waiting_list, cl);
+ mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
+ mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
+ mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
+ mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
+ return 0;
+}
+
+
/**
* mei_reset_iamthif_params - initializes mei device iamthif
@@ -106,8 +103,8 @@ static void mei_reset_iamthif_params(struct mei_device *dev)
dev->iamthif_current_cb = NULL;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = 0;
- dev->iamthif_ioctl = 0;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = false;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
}
@@ -119,9 +116,8 @@ static void mei_reset_iamthif_params(struct mei_device *dev)
*
* returns The mei_device_device pointer on success, NULL on failure.
*/
-struct mei_device *init_mei_device(struct pci_dev *pdev)
+struct mei_device *mei_device_init(struct pci_dev *pdev)
{
- int i;
struct mei_device *dev;
dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
@@ -129,13 +125,6 @@ struct mei_device *init_mei_device(struct pci_dev *pdev)
return NULL;
/* setup our list array */
- dev->io_list_array[0] = &dev->read_list;
- dev->io_list_array[1] = &dev->write_list;
- dev->io_list_array[2] = &dev->write_waiting_list;
- dev->io_list_array[3] = &dev->ctrl_wr_list;
- dev->io_list_array[4] = &dev->ctrl_rd_list;
- dev->io_list_array[5] = &dev->amthi_cmd_list;
- dev->io_list_array[6] = &dev->amthi_read_complete_list;
INIT_LIST_HEAD(&dev->file_list);
INIT_LIST_HEAD(&dev->wd_cl.link);
INIT_LIST_HEAD(&dev->iamthif_cl.link);
@@ -143,9 +132,18 @@ struct mei_device *init_mei_device(struct pci_dev *pdev)
init_waitqueue_head(&dev->wait_recvd_msg);
init_waitqueue_head(&dev->wait_stop_wd);
dev->mei_state = MEI_INITIALIZING;
+ dev->reset_count = 0;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
- for (i = 0; i < MEI_IO_LISTS_NUMBER; i++)
- mei_initialize_list(dev->io_list_array[i], dev);
+ dev->wd_interface_reg = false;
+
+
+ mei_io_list_init(&dev->read_list);
+ mei_io_list_init(&dev->write_list);
+ mei_io_list_init(&dev->write_waiting_list);
+ mei_io_list_init(&dev->ctrl_wr_list);
+ mei_io_list_init(&dev->ctrl_rd_list);
+ mei_io_list_init(&dev->amthi_cmd_list);
+ mei_io_list_init(&dev->amthi_read_complete_list);
dev->pdev = pdev;
return dev;
}
@@ -173,7 +171,7 @@ int mei_hw_init(struct mei_device *dev)
if ((dev->host_hw_state & H_IS) == H_IS)
mei_reg_write(dev, H_CSR, dev->host_hw_state);
- dev->recvd_msg = 0;
+ dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
mei_reset(dev, 1);
@@ -223,7 +221,7 @@ int mei_hw_init(struct mei_device *dev)
goto out;
}
- dev->recvd_msg = 0;
+ dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
dev->host_hw_state, dev->me_hw_state);
dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n");
@@ -267,7 +265,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
bool unexpected;
if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
- dev->need_reset = 1;
+ dev->need_reset = true;
return;
}
@@ -291,7 +289,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n",
dev->host_hw_state);
- dev->need_reset = 0;
+ dev->need_reset = false;
+
+ dev->reset_count++;
+ if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
+ dev_err(&dev->pdev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
+ dev->mei_state = MEI_DISABLED;
+ return;
+ }
+
if (dev->mei_state != MEI_INITIALIZING) {
if (dev->mei_state != MEI_DISABLED &&
@@ -318,10 +324,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->extra_write_index = 0;
}
- dev->num_mei_me_clients = 0;
+ dev->me_clients_num = 0;
dev->rd_msg_hdr = 0;
- dev->stop = 0;
- dev->wd_pending = 0;
+ dev->stop = false;
+ dev->wd_pending = false;
/* update the state of the registers after reset */
dev->host_hw_state = mei_hcsr_read(dev);
@@ -363,7 +369,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
*
* returns none.
*/
-void host_start_message(struct mei_device *dev)
+void mei_host_start_message(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_host_version_request *host_start_req;
@@ -382,7 +388,7 @@ void host_start_message(struct mei_device *dev)
host_start_req->cmd.cmd = HOST_START_REQ_CMD;
host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
- dev->recvd_msg = 0;
+ dev->recvd_msg = false;
if (!mei_write_message(dev, mei_hdr,
(unsigned char *) (host_start_req),
mei_hdr->length)) {
@@ -402,7 +408,7 @@ void host_start_message(struct mei_device *dev)
*
* returns none.
*/
-void host_enum_clients_message(struct mei_device *dev)
+void mei_host_enum_clients_message(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_host_enum_request *host_enum_req;
@@ -437,16 +443,16 @@ void host_enum_clients_message(struct mei_device *dev)
*
* returns none.
*/
-void allocate_me_clients_storage(struct mei_device *dev)
+void mei_allocate_me_clients_storage(struct mei_device *dev)
{
struct mei_me_client *clients;
int b;
/* count how many ME clients we have */
for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
- dev->num_mei_me_clients++;
+ dev->me_clients_num++;
- if (dev->num_mei_me_clients <= 0)
+ if (dev->me_clients_num <= 0)
return ;
@@ -455,9 +461,9 @@ void allocate_me_clients_storage(struct mei_device *dev)
dev->me_clients = NULL;
}
dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
- dev->num_mei_me_clients * sizeof(struct mei_me_client));
+ dev->me_clients_num * sizeof(struct mei_me_client));
/* allocate storage for ME clients representation */
- clients = kcalloc(dev->num_mei_me_clients,
+ clients = kcalloc(dev->me_clients_num,
sizeof(struct mei_me_client), GFP_KERNEL);
if (!clients) {
dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
@@ -473,9 +479,12 @@ void allocate_me_clients_storage(struct mei_device *dev)
*
* @dev: the device structure
*
- * returns none.
+ * returns:
+ * < 0 - Error.
+ * = 0 - no more clients.
+ * = 1 - still have clients to send properties request.
*/
-void host_client_properties(struct mei_device *dev)
+int mei_host_client_properties(struct mei_device *dev)
{
struct mei_msg_hdr *mei_header;
struct hbm_props_request *host_cli_req;
@@ -507,27 +516,15 @@ void host_client_properties(struct mei_device *dev)
dev->mei_state = MEI_RESETING;
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
mei_reset(dev, 1);
- return;
+ return -EIO;
}
dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
dev->me_client_index = b;
- return;
+ return 1;
}
-
- /*
- * Clear Map for indicating now ME clients
- * with associated host client
- */
- bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
- dev->write_hang = -1;
- dev->open_handle_count = 0;
- bitmap_set(dev->host_clients_map, 0, 3);
- dev->mei_state = MEI_ENABLED;
-
- mei_wd_host_init(dev);
- return;
+ return 0;
}
/**
@@ -536,7 +533,7 @@ void host_client_properties(struct mei_device *dev)
* @priv: private file structure to be initialized
* @file: the file structure
*/
-void mei_init_file_private(struct mei_cl *priv, struct mei_device *dev)
+void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
{
memset(priv, 0, sizeof(struct mei_cl));
init_waitqueue_head(&priv->wait);
@@ -552,7 +549,7 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
{
int i, res = -1;
- for (i = 0; i < dev->num_mei_me_clients; ++i)
+ for (i = 0; i < dev->me_clients_num; ++i)
if (uuid_le_cmp(cuuid,
dev->me_clients[i].props.protocol_name) == 0) {
res = i;
@@ -601,12 +598,12 @@ u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
* @dev: the device structure
*
*/
-void host_init_iamthif(struct mei_device *dev)
+void mei_host_init_iamthif(struct mei_device *dev)
{
u8 i;
unsigned char *msg_buf;
- mei_init_file_private(&dev->iamthif_cl, dev);
+ mei_cl_init(&dev->iamthif_cl, dev);
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
/* find ME amthi client */
@@ -656,17 +653,17 @@ void host_init_iamthif(struct mei_device *dev)
*
* returns The allocated file or NULL on failure
*/
-struct mei_cl *mei_alloc_file_private(struct mei_device *dev)
+struct mei_cl *mei_cl_allocate(struct mei_device *dev)
{
- struct mei_cl *priv;
+ struct mei_cl *cl;
- priv = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
- if (!priv)
+ cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
+ if (!cl)
return NULL;
- mei_init_file_private(priv, dev);
+ mei_cl_init(cl, dev);
- return priv;
+ return cl;
}
@@ -701,7 +698,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
cb->file_private = cl;
cb->major_file_operations = MEI_CLOSE;
if (dev->mei_host_buffer_is_empty) {
- dev->mei_host_buffer_is_empty = 0;
+ dev->mei_host_buffer_is_empty = false;
if (mei_disconnect(dev, cl)) {
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->cb_list,
@@ -739,8 +736,8 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
}
- mei_flush_list(&dev->ctrl_rd_list, cl);
- mei_flush_list(&dev->ctrl_wr_list, cl);
+ mei_io_list_flush(&dev->ctrl_rd_list, cl);
+ mei_io_list_flush(&dev->ctrl_wr_list, cl);
free:
mei_free_cb_private(cb);
return rets;
diff --git a/drivers/staging/mei/interface.c b/drivers/staging/mei/interface.c
index 4959aae..a65dacf 100644
--- a/drivers/staging/mei/interface.c
+++ b/drivers/staging/mei/interface.c
@@ -179,7 +179,6 @@ int mei_write_message(struct mei_device *dev,
if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
return 0;
- dev->write_hang = 0;
return 1;
}
@@ -256,13 +255,13 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl)
{
int i;
- if (!dev->num_mei_me_clients)
+ if (!dev->me_clients_num)
return 0;
if (cl->mei_flow_ctrl_creds > 0)
return 1;
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
struct mei_me_client *me_cl = &dev->me_clients[i];
if (me_cl->client_id == cl->me_client_id) {
if (me_cl->mei_flow_ctrl_creds) {
@@ -291,10 +290,10 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
{
int i;
- if (!dev->num_mei_me_clients)
+ if (!dev->me_clients_num)
return -ENOENT;
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
struct mei_me_client *me_cl = &dev->me_clients[i];
if (me_cl->client_id == cl->me_client_id) {
if (me_cl->props.single_recv_buf != 0) {
@@ -333,7 +332,7 @@ int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
mei_hdr->reserved = 0;
mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
- memset(mei_flow_control, 0, sizeof(mei_flow_control));
+ memset(mei_flow_control, 0, sizeof(*mei_flow_control));
mei_flow_control->host_addr = cl->host_client_id;
mei_flow_control->me_addr = cl->me_client_id;
mei_flow_control->cmd.cmd = MEI_FLOW_CONTROL_CMD;
@@ -397,7 +396,7 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
mei_cli_disconnect =
(struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
- memset(mei_cli_disconnect, 0, sizeof(mei_cli_disconnect));
+ memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
mei_cli_disconnect->host_addr = cl->host_client_id;
mei_cli_disconnect->me_addr = cl->me_client_id;
mei_cli_disconnect->cmd.cmd = CLIENT_DISCONNECT_REQ_CMD;
diff --git a/drivers/staging/mei/interface.h b/drivers/staging/mei/interface.h
index d0bf5cf..7bd38ae 100644
--- a/drivers/staging/mei/interface.h
+++ b/drivers/staging/mei/interface.h
@@ -23,7 +23,9 @@
#include "mei_dev.h"
-#define AMT_WD_VALUE 120 /* seconds */
+#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */
+#define AMT_WD_MIN_TIMEOUT 120 /* seconds */
+#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */
#define MEI_WATCHDOG_DATA_SIZE 16
#define MEI_START_WD_DATA_SIZE 20
@@ -48,8 +50,8 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
int mei_wd_send(struct mei_device *dev);
int mei_wd_stop(struct mei_device *dev, bool preserve);
-void mei_wd_host_init(struct mei_device *dev);
-void mei_wd_start_setup(struct mei_device *dev);
+bool mei_wd_host_init(struct mei_device *dev);
+void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout);
int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl);
diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c
index d1b9214..42b7c9a 100644
--- a/drivers/staging/mei/interrupt.c
+++ b/drivers/staging/mei/interrupt.c
@@ -94,7 +94,7 @@ static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
dev->iamthif_timer);
} else {
- run_next_iamthif_cmd(dev);
+ mei_run_next_iamthif_cmd(dev);
}
dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
@@ -195,7 +195,7 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
{
struct mei_cl *cl;
struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
- unsigned char *buffer;
+ unsigned char *buffer = NULL;
dev_dbg(&dev->pdev->dev, "start client msg\n");
if (!(dev->read_list.status == 0 &&
@@ -280,7 +280,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
} else {
dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
dev->iamthif_state = MEI_IAMTHIF_READING;
- dev->iamthif_flow_control_pending = 0;
+ dev->iamthif_flow_control_pending = false;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
@@ -396,7 +396,19 @@ static void mei_client_connect_response(struct mei_device *dev,
dev->wd_due_counter = (dev->wd_timeout) ? 1 : 0;
dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
- host_init_iamthif(dev);
+
+ /* Registering watchdog interface device once we got connection
+ to the WD Client
+ */
+ if (watchdog_register_device(&amt_wd_dev)) {
+ printk(KERN_ERR "mei: unable to register watchdog device.\n");
+ dev->wd_interface_reg = false;
+ } else {
+ dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
+ dev->wd_interface_reg = true;
+ }
+
+ mei_host_init_iamthif(dev);
return;
}
@@ -499,7 +511,7 @@ static void add_single_flow_creds(struct mei_device *dev,
struct mei_me_client *client;
int i;
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
client = &dev->me_clients[i];
if (client && flow->me_addr == client->client_id) {
if (client->props.single_recv_buf) {
@@ -593,7 +605,7 @@ static void mei_client_disconnect_request(struct mei_device *dev,
cl_pos->timer_count = 0;
if (cl_pos == &dev->wd_cl) {
dev->wd_due_counter = 0;
- dev->wd_pending = 0;
+ dev->wd_pending = false;
} else if (cl_pos == &dev->iamthif_cl)
dev->iamthif_timer = 0;
@@ -641,6 +653,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
struct hbm_host_enum_response *enum_res;
struct hbm_client_disconnect_request *disconnect_req;
struct hbm_host_stop_request *host_stop_req;
+ int res;
unsigned char *buffer;
@@ -659,9 +672,9 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
if (dev->mei_state == MEI_INIT_CLIENTS &&
dev->init_clients_state == MEI_START_MESSAGE) {
dev->init_clients_timer = 0;
- host_enum_clients_message(dev);
+ mei_host_enum_clients_message(dev);
} else {
- dev->recvd_msg = 0;
+ dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
mei_reset(dev, 1);
return;
@@ -690,7 +703,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
return;
}
- dev->recvd_msg = 1;
+ dev->recvd_msg = true;
dev_dbg(&dev->pdev->dev, "host start response message received.\n");
break;
@@ -734,7 +747,39 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
MEI_CLIENT_PROPERTIES_MESSAGE) {
dev->me_client_index++;
dev->me_client_presentation_num++;
- host_client_properties(dev);
+
+ /** Send Client Propeties request **/
+ res = mei_host_client_properties(dev);
+ if (res < 0) {
+ dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
+ return;
+ } else if (!res) {
+ /*
+ * No more clients to send to.
+ * Clear Map for indicating now ME clients
+ * with associated host client
+ */
+ bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
+ dev->open_handle_count = 0;
+
+ /*
+ * Reserving the first three client IDs
+ * Client Id 0 - Reserved for MEI Bus Message communications
+ * Client Id 1 - Reserved for Watchdog
+ * Client ID 2 - Reserved for AMTHI
+ */
+ bitmap_set(dev->host_clients_map, 0, 3);
+ dev->mei_state = MEI_ENABLED;
+ dev->reset_count = 0;
+
+ /* if wd initialization fails, initialization the AMTHI client,
+ * otherwise the AMTHI client will be initialized after the WD client connect response
+ * will be received
+ */
+ if (mei_wd_host_init(dev))
+ mei_host_init_iamthif(dev);
+ }
+
} else {
dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
mei_reset(dev, 1);
@@ -755,10 +800,10 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
dev->init_clients_timer = 0;
dev->me_client_presentation_num = 0;
dev->me_client_index = 0;
- allocate_me_clients_storage(dev);
+ mei_allocate_me_clients_storage(dev);
dev->init_clients_state =
MEI_CLIENT_PROPERTIES_MESSAGE;
- host_client_properties(dev);
+ mei_host_client_properties(dev);
} else {
dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
mei_reset(dev, 1);
@@ -1028,7 +1073,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
cb_pos->information = dev->iamthif_msg_buf_index;
cl->status = 0;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
- dev->iamthif_flow_control_pending = 1;
+ dev->iamthif_flow_control_pending = true;
/* save iamthif cb sent to amthi client */
dev->iamthif_current_cb = cb_pos;
list_move_tail(&cb_pos->cb_list,
@@ -1192,7 +1237,6 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
return 0;
}
- dev->write_hang = -1;
*slots = mei_count_empty_write_slots(dev);
/* complete all waiting for write CB */
dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
@@ -1232,7 +1276,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
}
if (dev->stop && !dev->wd_pending) {
- dev->wd_stopped = 1;
+ dev->wd_stopped = true;
wake_up_interruptible(&dev->wait_stop_wd);
return 0;
}
@@ -1256,7 +1300,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
return -ENODEV;
- dev->wd_pending = 0;
+ dev->wd_pending = false;
if (dev->wd_timeout) {
*slots -= (sizeof(struct mei_msg_hdr) +
@@ -1382,7 +1426,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
*
* NOTE: This function is called by timer interrupt work
*/
-void mei_wd_timer(struct work_struct *work)
+void mei_timer(struct work_struct *work)
{
unsigned long timeout;
struct mei_cl *cl_pos = NULL;
@@ -1392,7 +1436,7 @@ void mei_wd_timer(struct work_struct *work)
struct mei_cl_cb *cb_next = NULL;
struct mei_device *dev = container_of(work,
- struct mei_device, wd_work.work);
+ struct mei_device, timer_work.work);
mutex_lock(&dev->device_lock);
@@ -1419,41 +1463,14 @@ void mei_wd_timer(struct work_struct *work)
}
}
- if (dev->wd_cl.state != MEI_FILE_CONNECTED)
- goto out;
-
- /* Watchdog */
- if (dev->wd_due_counter && !dev->wd_bypass) {
- if (--dev->wd_due_counter == 0) {
- if (dev->mei_host_buffer_is_empty &&
- mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
- dev->mei_host_buffer_is_empty = 0;
- dev_dbg(&dev->pdev->dev, "send watchdog.\n");
-
- if (mei_wd_send(dev))
- dev_dbg(&dev->pdev->dev, "wd send failed.\n");
- else
- if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
- goto out;
-
- if (dev->wd_timeout)
- dev->wd_due_counter = 2;
- else
- dev->wd_due_counter = 0;
-
- } else
- dev->wd_pending = 1;
-
- }
- }
if (dev->iamthif_stall_timer) {
if (--dev->iamthif_stall_timer == 0) {
dev_dbg(&dev->pdev->dev, "reseting because of hang to amthi.\n");
mei_reset(dev, 1);
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = 0;
- dev->iamthif_ioctl = 1;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = true;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
@@ -1462,7 +1479,7 @@ void mei_wd_timer(struct work_struct *work)
dev->iamthif_file_object = NULL;
dev->iamthif_current_cb = NULL;
- run_next_iamthif_cmd(dev);
+ mei_run_next_iamthif_cmd(dev);
}
}
@@ -1506,12 +1523,13 @@ void mei_wd_timer(struct work_struct *work)
dev->iamthif_file_object = NULL;
dev->iamthif_current_cb = NULL;
dev->iamthif_timer = 0;
- run_next_iamthif_cmd(dev);
+ mei_run_next_iamthif_cmd(dev);
}
}
out:
- schedule_delayed_work(&dev->wd_work, 2 * HZ);
+ if (dev->mei_state != MEI_DISABLED)
+ schedule_delayed_work(&dev->timer_work, 2 * HZ);
mutex_unlock(&dev->device_lock);
}
@@ -1539,8 +1557,14 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
/* initialize our complete list */
mutex_lock(&dev->device_lock);
- mei_initialize_list(&complete_list, dev);
+ mei_io_list_init(&complete_list);
dev->host_hw_state = mei_hcsr_read(dev);
+
+ /* Ack the interrupt here
+ * In case of MSI we don't go throuhg the quick handler */
+ if (pci_dev_msi_enabled(dev->pdev))
+ mei_reg_write(dev, H_CSR, dev->host_hw_state);
+
dev->me_hw_state = mei_mecsr_read(dev);
/* check if ME wants a reset */
@@ -1564,7 +1588,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
/* link is established
* start sending messages.
*/
- host_start_message(dev);
+ mei_host_start_message(dev);
mutex_unlock(&dev->device_lock);
return IRQ_HANDLED;
} else {
diff --git a/drivers/staging/mei/iorw.c b/drivers/staging/mei/iorw.c
index 697a277..8a61d12 100644
--- a/drivers/staging/mei/iorw.c
+++ b/drivers/staging/mei/iorw.c
@@ -121,7 +121,7 @@ int mei_ioctl_connect_client(struct file *file,
clear_bit(cl->host_client_id, dev->host_clients_map);
list_for_each_entry_safe(cl_pos, cl_next,
&dev->file_list, link) {
- if (mei_fe_same_id(cl, cl_pos)) {
+ if (mei_cl_cmp_id(cl, cl_pos)) {
dev_dbg(&dev->pdev->dev,
"remove file private data node host"
" client = %d, ME client = %d.\n",
@@ -161,7 +161,7 @@ int mei_ioctl_connect_client(struct file *file,
if (dev->mei_host_buffer_is_empty
&& !mei_other_client_is_connecting(dev, cl)) {
dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
- dev->mei_host_buffer_is_empty = 0;
+ dev->mei_host_buffer_is_empty = false;
if (!mei_connect(dev, cl)) {
dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
rets = -ENODEV;
@@ -204,8 +204,8 @@ int mei_ioctl_connect_client(struct file *file,
}
rets = -EFAULT;
- mei_flush_list(&dev->ctrl_rd_list, cl);
- mei_flush_list(&dev->ctrl_wr_list, cl);
+ mei_io_list_flush(&dev->ctrl_rd_list, cl);
+ mei_io_list_flush(&dev->ctrl_wr_list, cl);
goto end;
}
rets = 0;
@@ -277,13 +277,13 @@ int amthi_read(struct mei_device *dev, struct file *file,
return -ETIMEDOUT;
}
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
if (dev->me_clients[i].client_id ==
dev->iamthif_cl.me_client_id)
break;
}
- if (i == dev->num_mei_me_clients) {
+ if (i == dev->me_clients_num) {
dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
return -ENODEV;
}
@@ -409,7 +409,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
if (dev->me_clients[i].client_id == cl->me_client_id)
break;
@@ -420,7 +420,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
goto unlock;
}
- if (i == dev->num_mei_me_clients) {
+ if (i == dev->me_clients_num) {
rets = -ENODEV;
goto unlock;
}
@@ -439,7 +439,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
cb->file_private = (void *) cl;
cl->read_cb = cb;
if (dev->mei_host_buffer_is_empty) {
- dev->mei_host_buffer_is_empty = 0;
+ dev->mei_host_buffer_is_empty = false;
if (!mei_send_flow_control(dev, cl)) {
rets = -ENODEV;
goto unlock;
@@ -478,8 +478,8 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
dev->iamthif_state = MEI_IAMTHIF_WRITING;
dev->iamthif_current_cb = cb;
dev->iamthif_file_object = cb->file_object;
- dev->iamthif_canceled = 0;
- dev->iamthif_ioctl = 1;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = true;
dev->iamthif_msg_buf_size = cb->request_buffer.size;
memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
cb->request_buffer.size);
@@ -490,7 +490,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
if (ret && dev->mei_host_buffer_is_empty) {
ret = 0;
- dev->mei_host_buffer_is_empty = 0;
+ dev->mei_host_buffer_is_empty = false;
if (cb->request_buffer.size >
(((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
-sizeof(struct mei_msg_hdr)) {
@@ -515,7 +515,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
if (mei_hdr.msg_complete) {
if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
return -ENODEV;
- dev->iamthif_flow_control_pending = 1;
+ dev->iamthif_flow_control_pending = true;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
dev->iamthif_current_cb = cb;
@@ -547,7 +547,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
*
* returns 0 on success, <0 on failure.
*/
-void run_next_iamthif_cmd(struct mei_device *dev)
+void mei_run_next_iamthif_cmd(struct mei_device *dev)
{
struct mei_cl *cl_tmp;
struct mei_cl_cb *cb_pos = NULL;
@@ -559,8 +559,8 @@ void run_next_iamthif_cmd(struct mei_device *dev)
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = 0;
- dev->iamthif_ioctl = 1;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = true;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
dev->iamthif_file_object = NULL;
diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
index bfd1b46..44ed7a8 100644
--- a/drivers/staging/mei/main.c
+++ b/drivers/staging/mei/main.c
@@ -14,8 +14,6 @@
*
*/
-
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -30,7 +28,6 @@
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
-#include <linux/version.h>
#include <linux/sched.h>
#include <linux/uuid.h>
#include <linux/compat.h>
@@ -61,7 +58,7 @@ static struct cdev mei_cdev;
static int mei_major;
/* The device pointer */
/* Currently this driver works as long as there is only a single AMT device. */
-static struct pci_dev *mei_device;
+struct pci_dev *mei_device;
static struct class *mei_class;
@@ -109,6 +106,27 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
static DEFINE_MUTEX(mei_mutex);
/**
+ * mei_quirk_probe - probe for devices that doesn't valid ME interface
+ * @pdev: PCI device structure
+ * @ent: entry into pci_device_table
+ *
+ * returns true if ME Interface is valid, false otherwise
+ */
+static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ u32 reg;
+ if (ent->device == MEI_DEV_ID_PBG_1) {
+ pci_read_config_dword(pdev, 0x48, &reg);
+ /* make sure that bit 9 is up and bit 10 is down */
+ if ((reg & 0x600) == 0x200) {
+ dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
+ return false;
+ }
+ }
+ return true;
+}
+/**
* mei_probe - Device Initialization Routine
*
* @pdev: PCI device structure
@@ -123,6 +141,12 @@ static int __devinit mei_probe(struct pci_dev *pdev,
int err;
mutex_lock(&mei_mutex);
+
+ if (!mei_quirk_probe(pdev, ent)) {
+ err = -ENODEV;
+ goto end;
+ }
+
if (mei_device) {
err = -EEXIST;
goto end;
@@ -142,7 +166,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
goto disable_device;
}
/* allocates and initializes the mei dev structure */
- dev = init_mei_device(pdev);
+ dev = mei_device_init(pdev);
if (!dev) {
err = -ENOMEM;
goto release_regions;
@@ -154,17 +178,26 @@ static int __devinit mei_probe(struct pci_dev *pdev,
err = -ENOMEM;
goto free_device;
}
- /* request and enable interrupt */
- err = request_threaded_irq(pdev->irq,
+ pci_enable_msi(pdev);
+
+ /* request and enable interrupt */
+ if (pci_dev_msi_enabled(pdev))
+ err = request_threaded_irq(pdev->irq,
+ NULL,
+ mei_interrupt_thread_handler,
+ 0, mei_driver_name, dev);
+ else
+ err = request_threaded_irq(pdev->irq,
mei_interrupt_quick_handler,
mei_interrupt_thread_handler,
IRQF_SHARED, mei_driver_name, dev);
+
if (err) {
printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
pdev->irq);
goto unmap_memory;
}
- INIT_DELAYED_WORK(&dev->wd_work, mei_wd_timer);
+ INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
if (mei_hw_init(dev)) {
printk(KERN_ERR "mei: Init hw failure.\n");
err = -ENODEV;
@@ -172,7 +205,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
}
mei_device = pdev;
pci_set_drvdata(pdev, dev);
- schedule_delayed_work(&dev->wd_work, HZ);
+ schedule_delayed_work(&dev->timer_work, HZ);
mutex_unlock(&mei_mutex);
@@ -186,6 +219,7 @@ release_irq:
mei_disable_interrupts(dev);
flush_scheduled_work();
free_irq(pdev->irq, dev);
+ pci_disable_msi(pdev);
unmap_memory:
pci_iounmap(pdev, dev->mem_addr);
free_device:
@@ -234,13 +268,17 @@ static void __devexit mei_remove(struct pci_dev *pdev)
mei_disconnect_host_client(dev, &dev->wd_cl);
}
+ /* Unregistering watchdog device */
+ if (dev->wd_interface_reg)
+ watchdog_unregister_device(&amt_wd_dev);
+
/* remove entry if already in list */
dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
dev->iamthif_current_cb = NULL;
- dev->num_mei_me_clients = 0;
+ dev->me_clients_num = 0;
mutex_unlock(&dev->device_lock);
@@ -250,6 +288,7 @@ static void __devexit mei_remove(struct pci_dev *pdev)
mei_disable_interrupts(dev);
free_irq(pdev->irq, dev);
+ pci_disable_msi(pdev);
pci_set_drvdata(pdev, NULL);
if (dev->mem_addr)
@@ -362,7 +401,6 @@ static struct mei_cl_cb *find_read_list_entry(
{
struct mei_cl_cb *cb_pos = NULL;
struct mei_cl_cb *cb_next = NULL;
- struct mei_cl *cl_list_temp;
if (!dev->read_list.status &&
!list_empty(&dev->read_list.mei_cb.cb_list)) {
@@ -370,14 +408,11 @@ static struct mei_cl_cb *find_read_list_entry(
dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
list_for_each_entry_safe(cb_pos, cb_next,
&dev->read_list.mei_cb.cb_list, cb_list) {
+ struct mei_cl *cl_temp;
+ cl_temp = (struct mei_cl *)cb_pos->file_private;
- cl_list_temp = (struct mei_cl *)
- cb_pos->file_private;
-
- if (cl_list_temp &&
- mei_fe_same_id(cl, cl_list_temp))
+ if (mei_cl_cmp_id(cl, cl_temp))
return cb_pos;
-
}
}
return NULL;
@@ -407,9 +442,9 @@ static int mei_open(struct inode *inode, struct file *file)
mutex_lock(&dev->device_lock);
err = -ENOMEM;
- cl = mei_alloc_file_private(dev);
+ cl = mei_cl_allocate(dev);
if (!cl)
- goto out;
+ goto out_unlock;
err = -ENODEV;
if (dev->mei_state != MEI_ENABLED) {
@@ -478,7 +513,7 @@ static int mei_release(struct inode *inode, struct file *file)
cl->me_client_id);
rets = mei_disconnect_host_client(dev, cl);
}
- mei_flush_queues(dev, cl);
+ mei_cl_flush_queues(cl);
dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
cl->host_client_id,
cl->me_client_id);
@@ -519,10 +554,10 @@ static int mei_release(struct inode *inode, struct file *file)
dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
dev->iamthif_state);
- dev->iamthif_canceled = 1;
+ dev->iamthif_canceled = true;
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
- run_next_iamthif_cmd(dev);
+ mei_run_next_iamthif_cmd(dev);
}
}
@@ -800,7 +835,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -ENODEV;
goto unlock_dev;
}
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
if (dev->me_clients[i].client_id ==
dev->iamthif_cl.me_client_id)
break;
@@ -810,7 +845,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -ENODEV;
goto unlock_dev;
}
- if (i == dev->num_mei_me_clients ||
+ if (i == dev->me_clients_num ||
(dev->me_clients[i].client_id !=
dev->iamthif_cl.me_client_id)) {
rets = -ENODEV;
@@ -868,7 +903,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
cl->me_client_id);
goto unlock_dev;
}
- for (i = 0; i < dev->num_mei_me_clients; i++) {
+ for (i = 0; i < dev->me_clients_num; i++) {
if (dev->me_clients[i].client_id ==
cl->me_client_id)
break;
@@ -877,7 +912,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -ENODEV;
goto unlock_dev;
}
- if (i == dev->num_mei_me_clients) {
+ if (i == dev->me_clients_num) {
rets = -ENODEV;
goto unlock_dev;
}
@@ -893,7 +928,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
if (rets && dev->mei_host_buffer_is_empty) {
rets = 0;
- dev->mei_host_buffer_is_empty = 0;
+ dev->mei_host_buffer_is_empty = false;
if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
sizeof(u32)) - sizeof(struct mei_msg_hdr))) {
@@ -1066,7 +1101,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
dev->iamthif_file_object == file) {
mask |= (POLLIN | POLLRDNORM);
dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
- run_next_iamthif_cmd(dev);
+ mei_run_next_iamthif_cmd(dev);
}
goto out;
}
@@ -1103,7 +1138,7 @@ static int mei_pci_suspend(struct device *device)
mutex_unlock(&dev->device_lock);
free_irq(pdev->irq, dev);
-
+ pci_disable_msi(pdev);
return err;
}
@@ -1118,11 +1153,20 @@ static int mei_pci_resume(struct device *device)
if (!dev)
return -ENODEV;
- /* request and enable interrupt */
- err = request_threaded_irq(pdev->irq,
+ pci_enable_msi(pdev);
+
+ /* request and enable interrupt */
+ if (pci_dev_msi_enabled(pdev))
+ err = request_threaded_irq(pdev->irq,
+ NULL,
+ mei_interrupt_thread_handler,
+ 0, mei_driver_name, dev);
+ else
+ err = request_threaded_irq(pdev->irq,
mei_interrupt_quick_handler,
mei_interrupt_thread_handler,
IRQF_SHARED, mei_driver_name, dev);
+
if (err) {
printk(KERN_ERR "mei: Request_irq failure. irq = %d\n",
pdev->irq);
@@ -1134,12 +1178,9 @@ static int mei_pci_resume(struct device *device)
mei_reset(dev, 1);
mutex_unlock(&dev->device_lock);
- /* Start watchdog if stopped in suspend */
- if (dev->wd_timeout) {
- mei_wd_start_setup(dev);
- dev->wd_due_counter = 1;
- schedule_delayed_work(&dev->wd_work, HZ);
- }
+ /* Start timer if stopped in suspend */
+ schedule_delayed_work(&dev->timer_work, HZ);
+
return err;
}
static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
@@ -1333,9 +1374,9 @@ module_init(mei_init_module);
*/
static void __exit mei_exit_module(void)
{
- pci_unregister_driver(&mei_driver);
mei_sysfs_device_remove();
mei_unregister_cdev();
+ pci_unregister_driver(&mei_driver);
pr_debug("mei: Driver unloaded successfully.\n");
}
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index 6f3ec06..264bf23 100644
--- a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -18,6 +18,7 @@
#define _MEI_DEV_H_
#include <linux/types.h>
+#include <linux/watchdog.h>
#include "mei.h"
#include "hw.h"
@@ -37,6 +38,17 @@
#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
/*
+ * MEI PCI Device object
+ */
+extern struct pci_dev *mei_device;
+
+/*
+ * AMT Watchdog Device
+ */
+#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
+extern struct watchdog_device amt_wd_dev;
+
+/*
* AMTHI Client UUID
*/
extern const uuid_le mei_amthi_guid;
@@ -52,6 +64,11 @@ extern const uuid_le mei_wd_guid;
extern const u8 mei_wd_state_independence_msg[3][4];
/*
+ * maximum number of consecutive resets
+ */
+#define MEI_MAX_CONSEC_RESET 3
+
+/*
* Number of File descriptors/handles
* that can be opened to the driver.
*
@@ -62,11 +79,6 @@ extern const u8 mei_wd_state_independence_msg[3][4];
#define MEI_MAX_OPEN_HANDLE_COUNT 253
/*
- * Number of queue lists used by this driver
- */
-#define MEI_IO_LISTS_NUMBER 7
-
-/*
* Number of Maximum MEI Clients
*/
#define MEI_CLIENTS_MAX 255
@@ -169,17 +181,19 @@ struct mei_cl {
struct mei_io_list {
struct mei_cl_cb mei_cb;
int status;
- struct mei_device *device_extension;
};
-/* MEI private device struct */
+/**
+ * mei_device - MEI private device struct
+ *
+ * @reset_count - limits the number of consecutive resets
+ */
struct mei_device {
struct pci_dev *pdev; /* pointer to pci device struct */
/*
* lists of queues
*/
/* array of pointers to aio lists */
- struct mei_io_list *io_list_array[MEI_IO_LISTS_NUMBER];
struct mei_io_list read_list; /* driver read queue */
struct mei_io_list write_list; /* driver write queue */
struct mei_io_list write_waiting_list; /* write waiting queue */
@@ -193,6 +207,7 @@ struct mei_device {
* list of files
*/
struct list_head file_list;
+ long open_handle_count;
/*
* memory of device
*/
@@ -203,8 +218,8 @@ struct mei_device {
* lock for the device
*/
struct mutex device_lock; /* device lock */
- int recvd_msg;
- struct delayed_work wd_work; /* watch dog deleye work */
+ struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
+ bool recvd_msg;
/*
* hw states of host and fw(ME)
*/
@@ -219,10 +234,12 @@ struct mei_device {
/*
* mei device states
*/
+ unsigned long reset_count;
enum mei_states mei_state;
enum mei_init_clients_states init_clients_state;
u16 init_clients_timer;
- int stop;
+ bool stop;
+ bool need_reset;
u32 extra_write_index;
u32 rd_msg_buf[128]; /* used for control messages */
@@ -232,81 +249,107 @@ struct mei_device {
struct hbm_version version;
- int mei_host_buffer_is_empty;
- struct mei_cl wd_cl;
struct mei_me_client *me_clients; /* Note: memory has to be allocated */
DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
- u8 num_mei_me_clients;
+ u8 me_clients_num;
u8 me_client_presentation_num;
u8 me_client_index;
+ bool mei_host_buffer_is_empty;
- int wd_pending;
- int wd_stopped;
+ struct mei_cl wd_cl;
+ bool wd_pending;
+ bool wd_stopped;
+ bool wd_bypass; /* if false, don't refresh watchdog ME client */
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
+ u16 wd_due_counter;
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
- u16 wd_due_counter;
- bool wd_bypass; /* if false, don't refresh watchdog ME client */
struct file *iamthif_file_object;
struct mei_cl iamthif_cl;
- int iamthif_ioctl;
- int iamthif_canceled;
+ struct mei_cl_cb *iamthif_current_cb;
int iamthif_mtu;
unsigned long iamthif_timer;
u32 iamthif_stall_timer;
unsigned char *iamthif_msg_buf; /* Note: memory has to be allocated */
u32 iamthif_msg_buf_size;
u32 iamthif_msg_buf_index;
- int iamthif_flow_control_pending;
enum iamthif_states iamthif_state;
- struct mei_cl_cb *iamthif_current_cb;
- u8 write_hang;
- int need_reset;
- long open_handle_count;
+ bool iamthif_flow_control_pending;
+ bool iamthif_ioctl;
+ bool iamthif_canceled;
+ bool wd_interface_reg;
};
/*
* mei init function prototypes
*/
-struct mei_device *init_mei_device(struct pci_dev *pdev);
+struct mei_device *mei_device_init(struct pci_dev *pdev);
void mei_reset(struct mei_device *dev, int interrupts);
int mei_hw_init(struct mei_device *dev);
int mei_task_initialize_clients(void *data);
int mei_initialize_clients(struct mei_device *dev);
-struct mei_cl *mei_alloc_file_private(struct mei_device *dev);
int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
-void mei_initialize_list(struct mei_io_list *list,
- struct mei_device *dev);
-void mei_flush_list(struct mei_io_list *list, struct mei_cl *cl);
-void mei_flush_queues(struct mei_device *dev, struct mei_cl *cl);
-void mei_remove_client_from_file_list(struct mei_device *dev,
- u8 host_client_id);
-void host_init_iamthif(struct mei_device *dev);
-void mei_init_file_private(struct mei_cl *priv, struct mei_device *dev);
-void allocate_me_clients_storage(struct mei_device *dev);
-
-void host_start_message(struct mei_device *dev);
-void host_enum_clients_message(struct mei_device *dev);
-void host_client_properties(struct mei_device *dev);
+void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
+void mei_host_init_iamthif(struct mei_device *dev);
+void mei_allocate_me_clients_storage(struct mei_device *dev);
+
u8 mei_find_me_client_update_filext(struct mei_device *dev,
struct mei_cl *priv,
const uuid_le *cguid, u8 client_id);
/*
- * interrupt functions prototype
+ * MEI IO List Functions
+ */
+void mei_io_list_init(struct mei_io_list *list);
+void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
+
+/*
+ * MEI ME Client Functions
+ */
+
+struct mei_cl *mei_cl_allocate(struct mei_device *dev);
+void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
+int mei_cl_flush_queues(struct mei_cl *cl);
+/**
+ * mei_cl_cmp_id - tells if file private data have same id
+ *
+ * @fe1: private data of 1. file object
+ * @fe2: private data of 2. file object
+ *
+ * returns true - if ids are the same and not NULL
+ */
+static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
+ const struct mei_cl *cl2)
+{
+ return cl1 && cl2 &&
+ (cl1->host_client_id == cl2->host_client_id) &&
+ (cl1->me_client_id == cl2->me_client_id);
+}
+
+
+
+/*
+ * MEI Host Client Functions
+ */
+void mei_host_start_message(struct mei_device *dev);
+void mei_host_enum_clients_message(struct mei_device *dev);
+int mei_host_client_properties(struct mei_device *dev);
+
+/*
+ * MEI interrupt functions prototype
*/
irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id);
-irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
-void mei_wd_timer(struct work_struct *work);
+irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
+void mei_timer(struct work_struct *work);
/*
- * input output function prototype
+ * MEI input output function prototype
*/
int mei_ioctl_connect_client(struct file *file,
struct mei_connect_client_data *data);
@@ -321,7 +364,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
struct file *file);
-void run_next_iamthif_cmd(struct mei_device *dev);
+void mei_run_next_iamthif_cmd(struct mei_device *dev);
void mei_free_cb_private(struct mei_cl_cb *priv_cb);
@@ -337,10 +380,9 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
* @dev: the device structure
* @offset: offset from which to read the data
*
- * returns the byte read.
+ * returns register value (u32)
*/
-static inline u32 mei_reg_read(struct mei_device *dev,
- unsigned long offset)
+static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
{
return ioread32(dev->mem_addr + offset);
}
@@ -350,7 +392,7 @@ static inline u32 mei_reg_read(struct mei_device *dev,
*
* @dev: the device structure
* @offset: offset from which to write the data
- * @value: the byte to write
+ * @value: register value to write (u32)
*/
static inline void mei_reg_write(struct mei_device *dev,
unsigned long offset, u32 value)
@@ -404,19 +446,4 @@ void mei_csr_clear_his(struct mei_device *dev);
void mei_enable_interrupts(struct mei_device *dev);
void mei_disable_interrupts(struct mei_device *dev);
-/**
- * mei_fe_same_id - tells if file private data have same id
- *
- * @fe1: private data of 1. file object
- * @fe2: private data of 2. file object
- *
- * returns !=0 - if ids are the same, 0 - if differ.
- */
-static inline int mei_fe_same_id(const struct mei_cl *fe1,
- const struct mei_cl *fe2)
-{
- return ((fe1->host_client_id == fe2->host_client_id) &&
- (fe1->me_client_id == fe2->me_client_id));
-}
-
#endif
diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index fff53d0..ffca7ca 100644
--- a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -19,22 +19,13 @@
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/watchdog.h>
#include "mei_dev.h"
#include "hw.h"
#include "interface.h"
#include "mei.h"
-/*
- * MEI Watchdog Module Parameters
- */
-static u16 watchdog_timeout = AMT_WD_VALUE;
-module_param(watchdog_timeout, ushort, 0);
-MODULE_PARM_DESC(watchdog_timeout,
- "Intel(R) AMT Watchdog timeout value in seconds. (default="
- __MODULE_STRING(AMT_WD_VALUE)
- ", disable=0)");
-
static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
@@ -50,12 +41,12 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
0x32, 0xAB);
-void mei_wd_start_setup(struct mei_device *dev)
+void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
{
- dev_dbg(&dev->pdev->dev, "dev->wd_timeout=%d.\n", dev->wd_timeout);
+ dev_dbg(&dev->pdev->dev, "timeout=%d.\n", timeout);
memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE);
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE,
- &dev->wd_timeout, sizeof(u16));
+ &timeout, sizeof(u16));
}
/**
@@ -63,39 +54,39 @@ void mei_wd_start_setup(struct mei_device *dev)
*
* @dev: the device structure
*/
-void mei_wd_host_init(struct mei_device *dev)
+bool mei_wd_host_init(struct mei_device *dev)
{
- mei_init_file_private(&dev->wd_cl, dev);
+ bool ret = false;
+
+ mei_cl_init(&dev->wd_cl, dev);
/* look for WD client and connect to it */
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
- dev->wd_timeout = watchdog_timeout;
-
- if (dev->wd_timeout > 0) {
- mei_wd_start_setup(dev);
- /* find ME WD client */
- mei_find_me_client_update_filext(dev, &dev->wd_cl,
- &mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
-
- dev_dbg(&dev->pdev->dev, "check wd_cl\n");
- if (MEI_FILE_CONNECTING == dev->wd_cl.state) {
- if (!mei_connect(dev, &dev->wd_cl)) {
- dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
- dev->wd_cl.state = MEI_FILE_DISCONNECTED;
- dev->wd_cl.host_client_id = 0;
- host_init_iamthif(dev) ;
- } else {
- dev->wd_cl.timer_count = CONNECT_TIMEOUT;
- }
+ dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT;
+
+ /* find ME WD client */
+ mei_find_me_client_update_filext(dev, &dev->wd_cl,
+ &mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
+
+ dev_dbg(&dev->pdev->dev, "check wd_cl\n");
+ if (MEI_FILE_CONNECTING == dev->wd_cl.state) {
+ if (!mei_connect(dev, &dev->wd_cl)) {
+ dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
+ dev->wd_cl.state = MEI_FILE_DISCONNECTED;
+ dev->wd_cl.host_client_id = 0;
+ ret = false;
+ goto end;
} else {
- dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
- host_init_iamthif(dev) ;
+ dev->wd_cl.timer_count = CONNECT_TIMEOUT;
}
} else {
- dev->wd_bypass = true;
- dev_dbg(&dev->pdev->dev, "WD requested to be disabled\n");
- host_init_iamthif(dev) ;
+ dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
+ ret = false;
+ goto end;
}
+
+end:
+ return ret;
}
/**
@@ -129,19 +120,29 @@ int mei_wd_send(struct mei_device *dev)
return -EIO;
}
+/**
+ * mei_wd_stop - sends watchdog stop message to fw.
+ *
+ * @dev: the device structure
+ * @preserve: indicate if to keep the timeout value
+ *
+ * returns 0 if success,
+ * -EIO when message send fails
+ * -EINVAL when invalid message is to be sent
+ */
int mei_wd_stop(struct mei_device *dev, bool preserve)
{
int ret;
u16 wd_timeout = dev->wd_timeout;
- cancel_delayed_work(&dev->wd_work);
+ cancel_delayed_work(&dev->timer_work);
if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout)
return 0;
dev->wd_timeout = 0;
dev->wd_due_counter = 0;
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
- dev->stop = 1;
+ dev->stop = true;
ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
if (ret < 0)
@@ -149,7 +150,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
if (ret && dev->mei_host_buffer_is_empty) {
ret = 0;
- dev->mei_host_buffer_is_empty = 0;
+ dev->mei_host_buffer_is_empty = false;
if (!mei_wd_send(dev)) {
ret = mei_flow_ctrl_reduce(dev, &dev->wd_cl);
@@ -159,11 +160,11 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
dev_dbg(&dev->pdev->dev, "send stop WD failed\n");
}
- dev->wd_pending = 0;
+ dev->wd_pending = false;
} else {
- dev->wd_pending = 1;
+ dev->wd_pending = true;
}
- dev->wd_stopped = 0;
+ dev->wd_stopped = false;
mutex_unlock(&dev->device_lock);
ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
@@ -186,3 +187,168 @@ out:
return ret;
}
+/*
+ * mei_wd_ops_start - wd start command from the watchdog core.
+ *
+ * @wd_dev - watchdog device struct
+ *
+ * returns 0 if success, negative errno code for failure
+ */
+static int mei_wd_ops_start(struct watchdog_device *wd_dev)
+{
+ int err = -ENODEV;
+ struct mei_device *dev;
+
+ dev = pci_get_drvdata(mei_device);
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->device_lock);
+
+ if (dev->mei_state != MEI_ENABLED) {
+ dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
+ dev->mei_state);
+ goto end_unlock;
+ }
+
+ if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
+ dev_dbg(&dev->pdev->dev, "MEI Driver is not connected to Watchdog Client\n");
+ goto end_unlock;
+ }
+
+ mei_wd_set_start_timeout(dev, dev->wd_timeout);
+
+ err = 0;
+end_unlock:
+ mutex_unlock(&dev->device_lock);
+ return err;
+}
+
+/*
+ * mei_wd_ops_stop - wd stop command from the watchdog core.
+ *
+ * @wd_dev - watchdog device struct
+ *
+ * returns 0 if success, negative errno code for failure
+ */
+static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
+{
+ struct mei_device *dev;
+ dev = pci_get_drvdata(mei_device);
+
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->device_lock);
+ mei_wd_stop(dev, false);
+ mutex_unlock(&dev->device_lock);
+
+ return 0;
+}
+
+/*
+ * mei_wd_ops_ping - wd ping command from the watchdog core.
+ *
+ * @wd_dev - watchdog device struct
+ *
+ * returns 0 if success, negative errno code for failure
+ */
+static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
+{
+ int ret = 0;
+ struct mei_device *dev;
+ dev = pci_get_drvdata(mei_device);
+
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->device_lock);
+
+ if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
+ dev_dbg(&dev->pdev->dev, "wd is not connected.\n");
+ ret = -ENODEV;
+ goto end;
+ }
+
+ /* Check if we can send the ping to HW*/
+ if (dev->mei_host_buffer_is_empty &&
+ mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
+
+ dev->mei_host_buffer_is_empty = false;
+ dev_dbg(&dev->pdev->dev, "sending watchdog ping\n");
+
+ if (mei_wd_send(dev)) {
+ dev_dbg(&dev->pdev->dev, "wd send failed.\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) {
+ dev_dbg(&dev->pdev->dev, "mei_flow_ctrl_reduce() failed.\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ } else {
+ dev->wd_pending = true;
+ }
+
+end:
+ mutex_unlock(&dev->device_lock);
+ return ret;
+}
+
+/*
+ * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core.
+ *
+ * @wd_dev - watchdog device struct
+ * @timeout - timeout value to set
+ *
+ * returns 0 if success, negative errno code for failure
+ */
+static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
+{
+ struct mei_device *dev;
+ dev = pci_get_drvdata(mei_device);
+
+ if (!dev)
+ return -ENODEV;
+
+ /* Check Timeout value */
+ if (timeout < AMT_WD_MIN_TIMEOUT || timeout > AMT_WD_MAX_TIMEOUT)
+ return -EINVAL;
+
+ mutex_lock(&dev->device_lock);
+
+ dev->wd_timeout = timeout;
+ mei_wd_set_start_timeout(dev, dev->wd_timeout);
+
+ mutex_unlock(&dev->device_lock);
+
+ return 0;
+}
+
+/*
+ * Watchdog Device structs
+ */
+const struct watchdog_ops wd_ops = {
+ .owner = THIS_MODULE,
+ .start = mei_wd_ops_start,
+ .stop = mei_wd_ops_stop,
+ .ping = mei_wd_ops_ping,
+ .set_timeout = mei_wd_ops_set_timeout,
+};
+const struct watchdog_info wd_info = {
+ .identity = INTEL_AMT_WATCHDOG_ID,
+ .options = WDIOF_KEEPALIVEPING,
+};
+
+struct watchdog_device amt_wd_dev = {
+ .info = &wd_info,
+ .ops = &wd_ops,
+ .timeout = AMT_WD_DEFAULT_TIMEOUT,
+ .min_timeout = AMT_WD_MIN_TIMEOUT,
+ .max_timeout = AMT_WD_MAX_TIMEOUT,
+};
+
+
diff --git a/drivers/staging/nvec/Kconfig b/drivers/staging/nvec/Kconfig
index 987ad48..86a8b8c 100644
--- a/drivers/staging/nvec/Kconfig
+++ b/drivers/staging/nvec/Kconfig
@@ -7,21 +7,27 @@ config MFD_NVEC
config KEYBOARD_NVEC
bool "Keyboard on nVidia compliant EC"
- depends on MFD_NVEC
+ depends on MFD_NVEC && INPUT=y
help
Say Y here to enable support for a keyboard connected to
a nVidia compliant embedded controller.
config SERIO_NVEC_PS2
bool "PS2 on nVidia EC"
- depends on MFD_NVEC
+ depends on MFD_NVEC && MOUSE_PS2
help
Say Y here to enable support for a Touchpad / Mouse connected
to a nVidia compliant embedded controller.
config NVEC_POWER
bool "NVEC charger and battery"
- depends on MFD_NVEC
+ depends on MFD_NVEC && POWER_SUPPLY=y
help
Say Y to enable support for battery and charger interface for
nVidia compliant embedded controllers.
+
+config NVEC_LEDS
+ bool "NVEC leds"
+ depends on MFD_NVEC && LEDS_CLASS
+ help
+ Say Y to enable yellow side leds on AC100 or other nVidia tegra nvec leds
diff --git a/drivers/staging/nvec/Makefile b/drivers/staging/nvec/Makefile
index 4b5fcec1..b844d60 100644
--- a/drivers/staging/nvec/Makefile
+++ b/drivers/staging/nvec/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_SERIO_NVEC_PS2) += nvec_ps2.o
obj-$(CONFIG_MFD_NVEC) += nvec.o
obj-$(CONFIG_NVEC_POWER) += nvec_power.o
obj-$(CONFIG_KEYBOARD_NVEC) += nvec_kbd.o
+obj-$(CONFIG_NVEC_LEDS) += nvec_leds.o
diff --git a/drivers/staging/nvec/TODO b/drivers/staging/nvec/TODO
index 77b47f7..f950ab8 100644
--- a/drivers/staging/nvec/TODO
+++ b/drivers/staging/nvec/TODO
@@ -1,8 +1,12 @@
ToDo list (incomplete, unordered)
- - convert mouse, keyboard, and power to platform devices
- - add copyright / driver author / license
- add compile as module support
- - move nvec devices to mfd cells?
- - adjust to kernel style
-
-
+ - fix clk usage
+ should not be using clk_get_sys(), but clk_get(&pdev->dev, conn)
+ where conn is either NULL if the device only has one clock, or
+ the device specific name if it has multiple clocks.
+ - move half of the nvec init stuff to i2c-tegra.c
+ - move event handling to nvec_events
+ - finish suspend/resume support
+ - modifiy the sync_write method to return the received
+ message in a variable (and return the error code).
+ - add support for more device implementations
diff --git a/drivers/staging/nvec/nvec-keytable.h b/drivers/staging/nvec/nvec-keytable.h
index 6a1c4f7..1dc22cb 100644
--- a/drivers/staging/nvec/nvec-keytable.h
+++ b/drivers/staging/nvec/nvec-keytable.h
@@ -22,7 +22,8 @@
*/
static unsigned short code_tab_102us[] = {
- KEY_GRAVE, // 0x00
+ /* 0x00 */
+ KEY_GRAVE,
KEY_ESC,
KEY_1,
KEY_2,
@@ -38,7 +39,8 @@ static unsigned short code_tab_102us[] = {
KEY_EQUAL,
KEY_BACKSPACE,
KEY_TAB,
- KEY_Q, // 0x10
+ /* 0x10 */
+ KEY_Q,
KEY_W,
KEY_E,
KEY_R,
@@ -54,7 +56,8 @@ static unsigned short code_tab_102us[] = {
KEY_LEFTCTRL,
KEY_A,
KEY_S,
- KEY_D, // 0x20
+ /* 0x20 */
+ KEY_D,
KEY_F,
KEY_G,
KEY_H,
@@ -70,7 +73,8 @@ static unsigned short code_tab_102us[] = {
KEY_X,
KEY_C,
KEY_V,
- KEY_B, // 0x30
+ /* 0x30 */
+ KEY_B,
KEY_N,
KEY_M,
KEY_COMMA,
@@ -86,13 +90,15 @@ static unsigned short code_tab_102us[] = {
KEY_F3,
KEY_F4,
KEY_F5,
- KEY_F6, // 0x40
+ /* 0x40 */
+ KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_FN,
- 0, //VK_SCROLL
+ /* VK_SCROLL */
+ 0,
KEY_KP7,
KEY_KP8,
KEY_KP9,
@@ -102,52 +108,57 @@ static unsigned short code_tab_102us[] = {
KEY_KP6,
KEY_KPPLUS,
KEY_KP1,
- KEY_KP2, // 0x50
+ /* 0x50 */
+ KEY_KP2,
KEY_KP3,
KEY_KP0,
KEY_KPDOT,
- KEY_MENU, //VK_SNAPSHOT
+ /* VK_SNAPSHOT */
+ KEY_MENU,
KEY_POWER,
- KEY_102ND, //VK_OEM_102 henry+ 0x2B (43) BACKSLASH have been used,change to use 0X56 (86)
- KEY_F11, //VK_F11
- KEY_F12, //VK_F12
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // 60
- 0,
- 0,
- KEY_SEARCH, // add search key map
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // 70
- 0,
- 0,
- KEY_KP5, //73 for JP keyboard '\' key, report 0x4c
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- KEY_KP9, //7d for JP keyboard '|' key, report 0x49
+ /* VK_OEM_102 */
+ KEY_102ND,
+ KEY_F11,
+ KEY_F12,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x60 */
+ 0,
+ 0,
+ 0,
+ KEY_SEARCH,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x70 */
+ 0,
+ 0,
+ 0,
+ KEY_KP5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ KEY_KP9,
};
static unsigned short extcode_tab_us102[] = {
@@ -167,27 +178,35 @@ static unsigned short extcode_tab_us102[] = {
0,
0,
0,
- 0, // 0xE0 0x10
+ /* 0x10 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
0,
0,
+ /* VK_MEDIA_NEXT_TRACK */
0,
0,
0,
+ /* VK_RETURN */
0,
+ KEY_RIGHTCTRL,
0,
0,
- 0, //VK_MEDIA_NEXT_TRACK,
+ /* 0x20 */
+ KEY_MUTE,
+ /* VK_LAUNCH_APP1 */
0,
+ /* VK_MEDIA_PLAY_PAUSE */
0,
- 0, //VK_RETURN,
- KEY_RIGHTCTRL, //VK_RCONTROL,
0,
+ /* VK_MEDIA_STOP */
0,
- KEY_MUTE, // 0xE0 0x20
- 0, //VK_LAUNCH_APP1
- 0, //VK_MEDIA_PLAY_PAUSE
0,
- 0, //VK_MEDIA_STOP
0,
0,
0,
@@ -198,41 +217,54 @@ static unsigned short extcode_tab_us102[] = {
0,
0,
0,
+ /* 0x30 */
+ KEY_VOLUMEUP,
0,
- KEY_VOLUMEUP, // 0xE0 0x30
+ /* VK_BROWSER_HOME */
+ 0,
+ 0,
+ 0,
+ /* VK_DIVIDE */
+ KEY_KPSLASH,
+ 0,
+ /* VK_SNAPSHOT */
+ KEY_SYSRQ,
+ /* VK_RMENU */
+ KEY_RIGHTALT,
+ /* VK_OEM_NV_BACKLIGHT_UP */
+ 0,
+ /* VK_OEM_NV_BACKLIGHT_DN */
+ 0,
+ /* VK_OEM_NV_BACKLIGHT_AUTOTOGGLE */
+ 0,
+ /* VK_OEM_NV_POWER_INFO */
+ 0,
+ /* VK_OEM_NV_WIFI_TOGGLE */
+ 0,
+ /* VK_OEM_NV_DISPLAY_SELECT */
+ 0,
+ /* VK_OEM_NV_AIRPLANE_TOGGLE */
+ 0,
+ /* 0x40 */
+ 0,
+ KEY_LEFT,
0,
- 0, //VK_BROWSER_HOME
0,
0,
- KEY_KPSLASH, //VK_DIVIDE
0,
- KEY_SYSRQ, //VK_SNAPSHOT
- KEY_RIGHTALT, //VK_RMENU
- 0, //VK_OEM_NV_BACKLIGHT_UP
- 0, //VK_OEM_NV_BACKLIGHT_DN
- 0, //VK_OEM_NV_BACKLIGHT_AUTOTOGGLE
- 0, //VK_OEM_NV_POWER_INFO
- 0, //VK_OEM_NV_WIFI_TOGGLE
- 0, //VK_OEM_NV_DISPLAY_SELECT
- 0, //VK_OEM_NV_AIRPLANE_TOGGLE
- 0, //0xE0 0x40
- KEY_LEFT, //VK_OEM_NV_RESERVED henry+ for JP keyboard
- 0, //VK_OEM_NV_RESERVED
- 0, //VK_OEM_NV_RESERVED
- 0, //VK_OEM_NV_RESERVED
- 0, //VK_OEM_NV_RESERVED
KEY_CANCEL,
KEY_HOME,
KEY_UP,
- KEY_PAGEUP, //VK_PRIOR
+ KEY_PAGEUP,
0,
KEY_LEFT,
0,
KEY_RIGHT,
0,
KEY_END,
- KEY_DOWN, // 0xE0 0x50
- KEY_PAGEDOWN, //VK_NEXT
+ /* 0x50 */
+ KEY_DOWN,
+ KEY_PAGEDOWN,
KEY_INSERT,
KEY_DELETE,
0,
@@ -242,25 +274,34 @@ static unsigned short extcode_tab_us102[] = {
0,
0,
0,
- KEY_LEFTMETA, //VK_LWIN
- 0, //VK_RWIN
- KEY_ESC, //VK_APPS
- KEY_KPMINUS, //for power button workaround
- 0,
+ KEY_LEFTMETA,
+ 0,
+ KEY_ESC,
+ KEY_KPMINUS,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* VK_BROWSER_SEARCH */
+ 0,
+ /* VK_BROWSER_FAVORITES */
+ 0,
+ /* VK_BROWSER_REFRESH */
+ 0,
+ /* VK_BROWSER_STOP */
+ 0,
+ /* VK_BROWSER_FORWARD */
0,
+ /* VK_BROWSER_BACK */
0,
+ /* VK_LAUNCH_APP2 */
0,
+ /* VK_LAUNCH_MAIL */
0,
+ /* VK_LAUNCH_MEDIA_SELECT */
0,
- 0, //VK_BROWSER_SEARCH
- 0, //VK_BROWSER_FAVORITES
- 0, //VK_BROWSER_REFRESH
- 0, //VK_BROWSER_STOP
- 0, //VK_BROWSER_FORWARD
- 0, //VK_BROWSER_BACK
- 0, //VK_LAUNCH_APP2
- 0, //VK_LAUNCH_MAIL
- 0, //VK_LAUNCH_MEDIA_SELECT
};
-static unsigned short* code_tabs[] = {code_tab_102us, extcode_tab_us102 };
+static unsigned short *code_tabs[] = { code_tab_102us, extcode_tab_us102 };
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 1a94364..e06b867 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -1,295 +1,706 @@
-// #define DEBUG
-
-/* ToDo list (incomplete, unorderd)
- - convert mouse, keyboard, and power to platform devices
-*/
-
-#include <asm/io.h>
-#include <asm/irq.h>
+/*
+ * NVEC: NVIDIA compliant embedded controller interface
+ *
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+ *
+ * Authors: Pierre-Hugues Husson <phhusson@free.fr>
+ * Ilya Petrov <ilya.muromec@gmail.com>
+ * Marc Dietrich <marvin24@gmx.de>
+ * Julian Andres Klode <jak@jak-linux.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+/* #define DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/serio.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/workqueue.h>
-#include <linux/clk.h>
-#include <mach/iomap.h>
-#include <mach/clk.h>
-#include <linux/semaphore.h>
#include <linux/list.h>
+#include <linux/mfd/core.h>
+#include <linux/mutex.h>
#include <linux/notifier.h>
-#include <linux/workqueue.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include <mach/clk.h>
+#include <mach/iomap.h>
+
#include "nvec.h"
-static unsigned char EC_DISABLE_EVENT_REPORTING[] = {'\x04','\x00','\x00'};
-static unsigned char EC_ENABLE_EVENT_REPORTING[] = {'\x04','\x00','\x01'};
-static unsigned char EC_GET_FIRMWARE_VERSION[] = {'\x07','\x15'};
+#define I2C_CNFG 0x00
+#define I2C_CNFG_PACKET_MODE_EN (1<<10)
+#define I2C_CNFG_NEW_MASTER_SFM (1<<11)
+#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12
+
+#define I2C_SL_CNFG 0x20
+#define I2C_SL_NEWL (1<<2)
+#define I2C_SL_NACK (1<<1)
+#define I2C_SL_RESP (1<<0)
+#define I2C_SL_IRQ (1<<3)
+#define END_TRANS (1<<4)
+#define RCVD (1<<2)
+#define RNW (1<<1)
+
+#define I2C_SL_RCVD 0x24
+#define I2C_SL_STATUS 0x28
+#define I2C_SL_ADDR1 0x2c
+#define I2C_SL_ADDR2 0x30
+#define I2C_SL_DELAY_COUNT 0x3c
+
+/**
+ * enum nvec_msg_category - Message categories for nvec_msg_alloc()
+ * @NVEC_MSG_RX: The message is an incoming message (from EC)
+ * @NVEC_MSG_TX: The message is an outgoing message (to EC)
+ */
+enum nvec_msg_category {
+ NVEC_MSG_RX,
+ NVEC_MSG_TX,
+};
+
+static const unsigned char EC_DISABLE_EVENT_REPORTING[3] = "\x04\x00\x00";
+static const unsigned char EC_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01";
+static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15";
static struct nvec_chip *nvec_power_handle;
+static struct mfd_cell nvec_devices[] = {
+ {
+ .name = "nvec-kbd",
+ .id = 1,
+ },
+ {
+ .name = "nvec-mouse",
+ .id = 1,
+ },
+ {
+ .name = "nvec-power",
+ .id = 1,
+ },
+ {
+ .name = "nvec-power",
+ .id = 2,
+ },
+ {
+ .name = "nvec-leds",
+ .id = 1,
+ },
+};
+
+/**
+ * nvec_register_notifier - Register a notifier with nvec
+ * @nvec: A &struct nvec_chip
+ * @nb: The notifier block to register
+ *
+ * Registers a notifier with @nvec. The notifier will be added to an atomic
+ * notifier chain that is called for all received messages except those that
+ * correspond to a request initiated by nvec_write_sync().
+ */
int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb,
- unsigned int events)
+ unsigned int events)
{
return atomic_notifier_chain_register(&nvec->notifier_list, nb);
}
EXPORT_SYMBOL_GPL(nvec_register_notifier);
-static int nvec_status_notifier(struct notifier_block *nb, unsigned long event_type,
- void *data)
+/**
+ * nvec_status_notifier - The final notifier
+ *
+ * Prints a message about control events not handled in the notifier
+ * chain.
+ */
+static int nvec_status_notifier(struct notifier_block *nb,
+ unsigned long event_type, void *data)
{
unsigned char *msg = (unsigned char *)data;
- int i;
- if(event_type != NVEC_CNTL)
+ if (event_type != NVEC_CNTL)
return NOTIFY_DONE;
- printk("unhandled msg type %ld, payload: ", event_type);
- for (i = 0; i < msg[1]; i++)
- printk("%0x ", msg[i+2]);
- printk("\n");
+ printk(KERN_WARNING "unhandled msg type %ld\n", event_type);
+ print_hex_dump(KERN_WARNING, "payload: ", DUMP_PREFIX_NONE, 16, 1,
+ msg, msg[1] + 2, true);
return NOTIFY_OK;
}
-void nvec_write_async(struct nvec_chip *nvec, unsigned char *data, short size)
+/**
+ * nvec_msg_alloc:
+ * @nvec: A &struct nvec_chip
+ * @category: Pool category, see &enum nvec_msg_category
+ *
+ * Allocate a single &struct nvec_msg object from the message pool of
+ * @nvec. The result shall be passed to nvec_msg_free() if no longer
+ * used.
+ *
+ * Outgoing messages are placed in the upper 75% of the pool, keeping the
+ * lower 25% available for RX buffers only. The reason is to prevent a
+ * situation where all buffers are full and a message is thus endlessly
+ * retried because the response could never be processed.
+ */
+static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec,
+ enum nvec_msg_category category)
+{
+ int i = (category == NVEC_MSG_TX) ? (NVEC_POOL_SIZE / 4) : 0;
+
+ for (; i < NVEC_POOL_SIZE; i++) {
+ if (atomic_xchg(&nvec->msg_pool[i].used, 1) == 0) {
+ dev_vdbg(nvec->dev, "INFO: Allocate %i\n", i);
+ return &nvec->msg_pool[i];
+ }
+ }
+
+ dev_err(nvec->dev, "could not allocate %s buffer\n",
+ (category == NVEC_MSG_TX) ? "TX" : "RX");
+
+ return NULL;
+}
+
+/**
+ * nvec_msg_free:
+ * @nvec: A &struct nvec_chip
+ * @msg: A message (must be allocated by nvec_msg_alloc() and belong to @nvec)
+ *
+ * Free the given message
+ */
+inline void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg)
{
- struct nvec_msg *msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT);
+ if (msg != &nvec->tx_scratch)
+ dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool);
+ atomic_set(&msg->used, 0);
+}
+EXPORT_SYMBOL_GPL(nvec_msg_free);
+
+/**
+ * nvec_msg_is_event - Return %true if @msg is an event
+ * @msg: A message
+ */
+static bool nvec_msg_is_event(struct nvec_msg *msg)
+{
+ return msg->data[0] >> 7;
+}
+
+/**
+ * nvec_msg_size - Get the size of a message
+ * @msg: The message to get the size for
+ *
+ * This only works for received messages, not for outgoing messages.
+ */
+static size_t nvec_msg_size(struct nvec_msg *msg)
+{
+ bool is_event = nvec_msg_is_event(msg);
+ int event_length = (msg->data[0] & 0x60) >> 5;
+
+ /* for variable size, payload size in byte 1 + count (1) + cmd (1) */
+ if (!is_event || event_length == NVEC_VAR_SIZE)
+ return (msg->pos || msg->size) ? (msg->data[1] + 2) : 0;
+ else if (event_length == NVEC_2BYTES)
+ return 2;
+ else if (event_length == NVEC_3BYTES)
+ return 3;
+ else
+ return 0;
+}
+
+/**
+ * nvec_gpio_set_value - Set the GPIO value
+ * @nvec: A &struct nvec_chip
+ * @value: The value to write (0 or 1)
+ *
+ * Like gpio_set_value(), but generating debugging information
+ */
+static void nvec_gpio_set_value(struct nvec_chip *nvec, int value)
+{
+ dev_dbg(nvec->dev, "GPIO changed from %u to %u\n",
+ gpio_get_value(nvec->gpio), value);
+ gpio_set_value(nvec->gpio, value);
+}
+
+/**
+ * nvec_write_async - Asynchronously write a message to NVEC
+ * @nvec: An nvec_chip instance
+ * @data: The message data, starting with the request type
+ * @size: The size of @data
+ *
+ * Queue a single message to be transferred to the embedded controller
+ * and return immediately.
+ *
+ * Returns: 0 on success, a negative error code on failure. If a failure
+ * occured, the nvec driver may print an error.
+ */
+int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
+ short size)
+{
+ struct nvec_msg *msg;
+ unsigned long flags;
+
+ msg = nvec_msg_alloc(nvec, NVEC_MSG_TX);
+
+ if (msg == NULL)
+ return -ENOMEM;
- msg->data = kzalloc(size, GFP_NOWAIT);
msg->data[0] = size;
memcpy(msg->data + 1, data, size);
msg->size = size + 1;
- msg->pos = 0;
- INIT_LIST_HEAD(&msg->node);
+ spin_lock_irqsave(&nvec->tx_lock, flags);
list_add_tail(&msg->node, &nvec->tx_data);
+ spin_unlock_irqrestore(&nvec->tx_lock, flags);
+
+ queue_work(nvec->wq, &nvec->tx_work);
- gpio_set_value(nvec->gpio, 0);
+ return 0;
}
EXPORT_SYMBOL(nvec_write_async);
+/**
+ * nvec_write_sync - Write a message to nvec and read the response
+ * @nvec: An &struct nvec_chip
+ * @data: The data to write
+ * @size: The size of @data
+ *
+ * This is similar to nvec_write_async(), but waits for the
+ * request to be answered before returning. This function
+ * uses a mutex and can thus not be called from e.g.
+ * interrupt handlers.
+ *
+ * Returns: A pointer to the response message on success,
+ * %NULL on failure. Free with nvec_msg_free() once no longer
+ * used.
+ */
+struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
+ const unsigned char *data, short size)
+{
+ struct nvec_msg *msg;
+
+ mutex_lock(&nvec->sync_write_mutex);
+
+ nvec->sync_write_pending = (data[1] << 8) + data[0];
+
+ if (nvec_write_async(nvec, data, size) < 0)
+ return NULL;
+
+ dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n",
+ nvec->sync_write_pending);
+ if (!(wait_for_completion_timeout(&nvec->sync_write,
+ msecs_to_jiffies(2000)))) {
+ dev_warn(nvec->dev, "timeout waiting for sync write to complete\n");
+ mutex_unlock(&nvec->sync_write_mutex);
+ return NULL;
+ }
+
+ dev_dbg(nvec->dev, "nvec_sync_write: pong!\n");
+
+ msg = nvec->last_sync_msg;
+
+ mutex_unlock(&nvec->sync_write_mutex);
+
+ return msg;
+}
+EXPORT_SYMBOL(nvec_write_sync);
+
+/**
+ * nvec_request_master - Process outgoing messages
+ * @work: A &struct work_struct (the tx_worker member of &struct nvec_chip)
+ *
+ * Processes all outgoing requests by sending the request and awaiting the
+ * response, then continuing with the next request. Once a request has a
+ * matching response, it will be freed and removed from the list.
+ */
static void nvec_request_master(struct work_struct *work)
{
struct nvec_chip *nvec = container_of(work, struct nvec_chip, tx_work);
+ unsigned long flags;
+ long err;
+ struct nvec_msg *msg;
+
+ spin_lock_irqsave(&nvec->tx_lock, flags);
+ while (!list_empty(&nvec->tx_data)) {
+ msg = list_first_entry(&nvec->tx_data, struct nvec_msg, node);
+ spin_unlock_irqrestore(&nvec->tx_lock, flags);
+ nvec_gpio_set_value(nvec, 0);
+ err = wait_for_completion_interruptible_timeout(
+ &nvec->ec_transfer, msecs_to_jiffies(5000));
+
+ if (err == 0) {
+ dev_warn(nvec->dev, "timeout waiting for ec transfer\n");
+ nvec_gpio_set_value(nvec, 1);
+ msg->pos = 0;
+ }
- if(!list_empty(&nvec->tx_data)) {
- gpio_set_value(nvec->gpio, 0);
+ spin_lock_irqsave(&nvec->tx_lock, flags);
+
+ if (err > 0) {
+ list_del_init(&msg->node);
+ nvec_msg_free(nvec, msg);
+ }
}
+ spin_unlock_irqrestore(&nvec->tx_lock, flags);
}
+/**
+ * parse_msg - Print some information and call the notifiers on an RX message
+ * @nvec: A &struct nvec_chip
+ * @msg: A message received by @nvec
+ *
+ * Paarse some pieces of the message and then call the chain of notifiers
+ * registered via nvec_register_notifier.
+ */
static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg)
{
- int i;
-
- if((msg->data[0] & 1<<7) == 0 && msg->data[3]) {
- dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n", msg->data[0],
- msg->data[1], msg->data[2], msg->data[3]);
+ if ((msg->data[0] & 1 << 7) == 0 && msg->data[3]) {
+ dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n",
+ msg->data[0], msg->data[1], msg->data[2], msg->data[3]);
return -EINVAL;
}
- if ((msg->data[0] >> 7 ) == 1 && (msg->data[0] & 0x0f) == 5)
- {
- dev_warn(nvec->dev, "ec system event ");
- for (i=0; i < msg->data[1]; i++)
- dev_warn(nvec->dev, "%02x ", msg->data[2+i]);
- dev_warn(nvec->dev, "\n");
- }
+ if ((msg->data[0] >> 7) == 1 && (msg->data[0] & 0x0f) == 5)
+ print_hex_dump(KERN_WARNING, "ec system event ",
+ DUMP_PREFIX_NONE, 16, 1, msg->data,
+ msg->data[1] + 2, true);
- atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f, msg->data);
+ atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f,
+ msg->data);
return 0;
}
-static struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, unsigned char *data, short size)
-{
- down(&nvec->sync_write_mutex);
-
- nvec->sync_write_pending = (data[1] << 8) + data[0];
- nvec_write_async(nvec, data, size);
-
- dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n", nvec->sync_write_pending);
- wait_for_completion(&nvec->sync_write);
- dev_dbg(nvec->dev, "nvec_sync_write: pong!\n");
-
- up(&nvec->sync_write_mutex);
-
- return nvec->last_sync_msg;
-}
-
-/* RX worker */
+/**
+ * nvec_dispatch - Process messages received from the EC
+ * @work: A &struct work_struct (the tx_worker member of &struct nvec_chip)
+ *
+ * Process messages previously received from the EC and put into the RX
+ * queue of the &struct nvec_chip instance associated with @work.
+ */
static void nvec_dispatch(struct work_struct *work)
{
struct nvec_chip *nvec = container_of(work, struct nvec_chip, rx_work);
+ unsigned long flags;
struct nvec_msg *msg;
- while(!list_empty(&nvec->rx_data))
- {
+ spin_lock_irqsave(&nvec->rx_lock, flags);
+ while (!list_empty(&nvec->rx_data)) {
msg = list_first_entry(&nvec->rx_data, struct nvec_msg, node);
list_del_init(&msg->node);
+ spin_unlock_irqrestore(&nvec->rx_lock, flags);
- if(nvec->sync_write_pending == (msg->data[2] << 8) + msg->data[0])
- {
+ if (nvec->sync_write_pending ==
+ (msg->data[2] << 8) + msg->data[0]) {
dev_dbg(nvec->dev, "sync write completed!\n");
nvec->sync_write_pending = 0;
nvec->last_sync_msg = msg;
complete(&nvec->sync_write);
} else {
parse_msg(nvec, msg);
- if((!msg) || (!msg->data))
- dev_warn(nvec->dev, "attempt access zero pointer");
- else {
- kfree(msg->data);
- kfree(msg);
- }
+ nvec_msg_free(nvec, msg);
}
+ spin_lock_irqsave(&nvec->rx_lock, flags);
+ }
+ spin_unlock_irqrestore(&nvec->rx_lock, flags);
+}
+
+/**
+ * nvec_tx_completed - Complete the current transfer
+ * @nvec: A &struct nvec_chip
+ *
+ * This is called when we have received an END_TRANS on a TX transfer.
+ */
+static void nvec_tx_completed(struct nvec_chip *nvec)
+{
+ /* We got an END_TRANS, let's skip this, maybe there's an event */
+ if (nvec->tx->pos != nvec->tx->size) {
+ dev_err(nvec->dev, "premature END_TRANS, resending\n");
+ nvec->tx->pos = 0;
+ nvec_gpio_set_value(nvec, 0);
+ } else {
+ nvec->state = 0;
}
}
-static irqreturn_t i2c_interrupt(int irq, void *dev)
+/**
+ * nvec_rx_completed - Complete the current transfer
+ * @nvec: A &struct nvec_chip
+ *
+ * This is called when we have received an END_TRANS on a RX transfer.
+ */
+static void nvec_rx_completed(struct nvec_chip *nvec)
+{
+ if (nvec->rx->pos != nvec_msg_size(nvec->rx)) {
+ dev_err(nvec->dev, "RX incomplete: Expected %u bytes, got %u\n",
+ (uint) nvec_msg_size(nvec->rx),
+ (uint) nvec->rx->pos);
+
+ nvec_msg_free(nvec, nvec->rx);
+ nvec->state = 0;
+
+ /* Battery quirk - Often incomplete, and likes to crash */
+ if (nvec->rx->data[0] == NVEC_BAT)
+ complete(&nvec->ec_transfer);
+
+ return;
+ }
+
+ spin_lock(&nvec->rx_lock);
+
+ /* add the received data to the work list
+ and move the ring buffer pointer to the next entry */
+ list_add_tail(&nvec->rx->node, &nvec->rx_data);
+
+ spin_unlock(&nvec->rx_lock);
+
+ nvec->state = 0;
+
+ if (!nvec_msg_is_event(nvec->rx))
+ complete(&nvec->ec_transfer);
+
+ queue_work(nvec->wq, &nvec->rx_work);
+}
+
+/**
+ * nvec_invalid_flags - Send an error message about invalid flags and jump
+ * @nvec: The nvec device
+ * @status: The status flags
+ * @reset: Whether we shall jump to state 0.
+ */
+static void nvec_invalid_flags(struct nvec_chip *nvec, unsigned int status,
+ bool reset)
+{
+ dev_err(nvec->dev, "unexpected status flags 0x%02x during state %i\n",
+ status, nvec->state);
+ if (reset)
+ nvec->state = 0;
+}
+
+/**
+ * nvec_tx_set - Set the message to transfer (nvec->tx)
+ * @nvec: A &struct nvec_chip
+ *
+ * Gets the first entry from the tx_data list of @nvec and sets the
+ * tx member to it. If the tx_data list is empty, this uses the
+ * tx_scratch message to send a no operation message.
+ */
+static void nvec_tx_set(struct nvec_chip *nvec)
+{
+ spin_lock(&nvec->tx_lock);
+ if (list_empty(&nvec->tx_data)) {
+ dev_err(nvec->dev, "empty tx - sending no-op\n");
+ memcpy(nvec->tx_scratch.data, "\x02\x07\x02", 3);
+ nvec->tx_scratch.size = 3;
+ nvec->tx_scratch.pos = 0;
+ nvec->tx = &nvec->tx_scratch;
+ list_add_tail(&nvec->tx->node, &nvec->tx_data);
+ } else {
+ nvec->tx = list_first_entry(&nvec->tx_data, struct nvec_msg,
+ node);
+ nvec->tx->pos = 0;
+ }
+ spin_unlock(&nvec->tx_lock);
+
+ dev_dbg(nvec->dev, "Sending message of length %u, command 0x%x\n",
+ (uint)nvec->tx->size, nvec->tx->data[1]);
+}
+
+/**
+ * nvec_interrupt - Interrupt handler
+ * @irq: The IRQ
+ * @dev: The nvec device
+ *
+ * Interrupt handler that fills our RX buffers and empties our TX
+ * buffers. This uses a finite state machine with ridiculous amounts
+ * of error checking, in order to be fairly reliable.
+ */
+static irqreturn_t nvec_interrupt(int irq, void *dev)
{
unsigned long status;
- unsigned long received;
- unsigned char to_send;
- struct nvec_msg *msg;
- struct nvec_chip *nvec = (struct nvec_chip *)dev;
- unsigned char *i2c_regs = nvec->i2c_regs;
+ unsigned int received = 0;
+ unsigned char to_send = 0xff;
+ const unsigned long irq_mask = I2C_SL_IRQ | END_TRANS | RCVD | RNW;
+ struct nvec_chip *nvec = dev;
+ unsigned int state = nvec->state;
- status = readl(i2c_regs + I2C_SL_STATUS);
+ status = readl(nvec->base + I2C_SL_STATUS);
- if(!(status & I2C_SL_IRQ))
- {
- dev_warn(nvec->dev, "nvec Spurious IRQ\n");
- //Yup, handled. ahum.
- goto handled;
+ /* Filter out some errors */
+ if ((status & irq_mask) == 0 && (status & ~irq_mask) != 0) {
+ dev_err(nvec->dev, "unexpected irq mask %lx\n", status);
+ return IRQ_HANDLED;
}
- if(status & END_TRANS && !(status & RCVD))
- {
- //Reenable IRQ only when even has been sent
- //printk("Write sequence ended !\n");
- //parse_msg(nvec);
- nvec->state = NVEC_WAIT;
- if(nvec->rx->size > 1)
- {
- list_add_tail(&nvec->rx->node, &nvec->rx_data);
- schedule_work(&nvec->rx_work);
+ if ((status & I2C_SL_IRQ) == 0) {
+ dev_err(nvec->dev, "Spurious IRQ\n");
+ return IRQ_HANDLED;
+ }
+
+ /* The EC did not request a read, so it send us something, read it */
+ if ((status & RNW) == 0) {
+ received = readl(nvec->base + I2C_SL_RCVD);
+ if (status & RCVD)
+ writel(0, nvec->base + I2C_SL_RCVD);
+ }
+
+ if (status == (I2C_SL_IRQ | RCVD))
+ nvec->state = 0;
+
+ switch (nvec->state) {
+ case 0: /* Verify that its a transfer start, the rest later */
+ if (status != (I2C_SL_IRQ | RCVD))
+ nvec_invalid_flags(nvec, status, false);
+ break;
+ case 1: /* command byte */
+ if (status != I2C_SL_IRQ) {
+ nvec_invalid_flags(nvec, status, true);
} else {
- kfree(nvec->rx->data);
- kfree(nvec->rx);
+ nvec->rx = nvec_msg_alloc(nvec, NVEC_MSG_RX);
+ /* Should not happen in a normal world */
+ if (unlikely(nvec->rx == NULL)) {
+ nvec->state = 0;
+ break;
+ }
+ nvec->rx->data[0] = received;
+ nvec->rx->pos = 1;
+ nvec->state = 2;
}
- return IRQ_HANDLED;
- } else if(status & RNW)
- {
- // Work around for AP20 New Slave Hw Bug. Give 1us extra.
- // nvec/smbus/nvec_i2c_transport.c in NV`s crap for reference
- if(status & RCVD)
- udelay(3);
-
- if(status & RCVD)
- {
- nvec->state = NVEC_WRITE;
- //Master wants something from us. New communication
-// dev_dbg(nvec->dev, "New read comm!\n");
+ break;
+ case 2: /* first byte after command */
+ if (status == (I2C_SL_IRQ | RNW | RCVD)) {
+ udelay(33);
+ if (nvec->rx->data[0] != 0x01) {
+ dev_err(nvec->dev,
+ "Read without prior read command\n");
+ nvec->state = 0;
+ break;
+ }
+ nvec_msg_free(nvec, nvec->rx);
+ nvec->state = 3;
+ nvec_tx_set(nvec);
+ BUG_ON(nvec->tx->size < 1);
+ to_send = nvec->tx->data[0];
+ nvec->tx->pos = 1;
+ } else if (status == (I2C_SL_IRQ)) {
+ BUG_ON(nvec->rx == NULL);
+ nvec->rx->data[1] = received;
+ nvec->rx->pos = 2;
+ nvec->state = 4;
} else {
- //Master wants something from us from a communication we've already started
-// dev_dbg(nvec->dev, "Read comm cont !\n");
+ nvec_invalid_flags(nvec, status, true);
}
- //if(msg_pos<msg_size) {
- if(list_empty(&nvec->tx_data))
- {
- dev_err(nvec->dev, "nvec empty tx - sending no-op\n");
- to_send = 0x8a;
- nvec_write_async(nvec, "\x07\x02", 2);
-// to_send = 0x01;
+ break;
+ case 3: /* EC does a block read, we transmit data */
+ if (status & END_TRANS) {
+ nvec_tx_completed(nvec);
+ } else if ((status & RNW) == 0 || (status & RCVD)) {
+ nvec_invalid_flags(nvec, status, true);
+ } else if (nvec->tx && nvec->tx->pos < nvec->tx->size) {
+ to_send = nvec->tx->data[nvec->tx->pos++];
} else {
- msg = list_first_entry(&nvec->tx_data, struct nvec_msg, node);
- if(msg->pos < msg->size) {
- to_send = msg->data[msg->pos];
- msg->pos++;
- } else {
- dev_err(nvec->dev, "nvec crap! %d\n", msg->size);
- to_send = 0x01;
- }
-
- if(msg->pos >= msg->size)
- {
- list_del_init(&msg->node);
- kfree(msg->data);
- kfree(msg);
- schedule_work(&nvec->tx_work);
- nvec->state = NVEC_WAIT;
- }
+ dev_err(nvec->dev, "tx buffer underflow on %p (%u > %u)\n",
+ nvec->tx,
+ (uint) (nvec->tx ? nvec->tx->pos : 0),
+ (uint) (nvec->tx ? nvec->tx->size : 0));
+ nvec->state = 0;
}
- writel(to_send, i2c_regs + I2C_SL_RCVD);
-
- gpio_set_value(nvec->gpio, 1);
+ break;
+ case 4: /* EC does some write, we read the data */
+ if ((status & (END_TRANS | RNW)) == END_TRANS)
+ nvec_rx_completed(nvec);
+ else if (status & (RNW | RCVD))
+ nvec_invalid_flags(nvec, status, true);
+ else if (nvec->rx && nvec->rx->pos < NVEC_MSG_SIZE)
+ nvec->rx->data[nvec->rx->pos++] = received;
+ else
+ dev_err(nvec->dev,
+ "RX buffer overflow on %p: "
+ "Trying to write byte %u of %u\n",
+ nvec->rx, nvec->rx->pos, NVEC_MSG_SIZE);
+ break;
+ default:
+ nvec->state = 0;
+ }
- dev_dbg(nvec->dev, "nvec sent %x\n", to_send);
+ /* If we are told that a new transfer starts, verify it */
+ if ((status & (RCVD | RNW)) == RCVD) {
+ if (received != nvec->i2c_addr)
+ dev_err(nvec->dev,
+ "received address 0x%02x, expected 0x%02x\n",
+ received, nvec->i2c_addr);
+ nvec->state = 1;
+ }
- goto handled;
- } else {
- received = readl(i2c_regs + I2C_SL_RCVD);
- //Workaround?
- if(status & RCVD) {
- writel(0, i2c_regs + I2C_SL_RCVD);
- goto handled;
- }
+ /* Send data if requested, but not on end of transmission */
+ if ((status & (RNW | END_TRANS)) == RNW)
+ writel(to_send, nvec->base + I2C_SL_RCVD);
+
+ /* If we have send the first byte */
+ if (status == (I2C_SL_IRQ | RNW | RCVD))
+ nvec_gpio_set_value(nvec, 1);
+
+ dev_dbg(nvec->dev,
+ "Handled: %s 0x%02x, %s 0x%02x in state %u [%s%s%s]\n",
+ (status & RNW) == 0 ? "received" : "R=",
+ received,
+ (status & (RNW | END_TRANS)) ? "sent" : "S=",
+ to_send,
+ state,
+ status & END_TRANS ? " END_TRANS" : "",
+ status & RCVD ? " RCVD" : "",
+ status & RNW ? " RNW" : "");
+
+
+ /*
+ * TODO: A correct fix needs to be found for this.
+ *
+ * We experience less incomplete messages with this delay than without
+ * it, but we don't know why. Help is appreciated.
+ */
+ udelay(100);
- if (nvec->state == NVEC_WAIT)
- {
- nvec->state = NVEC_READ;
- msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT);
- msg->data = kzalloc(32, GFP_NOWAIT);
- INIT_LIST_HEAD(&msg->node);
- nvec->rx = msg;
- } else
- msg = nvec->rx;
-
- BUG_ON(msg->pos > 32);
-
- msg->data[msg->pos] = received;
- msg->pos++;
- msg->size = msg->pos;
- dev_dbg(nvec->dev, "Got %02lx from Master (pos: %d)!\n", received, msg->pos);
- }
-handled:
return IRQ_HANDLED;
}
-static int __devinit nvec_add_subdev(struct nvec_chip *nvec, struct nvec_subdev *subdev)
+static void tegra_init_i2c_slave(struct nvec_chip *nvec)
{
- struct platform_device *pdev;
+ u32 val;
- pdev = platform_device_alloc(subdev->name, subdev->id);
- pdev->dev.parent = nvec->dev;
- pdev->dev.platform_data = subdev->platform_data;
+ clk_enable(nvec->i2c_clk);
- return platform_device_add(pdev);
-}
+ tegra_periph_reset_assert(nvec->i2c_clk);
+ udelay(2);
+ tegra_periph_reset_deassert(nvec->i2c_clk);
-static void tegra_init_i2c_slave(struct nvec_platform_data *pdata, unsigned char *i2c_regs,
- struct clk *i2c_clk)
-{
- u32 val;
+ val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN |
+ (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
+ writel(val, nvec->base + I2C_CNFG);
- clk_enable(i2c_clk);
- tegra_periph_reset_assert(i2c_clk);
- udelay(2);
- tegra_periph_reset_deassert(i2c_clk);
+ clk_set_rate(nvec->i2c_clk, 8 * 80000);
- writel(pdata->i2c_addr>>1, i2c_regs + I2C_SL_ADDR1);
- writel(0, i2c_regs + I2C_SL_ADDR2);
+ writel(I2C_SL_NEWL, nvec->base + I2C_SL_CNFG);
+ writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT);
- writel(0x1E, i2c_regs + I2C_SL_DELAY_COUNT);
- val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN |
- (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
- writel(val, i2c_regs + I2C_CNFG);
- writel(I2C_SL_NEWL, i2c_regs + I2C_SL_CNFG);
+ writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1);
+ writel(0, nvec->base + I2C_SL_ADDR2);
+
+ enable_irq(nvec->irq);
- clk_disable(i2c_clk);
+ clk_disable(nvec->i2c_clk);
+}
+
+static void nvec_disable_i2c_slave(struct nvec_chip *nvec)
+{
+ disable_irq(nvec->irq);
+ writel(I2C_SL_NEWL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG);
+ clk_disable(nvec->i2c_clk);
}
static void nvec_power_off(void)
@@ -300,86 +711,96 @@ static void nvec_power_off(void)
static int __devinit tegra_nvec_probe(struct platform_device *pdev)
{
- int err, i, ret;
+ int err, ret;
struct clk *i2c_clk;
struct nvec_platform_data *pdata = pdev->dev.platform_data;
struct nvec_chip *nvec;
struct nvec_msg *msg;
- unsigned char *i2c_regs;
+ struct resource *res;
+ struct resource *iomem;
+ void __iomem *base;
nvec = kzalloc(sizeof(struct nvec_chip), GFP_KERNEL);
- if(nvec == NULL) {
+ if (nvec == NULL) {
dev_err(&pdev->dev, "failed to reserve memory\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, nvec);
nvec->dev = &pdev->dev;
nvec->gpio = pdata->gpio;
- nvec->irq = pdata->irq;
+ nvec->i2c_addr = pdata->i2c_addr;
-/*
- i2c_clk=clk_get_sys(NULL, "i2c");
- if(IS_ERR_OR_NULL(i2c_clk))
- printk(KERN_ERR"No such clock tegra-i2c.2\n");
- else
- clk_enable(i2c_clk);
-*/
- i2c_regs = ioremap(pdata->base, pdata->size);
- if(!i2c_regs) {
- dev_err(nvec->dev, "failed to ioremap registers\n");
- goto failed;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ return -ENODEV;
}
- nvec->i2c_regs = i2c_regs;
+ iomem = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (!iomem) {
+ dev_err(&pdev->dev, "I2C region already claimed\n");
+ return -EBUSY;
+ }
- i2c_clk = clk_get_sys(pdata->clock, NULL);
- if(IS_ERR_OR_NULL(i2c_clk)) {
- dev_err(nvec->dev, "failed to get clock tegra-i2c.2\n");
- goto failed;
+ base = ioremap(iomem->start, resource_size(iomem));
+ if (!base) {
+ dev_err(&pdev->dev, "Can't ioremap I2C region\n");
+ return -ENOMEM;
}
- tegra_init_i2c_slave(pdata, i2c_regs, i2c_clk);
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ ret = -ENODEV;
+ goto err_iounmap;
+ }
- err = request_irq(nvec->irq, i2c_interrupt, IRQF_DISABLED, "nvec", nvec);
- if(err) {
- dev_err(nvec->dev, "couldn't request irq");
- goto failed;
+ i2c_clk = clk_get_sys("tegra-i2c.2", NULL);
+ if (IS_ERR(i2c_clk)) {
+ dev_err(nvec->dev, "failed to get controller clock\n");
+ goto err_iounmap;
}
- clk_enable(i2c_clk);
- clk_set_rate(i2c_clk, 8*80000);
+ nvec->base = base;
+ nvec->irq = res->start;
+ nvec->i2c_clk = i2c_clk;
+ nvec->rx = &nvec->msg_pool[0];
/* Set the gpio to low when we've got something to say */
err = gpio_request(nvec->gpio, "nvec gpio");
- if(err < 0)
+ if (err < 0)
dev_err(nvec->dev, "couldn't request gpio\n");
- tegra_gpio_enable(nvec->gpio);
- gpio_direction_output(nvec->gpio, 1);
- gpio_set_value(nvec->gpio, 1);
-
ATOMIC_INIT_NOTIFIER_HEAD(&nvec->notifier_list);
init_completion(&nvec->sync_write);
- sema_init(&nvec->sync_write_mutex, 1);
- INIT_LIST_HEAD(&nvec->tx_data);
+ init_completion(&nvec->ec_transfer);
+ mutex_init(&nvec->sync_write_mutex);
+ spin_lock_init(&nvec->tx_lock);
+ spin_lock_init(&nvec->rx_lock);
INIT_LIST_HEAD(&nvec->rx_data);
+ INIT_LIST_HEAD(&nvec->tx_data);
INIT_WORK(&nvec->rx_work, nvec_dispatch);
INIT_WORK(&nvec->tx_work, nvec_request_master);
+ nvec->wq = alloc_workqueue("nvec", WQ_NON_REENTRANT, 2);
- /* enable event reporting */
- nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING,
- sizeof(EC_ENABLE_EVENT_REPORTING));
+ err = request_irq(nvec->irq, nvec_interrupt, 0, "nvec", nvec);
+ if (err) {
+ dev_err(nvec->dev, "couldn't request irq\n");
+ goto failed;
+ }
+ disable_irq(nvec->irq);
- nvec_kbd_init(nvec);
-#ifdef CONFIG_SERIO_NVEC_PS2
- nvec_ps2(nvec);
-#endif
+ tegra_init_i2c_slave(nvec);
- /* setup subdevs */
- for (i = 0; i < pdata->num_subdevs; i++) {
- ret = nvec_add_subdev(nvec, &pdata->subdevs[i]);
- }
+ clk_enable(i2c_clk);
+
+ gpio_direction_output(nvec->gpio, 1);
+ gpio_set_value(nvec->gpio, 1);
+
+ /* enable event reporting */
+ nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING,
+ sizeof(EC_ENABLE_EVENT_REPORTING));
nvec->nvec_status_notifier.notifier_call = nvec_status_notifier;
nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0);
@@ -391,14 +812,20 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
msg = nvec_write_sync(nvec, EC_GET_FIRMWARE_VERSION,
sizeof(EC_GET_FIRMWARE_VERSION));
- dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n",
+ if (msg) {
+ dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n",
msg->data[4], msg->data[5], msg->data[6], msg->data[7]);
- kfree(msg->data);
- kfree(msg);
+ nvec_msg_free(nvec, msg);
+ }
+
+ ret = mfd_add_devices(nvec->dev, -1, nvec_devices,
+ ARRAY_SIZE(nvec_devices), base, 0);
+ if (ret)
+ dev_err(nvec->dev, "error adding subdevices\n");
/* unmute speakers? */
- nvec_write_async(nvec, "\x0d\x10\x59\x94", 4);
+ nvec_write_async(nvec, "\x0d\x10\x59\x95", 4);
/* enable lid switch event */
nvec_write_async(nvec, "\x01\x01\x01\x00\x00\x02\x00", 7);
@@ -408,6 +835,8 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
return 0;
+err_iounmap:
+ iounmap(base);
failed:
kfree(nvec);
return -ENOMEM;
@@ -415,7 +844,16 @@ failed:
static int __devexit tegra_nvec_remove(struct platform_device *pdev)
{
- // TODO: unregister
+ struct nvec_chip *nvec = platform_get_drvdata(pdev);
+
+ nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3);
+ mfd_remove_devices(nvec->dev);
+ free_irq(nvec->irq, &nvec_interrupt);
+ iounmap(nvec->base);
+ gpio_free(nvec->gpio);
+ destroy_workqueue(nvec->wq);
+ kfree(nvec);
+
return 0;
}
@@ -424,19 +862,27 @@ static int __devexit tegra_nvec_remove(struct platform_device *pdev)
static int tegra_nvec_suspend(struct platform_device *pdev, pm_message_t state)
{
struct nvec_chip *nvec = platform_get_drvdata(pdev);
+ struct nvec_msg *msg;
dev_dbg(nvec->dev, "suspending\n");
- nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3);
- nvec_write_async(nvec, "\x04\x02", 2);
+
+ /* keep these sync or you'll break suspend */
+ msg = nvec_write_sync(nvec, EC_DISABLE_EVENT_REPORTING, 3);
+ nvec_msg_free(nvec, msg);
+ msg = nvec_write_sync(nvec, "\x04\x02", 2);
+ nvec_msg_free(nvec, msg);
+
+ nvec_disable_i2c_slave(nvec);
return 0;
}
-static int tegra_nvec_resume(struct platform_device *pdev) {
-
+static int tegra_nvec_resume(struct platform_device *pdev)
+{
struct nvec_chip *nvec = platform_get_drvdata(pdev);
dev_dbg(nvec->dev, "resuming\n");
+ tegra_init_i2c_slave(nvec);
nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, 3);
return 0;
@@ -447,13 +893,12 @@ static int tegra_nvec_resume(struct platform_device *pdev) {
#define tegra_nvec_resume NULL
#endif
-static struct platform_driver nvec_device_driver =
-{
- .probe = tegra_nvec_probe,
- .remove = __devexit_p(tegra_nvec_remove),
+static struct platform_driver nvec_device_driver = {
+ .probe = tegra_nvec_probe,
+ .remove = __devexit_p(tegra_nvec_remove),
.suspend = tegra_nvec_suspend,
- .resume = tegra_nvec_resume,
- .driver = {
+ .resume = tegra_nvec_resume,
+ .driver = {
.name = "nvec",
.owner = THIS_MODULE,
}
@@ -465,4 +910,8 @@ static int __init tegra_nvec_init(void)
}
module_init(tegra_nvec_init);
+
MODULE_ALIAS("platform:nvec");
+MODULE_DESCRIPTION("NVIDIA compliant embedded controller interface");
+MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h
index a2d82dc..a4c17b0 100644
--- a/drivers/staging/nvec/nvec.h
+++ b/drivers/staging/nvec/nvec.h
@@ -1,110 +1,203 @@
+/*
+ * NVEC: NVIDIA compliant embedded controller interface
+ *
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
+ *
+ * Authors: Pierre-Hugues Husson <phhusson@free.fr>
+ * Ilya Petrov <ilya.muromec@gmail.com>
+ * Marc Dietrich <marvin24@gmx.de>
+ * Julian Andres Klode <jak@jak-linux.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
#ifndef __LINUX_MFD_NVEC
#define __LINUX_MFD_NVEC
-#include <linux/semaphore.h>
-
-typedef enum {
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+/* NVEC_POOL_SIZE - Size of the pool in &struct nvec_msg */
+#define NVEC_POOL_SIZE 64
+
+/*
+ * NVEC_MSG_SIZE - Maximum size of the data field of &struct nvec_msg.
+ *
+ * A message must store up to a SMBus block operation which consists of
+ * one command byte, one count byte, and up to 32 payload bytes = 34
+ * byte.
+ */
+#define NVEC_MSG_SIZE 34
+
+/**
+ * enum nvec_event_size - The size of an event message
+ * @NVEC_2BYTES: The message has one command byte and one data byte
+ * @NVEC_3BYTES: The message has one command byte and two data bytes
+ * @NVEC_VAR_SIZE: The message has one command byte, one count byte, and as
+ * up to as many bytes as the number in the count byte. The
+ * maximum is 32
+ *
+ * Events can be fixed or variable sized. This is useless on other message
+ * types, which are always variable sized.
+ */
+enum nvec_event_size {
NVEC_2BYTES,
NVEC_3BYTES,
- NVEC_VAR_SIZE
-} nvec_size;
-
-typedef enum {
- NOT_REALLY,
- YES,
- NOT_AT_ALL,
-} how_care;
+ NVEC_VAR_SIZE,
+};
-typedef enum {
- NVEC_SYS=1,
+/**
+ * enum nvec_msg_type - The type of a message
+ * @NVEC_SYS: A system request/response
+ * @NVEC_BAT: A battery request/response
+ * @NVEC_KBD: A keyboard request/response
+ * @NVEC_PS2: A mouse request/response
+ * @NVEC_CNTL: A EC control request/response
+ * @NVEC_KB_EVT: An event from the keyboard
+ * @NVEC_PS2_EVT: An event from the mouse
+ *
+ * Events can be fixed or variable sized. This is useless on other message
+ * types, which are always variable sized.
+ */
+enum nvec_msg_type {
+ NVEC_SYS = 1,
NVEC_BAT,
NVEC_KBD = 5,
NVEC_PS2,
NVEC_CNTL,
NVEC_KB_EVT = 0x80,
- NVEC_PS2_EVT
-} nvec_event;
-
-typedef enum {
- NVEC_WAIT,
- NVEC_READ,
- NVEC_WRITE
-} nvec_state;
+ NVEC_PS2_EVT,
+};
+/**
+ * struct nvec_msg - A buffer for a single message
+ * @node: Messages are part of various lists in a &struct nvec_chip
+ * @data: The data of the message
+ * @size: For TX messages, the number of bytes used in @data
+ * @pos: For RX messages, the current position to write to. For TX messages,
+ * the position to read from.
+ * @used: Used for the message pool to mark a message as free/allocated.
+ *
+ * This structure is used to hold outgoing and incoming messages. Outgoing
+ * messages have a different format than incoming messages, and that is not
+ * documented yet.
+ */
struct nvec_msg {
- unsigned char *data;
+ struct list_head node;
+ unsigned char data[NVEC_MSG_SIZE];
unsigned short size;
unsigned short pos;
- struct list_head node;
+ atomic_t used;
};
+/**
+ * struct nvec_subdev - A subdevice of nvec, such as nvec_kbd
+ * @name: The name of the sub device
+ * @platform_data: Platform data
+ * @id: Identifier of the sub device
+ */
struct nvec_subdev {
const char *name;
void *platform_data;
int id;
};
+/**
+ * struct nvec_platform_data - platform data for a tegra slave controller
+ * @i2c_addr: number of i2c slave adapter the ec is connected to
+ * @gpio: gpio number for the ec request line
+ *
+ * Platform data, to be used in board definitions. For an example, take a
+ * look at the paz00 board in arch/arm/mach-tegra/board-paz00.c
+ */
struct nvec_platform_data {
- int num_subdevs;
int i2c_addr;
int gpio;
- int irq;
- int base;
- int size;
- char clock[16];
- struct nvec_subdev *subdevs;
};
+/**
+ * struct nvec_chip - A single connection to an NVIDIA Embedded controller
+ * @dev: The device
+ * @gpio: The same as for &struct nvec_platform_data
+ * @irq: The IRQ of the I2C device
+ * @i2c_addr: The address of the I2C slave
+ * @base: The base of the memory mapped region of the I2C device
+ * @clk: The clock of the I2C device
+ * @notifier_list: Notifiers to be called on received messages, see
+ * nvec_register_notifier()
+ * @rx_data: Received messages that have to be processed
+ * @tx_data: Messages waiting to be sent to the controller
+ * @nvec_status_notifier: Internal notifier (see nvec_status_notifier())
+ * @rx_work: A work structure for the RX worker nvec_dispatch()
+ * @tx_work: A work structure for the TX worker nvec_request_master()
+ * @wq: The work queue in which @rx_work and @tx_work are executed
+ * @rx: The message currently being retrieved or %NULL
+ * @msg_pool: A pool of messages for allocation
+ * @tx: The message currently being transferred
+ * @tx_scratch: Used for building pseudo messages
+ * @ec_transfer: A completion that will be completed once a message has been
+ * received (see nvec_rx_completed())
+ * @tx_lock: Spinlock for modifications on @tx_data
+ * @rx_lock: Spinlock for modifications on @rx_data
+ * @sync_write_mutex: A mutex for nvec_write_sync()
+ * @sync_write: A completion to signal that a synchronous message is complete
+ * @sync_write_pending: The first two bytes of the request (type and subtype)
+ * @last_sync_msg: The last synchronous message.
+ * @state: State of our finite state machine used in nvec_interrupt()
+ */
struct nvec_chip {
struct device *dev;
int gpio;
int irq;
- unsigned char *i2c_regs;
- nvec_state state;
+ int i2c_addr;
+ void __iomem *base;
+ struct clk *i2c_clk;
struct atomic_notifier_head notifier_list;
struct list_head rx_data, tx_data;
struct notifier_block nvec_status_notifier;
struct work_struct rx_work, tx_work;
- struct nvec_msg *rx, *tx;
+ struct workqueue_struct *wq;
+ struct nvec_msg msg_pool[NVEC_POOL_SIZE];
+ struct nvec_msg *rx;
+
+ struct nvec_msg *tx;
+ struct nvec_msg tx_scratch;
+ struct completion ec_transfer;
+
+ spinlock_t tx_lock, rx_lock;
-/* sync write stuff */
- struct semaphore sync_write_mutex;
+ /* sync write stuff */
+ struct mutex sync_write_mutex;
struct completion sync_write;
u16 sync_write_pending;
struct nvec_msg *last_sync_msg;
+
+ int state;
};
-extern void nvec_write_async(struct nvec_chip *nvec, unsigned char *data, short size);
+extern int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
+ short size);
+
+extern struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
+ const unsigned char *data, short size);
extern int nvec_register_notifier(struct nvec_chip *nvec,
- struct notifier_block *nb, unsigned int events);
+ struct notifier_block *nb,
+ unsigned int events);
extern int nvec_unregister_notifier(struct device *dev,
- struct notifier_block *nb, unsigned int events);
-
-const char *nvec_send_msg(unsigned char *src, unsigned char *dst_size, how_care care_resp, void (*rt_handler)(unsigned char *data));
-
-extern int nvec_ps2(struct nvec_chip *nvec);
-extern int nvec_kbd_init(struct nvec_chip *nvec);
-
-#define I2C_CNFG 0x00
-#define I2C_CNFG_PACKET_MODE_EN (1<<10)
-#define I2C_CNFG_NEW_MASTER_SFM (1<<11)
-#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12
-
-#define I2C_SL_CNFG 0x20
-#define I2C_SL_NEWL (1<<2)
-#define I2C_SL_NACK (1<<1)
-#define I2C_SL_RESP (1<<0)
-#define I2C_SL_IRQ (1<<3)
-#define END_TRANS (1<<4)
-#define RCVD (1<<2)
-#define RNW (1<<1)
-
-#define I2C_SL_RCVD 0x24
-#define I2C_SL_STATUS 0x28
-#define I2C_SL_ADDR1 0x2c
-#define I2C_SL_ADDR2 0x30
-#define I2C_SL_DELAY_COUNT 0x3c
+ struct notifier_block *nb,
+ unsigned int events);
+
+extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
#endif
diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
index 9a98507..a4ce5a7 100644
--- a/drivers/staging/nvec/nvec_kbd.c
+++ b/drivers/staging/nvec/nvec_kbd.c
@@ -1,42 +1,76 @@
+/*
+ * nvec_kbd: keyboard driver for a NVIDIA compliant embedded controller
+ *
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
+ *
+ * Authors: Pierre-Hugues Husson <phhusson@free.fr>
+ * Marc Dietrich <marvin24@gmx.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/delay.h>
+#include <linux/platform_device.h>
+
#include "nvec-keytable.h"
#include "nvec.h"
-#define ACK_KBD_EVENT {'\x05','\xed','\x01'}
+#define ACK_KBD_EVENT {'\x05', '\xed', '\x01'}
+static const char led_on[3] = "\x05\xed\x07";
+static const char led_off[3] = "\x05\xed\x00";
static unsigned char keycodes[ARRAY_SIZE(code_tab_102us)
- + ARRAY_SIZE(extcode_tab_us102)];
+ + ARRAY_SIZE(extcode_tab_us102)];
struct nvec_keys {
struct input_dev *input;
struct notifier_block notifier;
struct nvec_chip *nvec;
+ bool caps_lock;
};
static struct nvec_keys keys_dev;
+static void nvec_kbd_toggle_led(void)
+{
+ keys_dev.caps_lock = !keys_dev.caps_lock;
+
+ if (keys_dev.caps_lock)
+ nvec_write_async(keys_dev.nvec, led_on, sizeof(led_on));
+ else
+ nvec_write_async(keys_dev.nvec, led_off, sizeof(led_off));
+}
+
static int nvec_keys_notifier(struct notifier_block *nb,
- unsigned long event_type, void *data)
+ unsigned long event_type, void *data)
{
int code, state;
unsigned char *msg = (unsigned char *)data;
if (event_type == NVEC_KB_EVT) {
- nvec_size _size = (msg[0] & (3 << 5)) >> 5;
+ int _size = (msg[0] & (3 << 5)) >> 5;
/* power on/off button */
- if(_size == NVEC_VAR_SIZE)
+ if (_size == NVEC_VAR_SIZE)
return NOTIFY_STOP;
- if(_size == NVEC_3BYTES)
+ if (_size == NVEC_3BYTES)
msg++;
code = msg[1] & 0x7f;
state = msg[1] & 0x80;
- input_report_key(keys_dev.input, code_tabs[_size][code], !state);
+ if (code_tabs[_size][code] == KEY_CAPSLOCK && state)
+ nvec_kbd_toggle_led();
+
+ input_report_key(keys_dev.input, code_tabs[_size][code],
+ !state);
input_sync(keys_dev.input);
return NOTIFY_STOP;
@@ -46,18 +80,18 @@ static int nvec_keys_notifier(struct notifier_block *nb,
}
static int nvec_kbd_event(struct input_dev *dev, unsigned int type,
- unsigned int code, int value)
+ unsigned int code, int value)
{
unsigned char buf[] = ACK_KBD_EVENT;
struct nvec_chip *nvec = keys_dev.nvec;
- if(type==EV_REP)
+ if (type == EV_REP)
return 0;
- if(type!=EV_LED)
+ if (type != EV_LED)
return -1;
- if(code!=LED_CAPSL)
+ if (code != LED_CAPSL)
return -1;
buf[2] = !!value;
@@ -66,22 +100,23 @@ static int nvec_kbd_event(struct input_dev *dev, unsigned int type,
return 0;
}
-int __init nvec_kbd_init(struct nvec_chip *nvec)
+static int __devinit nvec_kbd_probe(struct platform_device *pdev)
{
+ struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
int i, j, err;
struct input_dev *idev;
j = 0;
- for(i = 0; i < ARRAY_SIZE(code_tab_102us); ++i)
+ for (i = 0; i < ARRAY_SIZE(code_tab_102us); ++i)
keycodes[j++] = code_tab_102us[i];
- for(i = 0; i < ARRAY_SIZE(extcode_tab_us102); ++i)
- keycodes[j++]=extcode_tab_us102[i];
+ for (i = 0; i < ARRAY_SIZE(extcode_tab_us102); ++i)
+ keycodes[j++] = extcode_tab_us102[i];
idev = input_allocate_device();
- idev->name = "Tegra nvec keyboard";
- idev->phys = "i2c3_slave/nvec";
+ idev->name = "nvec keyboard";
+ idev->phys = "nvec";
idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_LED);
idev->ledbit[0] = BIT_MASK(LED_CAPSL);
idev->event = nvec_kbd_event;
@@ -89,12 +124,12 @@ int __init nvec_kbd_init(struct nvec_chip *nvec)
idev->keycodesize = sizeof(unsigned char);
idev->keycodemax = ARRAY_SIZE(keycodes);
- for( i = 0; i < ARRAY_SIZE(keycodes); ++i)
+ for (i = 0; i < ARRAY_SIZE(keycodes); ++i)
set_bit(keycodes[i], idev->keybit);
clear_bit(0, idev->keybit);
err = input_register_device(idev);
- if(err)
+ if (err)
goto fail;
keys_dev.input = idev;
@@ -114,9 +149,31 @@ int __init nvec_kbd_init(struct nvec_chip *nvec)
or until we have a sync write */
mdelay(1000);
+ /* Disable caps lock LED */
+ nvec_write_async(nvec, led_off, sizeof(led_off));
+
return 0;
fail:
input_free_device(idev);
return err;
}
+
+static struct platform_driver nvec_kbd_driver = {
+ .probe = nvec_kbd_probe,
+ .driver = {
+ .name = "nvec-kbd",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init nvec_kbd_init(void)
+{
+ return platform_driver_register(&nvec_kbd_driver);
+}
+
+module_init(nvec_kbd_init);
+
+MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
+MODULE_DESCRIPTION("NVEC keyboard driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
index df164ad..dfa966f 100644
--- a/drivers/staging/nvec/nvec_power.c
+++ b/drivers/staging/nvec/nvec_power.c
@@ -1,3 +1,17 @@
+/*
+ * nvec_power: power supply driver for a NVIDIA compliant embedded controller
+ *
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
+ *
+ * Authors: Ilya Petrov <ilya.muromec@gmail.com>
+ * Marc Dietrich <marvin24@gmx.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/err.h>
@@ -5,10 +19,10 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
+
#include "nvec.h"
-struct nvec_power
-{
+struct nvec_power {
struct notifier_block notifier;
struct delayed_work poller;
struct nvec_chip *nvec;
@@ -58,7 +72,8 @@ struct bat_response {
u8 length;
u8 sub_type;
u8 status;
- union { /* payload */
+ /* payload */
+ union {
char plc[30];
u16 plu;
s16 pls;
@@ -69,18 +84,17 @@ static struct power_supply nvec_bat_psy;
static struct power_supply nvec_psy;
static int nvec_power_notifier(struct notifier_block *nb,
- unsigned long event_type, void *data)
+ unsigned long event_type, void *data)
{
- struct nvec_power *power = container_of(nb, struct nvec_power, notifier);
+ struct nvec_power *power =
+ container_of(nb, struct nvec_power, notifier);
struct bat_response *res = (struct bat_response *)data;
if (event_type != NVEC_SYS)
return NOTIFY_DONE;
- if(res->sub_type == 0)
- {
- if (power->on != res->plu)
- {
+ if (res->sub_type == 0) {
+ if (power->on != res->plu) {
power->on = res->plu;
power_supply_changed(&nvec_psy);
}
@@ -89,8 +103,7 @@ static int nvec_power_notifier(struct notifier_block *nb,
return NOTIFY_OK;
}
-static const int bat_init[] =
-{
+static const int bat_init[] = {
LAST_FULL_CHARGE_CAPACITY, DESIGN_CAPACITY, CRITICAL_CAPACITY,
MANUFACTURER, MODEL, TYPE,
};
@@ -100,116 +113,115 @@ static void get_bat_mfg_data(struct nvec_power *power)
int i;
char buf[] = { '\x02', '\x00' };
- for (i = 0; i < ARRAY_SIZE(bat_init); i++)
- {
+ for (i = 0; i < ARRAY_SIZE(bat_init); i++) {
buf[1] = bat_init[i];
nvec_write_async(power->nvec, buf, 2);
}
}
static int nvec_power_bat_notifier(struct notifier_block *nb,
- unsigned long event_type, void *data)
+ unsigned long event_type, void *data)
{
- struct nvec_power *power = container_of(nb, struct nvec_power, notifier);
+ struct nvec_power *power =
+ container_of(nb, struct nvec_power, notifier);
struct bat_response *res = (struct bat_response *)data;
int status_changed = 0;
if (event_type != NVEC_BAT)
return NOTIFY_DONE;
- switch(res->sub_type)
- {
- case SLOT_STATUS:
- if (res->plc[0] & 1)
- {
- if (power->bat_present == 0)
- {
- status_changed = 1;
- get_bat_mfg_data(power);
- }
-
- power->bat_present = 1;
-
- switch ((res->plc[0] >> 1) & 3)
- {
- case 0:
- power->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
- break;
- case 1:
- power->bat_status = POWER_SUPPLY_STATUS_CHARGING;
- break;
- case 2:
- power->bat_status = POWER_SUPPLY_STATUS_DISCHARGING;
- break;
- default:
- power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
- }
- } else {
- if (power->bat_present == 1)
- status_changed = 1;
-
- power->bat_present = 0;
+ switch (res->sub_type) {
+ case SLOT_STATUS:
+ if (res->plc[0] & 1) {
+ if (power->bat_present == 0) {
+ status_changed = 1;
+ get_bat_mfg_data(power);
+ }
+
+ power->bat_present = 1;
+
+ switch ((res->plc[0] >> 1) & 3) {
+ case 0:
+ power->bat_status =
+ POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ case 1:
+ power->bat_status =
+ POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case 2:
+ power->bat_status =
+ POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ default:
power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
}
- power->bat_cap = res->plc[1];
- if (status_changed)
- power_supply_changed(&nvec_bat_psy);
- break;
- case VOLTAGE:
- power->bat_voltage_now = res->plu * 1000;
- break;
- case TIME_REMAINING:
- power->time_remain = res->plu * 3600;
- break;
- case CURRENT:
- power->bat_current_now = res->pls * 1000;
- break;
- case AVERAGE_CURRENT:
- power->bat_current_avg = res->pls * 1000;
- break;
- case CAPACITY_REMAINING:
- power->capacity_remain = res->plu * 1000;
- break;
- case LAST_FULL_CHARGE_CAPACITY:
- power->charge_last_full = res->plu * 1000;
- break;
- case DESIGN_CAPACITY:
- power->charge_full_design = res->plu * 1000;
- break;
- case CRITICAL_CAPACITY:
- power->critical_capacity = res->plu * 1000;
- break;
- case TEMPERATURE:
- power->bat_temperature = res->plu - 2732;
- break;
- case MANUFACTURER:
- memcpy(power->bat_manu, &res->plc, res->length-2);
- power->bat_model[res->length-2] = '\0';
- break;
- case MODEL:
- memcpy(power->bat_model, &res->plc, res->length-2);
- power->bat_model[res->length-2] = '\0';
- break;
- case TYPE:
- memcpy(power->bat_type, &res->plc, res->length-2);
- power->bat_type[res->length-2] = '\0';
- /* this differs a little from the spec
- fill in more if you find some */
- if (!strncmp(power->bat_type, "Li", 30))
- power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_LION;
- else
- power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
- break;
- default:
- return NOTIFY_STOP;
+ } else {
+ if (power->bat_present == 1)
+ status_changed = 1;
+
+ power->bat_present = 0;
+ power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+ power->bat_cap = res->plc[1];
+ if (status_changed)
+ power_supply_changed(&nvec_bat_psy);
+ break;
+ case VOLTAGE:
+ power->bat_voltage_now = res->plu * 1000;
+ break;
+ case TIME_REMAINING:
+ power->time_remain = res->plu * 3600;
+ break;
+ case CURRENT:
+ power->bat_current_now = res->pls * 1000;
+ break;
+ case AVERAGE_CURRENT:
+ power->bat_current_avg = res->pls * 1000;
+ break;
+ case CAPACITY_REMAINING:
+ power->capacity_remain = res->plu * 1000;
+ break;
+ case LAST_FULL_CHARGE_CAPACITY:
+ power->charge_last_full = res->plu * 1000;
+ break;
+ case DESIGN_CAPACITY:
+ power->charge_full_design = res->plu * 1000;
+ break;
+ case CRITICAL_CAPACITY:
+ power->critical_capacity = res->plu * 1000;
+ break;
+ case TEMPERATURE:
+ power->bat_temperature = res->plu - 2732;
+ break;
+ case MANUFACTURER:
+ memcpy(power->bat_manu, &res->plc, res->length - 2);
+ power->bat_model[res->length - 2] = '\0';
+ break;
+ case MODEL:
+ memcpy(power->bat_model, &res->plc, res->length - 2);
+ power->bat_model[res->length - 2] = '\0';
+ break;
+ case TYPE:
+ memcpy(power->bat_type, &res->plc, res->length - 2);
+ power->bat_type[res->length - 2] = '\0';
+ /* this differs a little from the spec
+ fill in more if you find some */
+ if (!strncmp(power->bat_type, "Li", 30))
+ power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_LION;
+ else
+ power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+ break;
+ default:
+ return NOTIFY_STOP;
}
return NOTIFY_STOP;
}
static int nvec_power_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
+ enum power_supply_property psp,
+ union power_supply_propval *val)
{
struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
switch (psp) {
@@ -223,61 +235,60 @@ static int nvec_power_get_property(struct power_supply *psy,
}
static int nvec_battery_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
+ enum power_supply_property psp,
+ union power_supply_propval *val)
{
struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
- switch(psp)
- {
- case POWER_SUPPLY_PROP_STATUS:
- val->intval = power->bat_status;
- break;
- case POWER_SUPPLY_PROP_CAPACITY:
- val->intval = power->bat_cap;
- break;
- case POWER_SUPPLY_PROP_PRESENT:
- val->intval = power->bat_present;
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = power->bat_voltage_now;
- break;
- case POWER_SUPPLY_PROP_CURRENT_NOW:
- val->intval = power->bat_current_now;
- break;
- case POWER_SUPPLY_PROP_CURRENT_AVG:
- val->intval = power->bat_current_avg;
- break;
- case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
- val->intval = power->time_remain;
- break;
- case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
- val->intval = power->charge_full_design;
- break;
- case POWER_SUPPLY_PROP_CHARGE_FULL:
- val->intval = power->charge_last_full;
- break;
- case POWER_SUPPLY_PROP_CHARGE_EMPTY:
- val->intval = power->critical_capacity;
- break;
- case POWER_SUPPLY_PROP_CHARGE_NOW:
- val->intval = power->capacity_remain;
- break;
- case POWER_SUPPLY_PROP_TEMP:
- val->intval = power->bat_temperature;
- break;
- case POWER_SUPPLY_PROP_MANUFACTURER:
- val->strval = power->bat_manu;
- break;
- case POWER_SUPPLY_PROP_MODEL_NAME:
- val->strval = power->bat_model;
- break;
- case POWER_SUPPLY_PROP_TECHNOLOGY:
- val->intval = power->bat_type_enum;
- break;
- default:
- return -EINVAL;
- }
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = power->bat_status;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = power->bat_cap;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = power->bat_present;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = power->bat_voltage_now;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = power->bat_current_now;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = power->bat_current_avg;
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+ val->intval = power->time_remain;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = power->charge_full_design;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = power->charge_last_full;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+ val->intval = power->critical_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = power->capacity_remain;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = power->bat_temperature;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = power->bat_manu;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = power->bat_model;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = power->bat_type_enum;
+ break;
+ default:
+ return -EINVAL;
+ }
return 0;
}
@@ -310,11 +321,11 @@ static char *nvec_power_supplied_to[] = {
};
static struct power_supply nvec_bat_psy = {
- .name = "battery",
- .type = POWER_SUPPLY_TYPE_BATTERY,
- .properties = nvec_battery_props,
- .num_properties = ARRAY_SIZE(nvec_battery_props),
- .get_property = nvec_battery_get_property,
+ .name = "battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = nvec_battery_props,
+ .num_properties = ARRAY_SIZE(nvec_battery_props),
+ .get_property = nvec_battery_get_property,
};
static struct power_supply nvec_psy = {
@@ -327,9 +338,8 @@ static struct power_supply nvec_psy = {
.get_property = nvec_power_get_property,
};
-static int counter = 0;
-static int const bat_iter[] =
-{
+static int counter;
+static int const bat_iter[] = {
SLOT_STATUS, VOLTAGE, CURRENT, CAPACITY_REMAINING,
#ifdef EC_FULL_DIAG
AVERAGE_CURRENT, TEMPERATURE, TIME_REMAINING,
@@ -340,7 +350,7 @@ static void nvec_power_poll(struct work_struct *work)
{
char buf[] = { '\x01', '\x00' };
struct nvec_power *power = container_of(work, struct nvec_power,
- poller.work);
+ poller.work);
if (counter >= ARRAY_SIZE(bat_iter))
counter = 0;
@@ -351,19 +361,18 @@ static void nvec_power_poll(struct work_struct *work)
/* select a battery request function via round robin
doing it all at once seems to overload the power supply */
- buf[0] = '\x02'; /* battery */
- buf[1] = bat_iter[counter++];
+ buf[0] = '\x02'; /* battery */
+ buf[1] = bat_iter[counter++];
nvec_write_async(power->nvec, buf, 2);
-// printk("%02x %02x\n", buf[0], buf[1]);
-
schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(5000));
};
static int __devinit nvec_power_probe(struct platform_device *pdev)
{
struct power_supply *psy;
- struct nvec_power *power = kzalloc(sizeof(struct nvec_power), GFP_NOWAIT);
+ struct nvec_power *power =
+ kzalloc(sizeof(struct nvec_power), GFP_NOWAIT);
struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
dev_set_drvdata(&pdev->dev, power);
@@ -381,7 +390,7 @@ static int __devinit nvec_power_probe(struct platform_device *pdev)
case BAT:
psy = &nvec_bat_psy;
- power->notifier.notifier_call = nvec_power_bat_notifier;
+ power->notifier.notifier_call = nvec_power_bat_notifier;
break;
default:
kfree(power);
@@ -398,14 +407,13 @@ static int __devinit nvec_power_probe(struct platform_device *pdev)
static struct platform_driver nvec_power_driver = {
.probe = nvec_power_probe,
-// .remove = __devexit_p(nvec_power_remove),
.driver = {
- .name = "nvec-power",
- .owner = THIS_MODULE,
- }
+ .name = "nvec-power",
+ .owner = THIS_MODULE,
+ }
};
-static int __init nvec_power_init(void)
+static int __init nvec_power_init(void)
{
return platform_driver_register(&nvec_power_driver);
}
diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
index 6bb9430..742f5cc 100644
--- a/drivers/staging/nvec/nvec_ps2.c
+++ b/drivers/staging/nvec/nvec_ps2.c
@@ -1,14 +1,33 @@
+/*
+ * nvec_ps2: mouse driver for a NVIDIA compliant embedded controller
+ *
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
+ *
+ * Authors: Pierre-Hugues Husson <phhusson@free.fr>
+ * Ilya Petrov <ilya.muromec@gmail.com>
+ * Marc Dietrich <marvin24@gmx.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/serio.h>
#include <linux/delay.h>
+#include <linux/platform_device.h>
+
#include "nvec.h"
-#define START_STREAMING {'\x06','\x03','\x01'}
-#define STOP_STREAMING {'\x06','\x04'}
-#define SEND_COMMAND {'\x06','\x01','\xf4','\x01'}
+#define START_STREAMING {'\x06', '\x03', '\x04'}
+#define STOP_STREAMING {'\x06', '\x04'}
+#define SEND_COMMAND {'\x06', '\x01', '\xf4', '\x01'}
-struct nvec_ps2
-{
+static const unsigned char MOUSE_RESET[] = {'\x06', '\x01', '\xff', '\x03'};
+
+struct nvec_ps2 {
struct serio *ser_dev;
struct notifier_block notifier;
struct nvec_chip *nvec;
@@ -19,8 +38,7 @@ static struct nvec_ps2 ps2_dev;
static int ps2_startstreaming(struct serio *ser_dev)
{
unsigned char buf[] = START_STREAMING;
- nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
- return 0;
+ return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
}
static void ps2_stopstreaming(struct serio *ser_dev)
@@ -29,12 +47,6 @@ static void ps2_stopstreaming(struct serio *ser_dev)
nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
}
-/* is this really needed?
-static void nvec_resp_handler(unsigned char *data) {
- serio_interrupt(ser_dev, data[4], 0);
-}
-*/
-
static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd)
{
unsigned char buf[] = SEND_COMMAND;
@@ -42,52 +54,49 @@ static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd)
buf[2] = cmd & 0xff;
dev_dbg(&ser_dev->dev, "Sending ps2 cmd %02x\n", cmd);
- nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
-
- return 0;
+ return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
}
static int nvec_ps2_notifier(struct notifier_block *nb,
- unsigned long event_type, void *data)
+ unsigned long event_type, void *data)
{
int i;
unsigned char *msg = (unsigned char *)data;
switch (event_type) {
- case NVEC_PS2_EVT:
- serio_interrupt(ps2_dev.ser_dev, msg[2], 0);
- return NOTIFY_STOP;
-
- case NVEC_PS2:
- if (msg[2] == 1)
- for(i = 0; i < (msg[1] - 2); i++)
- serio_interrupt(ps2_dev.ser_dev, msg[i+4], 0);
- else if (msg[1] != 2) /* !ack */
- {
- printk("nvec_ps2: unhandled mouse event ");
- for(i = 0; i <= (msg[1]+1); i++)
- printk("%02x ", msg[i]);
- printk(".\n");
- }
-
- return NOTIFY_STOP;
+ case NVEC_PS2_EVT:
+ for (i = 0; i < msg[1]; i++)
+ serio_interrupt(ps2_dev.ser_dev, msg[2 + i], 0);
+ return NOTIFY_STOP;
+
+ case NVEC_PS2:
+ if (msg[2] == 1)
+ for (i = 0; i < (msg[1] - 2); i++)
+ serio_interrupt(ps2_dev.ser_dev, msg[i + 4], 0);
+ else if (msg[1] != 2) { /* !ack */
+ print_hex_dump(KERN_WARNING, "unhandled mouse event: ",
+ DUMP_PREFIX_NONE, 16, 1,
+ msg, msg[1] + 2, true);
+ }
+
+ return NOTIFY_STOP;
}
return NOTIFY_DONE;
}
-
-int __init nvec_ps2(struct nvec_chip *nvec)
+static int __devinit nvec_mouse_probe(struct platform_device *pdev)
{
+ struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL);
- ser_dev->id.type=SERIO_8042;
- ser_dev->write=ps2_sendcommand;
- ser_dev->open=ps2_startstreaming;
- ser_dev->close=ps2_stopstreaming;
+ ser_dev->id.type = SERIO_8042;
+ ser_dev->write = ps2_sendcommand;
+ ser_dev->open = ps2_startstreaming;
+ ser_dev->close = ps2_stopstreaming;
- strlcpy(ser_dev->name, "NVEC PS2", sizeof(ser_dev->name));
- strlcpy(ser_dev->phys, "NVEC I2C slave", sizeof(ser_dev->phys));
+ strlcpy(ser_dev->name, "nvec mouse", sizeof(ser_dev->name));
+ strlcpy(ser_dev->phys, "nvec", sizeof(ser_dev->phys));
ps2_dev.ser_dev = ser_dev;
ps2_dev.notifier.notifier_call = nvec_ps2_notifier;
@@ -97,7 +106,26 @@ int __init nvec_ps2(struct nvec_chip *nvec)
serio_register_port(ser_dev);
/* mouse reset */
- nvec_write_async(nvec, "\x06\x01\xff\x03", 4);
+ nvec_write_async(nvec, MOUSE_RESET, 4);
return 0;
}
+
+static struct platform_driver nvec_mouse_driver = {
+ .probe = nvec_mouse_probe,
+ .driver = {
+ .name = "nvec-mouse",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init nvec_mouse_init(void)
+{
+ return platform_driver_register(&nvec_mouse_driver);
+}
+
+module_init(nvec_mouse_init);
+
+MODULE_DESCRIPTION("NVEC mouse driver");
+MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 8a11ffc..f18e3e1 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/ratelimit.h>
#include <net/dst.h>
@@ -129,22 +130,22 @@ static void cvm_oct_adjust_link(struct net_device *dev)
if (priv->last_link) {
netif_carrier_on(dev);
if (priv->queue != -1)
- DEBUGPRINT("%s: %u Mbps %s duplex, "
- "port %2d, queue %2d\n",
- dev->name, priv->phydev->speed,
- priv->phydev->duplex ?
- "Full" : "Half",
- priv->port, priv->queue);
+ printk_ratelimited("%s: %u Mbps %s duplex, "
+ "port %2d, queue %2d\n",
+ dev->name, priv->phydev->speed,
+ priv->phydev->duplex ?
+ "Full" : "Half",
+ priv->port, priv->queue);
else
- DEBUGPRINT("%s: %u Mbps %s duplex, "
- "port %2d, POW\n",
- dev->name, priv->phydev->speed,
- priv->phydev->duplex ?
- "Full" : "Half",
- priv->port);
+ printk_ratelimited("%s: %u Mbps %s duplex, "
+ "port %2d, POW\n",
+ dev->name, priv->phydev->speed,
+ priv->phydev->duplex ?
+ "Full" : "Half",
+ priv->port);
} else {
netif_carrier_off(dev);
- DEBUGPRINT("%s: Link down\n", dev->name);
+ printk_ratelimited("%s: Link down\n", dev->name);
}
}
}
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index a0d4d4b..c3d73f8 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -26,7 +26,9 @@
**********************************************************************/
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/interrupt.h>
#include <linux/phy.h>
+#include <linux/ratelimit.h>
#include <net/dst.h>
#include <asm/octeon/octeon.h>
@@ -116,9 +118,9 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
(index, interface),
gmxx_rxx_int_reg.u64);
- DEBUGPRINT("%s: Using 10Mbps with software "
- "preamble removal\n",
- dev->name);
+ printk_ratelimited("%s: Using 10Mbps with software "
+ "preamble removal\n",
+ dev->name);
}
}
@@ -174,23 +176,23 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
if (priv->queue != -1)
- DEBUGPRINT("%s: %u Mbps %s duplex, "
- "port %2d, queue %2d\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ?
- "Full" : "Half",
- priv->port, priv->queue);
+ printk_ratelimited("%s: %u Mbps %s duplex, "
+ "port %2d, queue %2d\n",
+ dev->name, link_info.s.speed,
+ (link_info.s.full_duplex) ?
+ "Full" : "Half",
+ priv->port, priv->queue);
else
- DEBUGPRINT("%s: %u Mbps %s duplex, "
- "port %2d, POW\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ?
- "Full" : "Half",
- priv->port);
+ printk_ratelimited("%s: %u Mbps %s duplex, "
+ "port %2d, POW\n",
+ dev->name, link_info.s.speed,
+ (link_info.s.full_duplex) ?
+ "Full" : "Half",
+ priv->port);
} else {
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
- DEBUGPRINT("%s: Link down\n", dev->name);
+ printk_ratelimited("%s: Link down\n", dev->name);
}
}
}
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index cb38f9e..8b307b4 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -34,6 +34,7 @@
#include <linux/ip.h>
#include <linux/string.h>
#include <linux/prefetch.h>
+#include <linux/ratelimit.h>
#include <linux/smp.h>
#include <net/dst.h>
#ifdef CONFIG_XFRM
@@ -41,7 +42,7 @@
#include <net/xfrm.h>
#endif /* CONFIG_XFRM */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/octeon/octeon.h>
@@ -186,13 +187,13 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
if (*ptr == 0xd5) {
/*
- DEBUGPRINT("Port %d received 0xd5 preamble\n", work->ipprt);
+ printk_ratelimited("Port %d received 0xd5 preamble\n", work->ipprt);
*/
work->packet_ptr.s.addr += i + 1;
work->len -= i + 5;
} else if ((*ptr & 0xf) == 0xd) {
/*
- DEBUGPRINT("Port %d received 0x?d preamble\n", work->ipprt);
+ printk_ratelimited("Port %d received 0x?d preamble\n", work->ipprt);
*/
work->packet_ptr.s.addr += i;
work->len -= i + 4;
@@ -203,9 +204,9 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
ptr++;
}
} else {
- DEBUGPRINT("Port %d unknown preamble, packet "
- "dropped\n",
- work->ipprt);
+ printk_ratelimited("Port %d unknown preamble, packet "
+ "dropped\n",
+ work->ipprt);
/*
cvmx_helper_dump_packet(work);
*/
@@ -214,8 +215,8 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
}
}
} else {
- DEBUGPRINT("Port %d receive error code %d, packet dropped\n",
- work->ipprt, work->word2.snoip.err_code);
+ printk_ratelimited("Port %d receive error code %d, packet dropped\n",
+ work->ipprt, work->word2.snoip.err_code);
cvm_oct_free_work(work);
return 1;
}
@@ -334,8 +335,9 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
*/
skb = dev_alloc_skb(work->len);
if (!skb) {
- DEBUGPRINT("Port %d failed to allocate skbuff, packet dropped\n",
- work->ipprt);
+ printk_ratelimited("Port %d failed to allocate "
+ "skbuff, packet dropped\n",
+ work->ipprt);
cvm_oct_free_work(work);
continue;
}
@@ -409,7 +411,8 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
skb->protocol = eth_type_trans(skb, dev);
skb->dev = dev;
- if (unlikely(work->word2.s.not_IP || work->word2.s.IP_exc || work->word2.s.L4_error))
+ if (unlikely(work->word2.s.not_IP || work->word2.s.IP_exc ||
+ work->word2.s.L4_error || !work->word2.s.tcp_or_udp))
skb->ip_summed = CHECKSUM_NONE;
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -429,7 +432,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
} else {
/* Drop any packet received for a device that isn't up */
/*
- DEBUGPRINT("%s: Device not up, packet dropped\n",
+ printk_ratelimited("%s: Device not up, packet dropped\n",
dev->name);
*/
#ifdef CONFIG_64BIT
@@ -444,7 +447,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
* Drop any packet received for a device that
* doesn't exist.
*/
- DEBUGPRINT("Port %d not controlled by Linux, packet dropped\n",
+ printk_ratelimited("Port %d not controlled by Linux, packet dropped\n",
work->ipprt);
dev_kfree_skb_irq(skb);
}
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c
index 2d8589e..5e148b5 100644
--- a/drivers/staging/octeon/ethernet-sgmii.c
+++ b/drivers/staging/octeon/ethernet-sgmii.c
@@ -26,6 +26,7 @@
**********************************************************************/
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/ratelimit.h>
#include <net/dst.h>
#include <asm/octeon/octeon.h>
@@ -90,20 +91,21 @@ static void cvm_oct_sgmii_poll(struct net_device *dev)
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
if (priv->queue != -1)
- DEBUGPRINT
+ printk_ratelimited
("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
dev->name, link_info.s.speed,
(link_info.s.full_duplex) ? "Full" : "Half",
priv->port, priv->queue);
else
- DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port);
+ printk_ratelimited
+ ("%s: %u Mbps %s duplex, port %2d, POW\n",
+ dev->name, link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port);
} else {
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
- DEBUGPRINT("%s: Link down\n", dev->name);
+ printk_ratelimited("%s: Link down\n", dev->name);
}
}
diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c
index 9708254..d0e2d51 100644
--- a/drivers/staging/octeon/ethernet-spi.c
+++ b/drivers/staging/octeon/ethernet-spi.c
@@ -26,6 +26,7 @@
**********************************************************************/
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/interrupt.h>
#include <net/dst.h>
#include <asm/octeon/octeon.h>
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index afc2b73..c5da0d2 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/etherdevice.h>
#include <linux/ip.h>
+#include <linux/ratelimit.h>
#include <linux/string.h>
#include <net/dst.h>
#ifdef CONFIG_XFRM
@@ -37,7 +38,7 @@
#include <net/xfrm.h>
#endif /* CONFIG_XFRM */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/octeon/octeon.h>
@@ -274,7 +275,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i;
- hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page) + fs->page_offset));
+ hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + fs->page_offset));
hw_buffer.s.size = fs->size;
CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
}
@@ -343,7 +344,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (unlikely
(skb->truesize !=
- sizeof(*skb) + skb_end_pointer(skb) - skb->head)) {
+ sizeof(*skb) + skb_end_offset(skb))) {
/*
printk("TX buffer truesize has been changed\n");
*/
@@ -446,7 +447,7 @@ dont_put_skbuff_in_hw:
priv->queue + qos,
pko_command, hw_buffer,
CVMX_PKO_LOCK_NONE))) {
- DEBUGPRINT("%s: Failed to send the packet\n", dev->name);
+ printk_ratelimited("%s: Failed to send the packet\n", dev->name);
queue_type = QUEUE_DROP;
}
skip_xmit:
@@ -525,8 +526,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
/* Get a work queue entry */
cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
if (unlikely(work == NULL)) {
- DEBUGPRINT("%s: Failed to allocate a work queue entry\n",
- dev->name);
+ printk_ratelimited("%s: Failed to allocate a work "
+ "queue entry\n", dev->name);
priv->stats.tx_dropped++;
dev_kfree_skb(skb);
return 0;
@@ -535,8 +536,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
/* Get a packet buffer */
packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL);
if (unlikely(packet_buffer == NULL)) {
- DEBUGPRINT("%s: Failed to allocate a packet buffer\n",
- dev->name);
+ printk_ratelimited("%s: Failed to allocate a packet buffer\n",
+ dev->name);
cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
priv->stats.tx_dropped++;
dev_kfree_skb(skb);
diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h
index c745a72..144fb99 100644
--- a/drivers/staging/octeon/ethernet-util.h
+++ b/drivers/staging/octeon/ethernet-util.h
@@ -25,10 +25,6 @@
* Contact Cavium Networks for more information
*********************************************************************/
-#define DEBUGPRINT(format, ...) do { if (printk_ratelimit()) \
- printk(format, ##__VA_ARGS__); \
- } while (0)
-
/**
* cvm_oct_get_buffer_ptr - convert packet data address to pointer
* @packet_ptr: Packet data hardware address
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c
index 3fca1cc..861a4b3 100644
--- a/drivers/staging/octeon/ethernet-xaui.c
+++ b/drivers/staging/octeon/ethernet-xaui.c
@@ -26,6 +26,7 @@
**********************************************************************/
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/ratelimit.h>
#include <net/dst.h>
#include <asm/octeon/octeon.h>
@@ -89,20 +90,21 @@ static void cvm_oct_xaui_poll(struct net_device *dev)
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
if (priv->queue != -1)
- DEBUGPRINT
- ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port, priv->queue);
+ printk_ratelimited
+ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
+ dev->name, link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port, priv->queue);
else
- DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port);
+ printk_ratelimited
+ ("%s: %u Mbps %s duplex, port %2d, POW\n",
+ dev->name, link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port);
} else {
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
- DEBUGPRINT("%s: Link down\n", dev->name);
+ printk_ratelimited("%s: Link down\n", dev->name);
}
}
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index a8f780e..076f866 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -512,7 +512,7 @@ static const struct net_device_ops cvm_oct_npi_netdev_ops = {
.ndo_init = cvm_oct_common_init,
.ndo_uninit = cvm_oct_common_uninit,
.ndo_start_xmit = cvm_oct_xmit,
- .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+ .ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
.ndo_do_ioctl = cvm_oct_ioctl,
.ndo_change_mtu = cvm_oct_common_change_mtu,
@@ -527,7 +527,7 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = {
.ndo_open = cvm_oct_xaui_open,
.ndo_stop = cvm_oct_xaui_stop,
.ndo_start_xmit = cvm_oct_xmit,
- .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+ .ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
.ndo_do_ioctl = cvm_oct_ioctl,
.ndo_change_mtu = cvm_oct_common_change_mtu,
@@ -542,7 +542,7 @@ static const struct net_device_ops cvm_oct_sgmii_netdev_ops = {
.ndo_open = cvm_oct_sgmii_open,
.ndo_stop = cvm_oct_sgmii_stop,
.ndo_start_xmit = cvm_oct_xmit,
- .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+ .ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
.ndo_do_ioctl = cvm_oct_ioctl,
.ndo_change_mtu = cvm_oct_common_change_mtu,
@@ -555,7 +555,7 @@ static const struct net_device_ops cvm_oct_spi_netdev_ops = {
.ndo_init = cvm_oct_spi_init,
.ndo_uninit = cvm_oct_spi_uninit,
.ndo_start_xmit = cvm_oct_xmit,
- .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+ .ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
.ndo_do_ioctl = cvm_oct_ioctl,
.ndo_change_mtu = cvm_oct_common_change_mtu,
@@ -570,7 +570,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = {
.ndo_open = cvm_oct_rgmii_open,
.ndo_stop = cvm_oct_rgmii_stop,
.ndo_start_xmit = cvm_oct_xmit,
- .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+ .ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
.ndo_do_ioctl = cvm_oct_ioctl,
.ndo_change_mtu = cvm_oct_common_change_mtu,
@@ -582,7 +582,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = {
static const struct net_device_ops cvm_oct_pow_netdev_ops = {
.ndo_init = cvm_oct_common_init,
.ndo_start_xmit = cvm_oct_xmit_pow,
- .ndo_set_multicast_list = cvm_oct_common_set_multicast_list,
+ .ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
.ndo_do_ioctl = cvm_oct_ioctl,
.ndo_change_mtu = cvm_oct_common_change_mtu,
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 750fe50..af24ddf 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -21,6 +21,7 @@
#include <linux/pci_ids.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/backlight.h>
#include <linux/device.h>
#include <linux/uaccess.h>
@@ -36,9 +37,6 @@
static int resumeline = 898;
module_param(resumeline, int, 0444);
-static int noinit;
-module_param(noinit, int, 0444);
-
/* Default off since it doesn't work on DCON ASIC in B-test OLPC board */
static int useaa = 1;
module_param(useaa, int, 0444);
@@ -68,11 +66,10 @@ static s32 dcon_read(struct dcon_priv *dcon, u8 reg)
static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
{
- struct i2c_client *client = dcon->client;
uint16_t ver;
int rc = 0;
- ver = i2c_smbus_read_word_data(client, DCON_REG_ID);
+ ver = dcon_read(dcon, DCON_REG_ID);
if ((ver >> 8) != 0xDC) {
printk(KERN_ERR "olpc-dcon: DCON ID not 0xDCxx: 0x%04x "
"instead.\n", ver);
@@ -90,30 +87,19 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
}
}
- if (ver < 0xdc02 && !noinit) {
- /* Initialize the DCON registers */
-
- /* Start with work-arounds for DCON ASIC */
- i2c_smbus_write_word_data(client, 0x4b, 0x00cc);
- i2c_smbus_write_word_data(client, 0x4b, 0x00cc);
- i2c_smbus_write_word_data(client, 0x4b, 0x00cc);
- i2c_smbus_write_word_data(client, 0x0b, 0x007a);
- i2c_smbus_write_word_data(client, 0x36, 0x025c);
- i2c_smbus_write_word_data(client, 0x37, 0x025e);
-
- /* Initialise SDRAM */
-
- i2c_smbus_write_word_data(client, 0x3b, 0x002b);
- i2c_smbus_write_word_data(client, 0x41, 0x0101);
- i2c_smbus_write_word_data(client, 0x42, 0x0101);
- } else if (!noinit) {
- /* SDRAM setup/hold time */
- i2c_smbus_write_word_data(client, 0x3a, 0xc040);
- i2c_smbus_write_word_data(client, 0x41, 0x0000);
- i2c_smbus_write_word_data(client, 0x41, 0x0101);
- i2c_smbus_write_word_data(client, 0x42, 0x0101);
+ if (ver < 0xdc02) {
+ dev_err(&dcon->client->dev,
+ "DCON v1 is unsupported, giving up..\n");
+ rc = -ENODEV;
+ goto err;
}
+ /* SDRAM setup/hold time */
+ dcon_write(dcon, 0x3a, 0xc040);
+ dcon_write(dcon, 0x41, 0x0000);
+ dcon_write(dcon, 0x41, 0x0101);
+ dcon_write(dcon, 0x42, 0x0101);
+
/* Colour swizzle, AA, no passthrough, backlight */
if (is_init) {
dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
@@ -121,11 +107,11 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
if (useaa)
dcon->disp_mode |= MODE_COL_AA;
}
- i2c_smbus_write_word_data(client, DCON_REG_MODE, dcon->disp_mode);
+ dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
/* Set the scanline to interrupt on during resume */
- i2c_smbus_write_word_data(client, DCON_REG_SCAN_INT, resumeline);
+ dcon_write(dcon, DCON_REG_SCAN_INT, resumeline);
err:
return rc;
@@ -712,7 +698,6 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
eirq:
free_irq(DCON_IRQ, dcon);
einit:
- i2c_set_clientdata(client, NULL);
kfree(dcon);
return rc;
}
@@ -721,8 +706,6 @@ static int dcon_remove(struct i2c_client *client)
{
struct dcon_priv *dcon = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
-
fb_unregister_client(&dcon->fbevent_nb);
unregister_reboot_notifier(&dcon->reboot_nb);
atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 6885f9a..9a584da 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -51,7 +51,6 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/parport.h>
-#include <linux/version.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
@@ -275,11 +274,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
* LCD types
*/
#define LCD_TYPE_NONE 0
-#define LCD_TYPE_OLD 1
-#define LCD_TYPE_KS0074 2
-#define LCD_TYPE_HANTRONIX 3
-#define LCD_TYPE_NEXCOM 4
-#define LCD_TYPE_CUSTOM 5
+#define LCD_TYPE_CUSTOM 1
+#define LCD_TYPE_OLD 2
+#define LCD_TYPE_KS0074 3
+#define LCD_TYPE_HANTRONIX 4
+#define LCD_TYPE_NEXCOM 5
/*
* keypad types
@@ -457,8 +456,7 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
static int lcd_type = -1;
module_param(lcd_type, int, 0000);
MODULE_PARM_DESC(lcd_type,
- "LCD type: 0=none, 1=old //, 2=serial ks0074, "
- "3=hantronix //, 4=nexcom //, 5=compiled-in");
+ "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
static int lcd_proto = -1;
module_param(lcd_proto, int, 0000);
@@ -1180,16 +1178,14 @@ static inline int handle_lcd_special_code(void)
break;
while (*esc) {
- char *endp;
-
if (*esc == 'x') {
esc++;
- lcd_addr_x = simple_strtoul(esc, &endp, 10);
- esc = endp;
+ if (kstrtoul(esc, 10, &lcd_addr_x) < 0)
+ break;
} else if (*esc == 'y') {
esc++;
- lcd_addr_y = simple_strtoul(esc, &endp, 10);
- esc = endp;
+ if (kstrtoul(esc, 10, &lcd_addr_y) < 0)
+ break;
} else
break;
}
diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig
index 58158b8..8d53b1a 100644
--- a/drivers/staging/pohmelfs/Kconfig
+++ b/drivers/staging/pohmelfs/Kconfig
@@ -18,11 +18,3 @@ config POHMELFS_DEBUG
Turns on excessive POHMELFS debugging facilities.
You usually do not want to slow things down noticeably and get really
lots of kernel messages in syslog.
-
-config POHMELFS_CRYPTO
- bool "POHMELFS crypto support"
- depends on POHMELFS
- help
- This option allows to encrypt and/or protect with strong
- cryptographic hash all dataflow between server and clients.
- Each config group can have its own keys.
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
index 5cca24f..ad92771 100644
--- a/drivers/staging/pohmelfs/crypto.c
+++ b/drivers/staging/pohmelfs/crypto.c
@@ -17,6 +17,7 @@
#include <linux/highmem.h>
#include <linux/kthread.h>
#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
#include <linux/slab.h>
#include "netfs.h"
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
index 9732a96..7598e77 100644
--- a/drivers/staging/pohmelfs/dir.c
+++ b/drivers/staging/pohmelfs/dir.c
@@ -512,7 +512,7 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
struct qstr str = dentry->d_name;
- if ((nd->intent.open.flags & O_ACCMODE) > 1)
+ if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY)
lock_type = POHMELFS_WRITE_LOCK;
if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index c0f0ac7..7a19555 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -887,11 +887,16 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
/*
* We want fsync() to work on POHMELFS.
*/
-static int pohmelfs_fsync(struct file *file, int datasync)
+static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
struct inode *inode = file->f_mapping->host;
-
- return sync_inode_metadata(inode, 1);
+ int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ if (!err) {
+ mutex_lock(&inode->i_mutex);
+ err = sync_inode_metadata(inode, 1);
+ mutex_unlock(&inode->i_mutex);
+ }
+ return err;
}
ssize_t pohmelfs_write(struct file *file, const char __user *buf,
@@ -1192,7 +1197,7 @@ const struct inode_operations pohmelfs_file_inode_operations = {
void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
{
inode->i_mode = info->mode;
- inode->i_nlink = info->nlink;
+ set_nlink(inode, info->nlink);
inode->i_uid = info->uid;
inode->i_gid = info->gid;
inode->i_blocks = info->blocks;
diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
index 36a2535..06c1a74 100644
--- a/drivers/staging/pohmelfs/trans.c
+++ b/drivers/staging/pohmelfs/trans.c
@@ -50,7 +50,7 @@ static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st)
int err = 0;
unsigned int i, attached_pages = t->attached_pages, ci;
struct msghdr msg;
- struct page **pages = (t->eng)?t->eng->pages:t->pages;
+ struct page **pages = (t->eng) ? t->eng->pages : t->pages;
struct page *p;
unsigned int size;
@@ -61,7 +61,7 @@ static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st)
msg.msg_flags = MSG_WAITALL | MSG_MORE;
ci = 0;
- for (i=0; i<t->page_num; ++i) {
+ for (i = 0; i < t->page_num; ++i) {
struct page *page = pages[ci];
struct netfs_cmd cmd;
struct iovec io;
@@ -169,7 +169,7 @@ int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
}
dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n",
- __func__, (t->page_num)?"partial":"full",
+ __func__, (t->page_num) ? "partial" : "full",
t, t->gen, t->iovec.iov_len, t->page_num);
err = 0;
diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile
index 11a9226..72db504 100644
--- a/drivers/staging/rtl8187se/Makefile
+++ b/drivers/staging/rtl8187se/Makefile
@@ -1,7 +1,7 @@
-#EXTRA_CFLAGS += -DCONFIG_IEEE80211_NOWEP=y
-#EXTRA_CFLAGS += -std=gnu89
-#EXTRA_CFLAGS += -O2
+#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y
+#ccflags-y += -std=gnu89
+#ccflags-y += -O2
#CC = gcc
ccflags-y := -DSW_ANTE
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 16aa6a8..40dd715 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -25,13 +25,13 @@
#define IEEE80211_H
#include <linux/if_ether.h> /* ETH_ALEN */
#include <linux/kernel.h> /* ARRAY_SIZE */
-#include <linux/version.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
+#include <linux/interrupt.h>
#define KEY_TYPE_NA 0x0
#define KEY_TYPE_WEP40 0x1
@@ -1339,8 +1339,8 @@ int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
/* ieee80211_softmac.c */
-extern short ieee80211_is_54g(struct ieee80211_network net);
-extern short ieee80211_is_shortslot(struct ieee80211_network net);
+extern short ieee80211_is_54g(const struct ieee80211_network *net);
+extern short ieee80211_is_shortslot(const struct ieee80211_network *net);
extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats, u16 type,
u16 stype);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
index c8dbcb9..b3882ae 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
@@ -12,7 +12,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
index 731d268..6aaaa2f 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
@@ -10,7 +10,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
index ee71ee9..da24e43 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
@@ -10,7 +10,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
index f790cd6..58f3eeb 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
@@ -10,7 +10,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
index 9d58a42..9422573 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
@@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index 736a140..26bacb9 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -19,7 +19,7 @@
#include <linux/random.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/version.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include "dot11d.h"
@@ -32,14 +32,14 @@ u8 rsn_authen_cipher_suite[16][4] = {
{0x00,0x0F,0xAC,0x05}, //WEP-104
};
-short ieee80211_is_54g(struct ieee80211_network net)
+short ieee80211_is_54g(const struct ieee80211_network *net)
{
- return ((net.rates_ex_len > 0) || (net.rates_len > 4));
+ return (net->rates_ex_len > 0) || (net->rates_len > 4);
}
-short ieee80211_is_shortslot(struct ieee80211_network net)
+short ieee80211_is_shortslot(const struct ieee80211_network *net)
{
- return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
+ return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
}
/* returns the total length needed for pleacing the RATE MFIE
@@ -789,7 +789,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
else
atim_len = 0;
- if(ieee80211_is_54g(ieee->current_network))
+ if(ieee80211_is_54g(&ieee->current_network))
erp_len = 3;
else
erp_len = 0;
@@ -821,7 +821,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
- cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
+ beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
crypt = ieee->crypt[ieee->tx_keyidx];
@@ -1258,7 +1258,7 @@ void ieee80211_associate_complete_wq(struct work_struct *work)
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
printk(KERN_INFO "Associated successfully\n");
- if(ieee80211_is_54g(ieee->current_network) &&
+ if(ieee80211_is_54g(&ieee->current_network) &&
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
ieee->rate = 540;
@@ -1379,7 +1379,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
ieee->beinretry = false;
queue_work(ieee->wq, &ieee->associate_procedure_wq);
}else{
- if(ieee80211_is_54g(ieee->current_network) &&
+ if(ieee80211_is_54g(&ieee->current_network) &&
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
ieee->rate = 540;
printk(KERN_INFO"Using G rates\n");
@@ -2568,11 +2568,8 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
ieee->beacon_timer.data = (unsigned long) ieee;
ieee->beacon_timer.function = ieee80211_send_beacon_cb;
-#ifdef PF_SYNCTHREAD
- ieee->wq = create_workqueue(DRV_NAME,0);
-#else
ieee->wq = create_workqueue(DRV_NAME);
-#endif
+
INIT_DELAYED_WORK(&ieee->start_ibss_wq,(void*) ieee80211_start_ibss_wq);
INIT_WORK(&ieee->associate_complete_wq,(void*) ieee80211_associate_complete_wq);
INIT_WORK(&ieee->associate_procedure_wq,(void*) ieee80211_associate_procedure_wq);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index 6cb31e1..552115c 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -445,7 +445,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb,
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN;
- /* Each fragment may need to have room for encryptiong pre/postfix */
+ /* Each fragment may need to have room for encryption pre/postfix */
if (encrypt)
bytes_per_frag -= crypt->ops->extra_prefix_len +
crypt->ops->extra_postfix_len;
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index d15bdf6..a2c46ae 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -18,6 +18,7 @@
#ifndef R8180H
#define R8180H
+#include <linux/interrupt.h>
#define RTL8180_MODULE_NAME "r8180"
#define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 2155a77..04c2391 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/eeprom_93cx6.h>
+#include <linux/interrupt.h>
#include "r8180_hw.h"
#include "r8180.h"
@@ -306,7 +307,7 @@ static int proc_get_stats_tx(char *page, char **start,
void rtl8180_proc_module_init(void)
{
DMESG("Initializing proc filesystem");
- rtl8180_proc = create_proc_entry(RTL8180_MODULE_NAME, S_IFDIR, init_net.proc_net);
+ rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net);
}
void rtl8180_proc_module_remove(void)
@@ -3533,7 +3534,7 @@ static const struct net_device_ops rtl8180_netdev_ops = {
.ndo_get_stats = rtl8180_stats,
.ndo_tx_timeout = rtl8180_restart,
.ndo_do_ioctl = rtl8180_ioctl,
- .ndo_set_multicast_list = r8180_set_multicast,
+ .ndo_set_rx_mode = r8180_set_multicast,
.ndo_set_mac_address = r8180_set_mac_adr,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
index 3f09f76..ee5b867 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
@@ -596,7 +596,7 @@ static void rtl8225_rf_set_chan(struct net_device *dev, short ch)
{
struct r8180_priv *priv = ieee80211_priv(dev);
short gset = (priv->ieee80211->state == IEEE80211_LINKED &&
- ieee80211_is_54g(priv->ieee80211->current_network)) ||
+ ieee80211_is_54g(&priv->ieee80211->current_network)) ||
priv->ieee80211->iw_mode == IW_MODE_MONITOR;
rtl8225_SetTXPowerLevel(dev, ch);
@@ -615,7 +615,7 @@ static void rtl8225_rf_set_chan(struct net_device *dev, short ch)
}
if (priv->ieee80211->state == IEEE80211_LINKED &&
- ieee80211_is_shortslot(priv->ieee80211->current_network))
+ ieee80211_is_shortslot(&priv->ieee80211->current_network))
write_nic_byte(dev, SLOT, 0x9);
else
write_nic_byte(dev, SLOT, 0x14);
diff --git a/drivers/staging/rtl8192u/ieee80211/Makefile b/drivers/staging/rtl8192u/ieee80211/Makefile
index 0775c55..51effd6 100644
--- a/drivers/staging/rtl8192u/ieee80211/Makefile
+++ b/drivers/staging/rtl8192u/ieee80211/Makefile
@@ -1,25 +1,9 @@
NIC_SELECT = RTL8192U
-KVER := $(shell uname -r)
-MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/$(NIC_SELECT)
-
-CC = gcc
-ifneq ($(shell uname -r|cut -d. -f1,2), 2.4)
ccflags-y := -I$(TOPDIR)/drivers/net/wireless
ccflags-y += -O2
ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
-#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem.
-ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0)
-ccflags-y := -DOPENSUSE_SLED
-endif
-
-ifeq ($(NIC_SELECT),RTL8192U)
-#ccflags-y := -DUSB_TX_DRIVER_AGGREGATION_ENABLE
-#ccflags-y := -DUSB_RX_AGGREGATION_SUPPORT
-endif
-#ccflags-y := -DJOHN_NOCPY
-#flags to enable or disble 80211D feature
ieee80211-rsl-objs := ieee80211_rx.o \
ieee80211_softmac.o \
ieee80211_tx.o \
@@ -42,96 +26,3 @@ obj-m +=ieee80211_crypt_wep-rsl.o
obj-m +=ieee80211_crypt_tkip-rsl.o
obj-m +=ieee80211_crypt_ccmp-rsl.o
-KSRC := /lib/modules/$(KVER)/build
-INSTALL_PREFIX :=
-
-all: modules
-
-modules:
- $(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules
-
-install: modules
- rm -fr $(MODDESTDIR)
- mkdir -p $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt-rsl.ko $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt_wep-rsl.ko $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt_tkip-rsl.ko $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt_ccmp-rsl.ko $(MODDESTDIR)
- @install -p -m 644 ieee80211-rsl.ko $(MODDESTDIR)
- depmod -a
-uninstall:
- rm -fr $(MODDESTDIR)
- depmod -a
-
-else
-LD := ld
-KSRC := /lib/modules/$(KVER)/build
-CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
-
-CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall
-CFLAGS += -I$(KSRC)/include -I.
-#Kernel 2.4.31
-CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h
-#Kernel 2.4.20
-#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB
-SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \
- grep CONFIG_SMP | awk '{print $$3}')
-ifneq ($(SMP),1)
- SMP := 0
-endif
-ifeq ($(SMP),1)
- CFLAGS += -D__SMP__
-endif
-
-#CFLAGS += -DJOHN_NOCPY
-
-OBJS := ${patsubst %.c, %.o, ${wildcard *.c}}
-all:${OBJS} ieee80211_crypt-rsl.o michael_mic-rsl.o aes-rsl.o ieee80211_crypt_wep-rsl.o ieee80211_crypt_tkip-rsl.o ieee80211_crypt_ccmp-rsl.o crypto-rsl.o ieee80211-rsl.o
-
-ieee80211_crypt-rsl.o: ieee80211_crypt.o
- mv $^ $@
-
-michael_mic-rsl.o: michael_mic.o
- mv $^ $@
-
-aes-rsl.o: aes.o
- mv $^ $@
-
-ieee80211_crypt_wep-rsl.o: ieee80211_crypt_wep.o
- mv $^ $@
-
-ieee80211_crypt_tkip-rsl.o: ieee80211_crypt_tkip.o
- mv $^ $@
-
-ieee80211_crypt_ccmp-rsl.o: ieee80211_crypt_ccmp.o
- mv $^ $@
-
-crypto-rsl.o: arc4.o api.o autoload.o cipher.o compress.o digest.o scatterwalk.o proc.o
- $(LD) -r $^ -o $@
-
-ieee80211-rsl.o: ieee80211_rx.o ieee80211_tx.o ieee80211_wx.o ieee80211_module.o ieee80211_softmac_wx.o ieee80211_softmac.o rtl819x_HTProc.o rtl819x_TSProc.o rtl819x_BAProc.o dot11d.o
- $(LD) -r $^ -o $@
-install:
- rm -fr $(MODDESTDIR)
- mkdir -p $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt-rsl.o $(MODDESTDIR)
- @install -p -m 644 crypto-rsl.o $(MODDESTDIR)
- @install -p -m 644 michael_mic-rsl.o $(MODDESTDIR)
- @install -p -m 644 aes-rsl.o $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt_wep-rsl.o $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt_tkip-rsl.o $(MODDESTDIR)
- @install -p -m 644 ieee80211_crypt_ccmp-rsl.o $(MODDESTDIR)
- @install -p -m 644 ieee80211-rsl.o $(MODDESTDIR)
- /sbin/depmod -a ${shell uname -r}
-
-uninstall:
- rm -fr $(MODDESTDIR)
- /sbin/depmod -a ${shell uname -r}
-
-endif
-
-.PHONY: clean
-clean:
- rm -fr *.mod.c *.mod *.o .*.cmd *.mod.* *.ko *.o *~
- rm -rf .tmp_versions
- rm -rf Module.symvers
diff --git a/drivers/staging/rtl8192u/ieee80211/compress.c b/drivers/staging/rtl8192u/ieee80211/compress.c
index 86c23c9..5416ab6 100644
--- a/drivers/staging/rtl8192u/ieee80211/compress.c
+++ b/drivers/staging/rtl8192u/ieee80211/compress.c
@@ -12,10 +12,10 @@
*
*/
#include <linux/types.h>
-//#include <linux/crypto.h>
+/*#include <linux/crypto.h>*/
#include "rtl_crypto.h"
#include <linux/errno.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/string.h>
#include "internal.h"
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index e716f7b..1c0a1db 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -25,12 +25,12 @@
#define IEEE80211_H
#include <linux/if_ether.h> /* ETH_ALEN */
#include <linux/kernel.h> /* ARRAY_SIZE */
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/wireless.h>
@@ -2416,8 +2416,8 @@ extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
/* ieee80211_softmac.c */
-extern short ieee80211_is_54g(struct ieee80211_network net);
-extern short ieee80211_is_shortslot(struct ieee80211_network net);
+extern short ieee80211_is_54g(const struct ieee80211_network *net);
+extern short ieee80211_is_shortslot(const struct ieee80211_network *net);
extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats, u16 type,
u16 stype);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
index 8707eba..a464d11 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
@@ -12,7 +12,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
index 4b078e5..fec0176 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
@@ -10,7 +10,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index a98584c..555eb80 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -10,7 +10,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
index 96c2c9d..3801f12 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
@@ -10,7 +10,6 @@
*/
//#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index fe978f3..e3d47bc 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
@@ -283,7 +282,7 @@ int __init ieee80211_debug_init(void)
ieee80211_debug_level = debug;
- ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+ ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
if (ieee80211_proc == NULL) {
IEEE80211_ERROR("Unable to create " DRV_NAME
" proc directory\n");
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index a414303..c9bdc7f 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -37,7 +37,6 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 4ec0a65..c2ab5fa 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -19,7 +19,6 @@
#include <linux/random.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/version.h>
#include <asm/uaccess.h>
#include "dot11d.h"
@@ -32,14 +31,14 @@ u8 rsn_authen_cipher_suite[16][4] = {
{0x00,0x0F,0xAC,0x05}, //WEP-104
};
-short ieee80211_is_54g(struct ieee80211_network net)
+short ieee80211_is_54g(const struct ieee80211_network *net)
{
- return ((net.rates_ex_len > 0) || (net.rates_len > 4));
+ return (net->rates_ex_len > 0) || (net->rates_len > 4);
}
-short ieee80211_is_shortslot(struct ieee80211_network net)
+short ieee80211_is_shortslot(const struct ieee80211_network *net)
{
- return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
+ return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
}
/* returns the total length needed for pleacing the RATE MFIE
@@ -719,7 +718,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
else
atim_len = 0;
- if(ieee80211_is_54g(ieee->current_network))
+ if(ieee80211_is_54g(&ieee->current_network))
erp_len = 3;
else
erp_len = 0;
@@ -777,7 +776,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
- cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
+ beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
crypt = ieee->crypt[ieee->tx_keyidx];
if (encrypt)
@@ -1334,7 +1333,7 @@ void ieee80211_associate_complete_wq(struct work_struct *work)
{
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
printk(KERN_INFO "Associated successfully\n");
- if(ieee80211_is_54g(ieee->current_network) &&
+ if(ieee80211_is_54g(&ieee->current_network) &&
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
ieee->rate = 108;
@@ -1490,7 +1489,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
ieee->state = IEEE80211_ASSOCIATING;
queue_work(ieee->wq, &ieee->associate_procedure_wq);
}else{
- if(ieee80211_is_54g(ieee->current_network) &&
+ if(ieee80211_is_54g(&ieee->current_network) &&
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
ieee->rate = 108;
ieee->SetWirelessMode(ieee->dev, IEEE_G);
@@ -2726,11 +2725,7 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
ieee->beacon_timer.data = (unsigned long) ieee;
ieee->beacon_timer.function = ieee80211_send_beacon_cb;
-#ifdef PF_SYNCTHREAD
- ieee->wq = create_workqueue(DRV_NAME,0);
-#else
ieee->wq = create_workqueue(DRV_NAME);
-#endif
INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index ec7845e..59c45a5 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -723,7 +723,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN;
- /* Each fragment may need to have room for encryptiong pre/postfix */
+ /* Each fragment may need to have room for encryption pre/postfix */
if (encrypt)
bytes_per_frag -= crypt->ops->extra_prefix_len +
crypt->ops->extra_postfix_len;
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index 0205079..9b81f26 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -37,7 +37,6 @@
#include <linux/proc_fs.h> // Necessary because we use the proc fs
#include <linux/if_arp.h>
#include <linux/random.h>
-#include <linux/version.h>
#include <asm/io.h>
#include "ieee80211/ieee80211.h"
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index e81b8ab..c09be0a 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -671,7 +671,7 @@ static int proc_get_stats_rx(char *page, char **start,
void rtl8192_proc_module_init(void)
{
RT_TRACE(COMP_INIT, "Initializing proc filesystem");
- rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net);
+ rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
}
@@ -706,9 +706,7 @@ void rtl8192_proc_init_one(struct net_device *dev)
{
struct proc_dir_entry *e;
struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
- priv->dir_dev = create_proc_entry(dev->name,
- S_IFDIR | S_IRUGO | S_IXUGO,
- rtl8192_proc);
+ priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
if (!priv->dir_dev) {
RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
dev->name);
@@ -2852,11 +2850,7 @@ static void rtl8192_init_priv_task(struct net_device* dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef PF_SYNCTHREAD
- priv->priv_wq = create_workqueue(DRV_NAME,0);
-#else
priv->priv_wq = create_workqueue(DRV_NAME);
-#endif
INIT_WORK(&priv->reset_wq, rtl8192_restart);
@@ -5745,7 +5739,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_get_stats = rtl8192_stats,
.ndo_tx_timeout = tx_timeout,
.ndo_do_ioctl = rtl8192_ioctl,
- .ndo_set_multicast_list = r8192_set_multicast,
+ .ndo_set_rx_mode = r8192_set_multicast,
.ndo_set_mac_address = r8192_set_mac_adr,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig
index 041e1e8..6a43312 100644
--- a/drivers/staging/rtl8712/Kconfig
+++ b/drivers/staging/rtl8712/Kconfig
@@ -9,11 +9,11 @@ config R8712U
This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130.
If built as a module, it will be called r8712u.
-config R8712_AP
- bool "Realtek RTL8712U AP code"
- depends on R8712U
+config R8712_TX_AGGR
+ bool "Realtek RTL8712U Transmit Aggregation code"
+ depends on R8712U && BROKEN
default N
---help---
- This option allows the Realtek RTL8712 USB device to be an Access Point.
+ This option provides transmit aggregation for the Realtek RTL8712 USB device.
diff --git a/drivers/staging/rtl8712/basic_types.h b/drivers/staging/rtl8712/basic_types.h
index a0538a8..7561bed 100644
--- a/drivers/staging/rtl8712/basic_types.h
+++ b/drivers/staging/rtl8712/basic_types.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __BASIC_TYPES_H__
#define __BASIC_TYPES_H__
diff --git a/drivers/staging/rtl8712/big_endian.h b/drivers/staging/rtl8712/big_endian.h
index 8512d1b..b16f8ec 100644
--- a/drivers/staging/rtl8712/big_endian.h
+++ b/drivers/staging/rtl8712/big_endian.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H
#define _LINUX_BYTEORDER_BIG_ENDIAN_H
diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h
index 3bb66dc..ed85b44 100644
--- a/drivers/staging/rtl8712/drv_types.h
+++ b/drivers/staging/rtl8712/drv_types.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
/*---------------------------------------------------------------------
For type defines and data structure defines
@@ -12,6 +37,8 @@ struct _adapter;
#include "wlan_bssdef.h"
#include "rtl8712_spec.h"
#include "rtl8712_hal.h"
+#include <linux/mutex.h>
+#include <linux/completion.h>
enum _NIC_VERSION {
RTL8711_NIC,
@@ -29,7 +56,6 @@ struct qos_priv {
#include "rtl871x_ht.h"
#include "rtl871x_cmd.h"
-#include "wlan_bssdef.h"
#include "rtl871x_xmit.h"
#include "rtl871x_recv.h"
#include "rtl871x_security.h"
@@ -118,6 +144,11 @@ struct dvobj_priv {
struct usb_device *pusbdev;
};
+/**
+ * struct _adapter - the main adapter structure for this device.
+ *
+ * bup: True indicates that the interface is Up.
+ */
struct _adapter {
struct dvobj_priv dvobjpriv;
struct mlme_priv mlmepriv;
@@ -139,6 +170,7 @@ struct _adapter {
s32 bSurpriseRemoved;
u32 IsrContent;
u32 ImrContent;
+ bool fw_found;
u8 EepromAddressSize;
u8 hw_init_completed;
struct task_struct *cmdThread;
@@ -152,6 +184,13 @@ struct _adapter {
struct net_device_stats stats;
struct iw_statistics iwstats;
int pid; /*process id from UI*/
+ _workitem wkFilterRxFF0;
+ u8 blnEnableRxFF0Filter;
+ spinlock_t lockRxFF0Filter;
+ const struct firmware *fw;
+ struct usb_interface *pusb_intf;
+ struct mutex mutex_start;
+ struct completion rtl8712_fw_ready;
};
static inline u8 *myid(struct eeprom_priv *peepriv)
diff --git a/drivers/staging/rtl8712/ethernet.h b/drivers/staging/rtl8712/ethernet.h
index ba8d777..882d61b 100644
--- a/drivers/staging/rtl8712/ethernet.h
+++ b/drivers/staging/rtl8712/ethernet.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __INC_ETHERNET_H
#define __INC_ETHERNET_H
diff --git a/drivers/staging/rtl8712/generic.h b/drivers/staging/rtl8712/generic.h
index 742424b..8868c9f 100644
--- a/drivers/staging/rtl8712/generic.h
+++ b/drivers/staging/rtl8712/generic.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _LINUX_BYTEORDER_GENERIC_H
#define _LINUX_BYTEORDER_GENERIC_H
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
index 1411c7bf..cc893c0 100644
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -28,6 +28,12 @@
#define _HAL_INIT_C_
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "rtl871x_byteorder.h"
@@ -36,29 +42,56 @@
#define FWBUFF_ALIGN_SZ 512
#define MAX_DUMP_FWSZ 49152 /*default = 49152 (48k)*/
-static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl,
- const u8 **ppmappedfw)
+static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
+{
+ struct _adapter *padapter = context;
+
+ complete(&padapter->rtl8712_fw_ready);
+ if (!firmware) {
+ struct usb_device *udev = padapter->dvobjpriv.pusbdev;
+ struct usb_interface *pusb_intf = padapter->pusb_intf;
+ printk(KERN_ERR "r8712u: Firmware request failed\n");
+ padapter->fw_found = false;
+ usb_put_dev(udev);
+ usb_set_intfdata(pusb_intf, NULL);
+ return;
+ }
+ padapter->fw = firmware;
+ padapter->fw_found = true;
+ /* firmware available - start netdev */
+ register_netdev(padapter->pnetdev);
+}
+
+static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+
+int rtl871x_load_fw(struct _adapter *padapter)
{
+ struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
int rc;
- const char firmware_file[] = "rtlwifi/rtl8712u.bin";
- const struct firmware **praw = (const struct firmware **)
- (pphfwfile_hdl);
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
- (&padapter->dvobjpriv);
- struct usb_device *pusbdev = pdvobjpriv->pusbdev;
+ init_completion(&padapter->rtl8712_fw_ready);
printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",
firmware_file);
- rc = request_firmware(praw, firmware_file, &pusbdev->dev);
- if (rc < 0) {
- printk(KERN_ERR "r8712u: Unable to load firmware\n");
- printk(KERN_ERR "r8712u: Install latest linux-firmware\n");
+ rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
+ GFP_KERNEL, padapter, rtl871x_load_fw_cb);
+ if (rc)
+ printk(KERN_ERR "r8712u: Firmware request error %d\n", rc);
+ return rc;
+}
+MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
+
+static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw)
+{
+ const struct firmware **praw = &padapter->fw;
+
+ if (padapter->fw->size > 200000) {
+ printk(KERN_ERR "r8172u: Badfw->size of %d\n",
+ (int)padapter->fw->size);
return 0;
}
*ppmappedfw = (u8 *)((*praw)->data);
return (*praw)->size;
}
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
{
@@ -136,18 +169,17 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
struct fw_hdr fwhdr;
u32 ulfilelength; /* FW file size */
- void *phfwfile_hdl = NULL;
const u8 *pmappedfw = NULL;
u8 *ptmpchar = NULL, *ppayload, *ptr;
struct tx_desc *ptx_desc;
u32 txdscp_sz = sizeof(struct tx_desc);
u8 ret = _FAIL;
- ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw);
+ ulfilelength = rtl871x_open_fw(padapter, &pmappedfw);
if (pmappedfw && (ulfilelength > 0)) {
update_fwhdr(&fwhdr, pmappedfw);
if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
- goto firmware_rel;
+ return ret;
fill_fwpriv(padapter, &fwhdr.fwpriv);
/* firmware check ok */
maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
@@ -155,7 +187,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
maxlen += txdscp_sz;
ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ);
if (ptmpchar == NULL)
- goto firmware_rel;
+ return ret;
ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ -
((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1)));
@@ -291,8 +323,6 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
exit_fail:
kfree(ptmpchar);
-firmware_rel:
- release_firmware((struct firmware *)phfwfile_hdl);
return ret;
}
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
index f06addc..cc68d97 100644
--- a/drivers/staging/rtl8712/ieee80211.c
+++ b/drivers/staging/rtl8712/ieee80211.c
@@ -170,17 +170,11 @@ static uint r8712_get_rateset_len(u8 *rateset)
return i;
}
-int r8712_generate_ie(struct registry_priv *pregistrypriv,
- struct _adapter *padapter)
+int r8712_generate_ie(struct registry_priv *pregistrypriv)
{
int sz = 0, rateLen;
struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
u8 *ie = pdev_network->IEs;
- struct ieee80211_ht_cap ht_capie;
- struct ieee80211_ht_addt_info ht_addt_info;
- unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
/*timestamp will be inserted by hardware*/
sz += 8;
@@ -219,33 +213,6 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv,
/*IBSS Parameter Set*/
ie = r8712_set_ie(ie, _IBSS_PARA_IE_, 2,
(u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
- if (pregistrypriv->ht_enable == 1) {
- if (pqospriv->qos_option == 0) {
- ie = r8712_set_ie(ie, _VENDOR_SPECIFIC_IE_,
- _WMM_IE_Length_, WMM_IE, &sz);
- pqospriv->qos_option = 1;
- }
- memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
- ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_TX_STBC |
- IEEE80211_HT_CAP_MAX_AMSDU |
- IEEE80211_HT_CAP_DSSSCCK40;
- ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR &
- 0x03) | (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
- ie = r8712_set_ie(ie, _HT_CAPABILITY_IE_,
- sizeof(struct ieee80211_ht_cap),
- (unsigned char *)&ht_capie, &sz);
- /*add HT info ie*/
- memset(&ht_addt_info, 0,
- sizeof(struct ieee80211_ht_addt_info));
- /*need to add the HT additional IEs*/
- ht_addt_info.control_chan = pregistrypriv->channel;
- ie = r8712_set_ie(ie, _HT_ADD_INFO_IE_,
- sizeof(struct ieee80211_ht_addt_info),
- (unsigned char *)&ht_addt_info, &sz);
- }
return sz;
}
diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h
index 1f4d147..3c0092b 100644
--- a/drivers/staging/rtl8712/ieee80211.h
+++ b/drivers/staging/rtl8712/ieee80211.h
@@ -1,9 +1,35 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __IEEE80211_H
#define __IEEE80211_H
#include "osdep_service.h"
#include "drv_types.h"
#include "wifi.h"
+#include <linux/compiler.h>
#include <linux/wireless.h>
#define MGMT_QUEUE_NUM 5
@@ -111,7 +137,7 @@ struct ieee_ibss_seq {
u8 mac[ETH_ALEN];
u16 seq_num;
u16 frag_num;
- unsigned int packet_time;
+ unsigned long packet_time;
struct list_head list;
};
@@ -123,7 +149,7 @@ struct ieee80211_hdr {
u8 addr3[ETH_ALEN];
u16 seq_ctl;
u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_hdr_3addr {
u16 frame_ctl;
@@ -132,7 +158,7 @@ struct ieee80211_hdr_3addr {
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
u16 seq_ctl;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_hdr_qos {
@@ -144,7 +170,7 @@ struct ieee80211_hdr_qos {
u16 seq_ctl;
u8 addr4[ETH_ALEN];
u16 qc;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_hdr_3addr_qos {
u16 frame_ctl;
@@ -154,7 +180,7 @@ struct ieee80211_hdr_3addr_qos {
u8 addr3[ETH_ALEN];
u16 seq_ctl;
u16 qc;
-} __attribute__ ((packed));
+} __packed;
struct eapol {
u8 snap[6];
@@ -162,7 +188,7 @@ struct eapol {
u8 version;
u8 type;
u16 length;
-} __attribute__ ((packed));
+} __packed;
enum eap_type {
@@ -260,7 +286,7 @@ struct ieee80211_snap_hdr {
u8 ssap; /* always 0xAA */
u8 ctrl; /* always 0x03 */
u8 oui[P80211_OUI_LEN]; /* organizational universal id */
-} __attribute__ ((packed));
+} __packed;
#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
@@ -510,7 +536,7 @@ struct ieee80211_security {
u8 keys[WEP_KEYS][WEP_KEY_LEN];
u8 level;
u16 flags;
-} __attribute__ ((packed));
+} __packed;
/*
@@ -555,13 +581,13 @@ struct ieee80211_header_data {
struct ieee80211_info_element_hdr {
u8 id;
u8 len;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_info_element {
u8 id;
u8 len;
u8 data[0];
-} __attribute__ ((packed));
+} __packed;
/*
* These are the data types that can make up management packets
@@ -574,7 +600,7 @@ struct ieee80211_info_element {
u16 listen_interval;
struct {
u16 association_id:14, reserved:2;
- } __attribute__ ((packed));
+ } __packed;
u32 time_stamp[2];
u16 reason;
u16 status;
@@ -588,7 +614,7 @@ struct ieee80211_authentication {
u16 algorithm;
u16 transaction;
u16 status;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_probe_response {
struct ieee80211_header_data header;
@@ -596,25 +622,25 @@ struct ieee80211_probe_response {
u16 beacon_interval;
u16 capability;
struct ieee80211_info_element info_element;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_probe_request {
struct ieee80211_header_data header;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_assoc_request_frame {
struct ieee80211_hdr_3addr header;
u16 capability;
u16 listen_interval;
struct ieee80211_info_element_hdr info_element;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_assoc_response_frame {
struct ieee80211_hdr_3addr header;
u16 capability;
u16 status;
u16 aid;
-} __attribute__ ((packed));
+} __packed;
struct ieee80211_txb {
u8 nr_frags;
@@ -643,7 +669,6 @@ struct ieee80211_txb {
#define CRC_LENGTH 4U
#define MAX_WPA_IE_LEN 128
-#define MAX_WPS_IE_LEN 512
#define NETWORK_EMPTY_ESSID (1<<0)
#define NETWORK_HAS_OFDM (1<<1)
@@ -763,8 +788,7 @@ int r8712_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
u8 *wpa_ie, u16 *wpa_len);
int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
-int r8712_generate_ie(struct registry_priv *pregistrypriv,
- struct _adapter *padapter);
+int r8712_generate_ie(struct registry_priv *pregistrypriv);
uint r8712_is_cckrates_included(u8 *rate);
uint r8712_is_cckratesonly_included(u8 *rate);
diff --git a/drivers/staging/rtl8712/if_ether.h b/drivers/staging/rtl8712/if_ether.h
index 0e9753b..2bbe527 100644
--- a/drivers/staging/rtl8712/if_ether.h
+++ b/drivers/staging/rtl8712/if_ether.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
diff --git a/drivers/staging/rtl8712/little_endian.h b/drivers/staging/rtl8712/little_endian.h
index 0248c14..cd57d6c 100644
--- a/drivers/staging/rtl8712/little_endian.h
+++ b/drivers/staging/rtl8712/little_endian.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H
#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H
diff --git a/drivers/staging/rtl8712/mlme_osdep.h b/drivers/staging/rtl8712/mlme_osdep.h
index 968e787..a20fe81 100644
--- a/drivers/staging/rtl8712/mlme_osdep.h
+++ b/drivers/staging/rtl8712/mlme_osdep.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __MLME_OSDEP_H_
#define __MLME_OSDEP_H_
diff --git a/drivers/staging/rtl8712/mp_custom_oid.h b/drivers/staging/rtl8712/mp_custom_oid.h
index a9e0b34..4051008 100644
--- a/drivers/staging/rtl8712/mp_custom_oid.h
+++ b/drivers/staging/rtl8712/mp_custom_oid.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __CUSTOM_OID_H
#define __CUSTOM_OID_H
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 3f38e8e..4bb2797 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h>
+#include <linux/firmware.h>
#include "osdep_service.h"
#include "drv_types.h"
#include "xmit_osdep.h"
@@ -177,7 +178,7 @@ static uint loadparam(struct _adapter *padapter, struct net_device *pnetdev)
static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(pnetdev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
struct sockaddr *addr = p;
if (padapter->bup == false)
@@ -187,7 +188,7 @@ static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
static struct net_device_stats *r871x_net_get_stats(struct net_device *pnetdev)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(pnetdev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(pnetdev);
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
struct recv_priv *precvpriv = &(padapter->recvpriv);
@@ -221,7 +222,7 @@ struct net_device *r8712_init_netdev(void)
strcpy(ifname, "wlan%d");
dev_alloc_name(pnetdev, ifname);
}
- padapter = (struct _adapter *) _netdev_priv(pnetdev);
+ padapter = (struct _adapter *) netdev_priv(pnetdev);
padapter->pnetdev = pnetdev;
printk(KERN_INFO "r8712u: register rtl8712_netdev_ops to"
" netdev_ops\n");
@@ -261,15 +262,15 @@ static void start_drv_timers(struct _adapter *padapter)
_set_timer(&padapter->mlmepriv.wdg_timer, 2000);
}
-static void stop_drv_timers(struct _adapter *padapter)
+void r8712_stop_drv_timers(struct _adapter *padapter)
{
_cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
- _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
- sitesurvey_ctrl_timer);
_cancel_timer_ex(&padapter->securitypriv.tkip_timer);
_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
_cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);
_cancel_timer_ex(&padapter->mlmepriv.wdg_timer);
+ _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
+ sitesurvey_ctrl_timer);
}
static u8 init_default_value(struct _adapter *padapter)
@@ -286,6 +287,9 @@ static u8 init_default_value(struct _adapter *padapter)
pxmitpriv->vcs_type = pregistrypriv->vcs_type;
pxmitpriv->rts_thresh = pregistrypriv->rts_thresh;
pxmitpriv->frag_len = pregistrypriv->frag_thresh;
+ /* mlme_priv */
+ /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
+ pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
/*ht_priv*/
{
int i;
@@ -344,11 +348,12 @@ u8 r8712_free_drv_sw(struct _adapter *padapter)
r8712_free_mlme_priv(&padapter->mlmepriv);
r8712_free_io_queue(padapter);
_free_xmit_priv(&padapter->xmitpriv);
- _r8712_free_sta_priv(&padapter->stapriv);
+ if (padapter->fw_found)
+ _r8712_free_sta_priv(&padapter->stapriv);
_r8712_free_recv_priv(&padapter->recvpriv);
mp871xdeinit(padapter);
if (pnetdev)
- os_free_netdev(pnetdev);
+ free_netdev(pnetdev);
return _SUCCESS;
}
@@ -375,10 +380,17 @@ static void enable_video_mode(struct _adapter *padapter, int cbw40_value)
r8712_fw_cmd(padapter, intcmd);
}
+/**
+ *
+ * This function intends to handle the activation of an interface
+ * i.e. when it is brought Up/Active from a Down state.
+ *
+ */
static int netdev_open(struct net_device *pnetdev)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(pnetdev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
+ mutex_lock(&padapter->mutex_start);
if (padapter->bup == false) {
padapter->bDriverStopped = false;
padapter->bSurpriseRemoved = false;
@@ -426,17 +438,25 @@ static int netdev_open(struct net_device *pnetdev)
/* start driver mlme relation timer */
start_drv_timers(padapter);
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
+ mutex_unlock(&padapter->mutex_start);
return 0;
netdev_open_error:
padapter->bup = false;
netif_carrier_off(pnetdev);
netif_stop_queue(pnetdev);
+ mutex_unlock(&padapter->mutex_start);
return -1;
}
+/**
+ *
+ * This function intends to handle the shutdown of an interface
+ * i.e. when it is brought Down from an Up/Active state.
+ *
+ */
static int netdev_close(struct net_device *pnetdev)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(pnetdev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(pnetdev);
/* Close LED*/
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_POWER_OFF);
@@ -456,8 +476,6 @@ static int netdev_close(struct net_device *pnetdev)
r8712_free_assoc_resources(padapter);
/*s2-4.*/
r8712_free_network_queue(padapter);
- /*Stop driver mlme relation timer*/
- stop_drv_timers(padapter);
return 0;
}
diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h
index 3bc2025..aa0ec74 100644
--- a/drivers/staging/rtl8712/osdep_intf.h
+++ b/drivers/staging/rtl8712/osdep_intf.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __OSDEP_INTF_H_
#define __OSDEP_INTF_H_
diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h
index 3d3f73c..1ee943a 100644
--- a/drivers/staging/rtl8712/osdep_service.h
+++ b/drivers/staging/rtl8712/osdep_service.h
@@ -1,43 +1,47 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __OSDEP_SERVICE_H_
#define __OSDEP_SERVICE_H_
#define _SUCCESS 1
#define _FAIL 0
-#include "basic_types.h"
#include <linux/version.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#include <linux/semaphore.h>
+#include <linux/sched.h>
#include <linux/sem.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <net/iw_handler.h>
-#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/io.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <linux/wireless.h>
-#include <linux/rtnetlink.h>
-#include "ethernet.h"
-#include <linux/if_arp.h>
-#include <linux/firmware.h>
-#define _usb_alloc_urb(x, y) usb_alloc_urb(x, y)
-#define _usb_submit_urb(x, y) usb_submit_urb(x, y)
+#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
+
+#include "basic_types.h"
struct __queue {
struct list_head queue;
@@ -48,7 +52,6 @@ struct __queue {
#define _buffer unsigned char
#define thread_exit() complete_and_exit(NULL, 0)
#define _workitem struct work_struct
-#define MSECS(t) (HZ * ((t) / 1000) + (HZ * ((t) % 1000)) / 1000)
#define _init_queue(pqueue) \
do { \
@@ -56,16 +59,6 @@ struct __queue {
spin_lock_init(&((pqueue)->lock)); \
} while (0)
-static inline void *_netdev_priv(struct net_device *dev)
-{
- return netdev_priv(dev);
-}
-
-static inline void os_free_netdev(struct net_device *dev)
-{
- free_netdev(dev);
-}
-
static inline struct list_head *get_next(struct list_head *list)
{
return list->next;
@@ -206,7 +199,6 @@ static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer)
static inline void thread_enter(void *context)
{
- daemonize("%s", "RTKTHREAD");
allow_signal(SIGTERM);
}
@@ -236,7 +228,5 @@ static inline u32 _RND512(u32 sz)
return ((sz >> 9) + ((sz & 511) ? 1 : 0)) << 9;
}
-#define STRUCT_PACKED __attribute__ ((packed))
-
#endif
diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c
index 30a9c62..495ee12 100644
--- a/drivers/staging/rtl8712/recv_linux.c
+++ b/drivers/staging/rtl8712/recv_linux.c
@@ -28,11 +28,15 @@
#define _RECV_OSDEP_C_
+#include <linux/usb.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "wifi.h"
#include "recv_osdep.h"
#include "osdep_intf.h"
+#include "ethernet.h"
+#include <linux/if_arp.h>
#include "usb_ops.h"
/*init os related resource in struct recv_priv*/
@@ -51,7 +55,7 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
int res = _SUCCESS;
precvbuf->irp_pending = false;
- precvbuf->purb = _usb_alloc_urb(0, GFP_KERNEL);
+ precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
if (precvbuf->purb == NULL)
res = _FAIL;
precvbuf->pskb = NULL;
diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h
index 60a54dd..f4384ef 100644
--- a/drivers/staging/rtl8712/recv_osdep.h
+++ b/drivers/staging/rtl8712/recv_osdep.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RECV_OSDEP_H_
#define __RECV_OSDEP_H_
diff --git a/drivers/staging/rtl8712/rtl8712_bitdef.h b/drivers/staging/rtl8712/rtl8712_bitdef.h
index 356184f..bff57a8 100644
--- a/drivers/staging/rtl8712/rtl8712_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_bitdef.h
@@ -1,3 +1,24 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+
+
#ifndef __RTL8712_BITDEF_H__
#define __RTL8712_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c
index 26c605e..9f6ebc4 100644
--- a/drivers/staging/rtl8712/rtl8712_cmd.c
+++ b/drivers/staging/rtl8712/rtl8712_cmd.c
@@ -28,6 +28,24 @@
#define _RTL8712_CMD_C_
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/circ_buf.h>
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+#include <linux/rtnetlink.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h
index 13ef062..766a646 100644
--- a/drivers/staging/rtl8712/rtl8712_cmd.h
+++ b/drivers/staging/rtl8712/rtl8712_cmd.h
@@ -1,9 +1,40 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_CMD_H_
#define __RTL8712_CMD_H_
+#define CMD_HDR_SZ 8
+
u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd);
void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag);
+struct cmd_hdr {
+ u32 cmd_dw0;
+ u32 cmd_dw1;
+};
enum rtl8712_h2c_cmd {
GEN_CMD_CODE(_Read_MACREG), /*0*/
@@ -72,6 +103,40 @@ enum rtl8712_h2c_cmd {
GEN_CMD_CODE(_SetPowerTracking),
GEN_CMD_CODE(_AMSDU_TO_AMPDU), /*57*/
GEN_CMD_CODE(_SetMacAddress), /*58*/
+
+ GEN_CMD_CODE(_DisconnectCtrl), /*59*/
+ GEN_CMD_CODE(_SetChannelPlan), /*60*/
+ GEN_CMD_CODE(_DisconnectCtrlEx), /*61*/
+
+ /* To do, modify these h2c cmd, add or delete */
+ GEN_CMD_CODE(_GetH2cLbk) ,
+
+ /* WPS extra IE */
+ GEN_CMD_CODE(_SetProbeReqExtraIE) ,
+ GEN_CMD_CODE(_SetAssocReqExtraIE) ,
+ GEN_CMD_CODE(_SetProbeRspExtraIE) ,
+ GEN_CMD_CODE(_SetAssocRspExtraIE) ,
+
+ /* the following is driver will do */
+ GEN_CMD_CODE(_GetCurDataRate) ,
+
+ GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to
+ * transmmit packet after association
+ */
+ GEN_CMD_CODE(_GetRxRetrycnt), /* to record total number of the
+ * received frame with ReTry bit set in
+ * the WLAN header
+ */
+
+ GEN_CMD_CODE(_GetBCNOKcnt),
+ GEN_CMD_CODE(_GetBCNERRcnt),
+ GEN_CMD_CODE(_GetCurTxPwrLevel),
+
+ GEN_CMD_CODE(_SetDIG),
+ GEN_CMD_CODE(_SetRA),
+ GEN_CMD_CODE(_SetPT),
+ GEN_CMD_CODE(_ReadTSSI),
+
MAX_H2CCMD
};
@@ -151,6 +216,28 @@ static struct _cmd_callback cmd_callback[] = {
{GEN_CMD_CODE(_SetPowerTracking), NULL},
{GEN_CMD_CODE(_AMSDU_TO_AMPDU), NULL}, /*57*/
{GEN_CMD_CODE(_SetMacAddress), NULL}, /*58*/
+
+ {GEN_CMD_CODE(_DisconnectCtrl), NULL}, /*59*/
+ {GEN_CMD_CODE(_SetChannelPlan), NULL}, /*60*/
+ {GEN_CMD_CODE(_DisconnectCtrlEx), NULL}, /*61*/
+
+ /* To do, modify these h2c cmd, add or delete */
+ {GEN_CMD_CODE(_GetH2cLbk), NULL},
+
+ {_SetProbeReqExtraIE_CMD_, NULL},
+ {_SetAssocReqExtraIE_CMD_, NULL},
+ {_SetProbeRspExtraIE_CMD_, NULL},
+ {_SetAssocRspExtraIE_CMD_, NULL},
+ {_GetCurDataRate_CMD_, NULL},
+ {_GetTxRetrycnt_CMD_, NULL},
+ {_GetRxRetrycnt_CMD_, NULL},
+ {_GetBCNOKcnt_CMD_, NULL},
+ {_GetBCNERRcnt_CMD_, NULL},
+ {_GetCurTxPwrLevel_CMD_, NULL},
+ {_SetDIG_CMD_, NULL},
+ {_SetRA_CMD_, NULL},
+ {_SetPT_CMD_, NULL},
+ {GEN_CMD_CODE(_ReadTSSI), &r8712_readtssi_cmdrsp_callback}
};
#endif
diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
index 6c49903..8dffe10 100644
--- a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_CMDCTRL_BITDEF_H__
#define __RTL8712_CMDCTRL_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
index 5d9a3f2..9374f1c 100644
--- a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_CMDCTRL_REGDEF_H__
#define __RTL8712_CMDCTRL_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
index 7b34d40..8bd4837 100644
--- a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_DEBUGCTRL_BITDEF_H__
#define __RTL8712_DEBUGCTRL_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
index 27cad71..43630bb 100644
--- a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_DEBUGCTRL_REGDEF_H__
#define __RTL8712_DEBUGCTRL_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
index c69b1b7..32dab81 100644
--- a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_EDCASETTING_BITDEF_H__
#define __RTL8712_EDCASETTING_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
index de3d3e2..d992cb8 100644
--- a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_EDCASETTING_REGDEF_H__
#define __RTL8712_EDCASETTING_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
index 1dc12b7..b08e9a2 100644
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ b/drivers/staging/rtl8712/rtl8712_efuse.c
@@ -307,21 +307,25 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr)
continue;
}
for (i = 0; i < PGPKG_MAX_WORDS; i++) {
- if (BIT(i) & word_en)
- continue;
- if (!(BIT(i) & pkt.word_en)) {
- if (efuse_one_byte_read(padapter, addr,
- &value) == true)
- pkt.data[i*2] = value;
- else
- return false;
- if (efuse_one_byte_read(padapter, addr + 1,
- &value) == true)
- pkt.data[i*2 + 1] = value;
- else
- return false;
+ if (BIT(i) & word_en) {
+ if (BIT(i) & pkt.word_en) {
+ if (efuse_one_byte_read(
+ padapter, addr,
+ &value) == true)
+ pkt.data[i*2] = value;
+ else
+ return false;
+ if (efuse_one_byte_read(
+ padapter,
+ addr + 1,
+ &value) == true)
+ pkt.data[i*2 + 1] =
+ value;
+ else
+ return false;
+ }
+ addr += 2;
}
- addr += 2;
}
}
if (addr != header_addr)
@@ -329,26 +333,29 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr)
addr++;
/* fill original data */
for (i = 0; i < PGPKG_MAX_WORDS; i++) {
- if (BIT(i) & pkt.word_en)
- continue;
- efuse_one_byte_write(padapter, addr, pkt.data[i*2]);
- efuse_one_byte_write(padapter, addr+1, pkt.data[i*2 + 1]);
- /* additional check */
- if (efuse_one_byte_read(padapter, addr, &value) == false)
- ret = false;
- else if (pkt.data[i*2] != value) {
- ret = false;
- if (0xFF == value) /* write again */
- efuse_one_byte_write(padapter, addr,
- pkt.data[i * 2]);
- }
- if (efuse_one_byte_read(padapter, addr+1, &value) == false)
- ret = false;
- else if (pkt.data[i*2 + 1] != value) {
- ret = false;
- if (0xFF == value) /* write again */
- efuse_one_byte_write(padapter, addr+1,
- pkt.data[i*2 + 1]);
+ if (BIT(i) & pkt.word_en) {
+ efuse_one_byte_write(padapter, addr, pkt.data[i*2]);
+ efuse_one_byte_write(padapter, addr+1,
+ pkt.data[i*2 + 1]);
+ /* additional check */
+ if (efuse_one_byte_read(padapter, addr, &value)
+ == false)
+ ret = false;
+ else if (pkt.data[i*2] != value) {
+ ret = false;
+ if (0xFF == value) /* write again */
+ efuse_one_byte_write(padapter, addr,
+ pkt.data[i * 2]);
+ }
+ if (efuse_one_byte_read(padapter, addr+1, &value) ==
+ false)
+ ret = false;
+ else if (pkt.data[i*2 + 1] != value) {
+ ret = false;
+ if (0xFF == value) /* write again */
+ efuse_one_byte_write(padapter, addr+1,
+ pkt.data[i*2 + 1]);
+ }
}
addr += 2;
}
diff --git a/drivers/staging/rtl8712/rtl8712_event.h b/drivers/staging/rtl8712/rtl8712_event.h
index 2731693..3d7f79e 100644
--- a/drivers/staging/rtl8712/rtl8712_event.h
+++ b/drivers/staging/rtl8712/rtl8712_event.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL8712_EVENT_H_
#define _RTL8712_EVENT_H_
diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
index e5df19f..c564dc8 100644
--- a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_FIFOCTRL_BITDEF_H__
#define __RTL8712_FIFOCTRL_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
index c2e3af2..29b89c4 100644
--- a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_FIFOCTRL_REGDEF_H__
#define __RTL8712_FIFOCTRL_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
index 35ca809..884a821 100644
--- a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_GP_BITDEF_H__
#define __RTL8712_GP_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_gp_regdef.h b/drivers/staging/rtl8712/rtl8712_gp_regdef.h
index 17e72bd..8fc68f6 100644
--- a/drivers/staging/rtl8712/rtl8712_gp_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_gp_regdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_GP_REGDEF_H__
#define __RTL8712_GP_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h
index 66baa87..d19865a 100644
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ b/drivers/staging/rtl8712/rtl8712_hal.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_HAL_H__
#define __RTL8712_HAL_H__
@@ -113,12 +138,13 @@ struct fw_hdr {/*8-byte alinment required*/
struct fw_priv fwpriv;
};
-struct hal_priv{
+struct hal_priv {
/*Endpoint handles*/
struct net_device *pipehdls_r8712[10];
u8 (*hal_bus_init)(struct _adapter *adapter);
};
uint rtl8712_hal_init(struct _adapter *padapter);
+int rtl871x_load_fw(struct _adapter *padapter);
#endif
diff --git a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h b/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
index 02f2480..49598c3 100644
--- a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_INTERRUPT_BITDEF_H__
#define __RTL8712_INTERRUPT_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index cb1751e..bac56e5 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -1786,7 +1786,7 @@ void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction)
{
struct led_priv *ledpriv = &(padapter->ledpriv);
- if (ledpriv == NULL || ledpriv->bRegUseLed == false)
+ if (ledpriv->bRegUseLed == false)
return;
switch (ledpriv->LedStrategy) {
case SW_LED_MODE0:
diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
index 74800cd..28e0a7e 100644
--- a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_MACSETTING_BITDEF_H__
#define __RTL8712_MACSETTING_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
index 00b003b..ced0da9 100644
--- a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_MACSETTING_REGDEF_H__
#define __RTL8712_MACSETTING_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h b/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
index 0922a8d..8fc6894 100644
--- a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_POWERSAVE_BITDEF_H__
#define __RTL8712_POWERSAVE_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h b/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
index 72927df..4632ddd 100644
--- a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_POWERSAVE_REGDEF_H__
#define __RTL8712_POWERSAVE_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
index 87048b3..6d3d6e8 100644
--- a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_RATECTRL_BITDEF_H__
#define __RTL8712_RATECTRL_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
index 31c8363..73dfc36 100644
--- a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_RATECTRL_REGDEF_H__
#define __RTL8712_RATECTRL_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index 625a8a0..a33bece 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -192,7 +192,7 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
} else
pattrib->tcpchk_valid = 0; /* invalid */
pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f);
- pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 6) & 0x1);
+ pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 14) & 0x1);
/*Offset 16*/
/*Offset 20*/
/*phy_info*/
@@ -207,7 +207,7 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter,
struct __queue *defrag_q)
{
struct list_head *plist, *phead;
- u8 wlanhdr_offset;
+ u8 *data, wlanhdr_offset;
u8 curfragnum;
struct recv_frame_hdr *pfhdr, *pnfhdr;
union recv_frame *prframe, *pnextrframe;
@@ -224,22 +224,25 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter,
/*the first fragment number must be 0
*free the whole queue*/
r8712_free_recvframe(prframe, pfree_recv_queue);
- prframe = NULL;
- goto exit;
+ r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
+ return NULL;
}
- plist = get_next(phead);
+ curfragnum++;
+ plist = get_list_head(defrag_q);
+ plist = get_next(plist);
+ data = get_recvframe_data(prframe);
while (end_of_queue_search(phead, plist) == false) {
pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
- /*check the fragment sequence (2nd ~n fragment frame) */
pnfhdr = &pnextrframe->u.hdr;
- curfragnum++;
+ /*check the fragment sequence (2nd ~n fragment frame) */
if (curfragnum != pnfhdr->attrib.frag_num) {
/* the fragment number must increase (after decache)
* release the defrag_q & prframe */
r8712_free_recvframe(prframe, pfree_recv_queue);
- prframe = NULL;
- goto exit;
+ r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
+ return NULL;
}
+ curfragnum++;
/* copy the 2nd~n fragment frame's payload to the first fragment
* get the 2nd~last fragment frame's payload */
wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
@@ -252,7 +255,6 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter,
pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
plist = get_next(plist);
}
-exit:
/* free the defrag_q queue and return the prframe */
r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
return prframe;
@@ -1074,7 +1076,8 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
/* for first fragment packet, driver need allocate 1536 +
* drvinfo_sz + RXDESC_SIZE to defrag packet. */
if ((mf == 1) && (frag == 0))
- alloc_sz = 1658;
+ /*1658+6=1664, 1664 is 128 alignment.*/
+ alloc_sz = max_t(u16, tmp_len, 1658);
else
alloc_sz = tmp_len;
/* 2 is for IP header 4 bytes alignment in QoS packet case.
diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h
index c48757f..8efbd1f 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.h
+++ b/drivers/staging/rtl8712/rtl8712_recv.h
@@ -1,10 +1,40 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL8712_RECV_H_
#define _RTL8712_RECV_H_
#include "osdep_service.h"
#include "drv_types.h"
+/* Realtek's v2.6.6 reduced this to 4. However, under heavy network and CPU
+ * loads, even 8 receive buffers might not be enough; cutting it to 4 seemed
+ * unwise.
+ */
#define NR_RECVBUFF (8)
+
#define NR_PREALLOC_RECV_SKB (8)
#define RXDESC_SIZE 24
#define RXDESC_OFFSET RXDESC_SIZE
@@ -115,7 +145,6 @@ union recv_frame {
union {
struct list_head list;
struct recv_frame_hdr hdr;
- addr_t mem[RECVFRAME_HDR_ALIGN>>2];
} u;
};
diff --git a/drivers/staging/rtl8712/rtl8712_regdef.h b/drivers/staging/rtl8712/rtl8712_regdef.h
index 5b0de2a..e7bca55 100644
--- a/drivers/staging/rtl8712/rtl8712_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_regdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_REGDEF_H__
#define __RTL8712_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_security_bitdef.h b/drivers/staging/rtl8712/rtl8712_security_bitdef.h
index 8df4bf4..05dafa0 100644
--- a/drivers/staging/rtl8712/rtl8712_security_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_security_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_SECURITY_BITDEF_H__
#define __RTL8712_SECURITY_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_spec.h b/drivers/staging/rtl8712/rtl8712_spec.h
index 3f181ee..af11b44 100644
--- a/drivers/staging/rtl8712/rtl8712_spec.h
+++ b/drivers/staging/rtl8712/rtl8712_spec.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_SPEC_H__
#define __RTL8712_SPEC_H__
diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
index dce15c2..eed09c8 100644
--- a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_SYSCFG_BITDEF_H__
#define __RTL8712_SYSCFG_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
index 687e1b7..767dfdf 100644
--- a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_SYSCFG_REGDEF_H__
#define __RTL8712_SYSCFG_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
index 32ce9fa..7244215 100644
--- a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_TIMECTRL_BITDEF_H__
#define __RTL8712_TIMECTRL_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
index 8a3dd56..106916c 100644
--- a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL8712_TIMECTRL_REGDEF_H__
#define __RTL8712_TIMECTRL_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h b/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
index 6d3be2a..61a3603 100644
--- a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_WMAC_BITDEF_H__
#define __RTL8712_WMAC_BITDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h b/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
index ac80dfb..d9f8347 100644
--- a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
+++ b/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_WMAC_REGDEF_H__
#define __RTL8712_WMAC_REGDEF_H__
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c
index 88a1504..6933319 100644
--- a/drivers/staging/rtl8712/rtl8712_xmit.c
+++ b/drivers/staging/rtl8712/rtl8712_xmit.c
@@ -37,6 +37,7 @@
static void dump_xframe(struct _adapter *padapter,
struct xmit_frame *pxmitframe);
+static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz);
sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag)
{
@@ -238,16 +239,180 @@ exit_dequeue_xframe_ex:
void r8712_do_queue_select(struct _adapter *padapter,
struct pkt_attrib *pattrib)
{
- u8 qsel = 0;
+ unsigned int qsel = 0;
struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv;
if (pdvobj->nr_endpoint == 6)
- qsel = pattrib->priority;
- else if (pdvobj->nr_endpoint == 4)
- qsel = pattrib->priority;
+ qsel = (unsigned int) pattrib->priority;
+ else if (pdvobj->nr_endpoint == 4) {
+ qsel = (unsigned int) pattrib->priority;
+ if (qsel == 0 || qsel == 3)
+ qsel = 3;
+ else if (qsel == 1 || qsel == 2)
+ qsel = 1;
+ else if (qsel == 4 || qsel == 5)
+ qsel = 5;
+ else if (qsel == 6 || qsel == 7)
+ qsel = 7;
+ else
+ qsel = 3;
+ }
pattrib->qsel = qsel;
}
+#ifdef CONFIG_R8712_TX_AGGR
+u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf)
+{
+ struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
+
+ /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/
+ /* dw0 */
+ ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ&0xffff);
+ ptx_desc->txdw0 |=
+ cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);
+ ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
+
+ /* dw1 */
+ ptx_desc->txdw1 |= cpu_to_le32((0x13<<QSEL_SHT)&0x00001f00);
+
+ return _SUCCESS;
+}
+
+u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf)
+{
+ struct xmit_frame *pxmitframe = (struct xmit_frame *)
+ pxmitbuf->priv_data;
+ struct _adapter *padapter = pxmitframe->padapter;
+ struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
+ struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
+ (pxmitbuf->pbuf + TXDESC_SIZE);
+
+ /* Fill up Cmd Header for USB FW Tx Aggregation.*/
+ /* dw0 */
+ pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) |
+ (pcmdpriv->cmd_seq << 24));
+ pcmdpriv->cmd_seq++;
+
+ return _SUCCESS;
+}
+
+u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf,
+ struct xmit_frame *pxmitframe)
+{
+ struct _adapter *padapter = pxmitframe->padapter;
+ struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
+ int last_txcmdsz = 0;
+ int padding_sz = 0;
+
+ /* 802.3->802.11 convertor */
+ r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
+ /* free skb struct */
+ r8712_xmit_complete(padapter, pxmitframe);
+ if (pxmitframe->attrib.ether_type != 0x0806) {
+ if ((pxmitframe->attrib.ether_type != 0x888e) &&
+ (pxmitframe->attrib.dhcp_pkt != 1)) {
+ r8712_issue_addbareq_cmd(padapter,
+ pxmitframe->attrib.priority);
+ }
+ }
+ pxmitframe->last[0] = 1;
+ update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr),
+ pxmitframe->attrib.last_txcmdsz);
+ /*padding zero */
+ last_txcmdsz = pxmitframe->attrib.last_txcmdsz;
+ padding_sz = (8 - (last_txcmdsz % 8));
+ if ((last_txcmdsz % 8) != 0) {
+ int i;
+ for (i = 0; i < padding_sz; i++)
+ *(pxmitframe->buf_addr+TXDESC_SIZE+last_txcmdsz+i) = 0;
+ }
+ /* Add the new mpdu's length */
+ ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0&0xffff0000) |
+ ((ptx_desc->txdw0&0x0000ffff)+
+ ((TXDESC_SIZE+last_txcmdsz+padding_sz)&0x0000ffff)));
+
+ return _SUCCESS;
+}
+
+
+u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
+ struct xmit_frame *pxmitframe)
+{
+ /* linux complete context doesnt need to protect */
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitbuf->priv_data = pxmitframe;
+ pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
+ /* buffer addr assoc */
+ pxmitframe->buf_addr = pxmitbuf->pbuf+TXDESC_SIZE+CMD_HDR_SZ;
+ /*RTL8712_DMA_H2CCMD */
+ r8712_construct_txaggr_cmd_desc(pxmitbuf);
+ r8712_construct_txaggr_cmd_hdr(pxmitbuf);
+ if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS)
+ pxmitbuf->aggr_nr = 1;
+
+ return _SUCCESS;
+}
+
+u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf,
+ struct xmit_frame *pxmitframe)
+{
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitbuf->priv_data = pxmitframe;
+ pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
+ /* buffer addr assoc */
+ pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE +
+ (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
+ if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) {
+ r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv,
+ pxmitframe);
+ pxmitbuf->aggr_nr++;
+ }
+
+ return TXDESC_SIZE +
+ (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
+}
+
+u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
+ struct xmit_frame *pxmitframe)
+{
+ struct _adapter *padapter = pxmitframe->padapter;
+ struct dvobj_priv *pdvobj = (struct dvobj_priv *) &padapter->dvobjpriv;
+ struct tx_desc * ptxdesc = (struct tx_desc *)pxmitbuf->pbuf;
+ struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
+ (pxmitbuf->pbuf + TXDESC_SIZE);
+ u16 total_length = (u16) (ptxdesc->txdw0 & 0xffff);
+
+ /* use 1st xmitframe as media */
+ xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
+ pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length-CMD_HDR_SZ)&0x0000ffff)|
+ (pcmd_hdr->cmd_dw0&0xffff0000));
+
+ /* urb length in cmd_dw1 */
+ pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff)|
+ ((total_length+TXDESC_SIZE) << 16));
+ pxmitframe->last[0] = 1;
+ pxmitframe->bpending[0] = false;
+ pxmitframe->mem_addr = pxmitbuf->pbuf;
+
+ if ((pdvobj->ishighspeed && ((total_length+TXDESC_SIZE)%0x200) == 0) ||
+ ((!pdvobj->ishighspeed &&
+ ((total_length+TXDESC_SIZE)%0x40) == 0))) {
+ ptxdesc->txdw0 |= cpu_to_le32
+ (((TXDESC_SIZE+OFFSET_SZ+8)<<OFFSET_SHT)&0x00ff0000);
+ /*32 bytes for TX Desc + 8 bytes pending*/
+ } else {
+ ptxdesc->txdw0 |= cpu_to_le32
+ (((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);
+ /*default = 32 bytes for TX Desc*/
+ }
+ r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD,
+ total_length+TXDESC_SIZE, (u8 *)pxmitframe);
+
+ return _SUCCESS;
+}
+
+#endif
+
static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
{
uint qsel;
@@ -258,6 +423,9 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv;
+#ifdef CONFIG_R8712_TX_AGGR
+ struct cmd_priv *pcmdpriv = (struct cmd_priv *)&padapter->cmdpriv;
+#endif
u8 blnSetTxDescOffset;
sint bmcst = IS_MCAST(pattrib->ra);
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
@@ -291,8 +459,40 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
if (pxmitframe->frame_tag == DATA_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id)&0x1f);
+
+#ifdef CONFIG_R8712_TX_AGGR
+ /* dirty workaround, need to check if it is aggr cmd. */
+ if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) {
+ ptxdesc->txdw0 |= cpu_to_le32
+ ((0x3 << TYPE_SHT)&TYPE_MSK);
+ qsel = (uint)(pattrib->qsel & 0x0000001f);
+ if (qsel == 2)
+ qsel = 0;
+ ptxdesc->txdw1 |= cpu_to_le32
+ ((qsel << QSEL_SHT) & 0x00001f00);
+ ptxdesc->txdw2 = cpu_to_le32
+ ((qsel << RTS_RC_SHT)&0x001f0000);
+ ptxdesc->txdw6 |= cpu_to_le32
+ ((0x5 << RSVD6_SHT)&RSVD6_MSK);
+ } else {
+ ptxdesc->txdw0 |= cpu_to_le32
+ ((0x3 << TYPE_SHT)&TYPE_MSK);
+ ptxdesc->txdw1 |= cpu_to_le32
+ ((0x13 << QSEL_SHT) & 0x00001f00);
+ qsel = (uint)(pattrib->qsel & 0x0000001f);
+ if (qsel == 2)
+ qsel = 0;
+ ptxdesc->txdw2 = cpu_to_le32
+ ((qsel << RTS_RC_SHT)&0x0001f000);
+ ptxdesc->txdw7 |= cpu_to_le32
+ (pcmdpriv->cmd_seq << 24);
+ pcmdpriv->cmd_seq++;
+ }
+ pattrib->qsel = 0x13;
+#else
qsel = (uint)(pattrib->qsel & 0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
+#endif
if (!pqospriv->qos_option)
ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/
if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
@@ -414,7 +614,11 @@ int r8712_xmitframe_complete(struct _adapter *padapter,
struct hw_xmit *phwxmits;
sint hwentry;
struct xmit_frame *pxmitframe = NULL;
+#ifdef CONFIG_R8712_TX_AGGR
+ struct xmit_frame *p2ndxmitframe = NULL;
+#else
int res = _SUCCESS, xcnt = 0;
+#endif
phwxmits = pxmitpriv->hwxmits;
hwentry = pxmitpriv->hwxmit_entry;
@@ -422,32 +626,74 @@ int r8712_xmitframe_complete(struct _adapter *padapter,
pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
if (!pxmitbuf)
return false;
+#ifdef CONFIG_R8712_TX_AGGR
+ pxmitbuf->aggr_nr = 0;
+#endif
}
- do {
- pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- if (pxmitframe) {
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- pxmitframe->buf_addr = pxmitbuf->pbuf;
- if (pxmitframe->frame_tag == DATA_FRAMETAG) {
- if (pxmitframe->attrib.priority <= 15)
- res = r8712_xmitframe_coalesce(padapter,
- pxmitframe->pkt, pxmitframe);
- /* always return ndis_packet after
- * r8712_xmitframe_coalesce */
- r8712_xmit_complete(padapter, pxmitframe);
- }
- if (res == _SUCCESS)
- dump_xframe(padapter, pxmitframe);
- else
- r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
- xcnt++;
- } else {
+ /* 1st frame dequeued */
+ pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
+ /* need to remember the 1st frame */
+ if (pxmitframe != NULL) {
+
+#ifdef CONFIG_R8712_TX_AGGR
+ /* 1. dequeue 2nd frame
+ * 2. aggr if 2nd xframe is dequeued, else dump directly
+ */
+ if (AGGR_NR_HIGH_BOUND > 1)
+ p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits,
+ hwentry);
+ if (pxmitframe->frame_tag != DATA_FRAMETAG) {
r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
return false;
}
- break;
- } while (0);
+ if (p2ndxmitframe != NULL)
+ if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) {
+ r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
+ return false;
+ }
+ r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe);
+ if (p2ndxmitframe != NULL) {
+ u16 total_length;
+ total_length = r8712_xmitframe_aggr_next(
+ pxmitbuf, p2ndxmitframe);
+ do {
+ p2ndxmitframe = dequeue_xframe_ex(
+ pxmitpriv, phwxmits, hwentry);
+ if (p2ndxmitframe != NULL)
+ total_length =
+ r8712_xmitframe_aggr_next(
+ pxmitbuf,
+ p2ndxmitframe);
+ else
+ break;
+ } while (total_length <= 0x1800 &&
+ pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND);
+ }
+ if (pxmitbuf->aggr_nr > 0)
+ r8712_dump_aggr_xframe(pxmitbuf, pxmitframe);
+
+#else
+
+ xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
+ if (pxmitframe->frame_tag == DATA_FRAMETAG) {
+ if (pxmitframe->attrib.priority <= 15)
+ res = r8712_xmitframe_coalesce(padapter,
+ pxmitframe->pkt, pxmitframe);
+ /* always return ndis_packet after
+ * r8712_xmitframe_coalesce */
+ r8712_xmit_complete(padapter, pxmitframe);
+ }
+ if (res == _SUCCESS)
+ dump_xframe(padapter, pxmitframe);
+ else
+ r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
+ xcnt++;
+#endif
+
+ } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
+ r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
+ return false;
+ }
return true;
}
@@ -481,8 +727,13 @@ static void dump_xframe(struct _adapter *padapter,
pxmitframe->mem_addr = mem_addr;
pxmitframe->bpending[t] = false;
ff_hwaddr = get_ff_hwaddr(pxmitframe);
+#ifdef CONFIG_R8712_TX_AGGR
+ r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz,
+ (unsigned char *)pxmitframe);
+#else
r8712_write_port(padapter, ff_hwaddr, w_sz,
(unsigned char *)pxmitframe);
+#endif
mem_addr += w_sz;
mem_addr = (u8 *)RND4(((addr_t)(mem_addr)));
}
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h
index 12a080f..b50e7a1 100644
--- a/drivers/staging/rtl8712/rtl8712_xmit.h
+++ b/drivers/staging/rtl8712/rtl8712_xmit.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL8712_XMIT_H_
#define _RTL8712_XMIT_H_
@@ -39,6 +64,8 @@
#define OWN BIT(31)
#define FSG BIT(27)
#define LSG BIT(26)
+#define TYPE_SHT (24)
+#define TYPE_MSK (0x03000000)
/*OFFSET 4*/
#define PKT_OFFSET_SZ (0)
@@ -49,6 +76,7 @@
#define BMC BIT(7)
#define BK BIT(30)
#define AGG_EN BIT(29)
+#define RTS_RC_SHT (16)
/*OFFSET 12*/
#define SEQ_SHT (16)
@@ -58,6 +86,8 @@
/*OFFSET 20*/
#define DISFB BIT(15)
+#define RSVD6_MSK (0x00E00000)
+#define RSVD6_SHT (21)
struct tx_desc {
/*DWORD 0*/
@@ -83,4 +113,11 @@ int r8712_xmitframe_complete(struct _adapter *padapter,
void r8712_do_queue_select(struct _adapter *padapter,
struct pkt_attrib *pattrib);
+#ifdef CONFIG_R8712_TX_AGGR
+u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
+ struct xmit_frame *pxmitframe);
+u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
+ struct xmit_frame *pxmitframe);
+#endif
+
#endif
diff --git a/drivers/staging/rtl8712/rtl871x_byteorder.h b/drivers/staging/rtl8712/rtl871x_byteorder.h
index 07707e2..bd3703b 100644
--- a/drivers/staging/rtl8712/rtl871x_byteorder.h
+++ b/drivers/staging/rtl8712/rtl871x_byteorder.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef _RTL871X_BYTEORDER_H_
#define _RTL871X_BYTEORDER_H_
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index ba92762..d77388b 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -28,6 +28,24 @@
#define _RTL871X_CMD_C_
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/circ_buf.h>
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+#include <linux/rtnetlink.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
@@ -222,7 +240,7 @@ u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
GEN_CMD_CODE(_SiteSurvey));
psurveyPara->bsslimit = cpu_to_le32(48);
- psurveyPara->passive_mode = cpu_to_le32(1);
+ psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode);
psurveyPara->ss_ssidlen = 0;
memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
if ((pssid != NULL) && (pssid->SsidLength)) {
@@ -233,6 +251,7 @@ u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
r8712_enqueue_cmd(pcmdpriv, ph2c);
_set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
+ padapter->blnEnableRxFF0Filter = 0;
return _SUCCESS;
}
@@ -259,6 +278,28 @@ u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
return _SUCCESS;
}
+u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
+{
+ struct cmd_obj *ph2c;
+ struct SetChannelPlan_param *psetchplanpara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
+ if (ph2c == NULL)
+ return _FAIL;
+ psetchplanpara = (struct SetChannelPlan_param *)
+ _malloc(sizeof(struct SetChannelPlan_param));
+ if (psetchplanpara == NULL) {
+ kfree((u8 *) ph2c);
+ return _FAIL;
+ }
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara,
+ GEN_CMD_CODE(_SetChannelPlan));
+ psetchplanpara->ChannelPlan = chplan;
+ r8712_enqueue_cmd(pcmdpriv, ph2c);
+ return _SUCCESS;
+}
+
u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset)
{
struct cmd_obj *ph2c;
@@ -285,20 +326,62 @@ u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset)
u8 r8712_setptm_cmd(struct _adapter *padapter, u8 type)
{
struct cmd_obj *ph2c;
- struct PT_param *pptparm;
+ struct writePTM_parm *pwriteptmparm;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
if (ph2c == NULL)
return _FAIL;
- pptparm = (struct PT_param *)_malloc(sizeof(struct PT_param));
- if (pptparm == NULL) {
+ pwriteptmparm = (struct writePTM_parm *)
+ _malloc(sizeof(struct writePTM_parm));
+ if (pwriteptmparm == NULL) {
+ kfree((u8 *) ph2c);
+ return _FAIL;
+ }
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetPT));
+ pwriteptmparm->type = type;
+ r8712_enqueue_cmd(pcmdpriv, ph2c);
+ return _SUCCESS;
+}
+
+u8 r8712_setfwdig_cmd(struct _adapter *padapter, u8 type)
+{
+ struct cmd_obj *ph2c;
+ struct writePTM_parm *pwriteptmparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
+ if (ph2c == NULL)
+ return _FAIL;
+ pwriteptmparm = (struct writePTM_parm *)
+ _malloc(sizeof(struct setdig_parm));
+ if (pwriteptmparm == NULL) {
+ kfree((u8 *) ph2c);
+ return _FAIL;
+ }
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetDIG));
+ pwriteptmparm->type = type;
+ r8712_enqueue_cmd(pcmdpriv, ph2c);
+ return _SUCCESS;
+}
+
+u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type)
+{
+ struct cmd_obj *ph2c;
+ struct writePTM_parm *pwriteptmparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
+ if (ph2c == NULL)
+ return _FAIL;
+ pwriteptmparm = (struct writePTM_parm *)
+ _malloc(sizeof(struct setra_parm));
+ if (pwriteptmparm == NULL) {
kfree((u8 *) ph2c);
return _FAIL;
}
- init_h2fwcmd_w_parm_no_rsp(ph2c, pptparm,
- GEN_CMD_CODE(_SetPowerTracking));
- pptparm->PT_En = type;
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetRA));
+ pwriteptmparm->type = type;
r8712_enqueue_cmd(pcmdpriv, ph2c);
return _SUCCESS;
}
@@ -353,8 +436,17 @@ u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
struct cmd_obj *pcmd)
{
- kfree((unsigned char *) pcmd->parmbuf);
- kfree((unsigned char *) pcmd);
+ kfree(pcmd->parmbuf);
+ kfree(pcmd);
+ padapter->mppriv.workparam.bcompleted = true;
+}
+
+void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter,
+ struct cmd_obj *pcmd)
+{
+ kfree(pcmd->parmbuf);
+ kfree(pcmd);
+
padapter->mppriv.workparam.bcompleted = true;
}
@@ -485,12 +577,6 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
&psecnetwork->IEs[0],
pnetwork->network.IELength,
&psecnetwork->IELength);
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
- r8712_add_ht_addt_info(padapter,
- &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0],
- pnetwork->network.IELength,
- &psecnetwork->IELength);
}
}
psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
@@ -675,6 +761,33 @@ u8 r8712_setrttbl_cmd(struct _adapter *padapter,
return _SUCCESS;
}
+u8 r8712_gettssi_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
+{
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct cmd_obj *ph2c;
+ struct readTSSI_parm *prdtssiparm;
+
+ ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
+ if (ph2c == NULL)
+ return _FAIL;
+ prdtssiparm = (struct readTSSI_parm *)
+ _malloc(sizeof(struct readTSSI_parm));
+ if (prdtssiparm == NULL) {
+ kfree((unsigned char *) ph2c);
+ return _FAIL;
+ }
+ _init_listhead(&ph2c->list);
+ ph2c->cmdcode = GEN_CMD_CODE(_ReadTSSI);
+ ph2c->parmbuf = (unsigned char *)prdtssiparm;
+ ph2c->cmdsz = sizeof(struct readTSSI_parm);
+ ph2c->rsp = pval;
+ ph2c->rspsz = sizeof(struct readTSSI_rsp);
+
+ prdtssiparm->offset = offset;
+ r8712_enqueue_cmd(pcmdpriv, ph2c);
+ return _SUCCESS;
+}
+
u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
{
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
@@ -923,3 +1036,32 @@ void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
r8712_free_cmd_obj(pcmd);
}
+
+u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
+ u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO)
+{
+ struct cmd_obj *ph2c;
+ struct DisconnectCtrlEx_param *param;
+ struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+
+ ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
+ if (ph2c == NULL)
+ return _FAIL;
+ param = (struct DisconnectCtrlEx_param *)
+ _malloc(sizeof(struct DisconnectCtrlEx_param));
+ if (param == NULL) {
+ kfree((unsigned char *) ph2c);
+ return _FAIL;
+ }
+ memset(param, 0, sizeof(struct DisconnectCtrlEx_param));
+
+ param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
+ param->TryPktCnt = (unsigned char)tryPktCnt;
+ param->TryPktInterval = (unsigned char)tryPktInterval;
+ param->FirstStageTO = (unsigned int)firstStageTO;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, param,
+ GEN_CMD_CODE(_DisconnectCtrlEx));
+ r8712_enqueue_cmd(pcmdpriv, ph2c);
+ return _SUCCESS;
+}
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h
index dcf256d..757ebf7 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.h
+++ b/drivers/staging/rtl8712/rtl871x_cmd.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_CMD_H_
#define __RTL871X_CMD_H_
@@ -295,6 +320,35 @@ struct setdatarate_parm {
u8 datarates[NumRates];
};
+enum _RT_CHANNEL_DOMAIN {
+ RT_CHANNEL_DOMAIN_FCC = 0,
+ RT_CHANNEL_DOMAIN_IC = 1,
+ RT_CHANNEL_DOMAIN_ETSI = 2,
+ RT_CHANNEL_DOMAIN_SPAIN = 3,
+ RT_CHANNEL_DOMAIN_FRANCE = 4,
+ RT_CHANNEL_DOMAIN_MKK = 5,
+ RT_CHANNEL_DOMAIN_MKK1 = 6,
+ RT_CHANNEL_DOMAIN_ISRAEL = 7,
+ RT_CHANNEL_DOMAIN_TELEC = 8,
+
+ /* Be compatible with old channel plan. No good! */
+ RT_CHANNEL_DOMAIN_MIC = 9,
+ RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 10,
+ RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 11,
+ RT_CHANNEL_DOMAIN_TELEC_NETGEAR = 12,
+
+ RT_CHANNEL_DOMAIN_NCC = 13,
+ RT_CHANNEL_DOMAIN_5G = 14,
+ RT_CHANNEL_DOMAIN_5G_40M = 15,
+ /*===== Add new channel plan above this line===============*/
+ RT_CHANNEL_DOMAIN_MAX,
+};
+
+
+struct SetChannelPlan_param {
+ enum _RT_CHANNEL_DOMAIN ChannelPlan;
+};
+
/*
Caller Mode: Any
@@ -367,6 +421,10 @@ struct writeBB_parm {
u8 value;
};
+struct writePTM_parm {
+ u8 type;
+};
+
struct readRF_parm {
u8 offset;
};
@@ -646,9 +704,14 @@ struct SetChannel_parm {
u32 curr_ch;
};
-/*H2C Handler index: 56 */
-struct PT_param {
- u8 PT_En;
+/*H2C Handler index: 61 */
+struct DisconnectCtrlEx_param {
+ /* MAXTIME = (2 * FirstStageTO) + (TryPktCnt * TryPktInterval) */
+ unsigned char EnableDrvCtrl;
+ unsigned char TryPktCnt;
+ unsigned char TryPktInterval; /* Unit: ms */
+ unsigned char rsvd;
+ unsigned int FirstStageTO; /* Unit: ms */
};
#define GEN_CMD_CODE(cmd) cmd ## _CMD_
@@ -684,13 +747,17 @@ u8 r8712_disassoc_cmd(struct _adapter *padapter);
u8 r8712_setopmode_cmd(struct _adapter *padapter,
enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype);
u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset);
+u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan);
u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset);
u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 * pval);
u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode);
u8 r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val);
u8 r8712_setrttbl_cmd(struct _adapter *padapter,
struct setratable_parm *prate_table);
+u8 r8712_gettssi_cmd(struct _adapter *padapter, u8 offset, u8 *pval);
u8 r8712_setptm_cmd(struct _adapter *padapter, u8 type);
+u8 r8712_setfwdig_cmd(struct _adapter *padapter, u8 type);
+u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type);
u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid);
u8 r8712_wdg_wk_cmd(struct _adapter *padapter);
void r8712_survey_cmd_callback(struct _adapter *padapter,
@@ -703,10 +770,14 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
struct cmd_obj *pcmd);
void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
struct cmd_obj *pcmd);
+void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter,
+ struct cmd_obj *pcmd);
void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter,
struct cmd_obj *pcmd);
void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
struct cmd_obj *pcmd);
+u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
+ u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO);
struct _cmd_callback {
u32 cmd_code;
diff --git a/drivers/staging/rtl8712/rtl871x_debug.h b/drivers/staging/rtl8712/rtl871x_debug.h
index c392fd9..74468b0 100644
--- a/drivers/staging/rtl8712/rtl871x_debug.h
+++ b/drivers/staging/rtl8712/rtl871x_debug.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_DEBUG_H__
#define __RTL871X_DEBUG_H__
diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.h b/drivers/staging/rtl8712/rtl871x_eeprom.h
index fb15f5b..497276e 100644
--- a/drivers/staging/rtl8712/rtl871x_eeprom.h
+++ b/drivers/staging/rtl8712/rtl871x_eeprom.h
@@ -1,3 +1,22 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
#ifndef __RTL871X_EEPROM_H__
#define __RTL871X_EEPROM_H__
diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h
index 6ce0676..e03ee90 100644
--- a/drivers/staging/rtl8712/rtl871x_event.h
+++ b/drivers/staging/rtl8712/rtl871x_event.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL871x_EVENT_H_
#define _RTL871x_EVENT_H_
diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h
index 612203d..41872d9 100644
--- a/drivers/staging/rtl8712/rtl871x_ht.h
+++ b/drivers/staging/rtl8712/rtl871x_ht.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL871X_HT_H_
#define _RTL871X_HT_H_
diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h
index b70cb2b..86308a0 100644
--- a/drivers/staging/rtl8712/rtl871x_io.h
+++ b/drivers/staging/rtl8712/rtl871x_io.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _IO_H_
#define _IO_H_
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index 40e6b5c..ef35bc2 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -39,8 +39,17 @@
#include "rtl871x_ioctl_set.h"
#include "rtl871x_mp_ioctl.h"
#include "mlme_osdep.h"
-
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
+#include <linux/wireless.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <net/iw_handler.h>
+#include <linux/if_arp.h>
+
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
#define SCAN_ITEM_SIZE 768
#define MAX_CUSTOM_LEN 64
@@ -160,10 +169,6 @@ static inline char *translate_scan(struct _adapter *padapter,
struct iw_event iwe;
struct ieee80211_ht_cap *pht_capie;
char *current_val;
- u8 *buf = (u8 *)_malloc(pnetwork->network.IELength * 2);
- u8 *wpa_ie = (u8 *)_malloc(255);
- u8 *rsn_ie = (u8 *)_malloc(255);
- u8 *wps_ie = (u8 *)_malloc(MAX_WPS_IE_LEN);
s8 *p;
u32 i = 0, ht_ielen = 0;
u16 cap, ht_cap = false, mcs_rate;
@@ -280,6 +285,8 @@ static inline char *translate_scan(struct _adapter *padapter,
start = current_val;
/* parsing WPA/WPA2 IE */
{
+ u8 buf[MAX_WPA_IE_LEN];
+ u8 wpa_ie[255], rsn_ie[255];
u16 wpa_len = 0, rsn_len = 0;
int n;
sint out_len = 0;
@@ -330,6 +337,7 @@ static inline char *translate_scan(struct _adapter *padapter,
}
{ /* parsing WPS IE */
+ u8 wps_ie[512];
uint wps_ielen;
if (r8712_get_wps_ie(pnetwork->network.IEs,
@@ -354,16 +362,12 @@ static inline char *translate_scan(struct _adapter *padapter,
iwe.u.qual.noise = 0; /* noise level */
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
/* how to translate rssi to ?% */
- kfree(buf);
- kfree(wpa_ie);
- kfree(rsn_ie);
- kfree(wps_ie);
return start;
}
static int wpa_set_auth_algs(struct net_device *dev, u32 value)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
int ret = 0;
if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
@@ -395,7 +399,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
int ret = 0;
u32 wep_key_idx, wep_key_len = 0;
struct NDIS_802_11_WEP *pwep = NULL;
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
@@ -526,7 +530,7 @@ static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
memcpy(buf, pie , ielen);
pos = buf;
if (ielen < RSN_HEADER_LEN) {
- ret = -1;
+ ret = -EINVAL;
goto exit;
}
if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
@@ -637,7 +641,7 @@ static int r8711_wx_get_name(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
u32 ht_ielen = 0;
char *p;
u8 ht_cap = false;
@@ -693,7 +697,7 @@ static int r8711_wx_set_freq(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct iw_freq *fwrq = &wrqu->freq;
int rc = 0;
@@ -727,7 +731,7 @@ static int r8711_wx_get_freq(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
@@ -736,8 +740,9 @@ static int r8711_wx_get_freq(struct net_device *dev,
pcur_bss->Configuration.DSConfig-1] * 100000;
wrqu->freq.e = 1;
wrqu->freq.i = pcur_bss->Configuration.DSConfig;
- } else
- return -1;
+ } else {
+ return -ENOLINK;
+ }
return 0;
}
@@ -745,7 +750,7 @@ static int r8711_wx_set_mode(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
switch (wrqu->mode) {
@@ -768,15 +773,15 @@ static int r8711_wx_set_mode(struct net_device *dev,
r8712_setopmode_cmd(padapter, networkType);
else
r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
- if (!r8712_set_802_11_infrastructure_mode(padapter, networkType))
- return -1;
+
+ r8712_set_802_11_infrastructure_mode(padapter, networkType);
return 0;
}
static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
@@ -795,7 +800,7 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
u8 strZeroMacAddress[ETH_ALEN] = {0x00};
@@ -949,6 +954,10 @@ static int r8711_wx_get_range(struct net_device *dev,
return 0;
}
+static int r8711_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
static int r871x_wx_set_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *awrq,
@@ -956,6 +965,7 @@ static int r871x_wx_set_priv(struct net_device *dev,
{
int ret = 0, len = 0;
char *ext;
+ struct _adapter *padapter = netdev_priv(dev);
struct iw_point *dwrq = (struct iw_point *)awrq;
len = dwrq->length;
@@ -966,6 +976,87 @@ static int r871x_wx_set_priv(struct net_device *dev,
kfree(ext);
return -EFAULT;
}
+
+ if (0 == strcasecmp(ext, "RSSI")) {
+ /*Return received signal strength indicator in -db for */
+ /* current AP */
+ /*<ssid> Rssi xx */
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_network *pcur_network = &pmlmepriv->cur_network;
+ /*static u8 xxxx; */
+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ sprintf(ext, "%s rssi %d",
+ pcur_network->network.Ssid.Ssid,
+ /*(xxxx=xxxx+10) */
+ ((padapter->recvpriv.fw_rssi)>>1)-95
+ /*pcur_network->network.Rssi */
+ );
+ } else {
+ sprintf(ext, "OK");
+ }
+ } else if (0 == strcasecmp(ext, "LINKSPEED")) {
+ /*Return link speed in MBPS */
+ /*LinkSpeed xx */
+ union iwreq_data wrqd;
+ int ret_inner;
+ int mbps;
+
+ ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
+ if (0 != ret_inner)
+ mbps = 0;
+ else
+ mbps = wrqd.bitrate.value / 1000000;
+ sprintf(ext, "LINKSPEED %d", mbps);
+ } else if (0 == strcasecmp(ext, "MACADDR")) {
+ /*Return mac address of the station */
+ /*Macaddr = xx.xx.xx.xx.xx.xx */
+ sprintf(ext,
+ "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
+ *(dev->dev_addr), *(dev->dev_addr+1),
+ *(dev->dev_addr+2), *(dev->dev_addr+3),
+ *(dev->dev_addr+4), *(dev->dev_addr+5));
+ } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
+ /*Set scan type to active */
+ /*OK if successful */
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ pmlmepriv->passive_mode = 1;
+ sprintf(ext, "OK");
+ } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
+ /*Set scan type to passive */
+ /*OK if successful */
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ pmlmepriv->passive_mode = 0;
+ sprintf(ext, "OK");
+ } else if (0 == strncmp(ext, "DCE-E", 5)) {
+ /*Set scan type to passive */
+ /*OK if successful */
+ r8712_disconnectCtrlEx_cmd(padapter
+ , 1 /*u32 enableDrvCtrl */
+ , 5 /*u32 tryPktCnt */
+ , 100 /*u32 tryPktInterval */
+ , 5000 /*u32 firstStageTO */
+ );
+ sprintf(ext, "OK");
+ } else if (0 == strncmp(ext, "DCE-D", 5)) {
+ /*Set scan type to passive */
+ /*OK if successfu */
+ r8712_disconnectCtrlEx_cmd(padapter
+ , 0 /*u32 enableDrvCtrl */
+ , 5 /*u32 tryPktCnt */
+ , 100 /*u32 tryPktInterval */
+ , 5000 /*u32 firstStageTO */
+ );
+ sprintf(ext, "OK");
+ } else {
+ printk(KERN_INFO "r8712u: r871x_wx_set_priv: unknown Command"
+ " %s.\n", ext);
+ goto FREE_EXT;
+ }
+ if (copy_to_user(dwrq->pointer, ext,
+ min(dwrq->length, (__u16)(strlen(ext)+1))))
+ ret = -EFAULT;
+
+FREE_EXT:
kfree(ext);
return ret;
}
@@ -975,6 +1066,13 @@ static int r871x_wx_set_priv(struct net_device *dev,
* s2. set_802_11_authentication_mode()
* s3. set_802_11_encryption_mode()
* s4. set_802_11_bssid()
+ *
+ * This function intends to handle the Set AP command, which specifies the
+ * MAC# of a preferred Access Point.
+ * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
+ *
+ * For this operation to succeed, there is no need for the interface to be Up.
+ *
*/
static int r8711_wx_set_wap(struct net_device *dev,
struct iw_request_info *info,
@@ -982,7 +1080,7 @@ static int r8711_wx_set_wap(struct net_device *dev,
char *extra)
{
int ret = -EINPROGRESS;
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct __queue *queue = &pmlmepriv->scanned_queue;
struct sockaddr *temp = (struct sockaddr *)awrq;
@@ -992,10 +1090,8 @@ static int r8711_wx_set_wap(struct net_device *dev,
struct wlan_network *pnetwork = NULL;
enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- if (padapter->bup == false)
- return -1;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
- return -1;
+ return -EBUSY;
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
return ret;
if (temp->sa_family != ARPHRD_ETHER)
@@ -1012,16 +1108,15 @@ static int r8711_wx_set_wap(struct net_device *dev,
pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
dst_bssid = pnetwork->network.MacAddress;
if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
- if (r8712_set_802_11_infrastructure_mode(padapter,
- pnetwork->network.InfrastructureMode) == false)
- ret = -1;
+ r8712_set_802_11_infrastructure_mode(padapter,
+ pnetwork->network.InfrastructureMode);
break;
}
}
spin_unlock_irqrestore(&queue->lock, irqL);
if (!ret) {
if (!r8712_set_802_11_authentication_mode(padapter, authmode))
- ret = -1;
+ ret = -ENOMEM;
else {
if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
ret = -1;
@@ -1034,7 +1129,7 @@ static int r8711_wx_get_wap(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
@@ -1053,7 +1148,7 @@ static int r871x_wx_set_mlme(struct net_device *dev,
{
int ret = 0;
u16 reason;
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *) extra;
if (mlme == NULL)
@@ -1074,11 +1169,19 @@ static int r871x_wx_set_mlme(struct net_device *dev,
return ret;
}
+/**
+ *
+ * This function intends to handle the Set Scan command.
+ * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
+ *
+ * For this operation to succeed, the interface is brought Up beforehand.
+ *
+ */
static int r8711_wx_set_scan(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 status = true;
@@ -1088,7 +1191,7 @@ static int r8711_wx_set_scan(struct net_device *dev,
return -1;
}
if (padapter->bup == false)
- return -1;
+ return -ENETDOWN;
if (padapter->hw_init_completed == false)
return -1;
if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
@@ -1126,7 +1229,7 @@ static int r8711_wx_get_scan(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct __queue *queue = &pmlmepriv->scanned_queue;
struct wlan_network *pnetwork = NULL;
@@ -1141,7 +1244,7 @@ static int r8711_wx_get_scan(struct net_device *dev,
while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
msleep(30);
cnt++;
- if (cnt > 1000)
+ if (cnt > 100)
break;
}
spin_lock_irqsave(&queue->lock, irqL);
@@ -1169,12 +1272,18 @@ static int r8711_wx_get_scan(struct net_device *dev,
* s2. set_802_11_authenticaion_mode()
* s3. set_802_11_encryption_mode()
* s4. set_802_11_ssid()
+ *
+ * This function intends to handle the Set ESSID command.
+ * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
+ *
+ * For this operation to succeed, there is no need for the interface to be Up.
+ *
*/
static int r8711_wx_set_essid(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct __queue *queue = &pmlmepriv->scanned_queue;
struct wlan_network *pnetwork = NULL;
@@ -1184,10 +1293,8 @@ static int r8711_wx_set_essid(struct net_device *dev,
struct list_head *phead;
u32 len;
- if (padapter->bup == false)
- return -1;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- return -1;
+ return -EBUSY;
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
return 0;
if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
@@ -1212,10 +1319,20 @@ static int r8711_wx_set_essid(struct net_device *dev,
if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
&& (pnetwork->network.Ssid.SsidLength ==
ndis_ssid.SsidLength)) {
- if (!r8712_set_802_11_infrastructure_mode(
+ if (check_fwstate(pmlmepriv,
+ WIFI_ADHOC_STATE)) {
+ if (pnetwork->network.
+ InfrastructureMode
+ !=
+ padapter->mlmepriv.
+ cur_network.network.
+ InfrastructureMode)
+ continue;
+ }
+
+ r8712_set_802_11_infrastructure_mode(
padapter,
- pnetwork->network.InfrastructureMode))
- return -1;
+ pnetwork->network.InfrastructureMode);
break;
}
}
@@ -1229,7 +1346,7 @@ static int r8711_wx_get_essid(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
u32 len, ret = 0;
@@ -1239,8 +1356,9 @@ static int r8711_wx_get_essid(struct net_device *dev,
wrqu->essid.length = len;
memcpy(extra, pcur_bss->Ssid.Ssid, len);
wrqu->essid.flags = 1;
- } else
- ret = -1;
+ } else {
+ ret = -ENOLINK;
+ }
return ret;
}
@@ -1248,7 +1366,7 @@ static int r8711_wx_set_rate(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
u32 target_rate = wrqu->bitrate.value;
u32 fixed = wrqu->bitrate.fixed;
u32 ratevalue = 0;
@@ -1312,7 +1430,7 @@ set_rate:
datarates[i] = 0xff;
}
if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
- ret = -1;
+ ret = -ENOMEM;
return ret;
}
@@ -1320,10 +1438,11 @@ static int r8711_wx_get_rate(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
struct ieee80211_ht_cap *pht_capie;
+ unsigned char rf_type = padapter->registrypriv.rf_config;
int i;
u8 *p;
u16 rate, max_rate = 0, ht_cap = false;
@@ -1356,7 +1475,9 @@ static int r8711_wx_get_rate(struct net_device *dev,
i++;
}
if (ht_cap == true) {
- if (mcs_rate & 0x8000) /* MCS15 */
+ if (mcs_rate & 0x8000 /* MCS15 */
+ &&
+ RTL8712_RF_2T2R == rf_type)
max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
270) : ((short_GI) ? 144 : 130);
else if (mcs_rate & 0x0080) /* MCS7 */
@@ -1371,7 +1492,7 @@ static int r8711_wx_get_rate(struct net_device *dev,
wrqu->bitrate.value = max_rate * 500000;
}
} else
- return -1;
+ return -ENOLINK;
return 0;
}
@@ -1379,7 +1500,7 @@ static int r8711_wx_get_rts(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
wrqu->rts.value = padapter->registrypriv.rts_thresh;
wrqu->rts.fixed = 0; /* no auto select */
@@ -1390,7 +1511,7 @@ static int r8711_wx_set_frag(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
if (wrqu->frag.disabled)
padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
@@ -1407,7 +1528,7 @@ static int r8711_wx_get_frag(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
wrqu->frag.value = padapter->xmitpriv.frag_len;
wrqu->frag.fixed = 0; /* no auto select */
@@ -1433,7 +1554,7 @@ static int r8711_wx_set_enc(struct net_device *dev,
struct NDIS_802_11_WEP wep;
enum NDIS_802_11_AUTHENTICATION_MODE authmode;
struct iw_point *erq = &(wrqu->encoding);
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
key = erq->flags & IW_ENCODE_INDEX;
memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
@@ -1527,7 +1648,7 @@ static int r8711_wx_get_enc(struct net_device *dev,
union iwreq_data *wrqu, char *keybuf)
{
uint key, ret = 0;
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
struct iw_point *erq = &(wrqu->encoding);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
@@ -1599,7 +1720,7 @@ static int r871x_wx_set_gen_ie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
}
@@ -1608,7 +1729,7 @@ static int r871x_wx_set_auth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct iw_param *param = (struct iw_param *)&(wrqu->param);
int paramid;
int paramval;
@@ -1701,7 +1822,7 @@ static int r871x_wx_set_enc_ext(struct net_device *dev,
param_len = sizeof(struct ieee_param) + pext->key_len;
param = (struct ieee_param *)_malloc(param_len);
if (param == NULL)
- return -1;
+ return -ENOMEM;
memset(param, 0, param_len);
param->cmd = IEEE_CMD_SET_ENCRYPTION;
memset(param->sta_addr, 0xff, ETH_ALEN);
@@ -1719,7 +1840,7 @@ static int r871x_wx_set_enc_ext(struct net_device *dev,
alg_name = "CCMP";
break;
default:
- return -1;
+ return -EINVAL;
}
strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
@@ -1754,7 +1875,7 @@ static int r8711_wx_read32(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
u32 addr;
u32 data32;
@@ -1771,7 +1892,7 @@ static int r8711_wx_write32(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
u32 addr;
u32 data32;
@@ -1785,7 +1906,7 @@ static int dummy(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
- return -1;
+ return -ENOSYS;
}
static int r8711_drvext_hdl(struct net_device *dev,
@@ -1799,7 +1920,7 @@ static int r871x_mp_ioctl_hdl(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct iw_point *p = &wrqu->data;
struct oid_par_priv oid_par;
struct mp_ioctl_handler *phandler;
@@ -1882,7 +2003,7 @@ static int r871x_get_ap_info(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct __queue *queue = &pmlmepriv->scanned_queue;
struct iw_point *pdata = &wrqu->data;
@@ -1953,7 +2074,7 @@ static int r871x_set_pid(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
struct iw_point *pdata = &wrqu->data;
if ((padapter->bDriverStopped) || (pdata == NULL))
@@ -1963,11 +2084,32 @@ static int r871x_set_pid(struct net_device *dev,
return 0;
}
+static int r871x_set_chplan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+ struct iw_point *pdata = &wrqu->data;
+ int ch_plan = -1;
+
+ if ((padapter->bDriverStopped) || (pdata == NULL)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ ch_plan = (int)*extra;
+ r8712_set_chplan_cmd(padapter, ch_plan);
+
+exit:
+
+ return ret;
+}
+
static int r871x_wps_start(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
struct iw_point *pdata = &wrqu->data;
u32 u32wps_start = 0;
@@ -1991,7 +2133,7 @@ static int r871x_wps_start(struct net_device *dev,
static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
switch (name) {
case IEEE_PARAM_WPA_ENABLED:
@@ -2044,7 +2186,7 @@ static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
switch (command) {
case IEEE_MLME_STA_DEAUTH:
@@ -2065,16 +2207,17 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
{
struct ieee_param *param;
int ret = 0;
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
if (p->length < sizeof(struct ieee_param) || !p->pointer)
return -EINVAL;
param = (struct ieee_param *)_malloc(p->length);
if (param == NULL)
return -ENOMEM;
- if (copy_from_user(param, p->pointer, p->length))
+ if (copy_from_user(param, p->pointer, p->length)) {
kfree((u8 *)param);
return -EFAULT;
+ }
switch (param->cmd) {
case IEEE_CMD_SET_WPA_PARAM:
ret = wpa_set_param(dev, param->u.wpa_param.name,
@@ -2201,6 +2344,10 @@ static const struct iw_priv_args r8711_private_args[] = {
{
SIOCIWFIRSTPRIV + 0x6,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x7,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
}
};
@@ -2211,12 +2358,13 @@ static iw_handler r8711_private_handler[] = {
r871x_mp_ioctl_hdl,
r871x_get_ap_info, /*for MM DTV platform*/
r871x_set_pid,
- r871x_wps_start,
+ r871x_wps_start,
+ r871x_set_chplan
};
static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
{
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
+ struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
struct iw_statistics *piwstats = &padapter->iwstats;
int tmp_level = 0;
int tmp_qual = 0;
@@ -2247,5 +2395,5 @@ struct iw_handler_def r871x_handlers_def = {
.num_private = sizeof(r8711_private_handler) / sizeof(iw_handler),
.num_private_args = sizeof(r8711_private_args) /
sizeof(struct iw_priv_args),
- .get_wireless_stats = r871x_get_wireless_stats,
+ .get_wireless_stats = r871x_get_wireless_stats
};
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
index 4f1aa87..3bcceae 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL871X_IOCTL_RTL_H
#define _RTL871X_IOCTL_RTL_H
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
index 8486eb1..fb29b42 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
@@ -243,7 +243,7 @@ done:
spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
}
-u8 r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
+void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
{
unsigned long irqL;
@@ -290,7 +290,6 @@ u8 r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
}
spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
}
- return true;
}
u8 r8712_set_802_11_disassociate(struct _adapter *padapter)
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h
index 8dff2b1..2c94cd1 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __IOCTL_SET_H
#define __IOCTL_SET_H
@@ -22,7 +47,7 @@ u8 r8712_set_802_11_disassociate(struct _adapter *padapter);
u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter);
-u8 r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
+void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype);
void r8712_set_802_11_ssid(struct _adapter *padapter,
diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h
index 8085e5e..1a90c7f 100644
--- a/drivers/staging/rtl8712/rtl871x_led.h
+++ b/drivers/staging/rtl8712/rtl871x_led.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL8712_LED_H
#define __RTL8712_LED_H
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index 866554d..ef8eb6c 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -52,6 +52,8 @@ static sint _init_mlme_priv(struct _adapter *padapter)
pmlmepriv->fw_state = 0;
pmlmepriv->cur_network.network.InfrastructureMode =
Ndis802_11AutoUnknown;
+ /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
+ pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
spin_lock_init(&(pmlmepriv->lock));
spin_lock_init(&(pmlmepriv->lock2));
_init_queue(&(pmlmepriv->free_bss_pool));
@@ -485,6 +487,12 @@ static int is_desired_network(struct _adapter *adapter,
if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
(pnetwork->network.Privacy == 0))
bselected = false;
+ if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE) == true) {
+ if (pnetwork->network.InfrastructureMode !=
+ adapter->mlmepriv.cur_network.network.
+ InfrastructureMode)
+ bselected = false;
+ }
return bselected;
}
@@ -683,9 +691,11 @@ void r8712_ind_disconnect(struct _adapter *padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- _clr_fwstate_(pmlmepriv, _FW_LINKED);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
- r8712_os_indicate_disconnect(padapter);
+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+ padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
+ r8712_os_indicate_disconnect(padapter);
+ }
if (padapter->pwrctrlpriv.pwr_mode !=
padapter->registrypriv.power_mgnt) {
_cancel_timer_ex(&pmlmepriv->dhcp_timer);
@@ -718,9 +728,9 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
if (sizeof(struct list_head) == 4 * sizeof(u32)) {
pnetwork = (struct wlan_network *)
- _malloc(sizeof(struct wlan_network));
+ _malloc(sizeof(struct wlan_network));
memcpy((u8 *)pnetwork+16, (u8 *)pbuf + 8,
- sizeof(struct wlan_network) - 16);
+ sizeof(struct wlan_network) - 16);
} else
pnetwork = (struct wlan_network *)pbuf;
@@ -1271,12 +1281,16 @@ sint r8712_set_key(struct _adapter *adapter,
psecuritypriv->DefKey[keyid].skey, keylen);
break;
case _TKIP_:
+ if (keyid < 1 || keyid > 2)
+ return _FAIL;
keylen = 16;
memcpy(psetkeyparm->key,
&psecuritypriv->XGrpKey[keyid - 1], keylen);
psetkeyparm->grpkey = 1;
break;
case _AES_:
+ if (keyid < 1 || keyid > 2)
+ return _FAIL;
keylen = 16;
memcpy(psetkeyparm->key,
&psecuritypriv->XGrpKey[keyid - 1], keylen);
@@ -1657,7 +1671,7 @@ void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
/* 1. Supported rates
* 2. IE
*/
- sz = r8712_generate_ie(pregistrypriv, adapter);
+ sz = r8712_generate_ie(pregistrypriv);
pdev_network->IELength = sz;
pdev_network->Length = r8712_get_ndis_wlan_bssid_ex_sz(
(struct ndis_wlan_bssid_ex *)pdev_network);
@@ -1802,39 +1816,3 @@ void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
}
}
}
-
-/*the function is >= passive_level*/
-unsigned int r8712_add_ht_addt_info(struct _adapter *padapter,
- u8 *in_ie, u8 *out_ie,
- uint in_len, uint *pout_len)
-{
- u32 ielen, out_len = 0;
- unsigned char *p, *pframe;
- struct ieee80211_ht_addt_info ht_addt_info;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- out_len = *pout_len;
-
- if (pregistrypriv->ht_enable == 1) {
- p = r8712_get_ie(in_ie+12, _HT_ADD_INFO_IE_,
- &ielen, in_len - 12);
- if (p && (ielen > 0)) {
- ; /* dummy branch */
- } else {
- if (p == NULL) {
- int sz = sizeof(struct ieee80211_ht_addt_info);
- memset(&ht_addt_info, 0, sz);
- /*need to add the HT additional IEs*/
- ht_addt_info.control_chan =
- pregistrypriv->channel;
- pframe = r8712_set_ie(out_ie + out_len,
- _HT_ADD_INFO_IE_,
- sz,
- (unsigned char *)&ht_addt_info,
- pout_len);
- }
- }
- }
- return phtpriv->ht_option;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h
index 2794804..71ca013 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.h
+++ b/drivers/staging/rtl8712/rtl871x_mlme.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_MLME_H_
#define __RTL871X_MLME_H_
@@ -70,6 +95,7 @@ struct mlme_priv {
struct __queue scanned_queue;
u8 *free_bss_buf;
unsigned long num_of_scanned;
+ u8 passive_mode; /*add for Android's SCAN-ACTIVE/SCAN-PASSIVE */
struct ndis_802_11_ssid assoc_ssid;
u8 assoc_bssid[6];
struct wlan_network cur_network;
@@ -201,8 +227,6 @@ void r8712_joinbss_reset(struct _adapter *padapter);
unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
u8 *out_ie, uint in_len, uint *pout_len);
void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority);
-unsigned int r8712_add_ht_addt_info(struct _adapter *padapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint *pout_len);
int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork);
#endif /*__RTL871X_MLME_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c
index 41e00a2..5638d5e 100644
--- a/drivers/staging/rtl8712/rtl871x_mp.c
+++ b/drivers/staging/rtl8712/rtl871x_mp.c
@@ -1,18 +1,28 @@
/******************************************************************************
- * rtl871x_mp.c
*
- * Description :
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
*
- * Author :
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
*
- * History :
+ * 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.
*
- * Copyright 2007, Realtek Corp.
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
*
- * The contents of this file is the sole property of Realtek Corp. It can not be
- * be used, copied or modified without written permission from Realtek Corp.
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
*
-*******************************************************************************/
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#define _RTL871X_MP_C_
#include "osdep_service.h"
diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h
index 805aba0..255dc94 100644
--- a/drivers/staging/rtl8712/rtl871x_mp.h
+++ b/drivers/staging/rtl8712/rtl871x_mp.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_MP_H_
#define __RTL871X_MP_H_
@@ -101,7 +126,6 @@ struct mp_xmit_frame {
struct urb *pxmit_urb[8];
u8 bpending[8];
u8 last[8];
- uint mem[(MAX_MP_XMITBUF_SZ >> 2)];
};
struct mp_wiparam {
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
index 67759c3..850143d 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
+++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL871X_MP_IOCTL_H
#define _RTL871X_MP_IOCTL_H
@@ -307,7 +332,6 @@ struct rfintfs_parm {
struct mp_xmit_packet {
unsigned int len;
- unsigned int mem[MAX_MP_XMITBUF_SZ >> 2];
};
struct psmode_param {
@@ -410,8 +434,7 @@ static struct mp_ioctl_handler mp_ioctl_hdl[] = {
{sizeof(struct psmode_param), NULL, 0},/*13*/
{sizeof(struct eeprom_rw_param), NULL, 0},/*14*/
{sizeof(struct eeprom_rw_param), NULL, 0},/*15*/
- {sizeof(u8), oid_rt_pro_set_power_tracking_hdl,
- OID_RT_PRO_SET_POWER_TRACKING},/*16*/
+ {sizeof(unsigned char), NULL, 0},/*16*/
{sizeof(u32), NULL, 0},/*17*/
{sizeof(u32), oid_rt_pro_set_continuous_tx_hdl,
OID_RT_PRO_SET_CONTINUOUS_TX},/*18*/
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h
index 34f074a..b41ca28 100644
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h
+++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_PWRCTRL_H_
#define __RTL871X_PWRCTRL_H_
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index aec83dd..4cc68d1 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -28,6 +28,9 @@
#define _RTL871X_RECV_C_
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
@@ -73,6 +76,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv,
RXFRAME_ALIGN_SZ);
if (precvpriv->pallocated_frame_buf == NULL)
return _FAIL;
+ kmemleak_not_leak(precvpriv->pallocated_frame_buf);
memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME *
sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
@@ -250,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
struct sta_info *psta;
struct sta_priv *pstapriv;
union recv_frame *prtnframe;
- u16 ether_type = 0;
+ u16 ether_type;
pstapriv = &adapter->stapriv;
ptr = get_recvframe_data(precv_frame);
@@ -259,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
psta = r8712_get_stainfo(pstapriv, psta_addr);
auth_alg = adapter->securitypriv.AuthAlgrthm;
if (auth_alg == 2) {
+ /* get ether_type */
+ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
+ memcpy(&ether_type, ptr, 2);
+ ether_type = ntohs((unsigned short)ether_type);
+
if ((psta != NULL) && (psta->ieee8021x_blocked)) {
/* blocked
* only accept EAPOL frame */
- prtnframe = precv_frame;
- /*get ether_type */
- ptr = ptr + pfhdr->attrib.hdrlen +
- pfhdr->attrib.iv_len + LLC_HEADER_SIZE;
- memcpy(&ether_type, ptr, 2);
- ether_type = ntohs((unsigned short)ether_type);
if (ether_type == 0x888e)
prtnframe = precv_frame;
else {
diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h
index 6c54966..133ed64 100644
--- a/drivers/staging/rtl8712/rtl871x_rf.h
+++ b/drivers/staging/rtl8712/rtl871x_rf.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_RF_H_
#define __RTL871X_RF_H_
diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c
index 65321be..7b92927 100644
--- a/drivers/staging/rtl8712/rtl871x_security.c
+++ b/drivers/staging/rtl8712/rtl871x_security.c
@@ -28,6 +28,21 @@
#define _RTL871X_SECURITY_C_
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/circ_buf.h>
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "wifi.h"
diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h
index bff71d2..a13395f 100644
--- a/drivers/staging/rtl8712/rtl871x_security.h
+++ b/drivers/staging/rtl8712/rtl871x_security.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __RTL871X_SECURITY_H_
#define __RTL871X_SECURITY_H_
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
index 64f5696..1247b3d 100644
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
@@ -42,9 +42,8 @@ static void _init_stainfo(struct sta_info *psta)
_init_listhead(&psta->hash_list);
_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
-#ifdef CONFIG_R8712_AP
+ _init_listhead(&psta->asoc_list);
_init_listhead(&psta->auth_list);
-#endif
}
u32 _r8712_init_sta_priv(struct sta_priv *pstapriv)
@@ -71,10 +70,8 @@ u32 _r8712_init_sta_priv(struct sta_priv *pstapriv)
get_list_head(&pstapriv->free_sta_queue));
psta++;
}
-#ifdef CONFIG_R8712_AP
_init_listhead(&pstapriv->asoc_list);
_init_listhead(&pstapriv->auth_list);
-#endif
return _SUCCESS;
}
diff --git a/drivers/staging/rtl8712/rtl871x_wlan_sme.h b/drivers/staging/rtl8712/rtl871x_wlan_sme.h
index d9733ac..44924d5 100644
--- a/drivers/staging/rtl8712/rtl871x_wlan_sme.h
+++ b/drivers/staging/rtl8712/rtl871x_wlan_sme.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL871X_WLAN_SME_H_
#define _RTL871X_WLAN_SME_H_
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
index ccf0891..8bbdee7 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ b/drivers/staging/rtl8712/rtl871x_xmit.c
@@ -152,11 +152,12 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
pxmitbuf++;
}
pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
+ _init_workitem(&padapter->wkFilterRxFF0, r8712_SetFilter, padapter);
alloc_hwxmits(padapter);
init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
tasklet_init(&pxmitpriv->xmit_tasklet,
- (void(*)(addr_t))r8712_xmit_bh,
- (addr_t)padapter);
+ (void(*)(unsigned long))r8712_xmit_bh,
+ (unsigned long)padapter);
return _SUCCESS;
}
@@ -612,7 +613,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL)
return _FAIL;
_r8712_open_pktfile(pkt, &pktfile);
- _r8712_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen);
+ _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
/* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
if (pattrib->ether_type == 0x8712) {
@@ -826,13 +827,16 @@ void r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
unsigned long irqL;
struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
struct _adapter *padapter = pxmitpriv->adapter;
+ struct sk_buff *pndis_pkt = NULL;
if (pxmitframe == NULL)
return;
- if (pxmitframe->pkt)
- r8712_xmit_complete(padapter, pxmitframe);
spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
list_delete(&pxmitframe->list);
+ if (pxmitframe->pkt) {
+ pndis_pkt = pxmitframe->pkt;
+ pxmitframe->pkt = NULL;
+ }
list_insert_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue));
pxmitpriv->free_xmitframe_cnt++;
spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
@@ -1011,6 +1015,19 @@ static void init_hwxmits(struct hw_xmit *phwxmit, sint entry)
}
}
+void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
+ struct xmit_buf *pxmitbuf)
+{
+ /* pxmitbuf attach to pxmitframe */
+ pxmitframe->pxmitbuf = pxmitbuf;
+ /* urb and irp connection */
+ pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
+ /* buffer addr assoc */
+ pxmitframe->buf_addr = pxmitbuf->pbuf;
+ /* pxmitframe attach to pxmitbuf */
+ pxmitbuf->priv_data = pxmitframe;
+}
+
/*
* tx_action == 0 == no frames to transmit
* tx_action > 0 ==> we have frames to transmit
@@ -1042,9 +1059,7 @@ int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe)
} else { /*dump packet directly*/
spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
ret = true;
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- pxmitframe->buf_addr = pxmitbuf->pbuf;
+ xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
r8712_xmit_direct(padapter, pxmitframe);
}
return ret;
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h
index df13e67..a034c0f 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.h
+++ b/drivers/staging/rtl8712/rtl871x_xmit.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _RTL871X_XMIT_H_
#define _RTL871X_XMIT_H_
@@ -5,8 +30,19 @@
#include "drv_types.h"
#include "xmit_osdep.h"
-#define MAX_XMITBUF_SZ (2048)
-#define NR_XMITBUFF (4)
+#ifdef CONFIG_R8712_TX_AGGR
+#define MAX_XMITBUF_SZ (16384)
+#else
+#define MAX_XMITBUF_SZ (2048)
+#endif
+
+#define NR_XMITBUFF (4)
+
+#ifdef CONFIG_R8712_TX_AGGR
+#define AGGR_NR_HIGH_BOUND (4) /*(8) */
+#define AGGR_NR_LOW_BOUND (2)
+#endif
+
#define XMITBUF_ALIGN_SZ 512
#define TX_GUARD_BAND 5
#define MAX_NUMBLKS (1)
@@ -68,9 +104,9 @@ struct pkt_attrib {
u16 seqnum;
u16 ether_type;
- u32 pktlen; /* the original 802.3 pkt raw_data len
+ u16 pktlen; /* the original 802.3 pkt raw_data len
* (not include ether_hdr data) */
- u32 last_txcmdsz;
+ u16 last_txcmdsz;
u8 pkt_hdrlen; /*the original 802.3 pkt header len*/
u8 hdrlen; /*the WLAN Header Len*/
@@ -110,7 +146,9 @@ struct xmit_buf {
u8 *pallocated_buf;
u8 *pbuf;
+ void *priv_data;
struct urb *pxmit_urb[8];
+ u32 aggr_nr;
};
struct xmit_frame {
@@ -198,6 +236,9 @@ struct xmit_priv {
struct semaphore tx_retevt;/*all tx return event;*/
u8 txirp_cnt;
struct tasklet_struct xmit_tasklet;
+ _workitem xmit_pipe4_reset_wi;
+ _workitem xmit_pipe6_reset_wi;
+ _workitem xmit_piped_reset_wi;
/*per AC pending irp*/
int beq_cnt;
int bkq_cnt;
@@ -255,6 +296,9 @@ int r8712_xmit_enqueue(struct _adapter *padapter,
int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe);
void r8712_xmit_bh(void *priv);
+void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
+ struct xmit_buf *pxmitbuf);
+
#include "rtl8712_xmit.h"
#endif /*_RTL871X_XMIT_H_*/
diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h
index 79ad159..f8016e9 100644
--- a/drivers/staging/rtl8712/sta_info.h
+++ b/drivers/staging/rtl8712/sta_info.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __STA_INFO_H_
#define __STA_INFO_H_
@@ -38,8 +63,8 @@ struct sta_info {
struct sta_recv_priv sta_recvpriv;
uint state;
uint aid;
- u8 mac_id;
- u8 qos_option;
+ uint mac_id;
+ uint qos_option;
u8 hwaddr[ETH_ALEN];
uint ieee8021x_blocked; /*0: allowed, 1:blocked */
uint XPrivacy; /*aes, tkip...*/
@@ -65,7 +90,6 @@ struct sta_info {
* curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO
* sta_info: (AP & STA) CAP/INFO
*/
-#ifdef CONFIG_R8712_AP
struct list_head asoc_list;
struct list_head auth_list;
unsigned int expire_to;
@@ -73,7 +97,6 @@ struct sta_info {
unsigned int authalg;
unsigned char chg_txt[128];
unsigned int tx_ra_bitmap;
-#endif
};
struct sta_priv {
@@ -86,13 +109,11 @@ struct sta_priv {
struct __queue sleep_q;
struct __queue wakeup_q;
struct _adapter *padapter;
-#ifdef CONFIG_R8712_AP
struct list_head asoc_list;
struct list_head auth_list;
unsigned int auth_to; /* sec, time to expire in authenticating. */
unsigned int assoc_to; /* sec, time to expire before associating. */
unsigned int expire_to; /* sec , time to expire after associated. */
-#endif
};
static inline u32 wifi_mac_hash(u8 *mac)
diff --git a/drivers/staging/rtl8712/swab.h b/drivers/staging/rtl8712/swab.h
index 44709a9..f127818 100644
--- a/drivers/staging/rtl8712/swab.h
+++ b/drivers/staging/rtl8712/swab.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _LINUX_BYTEORDER_SWAB_H
#define _LINUX_BYTEORDER_SWAB_H
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index af28a62..a74e83d 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -28,6 +28,10 @@
#define _HCI_INTF_C_
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
@@ -100,6 +104,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
/* - */
{USB_DEVICE(0x20F4, 0x646B)},
{USB_DEVICE(0x083A, 0xC512)},
+ {USB_DEVICE(0x25D4, 0x4CA1)},
+ {USB_DEVICE(0x25D4, 0x4CAB)},
/* RTL8191SU */
/* Realtek */
@@ -357,6 +363,10 @@ static u8 key_2char2num(u8 hch, u8 lch)
return (hex_to_bin(hch) << 4) | hex_to_bin(lch);
}
+static const struct device_type wlan_type = {
+ .name = "wlan",
+};
+
/*
* drv_init() - a device potentially for us
*
@@ -370,25 +380,29 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
struct _adapter *padapter = NULL;
struct dvobj_priv *pdvobjpriv;
struct net_device *pnetdev;
+ struct usb_device *udev;
printk(KERN_INFO "r8712u: DriverVersion: %s\n", DRVER);
/* In this probe function, O.S. will provide the usb interface pointer
* to driver. We have to increase the reference count of the usb device
* structure by using the usb_get_dev function.
*/
- usb_get_dev(interface_to_usbdev(pusb_intf));
+ udev = interface_to_usbdev(pusb_intf);
+ usb_get_dev(udev);
pintf = pusb_intf;
/* step 1. */
pnetdev = r8712_init_netdev();
if (!pnetdev)
goto error;
- padapter = (struct _adapter *)_netdev_priv(pnetdev);
+ padapter = netdev_priv(pnetdev);
disable_ht_for_spec_devid(pdid, padapter);
pdvobjpriv = &padapter->dvobjpriv;
pdvobjpriv->padapter = padapter;
- padapter->dvobjpriv.pusbdev = interface_to_usbdev(pusb_intf);
+ padapter->dvobjpriv.pusbdev = udev;
+ padapter->pusb_intf = pusb_intf;
usb_set_intfdata(pusb_intf, pnetdev);
SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
+ pnetdev->dev.type = &wlan_type;
/* step 2. */
padapter->dvobj_init = &r8712_usb_dvobj_init;
padapter->dvobj_deinit = &r8712_usb_dvobj_deinit;
@@ -593,17 +607,19 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
"%pM\n", mac);
memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
}
- /* step 6. Tell the network stack we exist */
- if (register_netdev(pnetdev) != 0)
+ /* step 6. Load the firmware asynchronously */
+ if (rtl871x_load_fw(padapter))
goto error;
+ spin_lock_init(&padapter->lockRxFF0Filter);
+ mutex_init(&padapter->mutex_start);
return 0;
error:
- usb_put_dev(interface_to_usbdev(pusb_intf));
+ usb_put_dev(udev);
usb_set_intfdata(pusb_intf, NULL);
if (padapter->dvobj_deinit != NULL)
padapter->dvobj_deinit(padapter);
if (pnetdev)
- os_free_netdev(pnetdev);
+ free_netdev(pnetdev);
return -ENODEV;
}
@@ -615,6 +631,11 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
struct _adapter *padapter = netdev_priv(pnetdev);
struct usb_device *udev = interface_to_usbdev(pusb_intf);
+ if (padapter->fw_found)
+ release_firmware(padapter->fw);
+ /* never exit with a firmware callback pending */
+ wait_for_completion(&padapter->rtl8712_fw_ready);
+ usb_set_intfdata(pusb_intf, NULL);
if (padapter) {
if (drvpriv.drv_registered == true)
padapter->bSurpriseRemoved = true;
@@ -624,6 +645,9 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
}
flush_scheduled_work();
udelay(1);
+ /*Stop driver mlme relation timer */
+ if (padapter->fw_found)
+ r8712_stop_drv_timers(padapter);
r871x_dev_unload(padapter);
r8712_free_drv_sw(padapter);
}
diff --git a/drivers/staging/rtl8712/usb_ops.h b/drivers/staging/rtl8712/usb_ops.h
index dc0611a..78e775a 100644
--- a/drivers/staging/rtl8712/usb_ops.h
+++ b/drivers/staging/rtl8712/usb_ops.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __USB_OPS_H_
#define __USB_OPS_H_
diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
index 7933ea4..24e1ec5 100644
--- a/drivers/staging/rtl8712/usb_ops_linux.c
+++ b/drivers/staging/rtl8712/usb_ops_linux.c
@@ -28,6 +28,8 @@
#define _HCI_OPS_OS_C_
+#include <linux/usb.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "osdep_intf.h"
@@ -48,7 +50,7 @@ struct zero_bulkout_context {
uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv)
{
- pintfpriv->piorw_urb = _usb_alloc_urb(0, GFP_ATOMIC);
+ pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!pintfpriv->piorw_urb)
return _FAIL;
sema_init(&(pintfpriv->io_retevt), 0);
@@ -187,7 +189,7 @@ void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
usb_fill_bulk_urb(piorw_urb, pusbd, pipe,
wmem, cnt, usb_write_mem_complete,
pio_queue);
- status = _usb_submit_urb(piorw_urb, GFP_ATOMIC);
+ status = usb_submit_urb(piorw_urb, GFP_ATOMIC);
_down_sema(&pintfpriv->io_retevt);
}
@@ -305,7 +307,7 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
precvbuf->pbuf, MAX_RECVBUF_SZ,
r8712_usb_read_port_complete,
precvbuf);
- err = _usb_submit_urb(purb, GFP_ATOMIC);
+ err = usb_submit_urb(purb, GFP_ATOMIC);
if ((err) && (err != (-EPERM)))
ret = _FAIL;
} else
@@ -332,17 +334,16 @@ void r8712_xmit_bh(void *priv)
struct _adapter *padapter = (struct _adapter *)priv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- while (1) {
- if ((padapter->bDriverStopped == true) ||
- (padapter->bSurpriseRemoved == true)) {
- printk(KERN_ERR "r8712u: xmit_bh => bDriverStopped"
- " or bSurpriseRemoved\n");
- break;
- }
- ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL);
- if (ret == false)
- break;
+ if ((padapter->bDriverStopped == true) ||
+ (padapter->bSurpriseRemoved == true)) {
+ printk(KERN_ERR "r8712u: xmit_bh => bDriverStopped"
+ " or bSurpriseRemoved\n");
+ return;
}
+ ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL);
+ if (ret == false)
+ return;
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
}
static void usb_write_port_complete(struct urb *purb)
@@ -462,7 +463,7 @@ u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
pxmitframe->mem_addr,
cnt, usb_write_port_complete,
pxmitframe); /* context is xmit_frame */
- status = _usb_submit_urb(purb, GFP_ATOMIC);
+ status = usb_submit_urb(purb, GFP_ATOMIC);
if (!status)
ret = _SUCCESS;
else
diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h
index 0da6c1d..d95797aa 100644
--- a/drivers/staging/rtl8712/usb_osintf.h
+++ b/drivers/staging/rtl8712/usb_osintf.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __USB_OSINTF_H
#define __USB_OSINTF_H
@@ -17,6 +42,7 @@ uint rtl8712_hal_deinit(struct _adapter *padapter);
void rtl871x_intf_stop(struct _adapter *padapter);
void r871x_dev_unload(struct _adapter *padapter);
void r8712_stop_drv_threads(struct _adapter *padapter);
+void r8712_stop_drv_timers(struct _adapter *padapter);
u8 r8712_init_drv_sw(struct _adapter *padapter);
u8 r8712_free_drv_sw(struct _adapter *padapter);
struct net_device *r8712_init_netdev(void);
diff --git a/drivers/staging/rtl8712/usb_vendor_req.h b/drivers/staging/rtl8712/usb_vendor_req.h
index d35c538..82335a8 100644
--- a/drivers/staging/rtl8712/usb_vendor_req.h
+++ b/drivers/staging/rtl8712/usb_vendor_req.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _USB_VENDOR_REQUEST_H_
#define _USB_VENDOR_REQUEST_H_
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
index 6032cdc..277398c 100644
--- a/drivers/staging/rtl8712/wifi.h
+++ b/drivers/staging/rtl8712/wifi.h
@@ -1,7 +1,33 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef _WIFI_H_
#define _WIFI_H_
#include "rtl871x_byteorder.h"
+#include <linux/compiler.h>
#ifdef BIT
#undef BIT
@@ -523,7 +549,7 @@ struct ieee80211_bar {
unsigned char ta[6];
unsigned short control;
unsigned short start_seq_num;
-} __attribute__((packed));
+} __packed;
/* 802.11 BAR control masks */
#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
@@ -544,7 +570,7 @@ struct ieee80211_ht_cap {
unsigned short extended_ht_cap_info;
unsigned int tx_BF_cap_info;
unsigned char antenna_selection_info;
-} __attribute__ ((packed));
+} __packed;
/**
* struct ieee80211_ht_cap - HT additional information
@@ -558,7 +584,7 @@ struct ieee80211_ht_addt_info {
unsigned short operation_mode;
unsigned short stbc_param;
unsigned char basic_set[16];
-} __attribute__ ((packed));
+} __packed;
/* 802.11n HT capabilities masks */
#define IEEE80211_HT_CAP_SUP_WIDTH 0x0002
diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h
index 0d90e1f..2ea8a3d 100644
--- a/drivers/staging/rtl8712/wlan_bssdef.h
+++ b/drivers/staging/rtl8712/wlan_bssdef.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __WLAN_BSSDEF_H__
#define __WLAN_BSSDEF_H__
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
index 7dea8b5..c970362 100644
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ b/drivers/staging/rtl8712/xmit_linux.c
@@ -28,6 +28,8 @@
#define _XMIT_OSDEP_C_
+#include <linux/usb.h>
+
#include "osdep_service.h"
#include "drv_types.h"
@@ -42,7 +44,6 @@
static uint remainder_len(struct pkt_file *pfile)
{
- /* Kovich: Need to extend the buf_len to 64 bit ?(unsigned long long) */
return (uint)(pfile->buf_len - ((addr_t)(pfile->cur_addr) -
(addr_t)(pfile->buf_start)));
}
@@ -107,13 +108,33 @@ void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
pattrib->subtype = WIFI_QOS_DATA_TYPE;
}
+void r8712_SetFilter(struct work_struct *work)
+{
+ struct _adapter *padapter = container_of(work, struct _adapter,
+ wkFilterRxFF0);
+ u8 oldvalue = 0x00, newvalue = 0x00;
+ unsigned long irqL;
+
+ oldvalue = r8712_read8(padapter, 0x117);
+ newvalue = oldvalue & 0xfe;
+ r8712_write8(padapter, 0x117, newvalue);
+
+ spin_lock_irqsave(&padapter->lockRxFF0Filter, irqL);
+ padapter->blnEnableRxFF0Filter = 1;
+ spin_unlock_irqrestore(&padapter->lockRxFF0Filter, irqL);
+ do {
+ msleep(100);
+ } while (padapter->blnEnableRxFF0Filter == 1);
+ r8712_write8(padapter, 0x117, oldvalue);
+}
+
int r8712_xmit_resource_alloc(struct _adapter *padapter,
struct xmit_buf *pxmitbuf)
{
int i;
for (i = 0; i < 8; i++) {
- pxmitbuf->pxmit_urb[i] = _usb_alloc_urb(0, GFP_KERNEL);
+ pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (pxmitbuf->pxmit_urb[i] == NULL) {
printk(KERN_ERR "r8712u: pxmitbuf->pxmit_urb[i]"
" == NULL");
@@ -146,7 +167,7 @@ void r8712_xmit_complete(struct _adapter *padapter, struct xmit_frame *pxframe)
int r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev)
{
struct xmit_frame *pxmitframe = NULL;
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(pnetdev);
+ struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
int ret = 0;
diff --git a/drivers/staging/rtl8712/xmit_osdep.h b/drivers/staging/rtl8712/xmit_osdep.h
index ca43937..8eba7ca 100644
--- a/drivers/staging/rtl8712/xmit_osdep.h
+++ b/drivers/staging/rtl8712/xmit_osdep.h
@@ -1,3 +1,28 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Modifications for inclusion into the Linux staging tree are
+ * Copyright(c) 2010 Larry Finger. All rights reserved.
+ *
+ * Contact information:
+ * WLAN FAE <wlanfae@realtek.com>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ******************************************************************************/
#ifndef __XMIT_OSDEP_H_
#define __XMIT_OSDEP_H_
@@ -22,6 +47,7 @@ struct xmit_frame;
struct xmit_buf;
int r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev);
+void r8712_SetFilter(struct work_struct *work);
int r8712_xmit_resource_alloc(struct _adapter *padapter,
struct xmit_buf *pxmitbuf);
void r8712_xmit_resource_free(struct _adapter *padapter,
diff --git a/drivers/staging/rts_pstor/Makefile b/drivers/staging/rts_pstor/Makefile
index 61609ae..42533d3 100644
--- a/drivers/staging/rts_pstor/Makefile
+++ b/drivers/staging/rts_pstor/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -Idrivers/scsi
+ccflags := -Idrivers/scsi
obj-$(CONFIG_RTS_PSTOR) := rts_pstor.o
diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c
index 2e82587..66341df 100644
--- a/drivers/staging/rts_pstor/ms.c
+++ b/drivers/staging/rts_pstor/ms.c
@@ -2064,11 +2064,10 @@ static int ms_init_l2p_tbl(struct rtsx_chip *chip)
RTSX_DEBUGP("ms_card->segment_cnt = %d\n", ms_card->segment_cnt);
size = ms_card->segment_cnt * sizeof(struct zone_entry);
- ms_card->segment = (struct zone_entry *)vmalloc(size);
+ ms_card->segment = vzalloc(size);
if (ms_card->segment == NULL) {
TRACE_RET(chip, STATUS_FAIL);
}
- memset(ms_card->segment, 0, size);
retval = ms_read_page(chip, ms_card->boot_block, 1);
if (retval != STATUS_SUCCESS) {
diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c
index 5ff59f2..115635f 100644
--- a/drivers/staging/rts_pstor/rtsx.c
+++ b/drivers/staging/rts_pstor/rtsx.c
@@ -36,7 +36,7 @@
#include "sd.h"
#include "xd.h"
-#define DRIVER_VERSION "v1.10"
+#define DRIVER_VERSION "v1.10"
MODULE_DESCRIPTION("Realtek PCI-Express card reader driver");
MODULE_LICENSE("GPL");
@@ -66,12 +66,6 @@ static int msi_en;
module_param(msi_en, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(msi_en, "enable msi");
-/* These are used to make sure the module doesn't unload before all the
- * threads have exited.
- */
-static atomic_t total_threads = ATOMIC_INIT(0);
-static DECLARE_COMPLETION(threads_gone);
-
static irqreturn_t rtsx_interrupt(int irq, void *dev_id);
/***********************************************************************
@@ -83,7 +77,7 @@ static const char *host_info(struct Scsi_Host *host)
return "SCSI emulation for PCI-Express Mass Storage devices";
}
-static int slave_alloc (struct scsi_device *sdev)
+static int slave_alloc(struct scsi_device *sdev)
{
/*
* Set the INQUIRY transfer length to 36. We don't use any of
@@ -136,7 +130,7 @@ static int slave_configure(struct scsi_device *sdev)
#define SPRINTF(args...) \
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-static int proc_info (struct Scsi_Host *host, char *buffer,
+static int proc_info(struct Scsi_Host *host, char *buffer,
char **start, off_t offset, int length, int inout)
{
char *pos = buffer;
@@ -192,7 +186,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
/* enqueue the command and wake up the control thread */
srb->scsi_done = done;
chip->srb = srb;
- up(&(dev->sema));
+ complete(&dev->cmnd_ready);
return 0;
}
@@ -475,7 +469,7 @@ static int rtsx_control_thread(void *__dev)
current->flags |= PF_NOFREEZE;
for (;;) {
- if (down_interruptible(&dev->sema))
+ if (wait_for_completion_interruptible(&dev->cmnd_ready))
break;
/* lock the device pointers */
@@ -512,13 +506,15 @@ static int rtsx_control_thread(void *__dev)
*/
else if (chip->srb->device->id) {
printk(KERN_ERR "Bad target number (%d:%d)\n",
- chip->srb->device->id, chip->srb->device->lun);
+ chip->srb->device->id,
+ chip->srb->device->lun);
chip->srb->result = DID_BAD_TARGET << 16;
}
else if (chip->srb->device->lun > chip->max_lun) {
printk(KERN_ERR "Bad LUN (%d:%d)\n",
- chip->srb->device->id, chip->srb->device->lun);
+ chip->srb->device->id,
+ chip->srb->device->lun);
chip->srb->result = DID_BAD_TARGET << 16;
}
@@ -557,8 +553,6 @@ SkipForAbort:
mutex_unlock(&dev->dev_mutex);
} /* for (;;) */
- scsi_host_put(host);
-
/* notify the exit routine that we're actually exiting now
*
* complete()/wait_for_completion() is similar to up()/down(),
@@ -573,7 +567,7 @@ SkipForAbort:
* This is important in preemption kernels, which transfer the flow
* of execution immediately upon a complete().
*/
- complete_and_exit(&threads_gone, 0);
+ complete_and_exit(&dev->control_exit, 0);
}
@@ -581,7 +575,6 @@ static int rtsx_polling_thread(void *__dev)
{
struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
struct rtsx_chip *chip = dev->chip;
- struct Scsi_Host *host = rtsx_to_host(dev);
struct sd_info *sd_card = &(chip->sd_card);
struct xd_info *xd_card = &(chip->xd_card);
struct ms_info *ms_card = &(chip->ms_card);
@@ -621,8 +614,7 @@ static int rtsx_polling_thread(void *__dev)
mutex_unlock(&dev->dev_mutex);
}
- scsi_host_put(host);
- complete_and_exit(&threads_gone, 0);
+ complete_and_exit(&dev->polling_exit, 0);
}
/*
@@ -635,26 +627,23 @@ static irqreturn_t rtsx_interrupt(int irq, void *dev_id)
int retval;
u32 status;
- if (dev) {
+ if (dev)
chip = dev->chip;
- } else {
+ else
return IRQ_NONE;
- }
- if (!chip) {
+ if (!chip)
return IRQ_NONE;
- }
spin_lock(&dev->reg_lock);
retval = rtsx_pre_handle_interrupt(chip);
if (retval == STATUS_FAIL) {
spin_unlock(&dev->reg_lock);
- if (chip->int_reg == 0xFFFFFFFF) {
+ if (chip->int_reg == 0xFFFFFFFF)
return IRQ_HANDLED;
- } else {
+ else
return IRQ_NONE;
- }
}
status = chip->int_reg;
@@ -671,9 +660,8 @@ static irqreturn_t rtsx_interrupt(int irq, void *dev_id)
if (status & (NEED_COMPLETE_INT | DELINK_INT)) {
if (status & (TRANS_FAIL_INT | DELINK_INT)) {
- if (status & DELINK_INT) {
+ if (status & DELINK_INT)
RTSX_SET_DELINK(chip);
- }
dev->trans_result = TRANS_RESULT_FAIL;
if (dev->done)
complete(dev->done);
@@ -699,29 +687,38 @@ static void rtsx_release_resources(struct rtsx_dev *dev)
{
printk(KERN_INFO "-- %s\n", __func__);
+ /* Tell the control thread to exit. The SCSI host must
+ * already have been removed so it won't try to queue
+ * any more commands.
+ */
+ printk(KERN_INFO "-- sending exit command to thread\n");
+ complete(&dev->cmnd_ready);
+ if (dev->ctl_thread)
+ wait_for_completion(&dev->control_exit);
+ if (dev->polling_thread)
+ wait_for_completion(&dev->polling_exit);
+
+ wait_timeout(200);
+
if (dev->rtsx_resv_buf) {
- dma_free_coherent(&(dev->pci->dev), HOST_CMDS_BUF_LEN,
+ dma_free_coherent(&(dev->pci->dev), RTSX_RESV_BUF_LEN,
dev->rtsx_resv_buf, dev->rtsx_resv_buf_addr);
dev->chip->host_cmds_ptr = NULL;
dev->chip->host_sg_tbl_ptr = NULL;
}
- pci_disable_device(dev->pci);
- pci_release_regions(dev->pci);
-
- if (dev->irq > 0) {
+ if (dev->irq > 0)
free_irq(dev->irq, (void *)dev);
- }
- if (dev->chip->msi_en) {
+ if (dev->chip->msi_en)
pci_disable_msi(dev->pci);
- }
+ if (dev->remap_addr)
+ iounmap(dev->remap_addr);
- /* Tell the control thread to exit. The SCSI host must
- * already have been removed so it won't try to queue
- * any more commands.
- */
- printk(KERN_INFO "-- sending exit command to thread\n");
- up(&dev->sema);
+ pci_disable_device(dev->pci);
+ pci_release_regions(dev->pci);
+
+ rtsx_release_chip(dev->chip);
+ kfree(dev->chip);
}
/* First stage of disconnect processing: stop all commands and remove
@@ -739,6 +736,7 @@ static void quiesce_and_remove_host(struct rtsx_dev *dev)
scsi_unlock(host);
mutex_unlock(&dev->dev_mutex);
wake_up(&dev->delay_wait);
+ wait_for_completion(&dev->scanning_done);
/* Wait some time to let other threads exist */
wait_timeout(100);
@@ -793,8 +791,7 @@ static int rtsx_scan_thread(void *__dev)
/* Should we unbind if no devices were detected? */
}
- scsi_host_put(rtsx_to_host(dev));
- complete_and_exit(&threads_gone, 0);
+ complete_and_exit(&dev->scanning_done, 0);
}
static void rtsx_init_options(struct rtsx_chip *chip)
@@ -845,7 +842,9 @@ static void rtsx_init_options(struct rtsx_chip *chip)
chip->ssc_en = 1;
chip->sd_speed_prior = 0x01040203;
chip->sd_current_prior = 0x00010203;
- chip->sd_ctl = SD_PUSH_POINT_AUTO | SD_SAMPLE_POINT_AUTO | SUPPORT_MMC_DDR_MODE;
+ chip->sd_ctl = SD_PUSH_POINT_AUTO |
+ SD_SAMPLE_POINT_AUTO |
+ SUPPORT_MMC_DDR_MODE;
chip->sd_ddr_tx_phase = 0;
chip->mmc_ddr_tx_phase = 1;
chip->sd_default_tx_phase = 15;
@@ -897,7 +896,8 @@ static void rtsx_init_options(struct rtsx_chip *chip)
chip->s3_pwr_off_delay = 1000;
}
-static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+static int __devinit rtsx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct Scsi_Host *host;
struct rtsx_dev *dev;
@@ -914,7 +914,8 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
err = pci_request_regions(pci, CR_DRIVER_NAME);
if (err < 0) {
- printk(KERN_ERR "PCI request regions for %s failed!\n", CR_DRIVER_NAME);
+ printk(KERN_ERR "PCI request regions for %s failed!\n",
+ CR_DRIVER_NAME);
pci_disable_device(pci);
return err;
}
@@ -935,20 +936,23 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
memset(dev, 0, sizeof(struct rtsx_dev));
dev->chip = kzalloc(sizeof(struct rtsx_chip), GFP_KERNEL);
- if (dev->chip == NULL) {
+ if (dev->chip == NULL)
goto errout;
- }
spin_lock_init(&dev->reg_lock);
mutex_init(&(dev->dev_mutex));
- sema_init(&(dev->sema), 0);
+ init_completion(&dev->cmnd_ready);
+ init_completion(&dev->control_exit);
+ init_completion(&dev->polling_exit);
init_completion(&(dev->notify));
+ init_completion(&dev->scanning_done);
init_waitqueue_head(&dev->delay_wait);
dev->pci = pci;
dev->irq = -1;
- printk(KERN_INFO "Resource length: 0x%x\n", (unsigned int)pci_resource_len(pci, 0));
+ printk(KERN_INFO "Resource length: 0x%x\n",
+ (unsigned int)pci_resource_len(pci, 0));
dev->addr = pci_resource_start(pci, 0);
dev->remap_addr = ioremap_nocache(dev->addr, pci_resource_len(pci, 0));
if (dev->remap_addr == NULL) {
@@ -957,9 +961,12 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
goto errout;
}
- /* Using "unsigned long" cast here to eliminate gcc warning in 64-bit system */
+ /*
+ * Using "unsigned long" cast here to eliminate gcc warning in
+ * 64-bit system
+ */
printk(KERN_INFO "Original address: 0x%lx, remapped address: 0x%lx\n",
- (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
+ (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
dev->rtsx_resv_buf = dma_alloc_coherent(&(pci->dev), RTSX_RESV_BUF_LEN,
&(dev->rtsx_resv_buf_addr), GFP_KERNEL);
@@ -971,7 +978,8 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
dev->chip->host_cmds_ptr = dev->rtsx_resv_buf;
dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr;
dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
- dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
+ dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr +
+ HOST_CMDS_BUF_LEN;
dev->chip->rtsx = dev;
@@ -992,60 +1000,44 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id
pci_set_master(pci);
synchronize_irq(dev->irq);
- err = scsi_add_host(host, &pci->dev);
- if (err) {
- printk(KERN_ERR "Unable to add the scsi host\n");
- goto errout;
- }
-
rtsx_init_chip(dev->chip);
/* Start up our control thread */
- th = kthread_create(rtsx_control_thread, dev, CR_DRIVER_NAME);
+ th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
if (IS_ERR(th)) {
printk(KERN_ERR "Unable to start control thread\n");
err = PTR_ERR(th);
goto errout;
}
+ dev->ctl_thread = th;
- /* Take a reference to the host for the control thread and
- * count it among all the threads we have launched. Then
- * start it up. */
- scsi_host_get(rtsx_to_host(dev));
- atomic_inc(&total_threads);
- wake_up_process(th);
+ err = scsi_add_host(host, &pci->dev);
+ if (err) {
+ printk(KERN_ERR "Unable to add the scsi host\n");
+ goto errout;
+ }
/* Start up the thread for delayed SCSI-device scanning */
th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan");
if (IS_ERR(th)) {
printk(KERN_ERR "Unable to start the device-scanning thread\n");
+ complete(&dev->scanning_done);
quiesce_and_remove_host(dev);
err = PTR_ERR(th);
goto errout;
}
- /* Take a reference to the host for the scanning thread and
- * count it among all the threads we have launched. Then
- * start it up. */
- scsi_host_get(rtsx_to_host(dev));
- atomic_inc(&total_threads);
wake_up_process(th);
/* Start up the thread for polling thread */
- th = kthread_create(rtsx_polling_thread, dev, "rtsx-polling");
+ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling");
if (IS_ERR(th)) {
printk(KERN_ERR "Unable to start the device-polling thread\n");
quiesce_and_remove_host(dev);
err = PTR_ERR(th);
goto errout;
}
-
- /* Take a reference to the host for the polling thread and
- * count it among all the threads we have launched. Then
- * start it up. */
- scsi_host_get(rtsx_to_host(dev));
- atomic_inc(&total_threads);
- wake_up_process(th);
+ dev->polling_thread = th;
pci_set_drvdata(pci, dev);
@@ -1073,10 +1065,10 @@ static void __devexit rtsx_remove(struct pci_dev *pci)
}
/* PCI IDs */
-static struct pci_device_id rtsx_ids[] = {
- { 0x10EC, 0x5208, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { 0x10EC, 0x5209, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { 0x10EC, 0x5288, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_OTHERS << 16, 0xFF0000 },
+static DEFINE_PCI_DEVICE_TABLE(rtsx_ids) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5208), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5288), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ 0, },
};
@@ -1108,16 +1100,6 @@ static void __exit rtsx_exit(void)
pci_unregister_driver(&driver);
- /* Don't return until all of our control and scanning threads
- * have exited. Since each thread signals threads_gone as its
- * last act, we have to call wait_for_completion the right number
- * of times.
- */
- while (atomic_read(&total_threads) > 0) {
- wait_for_completion(&threads_gone);
- atomic_dec(&total_threads);
- }
-
printk(KERN_INFO "%s module exit\n", CR_DRIVER_NAME);
}
diff --git a/drivers/staging/rts_pstor/rtsx.h b/drivers/staging/rts_pstor/rtsx.h
index 6afb635..1ab42fc 100644
--- a/drivers/staging/rts_pstor/rtsx.h
+++ b/drivers/staging/rts_pstor/rtsx.h
@@ -24,12 +24,11 @@
#ifndef __REALTEK_RTSX_H
#define __REALTEK_RTSX_H
-#include <asm/io.h>
-#include <asm/bitops.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -81,7 +80,7 @@
#define wait_timeout_x(task_state, msecs) \
do { \
- set_current_state((task_state)); \
+ set_current_state((task_state)); \
schedule_timeout((msecs) * HZ / 1000); \
} while (0)
#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
@@ -103,19 +102,26 @@ typedef unsigned long DELAY_PARA_T;
struct rtsx_chip;
struct rtsx_dev {
- struct pci_dev *pci;
+ struct pci_dev *pci;
/* pci resources */
unsigned long addr;
void __iomem *remap_addr;
- int irq;
+ int irq;
/* locks */
spinlock_t reg_lock;
+ struct task_struct *ctl_thread; /* the control thread */
+ struct task_struct *polling_thread; /* the polling thread */
+
/* mutual exclusion and synchronization structures */
- struct semaphore sema; /* to sleep thread on */
+ struct completion cmnd_ready; /* to sleep thread on */
+ struct completion control_exit; /* control thread exit */
+ struct completion polling_exit; /* polling thread exit */
struct completion notify; /* thread begin/end */
+ struct completion scanning_done; /* wait for scan thread */
+
wait_queue_head_t delay_wait; /* wait during scan, reset */
struct mutex dev_mutex;
diff --git a/drivers/staging/rts_pstor/rtsx_chip.c b/drivers/staging/rts_pstor/rtsx_chip.c
index 4e60780..5452069 100644
--- a/drivers/staging/rts_pstor/rtsx_chip.c
+++ b/drivers/staging/rts_pstor/rtsx_chip.c
@@ -1596,18 +1596,16 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int l
}
RTSX_DEBUGP("dw_len = %d\n", dw_len);
- data = (u32 *)vmalloc(dw_len * 4);
+ data = vzalloc(dw_len * 4);
if (!data) {
TRACE_RET(chip, STATUS_NOMEM);
}
- memset(data, 0, dw_len * 4);
- mask = (u32 *)vmalloc(dw_len * 4);
+ mask = vzalloc(dw_len * 4);
if (!mask) {
vfree(data);
TRACE_RET(chip, STATUS_NOMEM);
}
- memset(mask, 0, dw_len * 4);
j = 0;
for (i = 0; i < len; i++) {
diff --git a/drivers/staging/rts_pstor/rtsx_scsi.c b/drivers/staging/rts_pstor/rtsx_scsi.c
index 7de1fae..f2e5842 100644
--- a/drivers/staging/rts_pstor/rtsx_scsi.c
+++ b/drivers/staging/rts_pstor/rtsx_scsi.c
@@ -2730,7 +2730,7 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
buf_len = data_len = 0x6A;
}
- buf = (u8 *)kmalloc(buf_len, GFP_KERNEL);
+ buf = kmalloc(buf_len, GFP_KERNEL);
if (!buf) {
TRACE_RET(chip, TRANSPORT_ERROR);
}
diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c
index 4e3d2c1..9b2e5c9 100644
--- a/drivers/staging/rts_pstor/rtsx_transport.c
+++ b/drivers/staging/rts_pstor/rtsx_transport.c
@@ -335,6 +335,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
int sg_cnt, i, resid;
int err = 0;
long timeleft;
+ struct scatterlist *sg_ptr;
u32 val = TRIG_DMA;
if ((sg == NULL) || (num_sg <= 0) || !offset || !index)
@@ -371,7 +372,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
resid = size;
-
+ sg_ptr = sg;
chip->sgi = 0;
/* Usually the next entry will be @sg@ + 1, but if this sg element
* is part of a chained scatterlist, it could jump to the start of
@@ -379,14 +380,14 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
* the proper sg
*/
for (i = 0; i < *index; i++)
- sg = sg_next(sg);
+ sg_ptr = sg_next(sg_ptr);
for (i = *index; i < sg_cnt; i++) {
dma_addr_t addr;
unsigned int len;
u8 option;
- addr = sg_dma_address(sg);
- len = sg_dma_len(sg);
+ addr = sg_dma_address(sg_ptr);
+ len = sg_dma_len(sg_ptr);
RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
(unsigned int)addr, len);
@@ -415,7 +416,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
if (!resid)
break;
- sg = sg_next(sg);
+ sg_ptr = sg_next(sg_ptr);
}
RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c
index cdae497..aab6909 100644
--- a/drivers/staging/rts_pstor/sd.c
+++ b/drivers/staging/rts_pstor/sd.c
@@ -2661,7 +2661,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0);
if (retval != STATUS_SUCCESS) {
- TRACE_RET(chip, STATUS_FAIL);
+ TRACE_RET(chip, SWITCH_FAIL);
}
if (width == MMC_8BIT_BUS) {
@@ -2678,7 +2678,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
}
if (!CHECK_PID(chip, 0x5209)) {
- RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x02, 0x02);
+ retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
+ if (retval != STATUS_SUCCESS)
+ TRACE_RET(chip, SWITCH_ERR);
}
retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
@@ -2690,17 +2692,19 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
rtsx_read_register(chip, REG_SD_STAT2, &val2);
rtsx_clear_sd_error(chip);
if ((val1 & 0xE0) || val2) {
- TRACE_RET(chip, STATUS_FAIL);
+ TRACE_RET(chip, SWITCH_ERR);
}
} else {
rtsx_clear_sd_error(chip);
rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
- TRACE_RET(chip, STATUS_FAIL);
+ TRACE_RET(chip, SWITCH_ERR);
}
}
if (!CHECK_PID(chip, 0x5209)) {
- RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x02, 0);
+ retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
+ if (retval != STATUS_SUCCESS)
+ TRACE_RET(chip, SWITCH_ERR);
}
RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R);
@@ -2733,7 +2737,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
retval = rtsx_send_cmd(chip, SD_CARD, 100);
if (retval < 0) {
rtsx_clear_sd_error(chip);
- TRACE_RET(chip, STATUS_FAIL);
+ TRACE_RET(chip, SWITCH_ERR);
}
ptr = rtsx_get_cmd_data(chip) + 1;
@@ -2751,7 +2755,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
}
retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
- return STATUS_SUCCESS;
+ return SWITCH_SUCCESS;
}
}
} else {
@@ -2767,12 +2771,12 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
}
retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
- return STATUS_SUCCESS;
+ return SWITCH_SUCCESS;
}
}
}
- TRACE_RET(chip, STATUS_FAIL);
+ TRACE_RET(chip, SWITCH_FAIL);
}
@@ -2880,21 +2884,30 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
TRACE_RET(chip, STATUS_FAIL);
}
- if (mmc_test_switch_bus(chip, MMC_8BIT_BUS) == STATUS_SUCCESS) {
+ /* Test Bus Procedure */
+ retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
+ if (retval == SWITCH_SUCCESS) {
SET_MMC_8BIT(sd_card);
chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
#ifdef SUPPORT_SD_LOCK
sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
#endif
- } else if (mmc_test_switch_bus(chip, MMC_4BIT_BUS) == STATUS_SUCCESS) {
- SET_MMC_4BIT(sd_card);
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
+ } else if (retval == SWITCH_FAIL) {
+ retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
+ if (retval == SWITCH_SUCCESS) {
+ SET_MMC_4BIT(sd_card);
+ chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
+ sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
#endif
+ } else if (retval == SWITCH_FAIL) {
+ CLR_MMC_8BIT(sd_card);
+ CLR_MMC_4BIT(sd_card);
+ } else {
+ TRACE_RET(chip, STATUS_FAIL);
+ }
} else {
- CLR_MMC_8BIT(sd_card);
- CLR_MMC_4BIT(sd_card);
+ TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
@@ -2915,8 +2928,7 @@ static int reset_mmc(struct rtsx_chip *chip)
goto MMC_UNLOCK_ENTRY;
#endif
-DDR_TUNING_FAIL:
-
+Switch_Fail:
retval = sd_prepare_reset(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, retval);
@@ -3017,7 +3029,15 @@ MMC_UNLOCK_ENTRY:
if (!sd_card->mmc_dont_switch_bus) {
if (spec_ver == 4) {
- (void)mmc_switch_timing_bus(chip, switch_ddr);
+ /* MMC 4.x Cards */
+ retval = mmc_switch_timing_bus(chip, switch_ddr);
+ if (retval != STATUS_SUCCESS) {
+ retval = sd_init_power(chip);
+ if (retval != STATUS_SUCCESS)
+ TRACE_RET(chip, STATUS_FAIL);
+ sd_card->mmc_dont_switch_bus = 1;
+ TRACE_GOTO(chip, Switch_Fail);
+ }
}
if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) {
@@ -3037,7 +3057,7 @@ MMC_UNLOCK_ENTRY:
TRACE_RET(chip, STATUS_FAIL);
}
switch_ddr = 0;
- goto DDR_TUNING_FAIL;
+ TRACE_GOTO(chip, Switch_Fail);
}
retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
@@ -3049,7 +3069,7 @@ MMC_UNLOCK_ENTRY:
TRACE_RET(chip, STATUS_FAIL);
}
switch_ddr = 0;
- goto DDR_TUNING_FAIL;
+ TRACE_GOTO(chip, Switch_Fail);
}
}
}
@@ -3114,41 +3134,40 @@ int reset_sd_card(struct rtsx_chip *chip)
if (chip->sd_ctl & RESET_MMC_FIRST) {
retval = reset_mmc(chip);
- if ((retval != STATUS_SUCCESS) && !sd_check_err_code(chip, SD_NO_CARD)) {
+ if (retval != STATUS_SUCCESS) {
+ if (sd_check_err_code(chip, SD_NO_CARD))
+ TRACE_RET(chip, STATUS_FAIL);
+
retval = reset_sd(chip);
if (retval != STATUS_SUCCESS) {
- if (CHECK_PID(chip, 0x5209)) {
- retval = sd_change_bank_voltage(chip, SD_IO_3V3);
- if (retval != STATUS_SUCCESS) {
- TRACE_RET(chip, STATUS_FAIL);
- }
- }
+ if (CHECK_PID(chip, 0x5209))
+ sd_change_bank_voltage(chip, SD_IO_3V3);
+
+ TRACE_RET(chip, STATUS_FAIL);
}
}
} else {
retval = reset_sd(chip);
if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD)) {
+ if (sd_check_err_code(chip, SD_NO_CARD))
TRACE_RET(chip, STATUS_FAIL);
- }
if (CHECK_PID(chip, 0x5209)) {
retval = sd_change_bank_voltage(chip, SD_IO_3V3);
- if (retval != STATUS_SUCCESS) {
+ if (retval != STATUS_SUCCESS)
TRACE_RET(chip, STATUS_FAIL);
- }
}
- if (!chip->sd_io) {
+ if (chip->sd_io) {
+ TRACE_RET(chip, STATUS_FAIL);
+ } else {
retval = reset_mmc(chip);
+ if (retval != STATUS_SUCCESS)
+ TRACE_RET(chip, STATUS_FAIL);
}
}
}
- if (retval != STATUS_SUCCESS) {
- TRACE_RET(chip, STATUS_FAIL);
- }
-
retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
@@ -3727,7 +3746,7 @@ RTY_SEND_CMD:
if ((ptr[3] & 0x1E) != 0x04) {
TRACE_RET(chip, STATUS_FAIL);
}
- } else if (rsp_type == SD_RSP_TYPE_R2) {
+ } else if (rsp_type == SD_RSP_TYPE_R0) {
if ((ptr[3] & 0x1E) != 0x03) {
TRACE_RET(chip, STATUS_FAIL);
}
@@ -4119,7 +4138,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
cmd[3] = srb->cmnd[5];
cmd[4] = srb->cmnd[6];
- buf = (u8 *)kmalloc(data_len, GFP_KERNEL);
+ buf = kmalloc(data_len, GFP_KERNEL);
if (buf == NULL) {
TRACE_RET(chip, TRANSPORT_ERROR);
}
@@ -4365,7 +4384,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
u16 i;
u8 *buf;
- buf = (u8 *)kmalloc(data_len, GFP_KERNEL);
+ buf = kmalloc(data_len, GFP_KERNEL);
if (buf == NULL) {
TRACE_RET(chip, TRANSPORT_ERROR);
}
diff --git a/drivers/staging/rts_pstor/sd.h b/drivers/staging/rts_pstor/sd.h
index d62e690..1df1aa7 100644
--- a/drivers/staging/rts_pstor/sd.h
+++ b/drivers/staging/rts_pstor/sd.h
@@ -38,6 +38,11 @@
#define SD_RSP_TIMEOUT 0x04
#define SD_IO_ERR 0x02
+/* Return code for MMC switch bus */
+#define SWITCH_SUCCESS 0
+#define SWITCH_ERR 1
+#define SWITCH_FAIL 2
+
/* MMC/SD Command Index */
/* Basic command (class 0) */
#define GO_IDLE_STATE 0
diff --git a/drivers/staging/rts_pstor/spi.c b/drivers/staging/rts_pstor/spi.c
index c803ba6..6b36cc5 100644
--- a/drivers/staging/rts_pstor/spi.c
+++ b/drivers/staging/rts_pstor/spi.c
@@ -463,7 +463,7 @@ int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
}
if (len) {
- buf = (u8 *)kmalloc(len, GFP_KERNEL);
+ buf = kmalloc(len, GFP_KERNEL);
if (!buf)
TRACE_RET(chip, STATUS_ERROR);
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 52342c1..8ac3fae 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -50,7 +50,6 @@
#include <linux/interrupt.h>
#include <linux/pagemap.h>
#include <asm/cacheflush.h>
-#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/rar_register.h>
@@ -201,7 +200,7 @@ static int sep_singleton_release(struct inode *inode, struct file *filp)
}
/**
- * sep_request_daemonopen - request daemon open method
+ * sep_request_daemon_open - request daemon open method
* @inode: inode of SEP device
* @filp: file handle to SEP device
*
@@ -1102,9 +1101,9 @@ static int sep_lock_user_pages(struct sep_device *sep,
"lli_array[%x].bus_address is "
"%08lx, lli_array[%x].block_size is %x\n",
num_pages - 1,
- (unsigned long)lli_array[num_pages -1].bus_address,
+ (unsigned long)lli_array[num_pages - 1].bus_address,
num_pages - 1,
- lli_array[num_pages -1].block_size);
+ lli_array[num_pages - 1].block_size);
}
/* Set output params according to the in_out flag */
@@ -2421,11 +2420,12 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
(sep->pid_doing_transaction != 0)) {
dev_dbg(&sep->pdev->dev, "ioctl pid is not owner\n");
error = -EACCES;
- goto end_function;
}
-
mutex_unlock(&sep->sep_mutex);
+ if (error)
+ return error;
+
if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
return -ENOTTY;
@@ -2462,7 +2462,6 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
break;
}
-end_function:
mutex_unlock(&sep->ioctl_mutex);
return error;
}
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
index 1033425..d6bfd24 100644
--- a/drivers/staging/sep/sep_driver_config.h
+++ b/drivers/staging/sep/sep_driver_config.h
@@ -180,7 +180,7 @@ held by the process (struct file) */
/* offset of the caller id area */
#define SEP_CALLER_ID_OFFSET_BYTES \
(SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES + \
- SEP_DRIVER_SYSTEM_RAR_MEMORY_SIZE_IN_BYTES)
+ SEP_DRIVER_SYSTEM_RAR_MEMORY_SIZE_IN_BYTES)
/* offset of the DCB area */
#define SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES \
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 48aa61e..c2731ca 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -188,7 +188,7 @@ struct quatech_port {
struct usb_serial_port *port; /* owner of this object */
struct qt_get_device_data DeviceData;
- spinlock_t lock;
+ struct mutex lock;
bool read_urb_busy;
int RxHolding;
int ReadBulkStopped;
@@ -743,7 +743,7 @@ static int qt_startup(struct usb_serial *serial)
}
return -ENOMEM;
}
- spin_lock_init(&qt_port->lock);
+ mutex_init(&qt_port->lock);
usb_set_serial_port_data(port, qt_port);
@@ -772,7 +772,7 @@ static int qt_startup(struct usb_serial *serial)
goto startup_error;
}
- switch (serial->dev->descriptor.idProduct) {
+ switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
case QUATECH_DSU100:
case QUATECH_QSU100:
case QUATECH_ESU100A:
@@ -1157,7 +1157,6 @@ static int qt_write_room(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial;
struct quatech_port *qt_port;
- unsigned long flags;
int retval = -EINVAL;
@@ -1173,7 +1172,7 @@ static int qt_write_room(struct tty_struct *tty)
qt_port = qt_get_port_private(port);
- spin_lock_irqsave(&qt_port->lock, flags);
+ mutex_lock(&qt_port->lock);
dbg("%s - port %d\n", __func__, port->number);
@@ -1182,7 +1181,7 @@ static int qt_write_room(struct tty_struct *tty)
retval = port->bulk_out_size;
}
- spin_unlock_irqrestore(&qt_port->lock, flags);
+ mutex_unlock(&qt_port->lock);
return retval;
}
@@ -1355,7 +1354,6 @@ static void qt_break(struct tty_struct *tty, int break_state)
struct quatech_port *qt_port;
u16 index, onoff;
unsigned int result;
- unsigned long flags;
index = tty->index - serial->minor;
@@ -1366,7 +1364,7 @@ static void qt_break(struct tty_struct *tty, int break_state)
else
onoff = 0;
- spin_lock_irqsave(&qt_port->lock, flags);
+ mutex_lock(&qt_port->lock);
dbg("%s - port %d\n", __func__, port->number);
@@ -1374,7 +1372,7 @@ static void qt_break(struct tty_struct *tty, int break_state)
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300);
- spin_unlock_irqrestore(&qt_port->lock, flags);
+ mutex_unlock(&qt_port->lock);
}
static inline int qt_real_tiocmget(struct tty_struct *tty,
@@ -1463,21 +1461,20 @@ static int qt_tiocmget(struct tty_struct *tty)
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port = qt_get_port_private(port);
int retval = -ENODEV;
- unsigned long flags;
dbg("In %s\n", __func__);
if (!serial)
return -ENODEV;
- spin_lock_irqsave(&qt_port->lock, flags);
+ mutex_lock(&qt_port->lock);
dbg("%s - port %d\n", __func__, port->number);
dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
retval = qt_real_tiocmget(tty, port, serial);
- spin_unlock_irqrestore(&qt_port->lock, flags);
+ mutex_unlock(&qt_port->lock);
return retval;
}
@@ -1488,7 +1485,6 @@ static int qt_tiocmset(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port = qt_get_port_private(port);
- unsigned long flags;
int retval = -ENODEV;
dbg("In %s\n", __func__);
@@ -1496,14 +1492,14 @@ static int qt_tiocmset(struct tty_struct *tty,
if (!serial)
return -ENODEV;
- spin_lock_irqsave(&qt_port->lock, flags);
+ mutex_lock(&qt_port->lock);
dbg("%s - port %d\n", __func__, port->number);
dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding);
retval = qt_real_tiocmset(tty, port, serial, set);
- spin_unlock_irqrestore(&qt_port->lock, flags);
+ mutex_unlock(&qt_port->lock);
return retval;
}
@@ -1512,7 +1508,6 @@ static void qt_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port;
- unsigned long flags;
dbg("%s - port %d\n", __func__, port->number);
@@ -1521,13 +1516,13 @@ static void qt_throttle(struct tty_struct *tty)
qt_port = qt_get_port_private(port);
- spin_lock_irqsave(&qt_port->lock, flags);
+ mutex_lock(&qt_port->lock);
/* pass on to the driver specific version of this function */
qt_port->RxHolding = 1;
dbg("%s - port->RxHolding = 1\n", __func__);
- spin_unlock_irqrestore(&qt_port->lock, flags);
+ mutex_unlock(&qt_port->lock);
return;
}
@@ -1536,7 +1531,6 @@ static void qt_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port;
- unsigned long flags;
unsigned int result;
if (!serial)
@@ -1544,7 +1538,7 @@ static void qt_unthrottle(struct tty_struct *tty)
qt_port = qt_get_port_private(port);
- spin_lock_irqsave(&qt_port->lock, flags);
+ mutex_lock(&qt_port->lock);
dbg("%s - port %d\n", __func__, port->number);
@@ -1570,7 +1564,7 @@ static void qt_unthrottle(struct tty_struct *tty)
__func__, result);
}
}
- spin_unlock_irqrestore(&qt_port->lock, flags);
+ mutex_unlock(&qt_port->lock);
return;
}
diff --git a/drivers/staging/slicoss/Kconfig b/drivers/staging/slicoss/Kconfig
index d2993d3..5c2a15b 100644
--- a/drivers/staging/slicoss/Kconfig
+++ b/drivers/staging/slicoss/Kconfig
@@ -1,6 +1,6 @@
config SLICOSS
tristate "Alacritech Gigabit IS-NIC support"
- depends on PCI && X86 && NETDEV_1000
+ depends on PCI && X86 && NET
default n
help
This driver supports Alacritech's IS-NIC gigabit ethernet cards.
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 18f1103..77a0751 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -3724,7 +3724,7 @@ static const struct net_device_ops slic_netdev_ops = {
.ndo_do_ioctl = slic_ioctl,
.ndo_set_mac_address = slic_mac_set_address,
.ndo_get_stats = slic_get_stats,
- .ndo_set_multicast_list = slic_mcast_set_list,
+ .ndo_set_rx_mode = slic_mcast_set_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
};
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
index a164fc4..39dbf33 100644
--- a/drivers/staging/sm7xx/smtcfb.c
+++ b/drivers/staging/sm7xx/smtcfb.c
@@ -35,11 +35,13 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/module.h>
#include <linux/console.h>
#include <linux/screen_info.h>
#ifdef CONFIG_PM
#include <linux/pm.h>
+#include <linux/module.h>
#endif
#include "smtcfb.h"
diff --git a/drivers/staging/speakup/devsynth.c b/drivers/staging/speakup/devsynth.c
index 39dc586..940769e 100644
--- a/drivers/staging/speakup/devsynth.c
+++ b/drivers/staging/speakup/devsynth.c
@@ -18,13 +18,14 @@ static ssize_t speakup_file_write(struct file *fp, const char *buffer,
{
size_t count = nbytes;
const char *ptr = buffer;
- int bytes;
+ size_t bytes;
unsigned long flags;
u_char buf[256];
+
if (synth == NULL)
return -ENODEV;
while (count > 0) {
- bytes = min_t(size_t, count, sizeof(buf));
+ bytes = min(count, sizeof(buf));
if (copy_from_user(buf, ptr, bytes))
return -EFAULT;
count -= bytes;
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 07a7f54..6829195 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -521,9 +521,9 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr,
spk_lock(flags);
if (*punc_buf == 'd' || *punc_buf == 'r')
- x = set_mask_bits(0, var->value, 3);
+ x = spk_set_mask_bits(0, var->value, 3);
else
- x = set_mask_bits(punc_buf, var->value, 3);
+ x = spk_set_mask_bits(punc_buf, var->value, 3);
spk_unlock(flags);
return count;
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 59a6d4d..a076351 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -23,7 +23,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/vt.h>
#include <linux/tty.h>
#include <linux/mm.h> /* __get_free_page() and friends */
@@ -2266,7 +2265,7 @@ static int __init speakup_init(void)
(var->var_id >= 0) && (var->var_id < MAXVARS); var++)
speakup_register_var(var);
for (i = 1; punc_info[i].mask != 0; i++)
- set_mask_bits(0, i, 2);
+ spk_set_mask_bits(0, i, 2);
set_key_info(key_defaults, key_buf);
if (quiet_boot)
diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
index 46edabe..f39c0a2 100644
--- a/drivers/staging/speakup/speakup.h
+++ b/drivers/staging/speakup/speakup.h
@@ -1,6 +1,5 @@
#ifndef _SPEAKUP_H
#define _SPEAKUP_H
-#include <linux/version.h>
#include "spk_types.h"
#include "i18n.h"
@@ -72,7 +71,7 @@ extern struct st_var_header *var_header_by_name(const char *name);
extern struct punc_var_t *get_punc_var(enum var_id_t var_id);
extern int set_num_var(int val, struct st_var_header *var, int how);
extern int set_string_var(const char *page, struct st_var_header *var, int len);
-extern int set_mask_bits(const char *input, const int which, const int how);
+extern int spk_set_mask_bits(const char *input, const int which, const int how);
extern special_func special_handler;
extern int handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key);
extern int synth_init(char *name);
diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index e76a882..e2f5c81 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -46,7 +46,7 @@ static int misc_registered;
static struct var_t vars[] = {
{ CAPS_START, .u.s = {"\x01+3p" } },
{ CAPS_STOP, .u.s = {"\x01-3p" } },
- { RATE, .u.n = {"\x01%ds", 5, 0, 9, 0, 0, NULL } },
+ { RATE, .u.n = {"\x01%ds", 2, 0, 9, 0, 0, NULL } },
{ PITCH, .u.n = {"\x01%dp", 5, 0, 9, 0, 0, NULL } },
{ VOL, .u.n = {"\x01%dv", 5, 0, 9, 0, 0, NULL } },
{ TONE, .u.n = {"\x01%dx", 1, 0, 2, 0, 0, NULL } },
@@ -268,15 +268,8 @@ static ssize_t softsynth_write(struct file *fp, const char *buf, size_t count,
{
unsigned long supplied_index = 0;
int converted;
- char indbuf[5];
- if (count >= sizeof(indbuf))
- return -EINVAL;
- if (copy_from_user(indbuf, buf, count))
- return -EFAULT;
- indbuf[count] = '\0';
-
- converted = strict_strtoul(indbuf, 0, &supplied_index);
+ converted = kstrtoul_from_user(buf, count, 0, &supplied_index);
if (converted < 0)
return converted;
diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
index ab7de93..75eaf27 100644
--- a/drivers/staging/speakup/varhandlers.c
+++ b/drivers/staging/speakup/varhandlers.c
@@ -267,11 +267,11 @@ int set_string_var(const char *page, struct st_var_header *var, int len)
return ret;
}
-/* set_mask_bits sets or clears the punc/delim/repeat bits,
+/* spk_set_mask_bits sets or clears the punc/delim/repeat bits,
* if input is null uses the defaults.
* values for how: 0 clears bits of chars supplied,
* 1 clears allk, 2 sets bits for chars */
-int set_mask_bits(const char *input, const int which, const int how)
+int spk_set_mask_bits(const char *input, const int which, const int how)
{
u_char *cp;
short mask = punc_info[which].mask;
diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c
index 506547b..86d556d 100644
--- a/drivers/staging/spectra/ffsport.c
+++ b/drivers/staging/spectra/ffsport.c
@@ -227,19 +227,12 @@ static int ioctl_write_page_data(unsigned long arg)
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
return -EFAULT;
- buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
- if (!buf) {
- printk(KERN_ERR "ioctl_write_page_data: "
- "failed to allocate memory\n");
- return -ENOMEM;
- }
-
- if (copy_from_user(buf, (void __user *)info.data,
- IdentifyDeviceData.PageDataSize)) {
+ buf = memdup_user((void __user *)info.data,
+ IdentifyDeviceData.PageDataSize);
+ if (IS_ERR(buf)) {
printk(KERN_ERR "ioctl_write_page_data: "
"failed to copy user data\n");
- kfree(buf);
- return -EFAULT;
+ return PTR_ERR(buf);
}
mutex_lock(&spectra_lock);
diff --git a/drivers/staging/spectra/lld_mtd.c b/drivers/staging/spectra/lld_mtd.c
index 2bd3466..a9c309a 100644
--- a/drivers/staging/spectra/lld_mtd.c
+++ b/drivers/staging/spectra/lld_mtd.c
@@ -340,7 +340,7 @@ u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
struct mtd_oob_ops ops;
int ret;
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.datbuf = read_data;
ops.len = DeviceInfo.wPageDataSize;
ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
@@ -400,7 +400,7 @@ u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
struct mtd_oob_ops ops;
int ret;
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.datbuf = write_data;
ops.len = DeviceInfo.wPageDataSize;
ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
@@ -473,7 +473,7 @@ u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block,
struct mtd_oob_ops ops;
int ret;
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.datbuf = NULL;
ops.len = 0;
ops.oobbuf = read_data;
diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c
index 0be7adc..60a14ff 100644
--- a/drivers/staging/spectra/lld_nand.c
+++ b/drivers/staging/spectra/lld_nand.c
@@ -2397,6 +2397,12 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
struct mrst_nand_info *pndev = &info;
u32 int_mask;
+ ret = pci_enable_device(dev);
+ if (ret) {
+ printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
+ return ret;
+ }
+
nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
__FILE__, __LINE__, __func__);
@@ -2404,7 +2410,7 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
GLOB_HWCTL_REG_SIZE);
if (!FlashReg) {
printk(KERN_ERR "Spectra: ioremap_nocache failed!");
- return -ENOMEM;
+ goto failed_disable;
}
nand_dbg_print(NAND_DBG_WARN,
"Spectra: Remapped reg base address: "
@@ -2416,7 +2422,7 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (!FlashMem) {
printk(KERN_ERR "Spectra: ioremap_nocache failed!");
iounmap(FlashReg);
- return -ENOMEM;
+ goto failed_disable;
}
nand_dbg_print(NAND_DBG_WARN,
"Spectra: Remapped flash base address: "
@@ -2479,11 +2485,6 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES);
iowrite32(1, FlashReg + ECC_ENABLE);
enable_ecc = 1;
- ret = pci_enable_device(dev);
- if (ret) {
- printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
- goto failed_req_csr;
- }
pci_set_master(dev);
pndev->dev = dev;
@@ -2558,9 +2559,10 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
failed_remap_csr:
pci_release_regions(dev);
failed_req_csr:
- pci_disable_device(dev);
iounmap(FlashMem);
iounmap(FlashReg);
+failed_disable:
+ pci_disable_device(dev);
return ret;
}
diff --git a/drivers/staging/ste_rmi4/Makefile b/drivers/staging/ste_rmi4/Makefile
index 6cce2ed..176f469 100644
--- a/drivers/staging/ste_rmi4/Makefile
+++ b/drivers/staging/ste_rmi4/Makefile
@@ -2,3 +2,4 @@
# Makefile for the RMI4 touchscreen driver.
#
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
+obj-$(CONFIG_MACH_U8500) += board-mop500-u8500uib-rmi4.o
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 3e68d58..11728a0 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -30,6 +30,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "synaptics_i2c_rmi4.h"
/* TODO: for multiple device support will need a per-device mutex */
@@ -926,17 +927,19 @@ static int __devinit synaptics_rmi4_probe
goto err_input;
}
- if (platformdata->regulator_en) {
- rmi4_data->regulator = regulator_get(&client->dev, "vdd");
- if (IS_ERR(rmi4_data->regulator)) {
- dev_err(&client->dev, "%s:get regulator failed\n",
- __func__);
- retval = PTR_ERR(rmi4_data->regulator);
- goto err_regulator;
- }
- regulator_enable(rmi4_data->regulator);
+ rmi4_data->regulator = regulator_get(&client->dev, "vdd");
+ if (IS_ERR(rmi4_data->regulator)) {
+ dev_err(&client->dev, "%s:get regulator failed\n",
+ __func__);
+ retval = PTR_ERR(rmi4_data->regulator);
+ goto err_get_regulator;
+ }
+ retval = regulator_enable(rmi4_data->regulator);
+ if (retval < 0) {
+ dev_err(&client->dev, "%s:regulator enable failed\n",
+ __func__);
+ goto err_regulator_enable;
}
-
init_waitqueue_head(&rmi4_data->wait);
/*
* Copy i2c_client pointer into RTID's i2c_client pointer for
@@ -1011,11 +1014,10 @@ static int __devinit synaptics_rmi4_probe
err_free_irq:
free_irq(platformdata->irq_number, rmi4_data);
err_query_dev:
- if (platformdata->regulator_en) {
- regulator_disable(rmi4_data->regulator);
- regulator_put(rmi4_data->regulator);
- }
-err_regulator:
+ regulator_disable(rmi4_data->regulator);
+err_regulator_enable:
+ regulator_put(rmi4_data->regulator);
+err_get_regulator:
input_free_device(rmi4_data->input_dev);
rmi4_data->input_dev = NULL;
err_input:
@@ -1039,10 +1041,8 @@ static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
wake_up(&rmi4_data->wait);
free_irq(pdata->irq_number, rmi4_data);
input_unregister_device(rmi4_data->input_dev);
- if (pdata->regulator_en) {
- regulator_disable(rmi4_data->regulator);
- regulator_put(rmi4_data->regulator);
- }
+ regulator_disable(rmi4_data->regulator);
+ regulator_put(rmi4_data->regulator);
kfree(rmi4_data);
return 0;
@@ -1080,8 +1080,7 @@ static int synaptics_rmi4_suspend(struct device *dev)
if (retval < 0)
return retval;
- if (pdata->regulator_en)
- regulator_disable(rmi4_data->regulator);
+ regulator_disable(rmi4_data->regulator);
return 0;
}
@@ -1099,8 +1098,7 @@ static int synaptics_rmi4_resume(struct device *dev)
struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
- if (pdata->regulator_en)
- regulator_enable(rmi4_data->regulator);
+ regulator_enable(rmi4_data->regulator);
enable_irq(pdata->irq_number);
rmi4_data->touch_stopped = false;
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
index 3686a2f..384436e 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
@@ -34,7 +34,6 @@
* @irq_type: irq type
* @x flip: x flip flag
* @y flip: y flip flag
- * @regulator_en: regulator enable flag
*
* This structure gives platform data for rmi4.
*/
@@ -43,7 +42,6 @@ struct synaptics_rmi4_platform_data {
int irq_type;
bool x_flip;
bool y_flip;
- bool regulator_en;
};
#endif
diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig
index 93de4f2..b27d9aa 100644
--- a/drivers/staging/tidspbridge/Kconfig
+++ b/drivers/staging/tidspbridge/Kconfig
@@ -4,7 +4,7 @@
menuconfig TIDSPBRIDGE
tristate "DSP Bridge driver"
- depends on ARCH_OMAP3
+ depends on ARCH_OMAP3 && BROKEN
select OMAP_MBOX_FWK
help
DSP/BIOS Bridge is designed for platforms that contain a GPP and
diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c
index 589a055..7eb5617 100644
--- a/drivers/staging/tidspbridge/core/dsp-clock.c
+++ b/drivers/staging/tidspbridge/core/dsp-clock.c
@@ -54,6 +54,7 @@
/* Bridge GPT id (1 - 4), DM Timer id (5 - 8) */
#define DMT_ID(id) ((id) + 4)
+#define DM_TIMER_CLOCKS 4
/* Bridge MCBSP id (6 - 10), OMAP Mcbsp id (0 - 4) */
#define MCBSP_ID(id) ((id) - 6)
@@ -114,8 +115,13 @@ static s8 get_clk_type(u8 id)
*/
void dsp_clk_exit(void)
{
+ int i;
+
dsp_clock_disable_all(dsp_clocks);
+ for (i = 0; i < DM_TIMER_CLOCKS; i++)
+ omap_dm_timer_free(timer[i]);
+
clk_put(iva2_clk);
clk_put(ssi.sst_fck);
clk_put(ssi.ssr_fck);
@@ -130,9 +136,13 @@ void dsp_clk_exit(void)
void dsp_clk_init(void)
{
static struct platform_device dspbridge_device;
+ int i, id;
dspbridge_device.dev.bus = &platform_bus_type;
+ for (i = 0, id = 5; i < DM_TIMER_CLOCKS; i++, id++)
+ timer[i] = omap_dm_timer_request_specific(id);
+
iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck");
if (IS_ERR(iva2_clk))
dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk);
@@ -204,12 +214,10 @@ int dsp_clk_enable(enum dsp_clk_id clk_id)
clk_enable(iva2_clk);
break;
case GPT_CLK:
- timer[clk_id - 1] =
- omap_dm_timer_request_specific(DMT_ID(clk_id));
+ status = omap_dm_timer_start(timer[clk_id - 1]);
break;
#ifdef CONFIG_OMAP_MCBSP
case MCBSP_CLK:
- omap_mcbsp_set_io_type(MCBSP_ID(clk_id), OMAP_MCBSP_POLL_IO);
omap_mcbsp_request(MCBSP_ID(clk_id));
omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PAD_SRC);
break;
@@ -282,7 +290,7 @@ int dsp_clk_disable(enum dsp_clk_id clk_id)
clk_disable(iva2_clk);
break;
case GPT_CLK:
- omap_dm_timer_free(timer[clk_id - 1]);
+ status = omap_dm_timer_stop(timer[clk_id - 1]);
break;
#ifdef CONFIG_OMAP_MCBSP
case MCBSP_CLK:
diff --git a/drivers/staging/tidspbridge/gen/gh.c b/drivers/staging/tidspbridge/gen/gh.c
index cd72503..60aa7b0 100644
--- a/drivers/staging/tidspbridge/gen/gh.c
+++ b/drivers/staging/tidspbridge/gen/gh.c
@@ -55,7 +55,7 @@ struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size,
hash_tab->match = match;
hash_tab->delete = delete == NULL ? noop : delete;
- hash_tab->buckets = (struct element **)
+ hash_tab->buckets =
kzalloc(sizeof(struct element *) * max_bucket, GFP_KERNEL);
if (hash_tab->buckets == NULL) {
gh_delete(hash_tab);
diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.c b/drivers/staging/tidspbridge/hw/hw_mmu.c
index c214df9..8a93d55 100644
--- a/drivers/staging/tidspbridge/hw/hw_mmu.c
+++ b/drivers/staging/tidspbridge/hw/hw_mmu.c
@@ -558,5 +558,5 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
void hw_mmu_tlb_flush_all(const void __iomem *base)
{
- __raw_writeb(1, base + MMU_GFLUSH);
+ __raw_writel(1, base + MMU_GFLUSH);
}
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index b1b8acb..a2f31c6 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -18,13 +18,12 @@
#define _HOST_OS_H_
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/syscalls.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/stddef.h>
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index c43c7e3..76cfc6e 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -24,11 +24,7 @@
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
-
-#ifdef MODULE
#include <linux/module.h>
-#endif
-
#include <linux/device.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/staging/vme/boards/vme_vmivme7805.c
index 80eaa0c..8e05bb4 100644
--- a/drivers/staging/vme/boards/vme_vmivme7805.c
+++ b/drivers/staging/vme/boards/vme_vmivme7805.c
@@ -27,9 +27,9 @@ static void __exit vmic_exit(void);
/** Base address to access FPGA register */
static void *vmic_base;
-static char driver_name[] = "vmivme_7805";
+static const char driver_name[] = "vmivme_7805";
-static struct pci_device_id vmic_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(vmic_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) },
{ },
};
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index a400728..0e4feac 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -42,7 +42,7 @@ static void __exit ca91cx42_exit(void);
/* Module parameters */
static int geoid;
-static char driver_name[] = "vme_ca91cx42";
+static const char driver_name[] = "vme_ca91cx42";
static DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) },
@@ -190,7 +190,7 @@ static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr)
serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat);
/* Clear serviced interrupts */
- iowrite32(stat, bridge->base + LINT_STAT);
+ iowrite32(serviced, bridge->base + LINT_STAT);
return IRQ_HANDLED;
}
@@ -256,6 +256,18 @@ static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
free_irq(pdev->irq, pdev);
}
+static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level)
+{
+ u32 tmp;
+
+ tmp = ioread32(bridge->base + LINT_STAT);
+
+ if (tmp & (1 << level))
+ return 0;
+ else
+ return 1;
+}
+
/*
* Set up an VME interrupt
*/
@@ -311,7 +323,8 @@ static int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level,
iowrite32(tmp, bridge->base + VINT_EN);
/* Wait for IACK */
- wait_event_interruptible(bridge->iack_queue, 0);
+ wait_event_interruptible(bridge->iack_queue,
+ ca91cx42_iack_received(bridge, level));
/* Return interrupt to low state */
tmp = ioread32(bridge->base + VINT_EN);
@@ -1487,6 +1500,28 @@ static int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge)
}
+void *ca91cx42_alloc_consistent(struct device *parent, size_t size,
+ dma_addr_t *dma)
+{
+ struct pci_dev *pdev;
+
+ /* Find pci_dev container of dev */
+ pdev = container_of(parent, struct pci_dev, dev);
+
+ return pci_alloc_consistent(pdev, size, dma);
+}
+
+void ca91cx42_free_consistent(struct device *parent, size_t size, void *vaddr,
+ dma_addr_t dma)
+{
+ struct pci_dev *pdev;
+
+ /* Find pci_dev container of dev */
+ pdev = container_of(parent, struct pci_dev, dev);
+
+ pci_free_consistent(pdev, size, vaddr, dma);
+}
+
static int __init ca91cx42_init(void)
{
return pci_register_driver(&ca91cx42_driver);
@@ -1756,6 +1791,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ca91cx42_bridge->lm_attach = ca91cx42_lm_attach;
ca91cx42_bridge->lm_detach = ca91cx42_lm_detach;
ca91cx42_bridge->slot_get = ca91cx42_slot_get;
+ ca91cx42_bridge->alloc_consistent = ca91cx42_alloc_consistent;
+ ca91cx42_bridge->free_consistent = ca91cx42_free_consistent;
data = ioread32(ca91cx42_device->base + MISC_CTL);
dev_info(&pdev->dev, "Board is%s the VME system controller\n",
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 106aa9d..6c1167c 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -44,7 +44,7 @@ static void __exit tsi148_exit(void);
static int err_chk;
static int geoid;
-static char driver_name[] = "vme_tsi148";
+static const char driver_name[] = "vme_tsi148";
static DEFINE_PCI_DEVICE_TABLE(tsi148_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) },
@@ -2114,6 +2114,28 @@ static int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
return (int)slot;
}
+void *tsi148_alloc_consistent(struct device *parent, size_t size,
+ dma_addr_t *dma)
+{
+ struct pci_dev *pdev;
+
+ /* Find pci_dev container of dev */
+ pdev = container_of(parent, struct pci_dev, dev);
+
+ return pci_alloc_consistent(pdev, size, dma);
+}
+
+void tsi148_free_consistent(struct device *parent, size_t size, void *vaddr,
+ dma_addr_t dma)
+{
+ struct pci_dev *pdev;
+
+ /* Find pci_dev container of dev */
+ pdev = container_of(parent, struct pci_dev, dev);
+
+ pci_free_consistent(pdev, size, vaddr, dma);
+}
+
static int __init tsi148_init(void)
{
return pci_register_driver(&tsi148_driver);
@@ -2443,6 +2465,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
tsi148_bridge->lm_attach = tsi148_lm_attach;
tsi148_bridge->lm_detach = tsi148_lm_detach;
tsi148_bridge->slot_get = tsi148_slot_get;
+ tsi148_bridge->alloc_consistent = tsi148_alloc_consistent;
+ tsi148_bridge->free_consistent = tsi148_free_consistent;
data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
dev_info(&pdev->dev, "Board is%s the VME system controller\n",
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index a571173..7dcd162 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -41,9 +41,9 @@
#include "vme_user.h"
static DEFINE_MUTEX(vme_user_mutex);
-static char driver_name[] = "vme_user";
+static const char driver_name[] = "vme_user";
-static int bus[USER_BUS_MAX];
+static int bus[VME_USER_BUS_MAX];
static unsigned int bus_num;
/* Currently Documentation/devices.txt defines the following for VME:
@@ -91,7 +91,7 @@ static unsigned int bus_num;
/*
* Structure to handle image related parameters.
*/
-typedef struct {
+struct image_desc {
void *kern_buf; /* Buffer address in kernel space */
dma_addr_t pci_buf; /* Buffer address in PCI address space */
unsigned long long size_buf; /* Buffer size */
@@ -99,10 +99,10 @@ typedef struct {
struct device *device; /* Sysfs device */
struct vme_resource *resource; /* VME resource */
int users; /* Number of current users */
-} image_desc_t;
-static image_desc_t image[VME_DEVS];
+};
+static struct image_desc image[VME_DEVS];
-typedef struct {
+struct driver_stats {
unsigned long reads;
unsigned long writes;
unsigned long ioctls;
@@ -111,12 +111,12 @@ typedef struct {
unsigned long dmaErrors;
unsigned long timeouts;
unsigned long external;
-} driver_stats_t;
-static driver_stats_t statistics;
+};
+static struct driver_stats statistics;
static struct cdev *vme_user_cdev; /* Character device */
static struct class *vme_user_sysfs_class; /* Sysfs class */
-static struct device *vme_user_bridge; /* Pointer to bridge device */
+static struct vme_dev *vme_user_bridge; /* Pointer to user device */
static const int type[VME_DEVS] = { MASTER_MINOR, MASTER_MINOR,
@@ -135,10 +135,11 @@ static ssize_t vme_user_write(struct file *, const char __user *, size_t,
static loff_t vme_user_llseek(struct file *, loff_t, int);
static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
-static int __devinit vme_user_probe(struct device *, int, int);
-static int __devexit vme_user_remove(struct device *, int, int);
+static int vme_user_match(struct vme_dev *);
+static int __devinit vme_user_probe(struct vme_dev *);
+static int __devexit vme_user_remove(struct vme_dev *);
-static struct file_operations vme_user_fops = {
+static const struct file_operations vme_user_fops = {
.open = vme_user_open,
.release = vme_user_release,
.read = vme_user_read,
@@ -168,8 +169,8 @@ static int vme_user_open(struct inode *inode, struct file *file)
unsigned int minor = MINOR(inode->i_rdev);
down(&image[minor].sem);
- /* Only allow device to be opened if a resource is allocated */
- if (image[minor].resource == NULL) {
+ /* Allow device to be opened if a resource is needed and allocated. */
+ if (minor < CONTROL_MINOR && image[minor].resource == NULL) {
printk(KERN_ERR "No resources allocated for device\n");
err = -EINVAL;
goto err_res;
@@ -321,6 +322,9 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
size_t image_size;
size_t okcount;
+ if (minor == CONTROL_MINOR)
+ return 0;
+
down(&image[minor].sem);
/* XXX Do we *really* want this helper - we can use vme_*_get ? */
@@ -365,6 +369,9 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
size_t image_size;
size_t okcount;
+ if (minor == CONTROL_MINOR)
+ return 0;
+
down(&image[minor].sem);
image_size = vme_get_size(image[minor].resource);
@@ -406,6 +413,9 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
size_t image_size;
+ if (minor == CONTROL_MINOR)
+ return -EINVAL;
+
down(&image[minor].sem);
image_size = vme_get_size(image[minor].resource);
@@ -452,6 +462,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
{
struct vme_master master;
struct vme_slave slave;
+ struct vme_irq_id irq_req;
unsigned long copied;
unsigned int minor = MINOR(inode->i_rdev);
int retval;
@@ -462,6 +473,21 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
switch (type[minor]) {
case CONTROL_MINOR:
+ switch (cmd) {
+ case VME_IRQ_GEN:
+ copied = copy_from_user(&irq_req, (char *)arg,
+ sizeof(struct vme_irq_id));
+ if (copied != 0) {
+ printk(KERN_WARNING "Partial copy from userspace\n");
+ return -EFAULT;
+ }
+
+ retval = vme_irq_generate(vme_user_bridge,
+ irq_req.level,
+ irq_req.statid);
+
+ return retval;
+ }
break;
case MASTER_MINOR:
switch (cmd) {
@@ -595,6 +621,7 @@ static void buf_unalloc(int num)
static struct vme_driver vme_user_driver = {
.name = driver_name,
+ .match = vme_user_match,
.probe = vme_user_probe,
.remove = __devexit_p(vme_user_remove),
};
@@ -603,8 +630,6 @@ static struct vme_driver vme_user_driver = {
static int __init vme_user_init(void)
{
int retval = 0;
- int i;
- struct vme_device_id *ids;
printk(KERN_INFO "VME User Space Access Driver\n");
@@ -618,56 +643,42 @@ static int __init vme_user_init(void)
/* Let's start by supporting one bus, we can support more than one
* in future revisions if that ever becomes necessary.
*/
- if (bus_num > USER_BUS_MAX) {
+ if (bus_num > VME_USER_BUS_MAX) {
printk(KERN_ERR "%s: Driver only able to handle %d buses\n",
- driver_name, USER_BUS_MAX);
- bus_num = USER_BUS_MAX;
+ driver_name, VME_USER_BUS_MAX);
+ bus_num = VME_USER_BUS_MAX;
}
-
- /* Dynamically create the bind table based on module parameters */
- ids = kmalloc(sizeof(struct vme_device_id) * (bus_num + 1), GFP_KERNEL);
- if (ids == NULL) {
- printk(KERN_ERR "%s: Unable to allocate ID table\n",
- driver_name);
- retval = -ENOMEM;
- goto err_id;
- }
-
- memset(ids, 0, (sizeof(struct vme_device_id) * (bus_num + 1)));
-
- for (i = 0; i < bus_num; i++) {
- ids[i].bus = bus[i];
- /*
- * We register the driver against the slot occupied by *this*
- * card, since it's really a low level way of controlling
- * the VME bridge
- */
- ids[i].slot = VME_SLOT_CURRENT;
- }
-
- vme_user_driver.bind_table = ids;
-
- retval = vme_register_driver(&vme_user_driver);
+ /*
+ * Here we just register the maximum number of devices we can and
+ * leave vme_user_match() to allow only 1 to go through to probe().
+ * This way, if we later want to allow multiple user access devices,
+ * we just change the code in vme_user_match().
+ */
+ retval = vme_register_driver(&vme_user_driver, VME_MAX_SLOTS);
if (retval != 0)
goto err_reg;
return retval;
err_reg:
- kfree(ids);
-err_id:
err_nocard:
return retval;
}
+static int vme_user_match(struct vme_dev *vdev)
+{
+ if (vdev->num >= VME_USER_BUS_MAX)
+ return 0;
+ return 1;
+}
+
/*
* In this simple access driver, the old behaviour is being preserved as much
* as practical. We will therefore reserve the buffers and request the images
* here so that we don't have to do it later.
*/
-static int __devinit vme_user_probe(struct device *dev, int cur_bus,
- int cur_slot)
+static int __devinit vme_user_probe(struct vme_dev *vdev)
{
int i, err;
char name[12];
@@ -679,7 +690,7 @@ static int __devinit vme_user_probe(struct device *dev, int cur_bus,
err = -EINVAL;
goto err_dev;
}
- vme_user_bridge = dev;
+ vme_user_bridge = vdev;
/* Initialise descriptors */
for (i = 0; i < VME_DEVS; i++) {
@@ -773,6 +784,7 @@ static int __devinit vme_user_probe(struct device *dev, int cur_bus,
/* Add sysfs Entries */
for (i = 0; i < VME_DEVS; i++) {
+ int num;
switch (type[i]) {
case MASTER_MINOR:
sprintf(name, "bus/vme/m%%d");
@@ -789,10 +801,9 @@ static int __devinit vme_user_probe(struct device *dev, int cur_bus,
break;
}
- image[i].device =
- device_create(vme_user_sysfs_class, NULL,
- MKDEV(VME_MAJOR, i), NULL, name,
- (type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i);
+ num = (type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i;
+ image[i].device = device_create(vme_user_sysfs_class, NULL,
+ MKDEV(VME_MAJOR, i), NULL, name, num);
if (IS_ERR(image[i].device)) {
printk(KERN_INFO "%s: Error creating sysfs device\n",
driver_name);
@@ -842,8 +853,7 @@ err_dev:
return err;
}
-static int __devexit vme_user_remove(struct device *dev, int cur_bus,
- int cur_slot)
+static int __devexit vme_user_remove(struct vme_dev *dev)
{
int i;
@@ -875,8 +885,6 @@ static int __devexit vme_user_remove(struct device *dev, int cur_bus,
static void __exit vme_user_exit(void)
{
vme_unregister_driver(&vme_user_driver);
-
- kfree(vme_user_driver.bind_table);
}
diff --git a/drivers/staging/vme/devices/vme_user.h b/drivers/staging/vme/devices/vme_user.h
index ede77d7..d85a1e9 100644
--- a/drivers/staging/vme/devices/vme_user.h
+++ b/drivers/staging/vme/devices/vme_user.h
@@ -1,7 +1,7 @@
#ifndef _VME_USER_H_
#define _VME_USER_H_
-#define USER_BUS_MAX 1
+#define VME_USER_BUS_MAX 1
/*
* VMEbus Master Window Configuration Structure
@@ -43,10 +43,16 @@ struct vme_slave {
#endif
};
+struct vme_irq_id {
+ __u8 level;
+ __u8 statid;
+};
+
#define VME_GET_SLAVE _IOR(VME_IOC_MAGIC, 1, struct vme_slave)
#define VME_SET_SLAVE _IOW(VME_IOC_MAGIC, 2, struct vme_slave)
#define VME_GET_MASTER _IOR(VME_IOC_MAGIC, 3, struct vme_master)
#define VME_SET_MASTER _IOW(VME_IOC_MAGIC, 4, struct vme_master)
+#define VME_IRQ_GEN _IOW(VME_IOC_MAGIC, 5, struct vme_irq_id)
#endif /* _VME_USER_H_ */
diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
index c078ce3..b04b468 100644
--- a/drivers/staging/vme/vme.c
+++ b/drivers/staging/vme/vme.c
@@ -34,20 +34,17 @@
#include "vme.h"
#include "vme_bridge.h"
-/* Bitmask and mutex to keep track of bridge numbers */
+/* Bitmask and list of registered buses both protected by common mutex */
static unsigned int vme_bus_numbers;
-static DEFINE_MUTEX(vme_bus_num_mtx);
+static LIST_HEAD(vme_bus_list);
+static DEFINE_MUTEX(vme_buses_lock);
static void __exit vme_exit(void);
static int __init vme_init(void);
-
-/*
- * Find the bridge resource associated with a specific device resource
- */
-static struct vme_bridge *dev_to_bridge(struct device *dev)
+static struct vme_dev *dev_to_vme_dev(struct device *dev)
{
- return dev->platform_data;
+ return container_of(dev, struct vme_dev, dev);
}
/*
@@ -83,15 +80,11 @@ static struct vme_bridge *find_bridge(struct vme_resource *resource)
/*
* Allocate a contiguous block of memory for use by the driver. This is used to
* create the buffers for the slave windows.
- *
- * XXX VME bridges could be available on buses other than PCI. At the momment
- * this framework only supports PCI devices.
*/
void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
dma_addr_t *dma)
{
struct vme_bridge *bridge;
- struct pci_dev *pdev;
if (resource == NULL) {
printk(KERN_ERR "No resource\n");
@@ -104,28 +97,29 @@ void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
return NULL;
}
- /* Find pci_dev container of dev */
if (bridge->parent == NULL) {
- printk(KERN_ERR "Dev entry NULL\n");
+ printk(KERN_ERR "Dev entry NULL for"
+ " bridge %s\n", bridge->name);
return NULL;
}
- pdev = container_of(bridge->parent, struct pci_dev, dev);
- return pci_alloc_consistent(pdev, size, dma);
+ if (bridge->alloc_consistent == NULL) {
+ printk(KERN_ERR "alloc_consistent not supported by"
+ " bridge %s\n", bridge->name);
+ return NULL;
+ }
+
+ return bridge->alloc_consistent(bridge->parent, size, dma);
}
EXPORT_SYMBOL(vme_alloc_consistent);
/*
* Free previously allocated contiguous block of memory.
- *
- * XXX VME bridges could be available on buses other than PCI. At the momment
- * this framework only supports PCI devices.
*/
void vme_free_consistent(struct vme_resource *resource, size_t size,
void *vaddr, dma_addr_t dma)
{
struct vme_bridge *bridge;
- struct pci_dev *pdev;
if (resource == NULL) {
printk(KERN_ERR "No resource\n");
@@ -138,10 +132,19 @@ void vme_free_consistent(struct vme_resource *resource, size_t size,
return;
}
- /* Find pci_dev container of dev */
- pdev = container_of(bridge->parent, struct pci_dev, dev);
+ if (bridge->parent == NULL) {
+ printk(KERN_ERR "Dev entry NULL for"
+ " bridge %s\n", bridge->name);
+ return;
+ }
+
+ if (bridge->free_consistent == NULL) {
+ printk(KERN_ERR "free_consistent not supported by"
+ " bridge %s\n", bridge->name);
+ return;
+ }
- pci_free_consistent(pdev, size, vaddr, dma);
+ bridge->free_consistent(bridge->parent, size, vaddr, dma);
}
EXPORT_SYMBOL(vme_free_consistent);
@@ -229,7 +232,7 @@ static int vme_check_window(vme_address_t aspace, unsigned long long vme_base,
* Request a slave image with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_slave_request(struct device *dev,
+struct vme_resource *vme_slave_request(struct vme_dev *vdev,
vme_address_t address, vme_cycle_t cycle)
{
struct vme_bridge *bridge;
@@ -238,7 +241,7 @@ struct vme_resource *vme_slave_request(struct device *dev,
struct vme_slave_resource *slave_image = NULL;
struct vme_resource *resource = NULL;
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
goto err_bus;
@@ -385,7 +388,7 @@ EXPORT_SYMBOL(vme_slave_free);
* Request a master image with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_master_request(struct device *dev,
+struct vme_resource *vme_master_request(struct vme_dev *vdev,
vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth)
{
struct vme_bridge *bridge;
@@ -394,7 +397,7 @@ struct vme_resource *vme_master_request(struct device *dev,
struct vme_master_resource *master_image = NULL;
struct vme_resource *resource = NULL;
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
goto err_bus;
@@ -643,7 +646,8 @@ EXPORT_SYMBOL(vme_master_free);
* Request a DMA controller with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_dma_request(struct device *dev, vme_dma_route_t route)
+struct vme_resource *vme_dma_request(struct vme_dev *vdev,
+ vme_dma_route_t route)
{
struct vme_bridge *bridge;
struct list_head *dma_pos = NULL;
@@ -654,7 +658,7 @@ struct vme_resource *vme_dma_request(struct device *dev, vme_dma_route_t route)
/* XXX Not checking resource attributes */
printk(KERN_ERR "No VME resource Attribute tests done\n");
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
goto err_bus;
@@ -987,13 +991,13 @@ void vme_irq_handler(struct vme_bridge *bridge, int level, int statid)
}
EXPORT_SYMBOL(vme_irq_handler);
-int vme_irq_request(struct device *dev, int level, int statid,
+int vme_irq_request(struct vme_dev *vdev, int level, int statid,
void (*callback)(int, int, void *),
void *priv_data)
{
struct vme_bridge *bridge;
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
return -EINVAL;
@@ -1030,11 +1034,11 @@ int vme_irq_request(struct device *dev, int level, int statid,
}
EXPORT_SYMBOL(vme_irq_request);
-void vme_irq_free(struct device *dev, int level, int statid)
+void vme_irq_free(struct vme_dev *vdev, int level, int statid)
{
struct vme_bridge *bridge;
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
return;
@@ -1065,11 +1069,11 @@ void vme_irq_free(struct device *dev, int level, int statid)
}
EXPORT_SYMBOL(vme_irq_free);
-int vme_irq_generate(struct device *dev, int level, int statid)
+int vme_irq_generate(struct vme_dev *vdev, int level, int statid)
{
struct vme_bridge *bridge;
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
return -EINVAL;
@@ -1092,7 +1096,7 @@ EXPORT_SYMBOL(vme_irq_generate);
/*
* Request the location monitor, return resource or NULL
*/
-struct vme_resource *vme_lm_request(struct device *dev)
+struct vme_resource *vme_lm_request(struct vme_dev *vdev)
{
struct vme_bridge *bridge;
struct list_head *lm_pos = NULL;
@@ -1100,7 +1104,7 @@ struct vme_resource *vme_lm_request(struct device *dev)
struct vme_lm_resource *lm = NULL;
struct vme_resource *resource = NULL;
- bridge = dev_to_bridge(dev);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
goto err_bus;
@@ -1281,11 +1285,11 @@ void vme_lm_free(struct vme_resource *resource)
}
EXPORT_SYMBOL(vme_lm_free);
-int vme_slot_get(struct device *bus)
+int vme_slot_get(struct vme_dev *vdev)
{
struct vme_bridge *bridge;
- bridge = dev_to_bridge(bus);
+ bridge = vdev->bridge;
if (bridge == NULL) {
printk(KERN_ERR "Can't find VME bus\n");
return -EINVAL;
@@ -1303,207 +1307,212 @@ EXPORT_SYMBOL(vme_slot_get);
/* - Bridge Registration --------------------------------------------------- */
-static int vme_alloc_bus_num(void)
+static int vme_add_bus(struct vme_bridge *bridge)
{
int i;
+ int ret = -1;
- mutex_lock(&vme_bus_num_mtx);
+ mutex_lock(&vme_buses_lock);
for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) {
- if (((vme_bus_numbers >> i) & 0x1) == 0) {
- vme_bus_numbers |= (0x1 << i);
+ if ((vme_bus_numbers & (1 << i)) == 0) {
+ vme_bus_numbers |= (1 << i);
+ bridge->num = i;
+ INIT_LIST_HEAD(&bridge->devices);
+ list_add_tail(&bridge->bus_list, &vme_bus_list);
+ ret = 0;
break;
}
}
- mutex_unlock(&vme_bus_num_mtx);
+ mutex_unlock(&vme_buses_lock);
- return i;
+ return ret;
}
-static void vme_free_bus_num(int bus)
+static void vme_remove_bus(struct vme_bridge *bridge)
{
- mutex_lock(&vme_bus_num_mtx);
- vme_bus_numbers &= ~(0x1 << bus);
- mutex_unlock(&vme_bus_num_mtx);
+ struct vme_dev *vdev;
+ struct vme_dev *tmp;
+
+ mutex_lock(&vme_buses_lock);
+ vme_bus_numbers &= ~(1 << bridge->num);
+ list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) {
+ list_del(&vdev->drv_list);
+ list_del(&vdev->bridge_list);
+ device_unregister(&vdev->dev);
+ }
+ list_del(&bridge->bus_list);
+ mutex_unlock(&vme_buses_lock);
}
-int vme_register_bridge(struct vme_bridge *bridge)
+static void vme_dev_release(struct device *dev)
{
- struct device *dev;
- int retval;
- int i;
+ kfree(dev_to_vme_dev(dev));
+}
- bridge->num = vme_alloc_bus_num();
+int vme_register_bridge(struct vme_bridge *bridge)
+{
+ return vme_add_bus(bridge);
+}
+EXPORT_SYMBOL(vme_register_bridge);
- /* This creates 32 vme "slot" devices. This equates to a slot for each
- * ID available in a system conforming to the ANSI/VITA 1-1994
- * specification.
- */
- for (i = 0; i < VME_SLOTS_MAX; i++) {
- dev = &bridge->dev[i];
- memset(dev, 0, sizeof(struct device));
+void vme_unregister_bridge(struct vme_bridge *bridge)
+{
+ vme_remove_bus(bridge);
+}
+EXPORT_SYMBOL(vme_unregister_bridge);
- dev->parent = bridge->parent;
- dev->bus = &vme_bus_type;
- /*
- * We save a pointer to the bridge in platform_data so that we
- * can get to it later. We keep driver_data for use by the
- * driver that binds against the slot
- */
- dev->platform_data = bridge;
- dev_set_name(dev, "vme-%x.%x", bridge->num, i + 1);
+/* - Driver Registration --------------------------------------------------- */
- retval = device_register(dev);
- if (retval)
+static int __vme_register_driver_bus(struct vme_driver *drv,
+ struct vme_bridge *bridge, unsigned int ndevs)
+{
+ int err;
+ unsigned int i;
+ struct vme_dev *vdev;
+ struct vme_dev *tmp;
+
+ for (i = 0; i < ndevs; i++) {
+ vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL);
+ if (!vdev) {
+ err = -ENOMEM;
+ goto err_devalloc;
+ }
+ vdev->num = i;
+ vdev->bridge = bridge;
+ vdev->dev.platform_data = drv;
+ vdev->dev.release = vme_dev_release;
+ vdev->dev.parent = bridge->parent;
+ vdev->dev.bus = &vme_bus_type;
+ dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, bridge->num,
+ vdev->num);
+
+ err = device_register(&vdev->dev);
+ if (err)
goto err_reg;
- }
- return retval;
+ if (vdev->dev.platform_data) {
+ list_add_tail(&vdev->drv_list, &drv->devices);
+ list_add_tail(&vdev->bridge_list, &bridge->devices);
+ } else
+ device_unregister(&vdev->dev);
+ }
+ return 0;
err_reg:
- while (--i >= 0) {
- dev = &bridge->dev[i];
- device_unregister(dev);
- }
- vme_free_bus_num(bridge->num);
- return retval;
+ kfree(vdev);
+err_devalloc:
+ list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) {
+ list_del(&vdev->drv_list);
+ list_del(&vdev->bridge_list);
+ device_unregister(&vdev->dev);
+ }
+ return err;
}
-EXPORT_SYMBOL(vme_register_bridge);
-void vme_unregister_bridge(struct vme_bridge *bridge)
+static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
{
- int i;
- struct device *dev;
-
+ struct vme_bridge *bridge;
+ int err = 0;
- for (i = 0; i < VME_SLOTS_MAX; i++) {
- dev = &bridge->dev[i];
- device_unregister(dev);
+ mutex_lock(&vme_buses_lock);
+ list_for_each_entry(bridge, &vme_bus_list, bus_list) {
+ /*
+ * This cannot cause trouble as we already have vme_buses_lock
+ * and if the bridge is removed, it will have to go through
+ * vme_unregister_bridge() to do it (which calls remove() on
+ * the bridge which in turn tries to acquire vme_buses_lock and
+ * will have to wait). The probe() called after device
+ * registration in __vme_register_driver below will also fail
+ * as the bridge is being removed (since the probe() calls
+ * vme_bridge_get()).
+ */
+ err = __vme_register_driver_bus(drv, bridge, ndevs);
+ if (err)
+ break;
}
- vme_free_bus_num(bridge->num);
+ mutex_unlock(&vme_buses_lock);
+ return err;
}
-EXPORT_SYMBOL(vme_unregister_bridge);
-
-/* - Driver Registration --------------------------------------------------- */
-
-int vme_register_driver(struct vme_driver *drv)
+int vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
{
+ int err;
+
drv->driver.name = drv->name;
drv->driver.bus = &vme_bus_type;
+ INIT_LIST_HEAD(&drv->devices);
+
+ err = driver_register(&drv->driver);
+ if (err)
+ return err;
- return driver_register(&drv->driver);
+ err = __vme_register_driver(drv, ndevs);
+ if (err)
+ driver_unregister(&drv->driver);
+
+ return err;
}
EXPORT_SYMBOL(vme_register_driver);
void vme_unregister_driver(struct vme_driver *drv)
{
- driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(vme_unregister_driver);
-
-/* - Bus Registration ------------------------------------------------------ */
-
-static int vme_calc_slot(struct device *dev)
-{
- struct vme_bridge *bridge;
- int num;
-
- bridge = dev_to_bridge(dev);
-
- /* Determine slot number */
- num = 0;
- while (num < VME_SLOTS_MAX) {
- if (&bridge->dev[num] == dev)
- break;
+ struct vme_dev *dev, *dev_tmp;
- num++;
+ mutex_lock(&vme_buses_lock);
+ list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) {
+ list_del(&dev->drv_list);
+ list_del(&dev->bridge_list);
+ device_unregister(&dev->dev);
}
- if (num == VME_SLOTS_MAX) {
- dev_err(dev, "Failed to identify slot\n");
- num = 0;
- goto err_dev;
- }
- num++;
+ mutex_unlock(&vme_buses_lock);
-err_dev:
- return num;
+ driver_unregister(&drv->driver);
}
+EXPORT_SYMBOL(vme_unregister_driver);
-static struct vme_driver *dev_to_vme_driver(struct device *dev)
-{
- if (dev->driver == NULL)
- printk(KERN_ERR "Bugger dev->driver is NULL\n");
-
- return container_of(dev->driver, struct vme_driver, driver);
-}
+/* - Bus Registration ------------------------------------------------------ */
static int vme_bus_match(struct device *dev, struct device_driver *drv)
{
- struct vme_bridge *bridge;
- struct vme_driver *driver;
- int i, num;
+ struct vme_driver *vme_drv;
- bridge = dev_to_bridge(dev);
- driver = container_of(drv, struct vme_driver, driver);
+ vme_drv = container_of(drv, struct vme_driver, driver);
- num = vme_calc_slot(dev);
- if (!num)
- goto err_dev;
-
- if (driver->bind_table == NULL) {
- dev_err(dev, "Bind table NULL\n");
- goto err_table;
- }
+ if (dev->platform_data == vme_drv) {
+ struct vme_dev *vdev = dev_to_vme_dev(dev);
- i = 0;
- while ((driver->bind_table[i].bus != 0) ||
- (driver->bind_table[i].slot != 0)) {
+ if (vme_drv->match && vme_drv->match(vdev))
+ return 1;
- if (bridge->num == driver->bind_table[i].bus) {
- if (num == driver->bind_table[i].slot)
- return 1;
-
- if (driver->bind_table[i].slot == VME_SLOT_ALL)
- return 1;
-
- if ((driver->bind_table[i].slot == VME_SLOT_CURRENT) &&
- (num == vme_slot_get(dev)))
- return 1;
- }
- i++;
+ dev->platform_data = NULL;
}
-
-err_dev:
-err_table:
return 0;
}
static int vme_bus_probe(struct device *dev)
{
- struct vme_bridge *bridge;
- struct vme_driver *driver;
int retval = -ENODEV;
+ struct vme_driver *driver;
+ struct vme_dev *vdev = dev_to_vme_dev(dev);
- driver = dev_to_vme_driver(dev);
- bridge = dev_to_bridge(dev);
+ driver = dev->platform_data;
if (driver->probe != NULL)
- retval = driver->probe(dev, bridge->num, vme_calc_slot(dev));
+ retval = driver->probe(vdev);
return retval;
}
static int vme_bus_remove(struct device *dev)
{
- struct vme_bridge *bridge;
- struct vme_driver *driver;
int retval = -ENODEV;
+ struct vme_driver *driver;
+ struct vme_dev *vdev = dev_to_vme_dev(dev);
- driver = dev_to_vme_driver(dev);
- bridge = dev_to_bridge(dev);
+ driver = dev->platform_data;
if (driver->remove != NULL)
- retval = driver->remove(dev, bridge->num, vme_calc_slot(dev));
+ retval = driver->remove(vdev);
return retval;
}
diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h
index 48768ca..e3828ba 100644
--- a/drivers/staging/vme/vme.h
+++ b/drivers/staging/vme/vme.h
@@ -88,22 +88,38 @@ struct vme_resource {
extern struct bus_type vme_bus_type;
+/* VME_MAX_BRIDGES comes from the type of vme_bus_numbers */
+#define VME_MAX_BRIDGES (sizeof(unsigned int)*8)
+#define VME_MAX_SLOTS 32
+
#define VME_SLOT_CURRENT -1
#define VME_SLOT_ALL -2
-struct vme_device_id {
- int bus;
- int slot;
+/**
+ * Structure representing a VME device
+ * @id: The ID of the device (currently the bus and slot number)
+ * @bridge: Pointer to the bridge device this device is on
+ * @dev: Internal device structure
+ * @drv_list: List of devices (per driver)
+ * @bridge_list: List of devices (per bridge)
+ */
+struct vme_dev {
+ int num;
+ struct vme_bridge *bridge;
+ struct device dev;
+ struct list_head drv_list;
+ struct list_head bridge_list;
};
struct vme_driver {
struct list_head node;
- char *name;
- const struct vme_device_id *bind_table;
- int (*probe) (struct device *, int, int);
- int (*remove) (struct device *, int, int);
- void (*shutdown) (void);
- struct device_driver driver;
+ const char *name;
+ int (*match)(struct vme_dev *);
+ int (*probe)(struct vme_dev *);
+ int (*remove)(struct vme_dev *);
+ void (*shutdown)(void);
+ struct device_driver driver;
+ struct list_head devices;
};
void *vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *);
@@ -112,7 +128,7 @@ void vme_free_consistent(struct vme_resource *, size_t, void *,
size_t vme_get_size(struct vme_resource *);
-struct vme_resource *vme_slave_request(struct device *, vme_address_t,
+struct vme_resource *vme_slave_request(struct vme_dev *, vme_address_t,
vme_cycle_t);
int vme_slave_set(struct vme_resource *, int, unsigned long long,
unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t);
@@ -120,7 +136,7 @@ int vme_slave_get(struct vme_resource *, int *, unsigned long long *,
unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *);
void vme_slave_free(struct vme_resource *);
-struct vme_resource *vme_master_request(struct device *, vme_address_t,
+struct vme_resource *vme_master_request(struct vme_dev *, vme_address_t,
vme_cycle_t, vme_width_t);
int vme_master_set(struct vme_resource *, int, unsigned long long,
unsigned long long, vme_address_t, vme_cycle_t, vme_width_t);
@@ -132,7 +148,7 @@ unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int,
unsigned int, loff_t);
void vme_master_free(struct vme_resource *);
-struct vme_resource *vme_dma_request(struct device *, vme_dma_route_t);
+struct vme_resource *vme_dma_request(struct vme_dev *, vme_dma_route_t);
struct vme_dma_list *vme_new_dma_list(struct vme_resource *);
struct vme_dma_attr *vme_dma_pattern_attribute(u32, vme_pattern_t);
struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t);
@@ -145,12 +161,12 @@ int vme_dma_list_exec(struct vme_dma_list *);
int vme_dma_list_free(struct vme_dma_list *);
int vme_dma_free(struct vme_resource *);
-int vme_irq_request(struct device *, int, int,
+int vme_irq_request(struct vme_dev *, int, int,
void (*callback)(int, int, void *), void *);
-void vme_irq_free(struct device *, int, int);
-int vme_irq_generate(struct device *, int, int);
+void vme_irq_free(struct vme_dev *, int, int);
+int vme_irq_generate(struct vme_dev *, int, int);
-struct vme_resource * vme_lm_request(struct device *);
+struct vme_resource * vme_lm_request(struct vme_dev *);
int vme_lm_count(struct vme_resource *);
int vme_lm_set(struct vme_resource *, unsigned long long, vme_address_t,
vme_cycle_t);
@@ -160,9 +176,9 @@ int vme_lm_attach(struct vme_resource *, int, void (*callback)(int));
int vme_lm_detach(struct vme_resource *, int);
void vme_lm_free(struct vme_resource *);
-int vme_slot_get(struct device *);
+int vme_slot_get(struct vme_dev *);
-int vme_register_driver(struct vme_driver *);
+int vme_register_driver(struct vme_driver *, unsigned int);
void vme_unregister_driver(struct vme_driver *);
diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt
index 4910e92..e8ff215 100644
--- a/drivers/staging/vme/vme_api.txt
+++ b/drivers/staging/vme/vme_api.txt
@@ -18,37 +18,49 @@ registration function. The structure is as follows:
struct vme_driver {
struct list_head node;
- char *name;
- const struct vme_device_id *bind_table;
- int (*probe) (struct device *, int, int);
- int (*remove) (struct device *, int, int);
- void (*shutdown) (void);
- struct device_driver driver;
+ const char *name;
+ int (*match)(struct vme_dev *);
+ int (*probe)(struct vme_dev *);
+ int (*remove)(struct vme_dev *);
+ void (*shutdown)(void);
+ struct device_driver driver;
+ struct list_head devices;
+ unsigned int ndev;
};
-At the minimum, the '.name', '.probe' and '.bind_table' elements of this
-structure should be correctly set. The '.name' element is a pointer to a string
-holding the device driver's name. The '.probe' element should contain a pointer
-to the probe routine.
-
-The arguments of the probe routine are as follows:
-
- probe(struct device *dev, int bus, int slot);
-
-The '.bind_table' is a pointer to an array of type 'vme_device_id':
-
- struct vme_device_id {
- int bus;
- int slot;
+At the minimum, the '.name', '.match' and '.probe' elements of this structure
+should be correctly set. The '.name' element is a pointer to a string holding
+the device driver's name.
+
+The '.match' function allows controlling the number of devices that need to
+be registered. The match function should return 1 if a device should be
+probed and 0 otherwise. This example match function (from vme_user.c) limits
+the number of devices probed to one:
+
+ #define USER_BUS_MAX 1
+ ...
+ static int vme_user_match(struct vme_dev *vdev)
+ {
+ if (vdev->id.num >= USER_BUS_MAX)
+ return 0;
+ return 1;
+ }
+
+The '.probe' element should contain a pointer to the probe routine. The
+probe routine is passed a 'struct vme_dev' pointer as an argument. The
+'struct vme_dev' structure looks like the following:
+
+ struct vme_dev {
+ int num;
+ struct vme_bridge *bridge;
+ struct device dev;
+ struct list_head drv_list;
+ struct list_head bridge_list;
};
-Each structure in this array should provide a bus and slot number where the core
-should probe, using the driver's probe routine, for a device on the specified
-VME bus.
-
-The VME subsystem supports a single VME driver per 'slot'. There are considered
-to be 32 slots per bus, one for each slot-ID as defined in the ANSI/VITA 1-1994
-specification and are analogious to the physical slots on the VME backplane.
+Here, the 'num' field refers to the sequential device ID for this specific
+driver. The bridge number (or bus number) can be accessed using
+dev->bridge->num.
A function is also provided to unregister the driver from the VME core and is
usually called from the device driver's exit routine:
@@ -59,9 +71,11 @@ usually called from the device driver's exit routine:
Resource management
===================
-Once a driver has registered with the VME core the provided probe routine will
-be called for each of the bus/slot combination that becomes valid as VME buses
-are themselves registered. The probe routine is passed a pointer to the devices
+Once a driver has registered with the VME core the provided match routine will
+be called the number of times specified during the registration. If a match
+succeeds, a non-zero value should be returned. A zero return value indicates
+failure. For all successful matches, the probe routine of the corresponding
+driver is called. The probe routine is passed a pointer to the devices
device structure. This pointer should be saved, it will be required for
requesting VME resources.
@@ -71,13 +85,13 @@ specific window or DMA channel (which may be used by a different driver) this
driver allows a resource to be assigned based on the required attributes of the
driver in question:
- struct vme_resource * vme_master_request(struct device *dev,
+ struct vme_resource * vme_master_request(struct vme_dev *dev,
vme_address_t aspace, vme_cycle_t cycle, vme_width_t width);
- struct vme_resource * vme_slave_request(struct device *dev,
+ struct vme_resource * vme_slave_request(struct vme_dev *dev,
vme_address_t aspace, vme_cycle_t cycle);
- struct vme_resource *vme_dma_request(struct device *dev,
+ struct vme_resource *vme_dma_request(struct vme_dev *dev,
vme_dma_route_t route);
For slave windows these attributes are split into those of type 'vme_address_t'
@@ -301,10 +315,10 @@ status ID combination. Any given combination can only be assigned a single
callback function. A void pointer parameter is provided, the value of which is
passed to the callback function, the use of this pointer is user undefined:
- int vme_irq_request(struct device *dev, int level, int statid,
+ int vme_irq_request(struct vme_dev *dev, int level, int statid,
void (*callback)(int, int, void *), void *priv);
- void vme_irq_free(struct device *dev, int level, int statid);
+ void vme_irq_free(struct vme_dev *dev, int level, int statid);
The callback parameters are as follows. Care must be taken in writing a callback
function, callback functions run in interrupt context:
@@ -318,7 +332,7 @@ Interrupt Generation
The following function can be used to generate a VME interrupt at a given VME
level and VME status ID:
- int vme_irq_generate(struct device *dev, int level, int statid);
+ int vme_irq_generate(struct vme_dev *dev, int level, int statid);
Location monitors
@@ -334,7 +348,7 @@ Location Monitor Management
The following functions are provided to request the use of a block of location
monitors and to free them after they are no longer required:
- struct vme_resource * vme_lm_request(struct device *dev);
+ struct vme_resource * vme_lm_request(struct vme_dev *dev);
void vme_lm_free(struct vme_resource * res);
@@ -380,4 +394,4 @@ Slot Detection
This function returns the slot ID of the provided bridge.
- int vme_slot_get(struct device *dev);
+ int vme_slot_get(struct vme_dev *dev);
diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h
index 4c6ec31..c2deda2 100644
--- a/drivers/staging/vme/vme_bridge.h
+++ b/drivers/staging/vme/vme_bridge.h
@@ -2,7 +2,6 @@
#define _VME_BRIDGE_H_
#define VME_CRCSR_BUF_SIZE (508*1024)
-#define VME_SLOTS_MAX 32
/*
* Resource structures
*/
@@ -98,8 +97,6 @@ struct vme_irq {
/* This structure stores all the information about one bridge
* The structure should be dynamically allocated by the driver and one instance
* of the structure should be present for each VME chip present in the system.
- *
- * Currently we assume that all chips are PCI-based
*/
struct vme_bridge {
char name[VMENAMSIZ];
@@ -110,14 +107,12 @@ struct vme_bridge {
struct list_head lm_resources;
struct list_head vme_errors; /* List for errors generated on VME */
+ struct list_head devices; /* List of devices on this bridge */
/* Bridge Info - XXX Move to private structure? */
- struct device *parent; /* Generic device struct (pdev->dev for PCI) */
+ struct device *parent; /* Parent device (eg. pdev->dev for PCI) */
void *driver_priv; /* Private pointer for the bridge driver */
-
- struct device dev[VME_SLOTS_MAX]; /* Device registered with
- * device model on VME bus
- */
+ struct list_head bus_list; /* list of VME buses */
/* Interrupt callbacks */
struct vme_irq irq[7];
@@ -165,6 +160,12 @@ struct vme_bridge {
/* CR/CSR space functions */
int (*slot_get) (struct vme_bridge *);
+
+ /* Bridge parent interface */
+ void *(*alloc_consistent)(struct device *dev, size_t size,
+ dma_addr_t *dma);
+ void (*free_consistent)(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma);
};
void vme_irq_handler(struct vme_bridge *, int, int);
diff --git a/drivers/staging/vt6655/IEEE11h.c b/drivers/staging/vt6655/IEEE11h.c
index e07ebd5..cf7364d 100644
--- a/drivers/staging/vt6655/IEEE11h.c
+++ b/drivers/staging/vt6655/IEEE11h.c
@@ -41,52 +41,52 @@
#include "channel.h"
/*--------------------- Static Definitions -------------------------*/
-static int msglevel =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
#pragma pack(1)
typedef struct _WLAN_FRAME_ACTION {
- WLAN_80211HDR_A3 Header;
- unsigned char byCategory;
- unsigned char byAction;
- unsigned char abyVars[1];
+ WLAN_80211HDR_A3 Header;
+ unsigned char byCategory;
+ unsigned char byAction;
+ unsigned char abyVars[1];
} WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION;
typedef struct _WLAN_FRAME_MSRREQ {
- WLAN_80211HDR_A3 Header;
- unsigned char byCategory;
- unsigned char byAction;
- unsigned char byDialogToken;
- WLAN_IE_MEASURE_REQ sMSRReqEIDs[1];
+ WLAN_80211HDR_A3 Header;
+ unsigned char byCategory;
+ unsigned char byAction;
+ unsigned char byDialogToken;
+ WLAN_IE_MEASURE_REQ sMSRReqEIDs[1];
} WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ;
typedef struct _WLAN_FRAME_MSRREP {
- WLAN_80211HDR_A3 Header;
- unsigned char byCategory;
- unsigned char byAction;
- unsigned char byDialogToken;
- WLAN_IE_MEASURE_REP sMSRRepEIDs[1];
+ WLAN_80211HDR_A3 Header;
+ unsigned char byCategory;
+ unsigned char byAction;
+ unsigned char byDialogToken;
+ WLAN_IE_MEASURE_REP sMSRRepEIDs[1];
} WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP;
typedef struct _WLAN_FRAME_TPCREQ {
- WLAN_80211HDR_A3 Header;
- unsigned char byCategory;
- unsigned char byAction;
- unsigned char byDialogToken;
- WLAN_IE_TPC_REQ sTPCReqEIDs;
+ WLAN_80211HDR_A3 Header;
+ unsigned char byCategory;
+ unsigned char byAction;
+ unsigned char byDialogToken;
+ WLAN_IE_TPC_REQ sTPCReqEIDs;
} WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ;
typedef struct _WLAN_FRAME_TPCREP {
- WLAN_80211HDR_A3 Header;
- unsigned char byCategory;
- unsigned char byAction;
- unsigned char byDialogToken;
- WLAN_IE_TPC_REP sTPCRepEIDs;
+ WLAN_80211HDR_A3 Header;
+ unsigned char byCategory;
+ unsigned char byAction;
+ unsigned char byDialogToken;
+ WLAN_IE_TPC_REP sTPCRepEIDs;
} WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP;
#pragma pack()
-// action field reference ieee 802.11h Table 20e
+/* action field reference ieee 802.11h Table 20e */
#define ACTION_MSRREQ 0
#define ACTION_MSRREP 1
#define ACTION_TPCREQ 2
@@ -101,84 +101,100 @@ typedef struct _WLAN_FRAME_TPCREP {
static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
unsigned int uLength)
{
- size_t uNumOfEIDs = 0;
- bool bResult = true;
-
- if (uLength <= WLAN_A3FR_MAXLEN) {
- memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
- }
- uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ, sMSRReqEIDs))/ (sizeof(WLAN_IE_MEASURE_REQ)));
- pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
- pMgmt->uLengthOfRepEIDs = 0;
- bResult = CARDbStartMeasure(pMgmt->pAdapter,
- ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
- uNumOfEIDs
- );
- return (bResult);
+ size_t uNumOfEIDs = 0;
+ bool bResult = true;
+
+ if (uLength <= WLAN_A3FR_MAXLEN)
+ memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
+ uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ,
+ sMSRReqEIDs))/
+ (sizeof(WLAN_IE_MEASURE_REQ)));
+ pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP)
+ (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
+ pMgmt->uLengthOfRepEIDs = 0;
+ bResult = CARDbStartMeasure(pMgmt->pAdapter,
+ ((PWLAN_FRAME_MSRREQ)
+ (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
+ uNumOfEIDs
+ );
+ return bResult;
}
-static bool s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, unsigned char byRate, unsigned char byRSSI)
+static bool s_bRxTPCReq(PSMgmtObject pMgmt,
+ PWLAN_FRAME_TPCREQ pTPCReq,
+ unsigned char byRate,
+ unsigned char byRSSI)
{
- PWLAN_FRAME_TPCREP pFrame;
- PSTxMgmtPacket pTxPacket = NULL;
-
-
- pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
- memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
- pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-
- pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-
- pFrame->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
- WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
- );
-
- memcpy( pFrame->Header.abyAddr1, pTPCReq->Header.abyAddr2, WLAN_ADDR_LEN);
- memcpy( pFrame->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
- memcpy( pFrame->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
- pFrame->byCategory = 0;
- pFrame->byAction = 3;
- pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken;
-
- pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
- pFrame->sTPCRepEIDs.len = 2;
- pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
- switch (byRate) {
- case RATE_54M:
- pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI;
- break;
- case RATE_48M:
- pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI;
- break;
- case RATE_36M:
- pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI;
- break;
- case RATE_24M:
- pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI;
- break;
- case RATE_18M:
- pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI;
- break;
- case RATE_12M:
- pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI;
- break;
- case RATE_9M:
- pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI;
- break;
- case RATE_6M:
- default:
- pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
- break;
- }
-
- pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
- pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - WLAN_HDR_ADDR3_LEN;
- if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
- return (false);
- return (true);
-// return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, sizeof(WLAN_FRAME_TPCREP)));
+ PWLAN_FRAME_TPCREP pFrame;
+ PSTxMgmtPacket pTxPacket = NULL;
+
+ pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+ memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
+ pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
+sizeof(STxMgmtPacket));
+
+ pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket +
+sizeof(STxMgmtPacket));
+
+ pFrame->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
+ WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
+ );
+
+ memcpy(pFrame->Header.abyAddr1,
+ pTPCReq->Header.abyAddr2,
+ WLAN_ADDR_LEN);
+ memcpy(pFrame->Header.abyAddr2,
+ CARDpGetCurrentAddress(pMgmt->pAdapter),
+ WLAN_ADDR_LEN);
+ memcpy(pFrame->Header.abyAddr3,
+ pMgmt->abyCurrBSSID,
+ WLAN_BSSID_LEN);
+
+ pFrame->byCategory = 0;
+ pFrame->byAction = 3;
+ pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ)
+(pMgmt->abyCurrentMSRReq))->byDialogToken;
+
+ pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
+ pFrame->sTPCRepEIDs.len = 2;
+ pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
+ switch (byRate) {
+ case RATE_54M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI;
+ break;
+ case RATE_48M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI;
+ break;
+ case RATE_36M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI;
+ break;
+ case RATE_24M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI;
+ break;
+ case RATE_18M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI;
+ break;
+ case RATE_12M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI;
+ break;
+ case RATE_9M:
+ pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI;
+ break;
+ case RATE_6M:
+ default:
+ pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
+ break;
+}
+
+ pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
+ pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) -
+WLAN_HDR_ADDR3_LEN;
+ if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
+ return false;
+ return true;
+/* return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG,
+sizeof(WLAN_FRAME_TPCREP))); */
}
@@ -204,102 +220,110 @@ static bool s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, unsigned
*
-*/
bool
-IEEE11hbMgrRxAction (
- void *pMgmtHandle,
- void *pRxPacket
- )
+IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket)
{
- PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle;
- PWLAN_FRAME_ACTION pAction = NULL;
- unsigned int uLength = 0;
- PWLAN_IE_CH_SW pChannelSwitch = NULL;
-
-
- // decode the frame
- uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen;
- if (uLength > WLAN_A3FR_MAXLEN) {
- return (false);
- }
-
-
- pAction = (PWLAN_FRAME_ACTION) (((PSRxMgmtPacket)pRxPacket)->p80211Header);
-
- if (pAction->byCategory == 0) {
- switch (pAction->byAction) {
- case ACTION_MSRREQ:
- return (s_bRxMSRReq(pMgmt, (PWLAN_FRAME_MSRREQ) pAction, uLength));
- break;
- case ACTION_MSRREP:
- break;
- case ACTION_TPCREQ:
- return (s_bRxTPCReq(pMgmt,
- (PWLAN_FRAME_TPCREQ) pAction,
- ((PSRxMgmtPacket)pRxPacket)->byRxRate,
- (unsigned char) ((PSRxMgmtPacket)pRxPacket)->uRSSI));
- break;
- case ACTION_TPCREP:
- break;
- case ACTION_CHSW:
- pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
- if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) &&
- (pChannelSwitch->len == 3)) {
- // valid element id
- CARDbChannelSwitch( pMgmt->pAdapter,
- pChannelSwitch->byMode,
- get_channel_mapping(pMgmt->pAdapter, pChannelSwitch->byChannel, pMgmt->eCurrentPHYMode),
- pChannelSwitch->byCount
- );
- }
- break;
- default:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Action = %d\n", pAction->byAction);
- break;
- }
- } else {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", pAction->byCategory);
- pAction->byCategory |= 0x80;
-
- //return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, uLength));
- return (true);
- }
- return (true);
+ PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle;
+ PWLAN_FRAME_ACTION pAction = NULL;
+ unsigned int uLength = 0;
+ PWLAN_IE_CH_SW pChannelSwitch = NULL;
+
+ /* decode the frame */
+ uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen;
+ if (uLength > WLAN_A3FR_MAXLEN)
+ return false;
+
+ pAction = (PWLAN_FRAME_ACTION)
+(((PSRxMgmtPacket)pRxPacket)->p80211Header);
+
+ if (pAction->byCategory == 0) {
+ switch (pAction->byAction) {
+ case ACTION_MSRREQ:
+ return s_bRxMSRReq(pMgmt,
+ (PWLAN_FRAME_MSRREQ)
+ pAction,
+ uLength);
+ break;
+ case ACTION_MSRREP:
+ break;
+ case ACTION_TPCREQ:
+ return s_bRxTPCReq(pMgmt,
+ (PWLAN_FRAME_TPCREQ) pAction,
+ ((PSRxMgmtPacket)pRxPacket)->byRxRate,
+ (unsigned char)
+ ((PSRxMgmtPacket)pRxPacket)->uRSSI);
+ break;
+ case ACTION_TPCREP:
+ break;
+ case ACTION_CHSW:
+ pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
+ if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH)
+ && (pChannelSwitch->len == 3)) {
+ /* valid element id */
+ CARDbChannelSwitch(pMgmt->pAdapter,
+ pChannelSwitch->byMode,
+ get_channel_mapping(pMgmt->pAdapter,
+ pChannelSwitch->byChannel,
+ pMgmt->eCurrentPHYMode),
+ pChannelSwitch->byCount);
+ }
+ break;
+ default:
+ DBG_PRT(MSG_LEVEL_DEBUG,
+ KERN_INFO"Unknown Action = %d\n",
+ pAction->byAction);
+ break;
+ }
+ } else {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n",
+pAction->byCategory);
+ pAction->byCategory |= 0x80;
+
+ /*return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG,
+uLength));*/
+ return true;
+ }
+ return true;
}
-bool IEEE11hbMSRRepTx (
- void *pMgmtHandle
- )
+bool IEEE11hbMSRRepTx(void *pMgmtHandle)
{
- PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle;
- PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
- size_t uLength = 0;
- PSTxMgmtPacket pTxPacket = NULL;
-
- pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
- memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
- pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-
-
- pMSRRep->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
- WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
- );
-
- memcpy( pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
- memcpy( pMSRRep->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
- memcpy( pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
- pMSRRep->byCategory = 0;
- pMSRRep->byAction = 1;
- pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken;
-
- uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP, sMSRRepEIDs);
-
- pTxPacket->cbMPDULen = uLength;
- pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN;
- if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
- return (false);
- return (true);
-// return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, uLength));
+ PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle;
+ PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP)
+(pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
+ size_t uLength = 0;
+ PSTxMgmtPacket pTxPacket = NULL;
+
+ pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
+ memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
+ pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
+sizeof(STxMgmtPacket));
+
+ pMSRRep->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
+ WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
+ );
+
+ memcpy(pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ)
+ (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
+ memcpy(pMSRRep->Header.abyAddr2,
+ CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
+ memcpy(pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+ pMSRRep->byCategory = 0;
+ pMSRRep->byAction = 1;
+ pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ)
+ (pMgmt->abyCurrentMSRReq))->byDialogToken;
+
+ uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP,
+ sMSRRepEIDs);
+
+ pTxPacket->cbMPDULen = uLength;
+ pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN;
+ if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
+ return false;
+ return true;
+/* return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG,
+uLength)); */
}
diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c
index 577599e..ed4259c 100644
--- a/drivers/staging/vt6655/bssdb.c
+++ b/drivers/staging/vt6655/bssdb.c
@@ -1083,7 +1083,7 @@ start:
pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1));
}
-{
+ if (pDevice->eCommandState == WLAN_ASSOCIATE_WAIT) {
pDevice->byReAssocCount++;
if((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) { //10 sec timeout
printk("Re-association timeout!!!\n");
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 3d2a9ba..077c506 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -815,14 +815,8 @@ else CARDbRadioPowerOn(pDevice);
pMgmt->eScanType = WMAC_SCAN_PASSIVE;
// get Permanent network address
SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %02x-%02x-%02x=%02x-%02x-%02x\n",
- pDevice->abyCurrentNetAddr[0],
- pDevice->abyCurrentNetAddr[1],
- pDevice->abyCurrentNetAddr[2],
- pDevice->abyCurrentNetAddr[3],
- pDevice->abyCurrentNetAddr[4],
- pDevice->abyCurrentNetAddr[5]);
-
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n",
+ pDevice->abyCurrentNetAddr);
// reset Tx pointer
CARDvSafeResetRx(pDevice);
@@ -911,7 +905,7 @@ static const struct net_device_ops device_netdev_ops = {
.ndo_do_ioctl = device_ioctl,
.ndo_get_stats = device_get_stats,
.ndo_start_xmit = device_xmit,
- .ndo_set_multicast_list = device_set_multi,
+ .ndo_set_rx_mode = device_set_multi,
};
@@ -1608,6 +1602,10 @@ static int device_rx_srv(PSDevice pDevice, unsigned int uIdx) {
// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->pCurrRD = %x, works = %d\n", pRD, works);
if (works++>15)
break;
+
+ if (!pRD->pRDInfo->skb)
+ break;
+
if (device_receive_frame(pDevice, pRD)) {
if (!device_alloc_rx_buf(pDevice,pRD)) {
DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
@@ -2685,6 +2683,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) {
unsigned char byData = 0;
int ii= 0;
// unsigned char byRSSI;
+ unsigned long flags;
MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
@@ -2710,7 +2709,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) {
handled = 1;
MACvIntDisable(pDevice->PortOffset);
- spin_lock_irq(&pDevice->lock);
+
+ spin_lock_irqsave(&pDevice->lock, flags);
//Make sure current page is 0
VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
@@ -2958,7 +2958,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) {
MACvSelectPage1(pDevice->PortOffset);
}
- spin_unlock_irq(&pDevice->lock);
+ spin_unlock_irqrestore(&pDevice->lock, flags);
+
MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
return IRQ_RETVAL(handled);
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
index cf0deac..c0fab4b 100644
--- a/drivers/staging/vt6655/dpc.c
+++ b/drivers/staging/vt6655/dpc.c
@@ -1107,30 +1107,12 @@ static bool s_bAPModeRxCtl (
&Status
);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n");
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%02x-%02x-%02x=%02x-%02x-%02x \n",
- p802_11Header->abyAddr3[0],
- p802_11Header->abyAddr3[1],
- p802_11Header->abyAddr3[2],
- p802_11Header->abyAddr3[3],
- p802_11Header->abyAddr3[4],
- p802_11Header->abyAddr3[5]
- );
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%02x-%02x-%02x=%02x-%02x-%02x \n",
- p802_11Header->abyAddr2[0],
- p802_11Header->abyAddr2[1],
- p802_11Header->abyAddr2[2],
- p802_11Header->abyAddr2[3],
- p802_11Header->abyAddr2[4],
- p802_11Header->abyAddr2[5]
- );
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%02x-%02x-%02x=%02x-%02x-%02x \n",
- p802_11Header->abyAddr1[0],
- p802_11Header->abyAddr1[1],
- p802_11Header->abyAddr1[2],
- p802_11Header->abyAddr1[3],
- p802_11Header->abyAddr1[4],
- p802_11Header->abyAddr1[5]
- );
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n",
+ p802_11Header->abyAddr3);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n",
+ p802_11Header->abyAddr2);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n",
+ p802_11Header->abyAddr1);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl );
VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc:pDevice->byRxMode = %x\n", pDevice->byRxMode );
diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c
index 8cf88c3..432a209 100644
--- a/drivers/staging/vt6655/ioctl.c
+++ b/drivers/staging/vt6655/ioctl.c
@@ -38,715 +38,617 @@
#include "wpactl.h"
#include "rf.h"
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-//static int msglevel =MSG_LEVEL_DEBUG;
-static int msglevel =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
#ifdef WPA_SM_Transtatus
- SWPAResult wpa_Result;
+ SWPAResult wpa_Result;
#endif
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-int private_ioctl(PSDevice pDevice, struct ifreq *rq) {
-
- PSCmdRequest pReq = (PSCmdRequest)rq;
- PSMgmtObject pMgmt = pDevice->pMgmt;
- int result = 0;
- PWLAN_IE_SSID pItemSSID;
- SCmdBSSJoin sJoinCmd;
- SCmdZoneTypeSet sZoneTypeCmd;
- SCmdScan sScanCmd;
- SCmdStartAP sStartAPCmd;
- SCmdSetWEP sWEPCmd;
- SCmdValue sValue;
- SBSSIDList sList;
- SNodeList sNodeList;
- PSBSSIDList pList;
- PSNodeList pNodeList;
- unsigned int cbListCount;
- PKnownBSS pBSS;
- PKnownNodeDB pNode;
- unsigned int ii, jj;
- SCmdLinkStatus sLinkStatus;
- unsigned char abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
- unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- unsigned long dwKeyIndex= 0;
- unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
- long ldBm;
-
- pReq->wResult = 0;
-
- switch (pReq->wCmdCode) {
-
- case WLAN_CMD_BSS_SCAN:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin \n");
- if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) {
+int private_ioctl(PSDevice pDevice, struct ifreq *rq)
+{
+ PSCmdRequest pReq = (PSCmdRequest)rq;
+ PSMgmtObject pMgmt = pDevice->pMgmt;
+ int result = 0;
+ PWLAN_IE_SSID pItemSSID;
+ SCmdBSSJoin sJoinCmd;
+ SCmdZoneTypeSet sZoneTypeCmd;
+ SCmdScan sScanCmd;
+ SCmdStartAP sStartAPCmd;
+ SCmdSetWEP sWEPCmd;
+ SCmdValue sValue;
+ SBSSIDList sList;
+ SNodeList sNodeList;
+ PSBSSIDList pList;
+ PSNodeList pNodeList;
+ unsigned int cbListCount;
+ PKnownBSS pBSS;
+ PKnownNodeDB pNode;
+ unsigned int ii, jj;
+ SCmdLinkStatus sLinkStatus;
+ unsigned char abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
+ unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned long dwKeyIndex = 0;
+ unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+ long ldBm;
+
+ pReq->wResult = 0;
+
+ switch (pReq->wCmdCode) {
+ case WLAN_CMD_BSS_SCAN:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin\n");
+ if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) {
result = -EFAULT;
break;
}
- pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid;
- if (pItemSSID->len != 0) {
- memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
- memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
- }
-
- if (pDevice->bMACSuspend == true) {
- if (pDevice->bRadioOff == true)
- CARDbRadioPowerOn(pDevice);
- vMgrTimerInit(pDevice);
- MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
- add_timer(&pMgmt->sTimerSecondCallback);
- pDevice->bMACSuspend = false;
- }
- spin_lock_irq(&pDevice->lock);
- if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0)
- BSSvClearBSSList((void *)pDevice, false);
- else
- BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
-
- if (pItemSSID->len != 0)
- bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
- else
- bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
- spin_unlock_irq(&pDevice->lock);
- break;
-
- case WLAN_CMD_ZONETYPE_SET:
- //mike add :cann't support.
- result=-EOPNOTSUPP;
- break;
-
- if (copy_from_user(&sZoneTypeCmd, pReq->data, sizeof(SCmdZoneTypeSet))) {
- result = -EFAULT;
- break;
+ pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid;
+ if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
+ return -EINVAL;
+ if (pItemSSID->len != 0) {
+ memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+ memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
+ }
+
+ if (pDevice->bMACSuspend == true) {
+ if (pDevice->bRadioOff == true)
+ CARDbRadioPowerOn(pDevice);
+ vMgrTimerInit(pDevice);
+ MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
+ add_timer(&pMgmt->sTimerSecondCallback);
+ pDevice->bMACSuspend = false;
}
+ spin_lock_irq(&pDevice->lock);
+ if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0)
+ BSSvClearBSSList((void *)pDevice, false);
+ else
+ BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+
+ if (pItemSSID->len != 0)
+ bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
+ else
+ bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+ spin_unlock_irq(&pDevice->lock);
+ break;
- if(sZoneTypeCmd.bWrite==true) {
- //////write zonetype
- if(sZoneTypeCmd.ZoneType == ZoneType_USA) {
- //set to USA
- printk("set_ZoneType:USA\n");
- }
- else if(sZoneTypeCmd.ZoneType == ZoneType_Japan) {
- //set to Japan
- printk("set_ZoneType:Japan\n");
- }
- else if(sZoneTypeCmd.ZoneType == ZoneType_Europe) {
- //set to Europe
- printk("set_ZoneType:Europe\n");
- }
- }
- else {
- ///////read zonetype
- unsigned char zonetype=0;
-
-
- if(zonetype == 0x00) { //USA
- sZoneTypeCmd.ZoneType = ZoneType_USA;
- }
- else if(zonetype == 0x01) { //Japan
- sZoneTypeCmd.ZoneType = ZoneType_Japan;
- }
- else if(zonetype == 0x02) { //Europe
- sZoneTypeCmd.ZoneType = ZoneType_Europe;
- }
- else { //Unknown ZoneType
- printk("Error:ZoneType[%x] Unknown ???\n",zonetype);
- result = -EFAULT;
+ case WLAN_CMD_ZONETYPE_SET:
+ /* mike add :cann't support. */
+ result = -EOPNOTSUPP;
break;
- }
- if (copy_to_user(pReq->data, &sZoneTypeCmd, sizeof(SCmdZoneTypeSet))) {
+
+ if (copy_from_user(&sZoneTypeCmd, pReq->data, sizeof(SCmdZoneTypeSet))) {
result = -EFAULT;
break;
}
- }
- break;
-
- case WLAN_CMD_BSS_JOIN:
+ if (sZoneTypeCmd.bWrite == true) {
+ /* write zonetype */
+ if (sZoneTypeCmd.ZoneType == ZoneType_USA) {
+ /* set to USA */
+ printk("set_ZoneType:USA\n");
+ } else if (sZoneTypeCmd.ZoneType == ZoneType_Japan) {
+ /* set to Japan */
+ printk("set_ZoneType:Japan\n");
+ } else if (sZoneTypeCmd.ZoneType == ZoneType_Europe) {
+ /* set to Europe */
+ printk("set_ZoneType:Europe\n");
+ }
+ } else {
+ /* read zonetype */
+ unsigned char zonetype = 0;
+
+ if (zonetype == 0x00) { /* USA */
+ sZoneTypeCmd.ZoneType = ZoneType_USA;
+ } else if (zonetype == 0x01) { /* Japan */
+ sZoneTypeCmd.ZoneType = ZoneType_Japan;
+ } else if (zonetype == 0x02) { /* Europe */
+ sZoneTypeCmd.ZoneType = ZoneType_Europe;
+ } else { /* Unknown ZoneType */
+ printk("Error:ZoneType[%x] Unknown ???\n", zonetype);
+ result = -EFAULT;
+ break;
+ }
+ if (copy_to_user(pReq->data, &sZoneTypeCmd, sizeof(SCmdZoneTypeSet))) {
+ result = -EFAULT;
+ break;
+ }
+ }
+ break;
- if (pDevice->bMACSuspend == true) {
- if (pDevice->bRadioOff == true)
- CARDbRadioPowerOn(pDevice);
- vMgrTimerInit(pDevice);
- MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
- add_timer(&pMgmt->sTimerSecondCallback);
- pDevice->bMACSuspend = false;
- }
+ case WLAN_CMD_BSS_JOIN:
+ if (pDevice->bMACSuspend == true) {
+ if (pDevice->bRadioOff == true)
+ CARDbRadioPowerOn(pDevice);
+ vMgrTimerInit(pDevice);
+ MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
+ add_timer(&pMgmt->sTimerSecondCallback);
+ pDevice->bMACSuspend = false;
+ }
- if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) {
+ if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) {
result = -EFAULT;
break;
}
- pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid;
- memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+ pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid;
+ if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
+ return -EINVAL;
+ memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
- if (sJoinCmd.wBSSType == ADHOC) {
- pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to adhoc mode\n");
- }
- else {
- pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to STA mode\n");
- }
- if (sJoinCmd.bPSEnable == true) {
- pDevice->ePSMode = WMAC_POWER_FAST;
-// pDevice->ePSMode = WMAC_POWER_MAX;
- pMgmt->wListenInterval = 2;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving On\n");
- }
- else {
- pDevice->ePSMode = WMAC_POWER_CAM;
- pMgmt->wListenInterval = 1;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving Off \n");
- }
-
- if (sJoinCmd.bShareKeyAuth == true){
- pMgmt->bShareKeyAlgorithm = true;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key \n");
- }
- else {
- pMgmt->bShareKeyAlgorithm = false;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System \n");
- }
- pDevice->uChannel = sJoinCmd.uChannel;
- netif_stop_queue(pDevice->dev);
- spin_lock_irq(&pDevice->lock);
- pMgmt->eCurrState = WMAC_STATE_IDLE;
- bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
- bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
- spin_unlock_irq(&pDevice->lock);
- break;
-
- case WLAN_CMD_SET_WEP:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WEP Key. \n");
- memset(&sWEPCmd, 0 ,sizeof(SCmdSetWEP));
- if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) {
+ if (sJoinCmd.wBSSType == ADHOC) {
+ pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to adhoc mode\n");
+ } else {
+ pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to STA mode\n");
+ }
+ if (sJoinCmd.bPSEnable == true) {
+ pDevice->ePSMode = WMAC_POWER_FAST;
+ pMgmt->wListenInterval = 2;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving On\n");
+ } else {
+ pDevice->ePSMode = WMAC_POWER_CAM;
+ pMgmt->wListenInterval = 1;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving Off\n");
+ }
+
+ if (sJoinCmd.bShareKeyAuth == true) {
+ pMgmt->bShareKeyAlgorithm = true;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key\n");
+ } else {
+ pMgmt->bShareKeyAlgorithm = false;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System\n");
+ }
+ pDevice->uChannel = sJoinCmd.uChannel;
+ netif_stop_queue(pDevice->dev);
+ spin_lock_irq(&pDevice->lock);
+ pMgmt->eCurrState = WMAC_STATE_IDLE;
+ bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+ bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
+ spin_unlock_irq(&pDevice->lock);
+ break;
+
+ case WLAN_CMD_SET_WEP:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WEP Key.\n");
+ memset(&sWEPCmd, 0, sizeof(SCmdSetWEP));
+ if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) {
result = -EFAULT;
break;
}
- if (sWEPCmd.bEnableWep != true) {
- pDevice->bEncryptionEnable = false;
- pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
- MACvDisableDefaultKey(pDevice->PortOffset);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable. \n");
- break;
- }
-
- for (ii = 0; ii < WLAN_WEP_NKEYS; ii ++) {
- if (sWEPCmd.bWepKeyAvailable[ii]) {
- if (ii == sWEPCmd.byKeyIndex)
- //2006-1123-02,<Modify> by EinsnLiu
- //Evaluate the "dwKeyIndex" error
- // dwKeyIndex |= (1 << 31);
- dwKeyIndex =ii|(1 << 31);
- else
- dwKeyIndex = ii;
-
- KeybSetDefaultKey(&(pDevice->sKey),
- dwKeyIndex,
- sWEPCmd.auWepKeyLength[ii],
- NULL,
- (unsigned char *)&sWEPCmd.abyWepKey[ii][0],
- KEY_CTL_WEP,
- pDevice->PortOffset,
- pDevice->byLocalID);
- }
- }
- pDevice->byKeyIndex = sWEPCmd.byKeyIndex;
- pDevice->bTransmitKey = true;
- pDevice->bEncryptionEnable = true;
- pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-
- break;
-
- case WLAN_CMD_GET_LINK:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_GET_LINK status. \n");
-
- memset(sLinkStatus.abySSID, 0 , WLAN_SSID_MAXLEN + 1);
-
- if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
- sLinkStatus.wBSSType = ADHOC;
- else
- sLinkStatus.wBSSType = INFRA;
-
- if (pMgmt->eCurrState == WMAC_STATE_JOINTED)
- sLinkStatus.byState = ADHOC_JOINTED;
- else
- sLinkStatus.byState = ADHOC_STARTED;
-
- sLinkStatus.uChannel = pMgmt->uCurrChannel;
- if (pDevice->bLinkPass == true) {
- sLinkStatus.bLink = true;
- pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
- memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len);
- memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
- sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Link Success ! \n");
- }
- else {
- sLinkStatus.bLink = false;
- }
- if (copy_to_user(pReq->data, &sLinkStatus, sizeof(SCmdLinkStatus))) {
- result = -EFAULT;
+ if (sWEPCmd.bEnableWep != true) {
+ pDevice->bEncryptionEnable = false;
+ pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+ MACvDisableDefaultKey(pDevice->PortOffset);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable.\n");
break;
}
- break;
+ for (ii = 0; ii < WLAN_WEP_NKEYS; ii++) {
+ if (sWEPCmd.bWepKeyAvailable[ii]) {
+ if (ii == sWEPCmd.byKeyIndex)
+ dwKeyIndex = ii | (1 << 31);
+ else
+ dwKeyIndex = ii;
+
+ KeybSetDefaultKey(&(pDevice->sKey),
+ dwKeyIndex,
+ sWEPCmd.auWepKeyLength[ii],
+ NULL,
+ (unsigned char *)&sWEPCmd.abyWepKey[ii][0],
+ KEY_CTL_WEP,
+ pDevice->PortOffset,
+ pDevice->byLocalID);
+ }
+ }
+ pDevice->byKeyIndex = sWEPCmd.byKeyIndex;
+ pDevice->bTransmitKey = true;
+ pDevice->bEncryptionEnable = true;
+ pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+ break;
- case WLAN_CMD_GET_LISTLEN:
+ case WLAN_CMD_GET_LINK:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_GET_LINK status.\n");
+
+ memset(sLinkStatus.abySSID, 0 , WLAN_SSID_MAXLEN + 1);
+
+ if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
+ sLinkStatus.wBSSType = ADHOC;
+ else
+ sLinkStatus.wBSSType = INFRA;
+
+ if (pMgmt->eCurrState == WMAC_STATE_JOINTED)
+ sLinkStatus.byState = ADHOC_JOINTED;
+ else
+ sLinkStatus.byState = ADHOC_STARTED;
+
+ sLinkStatus.uChannel = pMgmt->uCurrChannel;
+ if (pDevice->bLinkPass == true) {
+ sLinkStatus.bLink = true;
+ pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+ memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len);
+ memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+ sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Link Success!\n");
+ } else {
+ sLinkStatus.bLink = false;
+ sLinkStatus.uLinkRate = 0;
+ }
+ if (copy_to_user(pReq->data, &sLinkStatus, sizeof(SCmdLinkStatus))) {
+ result = -EFAULT;
+ break;
+ }
+ break;
+
+ case WLAN_CMD_GET_LISTLEN:
cbListCount = 0;
pBSS = &(pMgmt->sBSSList[0]);
- for (ii = 0; ii < MAX_BSS_NUM; ii++) {
- pBSS = &(pMgmt->sBSSList[ii]);
- if (!pBSS->bActive)
- continue;
- cbListCount++;
- }
- sList.uItem = cbListCount;
- if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) {
+ for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+ pBSS = &(pMgmt->sBSSList[ii]);
+ if (!pBSS->bActive)
+ continue;
+ cbListCount++;
+ }
+ sList.uItem = cbListCount;
+ if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) {
result = -EFAULT;
break;
}
- pReq->wResult = 0;
- break;
+ pReq->wResult = 0;
+ break;
- case WLAN_CMD_GET_LIST:
- if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) {
+ case WLAN_CMD_GET_LIST:
+ if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) {
result = -EFAULT;
break;
}
- pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
- if (pList == NULL) {
- result = -ENOMEM;
- break;
- }
+ pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
+ if (pList == NULL) {
+ result = -ENOMEM;
+ break;
+ }
pList->uItem = sList.uItem;
pBSS = &(pMgmt->sBSSList[0]);
- for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
- pBSS = &(pMgmt->sBSSList[jj]);
- if (pBSS->bActive) {
- pList->sBSSIDList[ii].uChannel = pBSS->uChannel;
- pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval;
- pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo;
-// pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI;
- RFvRSSITodBm(pDevice, (unsigned char)(pBSS->uRSSI), &ldBm);
- pList->sBSSIDList[ii].uRSSI = (unsigned int)ldBm;
- memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN);
- pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
- memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1);
- memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len);
- if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
- pList->sBSSIDList[ii].byNetType = INFRA;
- }
- else {
- pList->sBSSIDList[ii].byNetType = ADHOC;
- }
- if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
- pList->sBSSIDList[ii].bWEPOn = true;
- }
- else {
- pList->sBSSIDList[ii].bWEPOn = false;
- }
- ii ++;
- if (ii >= pList->uItem)
- break;
- }
- }
-
- if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) {
+ for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
+ pBSS = &(pMgmt->sBSSList[jj]);
+ if (pBSS->bActive) {
+ pList->sBSSIDList[ii].uChannel = pBSS->uChannel;
+ pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval;
+ pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo;
+ /* pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI; */
+ RFvRSSITodBm(pDevice, (unsigned char)(pBSS->uRSSI), &ldBm);
+ pList->sBSSIDList[ii].uRSSI = (unsigned int)ldBm;
+ memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN);
+ pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
+ memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1);
+ memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len);
+ if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
+ pList->sBSSIDList[ii].byNetType = INFRA;
+ } else {
+ pList->sBSSIDList[ii].byNetType = ADHOC;
+ }
+ if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
+ pList->sBSSIDList[ii].bWEPOn = true;
+ } else {
+ pList->sBSSIDList[ii].bWEPOn = false;
+ }
+ ii++;
+ if (ii >= pList->uItem)
+ break;
+ }
+ }
+
+ if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) {
result = -EFAULT;
break;
}
- kfree(pList);
- pReq->wResult = 0;
- break;
+ kfree(pList);
+ pReq->wResult = 0;
+ break;
- case WLAN_CMD_GET_MIB:
- if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) {
+ case WLAN_CMD_GET_MIB:
+ if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) {
result = -EFAULT;
break;
}
- break;
+ break;
- case WLAN_CMD_GET_STAT:
- if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) {
+ case WLAN_CMD_GET_STAT:
+ if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) {
result = -EFAULT;
break;
}
- break;
- case WLAN_CMD_STOP_MAC:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n");
- netif_stop_queue(pDevice->dev);
-
- spin_lock_irq(&pDevice->lock);
- if (pDevice->bRadioOff == false) {
- CARDbRadioPowerOff(pDevice);
- }
- pDevice->bLinkPass = false;
- memset(pMgmt->abyCurrBSSID, 0, 6);
- pMgmt->eCurrState = WMAC_STATE_IDLE;
- del_timer(&pDevice->sTimerCommand);
- del_timer(&pMgmt->sTimerSecondCallback);
- pDevice->bCmdRunning = false;
- pDevice->bMACSuspend = true;
- MACvIntDisable(pDevice->PortOffset);
- spin_unlock_irq(&pDevice->lock);
-
- break;
+ break;
- case WLAN_CMD_START_MAC:
+ case WLAN_CMD_STOP_MAC:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n");
+ netif_stop_queue(pDevice->dev);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_START_MAC\n");
+ spin_lock_irq(&pDevice->lock);
+ if (pDevice->bRadioOff == false) {
+ CARDbRadioPowerOff(pDevice);
+ }
+ pDevice->bLinkPass = false;
+ memset(pMgmt->abyCurrBSSID, 0, 6);
+ pMgmt->eCurrState = WMAC_STATE_IDLE;
+ del_timer(&pDevice->sTimerCommand);
+ del_timer(&pMgmt->sTimerSecondCallback);
+ pDevice->bCmdRunning = false;
+ pDevice->bMACSuspend = true;
+ MACvIntDisable(pDevice->PortOffset);
+ spin_unlock_irq(&pDevice->lock);
+ break;
- if (pDevice->bMACSuspend == true) {
- if (pDevice->bRadioOff == true)
- CARDbRadioPowerOn(pDevice);
- vMgrTimerInit(pDevice);
- MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
- add_timer(&pMgmt->sTimerSecondCallback);
- pDevice->bMACSuspend = false;
- }
- break;
+ case WLAN_CMD_START_MAC:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_START_MAC\n");
- case WLAN_CMD_SET_HOSTAPD:
+ if (pDevice->bMACSuspend == true) {
+ if (pDevice->bRadioOff == true)
+ CARDbRadioPowerOn(pDevice);
+ vMgrTimerInit(pDevice);
+ MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
+ add_timer(&pMgmt->sTimerSecondCallback);
+ pDevice->bMACSuspend = false;
+ }
+ break;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD\n");
+ case WLAN_CMD_SET_HOSTAPD:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- if (vt6655_hostap_set_hostapd(pDevice, 1, 1) == 0){
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HOSTAP\n");
- }
- else {
- result = -EFAULT;
- break;
+ if (vt6655_hostap_set_hostapd(pDevice, 1, 1) == 0) {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HOSTAP\n");
+ } else {
+ result = -EFAULT;
+ break;
}
- }
- else {
- vt6655_hostap_set_hostapd(pDevice, 0, 1);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HOSTAP\n");
- }
-
- break;
-
- case WLAN_CMD_SET_HOSTAPD_STA:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD_STA\n");
+ } else {
+ vt6655_hostap_set_hostapd(pDevice, 0, 1);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HOSTAP\n");
+ }
+ break;
- break;
- case WLAN_CMD_SET_802_1X:
+ case WLAN_CMD_SET_HOSTAPD_STA:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD_STA\n");
+ break;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_802_1X\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ case WLAN_CMD_SET_802_1X:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_802_1X\n");
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- pDevice->bEnable8021x = true;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable 802.1x\n");
- }
- else {
- pDevice->bEnable8021x = false;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable 802.1x\n");
- }
-
- break;
-
-
- case WLAN_CMD_SET_HOST_WEP:
+ pDevice->bEnable8021x = true;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable 802.1x\n");
+ } else {
+ pDevice->bEnable8021x = false;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable 802.1x\n");
+ }
+ break;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOST_WEP\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ case WLAN_CMD_SET_HOST_WEP:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOST_WEP\n");
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- pDevice->bEnableHostWEP = true;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HostWEP\n");
- }
- else {
- pDevice->bEnableHostWEP = false;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HostWEP\n");
- }
-
- break;
+ pDevice->bEnableHostWEP = true;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HostWEP\n");
+ } else {
+ pDevice->bEnableHostWEP = false;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HostWEP\n");
+ }
+ break;
- case WLAN_CMD_SET_WPA:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WPA\n");
+ case WLAN_CMD_SET_WPA:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WPA\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "up wpadev\n");
- memcpy(pDevice->wpadev->dev_addr, pDevice->dev->dev_addr, ETH_ALEN);
- pDevice->bWPADEVUp = true;
- }
- else {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "close wpadev\n");
- pDevice->bWPADEVUp = false;
- }
-
- break;
-
- case WLAN_CMD_AP_START:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_AP_START\n");
- if (pDevice->bRadioOff == true) {
- CARDbRadioPowerOn(pDevice);
- vMgrTimerInit(pDevice);
- MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
- add_timer(&pMgmt->sTimerSecondCallback);
- }
- if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "up wpadev\n");
+ memcpy(pDevice->wpadev->dev_addr, pDevice->dev->dev_addr, ETH_ALEN);
+ pDevice->bWPADEVUp = true;
+ } else {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "close wpadev\n");
+ pDevice->bWPADEVUp = false;
+ }
+ break;
+
+ case WLAN_CMD_AP_START:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_AP_START\n");
+ if (pDevice->bRadioOff == true) {
+ CARDbRadioPowerOn(pDevice);
+ vMgrTimerInit(pDevice);
+ MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
+ add_timer(&pMgmt->sTimerSecondCallback);
+ }
+ if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) {
result = -EFAULT;
break;
}
- if (sStartAPCmd.wBSSType == AP) {
- pMgmt->eConfigMode = WMAC_CONFIG_AP;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to AP mode\n");
- }
- else {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct BSS type not set to AP mode\n");
+ if (sStartAPCmd.wBSSType == AP) {
+ pMgmt->eConfigMode = WMAC_CONFIG_AP;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to AP mode\n");
+ } else {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct BSS type not set to AP mode\n");
result = -EFAULT;
break;
- }
-
+ }
- if (sStartAPCmd.wBBPType == PHY80211g) {
- pMgmt->byAPBBType = PHY_TYPE_11G;
- }
- else if (sStartAPCmd.wBBPType == PHY80211a) {
- pMgmt->byAPBBType = PHY_TYPE_11A;
- }
- else {
- pMgmt->byAPBBType = PHY_TYPE_11B;
- }
+ if (sStartAPCmd.wBBPType == PHY80211g) {
+ pMgmt->byAPBBType = PHY_TYPE_11G;
+ } else if (sStartAPCmd.wBBPType == PHY80211a) {
+ pMgmt->byAPBBType = PHY_TYPE_11A;
+ } else {
+ pMgmt->byAPBBType = PHY_TYPE_11B;
+ }
- pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid;
- memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+ pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid;
+ if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
+ return -EINVAL;
+ memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
- if ((sStartAPCmd.uChannel > 0)&&(sStartAPCmd.uChannel <= 14))
- pDevice->uChannel = sStartAPCmd.uChannel;
-
- if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000))
- pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt;
- else
- pMgmt->wIBSSBeaconPeriod = 100;
-
- if (sStartAPCmd.bShareKeyAuth == true){
- pMgmt->bShareKeyAlgorithm = true;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key \n");
- }
- else {
- pMgmt->bShareKeyAlgorithm = false;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System \n");
- }
- memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6);
-
- if (sStartAPCmd.byBasicRate & BIT3) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- pMgmt->abyIBSSSuppRates[4] |= BIT7;
- pMgmt->abyIBSSSuppRates[5] |= BIT7;
- }else if (sStartAPCmd.byBasicRate & BIT2) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- pMgmt->abyIBSSSuppRates[4] |= BIT7;
- }else if (sStartAPCmd.byBasicRate & BIT1) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- }else if (sStartAPCmd.byBasicRate & BIT1) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- }else {
- //default 1,2M
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- }
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n",
- pMgmt->abyIBSSSuppRates[2],
- pMgmt->abyIBSSSuppRates[3],
- pMgmt->abyIBSSSuppRates[4],
- pMgmt->abyIBSSSuppRates[5]
- );
-
- netif_stop_queue(pDevice->dev);
- spin_lock_irq(&pDevice->lock);
- bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
- spin_unlock_irq(&pDevice->lock);
- break;
-
- case WLAN_CMD_GET_NODE_CNT:
+ if ((sStartAPCmd.uChannel > 0) && (sStartAPCmd.uChannel <= 14))
+ pDevice->uChannel = sStartAPCmd.uChannel;
+
+ if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000))
+ pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt;
+ else
+ pMgmt->wIBSSBeaconPeriod = 100;
+
+ if (sStartAPCmd.bShareKeyAuth == true) {
+ pMgmt->bShareKeyAlgorithm = true;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key\n");
+ } else {
+ pMgmt->bShareKeyAlgorithm = false;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System\n");
+ }
+ memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6);
+
+ if (sStartAPCmd.byBasicRate & BIT3) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ pMgmt->abyIBSSSuppRates[4] |= BIT7;
+ pMgmt->abyIBSSSuppRates[5] |= BIT7;
+ } else if (sStartAPCmd.byBasicRate & BIT2) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ pMgmt->abyIBSSSuppRates[4] |= BIT7;
+ } else if (sStartAPCmd.byBasicRate & BIT1) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ } else if (sStartAPCmd.byBasicRate & BIT1) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ } else {
+ /* default 1,2M */
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ }
+
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n",
+ pMgmt->abyIBSSSuppRates[2],
+ pMgmt->abyIBSSSuppRates[3],
+ pMgmt->abyIBSSSuppRates[4],
+ pMgmt->abyIBSSSuppRates[5]);
+
+ netif_stop_queue(pDevice->dev);
+ spin_lock_irq(&pDevice->lock);
+ bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
+ spin_unlock_irq(&pDevice->lock);
+ break;
+ case WLAN_CMD_GET_NODE_CNT:
cbListCount = 0;
pNode = &(pMgmt->sNodeDBTable[0]);
- for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
- pNode = &(pMgmt->sNodeDBTable[ii]);
- if (!pNode->bActive)
- continue;
- cbListCount++;
- }
-
- sNodeList.uItem = cbListCount;
- if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) {
+ for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
+ pNode = &(pMgmt->sNodeDBTable[ii]);
+ if (!pNode->bActive)
+ continue;
+ cbListCount++;
+ }
+
+ sNodeList.uItem = cbListCount;
+ if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) {
result = -EFAULT;
break;
}
- pReq->wResult = 0;
- break;
-
- case WLAN_CMD_GET_NODE_LIST:
+ pReq->wResult = 0;
+ break;
- if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) {
+ case WLAN_CMD_GET_NODE_LIST:
+ if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) {
result = -EFAULT;
break;
}
- pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
- if (pNodeList == NULL) {
- result = -ENOMEM;
- break;
- }
+ pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
+ if (pNodeList == NULL) {
+ result = -ENOMEM;
+ break;
+ }
pNodeList->uItem = sNodeList.uItem;
pNode = &(pMgmt->sNodeDBTable[0]);
- for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) {
- pNode = &(pMgmt->sNodeDBTable[ii]);
- if (pNode->bActive) {
- pNodeList->sNodeList[jj].wAID = pNode->wAID;
- memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN);
- pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate;
- pNodeList->sNodeList[jj].wInActiveCount = (unsigned short)pNode->uInActiveCount;
- pNodeList->sNodeList[jj].wEnQueueCnt = (unsigned short)pNode->wEnQueueCnt;
- pNodeList->sNodeList[jj].wFlags = (unsigned short)pNode->dwFlags;
- pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable;
- pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex;
- pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength;
- memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- pNodeList->sNodeList[jj].abyWepKey[0],
- pNodeList->sNodeList[jj].abyWepKey[1],
- pNodeList->sNodeList[jj].abyWepKey[2],
- pNodeList->sNodeList[jj].abyWepKey[3],
- pNodeList->sNodeList[jj].abyWepKey[4]
- );
- pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback;
- pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures;
- pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts;
- pNodeList->sNodeList[jj].wFailureRatio = (unsigned short)pNode->uFailureRatio;
- jj ++;
- if (jj >= pNodeList->uItem)
- break;
- }
- }
- if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
+ for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) {
+ pNode = &(pMgmt->sNodeDBTable[ii]);
+ if (pNode->bActive) {
+ pNodeList->sNodeList[jj].wAID = pNode->wAID;
+ memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN);
+ pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate;
+ pNodeList->sNodeList[jj].wInActiveCount = (unsigned short)pNode->uInActiveCount;
+ pNodeList->sNodeList[jj].wEnQueueCnt = (unsigned short)pNode->wEnQueueCnt;
+ pNodeList->sNodeList[jj].wFlags = (unsigned short)pNode->dwFlags;
+ pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable;
+ pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex;
+ pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength;
+ memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ pNodeList->sNodeList[jj].abyWepKey[0],
+ pNodeList->sNodeList[jj].abyWepKey[1],
+ pNodeList->sNodeList[jj].abyWepKey[2],
+ pNodeList->sNodeList[jj].abyWepKey[3],
+ pNodeList->sNodeList[jj].abyWepKey[4]);
+ pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback;
+ pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures;
+ pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts;
+ pNodeList->sNodeList[jj].wFailureRatio = (unsigned short)pNode->uFailureRatio;
+ jj++;
+ if (jj >= pNodeList->uItem)
+ break;
+ }
+ }
+ if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
result = -EFAULT;
break;
}
- kfree(pNodeList);
- pReq->wResult = 0;
- break;
+ kfree(pNodeList);
+ pReq->wResult = 0;
+ break;
#ifdef WPA_SM_Transtatus
- case 0xFF:
- memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname));
- wpa_Result.proto = 0;
- wpa_Result.key_mgmt = 0;
- wpa_Result.eap_type = 0;
- wpa_Result.authenticated = false;
- pDevice->fWPA_Authened = false;
- if (copy_from_user(&wpa_Result, pReq->data, sizeof(wpa_Result))) {
- result = -EFAULT;
+ case 0xFF:
+ memset(wpa_Result.ifname, 0, sizeof(wpa_Result.ifname));
+ wpa_Result.proto = 0;
+ wpa_Result.key_mgmt = 0;
+ wpa_Result.eap_type = 0;
+ wpa_Result.authenticated = false;
+ pDevice->fWPA_Authened = false;
+ if (copy_from_user(&wpa_Result, pReq->data, sizeof(wpa_Result))) {
+ result = -EFAULT;
break;
}
-if(wpa_Result.authenticated==true) {
- #ifdef SndEvt_ToAPI
- {
- union iwreq_data wrqu;
+ if (wpa_Result.authenticated == true) {
+#ifdef SndEvt_ToAPI
+ {
+ union iwreq_data wrqu;
- pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+ pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.flags = RT_WPACONNECTED_EVENT_FLAG;
- wrqu.data.length =pItemSSID->len;
- wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID);
- }
- #endif
- pDevice->fWPA_Authened = true; //is successful peer to wpa_Result.authenticated?
-}
-
- //printk("get private wpa_supplicant announce WPA SM\n");
- //printk("wpa-->ifname=%s\n",wpa_Result.ifname);
- //printk("wpa-->proto=%d\n",wpa_Result.proto);
- //printk("wpa-->key-mgmt=%d\n",wpa_Result.key_mgmt);
- //printk("wpa-->eap_type=%d\n",wpa_Result.eap_type);
- //printk("wpa-->authenticated is %s\n",(wpa_Result.authenticated==true)?"true":"false");
-
- pReq->wResult = 0;
- break;
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_WPACONNECTED_EVENT_FLAG;
+ wrqu.data.length = pItemSSID->len;
+ wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID);
+ }
+#endif
+ pDevice->fWPA_Authened = true; /* is successful peer to wpa_Result.authenticated? */
+ }
+ pReq->wResult = 0;
+ break;
#endif
- default:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not support..\n");
- }
-
- return result;
-}
+ default:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not support..\n");
+ }
-/*
-void
-vConfigWEPKey (
- PSDevice pDevice,
- unsigned long dwKeyIndex,
- unsigned char *pbyKey,
- unsigned long uKeyLength
- )
-{
- int ii;
-
-
- memset(&pDevice->abyWepKey[dwKeyIndex][0], 0, WLAN_WEPMAX_KEYLEN);
- memcpy(&pDevice->abyWepKey[dwKeyIndex][0], pbyKey, uKeyLength);
-
- pDevice->bWepKeyAvailable[dwKeyIndex] = true;
- pDevice->auWepKeyLength[dwKeyIndex] = uKeyLength;
-
- MACvSetDefaultKeyEntry(pDevice->PortOffset, uKeyLength, dwKeyIndex,
- (unsigned long *) &(pDevice->abyWepKey[dwKeyIndex][0]), pDevice->byLocalID);
-
- if (pDevice->eEncryptionStatus < Ndis802_11EncryptionNotSupported) {
- for(ii=0; ii<MAX_GROUP_KEY; ii++) {
- if ((pDevice->bWepKeyAvailable[ii] == true) &&
- (pDevice->auWepKeyLength[ii] == WLAN_WEP232_KEYLEN)) {
- pDevice->uCurrentWEPMode = TX_WEP_SW232;
- MACvDisableDefaultKey(pDevice->PortOffset);
- break;
- }
- }
- if ((ii == MAX_GROUP_KEY) &&
- (pDevice->eEncryptionStatus < Ndis802_11EncryptionNotSupported)) {
- MACvEnableDefaultKey(pDevice->PortOffset, pDevice->byLocalID);
- }
- }
+ return result;
}
-*/
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
index b8ec783..3003363 100644
--- a/drivers/staging/vt6655/rf.c
+++ b/drivers/staging/vt6655/rf.c
@@ -1029,6 +1029,7 @@ unsigned char byPwrdBm = 0;
break;
case RATE_6M:
case RATE_9M:
+ case RATE_12M:
case RATE_18M:
byPwr = pDevice->abyOFDMPwrTbl[uCH];
if (pDevice->byRFType == RF_UW2452) {
diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c
index ab289c3..c46d519 100644
--- a/drivers/staging/vt6655/wmgr.c
+++ b/drivers/staging/vt6655/wmgr.c
@@ -2521,14 +2521,8 @@ vMgrCreateOwnIBSS(
if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
// AP mode BSSID = MAC addr
memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
- DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%02x-%02x-%02x-%02x-%02x-%02x \n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]
- );
+ DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%pM\n",
+ pMgmt->abyCurrBSSID);
}
if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
@@ -2550,14 +2544,8 @@ vMgrCreateOwnIBSS(
pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL;
- DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%02x-%02x-%02x-%02x-%02x-%02x \n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]
- );
+ DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%pM\n",
+ pMgmt->abyCurrBSSID);
}
// Set Capability Info
@@ -2887,14 +2875,8 @@ vMgrJoinBSSBegin(
// pDevice->bLinkPass = true;
// memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%02x-%02x-%02x-%02x-%02x-%02x \n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]
- );
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%pM\n",
+ pMgmt->abyCurrBSSID);
// Preamble type auto-switch: if AP can receive short-preamble cap,
// and if registry setting is short preamble we can turn on too.
@@ -2984,13 +2966,8 @@ s_vMgrSynchBSS (
MACvReadBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = %02x-%02x-%02x=%02x-%02x-%02x\n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = "
+ "%pM\n", pMgmt->abyCurrBSSID);
if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) {
if ((pMgmt->eConfigPHYMode == PHY_TYPE_11A) ||
@@ -4462,14 +4439,8 @@ s_vMgrRxProbeRequest(
sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
vMgrDecodeProbeRequest(&sFrame);
/*
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%02x-%02x-%02x=%02x-%02x-%02x \n",
- sFrame.pHdr->sA3.abyAddr2[0],
- sFrame.pHdr->sA3.abyAddr2[1],
- sFrame.pHdr->sA3.abyAddr2[2],
- sFrame.pHdr->sA3.abyAddr2[3],
- sFrame.pHdr->sA3.abyAddr2[4],
- sFrame.pHdr->sA3.abyAddr2[5]
- );
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n",
+ sFrame.pHdr->sA3.abyAddr2);
*/
if (sFrame.pSSID->len != 0) {
if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len)
diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c
index a0f994e..732ba88 100644
--- a/drivers/staging/vt6655/wpactl.c
+++ b/drivers/staging/vt6655/wpactl.c
@@ -213,7 +213,9 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
int uu, ii;
- if (param->u.wpa_key.alg_name > WPA_ALG_CCMP)
+ if (param->u.wpa_key.alg_name > WPA_ALG_CCMP ||
+ param->u.wpa_key.key_len >= MAX_KEY_LEN ||
+ param->u.wpa_key.seq_len >= MAX_KEY_LEN)
return -EINVAL;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name);
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index 0d11147..59cf674 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -1656,7 +1656,6 @@ BBvUpdatePreEDThreshold(
if( bScanning )
{ // need Max sensitivity //RSSI -69, -70,....
- if(pDevice->byBBPreEDIndex == 0) break;
pDevice->byBBPreEDIndex = 0;
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9)
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE)
@@ -1799,7 +1798,6 @@ BBvUpdatePreEDThreshold(
if( bScanning )
{ // need Max sensitivity //RSSI -69, -70, ...
- if(pDevice->byBBPreEDIndex == 0) break;
pDevice->byBBPreEDIndex = 0;
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9)
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x24); //CR206(0xCE)
@@ -1951,7 +1949,6 @@ BBvUpdatePreEDThreshold(
case RF_VT3342A0: //RobertYu:20060627, testing table
if( bScanning )
{ // need Max sensitivity //RSSI -67, -68, ...
- if(pDevice->byBBPreEDIndex == 0) break;
pDevice->byBBPreEDIndex = 0;
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9)
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x38); //CR206(0xCE)
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index 5918ef7..4664e9d 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -1109,30 +1109,12 @@ static BOOL s_bAPModeRxCtl (
&Status
);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n");
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%02x-%02x-%02x=%02x-%02x-%02x \n",
- p802_11Header->abyAddr3[0],
- p802_11Header->abyAddr3[1],
- p802_11Header->abyAddr3[2],
- p802_11Header->abyAddr3[3],
- p802_11Header->abyAddr3[4],
- p802_11Header->abyAddr3[5]
- );
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%02x-%02x-%02x=%02x-%02x-%02x \n",
- p802_11Header->abyAddr2[0],
- p802_11Header->abyAddr2[1],
- p802_11Header->abyAddr2[2],
- p802_11Header->abyAddr2[3],
- p802_11Header->abyAddr2[4],
- p802_11Header->abyAddr2[5]
- );
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%02x-%02x-%02x=%02x-%02x-%02x \n",
- p802_11Header->abyAddr1[0],
- p802_11Header->abyAddr1[1],
- p802_11Header->abyAddr1[2],
- p802_11Header->abyAddr1[3],
- p802_11Header->abyAddr1[4],
- p802_11Header->abyAddr1[5]
- );
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n",
+ p802_11Header->abyAddr3);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n",
+ p802_11Header->abyAddr2);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n",
+ p802_11Header->abyAddr1);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl );
return TRUE;
}
diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c
index cfe9c95..4939002 100644
--- a/drivers/staging/vt6656/ioctl.c
+++ b/drivers/staging/vt6656/ioctl.c
@@ -40,665 +40,603 @@
#include "rndis.h"
#include "rf.h"
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-//static int msglevel =MSG_LEVEL_DEBUG;
-static int msglevel =MSG_LEVEL_INFO;
-
- SWPAResult wpa_Result;
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-int private_ioctl(PSDevice pDevice, struct ifreq *rq) {
-
- PSCmdRequest pReq = (PSCmdRequest)rq;
- PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
- int result = 0;
- PWLAN_IE_SSID pItemSSID;
- SCmdBSSJoin sJoinCmd;
- SCmdZoneTypeSet sZoneTypeCmd;
- SCmdScan sScanCmd;
- SCmdStartAP sStartAPCmd;
- SCmdSetWEP sWEPCmd;
- SCmdValue sValue;
- SBSSIDList sList;
- SNodeList sNodeList;
- PSBSSIDList pList;
- PSNodeList pNodeList;
- unsigned int cbListCount;
- PKnownBSS pBSS;
- PKnownNodeDB pNode;
- unsigned int ii, jj;
- SCmdLinkStatus sLinkStatus;
- BYTE abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
- BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- DWORD dwKeyIndex= 0;
- BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
- signed long ldBm;
-
- pReq->wResult = 0;
-
- switch(pReq->wCmdCode) {
-
- case WLAN_CMD_BSS_SCAN:
-
- if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) {
+SWPAResult wpa_Result;
+static int msglevel = MSG_LEVEL_INFO;
+
+int private_ioctl(PSDevice pDevice, struct ifreq *rq)
+{
+
+ PSCmdRequest pReq = (PSCmdRequest)rq;
+ PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+ int result = 0;
+ PWLAN_IE_SSID pItemSSID;
+ SCmdBSSJoin sJoinCmd;
+ SCmdZoneTypeSet sZoneTypeCmd;
+ SCmdScan sScanCmd;
+ SCmdStartAP sStartAPCmd;
+ SCmdSetWEP sWEPCmd;
+ SCmdValue sValue;
+ SBSSIDList sList;
+ SNodeList sNodeList;
+ PSBSSIDList pList;
+ PSNodeList pNodeList;
+ unsigned int cbListCount;
+ PKnownBSS pBSS;
+ PKnownNodeDB pNode;
+ unsigned int ii, jj;
+ SCmdLinkStatus sLinkStatus;
+ BYTE abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
+ BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ DWORD dwKeyIndex = 0;
+ BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+ signed long ldBm;
+
+ pReq->wResult = 0;
+
+ switch (pReq->wCmdCode) {
+ case WLAN_CMD_BSS_SCAN:
+ if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) {
result = -EFAULT;
break;
}
- pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid;
- if (pItemSSID->len != 0) {
- memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
- memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
- }
- spin_lock_irq(&pDevice->lock);
+ pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid;
+ if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
+ return -EINVAL;
+ if (pItemSSID->len != 0) {
+ memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+ memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
+ }
+ spin_lock_irq(&pDevice->lock);
- if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0)
- BSSvClearBSSList((void *) pDevice, FALSE);
- else
- BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass);
+ if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0)
+ BSSvClearBSSList((void *)pDevice, FALSE);
+ else
+ BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin\n");
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin\n");
- if (pItemSSID->len != 0)
- bScheduleCommand((void *) pDevice,
- WLAN_CMD_BSSID_SCAN,
- abyScanSSID);
- else
- bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+ if (pItemSSID->len != 0)
+ bScheduleCommand((void *)pDevice,
+ WLAN_CMD_BSSID_SCAN,
+ abyScanSSID);
+ else
+ bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
- spin_unlock_irq(&pDevice->lock);
- break;
+ spin_unlock_irq(&pDevice->lock);
+ break;
- case WLAN_CMD_ZONETYPE_SET:
- //mike add :cann't support.
- result=-EOPNOTSUPP;
- break;
+ case WLAN_CMD_ZONETYPE_SET:
+ result = -EOPNOTSUPP;
+ break;
- if (copy_from_user(&sZoneTypeCmd, pReq->data, sizeof(SCmdZoneTypeSet))) {
+ if (copy_from_user(&sZoneTypeCmd, pReq->data, sizeof(SCmdZoneTypeSet))) {
result = -EFAULT;
break;
}
- if(sZoneTypeCmd.bWrite==TRUE) {
- //////write zonetype
- if(sZoneTypeCmd.ZoneType == ZoneType_USA) {
- //set to USA
- printk("set_ZoneType:USA\n");
- }
- else if(sZoneTypeCmd.ZoneType == ZoneType_Japan) {
- //set to Japan
- printk("set_ZoneType:Japan\n");
- }
- else if(sZoneTypeCmd.ZoneType == ZoneType_Europe) {
- //set to Europe
- printk("set_ZoneType:Europe\n");
- }
- }
- else {
- ///////read zonetype
- BYTE zonetype=0;
-
-
- if(zonetype == 0x00) { //USA
- sZoneTypeCmd.ZoneType = ZoneType_USA;
- }
- else if(zonetype == 0x01) { //Japan
- sZoneTypeCmd.ZoneType = ZoneType_Japan;
- }
- else if(zonetype == 0x02) { //Europe
- sZoneTypeCmd.ZoneType = ZoneType_Europe;
- }
- else { //Unknown ZoneType
- printk("Error:ZoneType[%x] Unknown ???\n",zonetype);
- result = -EFAULT;
+ if (sZoneTypeCmd.bWrite == TRUE) {
+ /* write zonetype */
+ if (sZoneTypeCmd.ZoneType == ZoneType_USA) {
+ /* set to USA */
+ printk("set_ZoneType:USA\n");
+ } else if (sZoneTypeCmd.ZoneType == ZoneType_Japan) {
+ /* set to Japan */
+ printk("set_ZoneType:Japan\n");
+ } else if (sZoneTypeCmd.ZoneType == ZoneType_Europe) {
+ /* set to Europe */
+ printk("set_ZoneType:Europe\n");
+ }
+ } else {
+ /* read zonetype */
+ BYTE zonetype = 0;
+
+ if (zonetype == 0x00) { /* USA */
+ sZoneTypeCmd.ZoneType = ZoneType_USA;
+ } else if (zonetype == 0x01) { /* Japan */
+ sZoneTypeCmd.ZoneType = ZoneType_Japan;
+ } else if (zonetype == 0x02) { /* Europe */
+ sZoneTypeCmd.ZoneType = ZoneType_Europe;
+ } else { /* Unknown ZoneType */
+ printk("Error:ZoneType[%x] Unknown ???\n", zonetype);
+ result = -EFAULT;
+ break;
+ }
+
+ if (copy_to_user(pReq->data, &sZoneTypeCmd,
+ sizeof(SCmdZoneTypeSet))) {
+ result = -EFAULT;
+ break;
+ }
+ }
break;
- }
- if (copy_to_user(pReq->data, &sZoneTypeCmd, sizeof(SCmdZoneTypeSet))) {
+ case WLAN_CMD_BSS_JOIN:
+ if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) {
result = -EFAULT;
break;
}
- }
- break;
+ pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid;
+ if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
+ return -EINVAL;
+ memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+ memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
+ if (sJoinCmd.wBSSType == ADHOC) {
+ pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to adhoc mode\n");
+ } else {
+ pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to STA mode\n");
+ }
+ if (sJoinCmd.bPSEnable == TRUE) {
+ pDevice->ePSMode = WMAC_POWER_FAST;
+ pMgmt->wListenInterval = 2;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving On\n");
+ } else {
+ pDevice->ePSMode = WMAC_POWER_CAM;
+ pMgmt->wListenInterval = 1;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving Off\n");
+ }
+
+ if (sJoinCmd.bShareKeyAuth == TRUE) {
+ pMgmt->bShareKeyAlgorithm = TRUE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key\n");
+ } else {
+ pMgmt->bShareKeyAlgorithm = FALSE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System\n");
+ }
- case WLAN_CMD_BSS_JOIN:
+ pDevice->uChannel = sJoinCmd.uChannel;
+ netif_stop_queue(pDevice->dev);
+ spin_lock_irq(&pDevice->lock);
+ pMgmt->eCurrState = WMAC_STATE_IDLE;
+ bScheduleCommand((void *) pDevice,
+ WLAN_CMD_BSSID_SCAN,
+ pMgmt->abyDesireSSID);
+ bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
+ spin_unlock_irq(&pDevice->lock);
+ break;
- if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) {
+ case WLAN_CMD_SET_WEP:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WEP Key.\n");
+ memset(&sWEPCmd, 0, sizeof(SCmdSetWEP));
+ if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) {
result = -EFAULT;
break;
}
-
- pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid;
- memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
- memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
- if (sJoinCmd.wBSSType == ADHOC) {
- pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to adhoc mode\n");
- }
- else {
- pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to STA mode\n");
- }
- if (sJoinCmd.bPSEnable == TRUE) {
- pDevice->ePSMode = WMAC_POWER_FAST;
-// pDevice->ePSMode = WMAC_POWER_MAX;
- pMgmt->wListenInterval = 2;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving On\n");
- }
- else {
- pDevice->ePSMode = WMAC_POWER_CAM;
- pMgmt->wListenInterval = 1;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving Off \n");
- }
-
- if (sJoinCmd.bShareKeyAuth == TRUE){
- pMgmt->bShareKeyAlgorithm = TRUE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key \n");
- }
- else {
- pMgmt->bShareKeyAlgorithm = FALSE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System \n");
- }
- pDevice->uChannel = sJoinCmd.uChannel;
- netif_stop_queue(pDevice->dev);
- spin_lock_irq(&pDevice->lock);
- pMgmt->eCurrState = WMAC_STATE_IDLE;
- bScheduleCommand((void *) pDevice,
- WLAN_CMD_BSSID_SCAN,
- pMgmt->abyDesireSSID);
- bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
- spin_unlock_irq(&pDevice->lock);
- break;
-
- case WLAN_CMD_SET_WEP:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WEP Key. \n");
- memset(&sWEPCmd, 0 ,sizeof(SCmdSetWEP));
- if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) {
- result = -EFAULT;
+ if (sWEPCmd.bEnableWep != TRUE) {
+ int uu;
+
+ pDevice->bEncryptionEnable = FALSE;
+ pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+ spin_lock_irq(&pDevice->lock);
+ for (uu = 0; uu < MAX_KEY_TABLE; uu++)
+ MACvDisableKeyEntry(pDevice, uu);
+ spin_unlock_irq(&pDevice->lock);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable.\n");
break;
}
- if (sWEPCmd.bEnableWep != TRUE) {
- int uu;
-
- pDevice->bEncryptionEnable = FALSE;
- pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
- spin_lock_irq(&pDevice->lock);
- for (uu = 0; uu < MAX_KEY_TABLE; uu++)
- MACvDisableKeyEntry(pDevice, uu);
- spin_unlock_irq(&pDevice->lock);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable.\n");
- break;
- }
-
- for (ii = 0; ii < WLAN_WEP_NKEYS; ii ++) {
- if (sWEPCmd.bWepKeyAvailable[ii]) {
- if (ii == sWEPCmd.byKeyIndex)
-//2006-1207-01<Modify>by Einsn Liu
-// dwKeyIndex|= (1 << 31);
- dwKeyIndex=ii|(1 << 31);
- else
- dwKeyIndex = ii;
- spin_lock_irq(&pDevice->lock);
- KeybSetDefaultKey( pDevice,
- &(pDevice->sKey),
- dwKeyIndex,
- sWEPCmd.auWepKeyLength[ii],
- NULL,
- (PBYTE)&sWEPCmd.abyWepKey[ii][0],
- KEY_CTL_WEP
- );
- spin_unlock_irq(&pDevice->lock);
-
- }
- }
- pDevice->byKeyIndex = sWEPCmd.byKeyIndex;
- pDevice->bTransmitKey = TRUE;
- pDevice->bEncryptionEnable = TRUE;
- pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-
- break;
-
- case WLAN_CMD_GET_LINK:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_GET_LINK status. \n");
-
- memset(sLinkStatus.abySSID, 0 , WLAN_SSID_MAXLEN + 1);
-
- if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
- sLinkStatus.wBSSType = ADHOC;
- else
- sLinkStatus.wBSSType = INFRA;
-
- if (pMgmt->eCurrState == WMAC_STATE_JOINTED)
- sLinkStatus.byState = ADHOC_JOINTED;
- else
- sLinkStatus.byState = ADHOC_STARTED;
-
- sLinkStatus.uChannel = pMgmt->uCurrChannel;
- if (pDevice->bLinkPass == TRUE) {
- sLinkStatus.bLink = TRUE;
- pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
- memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len);
- memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
- sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Link Success ! \n");
- }
- else {
- sLinkStatus.bLink = FALSE;
- }
- if (copy_to_user(pReq->data, &sLinkStatus, sizeof(SCmdLinkStatus))) {
+
+ for (ii = 0; ii < WLAN_WEP_NKEYS; ii++) {
+ if (sWEPCmd.bWepKeyAvailable[ii]) {
+ if (ii == sWEPCmd.byKeyIndex)
+ dwKeyIndex = ii | (1 << 31);
+ else
+ dwKeyIndex = ii;
+ spin_lock_irq(&pDevice->lock);
+ KeybSetDefaultKey(pDevice, &(pDevice->sKey),
+ dwKeyIndex,
+ sWEPCmd.auWepKeyLength[ii],
+ NULL,
+ (PBYTE)&sWEPCmd.abyWepKey[ii][0],
+ KEY_CTL_WEP);
+ spin_unlock_irq(&pDevice->lock);
+ }
+ }
+ pDevice->byKeyIndex = sWEPCmd.byKeyIndex;
+ pDevice->bTransmitKey = TRUE;
+ pDevice->bEncryptionEnable = TRUE;
+ pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+ break;
+
+ case WLAN_CMD_GET_LINK:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_GET_LINK status.\n");
+
+ memset(sLinkStatus.abySSID, 0, WLAN_SSID_MAXLEN + 1);
+
+ if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
+ sLinkStatus.wBSSType = ADHOC;
+ else
+ sLinkStatus.wBSSType = INFRA;
+
+ if (pMgmt->eCurrState == WMAC_STATE_JOINTED)
+ sLinkStatus.byState = ADHOC_JOINTED;
+ else
+ sLinkStatus.byState = ADHOC_STARTED;
+
+ sLinkStatus.uChannel = pMgmt->uCurrChannel;
+ if (pDevice->bLinkPass == TRUE) {
+ sLinkStatus.bLink = TRUE;
+ pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+ memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len);
+ memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+ sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Link Success!\n");
+ } else {
+ sLinkStatus.bLink = FALSE;
+ sLinkStatus.uLinkRate = 0;
+ }
+ if (copy_to_user(pReq->data, &sLinkStatus,
+ sizeof(SCmdLinkStatus))) {
result = -EFAULT;
break;
}
+ break;
- break;
-
- case WLAN_CMD_GET_LISTLEN:
+ case WLAN_CMD_GET_LISTLEN:
cbListCount = 0;
pBSS = &(pMgmt->sBSSList[0]);
- for (ii = 0; ii < MAX_BSS_NUM; ii++) {
- pBSS = &(pMgmt->sBSSList[ii]);
- if (!pBSS->bActive)
- continue;
- cbListCount++;
- }
- sList.uItem = cbListCount;
- if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) {
+ for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+ pBSS = &(pMgmt->sBSSList[ii]);
+ if (!pBSS->bActive)
+ continue;
+ cbListCount++;
+ }
+ sList.uItem = cbListCount;
+ if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) {
result = -EFAULT;
break;
}
- pReq->wResult = 0;
- break;
+ pReq->wResult = 0;
+ break;
- case WLAN_CMD_GET_LIST:
- if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) {
+ case WLAN_CMD_GET_LIST:
+ if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) {
result = -EFAULT;
break;
}
- pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
- if (pList == NULL) {
- result = -ENOMEM;
- break;
- }
+ pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
+ if (pList == NULL) {
+ result = -ENOMEM;
+ break;
+ }
pList->uItem = sList.uItem;
pBSS = &(pMgmt->sBSSList[0]);
- for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
- pBSS = &(pMgmt->sBSSList[jj]);
- if (pBSS->bActive) {
- pList->sBSSIDList[ii].uChannel = pBSS->uChannel;
- pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval;
- pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo;
- RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
- pList->sBSSIDList[ii].uRSSI = (unsigned int) ldBm;
-// pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI;
- memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN);
- pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
- memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1);
- memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len);
- if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
- pList->sBSSIDList[ii].byNetType = INFRA;
- }
- else {
- pList->sBSSIDList[ii].byNetType = ADHOC;
- }
- if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
- pList->sBSSIDList[ii].bWEPOn = TRUE;
- }
- else {
- pList->sBSSIDList[ii].bWEPOn = FALSE;
- }
- ii ++;
- if (ii >= pList->uItem)
- break;
- }
- }
-
- if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) {
+ for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
+ pBSS = &(pMgmt->sBSSList[jj]);
+ if (pBSS->bActive) {
+ pList->sBSSIDList[ii].uChannel = pBSS->uChannel;
+ pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval;
+ pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo;
+ RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
+ pList->sBSSIDList[ii].uRSSI = (unsigned int) ldBm;
+ /* pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI; */
+ memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN);
+ pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
+ memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1);
+ memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len);
+ if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
+ pList->sBSSIDList[ii].byNetType = INFRA;
+ } else {
+ pList->sBSSIDList[ii].byNetType = ADHOC;
+ }
+ if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
+ pList->sBSSIDList[ii].bWEPOn = TRUE;
+ } else {
+ pList->sBSSIDList[ii].bWEPOn = FALSE;
+ }
+ ii++;
+ if (ii >= pList->uItem)
+ break;
+ }
+ }
+
+ if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) {
result = -EFAULT;
break;
}
- kfree(pList);
- pReq->wResult = 0;
- break;
+ kfree(pList);
+ pReq->wResult = 0;
+ break;
- case WLAN_CMD_GET_MIB:
- if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) {
+ case WLAN_CMD_GET_MIB:
+ if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) {
result = -EFAULT;
break;
}
- break;
+ break;
- case WLAN_CMD_GET_STAT:
- if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) {
+ case WLAN_CMD_GET_STAT:
+ if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) {
result = -EFAULT;
break;
}
- break;
- case WLAN_CMD_STOP_MAC:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n");
- // Todo xxxxxx
- netif_stop_queue(pDevice->dev);
- spin_lock_irq(&pDevice->lock);
- if (pDevice->bRadioOff == FALSE) {
- CARDbRadioPowerOff(pDevice);
- }
- pDevice->bLinkPass = FALSE;
- ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW);
- memset(pMgmt->abyCurrBSSID, 0, 6);
- pMgmt->eCurrState = WMAC_STATE_IDLE;
-// del_timer(&pDevice->sTimerCommand);
-// del_timer(&pMgmt->sTimerSecondCallback);
- pDevice->bCmdRunning = FALSE;
- spin_unlock_irq(&pDevice->lock);
-
- break;
-
- case WLAN_CMD_START_MAC:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_START_MAC\n");
- // Todo xxxxxxx
- if (pDevice->bRadioOff == TRUE)
- CARDbRadioPowerOn(pDevice);
- break;
+ break;
+ case WLAN_CMD_STOP_MAC:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n");
+ /* Todo xxxxxx */
+ netif_stop_queue(pDevice->dev);
+ spin_lock_irq(&pDevice->lock);
+ if (pDevice->bRadioOff == FALSE) {
+ CARDbRadioPowerOff(pDevice);
+ }
+ pDevice->bLinkPass = FALSE;
+ ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW);
+ memset(pMgmt->abyCurrBSSID, 0, 6);
+ pMgmt->eCurrState = WMAC_STATE_IDLE;
+ /* del_timer(&pDevice->sTimerCommand); */
+ /* del_timer(&pMgmt->sTimerSecondCallback); */
+ pDevice->bCmdRunning = FALSE;
+ spin_unlock_irq(&pDevice->lock);
+ break;
- case WLAN_CMD_SET_HOSTAPD:
+ case WLAN_CMD_START_MAC:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_START_MAC\n");
+ /* Todo xxxxxxx */
+ if (pDevice->bRadioOff == TRUE)
+ CARDbRadioPowerOn(pDevice);
+ break;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD\n");
+ case WLAN_CMD_SET_HOSTAPD:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- if (vt6656_hostap_set_hostapd(pDevice, 1, 1) == 0){
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HOSTAP\n");
- }
- else {
- result = -EFAULT;
- break;
+ if (vt6656_hostap_set_hostapd(pDevice, 1, 1) == 0) {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HOSTAP\n");
+ } else {
+ result = -EFAULT;
+ break;
}
- }
- else {
- vt6656_hostap_set_hostapd(pDevice, 0, 1);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HOSTAP\n");
- }
-
- break;
-
- case WLAN_CMD_SET_HOSTAPD_STA:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD_STA\n");
+ } else {
+ vt6656_hostap_set_hostapd(pDevice, 0, 1);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HOSTAP\n");
+ }
+ break;
- break;
- case WLAN_CMD_SET_802_1X:
+ case WLAN_CMD_SET_HOSTAPD_STA:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD_STA\n");
+ break;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_802_1X\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ case WLAN_CMD_SET_802_1X:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_802_1X\n");
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- pDevice->bEnable8021x = TRUE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable 802.1x\n");
- }
- else {
- pDevice->bEnable8021x = FALSE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable 802.1x\n");
- }
-
- break;
-
-
- case WLAN_CMD_SET_HOST_WEP:
+ pDevice->bEnable8021x = TRUE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable 802.1x\n");
+ } else {
+ pDevice->bEnable8021x = FALSE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable 802.1x\n");
+ }
+ break;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOST_WEP\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ case WLAN_CMD_SET_HOST_WEP:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOST_WEP\n");
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- pDevice->bEnableHostWEP = TRUE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HostWEP\n");
- }
- else {
- pDevice->bEnableHostWEP = FALSE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HostWEP\n");
- }
-
- break;
+ pDevice->bEnableHostWEP = TRUE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HostWEP\n");
+ } else {
+ pDevice->bEnableHostWEP = FALSE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HostWEP\n");
+ }
+ break;
- case WLAN_CMD_SET_WPA:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WPA\n");
+ case WLAN_CMD_SET_WPA:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WPA\n");
- if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
+ if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
result = -EFAULT;
break;
}
if (sValue.dwValue == 1) {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "up wpadev\n");
- memcpy(pDevice->wpadev->dev_addr,
- pDevice->dev->dev_addr,
- ETH_ALEN);
- pDevice->bWPADEVUp = TRUE;
- }
- else {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "close wpadev\n");
- pDevice->bWPADEVUp = FALSE;
- }
-
- break;
-
- case WLAN_CMD_AP_START:
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_AP_START\n");
- if (pDevice->bRadioOff == TRUE) {
- CARDbRadioPowerOn(pDevice);
- add_timer(&pMgmt->sTimerSecondCallback);
- }
- if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "up wpadev\n");
+ memcpy(pDevice->wpadev->dev_addr, pDevice->dev->dev_addr,
+ ETH_ALEN);
+ pDevice->bWPADEVUp = TRUE;
+ } else {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "close wpadev\n");
+ pDevice->bWPADEVUp = FALSE;
+ }
+ break;
+
+ case WLAN_CMD_AP_START:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_AP_START\n");
+ if (pDevice->bRadioOff == TRUE) {
+ CARDbRadioPowerOn(pDevice);
+ add_timer(&pMgmt->sTimerSecondCallback);
+ }
+ if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) {
result = -EFAULT;
break;
}
- if (sStartAPCmd.wBSSType == AP) {
- pMgmt->eConfigMode = WMAC_CONFIG_AP;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to AP mode\n");
- }
- else {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct BSS type not set to AP mode\n");
+ if (sStartAPCmd.wBSSType == AP) {
+ pMgmt->eConfigMode = WMAC_CONFIG_AP;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to AP mode\n");
+ } else {
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct BSS type not set to AP mode\n");
result = -EFAULT;
break;
- }
-
+ }
- if (sStartAPCmd.wBBPType == PHY80211g) {
- pMgmt->byAPBBType = PHY_TYPE_11G;
- }
- else if (sStartAPCmd.wBBPType == PHY80211a) {
- pMgmt->byAPBBType = PHY_TYPE_11A;
- }
- else {
- pMgmt->byAPBBType = PHY_TYPE_11B;
- }
+ if (sStartAPCmd.wBBPType == PHY80211g) {
+ pMgmt->byAPBBType = PHY_TYPE_11G;
+ } else if (sStartAPCmd.wBBPType == PHY80211a) {
+ pMgmt->byAPBBType = PHY_TYPE_11A;
+ } else {
+ pMgmt->byAPBBType = PHY_TYPE_11B;
+ }
- pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid;
- memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+ pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid;
+ if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
+ return -EINVAL;
+ memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
- if ((sStartAPCmd.uChannel > 0)&&(sStartAPCmd.uChannel <= 14))
- pDevice->uChannel = sStartAPCmd.uChannel;
-
- if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000))
- pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt;
- else
- pMgmt->wIBSSBeaconPeriod = 100;
-
- if (sStartAPCmd.bShareKeyAuth == TRUE){
- pMgmt->bShareKeyAlgorithm = TRUE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key \n");
- }
- else {
- pMgmt->bShareKeyAlgorithm = FALSE;
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System \n");
- }
- memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6);
-
- if (sStartAPCmd.byBasicRate & BIT3) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- pMgmt->abyIBSSSuppRates[4] |= BIT7;
- pMgmt->abyIBSSSuppRates[5] |= BIT7;
- }else if (sStartAPCmd.byBasicRate & BIT2) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- pMgmt->abyIBSSSuppRates[4] |= BIT7;
- }else if (sStartAPCmd.byBasicRate & BIT1) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- }else if (sStartAPCmd.byBasicRate & BIT1) {
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- }else {
- //default 1,2M
- pMgmt->abyIBSSSuppRates[2] |= BIT7;
- pMgmt->abyIBSSSuppRates[3] |= BIT7;
- }
-
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n",
- pMgmt->abyIBSSSuppRates[2],
- pMgmt->abyIBSSSuppRates[3],
- pMgmt->abyIBSSSuppRates[4],
- pMgmt->abyIBSSSuppRates[5]
- );
-
- netif_stop_queue(pDevice->dev);
- spin_lock_irq(&pDevice->lock);
- bScheduleCommand((void *) pDevice, WLAN_CMD_RUN_AP, NULL);
- spin_unlock_irq(&pDevice->lock);
- break;
-
- case WLAN_CMD_GET_NODE_CNT:
+ if ((sStartAPCmd.uChannel > 0) && (sStartAPCmd.uChannel <= 14))
+ pDevice->uChannel = sStartAPCmd.uChannel;
+
+ if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000))
+ pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt;
+ else
+ pMgmt->wIBSSBeaconPeriod = 100;
+
+ if (sStartAPCmd.bShareKeyAuth == TRUE) {
+ pMgmt->bShareKeyAlgorithm = TRUE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key\n");
+ } else {
+ pMgmt->bShareKeyAlgorithm = FALSE;
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System\n");
+ }
+ memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6);
+
+ if (sStartAPCmd.byBasicRate & BIT3) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ pMgmt->abyIBSSSuppRates[4] |= BIT7;
+ pMgmt->abyIBSSSuppRates[5] |= BIT7;
+ } else if (sStartAPCmd.byBasicRate & BIT2) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ pMgmt->abyIBSSSuppRates[4] |= BIT7;
+ } else if (sStartAPCmd.byBasicRate & BIT1) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ } else if (sStartAPCmd.byBasicRate & BIT1) {
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ } else {
+ /* default 1,2M */
+ pMgmt->abyIBSSSuppRates[2] |= BIT7;
+ pMgmt->abyIBSSSuppRates[3] |= BIT7;
+ }
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n",
+ pMgmt->abyIBSSSuppRates[2],
+ pMgmt->abyIBSSSuppRates[3],
+ pMgmt->abyIBSSSuppRates[4],
+ pMgmt->abyIBSSSuppRates[5]);
+
+ netif_stop_queue(pDevice->dev);
+ spin_lock_irq(&pDevice->lock);
+ bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
+ spin_unlock_irq(&pDevice->lock);
+ break;
+
+ case WLAN_CMD_GET_NODE_CNT:
cbListCount = 0;
pNode = &(pMgmt->sNodeDBTable[0]);
- for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
- pNode = &(pMgmt->sNodeDBTable[ii]);
- if (!pNode->bActive)
- continue;
- cbListCount++;
- }
-
- sNodeList.uItem = cbListCount;
- if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) {
+ for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
+ pNode = &(pMgmt->sNodeDBTable[ii]);
+ if (!pNode->bActive)
+ continue;
+ cbListCount++;
+ }
+
+ sNodeList.uItem = cbListCount;
+ if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) {
result = -EFAULT;
break;
}
- pReq->wResult = 0;
- break;
-
- case WLAN_CMD_GET_NODE_LIST:
+ pReq->wResult = 0;
+ break;
- if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) {
+ case WLAN_CMD_GET_NODE_LIST:
+ if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) {
result = -EFAULT;
break;
}
- pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
- if (pNodeList == NULL) {
- result = -ENOMEM;
- break;
- }
+ pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
+ if (pNodeList == NULL) {
+ result = -ENOMEM;
+ break;
+ }
pNodeList->uItem = sNodeList.uItem;
pNode = &(pMgmt->sNodeDBTable[0]);
- for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) {
- pNode = &(pMgmt->sNodeDBTable[ii]);
- if (pNode->bActive) {
- pNodeList->sNodeList[jj].wAID = pNode->wAID;
- memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN);
- pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate;
- pNodeList->sNodeList[jj].wInActiveCount = (WORD)pNode->uInActiveCount;
- pNodeList->sNodeList[jj].wEnQueueCnt = (WORD)pNode->wEnQueueCnt;
- pNodeList->sNodeList[jj].wFlags = (WORD)pNode->dwFlags;
- pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable;
- pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex;
- pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength;
- memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- pNodeList->sNodeList[jj].abyWepKey[0],
- pNodeList->sNodeList[jj].abyWepKey[1],
- pNodeList->sNodeList[jj].abyWepKey[2],
- pNodeList->sNodeList[jj].abyWepKey[3],
- pNodeList->sNodeList[jj].abyWepKey[4]
- );
- pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback;
- pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures;
- pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts;
- pNodeList->sNodeList[jj].wFailureRatio = (WORD)pNode->uFailureRatio;
- jj ++;
- if (jj >= pNodeList->uItem)
- break;
- }
- }
- if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
+ for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) {
+ pNode = &(pMgmt->sNodeDBTable[ii]);
+ if (pNode->bActive) {
+ pNodeList->sNodeList[jj].wAID = pNode->wAID;
+ memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN);
+ pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate;
+ pNodeList->sNodeList[jj].wInActiveCount = (WORD)pNode->uInActiveCount;
+ pNodeList->sNodeList[jj].wEnQueueCnt = (WORD)pNode->wEnQueueCnt;
+ pNodeList->sNodeList[jj].wFlags = (WORD)pNode->dwFlags;
+ pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable;
+ pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex;
+ pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength;
+ memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ pNodeList->sNodeList[jj].abyWepKey[0],
+ pNodeList->sNodeList[jj].abyWepKey[1],
+ pNodeList->sNodeList[jj].abyWepKey[2],
+ pNodeList->sNodeList[jj].abyWepKey[3],
+ pNodeList->sNodeList[jj].abyWepKey[4]);
+ pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback;
+ pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures;
+ pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts;
+ pNodeList->sNodeList[jj].wFailureRatio = (WORD)pNode->uFailureRatio;
+ jj++;
+ if (jj >= pNodeList->uItem)
+ break;
+ }
+ }
+ if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
result = -EFAULT;
break;
}
- kfree(pNodeList);
- pReq->wResult = 0;
- break;
-
- case 0xFF:
- memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname));
- wpa_Result.proto = 0;
- wpa_Result.key_mgmt = 0;
- wpa_Result.eap_type = 0;
- wpa_Result.authenticated = FALSE;
- pDevice->fWPA_Authened = FALSE;
- if (copy_from_user(&wpa_Result, pReq->data, sizeof(wpa_Result))) {
- result = -EFAULT;
+ kfree(pNodeList);
+ pReq->wResult = 0;
+ break;
+
+ case 0xFF:
+ memset(wpa_Result.ifname, 0, sizeof(wpa_Result.ifname));
+ wpa_Result.proto = 0;
+ wpa_Result.key_mgmt = 0;
+ wpa_Result.eap_type = 0;
+ wpa_Result.authenticated = FALSE;
+ pDevice->fWPA_Authened = FALSE;
+ if (copy_from_user(&wpa_Result, pReq->data, sizeof(wpa_Result))) {
+ result = -EFAULT;
break;
}
-//DavidWang for some AP maybe good authenticate
- if(wpa_Result.key_mgmt==0x20)
- pMgmt->Cisco_cckm =1;
- else
- pMgmt->Cisco_cckm =0;
-
-
-if(wpa_Result.authenticated==TRUE) {
- {
- union iwreq_data wrqu;
-
- pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.flags = RT_WPACONNECTED_EVENT_FLAG;
- wrqu.data.length =pItemSSID->len;
- wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID);
- }
- pDevice->fWPA_Authened = TRUE; //is successful peer to wpa_Result.authenticated?
-}
+ /* for some AP maybe good authenticate */
+ if (wpa_Result.key_mgmt == 0x20)
+ pMgmt->Cisco_cckm = 1;
+ else
+ pMgmt->Cisco_cckm = 0;
+
+ if (wpa_Result.authenticated == TRUE) {
+ {
+ union iwreq_data wrqu;
+
+ pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_WPACONNECTED_EVENT_FLAG;
+ wrqu.data.length = pItemSSID->len;
+ wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID);
+ }
- //printk("get private wpa_supplicant announce WPA SM\n");
- //printk("wpa-->ifname=%s\n",wpa_Result.ifname);
- //printk("wpa-->proto=%d\n",wpa_Result.proto);
- //printk("wpa-->key-mgmt=%d\n",wpa_Result.key_mgmt);
- //printk("wpa-->eap_type=%d\n",wpa_Result.eap_type);
- //printk("wpa-->authenticated is %s\n",(wpa_Result.authenticated==TRUE)?"TRUE":"FALSE");
+ pDevice->fWPA_Authened = TRUE; /* is successful peer to wpa_Result.authenticated? */
+ }
- pReq->wResult = 0;
- break;
+ pReq->wResult = 0;
+ break;
- default:
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not support..\n");
- }
+ default:
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not support..\n");
+ }
- return result;
+ return result;
}
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 0b8f93b..f680766 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -611,17 +611,10 @@ static BOOL device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType)
// if exist SW network address, use SW network address.
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %02x-%02x-%02x=%02x-%02x-%02x\n",
- pDevice->abyCurrentNetAddr[0],
- pDevice->abyCurrentNetAddr[1],
- pDevice->abyCurrentNetAddr[2],
- pDevice->abyCurrentNetAddr[3],
- pDevice->abyCurrentNetAddr[4],
- pDevice->abyCurrentNetAddr[5]);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n",
+ pDevice->abyCurrentNetAddr);
}
-
-
// Set BB and packet type at the same time.
// Set Short Slot Time, xIFS, and RSPINF.
if (pDevice->byBBType == BB_TYPE_11A) {
@@ -749,7 +742,7 @@ static const struct net_device_ops device_netdev_ops = {
.ndo_do_ioctl = device_ioctl,
.ndo_get_stats = device_get_stats,
.ndo_start_xmit = device_xmit,
- .ndo_set_multicast_list = device_set_multi,
+ .ndo_set_rx_mode = device_set_multi,
};
static int __devinit
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index f759352..c612ab5 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -168,11 +168,6 @@ int PIPEnsControlOut(
if (pDevice->Flags & fMP_CONTROL_WRITES)
return STATUS_FAILURE;
- if (pDevice->Flags & fMP_CONTROL_READS)
- return STATUS_FAILURE;
-
- MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
-
pDevice->sUsbCtlRequest.bRequestType = 0x40;
pDevice->sUsbCtlRequest.bRequest = byRequest;
pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
@@ -187,13 +182,12 @@ int PIPEnsControlOut(
ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
if (ntStatus != 0) {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
- "control send request submission failed: %d\n",
- ntStatus);
- MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus);
return STATUS_FAILURE;
}
-
+ else {
+ MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
+ }
spin_unlock_irq(&pDevice->lock);
for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
@@ -233,11 +227,6 @@ int PIPEnsControlIn(
if (pDevice->Flags & fMP_CONTROL_READS)
return STATUS_FAILURE;
- if (pDevice->Flags & fMP_CONTROL_WRITES)
- return STATUS_FAILURE;
-
- MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
-
pDevice->sUsbCtlRequest.bRequestType = 0xC0;
pDevice->sUsbCtlRequest.bRequest = byRequest;
pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
@@ -251,11 +240,10 @@ int PIPEnsControlIn(
ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
if (ntStatus != 0) {
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
- "control request submission failed: %d\n", ntStatus);
- MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
- return STATUS_FAILURE;
- }
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus);
+ }else {
+ MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
+ }
spin_unlock_irq(&pDevice->lock);
for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index d67748f..f08e2d1 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -2477,14 +2477,8 @@ void vMgrCreateOwnIBSS(void *hDeviceContext,
if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
// AP mode BSSID = MAC addr
memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
- DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%02x-%02x-%02x-%02x-%02x-%02x \n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]
- );
+ DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:"
+ "%pM\n", pMgmt->abyCurrBSSID);
}
if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
@@ -2506,14 +2500,8 @@ void vMgrCreateOwnIBSS(void *hDeviceContext,
pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL;
- DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%02x-%02x-%02x-%02x-%02x-%02x \n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]
- );
+ DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:"
+ "%pM\n", pMgmt->abyCurrBSSID);
}
// set BSSID filter
@@ -2878,14 +2866,8 @@ void vMgrJoinBSSBegin(void *hDeviceContext, PCMD_STATUS pStatus)
ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER);
memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%02x-%02x-%02x-%02x-%02x-%02x \n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]
- );
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%pM\n",
+ pMgmt->abyCurrBSSID);
// Preamble type auto-switch: if AP can receive short-preamble cap,
// and if registry setting is short preamble we can turn on too.
@@ -2983,13 +2965,8 @@ s_vMgrSynchBSS (
memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, 6);
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = %02x-%02x-%02x=%02x-%02x-%02x\n",
- pMgmt->abyCurrBSSID[0],
- pMgmt->abyCurrBSSID[1],
- pMgmt->abyCurrBSSID[2],
- pMgmt->abyCurrBSSID[3],
- pMgmt->abyCurrBSSID[4],
- pMgmt->abyCurrBSSID[5]);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = "
+ "%pM\n", pMgmt->abyCurrBSSID);
if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) {
if ((pDevice->eConfigPHYMode == PHY_TYPE_11A) ||
@@ -4334,14 +4311,8 @@ s_vMgrRxProbeRequest(
sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
vMgrDecodeProbeRequest(&sFrame);
/*
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%02x-%02x-%02x=%02x-%02x-%02x \n",
- sFrame.pHdr->sA3.abyAddr2[0],
- sFrame.pHdr->sA3.abyAddr2[1],
- sFrame.pHdr->sA3.abyAddr2[2],
- sFrame.pHdr->sA3.abyAddr2[3],
- sFrame.pHdr->sA3.abyAddr2[4],
- sFrame.pHdr->sA3.abyAddr2[5]
- );
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n",
+ sFrame.pHdr->sA3.abyAddr2);
*/
if (sFrame.pSSID->len != 0) {
if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len)
diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
index 9216df0..2fa4f84 100644
--- a/drivers/staging/vt6656/wpactl.c
+++ b/drivers/staging/vt6656/wpactl.c
@@ -229,6 +229,9 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
return ret;
}
+ if (param->u.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey))
+ return -EINVAL;
+
spin_unlock_irq(&pDevice->lock);
if(param->u.wpa_key.key && fcpfkernel) {
memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
@@ -269,6 +272,10 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
return ret;
}
+
+ if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
+ return -EINVAL;
+
spin_unlock_irq(&pDevice->lock);
if(param->u.wpa_key.seq && fcpfkernel) {
memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
@@ -772,9 +779,14 @@ static int wpa_set_associate(PSDevice pDevice,
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming dBm = %d\n", param->u.wpa_associate.roam_dbm); //Davidwang
- if (param->u.wpa_associate.wpa_ie &&
- copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
- return -EINVAL;
+ if (param->u.wpa_associate.wpa_ie) {
+ if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
+ return -EINVAL;
+
+ if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie,
+ param->u.wpa_associate.wpa_ie_len))
+ return -EFAULT;
+ }
if (param->u.wpa_associate.mode == 1)
pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h
index eeedf01..07d835b 100644
--- a/drivers/staging/winbond/mds_s.h
+++ b/drivers/staging/winbond/mds_s.h
@@ -3,7 +3,7 @@
#include <linux/timer.h>
#include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "localpara.h"
#include "mac_structures.h"
diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c
index 79e53e4..77a3fff 100644
--- a/drivers/staging/winbond/phy_calibration.c
+++ b/drivers/staging/winbond/phy_calibration.c
@@ -24,7 +24,7 @@
#define AG_CONST 0.6072529350
#define FIXED(X) ((s32)((X) * 32768.0))
-#define DEG2RAD(X) 0.017453 * (X)
+#define DEG2RAD(X) (0.017453 * (X))
static const s32 Angles[] = {
FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)),
@@ -44,147 +44,147 @@ static const s32 Angles[] = {
s32 _s13_to_s32(u32 data)
{
- u32 val;
+ u32 val;
- val = (data & 0x0FFF);
+ val = (data & 0x0FFF);
- if ((data & BIT(12)) != 0)
- val |= 0xFFFFF000;
+ if ((data & BIT(12)) != 0)
+ val |= 0xFFFFF000;
- return ((s32) val);
+ return (s32) val;
}
u32 _s32_to_s13(s32 data)
{
- u32 val;
+ u32 val;
- if (data > 4095)
- data = 4095;
- else if (data < -4096)
- data = -4096;
+ if (data > 4095)
+ data = 4095;
+ else if (data < -4096)
+ data = -4096;
- val = data & 0x1FFF;
+ val = data & 0x1FFF;
- return val;
+ return val;
}
/****************************************************************************/
s32 _s4_to_s32(u32 data)
{
- s32 val;
+ s32 val;
- val = (data & 0x0007);
+ val = (data & 0x0007);
- if ((data & BIT(3)) != 0)
- val |= 0xFFFFFFF8;
+ if ((data & BIT(3)) != 0)
+ val |= 0xFFFFFFF8;
- return val;
+ return val;
}
u32 _s32_to_s4(s32 data)
{
- u32 val;
+ u32 val;
- if (data > 7)
- data = 7;
- else if (data < -8)
- data = -8;
+ if (data > 7)
+ data = 7;
+ else if (data < -8)
+ data = -8;
- val = data & 0x000F;
+ val = data & 0x000F;
- return val;
+ return val;
}
/****************************************************************************/
s32 _s5_to_s32(u32 data)
{
- s32 val;
+ s32 val;
- val = (data & 0x000F);
+ val = (data & 0x000F);
- if ((data & BIT(4)) != 0)
- val |= 0xFFFFFFF0;
+ if ((data & BIT(4)) != 0)
+ val |= 0xFFFFFFF0;
- return val;
+ return val;
}
u32 _s32_to_s5(s32 data)
{
- u32 val;
+ u32 val;
- if (data > 15)
- data = 15;
- else if (data < -16)
- data = -16;
+ if (data > 15)
+ data = 15;
+ else if (data < -16)
+ data = -16;
- val = data & 0x001F;
+ val = data & 0x001F;
- return val;
+ return val;
}
/****************************************************************************/
s32 _s6_to_s32(u32 data)
{
- s32 val;
+ s32 val;
- val = (data & 0x001F);
+ val = (data & 0x001F);
- if ((data & BIT(5)) != 0)
- val |= 0xFFFFFFE0;
+ if ((data & BIT(5)) != 0)
+ val |= 0xFFFFFFE0;
- return val;
+ return val;
}
u32 _s32_to_s6(s32 data)
{
- u32 val;
+ u32 val;
- if (data > 31)
- data = 31;
- else if (data < -32)
- data = -32;
+ if (data > 31)
+ data = 31;
+ else if (data < -32)
+ data = -32;
- val = data & 0x003F;
+ val = data & 0x003F;
- return val;
+ return val;
}
/****************************************************************************/
s32 _s9_to_s32(u32 data)
{
- s32 val;
+ s32 val;
- val = data & 0x00FF;
+ val = data & 0x00FF;
- if ((data & BIT(8)) != 0)
- val |= 0xFFFFFF00;
+ if ((data & BIT(8)) != 0)
+ val |= 0xFFFFFF00;
- return val;
+ return val;
}
u32 _s32_to_s9(s32 data)
{
- u32 val;
+ u32 val;
- if (data > 255)
- data = 255;
- else if (data < -256)
- data = -256;
+ if (data > 255)
+ data = 255;
+ else if (data < -256)
+ data = -256;
- val = data & 0x01FF;
+ val = data & 0x01FF;
- return val;
+ return val;
}
/****************************************************************************/
s32 _floor(s32 n)
{
- if (n > 0)
- n += 5;
- else
- n -= 5;
+ if (n > 0)
+ n += 5;
+ else
+ n -= 5;
- return (n/10);
+ return n/10;
}
/****************************************************************************/
@@ -195,105 +195,105 @@ s32 _floor(s32 n)
*/
u32 _sqrt(u32 sqsum)
{
- u32 sq_rt;
-
- int g0, g1, g2, g3, g4;
- int seed;
- int next;
- int step;
-
- g4 = sqsum / 100000000;
- g3 = (sqsum - g4*100000000) / 1000000;
- g2 = (sqsum - g4*100000000 - g3*1000000) / 10000;
- g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) / 100;
- g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100);
-
- next = g4;
- step = 0;
- seed = 0;
- while (((seed+1)*(step+1)) <= next) {
- step++;
- seed++;
- }
-
- sq_rt = seed * 10000;
- next = (next-(seed*step))*100 + g3;
-
- step = 0;
- seed = 2 * seed * 10;
- while (((seed+1)*(step+1)) <= next) {
- step++;
- seed++;
- }
-
- sq_rt = sq_rt + step * 1000;
- next = (next - seed * step) * 100 + g2;
- seed = (seed + step) * 10;
- step = 0;
- while (((seed+1)*(step+1)) <= next) {
- step++;
- seed++;
- }
-
- sq_rt = sq_rt + step * 100;
- next = (next - seed * step) * 100 + g1;
- seed = (seed + step) * 10;
- step = 0;
-
- while (((seed+1)*(step+1)) <= next) {
- step++;
- seed++;
- }
-
- sq_rt = sq_rt + step * 10;
- next = (next - seed * step) * 100 + g0;
- seed = (seed + step) * 10;
- step = 0;
-
- while (((seed+1)*(step+1)) <= next) {
- step++;
- seed++;
- }
-
- sq_rt = sq_rt + step;
-
- return sq_rt;
+ u32 sq_rt;
+
+ int g0, g1, g2, g3, g4;
+ int seed;
+ int next;
+ int step;
+
+ g4 = sqsum / 100000000;
+ g3 = (sqsum - g4*100000000) / 1000000;
+ g2 = (sqsum - g4*100000000 - g3*1000000) / 10000;
+ g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) / 100;
+ g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100);
+
+ next = g4;
+ step = 0;
+ seed = 0;
+ while (((seed+1)*(step+1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = seed * 10000;
+ next = (next-(seed*step))*100 + g3;
+
+ step = 0;
+ seed = 2 * seed * 10;
+ while (((seed+1)*(step+1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 1000;
+ next = (next - seed * step) * 100 + g2;
+ seed = (seed + step) * 10;
+ step = 0;
+ while (((seed+1)*(step+1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 100;
+ next = (next - seed * step) * 100 + g1;
+ seed = (seed + step) * 10;
+ step = 0;
+
+ while (((seed+1)*(step+1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 10;
+ next = (next - seed * step) * 100 + g0;
+ seed = (seed + step) * 10;
+ step = 0;
+
+ while (((seed+1)*(step+1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step;
+
+ return sq_rt;
}
/****************************************************************************/
void _sin_cos(s32 angle, s32 *sin, s32 *cos)
{
- s32 X, Y, TargetAngle, CurrAngle;
- unsigned Step;
-
- X = FIXED(AG_CONST); /* AG_CONST * cos(0) */
- Y = 0; /* AG_CONST * sin(0) */
- TargetAngle = abs(angle);
- CurrAngle = 0;
-
- for (Step = 0; Step < 12; Step++) {
- s32 NewX;
-
- if (TargetAngle > CurrAngle) {
- NewX = X - (Y >> Step);
- Y = (X >> Step) + Y;
- X = NewX;
- CurrAngle += Angles[Step];
- } else {
- NewX = X + (Y >> Step);
- Y = -(X >> Step) + Y;
- X = NewX;
- CurrAngle -= Angles[Step];
- }
- }
-
- if (angle > 0) {
- *cos = X;
- *sin = Y;
- } else {
- *cos = X;
- *sin = -Y;
- }
+ s32 X, Y, TargetAngle, CurrAngle;
+ unsigned Step;
+
+ X = FIXED(AG_CONST); /* AG_CONST * cos(0) */
+ Y = 0; /* AG_CONST * sin(0) */
+ TargetAngle = abs(angle);
+ CurrAngle = 0;
+
+ for (Step = 0; Step < 12; Step++) {
+ s32 NewX;
+
+ if (TargetAngle > CurrAngle) {
+ NewX = X - (Y >> Step);
+ Y = (X >> Step) + Y;
+ X = NewX;
+ CurrAngle += Angles[Step];
+ } else {
+ NewX = X + (Y >> Step);
+ Y = -(X >> Step) + Y;
+ X = NewX;
+ CurrAngle -= Angles[Step];
+ }
+ }
+
+ if (angle > 0) {
+ *cos = X;
+ *sin = Y;
+ } else {
+ *cos = X;
+ *sin = -Y;
+ }
}
static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 * pValue)
@@ -338,24 +338,24 @@ void _reset_rx_cal(struct hw_data *phw_data)
/**********************************************/
void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency)
{
- u32 reg_agc_ctrl3;
- u32 reg_a_acq_ctrl;
- u32 reg_b_acq_ctrl;
- u32 val;
+ u32 reg_agc_ctrl3;
+ u32 reg_a_acq_ctrl;
+ u32 reg_b_acq_ctrl;
+ u32 val;
- PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n"));
- phy_init_rf(phw_data);
+ PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n"));
+ phy_init_rf(phw_data);
- /* set calibration channel */
- if ((RF_WB_242 == phw_data->phy_type) ||
+ /* set calibration channel */
+ if ((RF_WB_242 == phw_data->phy_type) ||
(RF_WB_242_1 == phw_data->phy_type)) /* 20060619.5 Add */{
- if ((frequency >= 2412) && (frequency <= 2484)) {
- /* w89rf242 change frequency to 2390Mhz */
- PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n"));
+ if ((frequency >= 2412) && (frequency <= 2484)) {
+ /* w89rf242 change frequency to 2390Mhz */
+ PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n"));
phy_set_rf_data(phw_data, 3, (3<<24)|0x025586);
- }
- } else {
+ }
+ } else {
}
@@ -455,7 +455,7 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data)
phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
/* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */
phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
- /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
+ /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
/* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */
phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
@@ -542,7 +542,7 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data)
}
if (loop >= 19)
- fix_cancel_dc_i = 0;
+ fix_cancel_dc_i = 0;
reg_dc_cancel &= ~(0x03FF);
reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_i) << CANCEL_DC_I_SHIFT);
@@ -577,7 +577,7 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data)
phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
/* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */
phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
- /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
+ /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
/* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */
phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
@@ -657,7 +657,7 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data)
}
if (loop >= 19)
- fix_cancel_dc_q = 0;
+ fix_cancel_dc_q = 0;
reg_dc_cancel &= ~(0x001F);
reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_q) << CANCEL_DC_Q_SHIFT);
@@ -974,7 +974,7 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data)
phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); /* 20060612.1.a 0x1905D6); */
/* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */
phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); /* 0x24C60A (high temperature) */
- /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
+ /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); /* 20060612.1.a 0x06890C); */
/* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */
phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
@@ -1154,33 +1154,33 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
capture_time = 0;
for (capture_time = 0; capture_time < 10; capture_time++) {
- /* i. Set "calib_start" to 0x0 */
- reg_mode_ctrl &= ~MASK_CALIB_START;
- if (!hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl))/*20060718.1 modify */
- return 0;
- PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ /* i. Set "calib_start" to 0x0 */
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ if (!hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl))/*20060718.1 modify */
+ return 0;
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
- reg_mode_ctrl &= ~MASK_IQCAL_MODE;
- reg_mode_ctrl |= (MASK_CALIB_START|0x1);
- hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
- PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ reg_mode_ctrl &= ~MASK_IQCAL_MODE;
+ reg_mode_ctrl |= (MASK_CALIB_START|0x1);
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
- /* c. */
- hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
- PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
+ /* c. */
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
- iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
- iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
- PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
- iqcal_tone_i, iqcal_tone_q));
+ iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
+ iqcal_tone_i, iqcal_tone_q));
- hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
- PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
- iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
- iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
- PHY_DEBUG(("[CAL] ** iqcal_image_i = %d, iqcal_image_q = %d\n",
- iqcal_image_i, iqcal_image_q));
+ iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_image_i = %d, iqcal_image_q = %d\n",
+ iqcal_image_i, iqcal_image_q));
if (capture_time == 0)
continue;
else {
@@ -1358,7 +1358,7 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
hw_set_dxx_reg(phw_data, 0x54, val);
if (loop == 3)
- return 0;
+ return 0;
}
PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val));
@@ -1476,40 +1476,40 @@ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency)
/******************/
void phy_set_rf_data(struct hw_data *pHwData, u32 index, u32 value)
{
- u32 ltmp = 0;
-
- switch (pHwData->phy_type) {
- case RF_MAXIM_2825:
- case RF_MAXIM_V1: /* 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) */
- ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
- break;
-
- case RF_MAXIM_2827:
- ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
- break;
-
- case RF_MAXIM_2828:
- ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
- break;
-
- case RF_MAXIM_2829:
- ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
- break;
-
- case RF_AIROHA_2230:
- case RF_AIROHA_2230S: /* 20060420 Add this */
- ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse(value, 20);
- break;
-
- case RF_AIROHA_7230:
- ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff);
- break;
-
- case RF_WB_242:
- case RF_WB_242_1:/* 20060619.5 Add */
- ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse(value, 24);
- break;
- }
+ u32 ltmp = 0;
+
+ switch (pHwData->phy_type) {
+ case RF_MAXIM_2825:
+ case RF_MAXIM_V1: /* 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) */
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+ break;
+
+ case RF_MAXIM_2827:
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+ break;
+
+ case RF_MAXIM_2828:
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+ break;
+
+ case RF_MAXIM_2829:
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+ break;
+
+ case RF_AIROHA_2230:
+ case RF_AIROHA_2230S: /* 20060420 Add this */
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse(value, 20);
+ break;
+
+ case RF_AIROHA_7230:
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff);
+ break;
+
+ case RF_WB_242:
+ case RF_WB_242_1:/* 20060619.5 Add */
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse(value, 24);
+ break;
+ }
Wb35Reg_WriteSync(pHwData, 0x0864, ltmp);
}
diff --git a/drivers/staging/winbond/wb35reg_s.h b/drivers/staging/winbond/wb35reg_s.h
index eb274ff..dc79faa 100644
--- a/drivers/staging/winbond/wb35reg_s.h
+++ b/drivers/staging/winbond/wb35reg_s.h
@@ -3,7 +3,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct hw_data;
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 02f9eb8..3f0ce2b 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -11,6 +11,7 @@
*/
#include <net/mac80211.h>
#include <linux/usb.h>
+#include <linux/module.h>
#include "core.h"
#include "mds_f.h"
@@ -277,7 +278,7 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
return 0;
}
-static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
+static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
{
printk("wbsoft_get_tsf called\n");
return 0;
diff --git a/drivers/staging/wlags49_h2/Makefile b/drivers/staging/wlags49_h2/Makefile
index e604ebd..31e1d89 100644
--- a/drivers/staging/wlags49_h2/Makefile
+++ b/drivers/staging/wlags49_h2/Makefile
@@ -11,11 +11,9 @@
#
# If you want to build AP support (untested), comment out -DSTA_ONLY
-INSTALLDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless
ccflags-y := -I$(KERNELDIR)/include
ccflags-y += -I$(src) \
-DBUS_PCMCIA \
- -DUSE_WPA \
-DUSE_WEXT \
-DSTA_ONLY \
-DWVLAN_49 \
@@ -39,9 +37,6 @@ $(WLNAME)-y += ap_h25.o
endif
endif
-# If KERNELRELEASE is defined, we've been invoked from the
-# kernel build system and can use its language.
-ifneq ($(KERNELRELEASE),)
obj-m += $(WLNAME).o
@@ -58,24 +53,3 @@ $(WLNAME)-y += wl_profile.o \
dhf.o
$(WLNAME)-$(CONFIG_SYSFS) += wl_sysfs.o
-
-# Otherwise we were called directly from the command
-# line; invoke the kernel build system.
-else
- KERNELDIR ?= /lib/modules/$(shell uname -r)/build
- PWD := $(shell pwd)
-
-default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
-endif
-
-clean:
- rm -fr *.o *.ko *.mod.c *.mod.o .*.*.cmd Module.symvers \
- Module.markers modules.order .tmp_versions
-
-install: default
- -rmmod $(WLNAME)
- install -d $(INSTALLDIR)
- install -m 0644 -o root -g root $(WLNAME).ko $(INSTALLDIR)
- /sbin/depmod -aq
-
diff --git a/drivers/staging/wlags49_h2/debug.h b/drivers/staging/wlags49_h2/debug.h
index 2c3dd14..8d5dddf 100644
--- a/drivers/staging/wlags49_h2/debug.h
+++ b/drivers/staging/wlags49_h2/debug.h
@@ -129,11 +129,15 @@
#define _LEAVE_STR "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
-#define _DBG_ENTER(A) DBG_PRINT("%s:%.*s:%s\n", DBG_NAME(A), ++DBG_LEVEL(A), _ENTER_STR, __FUNC__)
-#define _DBG_LEAVE(A) DBG_PRINT("%s:%.*s:%s\n", DBG_NAME(A), DBG_LEVEL(A)--, _LEAVE_STR, __FUNC__)
+#define _DBG_ENTER(A) \
+ DBG_PRINT("%s:%.*s:%s\n", DBG_NAME(A), ++DBG_LEVEL(A), \
+ _ENTER_STR, __func__)
+#define _DBG_LEAVE(A) \
+ DBG_PRINT("%s:%.*s:%s\n", DBG_NAME(A), DBG_LEVEL(A)--, \
+ _LEAVE_STR, __func__)
-#define DBG_FUNC(F) static const char *__FUNC__ = F;
+#define DBG_FUNC(F)
#define DBG_ENTER(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
_DBG_ENTER(A); }
@@ -145,29 +149,33 @@
DBG_PRINT(" %s -- "F"\n", N, S); }
-#define DBG_ERROR(A, S...) {if (DBG_FLAGS(A) & DBG_ERROR_ON) {\
- DBG_PRINT("%s:ERROR:%s ", DBG_NAME(A), __FUNC__);\
- DBG_PRINTC(S); \
- DBG_TRAP; \
- } \
- }
+#define DBG_ERROR(A, S...) do { \
+ if (DBG_FLAGS(A) & DBG_ERROR_ON) { \
+ DBG_PRINT("%s:ERROR:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ DBG_TRAP; \
+ } } while (0)
-#define DBG_WARNING(A, S...) {if (DBG_FLAGS(A) & DBG_WARNING_ON) {\
- DBG_PRINT("%s:WARNING:%s ", DBG_NAME(A), __FUNC__);\
- DBG_PRINTC(S); } }
+#define DBG_WARNING(A, S...) do { \
+ if (DBG_FLAGS(A) & DBG_WARNING_ON) { \
+ DBG_PRINT("%s:WARNING:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } } while (0)
-#define DBG_NOTICE(A, S...) {if (DBG_FLAGS(A) & DBG_NOTICE_ON) {\
- DBG_PRINT("%s:NOTICE:%s ", DBG_NAME(A), __FUNC__);\
- DBG_PRINTC(S); \
- } \
- }
+#define DBG_NOTICE(A, S...) do { \
+ if (DBG_FLAGS(A) & DBG_NOTICE_ON) { \
+ DBG_PRINT("%s:NOTICE:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } } while (0)
-#define DBG_TRACE(A, S...) do {if (DBG_FLAGS(A) & DBG_TRACE_ON) {\
- DBG_PRINT("%s:%s ", DBG_NAME(A), __FUNC__);\
- DBG_PRINTC(S); } } while (0)
+#define DBG_TRACE(A, S...) do { \
+ if (DBG_FLAGS(A) & DBG_TRACE_ON) { \
+ DBG_PRINT("%s:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } } while (0)
#define DBG_RX(A, S...) {if (DBG_FLAGS(A) & DBG_RX_ON) {\
@@ -181,13 +189,12 @@
DBG_PRINT(S); } }
-#define DBG_ASSERT(C) { \
- if (!(C)) {\
- DBG_PRINT("ASSERT(%s) -- %s#%d (%s)\n", \
- #C, __FILE__, __LINE__, __FUNC__); \
- DBG_TRAP; \
- } \
- }
+#define DBG_ASSERT(C) do { \
+ if (!(C)) { \
+ DBG_PRINT("ASSERT(%s) -- %s#%d (%s)\n", \
+ #C, __FILE__, __LINE__, __func__); \
+ DBG_TRAP; \
+ } } while (0)
typedef struct {
char *dbgName;
diff --git a/drivers/staging/wlags49_h2/hcf.c b/drivers/staging/wlags49_h2/hcf.c
index a73317e..7dc176a 100644
--- a/drivers/staging/wlags49_h2/hcf.c
+++ b/drivers/staging/wlags49_h2/hcf.c
@@ -1,97 +1,96 @@
-// vim:tw=110:ts=4:
/************************************************************************************************************
-*
-* FILE : HCF.C
-*
-* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.10 $
-* Original: 2004/06/02 10:22:22 Revision: 1.85 Tag: hcf7_t20040602_01
-* Original: 2004/04/15 09:24:41 Revision: 1.63 Tag: hcf7_t7_20040415_01
-* Original: 2004/04/13 14:22:44 Revision: 1.62 Tag: t7_20040413_01
-* Original: 2004/04/01 15:32:55 Revision: 1.59 Tag: t7_20040401_01
-* Original: 2004/03/10 15:39:27 Revision: 1.55 Tag: t20040310_01
-* Original: 2004/03/04 11:03:37 Revision: 1.53 Tag: t20040304_01
-* Original: 2004/03/02 14:51:21 Revision: 1.50 Tag: t20040302_03
-* Original: 2004/02/24 13:00:27 Revision: 1.43 Tag: t20040224_01
-* Original: 2004/02/19 10:57:25 Revision: 1.39 Tag: t20040219_01
-*
-* AUTHOR : Nico Valster
-*
-* SPECIFICATION: ........
-*
-* DESCRIPTION : HCF Routines for Hermes-II (callable via the Wireless Connection I/F or WCI)
-* Local Support Routines for above procedures
-*
-* Customizable via HCFCFG.H, which is included by HCF.H
-*
-*************************************************************************************************************
-*
-*
-* SOFTWARE LICENSE
-*
-* This software is provided subject to the following terms and conditions,
-* which you should read carefully before using the software. Using this
-* software indicates your acceptance of these terms and conditions. If you do
-* not agree with these terms and conditions, do not use the software.
-*
-* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved
-* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved
-* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved
-* All rights reserved.
-*
-* Redistribution and use in source or binary forms, with or without
-* modifications, are permitted provided that the following conditions are met:
-*
-* . Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following Disclaimer as comments in the code as
-* well as in the documentation and/or other materials provided with the
-* distribution.
-*
-* . Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following Disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* . Neither the name of Agere Systems Inc. nor the names of the contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* Disclaimer
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
-* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
-* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
-* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-* ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-* DAMAGE.
-*
-*
-************************************************************************************************************/
+ *
+ * FILE : HCF.C
+ *
+ * DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.10 $
+ * Original: 2004/06/02 10:22:22 Revision: 1.85 Tag: hcf7_t20040602_01
+ * Original: 2004/04/15 09:24:41 Revision: 1.63 Tag: hcf7_t7_20040415_01
+ * Original: 2004/04/13 14:22:44 Revision: 1.62 Tag: t7_20040413_01
+ * Original: 2004/04/01 15:32:55 Revision: 1.59 Tag: t7_20040401_01
+ * Original: 2004/03/10 15:39:27 Revision: 1.55 Tag: t20040310_01
+ * Original: 2004/03/04 11:03:37 Revision: 1.53 Tag: t20040304_01
+ * Original: 2004/03/02 14:51:21 Revision: 1.50 Tag: t20040302_03
+ * Original: 2004/02/24 13:00:27 Revision: 1.43 Tag: t20040224_01
+ * Original: 2004/02/19 10:57:25 Revision: 1.39 Tag: t20040219_01
+ *
+ * AUTHOR : Nico Valster
+ *
+ * SPECIFICATION: ........
+ *
+ * DESCRIPTION : HCF Routines for Hermes-II (callable via the Wireless Connection I/F or WCI)
+ * Local Support Routines for above procedures
+ *
+ * Customizable via HCFCFG.H, which is included by HCF.H
+ *
+ *************************************************************************************************************
+ *
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved
+ * COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved
+ * COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following Disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ ************************************************************************************************************/
/************************************************************************************************************
-**
-** Implementation Notes
-**
-* - a leading marker of //! is used. The purpose of such a sequence is to help to understand the flow
-* An example is: //!rc = HCF_SUCCESS;
-* if this is superfluous because rc is already guaranteed to be 0 but it shows to the (maintenance)
-* programmer it is an intentional omission at the place where someone could consider it most appropriate at
-* first glance
-* - using near pointers in a model where ss!=ds is an invitation for disaster, so be aware of how you specify
-* your model and how you define variables which are used at interrupt time
-* - remember that sign extension on 32 bit platforms may cause problems unless code is carefully constructed,
-* e.g. use "(hcf_16)~foo" rather than "~foo"
-*
-************************************************************************************************************/
+ **
+ ** Implementation Notes
+ **
+ * - a leading marker of //! is used. The purpose of such a sequence is to help to understand the flow
+ * An example is: //!rc = HCF_SUCCESS;
+ * if this is superfluous because rc is already guaranteed to be 0 but it shows to the (maintenance)
+ * programmer it is an intentional omission at the place where someone could consider it most appropriate at
+ * first glance
+ * - using near pointers in a model where ss!=ds is an invitation for disaster, so be aware of how you specify
+ * your model and how you define variables which are used at interrupt time
+ * - remember that sign extension on 32 bit platforms may cause problems unless code is carefully constructed,
+ * e.g. use "(hcf_16)~foo" rather than "~foo"
+ *
+ ************************************************************************************************************/
-#include "hcf.h" // HCF and MSF common include file
-#include "hcfdef.h" // HCF specific include file
-#include "mmd.h" // MoreModularDriver common include file
+#include "hcf.h" // HCF and MSF common include file
+#include "hcfdef.h" // HCF specific include file
+#include "mmd.h" // MoreModularDriver common include file
#include <linux/kernel.h>
#if ! defined offsetof
@@ -102,56 +101,52 @@
/***********************************************************************************************************/
/*************************************** PROTOTYPES ******************************************************/
/***********************************************************************************************************/
-HCF_STATIC int cmd_exe( IFBP ifbp, hcf_16 cmd_code, hcf_16 par_0 );
-HCF_STATIC int init( IFBP ifbp );
-HCF_STATIC int put_info( IFBP ifbp, LTVP ltvp );
-#if (HCF_EXT) & HCF_EXT_MB
-HCF_STATIC int put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp );
-#endif // HCF_EXT_MB
+HCF_STATIC int cmd_exe( IFBP ifbp, hcf_16 cmd_code, hcf_16 par_0 );
+HCF_STATIC int init( IFBP ifbp );
+HCF_STATIC int put_info( IFBP ifbp, LTVP ltvp );
+HCF_STATIC int put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp );
#if (HCF_TYPE) & HCF_TYPE_WPA
-HCF_STATIC void calc_mic( hcf_32* p, hcf_32 M );
-void calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len );
-void calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len );
-HCF_STATIC int check_mic( IFBP ifbp );
+HCF_STATIC void calc_mic( hcf_32* p, hcf_32 M );
+void calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len );
+void calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len );
+HCF_STATIC int check_mic( IFBP ifbp );
#endif // HCF_TYPE_WPA
-HCF_STATIC void calibrate( IFBP ifbp );
-HCF_STATIC int cmd_cmpl( IFBP ifbp );
-HCF_STATIC hcf_16 get_fid( IFBP ifbp );
-HCF_STATIC void isr_info( IFBP ifbp );
+HCF_STATIC void calibrate( IFBP ifbp );
+HCF_STATIC int cmd_cmpl( IFBP ifbp );
+HCF_STATIC hcf_16 get_fid( IFBP ifbp );
+HCF_STATIC void isr_info( IFBP ifbp );
#if HCF_DMA
-HCF_STATIC DESC_STRCT* get_frame_lst(IFBP ifbp, int tx_rx_flag);
+HCF_STATIC DESC_STRCT* get_frame_lst(IFBP ifbp, int tx_rx_flag);
#endif // HCF_DMA
-HCF_STATIC void get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ); //char*, byte count (usually even)
+HCF_STATIC void get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ); //char*, byte count (usually even)
#if HCF_DMA
-HCF_STATIC void put_frame_lst( IFBP ifbp, DESC_STRCT *descp, int tx_rx_flag );
+HCF_STATIC void put_frame_lst( IFBP ifbp, DESC_STRCT *descp, int tx_rx_flag );
#endif // HCF_DMA
-HCF_STATIC void put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) );
-HCF_STATIC void put_frag_finalize( IFBP ifbp );
-HCF_STATIC int setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type );
+HCF_STATIC void put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) );
+HCF_STATIC void put_frag_finalize( IFBP ifbp );
+HCF_STATIC int setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type );
#if (HCF_ASSERT) & HCF_ASSERT_PRINTF
static int fw_printf(IFBP ifbp, CFG_FW_PRINTF_STRCT FAR *ltvp);
#endif // HCF_ASSERT_PRINTF
-HCF_STATIC int download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp );
-#if (HCF_ENCAP) & HCF_ENC
-HCF_STATIC hcf_8 hcf_encap( wci_bufp type );
-#endif // HCF_ENCAP
-HCF_STATIC hcf_8 null_addr[4] = { 0, 0, 0, 0 };
-#if ! defined IN_PORT_WORD //replace I/O Macros with logging facility
+HCF_STATIC int download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp );
+HCF_STATIC hcf_8 hcf_encap( wci_bufp type );
+HCF_STATIC hcf_8 null_addr[4] = { 0, 0, 0, 0 };
+#if ! defined IN_PORT_WORD //replace I/O Macros with logging facility
extern FILE *log_file;
-#define IN_PORT_WORD(port) in_port_word( (hcf_io)(port) )
+#define IN_PORT_WORD(port) in_port_word( (hcf_io)(port) )
static hcf_16 in_port_word( hcf_io port ) {
-hcf_16 i = (hcf_16)_inpw( port );
+ hcf_16 i = (hcf_16)_inpw( port );
if ( log_file ) {
fprintf( log_file, "\nR %2.2x %4.4x", (port)&0xFF, i);
}
return i;
} // in_port_word
-#define OUT_PORT_WORD(port, value) out_port_word( (hcf_io)(port), (hcf_16)(value) )
+#define OUT_PORT_WORD(port, value) out_port_word( (hcf_io)(port), (hcf_16)(value) )
static void out_port_word( hcf_io port, hcf_16 value ) {
_outpw( port, value );
@@ -160,12 +155,12 @@ static void out_port_word( hcf_io port, hcf_16 value ) {
}
}
-void IN_PORT_STRING_32( hcf_io prt, hcf_32 FAR * dst, int n) {
+void IN_PORT_STRING_32( hcf_io prt, hcf_32 FAR * dst, int n) {
int i = 0;
hcf_16 FAR * p;
if ( log_file ) {
fprintf( log_file, "\nread string_32 length %04x (%04d) at port %02.2x to addr %lp",
- (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF, dst);
+ (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF, dst);
}
while ( n-- ) {
p = (hcf_16 FAR *)dst;
@@ -178,12 +173,12 @@ void IN_PORT_STRING_32( hcf_io prt, hcf_32 FAR * dst, int n) {
}
} // IN_PORT_STRING_32
-void IN_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * dst, int n) { //also handles byte alignment problems
- hcf_16 FAR * p = (hcf_16 FAR *)dst; //this needs more elaborate code in non-x86 platforms
+void IN_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * dst, int n) { //also handles byte alignment problems
+ hcf_16 FAR * p = (hcf_16 FAR *)dst; //this needs more elaborate code in non-x86 platforms
int i = 0;
if ( log_file ) {
fprintf( log_file, "\nread string_16 length %04x (%04d) at port %02.2x to addr %lp",
- (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF, dst );
+ (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF, dst );
}
while ( n-- ) {
*p =(hcf_16)_inpw( prt);
@@ -198,12 +193,12 @@ void IN_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * dst, int n) { //also handles b
}
} // IN_PORT_STRING_8_16
-void OUT_PORT_STRING_32( hcf_io prt, hcf_32 FAR * src, int n) {
+void OUT_PORT_STRING_32( hcf_io prt, hcf_32 FAR * src, int n) {
int i = 0;
hcf_16 FAR * p;
if ( log_file ) {
fprintf( log_file, "\nwrite string_32 length %04x (%04d) at port %02.2x",
- (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF);
+ (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF);
}
while ( n-- ) {
p = (hcf_16 FAR *)src;
@@ -216,8 +211,8 @@ void OUT_PORT_STRING_32( hcf_io prt, hcf_32 FAR * src, int n) {
}
} // OUT_PORT_STRING_32
-void OUT_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * src, int n) { //also handles byte alignment problems
- hcf_16 FAR * p = (hcf_16 FAR *)src; //this needs more elaborate code in non-x86 platforms
+void OUT_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * src, int n) { //also handles byte alignment problems
+ hcf_16 FAR * p = (hcf_16 FAR *)src; //this needs more elaborate code in non-x86 platforms
int i = 0;
if ( log_file ) {
fprintf( log_file, "\nwrite string_16 length %04x (%04d) at port %04x", n, n, (hcf_16)prt);
@@ -238,27 +233,25 @@ void OUT_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * src, int n) { //also handles
#endif // IN_PORT_WORD
/************************************************************************************************************
-******************************* D A T A D E F I N I T I O N S ********************************************
-************************************************************************************************************/
+ ******************************* D A T A D E F I N I T I O N S ********************************************
+ ************************************************************************************************************/
#if HCF_ASSERT
-IFBP BASED assert_ifbp = NULL; //to make asserts easily work under MMD and DHF
+IFBP BASED assert_ifbp = NULL; //to make asserts easily work under MMD and DHF
#endif // HCF_ASSERT
-#if HCF_ENCAP
/* SNAP header to be inserted in Ethernet-II frames */
-HCF_STATIC hcf_8 BASED snap_header[] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, //5 bytes signature +
- 0 }; //1 byte protocol identifier
-#endif // HCF_ENCAP
+HCF_STATIC hcf_8 BASED snap_header[] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, //5 bytes signature +
+ 0 }; //1 byte protocol identifier
#if (HCF_TYPE) & HCF_TYPE_WPA
-HCF_STATIC hcf_8 BASED mic_pad[8] = { 0x5A, 0, 0, 0, 0, 0, 0, 0 }; //MIC padding of message
+HCF_STATIC hcf_8 BASED mic_pad[8] = { 0x5A, 0, 0, 0, 0, 0, 0, 0 }; //MIC padding of message
#endif // HCF_TYPE_WPA
#if defined MSF_COMPONENT_ID
CFG_IDENTITY_STRCT BASED cfg_drv_identity = {
- sizeof(cfg_drv_identity)/sizeof(hcf_16) - 1, //length of RID
- CFG_DRV_IDENTITY, // (0x0826)
+ sizeof(cfg_drv_identity)/sizeof(hcf_16) - 1, //length of RID
+ CFG_DRV_IDENTITY, // (0x0826)
MSF_COMPONENT_ID,
MSF_COMPONENT_VAR,
MSF_COMPONENT_MAJOR_VER,
@@ -266,186 +259,186 @@ CFG_IDENTITY_STRCT BASED cfg_drv_identity = {
} ;
CFG_RANGES_STRCT BASED cfg_drv_sup_range = {
- sizeof(cfg_drv_sup_range)/sizeof(hcf_16) - 1, //length of RID
- CFG_DRV_SUP_RANGE, // (0x0827)
+ sizeof(cfg_drv_sup_range)/sizeof(hcf_16) - 1, //length of RID
+ CFG_DRV_SUP_RANGE, // (0x0827)
COMP_ROLE_SUPL,
COMP_ID_DUI,
- {{ DUI_COMPAT_VAR,
- DUI_COMPAT_BOT,
- DUI_COMPAT_TOP
+ {{ DUI_COMPAT_VAR,
+ DUI_COMPAT_BOT,
+ DUI_COMPAT_TOP
}}
} ;
struct CFG_RANGE3_STRCT BASED cfg_drv_act_ranges_pri = {
- sizeof(cfg_drv_act_ranges_pri)/sizeof(hcf_16) - 1, //length of RID
- CFG_DRV_ACT_RANGES_PRI, // (0x0828)
+ sizeof(cfg_drv_act_ranges_pri)/sizeof(hcf_16) - 1, //length of RID
+ CFG_DRV_ACT_RANGES_PRI, // (0x0828)
COMP_ROLE_ACT,
COMP_ID_PRI,
{
- { 0, 0, 0 }, // HCF_PRI_VAR_1 not supported by HCF 7
- { 0, 0, 0 }, // HCF_PRI_VAR_2 not supported by HCF 7
- { 3, //var_rec[2] - Variant number
- CFG_DRV_ACT_RANGES_PRI_3_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_PRI_3_TOP // - Top Compatibility
- }
+ { 0, 0, 0 }, // HCF_PRI_VAR_1 not supported by HCF 7
+ { 0, 0, 0 }, // HCF_PRI_VAR_2 not supported by HCF 7
+ { 3, //var_rec[2] - Variant number
+ CFG_DRV_ACT_RANGES_PRI_3_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_PRI_3_TOP // - Top Compatibility
+ }
}
} ;
struct CFG_RANGE4_STRCT BASED cfg_drv_act_ranges_sta = {
- sizeof(cfg_drv_act_ranges_sta)/sizeof(hcf_16) - 1, //length of RID
- CFG_DRV_ACT_RANGES_STA, // (0x0829)
+ sizeof(cfg_drv_act_ranges_sta)/sizeof(hcf_16) - 1, //length of RID
+ CFG_DRV_ACT_RANGES_STA, // (0x0829)
COMP_ROLE_ACT,
COMP_ID_STA,
{
#if defined HCF_STA_VAR_1
- { 1, //var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_STA_1_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_STA_1_TOP // - Top Compatibility
- },
+ { 1, //var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_STA_1_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_STA_1_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_STA_VAR_1
#if defined HCF_STA_VAR_2
- { 2, //var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_STA_2_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_STA_2_TOP // - Top Compatibility
- },
+ { 2, //var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_STA_2_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_STA_2_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_STA_VAR_2
// For Native_USB (Not used!)
#if defined HCF_STA_VAR_3
- { 3, //var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_STA_3_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_STA_3_TOP // - Top Compatibility
- },
+ { 3, //var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_STA_3_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_STA_3_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_STA_VAR_3
// Warp
#if defined HCF_STA_VAR_4
- { 4, //var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_STA_4_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_STA_4_TOP // - Top Compatibility
- }
+ { 4, //var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_STA_4_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_STA_4_TOP // - Top Compatibility
+ }
#else
- { 0, 0, 0 }
+ { 0, 0, 0 }
#endif // HCF_STA_VAR_4
}
} ;
struct CFG_RANGE6_STRCT BASED cfg_drv_act_ranges_hsi = {
- sizeof(cfg_drv_act_ranges_hsi)/sizeof(hcf_16) - 1, //length of RID
- CFG_DRV_ACT_RANGES_HSI, // (0x082A)
+ sizeof(cfg_drv_act_ranges_hsi)/sizeof(hcf_16) - 1, //length of RID
+ CFG_DRV_ACT_RANGES_HSI, // (0x082A)
COMP_ROLE_ACT,
COMP_ID_HSI,
{
-#if defined HCF_HSI_VAR_0 // Controlled deployment
- { 0, // var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_HSI_0_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_HSI_0_TOP // - Top Compatibility
- },
+#if defined HCF_HSI_VAR_0 // Controlled deployment
+ { 0, // var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_HSI_0_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_HSI_0_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_HSI_VAR_0
- { 0, 0, 0 }, // HCF_HSI_VAR_1 not supported by HCF 7
- { 0, 0, 0 }, // HCF_HSI_VAR_2 not supported by HCF 7
- { 0, 0, 0 }, // HCF_HSI_VAR_3 not supported by HCF 7
-#if defined HCF_HSI_VAR_4 // Hermes-II all types
- { 4, // var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_HSI_4_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_HSI_4_TOP // - Top Compatibility
- },
+ { 0, 0, 0 }, // HCF_HSI_VAR_1 not supported by HCF 7
+ { 0, 0, 0 }, // HCF_HSI_VAR_2 not supported by HCF 7
+ { 0, 0, 0 }, // HCF_HSI_VAR_3 not supported by HCF 7
+#if defined HCF_HSI_VAR_4 // Hermes-II all types
+ { 4, // var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_HSI_4_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_HSI_4_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_HSI_VAR_4
-#if defined HCF_HSI_VAR_5 // WARP Hermes-2.5
- { 5, // var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_HSI_5_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_HSI_5_TOP // - Top Compatibility
- }
+#if defined HCF_HSI_VAR_5 // WARP Hermes-2.5
+ { 5, // var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_HSI_5_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_HSI_5_TOP // - Top Compatibility
+ }
#else
- { 0, 0, 0 }
+ { 0, 0, 0 }
#endif // HCF_HSI_VAR_5
}
} ;
CFG_RANGE4_STRCT BASED cfg_drv_act_ranges_apf = {
- sizeof(cfg_drv_act_ranges_apf)/sizeof(hcf_16) - 1, //length of RID
- CFG_DRV_ACT_RANGES_APF, // (0x082B)
+ sizeof(cfg_drv_act_ranges_apf)/sizeof(hcf_16) - 1, //length of RID
+ CFG_DRV_ACT_RANGES_APF, // (0x082B)
COMP_ROLE_ACT,
COMP_ID_APF,
{
-#if defined HCF_APF_VAR_1 //(Fake) Hermes-I
- { 1, //var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_APF_1_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_APF_1_TOP // - Top Compatibility
- },
+#if defined HCF_APF_VAR_1 //(Fake) Hermes-I
+ { 1, //var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_APF_1_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_APF_1_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_APF_VAR_1
-#if defined HCF_APF_VAR_2 //Hermes-II
- { 2, // var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_APF_2_BOTTOM, // - Bottom Compatibility
- CFG_DRV_ACT_RANGES_APF_2_TOP // - Top Compatibility
- },
+#if defined HCF_APF_VAR_2 //Hermes-II
+ { 2, // var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_APF_2_BOTTOM, // - Bottom Compatibility
+ CFG_DRV_ACT_RANGES_APF_2_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_APF_VAR_2
-#if defined HCF_APF_VAR_3 // Native_USB
- { 3, // var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_APF_3_BOTTOM, // - Bottom Compatibility !!!!!see note below!!!!!!!
- CFG_DRV_ACT_RANGES_APF_3_TOP // - Top Compatibility
- },
+#if defined HCF_APF_VAR_3 // Native_USB
+ { 3, // var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_APF_3_BOTTOM, // - Bottom Compatibility !!!!!see note below!!!!!!!
+ CFG_DRV_ACT_RANGES_APF_3_TOP // - Top Compatibility
+ },
#else
- { 0, 0, 0 },
+ { 0, 0, 0 },
#endif // HCF_APF_VAR_3
-#if defined HCF_APF_VAR_4 // WARP Hermes 2.5
- { 4, // var_rec[1] - Variant number
- CFG_DRV_ACT_RANGES_APF_4_BOTTOM, // - Bottom Compatibility !!!!!see note below!!!!!!!
- CFG_DRV_ACT_RANGES_APF_4_TOP // - Top Compatibility
- }
+#if defined HCF_APF_VAR_4 // WARP Hermes 2.5
+ { 4, // var_rec[1] - Variant number
+ CFG_DRV_ACT_RANGES_APF_4_BOTTOM, // - Bottom Compatibility !!!!!see note below!!!!!!!
+ CFG_DRV_ACT_RANGES_APF_4_TOP // - Top Compatibility
+ }
#else
- { 0, 0, 0 }
+ { 0, 0, 0 }
#endif // HCF_APF_VAR_4
}
} ;
#define HCF_VERSION TEXT( "HCF$Revision: 1.10 $" )
static struct /*CFG_HCF_OPT_STRCT*/ {
- hcf_16 len; //length of cfg_hcf_opt struct
- hcf_16 typ; //type 0x082C
- hcf_16 v0; //offset HCF_VERSION
- hcf_16 v1; // MSF_COMPONENT_ID
- hcf_16 v2; // HCF_ALIGN
- hcf_16 v3; // HCF_ASSERT
- hcf_16 v4; // HCF_BIG_ENDIAN
- hcf_16 v5; // /* HCF_DLV | HCF_DLNV */
- hcf_16 v6; // HCF_DMA
- hcf_16 v7; // HCF_ENCAP
- hcf_16 v8; // HCF_EXT
- hcf_16 v9; // HCF_INT_ON
- hcf_16 v10; // HCF_IO
- hcf_16 v11; // HCF_LEGACY
- hcf_16 v12; // HCF_MAX_LTV
- hcf_16 v13; // HCF_PROT_TIME
- hcf_16 v14; // HCF_SLEEP
- hcf_16 v15; // HCF_TALLIES
- hcf_16 v16; // HCF_TYPE
- hcf_16 v17; // HCF_NIC_TAL_CNT
- hcf_16 v18; // HCF_HCF_TAL_CNT
- hcf_16 v19; // offset tallies
- TCHAR val[sizeof(HCF_VERSION)];
+ hcf_16 len; //length of cfg_hcf_opt struct
+ hcf_16 typ; //type 0x082C
+ hcf_16 v0; //offset HCF_VERSION
+ hcf_16 v1; // MSF_COMPONENT_ID
+ hcf_16 v2; // HCF_ALIGN
+ hcf_16 v3; // HCF_ASSERT
+ hcf_16 v4; // HCF_BIG_ENDIAN
+ hcf_16 v5; // /* HCF_DLV | HCF_DLNV */
+ hcf_16 v6; // HCF_DMA
+ hcf_16 v7; // HCF_ENCAP
+ hcf_16 v8; // HCF_EXT
+ hcf_16 v9; // HCF_INT_ON
+ hcf_16 v10; // HCF_IO
+ hcf_16 v11; // HCF_LEGACY
+ hcf_16 v12; // HCF_MAX_LTV
+ hcf_16 v13; // HCF_PROT_TIME
+ hcf_16 v14; // HCF_SLEEP
+ hcf_16 v15; // HCF_TALLIES
+ hcf_16 v16; // HCF_TYPE
+ hcf_16 v17; // HCF_NIC_TAL_CNT
+ hcf_16 v18; // HCF_HCF_TAL_CNT
+ hcf_16 v19; // offset tallies
+ char val[sizeof(HCF_VERSION)];
} BASED cfg_hcf_opt = {
sizeof(cfg_hcf_opt)/sizeof(hcf_16) -1,
- CFG_HCF_OPT, // (0x082C)
+ CFG_HCF_OPT, // (0x082C)
( sizeof(cfg_hcf_opt) - sizeof(HCF_VERSION) - 4 )/sizeof(hcf_16),
#if defined MSF_COMPONENT_ID
MSF_COMPONENT_ID,
@@ -455,7 +448,7 @@ static struct /*CFG_HCF_OPT_STRCT*/ {
HCF_ALIGN,
HCF_ASSERT,
HCF_BIG_ENDIAN,
- 0, // /* HCF_DLV | HCF_DLNV*/,
+ 0, // /* HCF_DLV | HCF_DLNV*/,
HCF_DMA,
HCF_ENCAP,
HCF_EXT,
@@ -478,218 +471,199 @@ static struct /*CFG_HCF_OPT_STRCT*/ {
}; // cfg_hcf_opt
#endif // MSF_COMPONENT_ID
-#if defined HCF_TALLIES_EXTRA
- replaced by HCF_EXT_TALLIES_FW ;
-#endif // HCF_TALLIES_EXTRA
-
-#if defined MSF_COMPONENT_ID || (HCF_EXT) & HCF_EXT_MB
-#if (HCF_EXT) & HCF_EXT_MB
HCF_STATIC LTV_STRCT BASED cfg_null = { 1, CFG_NULL, {0} };
-#endif // HCF_EXT_MB
+
HCF_STATIC hcf_16* BASED xxxx[ ] = {
-#if (HCF_EXT) & HCF_EXT_MB
- &cfg_null.len, //CFG_NULL 0x0820
-#endif // HCF_EXT_MB
+ &cfg_null.len, //CFG_NULL 0x0820
#if defined MSF_COMPONENT_ID
- &cfg_drv_identity.len, //CFG_DRV_IDENTITY 0x0826
- &cfg_drv_sup_range.len, //CFG_DRV_SUP_RANGE 0x0827
- &cfg_drv_act_ranges_pri.len, //CFG_DRV_ACT_RANGES_PRI 0x0828
- &cfg_drv_act_ranges_sta.len, //CFG_DRV_ACT_RANGES_STA 0x0829
- &cfg_drv_act_ranges_hsi.len, //CFG_DRV_ACT_RANGES_HSI 0x082A
- &cfg_drv_act_ranges_apf.len, //CFG_DRV_ACT_RANGES_APF 0x082B
- &cfg_hcf_opt.len, //CFG_HCF_OPT 0x082C
- NULL, //IFB_PRIIdentity placeholder 0xFD02
- NULL, //IFB_PRISup placeholder 0xFD03
+ &cfg_drv_identity.len, //CFG_DRV_IDENTITY 0x0826
+ &cfg_drv_sup_range.len, //CFG_DRV_SUP_RANGE 0x0827
+ &cfg_drv_act_ranges_pri.len, //CFG_DRV_ACT_RANGES_PRI 0x0828
+ &cfg_drv_act_ranges_sta.len, //CFG_DRV_ACT_RANGES_STA 0x0829
+ &cfg_drv_act_ranges_hsi.len, //CFG_DRV_ACT_RANGES_HSI 0x082A
+ &cfg_drv_act_ranges_apf.len, //CFG_DRV_ACT_RANGES_APF 0x082B
+ &cfg_hcf_opt.len, //CFG_HCF_OPT 0x082C
+ NULL, //IFB_PRIIdentity placeholder 0xFD02
+ NULL, //IFB_PRISup placeholder 0xFD03
#endif // MSF_COMPONENT_ID
- NULL //endsentinel
- };
-#define xxxx_PRI_IDENTITY_OFFSET (ARRAY_SIZE(xxxx) - 3)
-
-#endif // MSF_COMPONENT_ID / HCF_EXT_MB
+ NULL //endsentinel
+};
+#define xxxx_PRI_IDENTITY_OFFSET (ARRAY_SIZE(xxxx) - 3)
/************************************************************************************************************
-************************** T O P L E V E L H C F R O U T I N E S **************************************
-************************************************************************************************************/
+ ************************** T O P L E V E L H C F R O U T I N E S **************************************
+ ************************************************************************************************************/
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.MODULE int hcf_action( IFBP ifbp, hcf_16 action )
-*.PURPOSE Changes the run-time Card behavior.
-* Performs Miscellanuous actions.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* action number identifying the type of change
-* - HCF_ACT_CCX_OFF disable CKIP
-* - HCF_ACT_CCX_ON enable CKIP
-* - HCF_ACT_INT_FORCE_ON enable interrupt generation by WaveLAN NIC
-* - HCF_ACT_INT_OFF disable interrupt generation by WaveLAN NIC
-* - HCF_ACT_INT_ON compensate 1 HCF_ACT_INT_OFF, enable interrupt generation if balance reached
-* - HCF_ACT_PRS_SCAN Hermes Probe Respons Scan (F102) command
-* - HCF_ACT_RX_ACK acknowledge non-DMA receiver to Hermes
-* - HCF_ACT_SCAN Hermes Inquire Scan (F101) command (non-WARP only)
-* - HCF_ACT_SLEEP DDS Sleep request
-* - HCF_ACT_TALLIES Hermes Inquire Tallies (F100) command
-*
-*.RETURNS
-* HCF_SUCCESS all (including invalid)
-* HCF_INT_PENDING HCF_ACT_INT_OFF, interrupt pending
-* HCF_ERR_NO_NIC HCF_ACT_INT_OFF, NIC presence check fails
-*
-*.CONDITIONS
-* Except for hcf_action with HCF_ACT_INT_FORCE_ON or HCF_ACT_INT_OFF as parameter or hcf_connect with an I/O
-* address (i.e. not HCF_DISCONNECT), all hcf-function calls MUST be preceded by a call of hcf_action with
-* HCF_ACT_INT_OFF as parameter.
-* Note that hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF )
-* was called.
-*
-*.DESCRIPTION
-* hcf_action supports the following mode changing action-code pairs that are antonyms
-* - HCF_ACT_CCX_OFF / HCF_ACT_CCX_ON
-* - HCF_ACT_INT_[FORCE_]ON / HCF_ACT_INT_OFF
-*
-* Additionally hcf_action can start the following actions in the NIC:
-* - HCF_ACT_PRS_SCAN
-* - HCF_ACT_RX_ACK
-* - HCF_ACT_SCAN
-* - HCF_ACT_SLEEP
-* - HCF_ACT_TALLIES
-*
-* o HCF_ACT_INT_OFF: Sets NIC Interrupts mode Disabled.
-* This command, and the associated [Force] Enable NIC interrupts command, are only available if the HCF_INT_ON
-* compile time option is not set at 0x0000.
-*
-* o HCF_ACT_INT_ON: Sets NIC Interrupts mode Enabled.
-* Enable NIC Interrupts, depending on the number of preceding Disable NIC Interrupt calls.
-*
-* o HCF_ACT_INT_FORCE_ON: Force NIC Interrupts mode Enabled.
-* Sets NIC Interrupts mode Enabled, regardless off the number of preceding Disable NIC Interrupt calls.
-*
-* The disabling and enabling of interrupts are antonyms.
-* These actions must be balanced.
-* For each "disable interrupts" there must be a matching "enable interrupts".
-* The disable interrupts may be executed multiple times in a row without intervening enable interrupts, in
-* other words, the disable interrupts may be nested.
-* The interrupt generation mechanism is disabled at the first call with HCF_ACT_INT_OFF.
-* The interrupt generation mechanism is re-enabled when the number of calls with HCF_ACT_INT_ON matches the
-* number of calls with INT_OFF.
-*
-* It is not allowed to have more Enable NIC Interrupts calls than Disable NIC Interrupts calls.
-* The interrupt generation mechanism is initially (i.e. after hcf_connect) disabled.
-* An MSF based on a interrupt strategy must call hcf_action with INT_ON in its initialization logic.
-*
-*! The INT_OFF/INT_ON housekeeping is initialized at 0x0000 by hcf_connect, causing the interrupt generation
-* mechanism to be disabled at first. This suits MSF implementation based on a polling strategy.
-*
-* o HCF_ACT_CCX_OFF / HCF_ACT_CCX_ON
-*!! This can use some more explanation;?
-* Disables and Enables support in the HCF runtime code for the CCX feature. Each time one of these action
-* codes is used, the effects of the preceding use cease.
-*
-* o HCF_ACT_SLEEP: Initiates the Disconnected DeepSleep process
-* This command is only available if the HCF_DDS compile time option is set. It triggers the F/W to start the
-* sleep handshaking. Regardless whether the Host initiates a Disconnected DeepSleep (DDS) or the F/W initiates
-* a Connected DeepSleep (CDS), the Host-F/W sleep handshaking is completed when the NIC Interrupts mode is
-* enabled (by means of the balancing HCF_ACT_INT_ON), i.e. at that moment the F/W really goes into sleep mode.
-* The F/W is wokenup by the HCF when the NIC Interrupts mode are disabled, i.e. at the first HCF_ACT_INT_OFF
-* after going into sleep.
-*
-* The following Miscellanuous actions are defined:
-*
-* o HCF_ACT_RX_ACK: Receiver Acknowledgement (non-DMA, non-USB mode only)
-* Acking the receiver, frees the NIC memory used to hold the Rx frame and allows the F/W to
-* report the existence of the next Rx frame.
-* If the MSF does not need access (any longer) to the current frame, e.g. because it is rejected based on the
-* look ahead or copied to another buffer, the receiver may be acked. Acking earlier is assumed to have the
-* potential of improving the performance.
-* If the MSF does not explitly ack te receiver, the acking is done implicitly if:
-* - the received frame fits in the look ahead buffer, by the hcf_service_nic call that reported the Rx frame
-* - if not in the above step, by hcf_rcv_msg (assuming hcf_rcv_msg is called)
-* - if neither of the above implicit acks nor an explicit ack by the MSF, by the first hcf_service_nic after
-* the hcf_service_nic that reported the Rx frame.
-* Note: If an Rx frame is already acked, an explicit ACK by the MSF acts as a NoOperation.
-*
-* o HCF_ACT_TALLIES: Inquire Tallies command
-* This command is only operational if the F/W is enabled.
-* The Inquire Tallies command requests the F/W to provide its current set of tallies.
-* See also hcf_get_info with CFG_TALLIES as parameter.
-*
-* o HCF_ACT_PRS_SCAN: Inquire Probe Respons Scan command
-* This command is only operational if the F/W is enabled.
-* The Probe Respons Scan command starts a scan sequence.
-* The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT).
-*
-* o HCF_ACT_SCAN: Inquire Scan command
-* This command is only supported for HII F/W (i.e. pre-WARP) and it is operational if the F/W is enabled.
-* The Inquire Scan command starts a scan sequence.
-* The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT).
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value.
-* - NIC interrupts are not disabled while required by parameter action.
-* - an invalid code is specified in parameter action.
-* - HCF_ACT_INT_ON commands outnumber the HCF_ACT_INT_OFF commands.
-* - reentrancy, may be caused by calling hcf_functions without adequate protection against NIC interrupts or
-* multi-threading
-*
-* - Since the HCF does not maintain status information relative to the F/W enabled state, it is not asserted
-* whether HCF_ACT_SCAN, HCF_ACT_PRS_SCAN or HCF_ACT_TALLIES are only used while F/W is enabled.
-*
-*.DIAGRAM
-* 0: The assert embedded in HCFLOGENTRY checks against re-entrancy. Re-entrancy could be caused by a MSF logic
-* at task-level calling hcf_functions without shielding with HCF_ACT_ON/_OFF. However the HCF_ACT_INT_OFF
-* action itself can per definition not be protected this way. Based on code inspection, it can be concluded,
-* that there is no re-entrancy PROBLEM in this particular flow. It does not seem worth the trouble to
-* explicitly check for this condition (although there was a report of an MSF which ran into this assert.
-* 2:IFB_IntOffCnt is used to balance the INT_OFF and INT_ON calls. Disabling of the interrupts is achieved by
-* writing a zero to the Hermes IntEn register. In a shared interrupt environment (e.g. the mini-PCI NDIS
-* driver) it is considered more correct to return the status HCF_INT_PENDING if and only if, the current
-* invocation of hcf_service_nic is (apparently) called in the ISR when the ISR was activated as result of a
-* change in HREG_EV_STAT matching a bit in HREG_INT_EN, i.e. not if invoked as result of another device
-* generating an interrupt on the shared interrupt line.
-* Note 1: it has been observed that under certain adverse conditions on certain platforms the writing of
-* HREG_INT_EN can apparently fail, therefor it is paramount that HREG_INT_EN is written again with 0 for
-* each and every call to HCF_ACT_INT_OFF.
-* Note 2: it has been observed that under certain H/W & S/W architectures this logic is called when there is
-* no NIC at all. To cater for this, the value of HREG_INT_EN is validated. If the unused bit 0x0100 is set,
-* it is assumed there is no NIC.
-* Note 3: During the download process, some versions of the F/W reset HREG_SW_0, hence checking this
-* register for HCF_MAGIC (the classical NIC presence test) when HCF_ACT_INT_OFF is called due to another
-* card interrupting via a shared IRQ during a download, fails.
-*4: The construction "if ( ifbp->IFB_IntOffCnt-- == 0 )" is optimal (in the sense of shortest/quickest
-* path in error free flows) but NOT fail safe in case of too many INT_ON invocations compared to INT_OFF).
-* Enabling of the interrupts is achieved by writing the Hermes IntEn register.
-* - If the HCF is in Defunct mode, the interrupts stay disabled.
-* - Under "normal" conditions, the HCF is only interested in Info Events, Rx Events and Notify Events.
-* - When the HCF is out of Tx/Notify resources, the HCF is also interested in Alloc Events.
-* - via HCF_EXT, the MSF programmer can also request HREG_EV_TICK and/or HREG_EV_TX_EXC interrupts.
-* For DMA operation, the DMA hardware handles the alloc events. The DMA engine will generate a 'TxDmaDone'
-* event as soon as it has pumped a frame from host ram into NIC-RAM (note that the frame does not have to be
-* transmitted then), and a 'RxDmaDone' event as soon as a received frame has been pumped from NIC-RAM into
-* host ram. Note that the 'alloc' event has been removed from the event-mask, because the DMA engine will
-* react to and acknowledge this event.
-*6: ack the "old" Rx-event. See "Rx Buffer free strategy" in hcf_service_nic above for more explanation.
-* IFB_RxFID and IFB_RxLen must be cleared to bring both the internal HCF house keeping and the information
-* supplied to the MSF in the state "no frame received".
-*8: The HCF_ACT_SCAN, HCF_ACT_PRS_SCAN and HCF_ACT_TALLIES activity are merged by "clever" algebraic
-* manipulations of the RID-values and action codes, so foregoing robustness against migration problems for
-* ease of implementation. The assumptions about numerical relationships between CFG_TALLIES etc and
-* HCF_ACT_TALLIES etc are checked by the "#if" statements just prior to the body of this routine, resulting
-* in: err "maintenance" during compilation if the assumptions are no longer met. The writing of HREG_PARAM_1
-* with 0x3FFF in case of an PRS scan, is a kludge to get around lack of specification, hence different
-* implementation in F/W and Host.
-* When there is no NIC RAM available, some versions of the Hermes F/W do report 0x7F00 as error in the
-* Result field of the Status register and some F/W versions don't. To mask this difference to the MSF all
-* return codes of the Hermes are ignored ("best" and "most simple" solution to these types of analomies with
-* an acceptable loss due to ignoring all error situations as well).
-* The "No inquire space" is reported via the Hermes tallies.
-*30: do not HCFASSERT( rc, rc ) since rc == HCF_INT_PENDING is no error
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE int hcf_action( IFBP ifbp, hcf_16 action )
+ *.PURPOSE Changes the run-time Card behavior.
+ * Performs Miscellanuous actions.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * action number identifying the type of change
+ * - HCF_ACT_INT_FORCE_ON enable interrupt generation by WaveLAN NIC
+ * - HCF_ACT_INT_OFF disable interrupt generation by WaveLAN NIC
+ * - HCF_ACT_INT_ON compensate 1 HCF_ACT_INT_OFF, enable interrupt generation if balance reached
+ * - HCF_ACT_PRS_SCAN Hermes Probe Respons Scan (F102) command
+ * - HCF_ACT_RX_ACK acknowledge non-DMA receiver to Hermes
+ * - HCF_ACT_SCAN Hermes Inquire Scan (F101) command (non-WARP only)
+ * - HCF_ACT_SLEEP DDS Sleep request
+ * - HCF_ACT_TALLIES Hermes Inquire Tallies (F100) command
+ *
+ *.RETURNS
+ * HCF_SUCCESS all (including invalid)
+ * HCF_INT_PENDING HCF_ACT_INT_OFF, interrupt pending
+ * HCF_ERR_NO_NIC HCF_ACT_INT_OFF, NIC presence check fails
+ *
+ *.CONDITIONS
+ * Except for hcf_action with HCF_ACT_INT_FORCE_ON or HCF_ACT_INT_OFF as parameter or hcf_connect with an I/O
+ * address (i.e. not HCF_DISCONNECT), all hcf-function calls MUST be preceded by a call of hcf_action with
+ * HCF_ACT_INT_OFF as parameter.
+ * Note that hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF )
+ * was called.
+ *
+ *.DESCRIPTION
+ * hcf_action supports the following mode changing action-code pairs that are antonyms
+ * - HCF_ACT_INT_[FORCE_]ON / HCF_ACT_INT_OFF
+ *
+ * Additionally hcf_action can start the following actions in the NIC:
+ * - HCF_ACT_PRS_SCAN
+ * - HCF_ACT_RX_ACK
+ * - HCF_ACT_SCAN
+ * - HCF_ACT_SLEEP
+ * - HCF_ACT_TALLIES
+ *
+ * o HCF_ACT_INT_OFF: Sets NIC Interrupts mode Disabled.
+ * This command, and the associated [Force] Enable NIC interrupts command, are only available if the HCF_INT_ON
+ * compile time option is not set at 0x0000.
+ *
+ * o HCF_ACT_INT_ON: Sets NIC Interrupts mode Enabled.
+ * Enable NIC Interrupts, depending on the number of preceding Disable NIC Interrupt calls.
+ *
+ * o HCF_ACT_INT_FORCE_ON: Force NIC Interrupts mode Enabled.
+ * Sets NIC Interrupts mode Enabled, regardless off the number of preceding Disable NIC Interrupt calls.
+ *
+ * The disabling and enabling of interrupts are antonyms.
+ * These actions must be balanced.
+ * For each "disable interrupts" there must be a matching "enable interrupts".
+ * The disable interrupts may be executed multiple times in a row without intervening enable interrupts, in
+ * other words, the disable interrupts may be nested.
+ * The interrupt generation mechanism is disabled at the first call with HCF_ACT_INT_OFF.
+ * The interrupt generation mechanism is re-enabled when the number of calls with HCF_ACT_INT_ON matches the
+ * number of calls with INT_OFF.
+ *
+ * It is not allowed to have more Enable NIC Interrupts calls than Disable NIC Interrupts calls.
+ * The interrupt generation mechanism is initially (i.e. after hcf_connect) disabled.
+ * An MSF based on a interrupt strategy must call hcf_action with INT_ON in its initialization logic.
+ *
+ *! The INT_OFF/INT_ON housekeeping is initialized at 0x0000 by hcf_connect, causing the interrupt generation
+ * mechanism to be disabled at first. This suits MSF implementation based on a polling strategy.
+ *
+ * o HCF_ACT_SLEEP: Initiates the Disconnected DeepSleep process
+ * This command is only available if the HCF_DDS compile time option is set. It triggers the F/W to start the
+ * sleep handshaking. Regardless whether the Host initiates a Disconnected DeepSleep (DDS) or the F/W initiates
+ * a Connected DeepSleep (CDS), the Host-F/W sleep handshaking is completed when the NIC Interrupts mode is
+ * enabled (by means of the balancing HCF_ACT_INT_ON), i.e. at that moment the F/W really goes into sleep mode.
+ * The F/W is wokenup by the HCF when the NIC Interrupts mode are disabled, i.e. at the first HCF_ACT_INT_OFF
+ * after going into sleep.
+ *
+ * The following Miscellanuous actions are defined:
+ *
+ * o HCF_ACT_RX_ACK: Receiver Acknowledgement (non-DMA, non-USB mode only)
+ * Acking the receiver, frees the NIC memory used to hold the Rx frame and allows the F/W to
+ * report the existence of the next Rx frame.
+ * If the MSF does not need access (any longer) to the current frame, e.g. because it is rejected based on the
+ * look ahead or copied to another buffer, the receiver may be acked. Acking earlier is assumed to have the
+ * potential of improving the performance.
+ * If the MSF does not explitly ack te receiver, the acking is done implicitly if:
+ * - the received frame fits in the look ahead buffer, by the hcf_service_nic call that reported the Rx frame
+ * - if not in the above step, by hcf_rcv_msg (assuming hcf_rcv_msg is called)
+ * - if neither of the above implicit acks nor an explicit ack by the MSF, by the first hcf_service_nic after
+ * the hcf_service_nic that reported the Rx frame.
+ * Note: If an Rx frame is already acked, an explicit ACK by the MSF acts as a NoOperation.
+ *
+ * o HCF_ACT_TALLIES: Inquire Tallies command
+ * This command is only operational if the F/W is enabled.
+ * The Inquire Tallies command requests the F/W to provide its current set of tallies.
+ * See also hcf_get_info with CFG_TALLIES as parameter.
+ *
+ * o HCF_ACT_PRS_SCAN: Inquire Probe Respons Scan command
+ * This command is only operational if the F/W is enabled.
+ * The Probe Respons Scan command starts a scan sequence.
+ * The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT).
+ *
+ * o HCF_ACT_SCAN: Inquire Scan command
+ * This command is only supported for HII F/W (i.e. pre-WARP) and it is operational if the F/W is enabled.
+ * The Inquire Scan command starts a scan sequence.
+ * The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT).
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value.
+ * - NIC interrupts are not disabled while required by parameter action.
+ * - an invalid code is specified in parameter action.
+ * - HCF_ACT_INT_ON commands outnumber the HCF_ACT_INT_OFF commands.
+ * - reentrancy, may be caused by calling hcf_functions without adequate protection against NIC interrupts or
+ * multi-threading
+ *
+ * - Since the HCF does not maintain status information relative to the F/W enabled state, it is not asserted
+ * whether HCF_ACT_SCAN, HCF_ACT_PRS_SCAN or HCF_ACT_TALLIES are only used while F/W is enabled.
+ *
+ *.DIAGRAM
+ * 0: The assert embedded in HCFLOGENTRY checks against re-entrancy. Re-entrancy could be caused by a MSF logic
+ * at task-level calling hcf_functions without shielding with HCF_ACT_ON/_OFF. However the HCF_ACT_INT_OFF
+ * action itself can per definition not be protected this way. Based on code inspection, it can be concluded,
+ * that there is no re-entrancy PROBLEM in this particular flow. It does not seem worth the trouble to
+ * explicitly check for this condition (although there was a report of an MSF which ran into this assert.
+ * 2:IFB_IntOffCnt is used to balance the INT_OFF and INT_ON calls. Disabling of the interrupts is achieved by
+ * writing a zero to the Hermes IntEn register. In a shared interrupt environment (e.g. the mini-PCI NDIS
+ * driver) it is considered more correct to return the status HCF_INT_PENDING if and only if, the current
+ * invocation of hcf_service_nic is (apparently) called in the ISR when the ISR was activated as result of a
+ * change in HREG_EV_STAT matching a bit in HREG_INT_EN, i.e. not if invoked as result of another device
+ * generating an interrupt on the shared interrupt line.
+ * Note 1: it has been observed that under certain adverse conditions on certain platforms the writing of
+ * HREG_INT_EN can apparently fail, therefor it is paramount that HREG_INT_EN is written again with 0 for
+ * each and every call to HCF_ACT_INT_OFF.
+ * Note 2: it has been observed that under certain H/W & S/W architectures this logic is called when there is
+ * no NIC at all. To cater for this, the value of HREG_INT_EN is validated. If the unused bit 0x0100 is set,
+ * it is assumed there is no NIC.
+ * Note 3: During the download process, some versions of the F/W reset HREG_SW_0, hence checking this
+ * register for HCF_MAGIC (the classical NIC presence test) when HCF_ACT_INT_OFF is called due to another
+ * card interrupting via a shared IRQ during a download, fails.
+ *4: The construction "if ( ifbp->IFB_IntOffCnt-- == 0 )" is optimal (in the sense of shortest/quickest
+ * path in error free flows) but NOT fail safe in case of too many INT_ON invocations compared to INT_OFF).
+ * Enabling of the interrupts is achieved by writing the Hermes IntEn register.
+ * - If the HCF is in Defunct mode, the interrupts stay disabled.
+ * - Under "normal" conditions, the HCF is only interested in Info Events, Rx Events and Notify Events.
+ * - When the HCF is out of Tx/Notify resources, the HCF is also interested in Alloc Events.
+ * - via HCF_EXT, the MSF programmer can also request HREG_EV_TICK and/or HREG_EV_TX_EXC interrupts.
+ * For DMA operation, the DMA hardware handles the alloc events. The DMA engine will generate a 'TxDmaDone'
+ * event as soon as it has pumped a frame from host ram into NIC-RAM (note that the frame does not have to be
+ * transmitted then), and a 'RxDmaDone' event as soon as a received frame has been pumped from NIC-RAM into
+ * host ram. Note that the 'alloc' event has been removed from the event-mask, because the DMA engine will
+ * react to and acknowledge this event.
+ *6: ack the "old" Rx-event. See "Rx Buffer free strategy" in hcf_service_nic above for more explanation.
+ * IFB_RxFID and IFB_RxLen must be cleared to bring both the internal HCF house keeping and the information
+ * supplied to the MSF in the state "no frame received".
+ *8: The HCF_ACT_SCAN, HCF_ACT_PRS_SCAN and HCF_ACT_TALLIES activity are merged by "clever" algebraic
+ * manipulations of the RID-values and action codes, so foregoing robustness against migration problems for
+ * ease of implementation. The assumptions about numerical relationships between CFG_TALLIES etc and
+ * HCF_ACT_TALLIES etc are checked by the "#if" statements just prior to the body of this routine, resulting
+ * in: err "maintenance" during compilation if the assumptions are no longer met. The writing of HREG_PARAM_1
+ * with 0x3FFF in case of an PRS scan, is a kludge to get around lack of specification, hence different
+ * implementation in F/W and Host.
+ * When there is no NIC RAM available, some versions of the Hermes F/W do report 0x7F00 as error in the
+ * Result field of the Status register and some F/W versions don't. To mask this difference to the MSF all
+ * return codes of the Hermes are ignored ("best" and "most simple" solution to these types of analomies with
+ * an acceptable loss due to ignoring all error situations as well).
+ * The "No inquire space" is reported via the Hermes tallies.
+ *30: do not HCFASSERT( rc, rc ) since rc == HCF_INT_PENDING is no error
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0
#if CFG_SCAN != CFG_TALLIES - HCF_ACT_TALLIES + HCF_ACT_SCAN
err: "maintenance" apparently inviolated the underlying assumption about the numerical values of these macros
@@ -701,43 +675,43 @@ err: "maintenance" apparently inviolated the underlying assumption about the num
int
hcf_action( IFBP ifbp, hcf_16 action )
{
-int rc = HCF_SUCCESS;
+ int rc = HCF_SUCCESS;
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
#if HCF_INT_ON
- HCFLOGENTRY( action == HCF_ACT_INT_FORCE_ON ? HCF_TRACE_ACTION_KLUDGE : HCF_TRACE_ACTION, action ) /* 0 */
+ HCFLOGENTRY( action == HCF_ACT_INT_FORCE_ON ? HCF_TRACE_ACTION_KLUDGE : HCF_TRACE_ACTION, action ); /* 0 */
#if (HCF_SLEEP)
HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE || action == HCF_ACT_INT_OFF,
- MERGE_2( action, ifbp->IFB_IntOffCnt ) )
+ MERGE_2( action, ifbp->IFB_IntOffCnt ) );
#else
- HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE, action )
+ HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE, action );
#endif // HCF_SLEEP
HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFF ||
- action == HCF_ACT_INT_OFF || action == HCF_ACT_INT_FORCE_ON, action )
+ action == HCF_ACT_INT_OFF || action == HCF_ACT_INT_FORCE_ON, action );
HCFASSERT( ifbp->IFB_IntOffCnt <= 16 || ifbp->IFB_IntOffCnt >= 0xFFFE,
- MERGE_2( action, ifbp->IFB_IntOffCnt ) ) //nesting more than 16 deep seems unreasonable
+ MERGE_2( action, ifbp->IFB_IntOffCnt ) ); //nesting more than 16 deep seems unreasonable
#endif // HCF_INT_ON
switch (action) {
#if HCF_INT_ON
-hcf_16 i;
- case HCF_ACT_INT_OFF: // Disable Interrupt generation
+ hcf_16 i;
+ case HCF_ACT_INT_OFF: // Disable Interrupt generation
#if HCF_SLEEP
- if ( ifbp->IFB_IntOffCnt == 0xFFFE ) { // WakeUp test ;?tie this to the "new" super-LinkStat
- ifbp->IFB_IntOffCnt++; // restore conventional I/F
- OPW(HREG_IO, HREG_IO_WAKEUP_ASYNC ); // set wakeup bit
- OPW(HREG_IO, HREG_IO_WAKEUP_ASYNC ); // set wakeup bit to counteract the clearing by F/W
+ if ( ifbp->IFB_IntOffCnt == 0xFFFE ) { // WakeUp test ;?tie this to the "new" super-LinkStat
+ ifbp->IFB_IntOffCnt++; // restore conventional I/F
+ OPW(HREG_IO, HREG_IO_WAKEUP_ASYNC ); // set wakeup bit
+ OPW(HREG_IO, HREG_IO_WAKEUP_ASYNC ); // set wakeup bit to counteract the clearing by F/W
// 800 us latency before FW switches to high power
- MSF_WAIT(800); // MSF-defined function to wait n microseconds.
-//OOR if ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_DS_OOR ) { // OutOfRange
-// printk( "<5>ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day
+ MSF_WAIT(800); // MSF-defined function to wait n microseconds.
+//OOR if ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_DS_OOR ) { // OutOfRange
+// printk( "<5>ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day
// hcf_cntl( ifbp, HCF_CNTL_ENABLE );
// }
-// ifbp->IFB_DSLinkStat &= ~( CFG_LINK_STAT_DS_IR | CFG_LINK_STAT_DS_OOR); //clear IR/OOR state
+// ifbp->IFB_DSLinkStat &= ~( CFG_LINK_STAT_DS_IR | CFG_LINK_STAT_DS_OOR); //clear IR/OOR state
}
#endif // HCF_SLEEP
-/*2*/ ifbp->IFB_IntOffCnt++;
-//! rc = 0;
+ /*2*/ ifbp->IFB_IntOffCnt++;
+//! rc = 0;
i = IPW( HREG_INT_EN );
OPW( HREG_INT_EN, 0 );
if ( i & 0x1000 ) {
@@ -749,227 +723,219 @@ hcf_16 i;
}
break;
- case HCF_ACT_INT_FORCE_ON: // Enforce Enable Interrupt generation
+ case HCF_ACT_INT_FORCE_ON: // Enforce Enable Interrupt generation
ifbp->IFB_IntOffCnt = 0;
//Fall through in HCF_ACT_INT_ON
- case HCF_ACT_INT_ON: // Enable Interrupt generation
-/*4*/ if ( ifbp->IFB_IntOffCnt-- == 0 && ifbp->IFB_CardStat == 0 ) {
- //determine Interrupt Event mask
+ case HCF_ACT_INT_ON: // Enable Interrupt generation
+ /*4*/ if ( ifbp->IFB_IntOffCnt-- == 0 && ifbp->IFB_CardStat == 0 ) {
+ //determine Interrupt Event mask
#if HCF_DMA
if ( ifbp->IFB_CntlOpt & USE_DMA ) {
- i = HREG_EV_INFO | HREG_EV_RDMAD | HREG_EV_TDMAD | HREG_EV_TX_EXT; //mask when DMA active
+ i = HREG_EV_INFO | HREG_EV_RDMAD | HREG_EV_TDMAD | HREG_EV_TX_EXT; //mask when DMA active
} else
#endif // HCF_DMA
{
- i = HREG_EV_INFO | HREG_EV_RX | HREG_EV_TX_EXT; //mask when DMA not active
+ i = HREG_EV_INFO | HREG_EV_RX | HREG_EV_TX_EXT; //mask when DMA not active
if ( ifbp->IFB_RscInd == 0 ) {
- i |= HREG_EV_ALLOC; //mask when no TxFID available
+ i |= HREG_EV_ALLOC; //mask when no TxFID available
}
}
#if HCF_SLEEP
if ( ( IPW(HREG_EV_STAT) & ( i | HREG_EV_SLEEP_REQ ) ) == HREG_EV_SLEEP_REQ ) {
// firmware indicates it would like to go into sleep modus
// only acknowledge this request if no other events that can cause an interrupt are pending
- ifbp->IFB_IntOffCnt--; //becomes 0xFFFE
- OPW( HREG_INT_EN, i | HREG_EV_TICK );
+ ifbp->IFB_IntOffCnt--; //becomes 0xFFFE
+ OPW( HREG_INT_EN, i | HREG_EV_TICK );
OPW( HREG_EV_ACK, HREG_EV_SLEEP_REQ | HREG_EV_TICK | HREG_EV_ACK_REG_READY );
} else
#endif // HCF_SLEEP
{
- OPW( HREG_INT_EN, i | HREG_EV_SLEEP_REQ );
+ OPW( HREG_INT_EN, i | HREG_EV_SLEEP_REQ );
}
}
break;
#endif // HCF_INT_ON
#if (HCF_SLEEP) & HCF_DDS
- case HCF_ACT_SLEEP: // DDS Sleep request
+ case HCF_ACT_SLEEP: // DDS Sleep request
hcf_cntl( ifbp, HCF_CNTL_DISABLE );
cmd_exe( ifbp, HCMD_SLEEP, 0 );
break;
-// case HCF_ACT_WAKEUP: // DDS Wakeup request
-// HCFASSERT( ifbp->IFB_IntOffCnt == 0xFFFE, ifbp->IFB_IntOffCnt )
-// ifbp->IFB_IntOffCnt++; // restore conventional I/F
-// OPW( HREG_IO, HREG_IO_WAKEUP_ASYNC );
-// MSF_WAIT(800); // MSF-defined function to wait n microseconds.
-// rc = hcf_action( ifbp, HCF_ACT_INT_OFF ); /*bogus, IFB_IntOffCnt == 0xFFFF, so if you carefully look
-// *at the #if HCF_DDS statements, HCF_ACT_INT_OFF is empty
-// *for DDS. "Much" better would be to merge the flows for
-// *DDS and DEEP_SLEEP
-// */
-// break;
+// case HCF_ACT_WAKEUP: // DDS Wakeup request
+// HCFASSERT( ifbp->IFB_IntOffCnt == 0xFFFE, ifbp->IFB_IntOffCnt );
+// ifbp->IFB_IntOffCnt++; // restore conventional I/F
+// OPW( HREG_IO, HREG_IO_WAKEUP_ASYNC );
+// MSF_WAIT(800); // MSF-defined function to wait n microseconds.
+// rc = hcf_action( ifbp, HCF_ACT_INT_OFF ); /*bogus, IFB_IntOffCnt == 0xFFFF, so if you carefully look
+// *at the #if HCF_DDS statements, HCF_ACT_INT_OFF is empty
+// *for DDS. "Much" better would be to merge the flows for
+// *DDS and DEEP_SLEEP
+// */
+// break;
#endif // HCF_DDS
-#if (HCF_TYPE) & HCF_TYPE_CCX
- case HCF_ACT_CCX_ON: // enable CKIP
- case HCF_ACT_CCX_OFF: // disable CKIP
- ifbp->IFB_CKIPStat = action;
- break;
-#endif // HCF_TYPE_CCX
-
- case HCF_ACT_RX_ACK: //Receiver ACK
-/*6*/ if ( ifbp->IFB_RxFID ) {
+ case HCF_ACT_RX_ACK: //Receiver ACK
+ /*6*/ if ( ifbp->IFB_RxFID ) {
DAWA_ACK( HREG_EV_RX );
}
ifbp->IFB_RxFID = ifbp->IFB_RxLen = 0;
break;
-/*8*/ case HCF_ACT_PRS_SCAN: // Hermes PRS Scan (F102)
+ /*8*/ case HCF_ACT_PRS_SCAN: // Hermes PRS Scan (F102)
OPW( HREG_PARAM_1, 0x3FFF );
- //Fall through in HCF_ACT_TALLIES
- case HCF_ACT_TALLIES: // Hermes Inquire Tallies (F100)
+ //Fall through in HCF_ACT_TALLIES
+ case HCF_ACT_TALLIES: // Hermes Inquire Tallies (F100)
#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0
- case HCF_ACT_SCAN: // Hermes Inquire Scan (F101)
+ case HCF_ACT_SCAN: // Hermes Inquire Scan (F101)
#endif // HCF_TYPE_HII5
/*!! the assumptions about numerical relationships between CFG_TALLIES etc and HCF_ACT_TALLIES etc
- * are checked by #if statements just prior to this routine resulting in: err "maintenance" */
+ * are checked by #if statements just prior to this routine resulting in: err "maintenance" */
cmd_exe( ifbp, HCMD_INQUIRE, action - HCF_ACT_TALLIES + CFG_TALLIES );
break;
- default:
- HCFASSERT( DO_ASSERT, action )
+ default:
+ HCFASSERT( DO_ASSERT, action );
break;
}
- //! do not HCFASSERT( rc == HCF_SUCCESS, rc ) /* 30*/
- HCFLOGEXIT( HCF_TRACE_ACTION )
+ //! do not HCFASSERT( rc == HCF_SUCCESS, rc ) /* 30*/
+ HCFLOGEXIT( HCF_TRACE_ACTION );
return rc;
} // hcf_action
-#endif // HCF_DL_ONLY
/************************************************************************************************************
-*
-*.MODULE int hcf_cntl( IFBP ifbp, hcf_16 cmd )
-*.PURPOSE Connect or disconnect a specific port to a specific network.
-*!! ;???????????????? continue needs more explanation
-* recovers by means of "continue" when the connect process in CCX mode fails
-* Enables or disables data transmission and reception for the NIC.
-* Activates static NIC configuration for a specific port at connect.
-* Activates static configuration for all ports at enable.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* cmd 0x001F: Hermes command (disable, enable, connect, disconnect, continue)
-* HCF_CNTL_ENABLE Enable
-* HCF_CNTL_DISABLE Disable
-* HCF_CNTL_CONTINUE Continue
-* HCF_CNTL_CONNECT Connect
-* HCF_CNTL_DISCONNECT Disconnect
-* 0x0100: command qualifier (continue)
-* HCMD_RETRY retry flag
-* 0x0700: port number (connect/disconnect)
-* HCF_PORT_0 MAC Port 0
-* HCF_PORT_1 MAC Port 1
-* HCF_PORT_2 MAC Port 2
-* HCF_PORT_3 MAC Port 3
-* HCF_PORT_4 MAC Port 4
-* HCF_PORT_5 MAC Port 5
-* HCF_PORT_6 MAC Port 6
-*
-*.RETURNS
-* HCF_SUCCESS
-*!! via cmd_exe
-* HCF_ERR_NO_NIC
-* HCF_ERR_DEFUNCT_...
-* HCF_ERR_TIME_OUT
-*
-*.DESCRIPTION
-* The parameter cmd contains a number of subfields.
-* The actual value for cmd is created by logical or-ing the appropriate mnemonics for the subfields.
-* The field 0x001F contains the command code
-* - HCF_CNTL_ENABLE
-* - HCF_CNTL_DISABLE
-* - HCF_CNTL_CONNECT
-* - HCF_CNTL_DISCONNECT
-* - HCF_CNTL_CONTINUE
-*
-* For HCF_CNTL_CONTINUE, the field 0x0100 contains the retry flag HCMD_RETRY.
-* For HCF_CNTL_CONNECT and HCF_CNTL_DISCONNECT, the field 0x0700 contains the port number as HCF_PORT_#.
-* For Station as well as AccessPoint F/W, MAC Port 0 is the "normal" communication channel.
-* For AccessPoint F/W, MAC Port 1 through 6 control the WDS links.
-*
-* Note that despite the names HCF_CNTL_DISABLE and HCF_CNTL_ENABLE, hcf_cntl does not influence the NIC
-* Interrupts mode.
-*
-* The Connect is used by the MSF to bring a particular port in an inactive state as far as data transmission
-* and reception are concerned.
-* When a particular port is disconnected:
-* - the F/W disables the receiver for that port.
-* - the F/W ignores send commands for that port.
-* - all frames (Receive as well as pending Transmit) for that port on the NIC are discarded.
-*
-* When the NIC is disabled, above list applies to all ports, i.e. the result is like all ports are
-* disconnected.
-*
-* When a particular port is connected:
-* - the F/W effectuates the static configuration for that port.
-* - enables the receiver for that port.
-* - accepts send commands for that port.
-*
-* Enabling has the following effects:
-* - the F/W effectuates the static configuration for all ports.
-* The F/W only updates its static configuration at a transition from disabled to enabled or from
-* disconnected to connected.
-* In order to enforce the static configuration, the MSF must assure that such a transition takes place.
-* Due to such a disable/enable or disconnect/connect sequence, Rx/Tx frames may be lost, in other words,
-* configuration may impact communication.
-* - The DMA Engine (if applicable) is enabled.
-* Note that the Enable Function by itself only enables data transmission and reception, it
-* does not enable the Interrupt Generation mechanism. This is done by hcf_action.
-*
-* Disabling has the following effects:
-*!! ;?????is the following statement really true
-* - it acts as a disconnect on all ports.
-* - The DMA Engine (if applicable) is disabled.
-*
-* For impact of the disable command on the behavior of hcf_dma_tx/rx_get see the appropriate sections.
-*
-* Although the Enable/Disable and Connect/Disconnect are antonyms, there is no restriction on their sequencing,
-* in other words, they may be called multiple times in arbitrary sequence without being paired or balanced.
-* Each time one of these functions is called, the effects of the preceding calls cease.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value.
-* - NIC interrupts are not disabled.
-* - A command other than Continue, Enable, Disable, Connect or Disconnect is given.
-* - An invalid combination of the subfields is given or a bit outside the subfields is given.
-* - any return code besides HCF_SUCCESS.
-* - reentrancy, may be caused by calling a hcf_function without adequate protection against NIC interrupts or
-* multi-threading
-*
-*.DIAGRAM
-* hcf_cntl takes successively the following actions:
-*2: If the HCF is in Defunct mode or incompatible with the Primary or Station Supplier in the Hermes,
-* hcf_cntl() returns immediately with HCF_ERR_NO_NIC;? as status.
-*8: when the port is disabled, the DMA engine needs to be de-activated, so the host can safely reclaim tx
-* packets from the tx descriptor chain.
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE int hcf_cntl( IFBP ifbp, hcf_16 cmd )
+ *.PURPOSE Connect or disconnect a specific port to a specific network.
+ *!! ;???????????????? continue needs more explanation
+ * recovers by means of "continue" when the connect process in CCX mode fails
+ * Enables or disables data transmission and reception for the NIC.
+ * Activates static NIC configuration for a specific port at connect.
+ * Activates static configuration for all ports at enable.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * cmd 0x001F: Hermes command (disable, enable, connect, disconnect, continue)
+ * HCF_CNTL_ENABLE Enable
+ * HCF_CNTL_DISABLE Disable
+ * HCF_CNTL_CONTINUE Continue
+ * HCF_CNTL_CONNECT Connect
+ * HCF_CNTL_DISCONNECT Disconnect
+ * 0x0100: command qualifier (continue)
+ * HCMD_RETRY retry flag
+ * 0x0700: port number (connect/disconnect)
+ * HCF_PORT_0 MAC Port 0
+ * HCF_PORT_1 MAC Port 1
+ * HCF_PORT_2 MAC Port 2
+ * HCF_PORT_3 MAC Port 3
+ * HCF_PORT_4 MAC Port 4
+ * HCF_PORT_5 MAC Port 5
+ * HCF_PORT_6 MAC Port 6
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ *!! via cmd_exe
+ * HCF_ERR_NO_NIC
+ * HCF_ERR_DEFUNCT_...
+ * HCF_ERR_TIME_OUT
+ *
+ *.DESCRIPTION
+ * The parameter cmd contains a number of subfields.
+ * The actual value for cmd is created by logical or-ing the appropriate mnemonics for the subfields.
+ * The field 0x001F contains the command code
+ * - HCF_CNTL_ENABLE
+ * - HCF_CNTL_DISABLE
+ * - HCF_CNTL_CONNECT
+ * - HCF_CNTL_DISCONNECT
+ * - HCF_CNTL_CONTINUE
+ *
+ * For HCF_CNTL_CONTINUE, the field 0x0100 contains the retry flag HCMD_RETRY.
+ * For HCF_CNTL_CONNECT and HCF_CNTL_DISCONNECT, the field 0x0700 contains the port number as HCF_PORT_#.
+ * For Station as well as AccessPoint F/W, MAC Port 0 is the "normal" communication channel.
+ * For AccessPoint F/W, MAC Port 1 through 6 control the WDS links.
+ *
+ * Note that despite the names HCF_CNTL_DISABLE and HCF_CNTL_ENABLE, hcf_cntl does not influence the NIC
+ * Interrupts mode.
+ *
+ * The Connect is used by the MSF to bring a particular port in an inactive state as far as data transmission
+ * and reception are concerned.
+ * When a particular port is disconnected:
+ * - the F/W disables the receiver for that port.
+ * - the F/W ignores send commands for that port.
+ * - all frames (Receive as well as pending Transmit) for that port on the NIC are discarded.
+ *
+ * When the NIC is disabled, above list applies to all ports, i.e. the result is like all ports are
+ * disconnected.
+ *
+ * When a particular port is connected:
+ * - the F/W effectuates the static configuration for that port.
+ * - enables the receiver for that port.
+ * - accepts send commands for that port.
+ *
+ * Enabling has the following effects:
+ * - the F/W effectuates the static configuration for all ports.
+ * The F/W only updates its static configuration at a transition from disabled to enabled or from
+ * disconnected to connected.
+ * In order to enforce the static configuration, the MSF must assure that such a transition takes place.
+ * Due to such a disable/enable or disconnect/connect sequence, Rx/Tx frames may be lost, in other words,
+ * configuration may impact communication.
+ * - The DMA Engine (if applicable) is enabled.
+ * Note that the Enable Function by itself only enables data transmission and reception, it
+ * does not enable the Interrupt Generation mechanism. This is done by hcf_action.
+ *
+ * Disabling has the following effects:
+ *!! ;?????is the following statement really true
+ * - it acts as a disconnect on all ports.
+ * - The DMA Engine (if applicable) is disabled.
+ *
+ * For impact of the disable command on the behavior of hcf_dma_tx/rx_get see the appropriate sections.
+ *
+ * Although the Enable/Disable and Connect/Disconnect are antonyms, there is no restriction on their sequencing,
+ * in other words, they may be called multiple times in arbitrary sequence without being paired or balanced.
+ * Each time one of these functions is called, the effects of the preceding calls cease.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value.
+ * - NIC interrupts are not disabled.
+ * - A command other than Continue, Enable, Disable, Connect or Disconnect is given.
+ * - An invalid combination of the subfields is given or a bit outside the subfields is given.
+ * - any return code besides HCF_SUCCESS.
+ * - reentrancy, may be caused by calling a hcf_function without adequate protection against NIC interrupts or
+ * multi-threading
+ *
+ *.DIAGRAM
+ * hcf_cntl takes successively the following actions:
+ *2: If the HCF is in Defunct mode or incompatible with the Primary or Station Supplier in the Hermes,
+ * hcf_cntl() returns immediately with HCF_ERR_NO_NIC;? as status.
+ *8: when the port is disabled, the DMA engine needs to be de-activated, so the host can safely reclaim tx
+ * packets from the tx descriptor chain.
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
hcf_cntl( IFBP ifbp, hcf_16 cmd )
{
-int rc = HCF_ERR_INCOMP_FW;
+ int rc = HCF_ERR_INCOMP_FW;
#if HCF_ASSERT
-{ int x = cmd & HCMD_CMD_CODE;
- if ( x == HCF_CNTL_CONTINUE ) x &= ~HCMD_RETRY;
- else if ( (x == HCMD_DISABLE || x == HCMD_ENABLE) && ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ) {
- x &= ~HFS_TX_CNTL_PORT;
+ { int x = cmd & HCMD_CMD_CODE;
+ if ( x == HCF_CNTL_CONTINUE ) x &= ~HCMD_RETRY;
+ else if ( (x == HCMD_DISABLE || x == HCMD_ENABLE) && ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ) {
+ x &= ~HFS_TX_CNTL_PORT;
+ }
+ HCFASSERT( x==HCF_CNTL_ENABLE || x==HCF_CNTL_DISABLE || HCF_CNTL_CONTINUE ||
+ x==HCF_CNTL_CONNECT || x==HCF_CNTL_DISCONNECT, cmd );
}
- HCFASSERT( x==HCF_CNTL_ENABLE || x==HCF_CNTL_DISABLE || HCF_CNTL_CONTINUE ||
- x==HCF_CNTL_CONNECT || x==HCF_CNTL_DISCONNECT, cmd )
-}
#endif // HCF_ASSERT
// #if (HCF_SLEEP) & HCF_DDS
-// HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE, cmd )
+// HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE, cmd );
// #endif // HCF_DDS
- HCFLOGENTRY( HCF_TRACE_CNTL, cmd )
- if ( ifbp->IFB_CardStat == 0 ) { /*2*/
-/*6*/ rc = cmd_exe( ifbp, cmd, 0 );
+ HCFLOGENTRY( HCF_TRACE_CNTL, cmd );
+ if ( ifbp->IFB_CardStat == 0 ) { /*2*/
+ /*6*/ rc = cmd_exe( ifbp, cmd, 0 );
#if (HCF_SLEEP) & HCF_DDS
- ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty)
+ ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty)
#endif // HCF_DDS
}
#if HCF_DMA
@@ -980,7 +946,7 @@ int rc = HCF_ERR_INCOMP_FW;
hcf_io io_port = ifbp->IFB_IOBase;
DESC_STRCT *p;
if ( cmd == HCF_CNTL_DISABLE || cmd == HCF_CNTL_ENABLE ) {
- OUT_PORT_DWORD( (io_port + HREG_DMA_CTRL), DMA_CTRLSTAT_RESET); /*8*/
+ OUT_PORT_DWORD( (io_port + HREG_DMA_CTRL), DMA_CTRLSTAT_RESET); /*8*/
ifbp->IFB_CntlOpt &= ~DMA_ENABLED;
}
if ( cmd == HCF_CNTL_ENABLE ) {
@@ -989,12 +955,12 @@ int rc = HCF_ERR_INCOMP_FW;
* as additional beneficiary side effect, the SOP and EOP bits will also be cleared
*/
ifbp->IFB_CntlOpt |= DMA_ENABLED;
- HCFASSERT( NT_ASSERT, NEVER_TESTED )
+ HCFASSERT( NT_ASSERT, NEVER_TESTED );
// make the entire rx descriptor chain DMA-owned, so the DMA engine can (re-)use it.
p = ifbp->IFB_FirstDesc[DMA_RX];
if (p != NULL) { //;? Think this over again in the light of the new chaining strategy
- if ( 1 ) { //begin alternative
- HCFASSERT( NT_ASSERT, NEVER_TESTED )
+ if ( 1 ) { //begin alternative
+ HCFASSERT( NT_ASSERT, NEVER_TESTED );
put_frame_lst( ifbp, ifbp->IFB_FirstDesc[DMA_RX], DMA_RX );
if ( ifbp->IFB_FirstDesc[DMA_RX] ) {
put_frame_lst( ifbp, ifbp->IFB_FirstDesc[DMA_RX]->next_desc_addr, DMA_RX );
@@ -1013,147 +979,147 @@ int rc = HCF_ERR_INCOMP_FW;
}
}
#endif // HCF_DMA
- HCFASSERT( rc == HCF_SUCCESS, rc )
- HCFLOGEXIT( HCF_TRACE_CNTL )
+ HCFASSERT( rc == HCF_SUCCESS, rc );
+ HCFLOGEXIT( HCF_TRACE_CNTL );
return rc;
} // hcf_cntl
/************************************************************************************************************
-*
-*.MODULE int hcf_connect( IFBP ifbp, hcf_io io_base )
-*.PURPOSE Grants access right for the HCF to the IFB.
-* Initializes Card and HCF housekeeping.
-*
-*.ARGUMENTS
-* ifbp (near) address of the Interface Block
-* io_base non-USB: I/O Base address of the NIC (connect)
-* non-USB: HCF_DISCONNECT
-* USB: HCF_CONNECT, HCF_DISCONNECT
-*
-*.RETURNS
-* HCF_SUCCESS
-* HCF_ERR_INCOMP_PRI
-* HCF_ERR_INCOMP_FW
-* HCF_ERR_DEFUNCT_CMD_SEQ
-*!! HCF_ERR_NO_NIC really returned ;?
-* HCF_ERR_NO_NIC
-* HCF_ERR_TIME_OUT
-*
-* MSF-accessible fields of Result Block:
-* IFB_IOBase entry parameter io_base
-* IFB_IORange HREG_IO_RANGE (0x40/0x80)
-* IFB_Version version of the IFB layout
-* IFB_FWIdentity CFG_FW_IDENTITY_STRCT, specifies the identity of the
-* "running" F/W, i.e. tertiary F/W under normal conditions
-* IFB_FWSup CFG_SUP_RANGE_STRCT, specifies the supplier range of
-* the "running" F/W, i.e. tertiary F/W under normal conditions
-* IFB_HSISup CFG_SUP_RANGE_STRCT, specifies the HW/SW I/F range of the NIC
-* IFB_PRIIdentity CFG_PRI_IDENTITY_STRCT, specifies the Identity of the Primary F/W
-* IFB_PRISup CFG_SUP_RANGE_STRCT, specifies the supplier range of the Primary F/W
-* all other all MSF accessible fields, which are not specified above, are zero-filled
-*
-*.CONDITIONS
-* It is the responsibility of the MSF to assure the correctness of the I/O Base address.
-*
-* Note: hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF )
-* was called.
-*
-*.DESCRIPTION
-* hcf_connect passes the MSF-defined location of the IFB to the HCF and grants or revokes access right for the
-* HCF to the IFB. Revoking is done by specifying HCF_DISCONNECT rather than an I/O address for the parameter
-* io_base. Every call of hcf_connect in "connect" mode, must eventually be followed by a call of hcf_connect
-* in "disconnect" mode. Clalling hcf_connect in "connect"/"disconnect" mode can not be nested.
-* The IFB address must be used as a handle with all subsequent HCF-function calls and the HCF uses the IFB
-* address as a handle when it performs a call(back) of an MSF-function (i.e. msf_assert).
-*
-* Note that not only the MSF accessible fields are cleared, but also all internal housekeeping
-* information is re-initialized.
-* This implies that all settings which are done via hcf_action and hcf_put_info (e.g. CFG_MB_ASSERT, CFG_REG_MB,
-* CFG_REG_INFO_LOG) must be done again. The only field which is not cleared, is IFB_MSFSup.
-*
-* If HCF_INT_ON is selected as compile option, NIC interrupts are disabled.
-*
-* Assert fails if
-* - ifbp is not properly aligned ( ref chapter HCF_ALIGN in 4.1.1)
-* - I/O Base Address is not a multiple of 0x40 (note: 0x0000 is explicitly allowed).
-*
-*.DIAGRAM
-*
-*0: Throughout hcf_connect you need to distinguish the connect from the disconnect case, which requires
-* some attention about what to use as "I/O" address when for which purpose.
-*2:
-*2a: Reset H-II by toggling reset bit in IO-register on and off.
-* The HCF_TYPE_PRELOADED caters for the DOS environment where H-II is loaded by a separate program to
-* overcome the 64k size limit posed on DOS drivers.
-* The macro OPW is not yet useable because the IFB_IOBase field is not set.
-* Note 1: hopefully the clearing and initializing of the IFB (see below) acts as a delay which meets the
-* specification for S/W reset
-* Note 2: it turns out that on some H/W constellations, the clock to access the EEProm is not lowered
-* to an appropriate frequency by HREG_IO_SRESET. By giving an HCMD_INI first, this problem is worked around.
-*2b: Experimentally it is determined over a wide range of F/W versions that waiting for the for Cmd bit in
-* Ev register gives a workable strategy. The available documentation does not give much clues.
-*4: clear and initialize the IFB
-* The HCF house keeping info is designed such that zero is the appropriate initial value for as much as
-* feasible IFB-items.
-* The readable fields mentioned in the description section and some HCF specific fields are given their
-* actual value.
-* IFB_TickIni is initialized at best guess before calibration
-* Hcf_connect defaults to "no interrupt generation" (implicitly achieved by the zero-filling).
-*6: Register compile-time linked MSF Routine and set default filter level
-* cast needed to get around the "near" problem in DOS COM model
-* er C2446: no conversion from void (__near __cdecl *)(unsigned char __far *,unsigned int,unsigned short,int)
-* to void (__far __cdecl *)(unsigned char __far *,unsigned int,unsigned short,int)
-*8: If a command is apparently still active (as indicated by the Busy bit in Cmd register) this may indicate a
-* blocked cmd pipe line. To unblock the following actions are done:
-* - Ack everything
-* - Wait for Busy bit drop in Cmd register
-* - Wait for Cmd bit raise in Ev register
-* The two waits are combined in a single HCF_WAIT_WHILE to optimize memory size. If either of these waits
-* fail (prot_cnt becomes 0), then something is serious wrong. Rather than PANICK, the assumption is that the
-* next cmd_exe will fail, causing the HCF to go into DEFUNCT mode
-*10: Ack everything to unblock a (possibly blocked) cmd pipe line
-* Note 1: it is very likely that an Alloc event is pending and very well possible that a (Send) Cmd event is
-* pending on non-initial calls
-* Note 2: it is assumed that this strategy takes away the need to ack every conceivable event after an
-* Hermes Initialize
-*12: Only H-II NEEDS the Hermes Initialize command. Due to the different semantics for H-I and H-II
-* Initialize command, init() does not (and can not, since it is called e.g. after a download) execute the
-* Hermes Initialize command. Executing the Hermes Initialize command for H-I would not harm but not do
-* anything useful either, so it is skipped.
-* The return status of cmd_exe is ignored. It is assumed that if cmd_exe fails, init fails too
-*14: use io_base as a flag to merge hcf_connect and hcf_disconnect into 1 routine
-* the call to init and its subsequent call of cmd_exe will return HCF_ERR_NO_NIC if appropriate. This status
-* is (badly) needed by some legacy combination of NT4 and card services which do not yield an I/O address in
-* time.
-*
-*.NOTICE
-* On platforms where the NULL-pointer is not a bit-pattern of all zeros, the zero-filling of the IFB results
-* in an incorrect initialization of pointers.
-* The implementation of the MailBox manipulation in put_mb_info protects against the absence of a MailBox
-* based on IFB_MBSize, IFB_MBWp and ifbp->IFB_MBRp. This has ramifications on the initialization of the
-* MailBox via hcf_put_info with the CFG_REG_MB type, but it prevents dependency on the "NULL-"ness of
-* IFB_MBp.
-*
-*.NOTICE
-* There are a number of problems when asserting and logging hcf_connect, e.g.
-* - Asserting on re-entrancy of hcf_connect by means of
-* "HCFASSERT( (ifbp->IFB_AssertTrace & HCF_ASSERT_CONNECT) == 0, 0 )" is not useful because IFB contents
-* are undefined
-* - Asserting before the IFB is cleared will cause mdd_assert() to interpret the garbage in IFB_AssertRtn
-* as a routine address
-* Therefore HCFTRACE nor HCFLOGENTRY is called by hcf_connect.
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE int hcf_connect( IFBP ifbp, hcf_io io_base )
+ *.PURPOSE Grants access right for the HCF to the IFB.
+ * Initializes Card and HCF housekeeping.
+ *
+ *.ARGUMENTS
+ * ifbp (near) address of the Interface Block
+ * io_base non-USB: I/O Base address of the NIC (connect)
+ * non-USB: HCF_DISCONNECT
+ * USB: HCF_CONNECT, HCF_DISCONNECT
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ * HCF_ERR_INCOMP_PRI
+ * HCF_ERR_INCOMP_FW
+ * HCF_ERR_DEFUNCT_CMD_SEQ
+ *!! HCF_ERR_NO_NIC really returned ;?
+ * HCF_ERR_NO_NIC
+ * HCF_ERR_TIME_OUT
+ *
+ * MSF-accessible fields of Result Block:
+ * IFB_IOBase entry parameter io_base
+ * IFB_IORange HREG_IO_RANGE (0x40/0x80)
+ * IFB_Version version of the IFB layout
+ * IFB_FWIdentity CFG_FW_IDENTITY_STRCT, specifies the identity of the
+ * "running" F/W, i.e. tertiary F/W under normal conditions
+ * IFB_FWSup CFG_SUP_RANGE_STRCT, specifies the supplier range of
+ * the "running" F/W, i.e. tertiary F/W under normal conditions
+ * IFB_HSISup CFG_SUP_RANGE_STRCT, specifies the HW/SW I/F range of the NIC
+ * IFB_PRIIdentity CFG_PRI_IDENTITY_STRCT, specifies the Identity of the Primary F/W
+ * IFB_PRISup CFG_SUP_RANGE_STRCT, specifies the supplier range of the Primary F/W
+ * all other all MSF accessible fields, which are not specified above, are zero-filled
+ *
+ *.CONDITIONS
+ * It is the responsibility of the MSF to assure the correctness of the I/O Base address.
+ *
+ * Note: hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF )
+ * was called.
+ *
+ *.DESCRIPTION
+ * hcf_connect passes the MSF-defined location of the IFB to the HCF and grants or revokes access right for the
+ * HCF to the IFB. Revoking is done by specifying HCF_DISCONNECT rather than an I/O address for the parameter
+ * io_base. Every call of hcf_connect in "connect" mode, must eventually be followed by a call of hcf_connect
+ * in "disconnect" mode. Clalling hcf_connect in "connect"/"disconnect" mode can not be nested.
+ * The IFB address must be used as a handle with all subsequent HCF-function calls and the HCF uses the IFB
+ * address as a handle when it performs a call(back) of an MSF-function (i.e. msf_assert).
+ *
+ * Note that not only the MSF accessible fields are cleared, but also all internal housekeeping
+ * information is re-initialized.
+ * This implies that all settings which are done via hcf_action and hcf_put_info (e.g. CFG_MB_ASSERT, CFG_REG_MB,
+ * CFG_REG_INFO_LOG) must be done again. The only field which is not cleared, is IFB_MSFSup.
+ *
+ * If HCF_INT_ON is selected as compile option, NIC interrupts are disabled.
+ *
+ * Assert fails if
+ * - ifbp is not properly aligned ( ref chapter HCF_ALIGN in 4.1.1)
+ * - I/O Base Address is not a multiple of 0x40 (note: 0x0000 is explicitly allowed).
+ *
+ *.DIAGRAM
+ *
+ *0: Throughout hcf_connect you need to distinguish the connect from the disconnect case, which requires
+ * some attention about what to use as "I/O" address when for which purpose.
+ *2:
+ *2a: Reset H-II by toggling reset bit in IO-register on and off.
+ * The HCF_TYPE_PRELOADED caters for the DOS environment where H-II is loaded by a separate program to
+ * overcome the 64k size limit posed on DOS drivers.
+ * The macro OPW is not yet useable because the IFB_IOBase field is not set.
+ * Note 1: hopefully the clearing and initializing of the IFB (see below) acts as a delay which meets the
+ * specification for S/W reset
+ * Note 2: it turns out that on some H/W constellations, the clock to access the EEProm is not lowered
+ * to an appropriate frequency by HREG_IO_SRESET. By giving an HCMD_INI first, this problem is worked around.
+ *2b: Experimentally it is determined over a wide range of F/W versions that waiting for the for Cmd bit in
+ * Ev register gives a workable strategy. The available documentation does not give much clues.
+ *4: clear and initialize the IFB
+ * The HCF house keeping info is designed such that zero is the appropriate initial value for as much as
+ * feasible IFB-items.
+ * The readable fields mentioned in the description section and some HCF specific fields are given their
+ * actual value.
+ * IFB_TickIni is initialized at best guess before calibration
+ * Hcf_connect defaults to "no interrupt generation" (implicitly achieved by the zero-filling).
+ *6: Register compile-time linked MSF Routine and set default filter level
+ * cast needed to get around the "near" problem in DOS COM model
+ * er C2446: no conversion from void (__near __cdecl *)(unsigned char __far *,unsigned int,unsigned short,int)
+ * to void (__far __cdecl *)(unsigned char __far *,unsigned int,unsigned short,int)
+ *8: If a command is apparently still active (as indicated by the Busy bit in Cmd register) this may indicate a
+ * blocked cmd pipe line. To unblock the following actions are done:
+ * - Ack everything
+ * - Wait for Busy bit drop in Cmd register
+ * - Wait for Cmd bit raise in Ev register
+ * The two waits are combined in a single HCF_WAIT_WHILE to optimize memory size. If either of these waits
+ * fail (prot_cnt becomes 0), then something is serious wrong. Rather than PANICK, the assumption is that the
+ * next cmd_exe will fail, causing the HCF to go into DEFUNCT mode
+ *10: Ack everything to unblock a (possibly blocked) cmd pipe line
+ * Note 1: it is very likely that an Alloc event is pending and very well possible that a (Send) Cmd event is
+ * pending on non-initial calls
+ * Note 2: it is assumed that this strategy takes away the need to ack every conceivable event after an
+ * Hermes Initialize
+ *12: Only H-II NEEDS the Hermes Initialize command. Due to the different semantics for H-I and H-II
+ * Initialize command, init() does not (and can not, since it is called e.g. after a download) execute the
+ * Hermes Initialize command. Executing the Hermes Initialize command for H-I would not harm but not do
+ * anything useful either, so it is skipped.
+ * The return status of cmd_exe is ignored. It is assumed that if cmd_exe fails, init fails too
+ *14: use io_base as a flag to merge hcf_connect and hcf_disconnect into 1 routine
+ * the call to init and its subsequent call of cmd_exe will return HCF_ERR_NO_NIC if appropriate. This status
+ * is (badly) needed by some legacy combination of NT4 and card services which do not yield an I/O address in
+ * time.
+ *
+ *.NOTICE
+ * On platforms where the NULL-pointer is not a bit-pattern of all zeros, the zero-filling of the IFB results
+ * in an incorrect initialization of pointers.
+ * The implementation of the MailBox manipulation in put_mb_info protects against the absence of a MailBox
+ * based on IFB_MBSize, IFB_MBWp and ifbp->IFB_MBRp. This has ramifications on the initialization of the
+ * MailBox via hcf_put_info with the CFG_REG_MB type, but it prevents dependency on the "NULL-"ness of
+ * IFB_MBp.
+ *
+ *.NOTICE
+ * There are a number of problems when asserting and logging hcf_connect, e.g.
+ * - Asserting on re-entrancy of hcf_connect by means of
+ * "HCFASSERT( (ifbp->IFB_AssertTrace & HCF_ASSERT_CONNECT) == 0, 0 )" is not useful because IFB contents
+ * are undefined
+ * - Asserting before the IFB is cleared will cause mdd_assert() to interpret the garbage in IFB_AssertRtn
+ * as a routine address
+ * Therefore HCFTRACE nor HCFLOGENTRY is called by hcf_connect.
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
hcf_connect( IFBP ifbp, hcf_io io_base )
{
-int rc = HCF_SUCCESS;
-hcf_io io_addr;
-hcf_32 prot_cnt;
-hcf_8 *q;
-LTV_STRCT x;
+ int rc = HCF_SUCCESS;
+ hcf_io io_addr;
+ hcf_32 prot_cnt;
+ hcf_8 *q;
+ LTV_STRCT x;
#if HCF_ASSERT
hcf_16 xa = ifbp->IFB_FWIdentity.typ;
/* is assumed to cause an assert later on if hcf_connect is called without intervening hcf_disconnect.
@@ -1163,51 +1129,51 @@ LTV_STRCT x;
*/
#endif // HCF_ASSERT
- if ( io_base == HCF_DISCONNECT ) { //disconnect
+ if ( io_base == HCF_DISCONNECT ) { //disconnect
io_addr = ifbp->IFB_IOBase;
- OPW( HREG_INT_EN, 0 ); //;?workaround against dying F/W on subsequent hcf_connect calls
- } else { //connect /* 0 */
+ OPW( HREG_INT_EN, 0 ); //;?workaround against dying F/W on subsequent hcf_connect calls
+ } else { //connect /* 0 */
io_addr = io_base;
}
#if 0 //;? if a subsequent hcf_connect is preceded by an hcf_disconnect the wakeup is not needed !!
#if HCF_SLEEP
- OUT_PORT_WORD( .....+HREG_IO, HREG_IO_WAKEUP_ASYNC ); //OPW not yet useable
- MSF_WAIT(800); // MSF-defined function to wait n microseconds.
+ OUT_PORT_WORD( .....+HREG_IO, HREG_IO_WAKEUP_ASYNC ); //OPW not yet useable
+ MSF_WAIT(800); // MSF-defined function to wait n microseconds.
note that MSF_WAIT uses not yet defined!!!! IFB_IOBase and IFB_TickIni (via PROT_CNT_INI)
so be careful if this code is restored
#endif // HCF_SLEEP
#endif // 0
-#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 //switch clock back for SEEPROM access !!!
- OUT_PORT_WORD( io_addr + HREG_CMD, HCMD_INI ); //OPW not yet useable
+#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 //switch clock back for SEEPROM access !!!
+ OUT_PORT_WORD( io_addr + HREG_CMD, HCMD_INI ); //OPW not yet useable
prot_cnt = INI_TICK_INI;
HCF_WAIT_WHILE( (IN_PORT_WORD( io_addr + HREG_EV_STAT) & HREG_EV_CMD) == 0 );
- OUT_PORT_WORD( (io_addr + HREG_IO), HREG_IO_SRESET ); //OPW not yet useable /* 2a*/
+ OUT_PORT_WORD( (io_addr + HREG_IO), HREG_IO_SRESET ); //OPW not yet useable /* 2a*/
#endif // HCF_TYPE_PRELOADED
- for ( q = (hcf_8*)(&ifbp->IFB_Magic); q > (hcf_8*)ifbp; *--q = 0 ) /*NOP*/; /* 4 */
- ifbp->IFB_Magic = HCF_MAGIC;
- ifbp->IFB_Version = IFB_VERSION;
+ for ( q = (hcf_8*)(&ifbp->IFB_Magic); q > (hcf_8*)ifbp; *--q = 0 ) /*NOP*/; /* 4 */
+ ifbp->IFB_Magic = HCF_MAGIC;
+ ifbp->IFB_Version = IFB_VERSION;
#if defined MSF_COMPONENT_ID //a new IFB demonstrates how dirty the solution is
- xxxx[xxxx_PRI_IDENTITY_OFFSET] = NULL; //IFB_PRIIdentity placeholder 0xFD02
- xxxx[xxxx_PRI_IDENTITY_OFFSET+1] = NULL; //IFB_PRISup placeholder 0xFD03
+ xxxx[xxxx_PRI_IDENTITY_OFFSET] = NULL; //IFB_PRIIdentity placeholder 0xFD02
+ xxxx[xxxx_PRI_IDENTITY_OFFSET+1] = NULL; //IFB_PRISup placeholder 0xFD03
#endif // MSF_COMPONENT_ID
#if (HCF_TALLIES) & ( HCF_TALLIES_NIC | HCF_TALLIES_HCF )
- ifbp->IFB_TallyLen = 1 + 2 * (HCF_NIC_TAL_CNT + HCF_HCF_TAL_CNT); //convert # of Tallies to L value for LTV
- ifbp->IFB_TallyTyp = CFG_TALLIES; //IFB_TallyTyp: set T value
+ ifbp->IFB_TallyLen = 1 + 2 * (HCF_NIC_TAL_CNT + HCF_HCF_TAL_CNT); //convert # of Tallies to L value for LTV
+ ifbp->IFB_TallyTyp = CFG_TALLIES; //IFB_TallyTyp: set T value
#endif // HCF_TALLIES_NIC / HCF_TALLIES_HCF
- ifbp->IFB_IOBase = io_addr; //set IO_Base asap, so asserts via HREG_SW_2 don't harm
- ifbp->IFB_IORange = HREG_IO_RANGE;
- ifbp->IFB_CntlOpt = USE_16BIT;
+ ifbp->IFB_IOBase = io_addr; //set IO_Base asap, so asserts via HREG_SW_2 don't harm
+ ifbp->IFB_IORange = HREG_IO_RANGE;
+ ifbp->IFB_CntlOpt = USE_16BIT;
#if HCF_ASSERT
assert_ifbp = ifbp;
ifbp->IFB_AssertLvl = 1;
#if (HCF_ASSERT) & HCF_ASSERT_LNK_MSF_RTN
if ( io_base != HCF_DISCONNECT ) {
- ifbp->IFB_AssertRtn = (MSF_ASSERT_RTNP)msf_assert; /* 6 */
+ ifbp->IFB_AssertRtn = (MSF_ASSERT_RTNP)msf_assert; /* 6 */
}
#endif // HCF_ASSERT_LNK_MSF_RTN
-#if (HCF_ASSERT) & HCF_ASSERT_MB //build the structure to pass the assert info to hcf_put_info
+#if (HCF_ASSERT) & HCF_ASSERT_MB //build the structure to pass the assert info to hcf_put_info
ifbp->IFB_AssertStrct.len = sizeof(ifbp->IFB_AssertStrct)/sizeof(hcf_16) - 1;
ifbp->IFB_AssertStrct.typ = CFG_MB_INFO;
ifbp->IFB_AssertStrct.base_typ = CFG_MB_ASSERT;
@@ -1217,34 +1183,34 @@ LTV_STRCT x;
ifbp->IFB_AssertStrct.frag_buf[0].frag_addr = &ifbp->IFB_AssertLine;
#endif // HCF_ASSERT_MB
#endif // HCF_ASSERT
- IF_PROT_TIME( prot_cnt = ifbp->IFB_TickIni = INI_TICK_INI; )
+ IF_PROT_TIME( prot_cnt = ifbp->IFB_TickIni = INI_TICK_INI );
#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0
//!! No asserts before Reset-bit in HREG_IO is cleared
- OPW( HREG_IO, 0x0000 ); //OPW useable /* 2b*/
+ OPW( HREG_IO, 0x0000 ); //OPW useable /* 2b*/
HCF_WAIT_WHILE( (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 );
- IF_PROT_TIME( HCFASSERT( prot_cnt, IPW( HREG_EV_STAT) ) )
- IF_PROT_TIME( if ( prot_cnt ) prot_cnt = ifbp->IFB_TickIni; )
+ IF_PROT_TIME( HCFASSERT( prot_cnt, IPW( HREG_EV_STAT) ) );
+ IF_PROT_TIME( if ( prot_cnt ) prot_cnt = ifbp->IFB_TickIni );
#endif // HCF_TYPE_PRELOADED
//!! No asserts before Reset-bit in HREG_IO is cleared
- HCFASSERT( DO_ASSERT, MERGE_2( HCF_ASSERT, 0xCAF0 ) ) //just to proof that the complete assert machinery is working
- HCFASSERT( xa != CFG_FW_IDENTITY, 0 ) // assert if hcf_connect is called without intervening hcf_disconnect.
- HCFASSERT( ((hcf_32)(void*)ifbp & (HCF_ALIGN-1) ) == 0, (hcf_32)(void*)ifbp )
- HCFASSERT( (io_addr & 0x003F) == 0, io_addr )
- //if Busy bit in Cmd register
- if (IPW( HREG_CMD ) & HCMD_BUSY ) { /* 8 */
- //. Ack all to unblock a (possibly) blocked cmd pipe line
+ HCFASSERT( DO_ASSERT, MERGE_2( HCF_ASSERT, 0xCAF0 ) ); //just to proof that the complete assert machinery is working
+ HCFASSERT( xa != CFG_FW_IDENTITY, 0 ); // assert if hcf_connect is called without intervening hcf_disconnect.
+ HCFASSERT( ((hcf_32)(void*)ifbp & (HCF_ALIGN-1) ) == 0, (hcf_32)(void*)ifbp );
+ HCFASSERT( (io_addr & 0x003F) == 0, io_addr );
+ //if Busy bit in Cmd register
+ if (IPW( HREG_CMD ) & HCMD_BUSY ) { /* 8 */
+ //. Ack all to unblock a (possibly) blocked cmd pipe line
OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ );
- //. Wait for Busy bit drop in Cmd register
- //. Wait for Cmd bit raise in Ev register
+ //. Wait for Busy bit drop in Cmd register
+ //. Wait for Cmd bit raise in Ev register
HCF_WAIT_WHILE( ( IPW( HREG_CMD ) & HCMD_BUSY ) && (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 );
- IF_PROT_TIME( HCFASSERT( prot_cnt, IPW( HREG_EV_STAT) ) ) /* if prot_cnt == 0, cmd_exe will fail, causing DEFUNCT */
+ IF_PROT_TIME( HCFASSERT( prot_cnt, IPW( HREG_EV_STAT) ) ); /* if prot_cnt == 0, cmd_exe will fail, causing DEFUNCT */
}
OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ );
-#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 /*12*/
+#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 /*12*/
(void)cmd_exe( ifbp, HCMD_INI, 0 );
#endif // HCF_TYPE_PRELOADED
-if ( io_base != HCF_DISCONNECT ) {
- rc = init( ifbp ); /*14*/
+ if ( io_base != HCF_DISCONNECT ) {
+ rc = init( ifbp ); /*14*/
if ( rc == HCF_SUCCESS ) {
x.len = 2;
x.typ = CFG_NIC_BUS_TYPE;
@@ -1253,10 +1219,10 @@ if ( io_base != HCF_DISCONNECT ) {
//CFG_NIC_BUS_TYPE not supported -> default 32 bits/DMA, MSF has to overrule via CFG_CNTL_OPT
if ( x.len == 0 || x.val[0] == 0x0002 || x.val[0] == 0x0003 ) {
#if (HCF_IO) & HCF_IO_32BITS
- ifbp->IFB_CntlOpt &= ~USE_16BIT; //reset USE_16BIT
+ ifbp->IFB_CntlOpt &= ~USE_16BIT; //reset USE_16BIT
#endif // HCF_IO_32BITS
#if HCF_DMA
- ifbp->IFB_CntlOpt |= USE_DMA; //SET DMA
+ ifbp->IFB_CntlOpt |= USE_DMA; //SET DMA
#else
ifbp->IFB_IORange = 0x40 /*i.s.o. HREG_IO_RANGE*/;
#endif // HCF_DMA
@@ -1264,188 +1230,188 @@ if ( io_base != HCF_DISCONNECT ) {
}
} else HCFASSERT( ( ifbp->IFB_Magic ^= HCF_MAGIC ) == 0, ifbp->IFB_Magic ) /*NOP*/;
/* of above HCFASSERT only the side effect is needed, NOP in case HCFASSERT is dummy */
- ifbp->IFB_IOBase = io_base; /* 0*/
+ ifbp->IFB_IOBase = io_base; /* 0*/
return rc;
} // hcf_connect
#if HCF_DMA
/************************************************************************************************************
-* Function get_frame_lst
-* - resolve the "last host-owned descriptor" problems when a descriptor list is reclaimed by the MSF.
-*
-* The FrameList to be reclaimed as well as the DescriptorList always start in IFB_FirstDesc[tx_rx_flag]
-* and this is always the "current" DELWA Descriptor.
-*
-* If a FrameList is available, the last descriptor of the FrameList to turned into a new DELWA Descriptor:
-* - a copy is made from the information in the last descriptor of the FrameList into the current
-* DELWA Descriptor
-* - the remainder of the DescriptorList is detached from the copy by setting the next_desc_addr at NULL
-* - the DMA control bits of the copy are cleared to do not confuse the MSF
-* - the copy of the last descriptor (i.e. the "old" DELWA Descriptor) is chained to the prev Descriptor
-* of the FrameList, thus replacing the original last Descriptor of the FrameList.
-* - IFB_FirstDesc is changed to the address of that replaced (original) last descriptor of the FrameList,
-* i.e. the "new" DELWA Descriptor.
-*
-* This function makes a copy of that last host-owned descriptor, so the MSF will get a copy of the descriptor.
-* On top of that, it adjusts DMA related fields in the IFB structure.
- // perform a copying-scheme to circumvent the 'last host owned descriptor cannot be reclaimed' limitation imposed by H2.5's DMA hardware design
- // a 'reclaim descriptor' should be available in the HCF:
-*
-* Returns: address of the first descriptor of the FrameList
-*
+ * Function get_frame_lst
+ * - resolve the "last host-owned descriptor" problems when a descriptor list is reclaimed by the MSF.
+ *
+ * The FrameList to be reclaimed as well as the DescriptorList always start in IFB_FirstDesc[tx_rx_flag]
+ * and this is always the "current" DELWA Descriptor.
+ *
+ * If a FrameList is available, the last descriptor of the FrameList to turned into a new DELWA Descriptor:
+ * - a copy is made from the information in the last descriptor of the FrameList into the current
+ * DELWA Descriptor
+ * - the remainder of the DescriptorList is detached from the copy by setting the next_desc_addr at NULL
+ * - the DMA control bits of the copy are cleared to do not confuse the MSF
+ * - the copy of the last descriptor (i.e. the "old" DELWA Descriptor) is chained to the prev Descriptor
+ * of the FrameList, thus replacing the original last Descriptor of the FrameList.
+ * - IFB_FirstDesc is changed to the address of that replaced (original) last descriptor of the FrameList,
+ * i.e. the "new" DELWA Descriptor.
+ *
+ * This function makes a copy of that last host-owned descriptor, so the MSF will get a copy of the descriptor.
+ * On top of that, it adjusts DMA related fields in the IFB structure.
+ // perform a copying-scheme to circumvent the 'last host owned descriptor cannot be reclaimed' limitation imposed by H2.5's DMA hardware design
+ // a 'reclaim descriptor' should be available in the HCF:
+ *
+ * Returns: address of the first descriptor of the FrameList
+ *
8: Be careful once you start re-ordering the steps in the copy process, that it still works for cases
-* of FrameLists of 1, 2 and more than 2 descriptors
-*
-* Input parameters:
-* tx_rx_flag : specifies 'transmit' or 'receive' descriptor.
-*
-************************************************************************************************************/
+ * of FrameLists of 1, 2 and more than 2 descriptors
+ *
+ * Input parameters:
+ * tx_rx_flag : specifies 'transmit' or 'receive' descriptor.
+ *
+ ************************************************************************************************************/
HCF_STATIC DESC_STRCT*
get_frame_lst( IFBP ifbp, int tx_rx_flag )
{
-DESC_STRCT *head = ifbp->IFB_FirstDesc[tx_rx_flag];
-DESC_STRCT *copy, *p, *prev;
+ DESC_STRCT *head = ifbp->IFB_FirstDesc[tx_rx_flag];
+ DESC_STRCT *copy, *p, *prev;
- HCFASSERT( tx_rx_flag == DMA_RX || tx_rx_flag == DMA_TX, tx_rx_flag )
- //if FrameList
+ HCFASSERT( tx_rx_flag == DMA_RX || tx_rx_flag == DMA_TX, tx_rx_flag );
+ //if FrameList
if ( head ) {
- //. search for last descriptor of first FrameList
+ //. search for last descriptor of first FrameList
p = prev = head;
while ( ( p->BUF_SIZE & DESC_EOP ) == 0 && p->next_desc_addr ) {
- if ( ( ifbp->IFB_CntlOpt & DMA_ENABLED ) == 0 ) { //clear control bits when disabled
+ if ( ( ifbp->IFB_CntlOpt & DMA_ENABLED ) == 0 ) { //clear control bits when disabled
p->BUF_CNT &= DESC_CNT_MASK;
}
prev = p;
p = p->next_desc_addr;
}
- //. if DMA enabled
+ //. if DMA enabled
if ( ifbp->IFB_CntlOpt & DMA_ENABLED ) {
- //. . if last descriptor of FrameList is DMA owned
- //. . or if FrameList is single (DELWA) Descriptor
+ //. . if last descriptor of FrameList is DMA owned
+ //. . or if FrameList is single (DELWA) Descriptor
if ( p->BUF_CNT & DESC_DMA_OWNED || head->next_desc_addr == NULL ) {
- //. . . refuse to return FrameList to caller
+ //. . . refuse to return FrameList to caller
head = NULL;
}
}
}
- //if returnable FrameList found
+ //if returnable FrameList found
if ( head ) {
- //. if FrameList is single (DELWA) Descriptor (implies DMA disabled)
- if ( head->next_desc_addr == NULL ) {
- //. . clear DescriptorList
+ //. if FrameList is single (DELWA) Descriptor (implies DMA disabled)
+ if ( head->next_desc_addr == NULL ) {
+ //. . clear DescriptorList
/*;?ifbp->IFB_LastDesc[tx_rx_flag] =*/ ifbp->IFB_FirstDesc[tx_rx_flag] = NULL;
- //. else
+ //. else
} else {
- //. . strip hardware-related bits from last descriptor
- //. . remove DELWA Descriptor from head of DescriptorList
+ //. . strip hardware-related bits from last descriptor
+ //. . remove DELWA Descriptor from head of DescriptorList
copy = head;
- head = head->next_desc_addr;
- //. . exchange first (Confined) and last (possibly imprisoned) Descriptor
+ head = head->next_desc_addr;
+ //. . exchange first (Confined) and last (possibly imprisoned) Descriptor
copy->buf_phys_addr = p->buf_phys_addr;
copy->buf_addr = p->buf_addr;
- copy->BUF_SIZE = p->BUF_SIZE &= DESC_CNT_MASK; //get rid of DESC_EOP and possibly DESC_SOP
- copy->BUF_CNT = p->BUF_CNT &= DESC_CNT_MASK; //get rid of DESC_DMA_OWNED
+ copy->BUF_SIZE = p->BUF_SIZE &= DESC_CNT_MASK; //get rid of DESC_EOP and possibly DESC_SOP
+ copy->BUF_CNT = p->BUF_CNT &= DESC_CNT_MASK; //get rid of DESC_DMA_OWNED
#if (HCF_EXT) & HCF_DESC_STRCT_EXT
copy->DESC_MSFSup = p->DESC_MSFSup;
#endif // HCF_DESC_STRCT_EXT
- //. . turn into a DELWA Descriptor
+ //. . turn into a DELWA Descriptor
p->buf_addr = NULL;
- //. . chain copy to prev /* 8*/
+ //. . chain copy to prev /* 8*/
prev->next_desc_addr = copy;
- //. . detach remainder of the DescriptorList from FrameList
+ //. . detach remainder of the DescriptorList from FrameList
copy->next_desc_addr = NULL;
copy->next_desc_phys_addr = 0xDEAD0000; //! just to be nice, not really needed
- //. . save the new start (i.e. DELWA Descriptor) in IFB_FirstDesc
+ //. . save the new start (i.e. DELWA Descriptor) in IFB_FirstDesc
ifbp->IFB_FirstDesc[tx_rx_flag] = p;
}
- //. strip DESC_SOP from first descriptor
+ //. strip DESC_SOP from first descriptor
head->BUF_SIZE &= DESC_CNT_MASK;
//head->BUF_CNT &= DESC_CNT_MASK; get rid of DESC_DMA_OWNED
head->next_desc_phys_addr = 0xDEAD0000; //! just to be nice, not really needed
}
- //return the just detached FrameList (if any)
+ //return the just detached FrameList (if any)
return head;
} // get_frame_lst
/************************************************************************************************************
-* Function put_frame_lst
-*
-* This function
-*
-* Returns: address of the first descriptor of the FrameList
-*
-* Input parameters:
-* tx_rx_flag : specifies 'transmit' or 'receive' descriptor.
-*
-* The following list should be kept in sync with hcf_dma_tx/rx_put, in order to get them in the WCI-spec !!!!
-* Assert fails if
-* - DMA is not enabled
-* - descriptor list is NULL
-* - a descriptor in the descriptor list is not double word aligned
-* - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble.
-* - the DELWA descriptor is not a "singleton" DescriptorList.
-* - the DELWA descriptor is not the first Descriptor supplied
-* - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied
-* - Possibly more checks could be added !!!!!!!!!!!!!
-
-*.NOTICE
-* The asserts marked with *sc* are really sanity checks for the HCF, they can (supposedly) not be influenced
-* by incorrect MSF behavior
-
- // The MSF is required to supply the HCF with a single descriptor for MSF tx reclaim purposes.
- // This 'reclaim descriptor' can be recognized by the fact that its buf_addr field is zero.
- *********************************************************************************************
- * Although not required from a hardware perspective:
- * - make each descriptor in this rx-chain DMA-owned.
- * - Also set the count to zero. EOP and SOP bits are also cleared.
- *********************************************************************************************/
+ * Function put_frame_lst
+ *
+ * This function
+ *
+ * Returns: address of the first descriptor of the FrameList
+ *
+ * Input parameters:
+ * tx_rx_flag : specifies 'transmit' or 'receive' descriptor.
+ *
+ * The following list should be kept in sync with hcf_dma_tx/rx_put, in order to get them in the WCI-spec !!!!
+ * Assert fails if
+ * - DMA is not enabled
+ * - descriptor list is NULL
+ * - a descriptor in the descriptor list is not double word aligned
+ * - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble.
+ * - the DELWA descriptor is not a "singleton" DescriptorList.
+ * - the DELWA descriptor is not the first Descriptor supplied
+ * - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied
+ * - Possibly more checks could be added !!!!!!!!!!!!!
+
+ *.NOTICE
+ * The asserts marked with *sc* are really sanity checks for the HCF, they can (supposedly) not be influenced
+ * by incorrect MSF behavior
+
+ // The MSF is required to supply the HCF with a single descriptor for MSF tx reclaim purposes.
+ // This 'reclaim descriptor' can be recognized by the fact that its buf_addr field is zero.
+ *********************************************************************************************
+ * Although not required from a hardware perspective:
+ * - make each descriptor in this rx-chain DMA-owned.
+ * - Also set the count to zero. EOP and SOP bits are also cleared.
+ *********************************************************************************************/
HCF_STATIC void
put_frame_lst( IFBP ifbp, DESC_STRCT *descp, int tx_rx_flag )
{
- DESC_STRCT *p = descp;
+ DESC_STRCT *p = descp;
hcf_16 port;
- HCFASSERT( ifbp->IFB_CntlOpt & USE_DMA, ifbp->IFB_CntlOpt) //only hcf_dma_tx_put must also be DMA_ENABLED
- HCFASSERT( tx_rx_flag == DMA_RX || tx_rx_flag == DMA_TX, tx_rx_flag )
- HCFASSERT( p , 0 )
+ HCFASSERT( ifbp->IFB_CntlOpt & USE_DMA, ifbp->IFB_CntlOpt); //only hcf_dma_tx_put must also be DMA_ENABLED
+ HCFASSERT( tx_rx_flag == DMA_RX || tx_rx_flag == DMA_TX, tx_rx_flag );
+ HCFASSERT( p , 0 );
while ( p ) {
- HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p )
- HCFASSERT( (p->BUF_CNT & ~DESC_CNT_MASK) == 0, p->BUF_CNT )
- HCFASSERT( (p->BUF_SIZE & ~DESC_CNT_MASK) == 0, p->BUF_SIZE )
- p->BUF_SIZE &= DESC_CNT_MASK; //!!this SHOULD be superfluous in case of correct MSF
- p->BUF_CNT &= tx_rx_flag == DMA_RX ? 0 : DESC_CNT_MASK; //!!this SHOULD be superfluous in case of correct MSF
+ HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p );
+ HCFASSERT( (p->BUF_CNT & ~DESC_CNT_MASK) == 0, p->BUF_CNT );
+ HCFASSERT( (p->BUF_SIZE & ~DESC_CNT_MASK) == 0, p->BUF_SIZE );
+ p->BUF_SIZE &= DESC_CNT_MASK; //!!this SHOULD be superfluous in case of correct MSF
+ p->BUF_CNT &= tx_rx_flag == DMA_RX ? 0 : DESC_CNT_MASK; //!!this SHOULD be superfluous in case of correct MSF
p->BUF_CNT |= DESC_DMA_OWNED;
if ( p->next_desc_addr ) {
-// HCFASSERT( p->buf_addr && p->buf_phys_addr && p->BUF_SIZE && +/- p->BUF_SIZE, ... )
- HCFASSERT( p->next_desc_addr->desc_phys_addr, (hcf_32)p->next_desc_addr )
+// HCFASSERT( p->buf_addr && p->buf_phys_addr && p->BUF_SIZE && +/- p->BUF_SIZE, ... );
+ HCFASSERT( p->next_desc_addr->desc_phys_addr, (hcf_32)p->next_desc_addr );
p->next_desc_phys_addr = p->next_desc_addr->desc_phys_addr;
- } else { //
+ } else { //
p->next_desc_phys_addr = 0;
- if ( p->buf_addr == NULL ) { // DELWA Descriptor
- HCFASSERT( descp == p, (hcf_32)descp ) //singleton DescriptorList
- HCFASSERT( ifbp->IFB_FirstDesc[tx_rx_flag] == NULL, (hcf_32)ifbp->IFB_FirstDesc[tx_rx_flag])
- HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag] == NULL, (hcf_32)ifbp->IFB_LastDesc[tx_rx_flag])
+ if ( p->buf_addr == NULL ) { // DELWA Descriptor
+ HCFASSERT( descp == p, (hcf_32)descp ); //singleton DescriptorList
+ HCFASSERT( ifbp->IFB_FirstDesc[tx_rx_flag] == NULL, (hcf_32)ifbp->IFB_FirstDesc[tx_rx_flag]);
+ HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag] == NULL, (hcf_32)ifbp->IFB_LastDesc[tx_rx_flag]);
descp->BUF_CNT = 0; //&= ~DESC_DMA_OWNED;
ifbp->IFB_FirstDesc[tx_rx_flag] = descp;
// part of alternative ifbp->IFB_LastDesc[tx_rx_flag] = ifbp->IFB_FirstDesc[tx_rx_flag] = descp;
- // if "recycling" a FrameList
- // (e.g. called from hcf_cntl( HCF_CNTL_ENABLE )
- // . prepare for activation DMA controller
+ // if "recycling" a FrameList
+ // (e.g. called from hcf_cntl( HCF_CNTL_ENABLE )
+ // . prepare for activation DMA controller
// part of alternative descp = descp->next_desc_addr;
- } else { //a "real" FrameList, hand it over to the DMA engine
- HCFASSERT( ifbp->IFB_FirstDesc[tx_rx_flag], (hcf_32)descp )
- HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag], (hcf_32)descp )
+ } else { //a "real" FrameList, hand it over to the DMA engine
+ HCFASSERT( ifbp->IFB_FirstDesc[tx_rx_flag], (hcf_32)descp );
+ HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag], (hcf_32)descp );
HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr == NULL,
- (hcf_32)ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr)
+ (hcf_32)ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr);
// p->buf_cntl.cntl_stat |= DESC_DMA_OWNED;
ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr = descp;
ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_phys_addr = descp->desc_phys_addr;
port = HREG_RXDMA_PTR32;
if ( tx_rx_flag ) {
- p->BUF_SIZE |= DESC_EOP; // p points at the last descriptor in the caller-supplied descriptor chain
+ p->BUF_SIZE |= DESC_EOP; // p points at the last descriptor in the caller-supplied descriptor chain
descp->BUF_SIZE |= DESC_SOP;
port = HREG_TXDMA_PTR32;
}
@@ -1459,79 +1425,75 @@ put_frame_lst( IFBP ifbp, DESC_STRCT *descp, int tx_rx_flag )
/************************************************************************************************************
-*
-*.MODULE DESC_STRCT* hcf_dma_rx_get( IFBP ifbp )
-*.PURPOSE decapsulate a message and provides that message to the MSF.
-* reclaim all descriptors in the rx descriptor chain.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS
-* pointer to a FrameList
-*
-*.DESCRIPTION
-* hcf_dma_rx_get is intended to return a received frame when such a frame is deposited in Host memory by the
-* DMA engine. In addition hcf_dma_rx_get can be used to reclaim all descriptors in the rx descriptor chain
-* when the DMA Engine is disabled, e.g. as part of a driver unloading strategy.
-* hcf_dma_rx_get must be called repeatedly by the MSF when hcf_service_nic signals availability of a rx frame
-* through the HREG_EV_RDMAD flag of IFB_DmaPackets. The calling must stop when a NULL pointer is returned, at
-* which time the HREG_EV_RDMAD flag is also cleared by the HCF to arm the mechanism for the next frame
-* reception.
-* Regardless whether the DMA Engine is currently enabled (as controlled via hcf_cntl), if the DMA controller
-* deposited an Rx-frame in the Rx-DescriptorList, this frame is detached from the Rx-DescriptorList,
-* transformed into a FrameList (i.e. updating the housekeeping fields in the descriptors) and returned to the
-* caller.
-* If no such Rx-frame is available in the Rx-DescriptorList, the behavior of hcf_dma_rx_get depends on the
-* status of the DMA Engine.
-* If the DMA Engine is enabled, a NULL pointer is returned.
-* If the DMA Engine is disabled, the following strategy is used:
-* - the complete Rx-DescriptorList is returned. The DELWA Descriptor is not part of the Rx-DescriptorList.
-* - If there is no Rx-DescriptorList, the DELWA Descriptor is returned.
-* - If there is no DELWA Descriptor, a NULL pointer is returned.
-*
-* If the MSF performs an disable/enable sequence without exhausting the Rx-DescriptorList as described above,
-* the enable command will reset all house keeping information, i.e. already received but not yet by the MSF
-* retrieved frames are lost and the next frame will be received starting with the oldest descriptor.
-*
-* The HCF can be used in 2 fashions: with and without decapsulation for data transfer.
-* This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant.
-* If appropriate, decapsulation is done by moving some data inside the buffers and updating the descriptors
-* accordingly.
-*!! ;?????where did I describe why a simple manipulation with the count values does not suffice?
-*
-*.DIAGRAM
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE DESC_STRCT* hcf_dma_rx_get( IFBP ifbp )
+ *.PURPOSE decapsulate a message and provides that message to the MSF.
+ * reclaim all descriptors in the rx descriptor chain.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS
+ * pointer to a FrameList
+ *
+ *.DESCRIPTION
+ * hcf_dma_rx_get is intended to return a received frame when such a frame is deposited in Host memory by the
+ * DMA engine. In addition hcf_dma_rx_get can be used to reclaim all descriptors in the rx descriptor chain
+ * when the DMA Engine is disabled, e.g. as part of a driver unloading strategy.
+ * hcf_dma_rx_get must be called repeatedly by the MSF when hcf_service_nic signals availability of a rx frame
+ * through the HREG_EV_RDMAD flag of IFB_DmaPackets. The calling must stop when a NULL pointer is returned, at
+ * which time the HREG_EV_RDMAD flag is also cleared by the HCF to arm the mechanism for the next frame
+ * reception.
+ * Regardless whether the DMA Engine is currently enabled (as controlled via hcf_cntl), if the DMA controller
+ * deposited an Rx-frame in the Rx-DescriptorList, this frame is detached from the Rx-DescriptorList,
+ * transformed into a FrameList (i.e. updating the housekeeping fields in the descriptors) and returned to the
+ * caller.
+ * If no such Rx-frame is available in the Rx-DescriptorList, the behavior of hcf_dma_rx_get depends on the
+ * status of the DMA Engine.
+ * If the DMA Engine is enabled, a NULL pointer is returned.
+ * If the DMA Engine is disabled, the following strategy is used:
+ * - the complete Rx-DescriptorList is returned. The DELWA Descriptor is not part of the Rx-DescriptorList.
+ * - If there is no Rx-DescriptorList, the DELWA Descriptor is returned.
+ * - If there is no DELWA Descriptor, a NULL pointer is returned.
+ *
+ * If the MSF performs an disable/enable sequence without exhausting the Rx-DescriptorList as described above,
+ * the enable command will reset all house keeping information, i.e. already received but not yet by the MSF
+ * retrieved frames are lost and the next frame will be received starting with the oldest descriptor.
+ *
+ * The HCF can be used in 2 fashions: with and without decapsulation for data transfer.
+ * This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant.
+ * If appropriate, decapsulation is done by moving some data inside the buffers and updating the descriptors
+ * accordingly.
+ *!! ;?????where did I describe why a simple manipulation with the count values does not suffice?
+ *
+ *.DIAGRAM
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
DESC_STRCT*
hcf_dma_rx_get (IFBP ifbp)
{
-DESC_STRCT *descp; // pointer to start of FrameList
+ DESC_STRCT *descp; // pointer to start of FrameList
descp = get_frame_lst( ifbp, DMA_RX );
- if ( descp && descp->buf_addr ) //!be aware of the missing curly bracket
+ if ( descp && descp->buf_addr ) {
- //skip decapsulation at confined descriptor
+ //skip decapsulation at confined descriptor
#if (HCF_ENCAP) == HCF_ENC
-#if (HCF_TYPE) & HCF_TYPE_CCX
- if ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_OFF )
-#endif // HCF_TYPE_CCX
- {
-int i;
-DESC_STRCT *p = descp->next_desc_addr; //pointer to 2nd descriptor of frame
- HCFASSERT(p, 0)
+ int i;
+ DESC_STRCT *p = descp->next_desc_addr; //pointer to 2nd descriptor of frame
+ HCFASSERT(p, 0);
// The 2nd descriptor contains (maybe) a SNAP header plus part or whole of the payload.
//determine decapsulation sub-flag in RxFS
i = *(wci_recordp)&descp->buf_addr[HFS_STAT] & ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR );
if ( i == HFS_STAT_TUNNEL ||
- ( i == HFS_STAT_1042 && hcf_encap( (wci_bufp)&p->buf_addr[HCF_DASA_SIZE] ) != ENC_TUNNEL )) {
+ ( i == HFS_STAT_1042 && hcf_encap( (wci_bufp)&p->buf_addr[HCF_DASA_SIZE] ) != ENC_TUNNEL )) {
// The 2nd descriptor contains a SNAP header plus part or whole of the payload.
- HCFASSERT( p->BUF_CNT == (p->buf_addr[5] + (p->buf_addr[4]<<8) + 2*6 + 2 - 8), p->BUF_CNT )
+ HCFASSERT( p->BUF_CNT == (p->buf_addr[5] + (p->buf_addr[4]<<8) + 2*6 + 2 - 8), p->BUF_CNT );
// perform decapsulation
- HCFASSERT(p->BUF_SIZE >=8, p->BUF_SIZE)
+ HCFASSERT(p->BUF_SIZE >=8, p->BUF_SIZE);
// move SA[2:5] in the second buffer to replace part of the SNAP header
for ( i=3; i >= 0; i--) p->buf_addr[i+8] = p->buf_addr[i];
// copy DA[0:5], SA[0:1] from first buffer to second buffer
@@ -1542,532 +1504,494 @@ DESC_STRCT *p = descp->next_desc_addr; //pointer to 2nd descriptor of frame
}
#endif // HCF_ENC
if ( descp == NULL ) ifbp->IFB_DmaPackets &= (hcf_16)~HREG_EV_RDMAD; //;?could be integrated into get_frame_lst
- HCFLOGEXIT( HCF_TRACE_DMA_RX_GET )
+ HCFLOGEXIT( HCF_TRACE_DMA_RX_GET );
return descp;
} // hcf_dma_rx_get
/************************************************************************************************************
-*
-*.MODULE void hcf_dma_rx_put( IFBP ifbp, DESC_STRCT *descp )
-*.PURPOSE supply buffers for receive purposes.
-* supply the Rx-DELWA descriptor.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* descp address of a DescriptorList
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* This function is called by the MSF to supply the HCF with new/more buffers for receive purposes.
-* The HCF can be used in 2 fashions: with and without encapsulation for data transfer.
-* This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant.
-* As a consequence, some additional constraints apply to the number of descriptor and the buffers associated
-* with the first 2 descriptors. Independent of the encapsulation feature, the COUNT fields are ignored.
-* A special case is the supplying of the DELWA descriptor, which must be supplied as the first descriptor.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value.
-* - NIC interrupts are not disabled while required by parameter action.
-* - in case decapsulation by the HCF is selected:
-* - The first databuffer does not have the exact size corresponding with the RxFS up to the 802.3 DestAddr
-* field (== 29 words).
-* - The FrameList does not consists of at least 2 Descriptors.
-* - The second databuffer does not have the minimum size of 8 bytes.
-*!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get
-*!! them in the WCI-spec !!!!
-* - DMA is not enabled
-* - descriptor list is NULL
-* - a descriptor in the descriptor list is not double word aligned
-* - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble.
-* - the DELWA descriptor is not a "singleton" DescriptorList.
-* - the DELWA descriptor is not the first Descriptor supplied
-* - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied
-*!! - Possibly more checks could be added !!!!!!!!!!!!!
-*
-*.DIAGRAM
-*
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE void hcf_dma_rx_put( IFBP ifbp, DESC_STRCT *descp )
+ *.PURPOSE supply buffers for receive purposes.
+ * supply the Rx-DELWA descriptor.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * descp address of a DescriptorList
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * This function is called by the MSF to supply the HCF with new/more buffers for receive purposes.
+ * The HCF can be used in 2 fashions: with and without encapsulation for data transfer.
+ * This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant.
+ * As a consequence, some additional constraints apply to the number of descriptor and the buffers associated
+ * with the first 2 descriptors. Independent of the encapsulation feature, the COUNT fields are ignored.
+ * A special case is the supplying of the DELWA descriptor, which must be supplied as the first descriptor.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value.
+ * - NIC interrupts are not disabled while required by parameter action.
+ * - in case decapsulation by the HCF is selected:
+ * - The first databuffer does not have the exact size corresponding with the RxFS up to the 802.3 DestAddr
+ * field (== 29 words).
+ * - The FrameList does not consists of at least 2 Descriptors.
+ * - The second databuffer does not have the minimum size of 8 bytes.
+ *!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get
+ *!! them in the WCI-spec !!!!
+ * - DMA is not enabled
+ * - descriptor list is NULL
+ * - a descriptor in the descriptor list is not double word aligned
+ * - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble.
+ * - the DELWA descriptor is not a "singleton" DescriptorList.
+ * - the DELWA descriptor is not the first Descriptor supplied
+ * - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied
+ *!! - Possibly more checks could be added !!!!!!!!!!!!!
+ *
+ *.DIAGRAM
+ *
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
void
hcf_dma_rx_put( IFBP ifbp, DESC_STRCT *descp )
{
- HCFLOGENTRY( HCF_TRACE_DMA_RX_PUT, 0xDA01 )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
+ HCFLOGENTRY( HCF_TRACE_DMA_RX_PUT, 0xDA01 );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
put_frame_lst( ifbp, descp, DMA_RX );
#if HCF_ASSERT && (HCF_ENCAP) == HCF_ENC
if ( descp->buf_addr ) {
- HCFASSERT( descp->BUF_SIZE == HCF_DMA_RX_BUF1_SIZE, descp->BUF_SIZE )
- HCFASSERT( descp->next_desc_addr, 0 ) // first descriptor should be followed by another descriptor
+ HCFASSERT( descp->BUF_SIZE == HCF_DMA_RX_BUF1_SIZE, descp->BUF_SIZE );
+ HCFASSERT( descp->next_desc_addr, 0 ); // first descriptor should be followed by another descriptor
// The second DB is for SNAP and payload purposes. It should be a minimum of 12 bytes in size.
- HCFASSERT( descp->next_desc_addr->BUF_SIZE >= 12, descp->next_desc_addr->BUF_SIZE )
+ HCFASSERT( descp->next_desc_addr->BUF_SIZE >= 12, descp->next_desc_addr->BUF_SIZE );
}
#endif // HCFASSERT / HCF_ENC
- HCFLOGEXIT( HCF_TRACE_DMA_RX_PUT )
+ HCFLOGEXIT( HCF_TRACE_DMA_RX_PUT );
} // hcf_dma_rx_put
/************************************************************************************************************
-*
-*.MODULE DESC_STRCT* hcf_dma_tx_get( IFBP ifbp )
-*.PURPOSE DMA mode: reclaims and decapsulates packets in the tx descriptor chain if:
-* - A Tx packet has been copied from host-RAM into NIC-RAM by the DMA engine
-* - The Hermes/DMAengine have been disabled
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS
-* pointer to a reclaimed Tx packet.
-*
-*.DESCRIPTION
-* impact of the disable command:
-* When a non-empty pool of Tx descriptors exists (created by means of hcf_dma_put_tx), the MSF
-* is supposed to empty that pool by means of hcf_dma_tx_get calls after the disable in an
-* disable/enable sequence.
-*
-*.DIAGRAM
-*
-*.NOTICE
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE DESC_STRCT* hcf_dma_tx_get( IFBP ifbp )
+ *.PURPOSE DMA mode: reclaims and decapsulates packets in the tx descriptor chain if:
+ * - A Tx packet has been copied from host-RAM into NIC-RAM by the DMA engine
+ * - The Hermes/DMAengine have been disabled
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS
+ * pointer to a reclaimed Tx packet.
+ *
+ *.DESCRIPTION
+ * impact of the disable command:
+ * When a non-empty pool of Tx descriptors exists (created by means of hcf_dma_put_tx), the MSF
+ * is supposed to empty that pool by means of hcf_dma_tx_get calls after the disable in an
+ * disable/enable sequence.
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
DESC_STRCT*
hcf_dma_tx_get( IFBP ifbp )
{
-DESC_STRCT *descp; // pointer to start of FrameList
+ DESC_STRCT *descp; // pointer to start of FrameList
descp = get_frame_lst( ifbp, DMA_TX );
- if ( descp && descp->buf_addr ) //!be aware of the missing curly bracket
- //skip decapsulation at confined descriptor
+ if ( descp && descp->buf_addr ) {
+ //skip decapsulation at confined descriptor
#if (HCF_ENCAP) == HCF_ENC
- if ( ( descp->BUF_CNT == HFS_TYPE )
-#if (HCF_TYPE) & HCF_TYPE_CCX
- || ( descp->BUF_CNT == HFS_DAT )
-#endif // HCF_TYPE_CCX
- ) { // perform decapsulation if needed
+ if ( ( descp->BUF_CNT == HFS_TYPE )) {
+ // perform decapsulation if needed
descp->next_desc_addr->buf_phys_addr -= HCF_DASA_SIZE;
- descp->next_desc_addr->BUF_CNT += HCF_DASA_SIZE;
+ descp->next_desc_addr->BUF_CNT += HCF_DASA_SIZE;
}
#endif // HCF_ENC
+ }
if ( descp == NULL ) { //;?could be integrated into get_frame_lst
ifbp->IFB_DmaPackets &= (hcf_16)~HREG_EV_TDMAD;
}
- HCFLOGEXIT( HCF_TRACE_DMA_TX_GET )
+ HCFLOGEXIT( HCF_TRACE_DMA_TX_GET );
return descp;
} // hcf_dma_tx_get
/************************************************************************************************************
-*
-*.MODULE void hcf_dma_tx_put( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl )
-*.PURPOSE puts a packet in the Tx DMA queue in host ram and kicks off the TxDma engine.
-* supply the Tx-DELWA descriptor.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* descp address of Tx Descriptor Chain (i.e. a single Tx frame)
-* tx_cntl indicates MAC-port and (Hermes) options
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* The HCF can be used in 2 fashions: with and without encapsulation for data transfer.
-* This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant.
-*
-* Regardless of the HCF_ENCAP system constant, the descriptor list created to describe the frame to be
-* transmitted, must supply space to contain the 802.11 header, preceding the actual frame to be transmitted.
-* Basically, this only supplies working storage to the HCF which passes this on to the DMA engine.
-* As a consequence the contents of this space do not matter.
-* Nevertheless BUF_CNT must take in account this storage.
-* This working space to contain the 802.11 header may not be fragmented, the first buffer must be
-* sufficiently large to contain at least the 802.11 header, i.e. HFS_ADDR_DEST (29 words or 0x3A bytes).
-* This way, the HCF can simply, regardless whether or not the HCF encapsulates the frame, write the parameter
-* tx_cntl at offset 0x36 (HFS_TX_CNTL) in the first buffer.
-* Note that it is allowed to have part or all of the actual frame represented by the first descriptor as long
-* as the requirement for storage for the 802.11 header is met, i.e. the 802.3 frame starts at offset
-* HFS_ADDR_DEST.
-* Except for the Assert on the 1st buffer in case of Encapsualtion, the SIZE fields are ignored.
-*
-* In case the encapsulation feature is compiled in, there are the following additional requirements.
-* o The BUF_CNT of the first buffer changes from a minimum of 0x3A bytes to exactly 0x3A, i.e. the workspace
-* to store the 802.11 header
-* o The BUF_SIZE of the first buffer is at least the space needed to store the
-* - 802.11 header (29 words)
-* - 802.3 header, i.e. 12 bytes addressing information and 2 bytes length field
-* - 6 bytes SNAP-header
-* This results in 39 words or 0x4E bytes or HFS_TYPE.
-* Note that if the BUF_SIZE is larger than 0x4E, this surplus is not used.
-* o The actual frame begins in the 2nd descriptor (which is already implied by the BUF_CNT == 0x3A requirement) and the associated buffer contains at least the 802.3 header, i.e. the 14 bytes representing addressing information and length/type field
-*
-* When the HCF does not encapsulates (i.e. length/type field <= 1500), no changes are made to descriptors
-* or buffers.
-*
-* When the HCF actually encapsulates (i.e. length/type field > 1500), it successively writes, starting at
-* offset HFS_ADDR_DEST (0x3A) in the first buffer:
-* - the 802.3 addressing information, copied from the begin of the second buffer
-* - the frame length, derived from the total length of the individual fragments, corrected for the SNAP
-* header length and Type field and ignoring the Destination Address, Source Address and Length field
-* - the appropriate snap header (Tunnel or 1042, depending on the value of the type field).
-*
-* The information in the first two descriptors is adjusted accordingly:
-* - the first descriptor count is changed from 0x3A to 0x4E (HFS_TYPE), which matches 0x3A + 12 + 2 + 6
-* - the second descriptor count is decreased by 12, being the moved addressing information
-* - the second descriptor (physical) buffer address is increased by 12.
-*
-* When the descriptors are returned by hcf_dma_tx_get, the transformation of the first two descriptors is
-* undone.
-*
-* Under any of the above scenarios, the assert BUF_CNT <= BUF_SIZE must be true for all descriptors
-* In case of encapsulation, BUF_SIZE of the 1st descriptor is asserted to be at least HFS_TYPE (0x4E), so it is NOT tested.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value.
-* - tx_cntl has a recognizable out-of-range value.
-* - NIC interrupts are not disabled while required by parameter action.
-* - in case encapsulation by the HCF is selected:
-* - The FrameList does not consists of at least 2 Descriptors.
-* - The first databuffer does not contain exactly the (space for) the 802.11 header (== 28 words)
-* - The first databuffer does not have a size to additionally accommodate the 802.3 header and the
-* SNAP header of the frame after encapsulation (== 39 words).
-* - The second databuffer does not contain at least DA, SA and 'type/length' (==14 bytes or 7 words)
-*!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get
-*!! them in the WCI-spec !!!!
-* - DMA is not enabled
-* - descriptor list is NULL
-* - a descriptor in the descriptor list is not double word aligned
-* - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble.
-* - the DELWA descriptor is not a "singleton" DescriptorList.
-* - the DELWA descriptor is not the first Descriptor supplied
-* - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied
-*!! - Possibly more checks could be added !!!!!!!!!!!!!
-*.DIAGRAM
-*
-*.NOTICE
-*
-*.ENDDOC END DOCUMENTATION
-*
-*
-*1: Write tx_cntl parameter to HFS_TX_CNTL field into the Hermes-specific header in buffer 1
-*4: determine whether encapsulation is needed and write the type (tunnel or 1042) already at the appropriate
-* offset in the 1st buffer
-*6: Build the encapsualtion enveloppe in the free space at the end of the 1st buffer
-* - Copy DA/SA fields from the 2nd buffer
-* - Calculate total length of the message (snap-header + type-field + the length of all buffer fragments
-* associated with the 802.3 frame (i.e all descriptors except the first), but not the DestinationAddress,
-* SourceAddress and length-field)
-* Assert the message length
-* Write length. Note that the message is in BE format, hence on LE platforms the length must be converted
-* ;? THIS IS NOT WHAT CURRENTLY IS IMPLEMENTED
-* - Write snap header. Note that the last byte of the snap header is NOT copied, that byte is already in
-* place as result of the call to hcf_encap.
-* Note that there are many ways to skin a cat. To express the offsets in the 1st buffer while writing
-* the snap header, HFS_TYPE is chosen as a reference point to make it easier to grasp that the snap header
-* and encapsualtion type are at least relative in the right.
-*8: modify 1st descriptor to reflect moved part of the 802.3 header + Snap-header
-* modify 2nd descriptor to skip the moved part of the 802.3 header (DA/SA
-*10: set each descriptor to 'DMA owned', clear all other control bits.
-* Set SOP bit on first descriptor. Set EOP bit on last descriptor.
-*12: Either append the current frame to an existing descriptor list or
-*14: create a list beginning with the current frame
-*16: remember the new end of the list
-*20: hand the frame over to the DMA engine
-************************************************************************************************************/
+ *
+ *.MODULE void hcf_dma_tx_put( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl )
+ *.PURPOSE puts a packet in the Tx DMA queue in host ram and kicks off the TxDma engine.
+ * supply the Tx-DELWA descriptor.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * descp address of Tx Descriptor Chain (i.e. a single Tx frame)
+ * tx_cntl indicates MAC-port and (Hermes) options
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * The HCF can be used in 2 fashions: with and without encapsulation for data transfer.
+ * This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant.
+ *
+ * Regardless of the HCF_ENCAP system constant, the descriptor list created to describe the frame to be
+ * transmitted, must supply space to contain the 802.11 header, preceding the actual frame to be transmitted.
+ * Basically, this only supplies working storage to the HCF which passes this on to the DMA engine.
+ * As a consequence the contents of this space do not matter.
+ * Nevertheless BUF_CNT must take in account this storage.
+ * This working space to contain the 802.11 header may not be fragmented, the first buffer must be
+ * sufficiently large to contain at least the 802.11 header, i.e. HFS_ADDR_DEST (29 words or 0x3A bytes).
+ * This way, the HCF can simply, regardless whether or not the HCF encapsulates the frame, write the parameter
+ * tx_cntl at offset 0x36 (HFS_TX_CNTL) in the first buffer.
+ * Note that it is allowed to have part or all of the actual frame represented by the first descriptor as long
+ * as the requirement for storage for the 802.11 header is met, i.e. the 802.3 frame starts at offset
+ * HFS_ADDR_DEST.
+ * Except for the Assert on the 1st buffer in case of Encapsualtion, the SIZE fields are ignored.
+ *
+ * In case the encapsulation feature is compiled in, there are the following additional requirements.
+ * o The BUF_CNT of the first buffer changes from a minimum of 0x3A bytes to exactly 0x3A, i.e. the workspace
+ * to store the 802.11 header
+ * o The BUF_SIZE of the first buffer is at least the space needed to store the
+ * - 802.11 header (29 words)
+ * - 802.3 header, i.e. 12 bytes addressing information and 2 bytes length field
+ * - 6 bytes SNAP-header
+ * This results in 39 words or 0x4E bytes or HFS_TYPE.
+ * Note that if the BUF_SIZE is larger than 0x4E, this surplus is not used.
+ * o The actual frame begins in the 2nd descriptor (which is already implied by the BUF_CNT == 0x3A requirement) and the associated buffer contains at least the 802.3 header, i.e. the 14 bytes representing addressing information and length/type field
+ *
+ * When the HCF does not encapsulates (i.e. length/type field <= 1500), no changes are made to descriptors
+ * or buffers.
+ *
+ * When the HCF actually encapsulates (i.e. length/type field > 1500), it successively writes, starting at
+ * offset HFS_ADDR_DEST (0x3A) in the first buffer:
+ * - the 802.3 addressing information, copied from the begin of the second buffer
+ * - the frame length, derived from the total length of the individual fragments, corrected for the SNAP
+ * header length and Type field and ignoring the Destination Address, Source Address and Length field
+ * - the appropriate snap header (Tunnel or 1042, depending on the value of the type field).
+ *
+ * The information in the first two descriptors is adjusted accordingly:
+ * - the first descriptor count is changed from 0x3A to 0x4E (HFS_TYPE), which matches 0x3A + 12 + 2 + 6
+ * - the second descriptor count is decreased by 12, being the moved addressing information
+ * - the second descriptor (physical) buffer address is increased by 12.
+ *
+ * When the descriptors are returned by hcf_dma_tx_get, the transformation of the first two descriptors is
+ * undone.
+ *
+ * Under any of the above scenarios, the assert BUF_CNT <= BUF_SIZE must be true for all descriptors
+ * In case of encapsulation, BUF_SIZE of the 1st descriptor is asserted to be at least HFS_TYPE (0x4E), so it is NOT tested.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value.
+ * - tx_cntl has a recognizable out-of-range value.
+ * - NIC interrupts are not disabled while required by parameter action.
+ * - in case encapsulation by the HCF is selected:
+ * - The FrameList does not consists of at least 2 Descriptors.
+ * - The first databuffer does not contain exactly the (space for) the 802.11 header (== 28 words)
+ * - The first databuffer does not have a size to additionally accommodate the 802.3 header and the
+ * SNAP header of the frame after encapsulation (== 39 words).
+ * - The second databuffer does not contain at least DA, SA and 'type/length' (==14 bytes or 7 words)
+ *!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get
+ *!! them in the WCI-spec !!!!
+ * - DMA is not enabled
+ * - descriptor list is NULL
+ * - a descriptor in the descriptor list is not double word aligned
+ * - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble.
+ * - the DELWA descriptor is not a "singleton" DescriptorList.
+ * - the DELWA descriptor is not the first Descriptor supplied
+ * - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied
+ *!! - Possibly more checks could be added !!!!!!!!!!!!!
+ *.DIAGRAM
+ *
+ *.NOTICE
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ *
+ *1: Write tx_cntl parameter to HFS_TX_CNTL field into the Hermes-specific header in buffer 1
+ *4: determine whether encapsulation is needed and write the type (tunnel or 1042) already at the appropriate
+ * offset in the 1st buffer
+ *6: Build the encapsualtion enveloppe in the free space at the end of the 1st buffer
+ * - Copy DA/SA fields from the 2nd buffer
+ * - Calculate total length of the message (snap-header + type-field + the length of all buffer fragments
+ * associated with the 802.3 frame (i.e all descriptors except the first), but not the DestinationAddress,
+ * SourceAddress and length-field)
+ * Assert the message length
+ * Write length. Note that the message is in BE format, hence on LE platforms the length must be converted
+ * ;? THIS IS NOT WHAT CURRENTLY IS IMPLEMENTED
+ * - Write snap header. Note that the last byte of the snap header is NOT copied, that byte is already in
+ * place as result of the call to hcf_encap.
+ * Note that there are many ways to skin a cat. To express the offsets in the 1st buffer while writing
+ * the snap header, HFS_TYPE is chosen as a reference point to make it easier to grasp that the snap header
+ * and encapsualtion type are at least relative in the right.
+ *8: modify 1st descriptor to reflect moved part of the 802.3 header + Snap-header
+ * modify 2nd descriptor to skip the moved part of the 802.3 header (DA/SA
+ *10: set each descriptor to 'DMA owned', clear all other control bits.
+ * Set SOP bit on first descriptor. Set EOP bit on last descriptor.
+ *12: Either append the current frame to an existing descriptor list or
+ *14: create a list beginning with the current frame
+ *16: remember the new end of the list
+ *20: hand the frame over to the DMA engine
+ ************************************************************************************************************/
void
hcf_dma_tx_put( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl )
{
-DESC_STRCT *p = descp->next_desc_addr;
-int i;
+ DESC_STRCT *p = descp->next_desc_addr;
+ int i;
#if HCF_ASSERT
int x = ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ? tx_cntl & ~HFS_TX_CNTL_PORT : tx_cntl;
- HCFASSERT( (x & ~HCF_TX_CNTL_MASK ) == 0, tx_cntl )
+ HCFASSERT( (x & ~HCF_TX_CNTL_MASK ) == 0, tx_cntl );
#endif // HCF_ASSERT
- HCFLOGENTRY( HCF_TRACE_DMA_TX_PUT, 0xDA03 )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
- HCFASSERT( ( ifbp->IFB_CntlOpt & (USE_DMA|DMA_ENABLED) ) == (USE_DMA|DMA_ENABLED), ifbp->IFB_CntlOpt)
+ HCFLOGENTRY( HCF_TRACE_DMA_TX_PUT, 0xDA03 );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
+ HCFASSERT( ( ifbp->IFB_CntlOpt & (USE_DMA|DMA_ENABLED) ) == (USE_DMA|DMA_ENABLED), ifbp->IFB_CntlOpt);
if ( descp->buf_addr ) {
- *(hcf_16*)(descp->buf_addr + HFS_TX_CNTL) = tx_cntl; /*1*/
+ *(hcf_16*)(descp->buf_addr + HFS_TX_CNTL) = tx_cntl; /*1*/
#if (HCF_ENCAP) == HCF_ENC
- HCFASSERT( descp->next_desc_addr, 0 ) //at least 2 descripors
- HCFASSERT( descp->BUF_CNT == HFS_ADDR_DEST, descp->BUF_CNT ) //exact length required for 1st buffer
- HCFASSERT( descp->BUF_SIZE >= HCF_DMA_TX_BUF1_SIZE, descp->BUF_SIZE ) //minimal storage for encapsulation
- HCFASSERT( p->BUF_CNT >= 14, p->BUF_CNT ); //at least DA, SA and 'type' in 2nd buffer
-
-#if (HCF_TYPE) & HCF_TYPE_CCX
- /* if we are doing PPK +/- CMIC, or we are sending a DDP frame */
- if ( ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_ON ) ||
- ( ( p->BUF_CNT >= 20 ) && ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_OFF ) &&
- ( p->buf_addr[12] == 0xAA ) && ( p->buf_addr[13] == 0xAA ) &&
- ( p->buf_addr[14] == 0x03 ) && ( p->buf_addr[15] == 0x00 ) &&
- ( p->buf_addr[16] == 0x40 ) && ( p->buf_addr[17] == 0x96 ) &&
- ( p->buf_addr[18] == 0x00 ) && ( p->buf_addr[19] == 0x00 )))
- {
- /* copy the DA/SA to the first buffer */
- for ( i = 0; i < HCF_DASA_SIZE; i++ ) {
- descp->buf_addr[i + HFS_ADDR_DEST] = p->buf_addr[i];
+ HCFASSERT( descp->next_desc_addr, 0 ); //at least 2 descripors
+ HCFASSERT( descp->BUF_CNT == HFS_ADDR_DEST, descp->BUF_CNT ); //exact length required for 1st buffer
+ HCFASSERT( descp->BUF_SIZE >= HCF_DMA_TX_BUF1_SIZE, descp->BUF_SIZE ); //minimal storage for encapsulation
+ HCFASSERT( p->BUF_CNT >= 14, p->BUF_CNT ); //at least DA, SA and 'type' in 2nd buffer
+
+ descp->buf_addr[HFS_TYPE-1] = hcf_encap(&descp->next_desc_addr->buf_addr[HCF_DASA_SIZE]); /*4*/
+ if ( descp->buf_addr[HFS_TYPE-1] != ENC_NONE ) {
+ for ( i=0; i < HCF_DASA_SIZE; i++ ) { /*6*/
+ descp->buf_addr[i + HFS_ADDR_DEST] = descp->next_desc_addr->buf_addr[i];
}
- /* calculate the length of the second fragment only */
- i = 0;
- do { i += p->BUF_CNT; } while( p = p->next_desc_addr );
- i -= HCF_DASA_SIZE ;
- /* convert the length field to big endian, using the endian friendly macros */
- i = CNV_SHORT_TO_BIG(i); //!! this converts ONLY on LE platforms, how does that relate to the non-CCX code
- *(hcf_16*)(&descp->buf_addr[HFS_LEN]) = (hcf_16)i;
- descp->BUF_CNT = HFS_DAT;
- // modify 2nd descriptor to skip the 'Da/Sa' fields
- descp->next_desc_addr->buf_phys_addr += HCF_DASA_SIZE;
- descp->next_desc_addr->BUF_CNT -= HCF_DASA_SIZE;
- }
- else
-#endif // HCF_TYPE_CCX
- {
- descp->buf_addr[HFS_TYPE-1] = hcf_encap(&descp->next_desc_addr->buf_addr[HCF_DASA_SIZE]); /*4*/
- if ( descp->buf_addr[HFS_TYPE-1] != ENC_NONE ) {
- for ( i=0; i < HCF_DASA_SIZE; i++ ) { /*6*/
- descp->buf_addr[i + HFS_ADDR_DEST] = descp->next_desc_addr->buf_addr[i];
- }
- i = sizeof(snap_header) + 2 - ( 2*6 + 2 );
- do { i += p->BUF_CNT; } while ( ( p = p->next_desc_addr ) != NULL );
- *(hcf_16*)(&descp->buf_addr[HFS_LEN]) = CNV_END_SHORT(i); //!! this converts on ALL platforms, how does that relate to the CCX code
- for ( i=0; i < sizeof(snap_header) - 1; i++) {
- descp->buf_addr[HFS_TYPE - sizeof(snap_header) + i] = snap_header[i];
- }
- descp->BUF_CNT = HFS_TYPE; /*8*/
- descp->next_desc_addr->buf_phys_addr += HCF_DASA_SIZE;
- descp->next_desc_addr->BUF_CNT -= HCF_DASA_SIZE;
+ i = sizeof(snap_header) + 2 - ( 2*6 + 2 );
+ do { i += p->BUF_CNT; } while ( ( p = p->next_desc_addr ) != NULL );
+ *(hcf_16*)(&descp->buf_addr[HFS_LEN]) = CNV_END_SHORT(i); //!! this converts on ALL platforms, how does that relate to the CCX code
+ for ( i=0; i < sizeof(snap_header) - 1; i++) {
+ descp->buf_addr[HFS_TYPE - sizeof(snap_header) + i] = snap_header[i];
}
+ descp->BUF_CNT = HFS_TYPE; /*8*/
+ descp->next_desc_addr->buf_phys_addr += HCF_DASA_SIZE;
+ descp->next_desc_addr->BUF_CNT -= HCF_DASA_SIZE;
}
#endif // HCF_ENC
- }
+ }
put_frame_lst( ifbp, descp, DMA_TX );
- HCFLOGEXIT( HCF_TRACE_DMA_TX_PUT )
+ HCFLOGEXIT( HCF_TRACE_DMA_TX_PUT );
} // hcf_dma_tx_put
#endif // HCF_DMA
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.MODULE hcf_8 hcf_encap( wci_bufp type )
-*.PURPOSE test whether RFC1042 or Bridge-Tunnel encapsulation is needed.
-*
-*.ARGUMENTS
-* type (Far) pointer to the (Big Endian) Type/Length field in the message
-*
-*.RETURNS
-* ENC_NONE len/type is "len" ( (BIG_ENDIAN)type <= 1500 )
-* ENC_TUNNEL len/type is "type" and 0x80F3 or 0x8137
-* ENC_1042 len/type is "type" but not 0x80F3 or 0x8137
-*
-*.CONDITIONS
-* NIC Interrupts d.c
-*
-*.DESCRIPTION
-* Type must point to the Len/Type field of the message, this is the 2-byte field immediately after the 6 byte
-* Destination Address and 6 byte Source Address. The 2 successive bytes addressed by type are interpreted as
-* a Big Endian value. If that value is less than or equal to 1500, the message is assumed to be in 802.3
-* format. Otherwise the message is assumed to be in Ethernet-II format. Depending on the value of Len/Typ,
-* Bridge Tunnel or RFC1042 encapsulation is needed.
-*
-*.DIAGRAM
-*
-* 1: presume 802.3, hence preset return value at ENC_NONE
-* 2: convert type from "network" Endian format to native Endian
-* 4: the litmus test to distinguish type and len.
-* The hard code "magic" value of 1500 is intentional and should NOT be replaced by a mnemonic because it is
-* not related at all to the maximum frame size supported by the Hermes.
-* 6: check type against:
-* 0x80F3 //AppleTalk Address Resolution Protocol (AARP)
-* 0x8137 //IPX
-* to determine the type of encapsulation
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
-#if HCF_ENCAP //i.e HCF_ENC or HCF_ENC_SUP
-#if ! ( (HCF_ENCAP) & HCF_ENC_SUP )
-HCF_STATIC
-#endif // HCF_ENCAP
-hcf_8
+ *
+ *.MODULE hcf_8 hcf_encap( wci_bufp type )
+ *.PURPOSE test whether RFC1042 or Bridge-Tunnel encapsulation is needed.
+ *
+ *.ARGUMENTS
+ * type (Far) pointer to the (Big Endian) Type/Length field in the message
+ *
+ *.RETURNS
+ * ENC_NONE len/type is "len" ( (BIG_ENDIAN)type <= 1500 )
+ * ENC_TUNNEL len/type is "type" and 0x80F3 or 0x8137
+ * ENC_1042 len/type is "type" but not 0x80F3 or 0x8137
+ *
+ *.CONDITIONS
+ * NIC Interrupts d.c
+ *
+ *.DESCRIPTION
+ * Type must point to the Len/Type field of the message, this is the 2-byte field immediately after the 6 byte
+ * Destination Address and 6 byte Source Address. The 2 successive bytes addressed by type are interpreted as
+ * a Big Endian value. If that value is less than or equal to 1500, the message is assumed to be in 802.3
+ * format. Otherwise the message is assumed to be in Ethernet-II format. Depending on the value of Len/Typ,
+ * Bridge Tunnel or RFC1042 encapsulation is needed.
+ *
+ *.DIAGRAM
+ *
+ * 1: presume 802.3, hence preset return value at ENC_NONE
+ * 2: convert type from "network" Endian format to native Endian
+ * 4: the litmus test to distinguish type and len.
+ * The hard code "magic" value of 1500 is intentional and should NOT be replaced by a mnemonic because it is
+ * not related at all to the maximum frame size supported by the Hermes.
+ * 6: check type against:
+ * 0x80F3 //AppleTalk Address Resolution Protocol (AARP)
+ * 0x8137 //IPX
+ * to determine the type of encapsulation
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
+HCF_STATIC hcf_8
hcf_encap( wci_bufp type )
{
-hcf_8 rc = ENC_NONE; /* 1 */
-hcf_16 t = (hcf_16)(*type<<8) + *(type+1); /* 2 */
+ hcf_8 rc = ENC_NONE; /* 1 */
+ hcf_16 t = (hcf_16)(*type<<8) + *(type+1); /* 2 */
- if ( t > 1500 ) { /* 4 */
+ if ( t > 1500 ) { /* 4 */
if ( t == 0x8137 || t == 0x80F3 ) {
- rc = ENC_TUNNEL; /* 6 */
+ rc = ENC_TUNNEL; /* 6 */
} else {
rc = ENC_1042;
}
}
return rc;
} // hcf_encap
-#endif // HCF_ENCAP
-#endif // HCF_DL_ONLY
/************************************************************************************************************
-*
-*.MODULE int hcf_get_info( IFBP ifbp, LTVP ltvp )
-*.PURPOSE Obtains transient and persistent configuration information from the Card and from the HCF.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* ltvp address of LengthTypeValue structure specifying the "what" and the "how much" of the
-* information to be collected from the HCF or from the Hermes
-*
-*.RETURNS
-* HCF_ERR_LEN The provided buffer was too small
-* HCF_SUCCESS Success
-*!! via cmd_exe ( type >= CFG_RID_FW_MIN )
-* HCF_ERR_NO_NIC NIC removed during retrieval
-* HCF_ERR_TIME_OUT Expected Hermes event did not occur in expected time
-*!! via cmd_exe and setup_bap (type >= CFG_RID_FW_MIN )
-* HCF_ERR_DEFUNCT_... HCF is in defunct mode (bits 0x7F reflect cause)
-*
-*.DESCRIPTION
-* The T-field of the LTV-record (provided by the MSF in parameter ltvp) specifies the RID wanted. The RID
-* information identified by the T-field is copied into the V-field.
-* On entry, the L-field specifies the size of the buffer, also called the "Initial DataLength". The L-value
-* includes the size of the T-field, but not the size of the L-field itself.
-* On return, the L-field indicates the number of words actually contained by the Type and Value fields.
-* As the size of the Type field in the LTV-record is included in the "Initial DataLength" of the record, the
-* V-field can contain at most "Initial DataLength" - 1 words of data.
-* Copying stops if either the complete Information is copied or if the number of words indicated by the
-* "Initial DataLength" were copied. The "Initial DataLength" acts as a safe guard against Configuration
-* Information blocks that have different sizes for different F/W versions, e.g. when later versions support
-* more tallies than earlier versions.
-* If the size of Value field of the RID exceeds the size of the "Initial DataLength" -1, as much data
-* as fits is copied, and an error status of HCF_ERR_LEN is returned.
-*
-* It is the responsibility of the MSF to detect card removal and re-insertion and not call the HCF when the
-* NIC is absent. The MSF cannot, however, timely detect a Card removal if the Card is removed while
-* hcf_get_info is in progress. Therefore, the HCF performs its own check on Card presence after the read
-* operation of the NIC data. If the Card is not present or removed during the execution of hcf_get_info,
-* HCF_ERR_NO_NIC is returned and the content of the Data Buffer is unpredictable. This check is not performed
-* in case of the "HCF embedded" pseudo RIDs like CFG_TALLIES.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value.
-* - reentrancy, may be caused by calling hcf_functions without adequate protection
-* against NIC interrupts or multi-threading.
-* - ltvp is a NULL pointer.
-* - length field of the LTV-record at entry is 0 or 1 or has an excessive value (i.e. exceeds HCF_MAX_LTV).
-* - type field of the LTV-record is invalid.
-*
-*.DIAGRAM
-* Hcf_get_mb_info copies the contents of the oldest MailBox Info block in the MailBox to PC RAM. If len is
-* less than the size of the MailBox Info block, only as much as fits in the PC RAM buffer is copied. After
-* the copying the MailBox Read pointer is updated to point to the next MailBox Info block, hence the
-* remainder of an "oversized" MailBox Info block is lost. The truncation of the MailBox Info block is NOT
-* reflected in the return status. Note that hcf_get_info guarantees the length of the PC RAM buffer meets
-* the minimum requirements of at least 2, so no PC RAM buffer overrun.
-*
-* Calling hcf_get_mb_info when their is no MailBox Info block available or when there is no MailBox at all,
-* results in a "NULL" MailBox Info block.
-*
-*12: see NOTICE
-*17: The return status of cmd_wait and the first hcfio_in_string can be ignored, because when one fails, the
-* other fails via the IFB_DefunctStat mechanism
-*20: "HCFASSERT( rc == HCF_SUCCESS, rc )" is not suitable because this will always trigger as side effect of
-* the HCFASSERT in hcf_put_info which calls hcf_get_info to figure out whether the RID exists at all.
+ *
+ *.MODULE int hcf_get_info( IFBP ifbp, LTVP ltvp )
+ *.PURPOSE Obtains transient and persistent configuration information from the Card and from the HCF.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * ltvp address of LengthTypeValue structure specifying the "what" and the "how much" of the
+ * information to be collected from the HCF or from the Hermes
+ *
+ *.RETURNS
+ * HCF_ERR_LEN The provided buffer was too small
+ * HCF_SUCCESS Success
+ *!! via cmd_exe ( type >= CFG_RID_FW_MIN )
+ * HCF_ERR_NO_NIC NIC removed during retrieval
+ * HCF_ERR_TIME_OUT Expected Hermes event did not occur in expected time
+ *!! via cmd_exe and setup_bap (type >= CFG_RID_FW_MIN )
+ * HCF_ERR_DEFUNCT_... HCF is in defunct mode (bits 0x7F reflect cause)
+ *
+ *.DESCRIPTION
+ * The T-field of the LTV-record (provided by the MSF in parameter ltvp) specifies the RID wanted. The RID
+ * information identified by the T-field is copied into the V-field.
+ * On entry, the L-field specifies the size of the buffer, also called the "Initial DataLength". The L-value
+ * includes the size of the T-field, but not the size of the L-field itself.
+ * On return, the L-field indicates the number of words actually contained by the Type and Value fields.
+ * As the size of the Type field in the LTV-record is included in the "Initial DataLength" of the record, the
+ * V-field can contain at most "Initial DataLength" - 1 words of data.
+ * Copying stops if either the complete Information is copied or if the number of words indicated by the
+ * "Initial DataLength" were copied. The "Initial DataLength" acts as a safe guard against Configuration
+ * Information blocks that have different sizes for different F/W versions, e.g. when later versions support
+ * more tallies than earlier versions.
+ * If the size of Value field of the RID exceeds the size of the "Initial DataLength" -1, as much data
+ * as fits is copied, and an error status of HCF_ERR_LEN is returned.
+ *
+ * It is the responsibility of the MSF to detect card removal and re-insertion and not call the HCF when the
+ * NIC is absent. The MSF cannot, however, timely detect a Card removal if the Card is removed while
+ * hcf_get_info is in progress. Therefore, the HCF performs its own check on Card presence after the read
+ * operation of the NIC data. If the Card is not present or removed during the execution of hcf_get_info,
+ * HCF_ERR_NO_NIC is returned and the content of the Data Buffer is unpredictable. This check is not performed
+ * in case of the "HCF embedded" pseudo RIDs like CFG_TALLIES.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value.
+ * - reentrancy, may be caused by calling hcf_functions without adequate protection
+ * against NIC interrupts or multi-threading.
+ * - ltvp is a NULL pointer.
+ * - length field of the LTV-record at entry is 0 or 1 or has an excessive value (i.e. exceeds HCF_MAX_LTV).
+ * - type field of the LTV-record is invalid.
+ *
+ *.DIAGRAM
+ * Hcf_get_mb_info copies the contents of the oldest MailBox Info block in the MailBox to PC RAM. If len is
+ * less than the size of the MailBox Info block, only as much as fits in the PC RAM buffer is copied. After
+ * the copying the MailBox Read pointer is updated to point to the next MailBox Info block, hence the
+ * remainder of an "oversized" MailBox Info block is lost. The truncation of the MailBox Info block is NOT
+ * reflected in the return status. Note that hcf_get_info guarantees the length of the PC RAM buffer meets
+ * the minimum requirements of at least 2, so no PC RAM buffer overrun.
+ *
+ * Calling hcf_get_mb_info when their is no MailBox Info block available or when there is no MailBox at all,
+ * results in a "NULL" MailBox Info block.
+ *
+ *12: see NOTICE
+ *17: The return status of cmd_wait and the first hcfio_in_string can be ignored, because when one fails, the
+ * other fails via the IFB_DefunctStat mechanism
+ *20: "HCFASSERT( rc == HCF_SUCCESS, rc )" is not suitable because this will always trigger as side effect of
+ * the HCFASSERT in hcf_put_info which calls hcf_get_info to figure out whether the RID exists at all.
-*.NOTICE
-*
-* "HCF embedded" pseudo RIDs:
-* CFG_MB_INFO, CFG_TALLIES, CFG_DRV_IDENTITY, CFG_DRV_SUP_RANGE, CFG_DRV_ACT_RANGES_PRI,
-* CFG_DRV_ACT_RANGES_STA, CFG_DRV_ACT_RANGES_HSI
-* Note the HCF_ERR_LEN is NOT adequately set, when L >= 2 but less than needed
-*
-* Remarks: Transfers operation information and transient and persistent configuration information from the
-* Card and from the HCF to the MSF.
-* The exact layout of the provided data structure depends on the action code. Copying stops if either the
-* complete Configuration Information is copied or if the number of bytes indicated by len is copied. Len
-* acts as a safe guard against Configuration Information blocks which have different sizes for different
-* Hermes versions, e.g. when later versions support more tallies than earlier versions. It is a conscious
-* decision that unused parts of the PC RAM buffer are not cleared.
-*
-* Remarks: The only error against which is protected is the "Read error" as result of Card removal. Only the
-* last hcf_io_string need to be protected because if the first fails the second will fail as well. Checking
-* for cmd_exe errors is supposed superfluous because problems in cmd_exe are already caught or will be
-* caught by hcf_enable.
-*
-* CFG_MB_INFO: copy the oldest MailBox Info Block or the "null" block if none available.
-*
-* The mechanism to HCF_ASSERT on invalid typ-codes in the LTV record is based on the following strategy:
-* - during the pseudo-asynchronous Hermes commands (diagnose, download) only CFG_MB_INFO is acceptable
-* - some codes (e.g. CFG_TALLIES) are explicitly handled by the HCF which implies that these codes
-* are valid
-* - all other codes in the range 0xFC00 through 0xFFFF are passed to the Hermes. The Hermes returns an
-* LTV record with a zero value in the L-field for all Typ-codes it does not recognize. This is
-* defined and intended behavior, so HCF_ASSERT does not catch on this phenomena.
-* - all remaining codes are invalid and cause an ASSERT.
-*
-*.CONDITIONS
-* In case of USB, HCF_MAX_MSG ;?USED;? to limit the amount of data that can be retrieved via hcf_get_info.
-*
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *.NOTICE
+ *
+ * "HCF embedded" pseudo RIDs:
+ * CFG_MB_INFO, CFG_TALLIES, CFG_DRV_IDENTITY, CFG_DRV_SUP_RANGE, CFG_DRV_ACT_RANGES_PRI,
+ * CFG_DRV_ACT_RANGES_STA, CFG_DRV_ACT_RANGES_HSI
+ * Note the HCF_ERR_LEN is NOT adequately set, when L >= 2 but less than needed
+ *
+ * Remarks: Transfers operation information and transient and persistent configuration information from the
+ * Card and from the HCF to the MSF.
+ * The exact layout of the provided data structure depends on the action code. Copying stops if either the
+ * complete Configuration Information is copied or if the number of bytes indicated by len is copied. Len
+ * acts as a safe guard against Configuration Information blocks which have different sizes for different
+ * Hermes versions, e.g. when later versions support more tallies than earlier versions. It is a conscious
+ * decision that unused parts of the PC RAM buffer are not cleared.
+ *
+ * Remarks: The only error against which is protected is the "Read error" as result of Card removal. Only the
+ * last hcf_io_string need to be protected because if the first fails the second will fail as well. Checking
+ * for cmd_exe errors is supposed superfluous because problems in cmd_exe are already caught or will be
+ * caught by hcf_enable.
+ *
+ * CFG_MB_INFO: copy the oldest MailBox Info Block or the "null" block if none available.
+ *
+ * The mechanism to HCF_ASSERT on invalid typ-codes in the LTV record is based on the following strategy:
+ * - during the pseudo-asynchronous Hermes commands (diagnose, download) only CFG_MB_INFO is acceptable
+ * - some codes (e.g. CFG_TALLIES) are explicitly handled by the HCF which implies that these codes
+ * are valid
+ * - all other codes in the range 0xFC00 through 0xFFFF are passed to the Hermes. The Hermes returns an
+ * LTV record with a zero value in the L-field for all Typ-codes it does not recognize. This is
+ * defined and intended behavior, so HCF_ASSERT does not catch on this phenomena.
+ * - all remaining codes are invalid and cause an ASSERT.
+ *
+ *.CONDITIONS
+ * In case of USB, HCF_MAX_MSG ;?USED;? to limit the amount of data that can be retrieved via hcf_get_info.
+ *
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
hcf_get_info( IFBP ifbp, LTVP ltvp )
{
-int rc = HCF_SUCCESS;
-hcf_16 len = ltvp->len;
-hcf_16 type = ltvp->typ;
-wci_recordp p = &ltvp->len; //destination word pointer (in LTV record)
-hcf_16 *q = NULL; /* source word pointer Note!! DOS COM can't cope with FAR
- * as a consequence MailBox must be near which is usually true anyway
- */
-int i;
-
- HCFLOGENTRY( HCF_TRACE_GET_INFO, ltvp->typ )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
- HCFASSERT( ltvp, 0 )
- HCFASSERT( 1 < ltvp->len && ltvp->len <= HCF_MAX_LTV + 1, MERGE_2( ltvp->typ, ltvp->len ) )
-
- ltvp->len = 0; //default to: No Info Available
-#if defined MSF_COMPONENT_ID || (HCF_EXT) & HCF_EXT_MB //filter out all specials
+ int rc = HCF_SUCCESS;
+ hcf_16 len = ltvp->len;
+ hcf_16 type = ltvp->typ;
+ wci_recordp p = &ltvp->len; //destination word pointer (in LTV record)
+ hcf_16 *q = NULL; /* source word pointer Note!! DOS COM can't cope with FAR
+ * as a consequence MailBox must be near which is usually true anyway
+ */
+ int i;
+
+ HCFLOGENTRY( HCF_TRACE_GET_INFO, ltvp->typ );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
+ HCFASSERT( ltvp, 0 );
+ HCFASSERT( 1 < ltvp->len && ltvp->len <= HCF_MAX_LTV + 1, MERGE_2( ltvp->typ, ltvp->len ) );
+
+ ltvp->len = 0; //default to: No Info Available
+ //filter out all specials
for ( i = 0; ( q = xxxx[i] ) != NULL && q[1] != type; i++ ) /*NOP*/;
-#endif // MSF_COMPONENT_ID / HCF_EXT_MB
+
#if HCF_TALLIES
- if ( type == CFG_TALLIES ) { /*3*/
+ if ( type == CFG_TALLIES ) { /*3*/
(void)hcf_action( ifbp, HCF_ACT_TALLIES );
q = (hcf_16*)&ifbp->IFB_TallyLen;
}
#endif // HCF_TALLIES
-#if (HCF_EXT) & HCF_EXT_MB
+
if ( type == CFG_MB_INFO ) {
if ( ifbp->IFB_MBInfoLen ) {
if ( ifbp->IFB_MBp[ifbp->IFB_MBRp] == 0xFFFF ) {
ifbp->IFB_MBRp = 0; //;?Probably superfluous
}
q = &ifbp->IFB_MBp[ifbp->IFB_MBRp];
- ifbp->IFB_MBRp += *q + 1; //update read pointer
+ ifbp->IFB_MBRp += *q + 1; //update read pointer
if ( ifbp->IFB_MBp[ifbp->IFB_MBRp] == 0xFFFF ) {
ifbp->IFB_MBRp = 0;
}
ifbp->IFB_MBInfoLen = ifbp->IFB_MBp[ifbp->IFB_MBRp];
}
}
-#endif // HCF_EXT_MB
- if ( q != NULL ) { //a special or CFG_TALLIES or CFG_MB_INFO
- i = min( len, *q ) + 1; //total size of destination (including T-field)
+
+ if ( q != NULL ) { //a special or CFG_TALLIES or CFG_MB_INFO
+ i = min( len, *q ) + 1; //total size of destination (including T-field)
while ( i-- ) {
*p++ = *q;
#if (HCF_TALLIES) & HCF_TALLIES_RESET
@@ -2077,50 +2001,50 @@ int i;
#endif // HCF_TALLIES_RESET
q++;
}
- } else { // not a special nor CFG_TALLIES nor CFG_MB_INFO
- if ( type == CFG_CNTL_OPT ) { //read back effective options
+ } else { // not a special nor CFG_TALLIES nor CFG_MB_INFO
+ if ( type == CFG_CNTL_OPT ) { //read back effective options
ltvp->len = 2;
ltvp->val[0] = ifbp->IFB_CntlOpt;
#if (HCF_EXT) & HCF_EXT_NIC_ACCESS
} else if ( type == CFG_PROD_DATA ) { //only needed for some test tool on top of H-II NDIS driver
-hcf_io io_port;
-wci_bufp pt; //pointer with the "right" type, just to help ease writing macros with embedded assembly
+ hcf_io io_port;
+ wci_bufp pt; //pointer with the "right" type, just to help ease writing macros with embedded assembly
OPW( HREG_AUX_PAGE, (hcf_16)(PLUG_DATA_OFFSET >> 7) );
OPW( HREG_AUX_OFFSET, (hcf_16)(PLUG_DATA_OFFSET & 0x7E) );
- io_port = ifbp->IFB_IOBase + HREG_AUX_DATA; //to prevent side effects of the MSF-defined macro
- p = ltvp->val; //destination char pointer (in LTV record)
+ io_port = ifbp->IFB_IOBase + HREG_AUX_DATA; //to prevent side effects of the MSF-defined macro
+ p = ltvp->val; //destination char pointer (in LTV record)
i = len - 1;
if (i > 0 ) {
- pt = (wci_bufp)p; //just to help ease writing macros with embedded assembly
+ pt = (wci_bufp)p; //just to help ease writing macros with embedded assembly
IN_PORT_STRING_8_16( io_port, pt, i ); //space used by T: -1
}
} else if ( type == CFG_CMD_HCF ) {
#define P ((CFG_CMD_HCF_STRCT FAR *)ltvp)
- HCFASSERT( P->cmd == CFG_CMD_HCF_REG_ACCESS, P->cmd ) //only Hermes register access supported
+ HCFASSERT( P->cmd == CFG_CMD_HCF_REG_ACCESS, P->cmd ); //only Hermes register access supported
if ( P->cmd == CFG_CMD_HCF_REG_ACCESS ) {
- HCFASSERT( P->mode < ifbp->IFB_IOBase, P->mode ) //Check Register space
- ltvp->len = min( len, 4 ); //RESTORE ltv length
+ HCFASSERT( P->mode < ifbp->IFB_IOBase, P->mode ); //Check Register space
+ ltvp->len = min( len, 4 ); //RESTORE ltv length
P->add_info = IPW( P->mode );
}
#undef P
#endif // HCF_EXT_NIC_ACCESS
#if (HCF_ASSERT) & HCF_ASSERT_PRINTF
- } else if (type == CFG_FW_PRINTF) {
- rc = fw_printf(ifbp, (CFG_FW_PRINTF_STRCT*)ltvp);
+ } else if (type == CFG_FW_PRINTF) {
+ rc = fw_printf(ifbp, (CFG_FW_PRINTF_STRCT*)ltvp);
#endif // HCF_ASSERT_PRINTF
} else if ( type >= CFG_RID_FW_MIN ) {
//;? by using HCMD_BUSY option when calling cmd_exe, using a get_frag with length 0 just to set up the
//;? BAP and calling cmd_cmpl, you could merge the 2 Busy waits. Whether this really helps (and what
//;? would be the optimal sequence in cmd_exe and get_frag) would have to be MEASURED
-/*17*/ if ( ( rc = cmd_exe( ifbp, HCMD_ACCESS, type ) ) == HCF_SUCCESS &&
+ /*17*/ if ( ( rc = cmd_exe( ifbp, HCMD_ACCESS, type ) ) == HCF_SUCCESS &&
( rc = setup_bap( ifbp, type, 0, IO_IN ) ) == HCF_SUCCESS ) {
get_frag( ifbp, (wci_bufp)&ltvp->len, 2*len+2 BE_PAR(2) );
- if ( IPW( HREG_STAT ) == 0xFFFF ) { //NIC removal test
+ if ( IPW( HREG_STAT ) == 0xFFFF ) { //NIC removal test
ltvp->len = 0;
- HCFASSERT( DO_ASSERT, type )
+ HCFASSERT( DO_ASSERT, type );
}
}
-/*12*/ } else HCFASSERT( DO_ASSERT, type ) /*NOP*/; //NOP in case HCFASSERT is dummy
+ /*12*/ } else HCFASSERT( DO_ASSERT, type ) /*NOP*/; //NOP in case HCFASSERT is dummy
}
if ( len < ltvp->len ) {
ltvp->len = len;
@@ -2129,721 +2053,676 @@ wci_bufp pt; //pointer with the "right" type, just to help ease writing macr
}
}
HCFASSERT( rc == HCF_SUCCESS || ( rc == HCF_ERR_LEN && ifbp->IFB_AssertTrace & 1<<HCF_TRACE_PUT_INFO ),
- MERGE_2( type, rc ) ) /*20*/
- HCFLOGEXIT( HCF_TRACE_GET_INFO )
+ MERGE_2( type, rc ) ); /*20*/
+ HCFLOGEXIT( HCF_TRACE_GET_INFO );
return rc;
} // hcf_get_info
/************************************************************************************************************
-*
-*.MODULE int hcf_put_info( IFBP ifbp, LTVP ltvp )
-*.PURPOSE Transfers operation and configuration information to the Card and to the HCF.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* ltvp specifies the RID (as defined by Hermes I/F) or pseudo-RID (as defined by WCI)
-*
-*.RETURNS
-* HCF_SUCCESS
-*!! via cmd_exe
-* HCF_ERR_NO_NIC NIC removed during data retrieval
-* HCF_ERR_TIME_OUT Expected F/W event did not occur in time
-* HCF_ERR_DEFUNCT_...
-*!! via download CFG_DLNV_START <= type <= CFG_DL_STOP
-*!! via put_info CFG_RID_CFG_MIN <= type <= CFG_RID_CFG_MAX
-*!! via put_frag
-*
-*.DESCRIPTION
-* The L-field of the LTV-record (provided by the MSF in parameter ltvp) specifies the size of the buffer.
-* The L-value includes the size of the T-field, but not the size of the L-field.
-* The T- field specifies the RID placed in the V-field by the MSF.
-*
-* Not all CFG-codes can be used for hcf_put_info. The following CFG-codes are valid for hcf_put_info:
-* o One of the CFG-codes in the group "Network Parameters, Static Configuration Entities"
-* Changes made by hcf_put_info to CFG_codes in this group will not affect the F/W
-* and HCF behavior until hcf_cntl_port( HCF_PORT_ENABLE) is called.
-* o One of the CFG-codes in the group "Network Parameters, Dynamic Configuration Entities"
-* Changes made by hcf_put_info to CFG_codes will affect the F/W and HCF behavior immediately.
-* o CFG_PROG.
-* This code is used to initiate and terminate the process to download data either to
-* volatile or to non-volatile RAM on the NIC as well as for the actual download.
-* o CFG-codes related to the HCF behavior.
-* The related CFG-codes are:
-* - CFG_REG_MB
-* - CFG_REG_ASSERT_RTNP
-* - CFG_REG_INFO_LOG
-* - CFG_CMD_NIC
-* - CFG_CMD_DONGLE
-* - CFG_CMD_HCF
-* - CFG_NOTIFY
-*
-* All LTV-records "unknown" to the HCF are forwarded to the F/W.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value.
-* - ltvp is a NULL pointer.
-* - hcf_put_info was called without prior call to hcf_connect
-* - type field of the LTV-record is invalid, i.e. neither HCF nor F/W can handle the value.
-* - length field of the LTV-record at entry is less than 1 or exceeds MAX_LTV_SIZE.
-* - registering a MailBox with size less than 60 or a non-aligned buffer address is used.
-* - reentrancy, may be caused by calling hcf_functions without adequate protection against
-* NIC interrupts or multi-threading.
-*
-*.DIAGRAM
-*
-*.NOTICE
-* Remarks: In case of Hermes Configuration LTVs, the codes for the type are "cleverly" chosen to be
-* identical to the RID. Hermes Configuration information is copied from the provided data structure into the
-* Card.
-* In case of HCF Configuration LTVs, the type values are chosen in a range which does not overlap the
-* RID-range.
-*
-*20:
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE int hcf_put_info( IFBP ifbp, LTVP ltvp )
+ *.PURPOSE Transfers operation and configuration information to the Card and to the HCF.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * ltvp specifies the RID (as defined by Hermes I/F) or pseudo-RID (as defined by WCI)
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ *!! via cmd_exe
+ * HCF_ERR_NO_NIC NIC removed during data retrieval
+ * HCF_ERR_TIME_OUT Expected F/W event did not occur in time
+ * HCF_ERR_DEFUNCT_...
+ *!! via download CFG_DLNV_START <= type <= CFG_DL_STOP
+ *!! via put_info CFG_RID_CFG_MIN <= type <= CFG_RID_CFG_MAX
+ *!! via put_frag
+ *
+ *.DESCRIPTION
+ * The L-field of the LTV-record (provided by the MSF in parameter ltvp) specifies the size of the buffer.
+ * The L-value includes the size of the T-field, but not the size of the L-field.
+ * The T- field specifies the RID placed in the V-field by the MSF.
+ *
+ * Not all CFG-codes can be used for hcf_put_info. The following CFG-codes are valid for hcf_put_info:
+ * o One of the CFG-codes in the group "Network Parameters, Static Configuration Entities"
+ * Changes made by hcf_put_info to CFG_codes in this group will not affect the F/W
+ * and HCF behavior until hcf_cntl_port( HCF_PORT_ENABLE) is called.
+ * o One of the CFG-codes in the group "Network Parameters, Dynamic Configuration Entities"
+ * Changes made by hcf_put_info to CFG_codes will affect the F/W and HCF behavior immediately.
+ * o CFG_PROG.
+ * This code is used to initiate and terminate the process to download data either to
+ * volatile or to non-volatile RAM on the NIC as well as for the actual download.
+ * o CFG-codes related to the HCF behavior.
+ * The related CFG-codes are:
+ * - CFG_REG_MB
+ * - CFG_REG_ASSERT_RTNP
+ * - CFG_REG_INFO_LOG
+ * - CFG_CMD_NIC
+ * - CFG_CMD_DONGLE
+ * - CFG_CMD_HCF
+ * - CFG_NOTIFY
+ *
+ * All LTV-records "unknown" to the HCF are forwarded to the F/W.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value.
+ * - ltvp is a NULL pointer.
+ * - hcf_put_info was called without prior call to hcf_connect
+ * - type field of the LTV-record is invalid, i.e. neither HCF nor F/W can handle the value.
+ * - length field of the LTV-record at entry is less than 1 or exceeds MAX_LTV_SIZE.
+ * - registering a MailBox with size less than 60 or a non-aligned buffer address is used.
+ * - reentrancy, may be caused by calling hcf_functions without adequate protection against
+ * NIC interrupts or multi-threading.
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ * Remarks: In case of Hermes Configuration LTVs, the codes for the type are "cleverly" chosen to be
+ * identical to the RID. Hermes Configuration information is copied from the provided data structure into the
+ * Card.
+ * In case of HCF Configuration LTVs, the type values are chosen in a range which does not overlap the
+ * RID-range.
+ *
+ *20:
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
hcf_put_info( IFBP ifbp, LTVP ltvp )
{
-int rc = HCF_SUCCESS;
+ int rc = HCF_SUCCESS;
- HCFLOGENTRY( HCF_TRACE_PUT_INFO, ltvp->typ )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
- HCFASSERT( ltvp, 0 )
- HCFASSERT( 1 < ltvp->len && ltvp->len <= HCF_MAX_LTV + 1, ltvp->len )
+ HCFLOGENTRY( HCF_TRACE_PUT_INFO, ltvp->typ );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
+ HCFASSERT( ltvp, 0 );
+ HCFASSERT( 1 < ltvp->len && ltvp->len <= HCF_MAX_LTV + 1, ltvp->len );
- //all codes between 0xFA00 and 0xFCFF are passed to Hermes
+ //all codes between 0xFA00 and 0xFCFF are passed to Hermes
#if (HCF_TYPE) & HCF_TYPE_WPA
- { hcf_16 i;
- hcf_32 FAR * key_p;
-
- if ( ltvp->typ == CFG_ADD_TKIP_DEFAULT_KEY || ltvp->typ == CFG_ADD_TKIP_MAPPED_KEY ) {
- key_p = (hcf_32*)((CFG_ADD_TKIP_MAPPED_KEY_STRCT FAR *)ltvp)->tx_mic_key;
- i = TX_KEY; //i.e. TxKeyIndicator == 1, KeyID == 0
- if ( ltvp->typ == CFG_ADD_TKIP_DEFAULT_KEY ) {
- key_p = (hcf_32*)((CFG_ADD_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)->tx_mic_key;
- i = CNV_LITTLE_TO_SHORT(((CFG_ADD_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)->tkip_key_id_info);
- }
- if ( i & TX_KEY ) { /* TxKeyIndicator == 1
- (either really set by MSF in case of DEFAULT or faked by HCF in case of MAPPED ) */
- ifbp->IFB_MICTxCntl = (hcf_16)( HFS_TX_CNTL_MIC | (i & KEY_ID )<<8 );
- ifbp->IFB_MICTxKey[0] = CNV_LONGP_TO_LITTLE( key_p );
- ifbp->IFB_MICTxKey[1] = CNV_LONGP_TO_LITTLE( (key_p+1) );
+ {
+ hcf_16 i;
+ hcf_32 FAR * key_p;
+
+ if ( ltvp->typ == CFG_ADD_TKIP_DEFAULT_KEY || ltvp->typ == CFG_ADD_TKIP_MAPPED_KEY ) {
+ key_p = (hcf_32*)((CFG_ADD_TKIP_MAPPED_KEY_STRCT FAR *)ltvp)->tx_mic_key;
+ i = TX_KEY; //i.e. TxKeyIndicator == 1, KeyID == 0
+ if ( ltvp->typ == CFG_ADD_TKIP_DEFAULT_KEY ) {
+ key_p = (hcf_32*)((CFG_ADD_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)->tx_mic_key;
+ i = CNV_LITTLE_TO_SHORT(((CFG_ADD_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)->tkip_key_id_info);
+ }
+ if ( i & TX_KEY ) { /* TxKeyIndicator == 1
+ (either really set by MSF in case of DEFAULT or faked by HCF in case of MAPPED ) */
+ ifbp->IFB_MICTxCntl = (hcf_16)( HFS_TX_CNTL_MIC | (i & KEY_ID )<<8 );
+ ifbp->IFB_MICTxKey[0] = CNV_LONGP_TO_LITTLE( key_p );
+ ifbp->IFB_MICTxKey[1] = CNV_LONGP_TO_LITTLE( (key_p+1) );
+ }
+ i = ( i & KEY_ID ) * 2;
+ ifbp->IFB_MICRxKey[i] = CNV_LONGP_TO_LITTLE( (key_p+2) );
+ ifbp->IFB_MICRxKey[i+1] = CNV_LONGP_TO_LITTLE( (key_p+3) );
}
- i = ( i & KEY_ID ) * 2;
- ifbp->IFB_MICRxKey[i] = CNV_LONGP_TO_LITTLE( (key_p+2) );
- ifbp->IFB_MICRxKey[i+1] = CNV_LONGP_TO_LITTLE( (key_p+3) );
- }
#define P ((CFG_REMOVE_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)
- if ( ( ltvp->typ == CFG_REMOVE_TKIP_MAPPED_KEY ) ||
- ( ltvp->typ == CFG_REMOVE_TKIP_DEFAULT_KEY &&
- ( (ifbp->IFB_MICTxCntl >> 8) & KEY_ID ) == CNV_SHORT_TO_LITTLE(P->tkip_key_id )
- )
- ) { ifbp->IFB_MICTxCntl = 0; } //disable MIC-engine
+ if ( ( ltvp->typ == CFG_REMOVE_TKIP_MAPPED_KEY ) ||
+ ( ltvp->typ == CFG_REMOVE_TKIP_DEFAULT_KEY &&
+ ( (ifbp->IFB_MICTxCntl >> 8) & KEY_ID ) == CNV_SHORT_TO_LITTLE(P->tkip_key_id )
+ )
+ ) { ifbp->IFB_MICTxCntl = 0; } //disable MIC-engine
#undef P
- }
+ }
#endif // HCF_TYPE_WPA
if ( ltvp->typ == CFG_PROG ) {
rc = download( ifbp, (CFG_PROG_STRCT FAR *)ltvp );
} else switch (ltvp->typ) {
#if (HCF_ASSERT) & HCF_ASSERT_RT_MSF_RTN
- case CFG_REG_ASSERT_RTNP: //Register MSF Routines
+ case CFG_REG_ASSERT_RTNP: //Register MSF Routines
#define P ((CFG_REG_ASSERT_RTNP_STRCT FAR *)ltvp)
- ifbp->IFB_AssertRtn = P->rtnp;
-// ifbp->IFB_AssertLvl = P->lvl; //TODO not yet supported so default is set in hcf_connect
- HCFASSERT( DO_ASSERT, MERGE_2( HCF_ASSERT, 0xCAF1 ) ) //just to proof that the complete assert machinery is working
+ ifbp->IFB_AssertRtn = P->rtnp;
+// ifbp->IFB_AssertLvl = P->lvl; //TODO not yet supported so default is set in hcf_connect
+ HCFASSERT( DO_ASSERT, MERGE_2( HCF_ASSERT, 0xCAF1 ) ); //just to proof that the complete assert machinery is working
#undef P
- break;
+ break;
#endif // HCF_ASSERT_RT_MSF_RTN
#if (HCF_EXT) & HCF_EXT_INFO_LOG
- case CFG_REG_INFO_LOG: //Register Log filter
- ifbp->IFB_RIDLogp = ((CFG_RID_LOG_STRCT FAR*)ltvp)->recordp;
- break;
+ case CFG_REG_INFO_LOG: //Register Log filter
+ ifbp->IFB_RIDLogp = ((CFG_RID_LOG_STRCT FAR*)ltvp)->recordp;
+ break;
#endif // HCF_EXT_INFO_LOG
- case CFG_CNTL_OPT: //overrule option
- HCFASSERT( ( ltvp->val[0] & ~(USE_DMA | USE_16BIT) ) == 0, ltvp->val[0] )
- if ( ( ltvp->val[0] & USE_DMA ) == 0 ) ifbp->IFB_CntlOpt &= ~USE_DMA;
- ifbp->IFB_CntlOpt |= ltvp->val[0] & USE_16BIT;
- break;
-#if (HCF_EXT) & HCF_EXT_MB
- case CFG_REG_MB: //Register MailBox
+ case CFG_CNTL_OPT: //overrule option
+ HCFASSERT( ( ltvp->val[0] & ~(USE_DMA | USE_16BIT) ) == 0, ltvp->val[0] );
+ if ( ( ltvp->val[0] & USE_DMA ) == 0 ) ifbp->IFB_CntlOpt &= ~USE_DMA;
+ ifbp->IFB_CntlOpt |= ltvp->val[0] & USE_16BIT;
+ break;
+
+ case CFG_REG_MB: //Register MailBox
#define P ((CFG_REG_MB_STRCT FAR *)ltvp)
- HCFASSERT( ( (hcf_32)P->mb_addr & 0x0001 ) == 0, (hcf_32)P->mb_addr )
- HCFASSERT( (P)->mb_size >= 60, (P)->mb_size )
- ifbp->IFB_MBp = P->mb_addr;
- /* if no MB present, size must be 0 for ;?the old;? put_info_mb to work correctly */
- ifbp->IFB_MBSize = ifbp->IFB_MBp == NULL ? 0 : P->mb_size;
- ifbp->IFB_MBWp = ifbp->IFB_MBRp = 0;
- ifbp->IFB_MBp[0] = 0; //flag the MailBox as empty
- ifbp->IFB_MBInfoLen = 0;
- HCFASSERT( ifbp->IFB_MBSize >= 60 || ifbp->IFB_MBp == NULL, ifbp->IFB_MBSize )
+ HCFASSERT( ( (hcf_32)P->mb_addr & 0x0001 ) == 0, (hcf_32)P->mb_addr );
+ HCFASSERT( (P)->mb_size >= 60, (P)->mb_size );
+ ifbp->IFB_MBp = P->mb_addr;
+ /* if no MB present, size must be 0 for ;?the old;? put_info_mb to work correctly */
+ ifbp->IFB_MBSize = ifbp->IFB_MBp == NULL ? 0 : P->mb_size;
+ ifbp->IFB_MBWp = ifbp->IFB_MBRp = 0;
+ ifbp->IFB_MBp[0] = 0; //flag the MailBox as empty
+ ifbp->IFB_MBInfoLen = 0;
+ HCFASSERT( ifbp->IFB_MBSize >= 60 || ifbp->IFB_MBp == NULL, ifbp->IFB_MBSize );
#undef P
- break;
- case CFG_MB_INFO: //store MailBoxInfoBlock
- rc = put_info_mb( ifbp, (CFG_MB_INFO_STRCT FAR *)ltvp );
- break;
-#endif // HCF_EXT_MB
+ break;
+ case CFG_MB_INFO: //store MailBoxInfoBlock
+ rc = put_info_mb( ifbp, (CFG_MB_INFO_STRCT FAR *)ltvp );
+ break;
#if (HCF_EXT) & HCF_EXT_NIC_ACCESS
- case CFG_CMD_NIC:
+ case CFG_CMD_NIC:
#define P ((CFG_CMD_NIC_STRCT FAR *)ltvp)
- OPW( HREG_PARAM_2, P->parm2 );
- OPW( HREG_PARAM_1, P->parm1 );
- rc = cmd_exe( ifbp, P->cmd, P->parm0 );
- P->hcf_stat = (hcf_16)rc;
- P->stat = IPW( HREG_STAT );
- P->resp0 = IPW( HREG_RESP_0 );
- P->resp1 = IPW( HREG_RESP_1 );
- P->resp2 = IPW( HREG_RESP_2 );
- P->ifb_err_cmd = ifbp->IFB_ErrCmd;
- P->ifb_err_qualifier = ifbp->IFB_ErrQualifier;
+ OPW( HREG_PARAM_2, P->parm2 );
+ OPW( HREG_PARAM_1, P->parm1 );
+ rc = cmd_exe( ifbp, P->cmd, P->parm0 );
+ P->hcf_stat = (hcf_16)rc;
+ P->stat = IPW( HREG_STAT );
+ P->resp0 = IPW( HREG_RESP_0 );
+ P->resp1 = IPW( HREG_RESP_1 );
+ P->resp2 = IPW( HREG_RESP_2 );
+ P->ifb_err_cmd = ifbp->IFB_ErrCmd;
+ P->ifb_err_qualifier = ifbp->IFB_ErrQualifier;
#undef P
- break;
- case CFG_CMD_HCF:
+ break;
+ case CFG_CMD_HCF:
#define P ((CFG_CMD_HCF_STRCT FAR *)ltvp)
- HCFASSERT( P->cmd == CFG_CMD_HCF_REG_ACCESS, P->cmd ) //only Hermes register access supported
- if ( P->cmd == CFG_CMD_HCF_REG_ACCESS ) {
- HCFASSERT( P->mode < ifbp->IFB_IOBase, P->mode ) //Check Register space
- OPW( P->mode, P->add_info);
- }
+ HCFASSERT( P->cmd == CFG_CMD_HCF_REG_ACCESS, P->cmd ); //only Hermes register access supported
+ if ( P->cmd == CFG_CMD_HCF_REG_ACCESS ) {
+ HCFASSERT( P->mode < ifbp->IFB_IOBase, P->mode ); //Check Register space
+ OPW( P->mode, P->add_info);
+ }
#undef P
- break;
+ break;
#endif // HCF_EXT_NIC_ACCESS
#if (HCF_ASSERT) & HCF_ASSERT_PRINTF
- case CFG_FW_PRINTF_BUFFER_LOCATION:
- ifbp->IFB_FwPfBuff = *(CFG_FW_PRINTF_BUFFER_LOCATION_STRCT*)ltvp;
- break;
+ case CFG_FW_PRINTF_BUFFER_LOCATION:
+ ifbp->IFB_FwPfBuff = *(CFG_FW_PRINTF_BUFFER_LOCATION_STRCT*)ltvp;
+ break;
#endif // HCF_ASSERT_PRINTF
- default: //pass everything unknown above the "FID" range to the Hermes or Dongle
- rc = put_info( ifbp, ltvp );
- }
- //DO NOT !!! HCFASSERT( rc == HCF_SUCCESS, rc ) /* 20 */
- HCFLOGEXIT( HCF_TRACE_PUT_INFO )
+ default: //pass everything unknown above the "FID" range to the Hermes or Dongle
+ rc = put_info( ifbp, ltvp );
+ }
+ //DO NOT !!! HCFASSERT( rc == HCF_SUCCESS, rc ) /* 20 */
+ HCFLOGEXIT( HCF_TRACE_PUT_INFO );
return rc;
} // hcf_put_info
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.MODULE int hcf_rcv_msg( IFBP ifbp, DESC_STRCT *descp, unsigned int offset )
-*.PURPOSE All: decapsulate a message.
-* pre-HermesII.5: verify MIC.
-* non-USB, non-DMA mode: Transfer a message from the NIC to the Host and acknowledge reception.
-* USB: Transform a message from proprietary USB format to 802.3 format
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* descp Pointer to the Descriptor List location.
-* offset USB: not used
-* non-USB: specifies the beginning of the data to be obtained (0 corresponds with DestAddr field
-* of frame).
-*
-*.RETURNS
-* HCF_SUCCESS No SSN error ( or HCF_ERR_MIC already reported by hcf_service_nic)
-* HCF_ERR_MIC message contains an erroneous MIC ( HCF_SUCCESS is reported if HCF_ERR_MIC is already
-* reported by hcf_service_nic)
-* HCF_ERR_NO_NIC NIC removed during data retrieval
-* HCF_ERR_DEFUNCT...
-*
-*.DESCRIPTION
-* The Receive Message Function can be executed by the MSF to obtain the Data Info fields of the message that
-* is reported to be available by the Service NIC Function.
-*
-* The Receive Message Function copies the message data available in the Card memory into a buffer structure
-* provided by the MSF.
-* Only data of the message indicated by the Service NIC Function can be obtained.
-* Execution of the Service NIC function may result in the availability of a new message, but it definitely
-* makes the message reported by the preceding Service NIC function, unavailable.
-*
-* in non-USB/non-DMA mode, hcf_rcv_msg starts the copy process at the (non-negative) offset requested by the
-* parameter offset, relative to HFS_ADDR_DEST, e.g offset 0 starts copying from the Destination Address, the
-* very begin of the 802.3 frame message. Offset must either lay within the part of the 802.3 frame as stored
-* by hcf_service_nic in the lookahead buffer or be just behind it, i.e. the first byte not yet read.
-* When offset is within lookahead, data is copied from lookahead.
-* When offset is beyond lookahead, data is read directly from RxFS in NIC with disregard of the actual value
-* of offset
-*
-*.NOTICE:
-* o at entry: look ahead buffer as passed with hcf_service_nic is still accessible and unchanged
-* o at exit: Receive Frame in NIC memory is released
-*
-* Description:
-* Starting at the byte indicated by the Offset value, the bytes are copied from the Data Info
-* Part of the current Receive Frame Structure to the Host memory data buffer structure
-* identified by descp.
-* The maximum value for Offset is the number of characters of the 802.3 frame read into the
-* look ahead buffer by hcf_service_nic (i.e. the look ahead buffer size minus
-* Control and 802.11 fields)
-* If Offset is less than the maximum value, copying starts from the look ahead buffer till the
-* end of that buffer is reached
-* Then (or if the maximum value is specified for Offset), the
-* message is directly copied from NIC memory to Host memory.
-* If an invalid (i.e. too large) offset is specified, an assert catches but the buffer contents are
-* undefined.
-* Copying stops if either:
-* o the end of the 802.3 frame is reached
-* o the Descriptor with a NULL pointer in the next_desc_addr field is reached
-*
-* When the copying stops, the receiver is ack'ed, thus freeing the NIC memory where the frame is stored
-* As a consequence, hcf_rcv_msg can only be called once for any particular Rx frame.
-*
-* For the time being (PCI Bus mastering not yet supported), only the following fields of each
-* of the descriptors in the descriptor list must be set by the MSF:
-* o buf_cntl.buf_dim[1]
-* o *next_desc_addr
-* o *buf_addr
-* At return from hcf_rcv_msg, the field buf_cntl.buf_dim[0] of the used Descriptors reflects
-* the number of bytes in the buffer corresponding with the Descriptor.
-* On the last used Descriptor, buf_cntl.buf_dim[0] is less or equal to buf_cntl.buf_dim[1].
-* On all preceding Descriptors buf_cntl.buf_dim[0] is equal to buf_cntl.buf_dim[1].
-* On all succeeding (unused) Descriptors, buf_cntl.buf_dim[0] is zero.
-* Note: this I/F is based on the assumptions how the I/F needed for PCI Bus mastering will
-* be, so it may change.
-*
-* The most likely handling of HCF_ERR_NO_NIC by the MSF is to drop the already copied
-* data as elegantly as possible under the constraints and requirements posed by the (N)OS.
-* If no received Frame Structure is pending, "Success" rather than "Read error" is returned.
-* This error constitutes a logic flaw in the MSF
-* The HCF can only catch a minority of this
-* type of errors
-* Based on consistency ideas, the HCF catches none of these errors.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value
-* - there is no unacknowledged Rx-message available
-* - offset is out of range (outside look ahead buffer)
-* - descp is a NULL pointer
-* - any of the descriptors is not double word aligned
-* - reentrancy, may be caused by calling hcf_functions without adequate protection
-* against NIC interrupts or multi-threading.
-* - Interrupts are enabled.
-*
-*.DIAGRAM
-*
-*.NOTICE
-* - by using unsigned int as type for offset, no need to worry about negative offsets
-* - Asserting on being enabled/present is superfluous, since a non-zero IFB_lal implies that hcf_service_nic
-* was called and detected a Rx-message. A zero IFB_lal will set the BUF_CNT field of at least the first
-* descriptor to zero.
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE int hcf_rcv_msg( IFBP ifbp, DESC_STRCT *descp, unsigned int offset )
+ *.PURPOSE All: decapsulate a message.
+ * pre-HermesII.5: verify MIC.
+ * non-USB, non-DMA mode: Transfer a message from the NIC to the Host and acknowledge reception.
+ * USB: Transform a message from proprietary USB format to 802.3 format
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * descp Pointer to the Descriptor List location.
+ * offset USB: not used
+ * non-USB: specifies the beginning of the data to be obtained (0 corresponds with DestAddr field
+ * of frame).
+ *
+ *.RETURNS
+ * HCF_SUCCESS No WPA error ( or HCF_ERR_MIC already reported by hcf_service_nic)
+ * HCF_ERR_MIC message contains an erroneous MIC ( HCF_SUCCESS is reported if HCF_ERR_MIC is already
+ * reported by hcf_service_nic)
+ * HCF_ERR_NO_NIC NIC removed during data retrieval
+ * HCF_ERR_DEFUNCT...
+ *
+ *.DESCRIPTION
+ * The Receive Message Function can be executed by the MSF to obtain the Data Info fields of the message that
+ * is reported to be available by the Service NIC Function.
+ *
+ * The Receive Message Function copies the message data available in the Card memory into a buffer structure
+ * provided by the MSF.
+ * Only data of the message indicated by the Service NIC Function can be obtained.
+ * Execution of the Service NIC function may result in the availability of a new message, but it definitely
+ * makes the message reported by the preceding Service NIC function, unavailable.
+ *
+ * in non-USB/non-DMA mode, hcf_rcv_msg starts the copy process at the (non-negative) offset requested by the
+ * parameter offset, relative to HFS_ADDR_DEST, e.g offset 0 starts copying from the Destination Address, the
+ * very begin of the 802.3 frame message. Offset must either lay within the part of the 802.3 frame as stored
+ * by hcf_service_nic in the lookahead buffer or be just behind it, i.e. the first byte not yet read.
+ * When offset is within lookahead, data is copied from lookahead.
+ * When offset is beyond lookahead, data is read directly from RxFS in NIC with disregard of the actual value
+ * of offset
+ *
+ *.NOTICE:
+ * o at entry: look ahead buffer as passed with hcf_service_nic is still accessible and unchanged
+ * o at exit: Receive Frame in NIC memory is released
+ *
+ * Description:
+ * Starting at the byte indicated by the Offset value, the bytes are copied from the Data Info
+ * Part of the current Receive Frame Structure to the Host memory data buffer structure
+ * identified by descp.
+ * The maximum value for Offset is the number of characters of the 802.3 frame read into the
+ * look ahead buffer by hcf_service_nic (i.e. the look ahead buffer size minus
+ * Control and 802.11 fields)
+ * If Offset is less than the maximum value, copying starts from the look ahead buffer till the
+ * end of that buffer is reached
+ * Then (or if the maximum value is specified for Offset), the
+ * message is directly copied from NIC memory to Host memory.
+ * If an invalid (i.e. too large) offset is specified, an assert catches but the buffer contents are
+ * undefined.
+ * Copying stops if either:
+ * o the end of the 802.3 frame is reached
+ * o the Descriptor with a NULL pointer in the next_desc_addr field is reached
+ *
+ * When the copying stops, the receiver is ack'ed, thus freeing the NIC memory where the frame is stored
+ * As a consequence, hcf_rcv_msg can only be called once for any particular Rx frame.
+ *
+ * For the time being (PCI Bus mastering not yet supported), only the following fields of each
+ * of the descriptors in the descriptor list must be set by the MSF:
+ * o buf_cntl.buf_dim[1]
+ * o *next_desc_addr
+ * o *buf_addr
+ * At return from hcf_rcv_msg, the field buf_cntl.buf_dim[0] of the used Descriptors reflects
+ * the number of bytes in the buffer corresponding with the Descriptor.
+ * On the last used Descriptor, buf_cntl.buf_dim[0] is less or equal to buf_cntl.buf_dim[1].
+ * On all preceding Descriptors buf_cntl.buf_dim[0] is equal to buf_cntl.buf_dim[1].
+ * On all succeeding (unused) Descriptors, buf_cntl.buf_dim[0] is zero.
+ * Note: this I/F is based on the assumptions how the I/F needed for PCI Bus mastering will
+ * be, so it may change.
+ *
+ * The most likely handling of HCF_ERR_NO_NIC by the MSF is to drop the already copied
+ * data as elegantly as possible under the constraints and requirements posed by the (N)OS.
+ * If no received Frame Structure is pending, "Success" rather than "Read error" is returned.
+ * This error constitutes a logic flaw in the MSF
+ * The HCF can only catch a minority of this
+ * type of errors
+ * Based on consistency ideas, the HCF catches none of these errors.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value
+ * - there is no unacknowledged Rx-message available
+ * - offset is out of range (outside look ahead buffer)
+ * - descp is a NULL pointer
+ * - any of the descriptors is not double word aligned
+ * - reentrancy, may be caused by calling hcf_functions without adequate protection
+ * against NIC interrupts or multi-threading.
+ * - Interrupts are enabled.
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ * - by using unsigned int as type for offset, no need to worry about negative offsets
+ * - Asserting on being enabled/present is superfluous, since a non-zero IFB_lal implies that hcf_service_nic
+ * was called and detected a Rx-message. A zero IFB_lal will set the BUF_CNT field of at least the first
+ * descriptor to zero.
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
hcf_rcv_msg( IFBP ifbp, DESC_STRCT *descp, unsigned int offset )
{
-int rc = HCF_SUCCESS;
-wci_bufp cp; //char oriented working pointer
-hcf_16 i;
-int tot_len = ifbp->IFB_RxLen - offset; //total length
-wci_bufp lap = ifbp->IFB_lap + offset; //start address in LookAhead Buffer
-hcf_16 lal = ifbp->IFB_lal - offset; //available data within LookAhead Buffer
-hcf_16 j;
-
- HCFLOGENTRY( HCF_TRACE_RCV_MSG, offset )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
- HCFASSERT( descp, HCF_TRACE_RCV_MSG )
- HCFASSERT( ifbp->IFB_RxLen, HCF_TRACE_RCV_MSG )
- HCFASSERT( ifbp->IFB_RxLen >= offset, MERGE_2( offset, ifbp->IFB_RxLen ) )
- HCFASSERT( ifbp->IFB_lal >= offset, offset )
- HCFASSERT( (ifbp->IFB_CntlOpt & USE_DMA) == 0, 0xDADA )
+ int rc = HCF_SUCCESS;
+ wci_bufp cp; //char oriented working pointer
+ hcf_16 i;
+ int tot_len = ifbp->IFB_RxLen - offset; //total length
+ wci_bufp lap = ifbp->IFB_lap + offset; //start address in LookAhead Buffer
+ hcf_16 lal = ifbp->IFB_lal - offset; //available data within LookAhead Buffer
+ hcf_16 j;
+
+ HCFLOGENTRY( HCF_TRACE_RCV_MSG, offset );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
+ HCFASSERT( descp, HCF_TRACE_RCV_MSG );
+ HCFASSERT( ifbp->IFB_RxLen, HCF_TRACE_RCV_MSG );
+ HCFASSERT( ifbp->IFB_RxLen >= offset, MERGE_2( offset, ifbp->IFB_RxLen ) );
+ HCFASSERT( ifbp->IFB_lal >= offset, offset );
+ HCFASSERT( (ifbp->IFB_CntlOpt & USE_DMA) == 0, 0xDADA );
if ( tot_len < 0 ) {
- lal = 0; tot_len = 0; //suppress all copying activity in the do--while loop
+ lal = 0; tot_len = 0; //suppress all copying activity in the do--while loop
}
- do { //loop over all available fragments
+ do { //loop over all available fragments
// obnoxious hcf.c(1480) : warning C4769: conversion of near pointer to long integer
- HCFASSERT( ((hcf_32)descp & 3 ) == 0, (hcf_32)descp )
+ HCFASSERT( ((hcf_32)descp & 3 ) == 0, (hcf_32)descp );
cp = descp->buf_addr;
- j = min( (hcf_16)tot_len, descp->BUF_SIZE ); //minimum of "what's` available" and fragment size
+ j = min( (hcf_16)tot_len, descp->BUF_SIZE ); //minimum of "what's` available" and fragment size
descp->BUF_CNT = j;
- tot_len -= j; //adjust length still to go
- if ( lal ) { //if lookahead Buffer not yet completely copied
- i = min( lal, j ); //minimum of "what's available" in LookAhead and fragment size
- lal -= i; //adjust length still available in LookAhead
- j -= i; //adjust length still available in current fragment
+ tot_len -= j; //adjust length still to go
+ if ( lal ) { //if lookahead Buffer not yet completely copied
+ i = min( lal, j ); //minimum of "what's available" in LookAhead and fragment size
+ lal -= i; //adjust length still available in LookAhead
+ j -= i; //adjust length still available in current fragment
/*;? while loop could be improved by moving words but that is complicated on platforms with
* alignment requirements*/
while ( i-- ) *cp++ = *lap++;
}
- if ( j ) { //if LookAhead Buffer exhausted but still space in fragment, copy directly from NIC RAM
+ if ( j ) { //if LookAhead Buffer exhausted but still space in fragment, copy directly from NIC RAM
get_frag( ifbp, cp, j BE_PAR(0) );
CALC_RX_MIC( cp, j );
}
} while ( ( descp = descp->next_desc_addr ) != NULL );
#if (HCF_TYPE) & HCF_TYPE_WPA
if ( ifbp->IFB_RxFID ) {
- rc = check_mic( ifbp ); //prevents MIC error report if hcf_service_nic already consumed all
+ rc = check_mic( ifbp ); //prevents MIC error report if hcf_service_nic already consumed all
}
#endif // HCF_TYPE_WPA
- (void)hcf_action( ifbp, HCF_ACT_RX_ACK ); //only 1 shot to get the data, so free the resources in the NIC
- HCFASSERT( rc == HCF_SUCCESS, rc )
- HCFLOGEXIT( HCF_TRACE_RCV_MSG )
+ (void)hcf_action( ifbp, HCF_ACT_RX_ACK ); //only 1 shot to get the data, so free the resources in the NIC
+ HCFASSERT( rc == HCF_SUCCESS, rc );
+ HCFLOGEXIT( HCF_TRACE_RCV_MSG );
return rc;
} // hcf_rcv_msg
-#endif // HCF_DL_ONLY
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.MODULE int hcf_send_msg( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl )
-*.PURPOSE Encapsulate a message and append padding and MIC.
-* non-USB: Transfers the resulting message from Host to NIC and initiates transmission.
-* USB: Transfer resulting message into a flat buffer.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* descp pointer to the DescriptorList or NULL
-* tx_cntl indicates MAC-port and (Hermes) options
-* HFS_TX_CNTL_SPECTRALINK
-* HFS_TX_CNTL_PRIO
-* HFS_TX_CNTL_TX_OK
-* HFS_TX_CNTL_TX_EX
-* HFS_TX_CNTL_TX_DELAY
-* HFS_TX_CNTL_TX_CONT
-* HCF_PORT_0 MAC Port 0 (default)
-* HCF_PORT_1 (AP only) MAC Port 1
-* HCF_PORT_2 (AP only) MAC Port 2
-* HCF_PORT_3 (AP only) MAC Port 3
-* HCF_PORT_4 (AP only) MAC Port 4
-* HCF_PORT_5 (AP only) MAC Port 5
-* HCF_PORT_6 (AP only) MAC Port 6
-*
-*.RETURNS
-* HCF_SUCCESS
-* HCF_ERR_DEFUNCT_..
-* HCF_ERR_TIME_OUT
-*
-*.DESCRIPTION:
-* The Send Message Function embodies 2 functions:
-* o transfers a message (including MAC header) from the provided buffer structure in Host memory to the Transmit
-* Frame Structure (TxFS) in NIC memory.
-* o Issue a send command to the F/W to actually transmit the contents of the TxFS.
-*
-* Control is based on the Resource Indicator IFB_RscInd.
-* The Resource Indicator is maintained by the HCF and should only be interpreted but not changed by the MSF.
-* The MSF must check IFB_RscInd to be non-zero before executing the call to the Send Message Function.
-* When no resources are available, the MSF must handle the queuing of the Transmit frame and check the
-* Resource Indicator periodically after calling hcf_service_nic.
-*
-* The Send Message Functions transfers a message to NIC memory when it is called with a non-NULL descp.
-* Before the Send Message Function is invoked this way, the Resource Indicator (IFB_RscInd) must be checked.
-* If the Resource is not available, Send Message Function execution must be postponed until after processing of
-* a next hcf_service_nic it appears that the Resource has become available.
-* The message is copied from the buffer structure identified by descp to the NIC.
-* Copying stops if a NULL pointer in the next_desc_addr field is reached.
-* Hcf_send_msg does not check for transmit buffer overflow, because the F/W does this protection.
-* In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped.
-*
-* The Send Message Function activates the F/W to actually send the message to the medium when the
-* HFS_TX_CNTL_TX_DELAY bit of the tx_cntl parameter is not set.
-* If the descp parameter of the current call is non-NULL, the message as represented by descp is send.
-* If the descp parameter of the current call is NULL, and if the preceding call of the Send Message Function had
-* a non-NULL descp and the preceding call had the HFS_TX_CNTL_TX_DELAY bit of tx_cntl set, then the message as
-* represented by the descp of the preceding call is send.
-*
-* Hcf_send_msg supports encapsulation (see HCF_ENCAP) of Ethernet-II frames.
-* An Ethernet-II frame is transferred to the Transmit Frame structure as an 802.3 frame.
-* Hcf_send_msg distinguishes between an 802.3 and an Ethernet-II frame by looking at the data length/type field
-* of the frame. If this field contains a value larger than 1514, the frame is considered to be an Ethernet-II
-* frame, otherwise it is treated as an 802.3 frame.
-* To ease implementation of the HCF, this type/type field must be located in the first descriptor structure,
-* i.e. the 1st fragment must have a size of at least 14 (to contain DestAddr, SrcAddr and Len/Type field).
-* An Ethernet-II frame is encapsulated by inserting a SNAP header between the addressing information and the
-* type field. This insertion is transparent for the MSF.
-* The HCF contains a fixed table that stores a number of types. If the value specified by the type/type field
-* occurs in this table, Bridge Tunnel Encapsulation is used, otherwise RFC1042 encapsulation is used.
-* Bridge Tunnel uses AA AA 03 00 00 F8 as SNAP header,
-* RFC1042 uses AA AA 03 00 00 00 as SNAP header.
-* The table currently contains:
-* 0 0x80F3 AppleTalk Address Resolution Protocol (AARP)
-* 0 0x8137 IPX
-*
-* The algorithm to distinguish between 802.3 and Ethernet-II frames limits the maximum length for frames of
-* 802.3 frames to 1514 bytes.
-* Encapsulation can be suppressed by means of the system constant HCF_ENCAP, e.g. to support proprietary
-* protocols with 802.3 like frames with a size larger than 1514 bytes.
-*
-* In case the HCF encapsulates the frame, the number of bytes that is actually transmitted is determined by the
-* cumulative value of the buf_cntl.buf_dim[0] fields.
-* In case the HCF does not encapsulate the frame, the number of bytes that is actually transmitted is not
-* determined by the cumulative value of the buf_cntl.buf_dim[DESC_CNTL_CNT] fields of the desc_strct's but by
-* the Length field of the 802.3 frame.
-* If there is a conflict between the cumulative value of the buf_cntl.buf_dim[0] fields and the
-* 802.3 Length field the 802.3 Length field determines the number of bytes actually transmitted by the NIC while
-* the cumulative value of the buf_cntl.buf_dim[0] fields determines the position of the MIC, hence a mismatch
-* will result in MIC errors on the Receiving side.
-* Currently this problem is flagged on the Transmit side by an Assert.
-* The following fields of each of the descriptors in the descriptor list must be set by the MSF:
-* o buf_cntl.buf_dim[0]
-* o *next_desc_addr
-* o *buf_addr
-*
-* All bits of the tx_cntl parameter except HFS_TX_CNTL_TX_DELAY and the HCF_PORT# bits are passed to the F/W via
-* the HFS_TX_CNTL field of the TxFS.
-*
-* Note that hcf_send_msg does not detect NIC absence. The MSF is supposed to have its own -platform dependent-
-* way to recognize card removal/insertion.
-* The total system must be robust against card removal and there is no principal difference between card removal
-* just after hcf_send_msg returns but before the actual transmission took place or sometime earlier.
-*
-* Assert fails if
-* - ifbp has a recognizable out-of-range value
-* - descp is a NULL pointer
-* - no resources for PIF available.
-* - Interrupts are enabled.
-* - reentrancy, may be caused by calling hcf_functions without adequate protection
-* against NIC interrupts or multi-threading.
-*
-*.DIAGRAM
-*4: for the normal case (i.e. no HFS_TX_CNTL_TX_DELAY option active), a fid is acquired via the
-* routine get_fid. If no FID is acquired, the remainder is skipped without an error notification. After
-* all, the MSF is not supposed to call hcf_send_msg when no Resource is available.
-*7: The ControlField of the TxFS is written. Since put_frag can only return the fatal Defunct or "No NIC", the
-* return status can be ignored because when it fails, cmd_wait will fail as well. (see also the note on the
-* need for a return code below).
-* Note that HFS_TX_CNTL has different values for H-I, H-I/SSN and H-II and HFS_ADDR_DEST has different
-* values for H-I (regardless of SSN) and H-II.
-* By writing 17, 1 or 2 ( implying 16, 0 or 1 garbage word after HFS_TX_CNTL) the BAP just gets to
-* HFS_ADDR_DEST for H-I, H-I/SSN and H-II respectively.
-*10: if neither encapsulation nor MIC calculation is needed, splitting the first fragment in two does not
-* really help but it makes the flow easier to follow to do not optimize on this difference
-*
-* hcf_send_msg checks whether the frame is an Ethernet-II rather than an "official" 802.3 frame.
-* The E-II check is based on the length/type field in the MAC header. If this field has a value larger than
-* 1500, E-II is assumed. The implementation of this test fails if the length/type field is not in the first
-* descriptor. If E-II is recognized, a SNAP header is inserted. This SNAP header represents either RFC1042
-* or Bridge-Tunnel encapsulation, depending on the return status of the support routine hcf_encap.
-*
-*.NOTICE
-* hcf_send_msg leaves the responsibility to only send messages on enabled ports at the MSF level.
-* This is considered the strategy which is sufficiently adequate for all "robust" MSFs, have the least
-* processor utilization and being still acceptable robust at the WCI !!!!!
-*
-* hcf_send_msg does not NEED a return value to report NIC absence or removal during the execution of
-* hcf_send_msg(), because the MSF and higher layers must be able to cope anyway with the NIC being removed
-* after a successful completion of hcf_send_msg() but before the actual transmission took place.
-* To accommodate user expectations the current implementation does report NIC absence.
-* Defunct blocks all NIC access and will (also) be reported on a number of other calls.
-*
-* hcf_send_msg does not check for transmit buffer overflow because the Hermes does this protection.
-* In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped.
-* Note that this possibly results in the transmission of incomplete frames.
-*
-* After some deliberation with F/W team, it is decided that - being in the twilight zone of not knowing
-* whether the problem at hand is an MSF bug, HCF buf, F/W bug, H/W malfunction or even something else - there
-* is no "best thing to do" in case of a failing send, hence the HCF considers the TxFID ownership to be taken
-* over by the F/W and hopes for an Allocate event in due time
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.MODULE int hcf_send_msg( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl )
+ *.PURPOSE Encapsulate a message and append padding and MIC.
+ * non-USB: Transfers the resulting message from Host to NIC and initiates transmission.
+ * USB: Transfer resulting message into a flat buffer.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * descp pointer to the DescriptorList or NULL
+ * tx_cntl indicates MAC-port and (Hermes) options
+ * HFS_TX_CNTL_SPECTRALINK
+ * HFS_TX_CNTL_PRIO
+ * HFS_TX_CNTL_TX_OK
+ * HFS_TX_CNTL_TX_EX
+ * HFS_TX_CNTL_TX_DELAY
+ * HFS_TX_CNTL_TX_CONT
+ * HCF_PORT_0 MAC Port 0 (default)
+ * HCF_PORT_1 (AP only) MAC Port 1
+ * HCF_PORT_2 (AP only) MAC Port 2
+ * HCF_PORT_3 (AP only) MAC Port 3
+ * HCF_PORT_4 (AP only) MAC Port 4
+ * HCF_PORT_5 (AP only) MAC Port 5
+ * HCF_PORT_6 (AP only) MAC Port 6
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ * HCF_ERR_DEFUNCT_..
+ * HCF_ERR_TIME_OUT
+ *
+ *.DESCRIPTION:
+ * The Send Message Function embodies 2 functions:
+ * o transfers a message (including MAC header) from the provided buffer structure in Host memory to the Transmit
+ * Frame Structure (TxFS) in NIC memory.
+ * o Issue a send command to the F/W to actually transmit the contents of the TxFS.
+ *
+ * Control is based on the Resource Indicator IFB_RscInd.
+ * The Resource Indicator is maintained by the HCF and should only be interpreted but not changed by the MSF.
+ * The MSF must check IFB_RscInd to be non-zero before executing the call to the Send Message Function.
+ * When no resources are available, the MSF must handle the queuing of the Transmit frame and check the
+ * Resource Indicator periodically after calling hcf_service_nic.
+ *
+ * The Send Message Functions transfers a message to NIC memory when it is called with a non-NULL descp.
+ * Before the Send Message Function is invoked this way, the Resource Indicator (IFB_RscInd) must be checked.
+ * If the Resource is not available, Send Message Function execution must be postponed until after processing of
+ * a next hcf_service_nic it appears that the Resource has become available.
+ * The message is copied from the buffer structure identified by descp to the NIC.
+ * Copying stops if a NULL pointer in the next_desc_addr field is reached.
+ * Hcf_send_msg does not check for transmit buffer overflow, because the F/W does this protection.
+ * In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped.
+ *
+ * The Send Message Function activates the F/W to actually send the message to the medium when the
+ * HFS_TX_CNTL_TX_DELAY bit of the tx_cntl parameter is not set.
+ * If the descp parameter of the current call is non-NULL, the message as represented by descp is send.
+ * If the descp parameter of the current call is NULL, and if the preceding call of the Send Message Function had
+ * a non-NULL descp and the preceding call had the HFS_TX_CNTL_TX_DELAY bit of tx_cntl set, then the message as
+ * represented by the descp of the preceding call is send.
+ *
+ * Hcf_send_msg supports encapsulation (see HCF_ENCAP) of Ethernet-II frames.
+ * An Ethernet-II frame is transferred to the Transmit Frame structure as an 802.3 frame.
+ * Hcf_send_msg distinguishes between an 802.3 and an Ethernet-II frame by looking at the data length/type field
+ * of the frame. If this field contains a value larger than 1514, the frame is considered to be an Ethernet-II
+ * frame, otherwise it is treated as an 802.3 frame.
+ * To ease implementation of the HCF, this type/type field must be located in the first descriptor structure,
+ * i.e. the 1st fragment must have a size of at least 14 (to contain DestAddr, SrcAddr and Len/Type field).
+ * An Ethernet-II frame is encapsulated by inserting a SNAP header between the addressing information and the
+ * type field. This insertion is transparent for the MSF.
+ * The HCF contains a fixed table that stores a number of types. If the value specified by the type/type field
+ * occurs in this table, Bridge Tunnel Encapsulation is used, otherwise RFC1042 encapsulation is used.
+ * Bridge Tunnel uses AA AA 03 00 00 F8 as SNAP header,
+ * RFC1042 uses AA AA 03 00 00 00 as SNAP header.
+ * The table currently contains:
+ * 0 0x80F3 AppleTalk Address Resolution Protocol (AARP)
+ * 0 0x8137 IPX
+ *
+ * The algorithm to distinguish between 802.3 and Ethernet-II frames limits the maximum length for frames of
+ * 802.3 frames to 1514 bytes.
+ * Encapsulation can be suppressed by means of the system constant HCF_ENCAP, e.g. to support proprietary
+ * protocols with 802.3 like frames with a size larger than 1514 bytes.
+ *
+ * In case the HCF encapsulates the frame, the number of bytes that is actually transmitted is determined by the
+ * cumulative value of the buf_cntl.buf_dim[0] fields.
+ * In case the HCF does not encapsulate the frame, the number of bytes that is actually transmitted is not
+ * determined by the cumulative value of the buf_cntl.buf_dim[DESC_CNTL_CNT] fields of the desc_strct's but by
+ * the Length field of the 802.3 frame.
+ * If there is a conflict between the cumulative value of the buf_cntl.buf_dim[0] fields and the
+ * 802.3 Length field the 802.3 Length field determines the number of bytes actually transmitted by the NIC while
+ * the cumulative value of the buf_cntl.buf_dim[0] fields determines the position of the MIC, hence a mismatch
+ * will result in MIC errors on the Receiving side.
+ * Currently this problem is flagged on the Transmit side by an Assert.
+ * The following fields of each of the descriptors in the descriptor list must be set by the MSF:
+ * o buf_cntl.buf_dim[0]
+ * o *next_desc_addr
+ * o *buf_addr
+ *
+ * All bits of the tx_cntl parameter except HFS_TX_CNTL_TX_DELAY and the HCF_PORT# bits are passed to the F/W via
+ * the HFS_TX_CNTL field of the TxFS.
+ *
+ * Note that hcf_send_msg does not detect NIC absence. The MSF is supposed to have its own -platform dependent-
+ * way to recognize card removal/insertion.
+ * The total system must be robust against card removal and there is no principal difference between card removal
+ * just after hcf_send_msg returns but before the actual transmission took place or sometime earlier.
+ *
+ * Assert fails if
+ * - ifbp has a recognizable out-of-range value
+ * - descp is a NULL pointer
+ * - no resources for PIF available.
+ * - Interrupts are enabled.
+ * - reentrancy, may be caused by calling hcf_functions without adequate protection
+ * against NIC interrupts or multi-threading.
+ *
+ *.DIAGRAM
+ *4: for the normal case (i.e. no HFS_TX_CNTL_TX_DELAY option active), a fid is acquired via the
+ * routine get_fid. If no FID is acquired, the remainder is skipped without an error notification. After
+ * all, the MSF is not supposed to call hcf_send_msg when no Resource is available.
+ *7: The ControlField of the TxFS is written. Since put_frag can only return the fatal Defunct or "No NIC", the
+ * return status can be ignored because when it fails, cmd_wait will fail as well. (see also the note on the
+ * need for a return code below).
+ * Note that HFS_TX_CNTL has different values for H-I, H-I/WPA and H-II and HFS_ADDR_DEST has different
+ * values for H-I (regardless of WPA) and H-II.
+ * By writing 17, 1 or 2 ( implying 16, 0 or 1 garbage word after HFS_TX_CNTL) the BAP just gets to
+ * HFS_ADDR_DEST for H-I, H-I/WPA and H-II respectively.
+ *10: if neither encapsulation nor MIC calculation is needed, splitting the first fragment in two does not
+ * really help but it makes the flow easier to follow to do not optimize on this difference
+ *
+ * hcf_send_msg checks whether the frame is an Ethernet-II rather than an "official" 802.3 frame.
+ * The E-II check is based on the length/type field in the MAC header. If this field has a value larger than
+ * 1500, E-II is assumed. The implementation of this test fails if the length/type field is not in the first
+ * descriptor. If E-II is recognized, a SNAP header is inserted. This SNAP header represents either RFC1042
+ * or Bridge-Tunnel encapsulation, depending on the return status of the support routine hcf_encap.
+ *
+ *.NOTICE
+ * hcf_send_msg leaves the responsibility to only send messages on enabled ports at the MSF level.
+ * This is considered the strategy which is sufficiently adequate for all "robust" MSFs, have the least
+ * processor utilization and being still acceptable robust at the WCI !!!!!
+ *
+ * hcf_send_msg does not NEED a return value to report NIC absence or removal during the execution of
+ * hcf_send_msg(), because the MSF and higher layers must be able to cope anyway with the NIC being removed
+ * after a successful completion of hcf_send_msg() but before the actual transmission took place.
+ * To accommodate user expectations the current implementation does report NIC absence.
+ * Defunct blocks all NIC access and will (also) be reported on a number of other calls.
+ *
+ * hcf_send_msg does not check for transmit buffer overflow because the Hermes does this protection.
+ * In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped.
+ * Note that this possibly results in the transmission of incomplete frames.
+ *
+ * After some deliberation with F/W team, it is decided that - being in the twilight zone of not knowing
+ * whether the problem at hand is an MSF bug, HCF buf, F/W bug, H/W malfunction or even something else - there
+ * is no "best thing to do" in case of a failing send, hence the HCF considers the TxFID ownership to be taken
+ * over by the F/W and hopes for an Allocate event in due time
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
hcf_send_msg( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl )
{
-int rc = HCF_SUCCESS;
-DESC_STRCT *p /* = descp*/; //working pointer
-hcf_16 len; // total byte count
-hcf_16 i;
+ int rc = HCF_SUCCESS;
+ DESC_STRCT *p /* = descp*/; //working pointer
+ hcf_16 len; // total byte count
+ hcf_16 i;
-hcf_16 fid = 0;
+ hcf_16 fid = 0;
- HCFASSERT( ifbp->IFB_RscInd || descp == NULL, ifbp->IFB_RscInd )
- HCFASSERT( (ifbp->IFB_CntlOpt & USE_DMA) == 0, 0xDADB )
+ HCFASSERT( ifbp->IFB_RscInd || descp == NULL, ifbp->IFB_RscInd );
+ HCFASSERT( (ifbp->IFB_CntlOpt & USE_DMA) == 0, 0xDADB );
- HCFLOGENTRY( HCF_TRACE_SEND_MSG, tx_cntl )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
+ HCFLOGENTRY( HCF_TRACE_SEND_MSG, tx_cntl );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
/* obnoxious c:/hcf/hcf.c(1480) : warning C4769: conversion of near pointer to long integer,
* so skip */
- HCFASSERT( ((hcf_32)descp & 3 ) == 0, (hcf_32)descp )
+ HCFASSERT( ((hcf_32)descp & 3 ) == 0, (hcf_32)descp );
#if HCF_ASSERT
-{ int x = ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ? tx_cntl & ~HFS_TX_CNTL_PORT : tx_cntl;
- HCFASSERT( (x & ~HCF_TX_CNTL_MASK ) == 0, tx_cntl )
-}
+ { int x = ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ? tx_cntl & ~HFS_TX_CNTL_PORT : tx_cntl;
+ HCFASSERT( (x & ~HCF_TX_CNTL_MASK ) == 0, tx_cntl );
+ }
#endif // HCF_ASSERT
- if ( descp ) ifbp->IFB_TxFID = 0; //cancel a pre-put message
-
-#if (HCF_EXT) & HCF_EXT_TX_CONT // Continuous transmit test
- if ( tx_cntl == HFS_TX_CNTL_TX_CONT ) {
- fid = get_fid(ifbp);
- if (fid != 0 ) {
- //setup BAP to begin of TxFS
- (void)setup_bap( ifbp, fid, 0, IO_OUT );
- //copy all the fragments in a transparent fashion
- for ( p = descp; p; p = p->next_desc_addr ) {
- /* obnoxious warning C4769: conversion of near pointer to long integer */
- HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p )
- put_frag( ifbp, p->buf_addr, p->BUF_CNT BE_PAR(0) );
- }
- rc = cmd_exe( ifbp, HCMD_THESEUS | HCMD_BUSY | HCMD_STARTPREAMBLE, fid );
- if ( ifbp->IFB_RscInd == 0 ) {
- ifbp->IFB_RscInd = get_fid( ifbp );
- }
- }
- // een slecht voorbeeld doet goed volgen ;?
- HCFLOGEXIT( HCF_TRACE_SEND_MSG )
- return rc;
- }
-#endif // HCF_EXT_TX_CONT
- /* the following initialization code is redundant for a pre-put message
- * but moving it inside the "if fid" logic makes the merging with the
- * USB flow awkward
- */
+ if ( descp ) ifbp->IFB_TxFID = 0; //cancel a pre-put message
+
+ /* the following initialization code is redundant for a pre-put message
+ * but moving it inside the "if fid" logic makes the merging with the
+ * USB flow awkward
+ */
#if (HCF_TYPE) & HCF_TYPE_WPA
tx_cntl |= ifbp->IFB_MICTxCntl;
#endif // HCF_TYPE_WPA
fid = ifbp->IFB_TxFID;
- if (fid == 0 && ( fid = get_fid( ifbp ) ) != 0 ) /* 4 */
- /* skip the next compound statement if:
- - pre-put message or
- - no fid available (which should never occur if the MSF adheres to the WCI)
- */
- { // to match the closing curly bracket of above "if" in case of HCF_TYPE_USB
- //calculate total length ;? superfluous unless CCX or Encapsulation
+ if (fid == 0 && ( fid = get_fid( ifbp ) ) != 0 ) /* 4 */
+ /* skip the next compound statement if:
+ - pre-put message or
+ - no fid available (which should never occur if the MSF adheres to the WCI)
+ */
+ { // to match the closing curly bracket of above "if" in case of HCF_TYPE_USB
+ //calculate total length ;? superfluous unless CCX or Encapsulation
len = 0;
p = descp;
do len += p->BUF_CNT; while ( ( p = p->next_desc_addr ) != NULL );
p = descp;
-//;? HCFASSERT( len <= HCF_MAX_MSG, len )
-/*7*/ (void)setup_bap( ifbp, fid, HFS_TX_CNTL, IO_OUT );
+//;? HCFASSERT( len <= HCF_MAX_MSG, len );
+ /*7*/ (void)setup_bap( ifbp, fid, HFS_TX_CNTL, IO_OUT );
#if (HCF_TYPE) & HCF_TYPE_TX_DELAY
- HCFASSERT( ( descp != NULL ) ^ ( tx_cntl & HFS_TX_CNTL_TX_DELAY ), tx_cntl )
+ HCFASSERT( ( descp != NULL ) ^ ( tx_cntl & HFS_TX_CNTL_TX_DELAY ), tx_cntl );
if ( tx_cntl & HFS_TX_CNTL_TX_DELAY ) {
- tx_cntl &= ~HFS_TX_CNTL_TX_DELAY; //!!HFS_TX_CNTL_TX_DELAY no longer available
+ tx_cntl &= ~HFS_TX_CNTL_TX_DELAY; //!!HFS_TX_CNTL_TX_DELAY no longer available
ifbp->IFB_TxFID = fid;
- fid = 0; //!!fid no longer available, be careful when modifying code
+ fid = 0; //!!fid no longer available, be careful when modifying code
}
#endif // HCF_TYPE_TX_DELAY
OPW( HREG_DATA_1, tx_cntl ) ;
OPW( HREG_DATA_1, 0 );
-#if ! ( (HCF_TYPE) & HCF_TYPE_CCX )
- HCFASSERT( p->BUF_CNT >= 14, p->BUF_CNT )
- /* assume DestAddr/SrcAddr/Len/Type ALWAYS contained in 1st fragment
- * otherwise life gets too cumbersome for MIC and Encapsulation !!!!!!!!
- if ( p->BUF_CNT >= 14 ) { alternatively: add a safety escape !!!!!!!!!!!! } */
-#endif // HCF_TYPE_CCX
- CALC_TX_MIC( NULL, -1 ); //initialize MIC
-/*10*/ put_frag( ifbp, p->buf_addr, HCF_DASA_SIZE BE_PAR(0) ); //write DA, SA with MIC calculation
- CALC_TX_MIC( p->buf_addr, HCF_DASA_SIZE ); //MIC over DA, SA
- CALC_TX_MIC( null_addr, 4 ); //MIC over (virtual) priority field
-#if (HCF_TYPE) & HCF_TYPE_CCX
- //!!be careful do not use positive test on HCF_ACT_CCX_OFF, because IFB_CKIPStat is initially 0
- if(( ifbp->IFB_CKIPStat == HCF_ACT_CCX_ON ) ||
- ((GET_BUF_CNT(p) >= 20 ) && ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_OFF ) &&
- (p->buf_addr[12] == 0xAA) && (p->buf_addr[13] == 0xAA) &&
- (p->buf_addr[14] == 0x03) && (p->buf_addr[15] == 0x00) &&
- (p->buf_addr[16] == 0x40) && (p->buf_addr[17] == 0x96) &&
- (p->buf_addr[18] == 0x00) && (p->buf_addr[19] == 0x00)))
- {
- i = HCF_DASA_SIZE;
-
- OPW( HREG_DATA_1, CNV_SHORT_TO_BIG( len - i ));
-
- /* need to send out the remainder of the fragment */
- put_frag( ifbp, &p->buf_addr[i], GET_BUF_CNT(p) - i BE_PAR(0) );
- }
- else
-#endif // HCF_TYPE_CCX
- {
- //if encapsulation needed
+
+ HCFASSERT( p->BUF_CNT >= 14, p->BUF_CNT );
+ /* assume DestAddr/SrcAddr/Len/Type ALWAYS contained in 1st fragment
+ * otherwise life gets too cumbersome for MIC and Encapsulation !!!!!!!!
+ if ( p->BUF_CNT >= 14 ) { alternatively: add a safety escape !!!!!!!!!!!! } */
+
+ CALC_TX_MIC( NULL, -1 ); //initialize MIC
+ /*10*/ put_frag( ifbp, p->buf_addr, HCF_DASA_SIZE BE_PAR(0) ); //write DA, SA with MIC calculation
+ CALC_TX_MIC( p->buf_addr, HCF_DASA_SIZE ); //MIC over DA, SA
+ CALC_TX_MIC( null_addr, 4 ); //MIC over (virtual) priority field
+
+ //if encapsulation needed
#if (HCF_ENCAP) == HCF_ENC
- //write length (with SNAP-header,Type, without //DA,SA,Length ) no MIC calc.
- if ( ( snap_header[sizeof(snap_header)-1] = hcf_encap( &p->buf_addr[HCF_DASA_SIZE] ) ) != ENC_NONE ) {
- OPW( HREG_DATA_1, CNV_END_SHORT( len + (sizeof(snap_header) + 2) - ( 2*6 + 2 ) ) );
- //write splice with MIC calculation
- put_frag( ifbp, snap_header, sizeof(snap_header) BE_PAR(0) );
- CALC_TX_MIC( snap_header, sizeof(snap_header) ); //MIC over 6 byte SNAP
- i = HCF_DASA_SIZE;
- } else
+ //write length (with SNAP-header,Type, without //DA,SA,Length ) no MIC calc.
+ if ( ( snap_header[sizeof(snap_header)-1] = hcf_encap( &p->buf_addr[HCF_DASA_SIZE] ) ) != ENC_NONE ) {
+ OPW( HREG_DATA_1, CNV_END_SHORT( len + (sizeof(snap_header) + 2) - ( 2*6 + 2 ) ) );
+ //write splice with MIC calculation
+ put_frag( ifbp, snap_header, sizeof(snap_header) BE_PAR(0) );
+ CALC_TX_MIC( snap_header, sizeof(snap_header) ); //MIC over 6 byte SNAP
+ i = HCF_DASA_SIZE;
+ } else
#endif // HCF_ENC
- {
- OPW( HREG_DATA_1, *(wci_recordp)&p->buf_addr[HCF_DASA_SIZE] );
- i = 14;
- }
- //complete 1st fragment starting with Type with MIC calculation
- put_frag( ifbp, &p->buf_addr[i], p->BUF_CNT - i BE_PAR(0) );
- CALC_TX_MIC( &p->buf_addr[i], p->BUF_CNT - i );
+ {
+ OPW( HREG_DATA_1, *(wci_recordp)&p->buf_addr[HCF_DASA_SIZE] );
+ i = 14;
}
- //do the remaining fragments with MIC calculation
+ //complete 1st fragment starting with Type with MIC calculation
+ put_frag( ifbp, &p->buf_addr[i], p->BUF_CNT - i BE_PAR(0) );
+ CALC_TX_MIC( &p->buf_addr[i], p->BUF_CNT - i );
+
+ //do the remaining fragments with MIC calculation
while ( ( p = p->next_desc_addr ) != NULL ) {
/* obnoxious c:/hcf/hcf.c(1480) : warning C4769: conversion of near pointer to long integer,
* so skip */
- HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p )
+ HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p );
put_frag( ifbp, p->buf_addr, p->BUF_CNT BE_PAR(0) );
CALC_TX_MIC( p->buf_addr, p->BUF_CNT );
}
- //pad message, finalize MIC calculation and write MIC to NIC
+ //pad message, finalize MIC calculation and write MIC to NIC
put_frag_finalize( ifbp );
}
if ( fid ) {
-/*16*/ rc = cmd_exe( ifbp, HCMD_BUSY | HCMD_TX | HCMD_RECL, fid );
+ /*16*/ rc = cmd_exe( ifbp, HCMD_BUSY | HCMD_TX | HCMD_RECL, fid );
ifbp->IFB_TxFID = 0;
- /* probably this (i.e. no RscInd AND "HREG_EV_ALLOC") at this point in time occurs so infrequent,
- * that it might just as well be acceptable to skip this
- * "optimization" code and handle that additional interrupt once in a while
- */
+ /* probably this (i.e. no RscInd AND "HREG_EV_ALLOC") at this point in time occurs so infrequent,
+ * that it might just as well be acceptable to skip this
+ * "optimization" code and handle that additional interrupt once in a while
+ */
// 180 degree error in logic ;? #if ALLOC_15
-/*20*/ if ( ifbp->IFB_RscInd == 0 ) {
+ /*20*/ if ( ifbp->IFB_RscInd == 0 ) {
ifbp->IFB_RscInd = get_fid( ifbp );
}
// #endif // ALLOC_15
}
-// HCFASSERT( level::ifbp->IFB_RscInd, ifbp->IFB_RscInd )
- HCFLOGEXIT( HCF_TRACE_SEND_MSG )
+// HCFASSERT( level::ifbp->IFB_RscInd, ifbp->IFB_RscInd );
+ HCFLOGEXIT( HCF_TRACE_SEND_MSG );
return rc;
} // hcf_send_msg
-#endif // HCF_DL_ONLY
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.MODULE int hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len )
-*.PURPOSE Services (most) NIC events.
-* Provides received message
-* Provides status information.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* In non-DMA mode:
-* bufp address of char buffer, sufficiently large to hold the first part of the RxFS up through HFS_TYPE
-* len length in bytes of buffer specified by bufp
-* value between HFS_TYPE + 2 and HFS_ADDR_DEST + HCF_MAX_MSG
-*
-*.RETURNS
-* HCF_SUCCESS
-* HCF_ERR_MIC message contains an erroneous MIC (only if frame fits completely in bufp)
-*
-*.DESCRIPTION
-*
-* MSF-accessible fields of Result Block
-* - IFB_RxLen 0 or Frame size.
-* - IFB_MBInfoLen 0 or the L-field of the oldest MBIB.
-* - IFB_RscInd
-* - IFB_HCF_Tallies updated if a corresponding event occurred.
-* - IFB_NIC_Tallies updated if a Tally Info frame received from the NIC.
-* - IFB_DmaPackets
-* - IFB_TxFsStat
-* - IFB_TxFsSwSup
-* - IFB_LinkStat reflects new link status or 0x0000 if no change relative to previous hcf_service_nic call.
+ *
+ *.MODULE int hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len )
+ *.PURPOSE Services (most) NIC events.
+ * Provides received message
+ * Provides status information.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * In non-DMA mode:
+ * bufp address of char buffer, sufficiently large to hold the first part of the RxFS up through HFS_TYPE
+ * len length in bytes of buffer specified by bufp
+ * value between HFS_TYPE + 2 and HFS_ADDR_DEST + HCF_MAX_MSG
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ * HCF_ERR_MIC message contains an erroneous MIC (only if frame fits completely in bufp)
+ *
+ *.DESCRIPTION
+ *
+ * MSF-accessible fields of Result Block
+ * - IFB_RxLen 0 or Frame size.
+ * - IFB_MBInfoLen 0 or the L-field of the oldest MBIB.
+ * - IFB_RscInd
+ * - IFB_HCF_Tallies updated if a corresponding event occurred.
+ * - IFB_NIC_Tallies updated if a Tally Info frame received from the NIC.
+ * - IFB_DmaPackets
+ * - IFB_TxFsStat
+ * - IFB_TxFsSwSup
+ * - IFB_LinkStat reflects new link status or 0x0000 if no change relative to previous hcf_service_nic call.
or
-* - IFB_LinkStat link status, 0x8000 reflects change relative to previous hcf_service_nic call.
+* - IFB_LinkStat link status, 0x8000 reflects change relative to previous hcf_service_nic call.
*
* When IFB_MBInfoLen is non-zero, at least one MBIB is available.
*
-* IFB_RxLen reflects the number of received bytes in 802.3 view (Including DestAddr, SrcAddr and Length,
+* IFB_RxLen reflects the number of received bytes in 802.3 view (Including DestAddr, SrcAddr and Length,
* excluding MIC-padding, MIC and sum check) of active Rx Frame Structure. If no Rx Data s available, IFB_RxLen
* equals 0x0000.
* Repeated execution causes the Service NIC Function to provide information about subsequently received
@@ -2891,150 +2770,150 @@ or
* specific requirements of that environment to translate the interrupt strategy to a polled strategy.
*
* hcf_service_nic services the following Hermes events:
-* - HREG_EV_INFO Asynchronous Information Frame
-* - HREG_EV_INFO_DROP WMAC did not have sufficient RAM to build Unsolicited Information Frame
-* - HREG_EV_TX_EXC (if applicable, i.e. selected via HCF_EXT_INT_TX_EX bit of HCF_EXT)
-* - HREG_EV_SLEEP_REQ (if applicable, i.e. selected via HCF_DDS/HCF_CDS bit of HCF_SLEEP)
+* - HREG_EV_INFO Asynchronous Information Frame
+* - HREG_EV_INFO_DROP WMAC did not have sufficient RAM to build Unsolicited Information Frame
+* - HREG_EV_TX_EXC (if applicable, i.e. selected via HCF_EXT_INT_TX_EX bit of HCF_EXT)
+* - HREG_EV_SLEEP_REQ (if applicable, i.e. selected via HCF_DDS/HCF_CDS bit of HCF_SLEEP)
* ** in non_DMA mode
-* - HREG_EV_ALLOC Asynchronous part of Allocation/Reclaim completed while out of resources at
-* completion of hcf_send_msg/notify
-* - HREG_EV_RX the detection of the availability of received messages
-* including WaveLAN Management Protocol (WMP) message processing
+* - HREG_EV_ALLOC Asynchronous part of Allocation/Reclaim completed while out of resources at
+* completion of hcf_send_msg/notify
+* - HREG_EV_RX the detection of the availability of received messages
+* including WaveLAN Management Protocol (WMP) message processing
* ** in DMA mode
* - HREG_EV_RDMAD
* - HREG_EV_TDMAD
*!! hcf_service_nic does not service the following Hermes events:
-*!! HREG_EV_TX (the "OK" Tx Event) is no longer supported by the WCI, if it occurs it is unclear
-*!! what the cause is, so no meaningful strategy is available. Not acking the bit is
-*!! probably the best help that can be given to the debugger.
-*!! HREG_EV_CMD handled in cmd_wait.
-*!! HREG_EV_FW_DMA (i.e. HREG_EV_RXDMA, HREG_EV_TXDMA and_EV_LPESC) are either not used or used
-*!! between the F/W and the DMA engine.
-*!! HREG_EV_ACK_REG_READY is only applicable for H-II (i.e. not HII.5 and up, see DAWA)
-*
-* If, in non-DMA mode, a Rx message is available, its length is reflected by the IFB_RxLen field of the IFB.
-* This length reflects the data itself and the Destination Address, Source Address and DataLength/Type field
-* but not the SNAP-header in case of decapsulation by the HCF. If no message is available, IFB_RxLen is
-* zero. Former versions of the HCF handled WMP messages and supported a "monitor" mode in hcf_service_nic,
-* which deposited certain or all Rx messages in the MailBox. The responsibility to handle these frames is
-* moved to the MSF. The HCF offers as supports hcf_put_info with CFG_MB_INFO as parameter to emulate the old
-* implementation under control of the MSF.
+*!! HREG_EV_TX (the "OK" Tx Event) is no longer supported by the WCI, if it occurs it is unclear
+*!! what the cause is, so no meaningful strategy is available. Not acking the bit is
+*!! probably the best help that can be given to the debugger.
+*!! HREG_EV_CMD handled in cmd_wait.
+*!! HREG_EV_FW_DMA (i.e. HREG_EV_RXDMA, HREG_EV_TXDMA and_EV_LPESC) are either not used or used
+*!! between the F/W and the DMA engine.
+*!! HREG_EV_ACK_REG_READY is only applicable for H-II (i.e. not HII.5 and up, see DAWA)
+*
+* If, in non-DMA mode, a Rx message is available, its length is reflected by the IFB_RxLen field of the IFB.
+* This length reflects the data itself and the Destination Address, Source Address and DataLength/Type field
+* but not the SNAP-header in case of decapsulation by the HCF. If no message is available, IFB_RxLen is
+* zero. Former versions of the HCF handled WMP messages and supported a "monitor" mode in hcf_service_nic,
+* which deposited certain or all Rx messages in the MailBox. The responsibility to handle these frames is
+* moved to the MSF. The HCF offers as supports hcf_put_info with CFG_MB_INFO as parameter to emulate the old
+* implementation under control of the MSF.
*
* **Rx Buffer free strategy
-* When hcf_service_nic reports the availability of a non-DMA message, the MSF can access that message by
-* means of hcf_rcv_msg. It must be prevented that the LAN Controller writes new data in the NIC buffer
-* before the MSF is finished with the current message. The NIC buffer is returned to the LAN Controller
-* when:
-* - the complete frame fits in the lookahead buffer or
-* - hcf_rcv_msg is called or
-* - hcf_action with HCF_ACT_RX is called or
-* - hcf_service_nic is called again
-* It can be reasoned that hcf_action( INT_ON ) should not be given before the MSF has completely processed
-* a reported Rx-frame. The reason is that the INT_ON action is guaranteed to cause a (Rx-)interrupt (the
-* MSF is processing a Rx-frame, hence the Rx-event bit in the Hermes register must be active). This
-* interrupt will cause hcf_service_nic to be called, which will cause the ack-ing of the "last" Rx-event
-* to the Hermes, causing the Hermes to discard the associated NIC RAM buffer.
+* When hcf_service_nic reports the availability of a non-DMA message, the MSF can access that message by
+* means of hcf_rcv_msg. It must be prevented that the LAN Controller writes new data in the NIC buffer
+* before the MSF is finished with the current message. The NIC buffer is returned to the LAN Controller
+* when:
+* - the complete frame fits in the lookahead buffer or
+* - hcf_rcv_msg is called or
+* - hcf_action with HCF_ACT_RX is called or
+* - hcf_service_nic is called again
+* It can be reasoned that hcf_action( INT_ON ) should not be given before the MSF has completely processed
+* a reported Rx-frame. The reason is that the INT_ON action is guaranteed to cause a (Rx-)interrupt (the
+* MSF is processing a Rx-frame, hence the Rx-event bit in the Hermes register must be active). This
+* interrupt will cause hcf_service_nic to be called, which will cause the ack-ing of the "last" Rx-event
+* to the Hermes, causing the Hermes to discard the associated NIC RAM buffer.
* Assert fails if
* - ifbp is zero or other recognizable out-of-range value.
* - hcf_service_nic is called without a prior call to hcf_connect.
* - interrupts are enabled.
* - reentrancy, may be caused by calling hcf_functions without adequate protection
-* against NIC interrupts or multi-threading.
+* against NIC interrupts or multi-threading.
*
*
*.DIAGRAM
-*1: IFB_LinkStat is cleared, if a LinkStatus frame is received, IFB_LinkStat will be updated accordingly
-* by isr_info.
+*1: IFB_LinkStat is cleared, if a LinkStatus frame is received, IFB_LinkStat will be updated accordingly
+* by isr_info.
or
-*1: IFB_LinkStat change indication is cleared. If a LinkStatus frame is received, IFB_LinkStat will be updated
-* accordingly by isr_info.
+*1: IFB_LinkStat change indication is cleared. If a LinkStatus frame is received, IFB_LinkStat will be updated
+* accordingly by isr_info.
*2: IFB_RxLen must be cleared before the NIC presence check otherwise:
-* - this value may stay non-zero if the NIC is pulled out at an inconvenient moment.
-* - the RxAck on a zero-FID needs a zero-value for IFB_RxLen to work
-* Note that as side-effect of the hcf_action call, the remainder of Rx related info is re-initialized as
-* well.
-*4: In case of Defunct mode, the information supplied by Hermes is unreliable, so the body of
-* hcf_service_nic is skipped. Since hcf_cntl turns into a NOP if Primary or Station F/W is incompatible,
-* hcf_service_nic is also skipped in those cases.
-* To prevent that hcf_service_nic reports bogus information to the MSF with all - possibly difficult to
-* debug - undesirable side effects, it is paramount to check the NIC presence. In former days the presence
-* test was based on the Hermes register HREG_SW_0. Since in HCF_ACT_INT_OFF is chosen for strategy based on
-* HREG_EV_STAT, this is now also used in hcf_service_nic. The motivation to change strategy is partly
-* due to inconsistent F/W implementations with respect to HREG_SW_0 manipulation around reset and download.
-* Note that in polled environments Card Removal is not detected by INT_OFF which makes the check in
-* hcf_service_nic even more important.
-*8: The event status register of the Hermes is sampled
-* The assert checks for unexpected events ;?????????????????????????????????????.
-* - HREG_EV_INFO_DROP is explicitly excluded from the acceptable HREG_EV_STAT bits because it indicates
-* a too heavily loaded system.
-* - HREG_EV_ACK_REG_READY is 0x0000 for H-I (and hopefully H-II.5)
-*
-*
-* HREG_EV_TX_EXC is accepted (via HREG_EV_TX_EXT) if and only if HCF_EXT_INT_TX_EX set in the HCF_EXT
-* definition at compile time.
-* The following activities are handled:
-* - Alloc events are handled by hcf_send_msg (and notify). Only if there is no "spare" resource, the
-* alloc event is superficially serviced by hcf_service_nic to create a pseudo-resource with value
-* 0x001. This value is recognized by get_fid (called by hcf_send_msg and notify) where the real
-* TxFid is retrieved and the Hermes is acked and - hopefully - the "normal" case with a spare TxFid
-* in IFB_RscInd is restored.
-* - Info drop events are handled by incrementing a tally
-* - LinkEvent (including solicited and unsolicited tallies) are handled by procedure isr_info.
-* - TxEx (if selected at compile time) is handled by copying the significant part of the TxFS
-* into the IFB for further processing by the MSF.
-* Note the complication of the zero-FID protection sub-scheme in DAWA.
-* Note, the Ack of all of above events is handled at the end of hcf_service_nic
+* - this value may stay non-zero if the NIC is pulled out at an inconvenient moment.
+* - the RxAck on a zero-FID needs a zero-value for IFB_RxLen to work
+* Note that as side-effect of the hcf_action call, the remainder of Rx related info is re-initialized as
+* well.
+*4: In case of Defunct mode, the information supplied by Hermes is unreliable, so the body of
+* hcf_service_nic is skipped. Since hcf_cntl turns into a NOP if Primary or Station F/W is incompatible,
+* hcf_service_nic is also skipped in those cases.
+* To prevent that hcf_service_nic reports bogus information to the MSF with all - possibly difficult to
+* debug - undesirable side effects, it is paramount to check the NIC presence. In former days the presence
+* test was based on the Hermes register HREG_SW_0. Since in HCF_ACT_INT_OFF is chosen for strategy based on
+* HREG_EV_STAT, this is now also used in hcf_service_nic. The motivation to change strategy is partly
+* due to inconsistent F/W implementations with respect to HREG_SW_0 manipulation around reset and download.
+* Note that in polled environments Card Removal is not detected by INT_OFF which makes the check in
+* hcf_service_nic even more important.
+*8: The event status register of the Hermes is sampled
+* The assert checks for unexpected events ;?????????????????????????????????????.
+* - HREG_EV_INFO_DROP is explicitly excluded from the acceptable HREG_EV_STAT bits because it indicates
+* a too heavily loaded system.
+* - HREG_EV_ACK_REG_READY is 0x0000 for H-I (and hopefully H-II.5)
+*
+*
+* HREG_EV_TX_EXC is accepted (via HREG_EV_TX_EXT) if and only if HCF_EXT_INT_TX_EX set in the HCF_EXT
+* definition at compile time.
+* The following activities are handled:
+* - Alloc events are handled by hcf_send_msg (and notify). Only if there is no "spare" resource, the
+* alloc event is superficially serviced by hcf_service_nic to create a pseudo-resource with value
+* 0x001. This value is recognized by get_fid (called by hcf_send_msg and notify) where the real
+* TxFid is retrieved and the Hermes is acked and - hopefully - the "normal" case with a spare TxFid
+* in IFB_RscInd is restored.
+* - Info drop events are handled by incrementing a tally
+* - LinkEvent (including solicited and unsolicited tallies) are handled by procedure isr_info.
+* - TxEx (if selected at compile time) is handled by copying the significant part of the TxFS
+* into the IFB for further processing by the MSF.
+* Note the complication of the zero-FID protection sub-scheme in DAWA.
+* Note, the Ack of all of above events is handled at the end of hcf_service_nic
*16: In case of non-DMA ( either not compiled in or due to a run-time choice):
-* If an Rx-frame is available, first the FID of that frame is read, including the complication of the
-* zero-FID protection sub-scheme in DAWA. Note that such a zero-FID is acknowledged at the end of
-* hcf_service_nic and that this depends on the IFB_RxLen initialization in the begin of hcf_service_nic.
-* The Assert validates the HCF assumption about Hermes implementation upon which the range of
-* Pseudo-RIDs is based.
-* Then the control fields up to the start of the 802.3 frame are read from the NIC into the lookahead buffer.
-* The status field is converted to native Endianess.
-* The length is, after implicit Endianess conversion if needed, and adjustment for the 14 bytes of the
-* 802.3 MAC header, stored in IFB_RxLen.
-* In MAC Monitor mode, 802.11 control frames with a TOTAL length of 14 are received, so without this
-* length adjustment, IFB_RxLen could not be used to distinguish these frames from "no frame".
-* No MIC calculation processes are associated with the reading of these Control fields.
+* If an Rx-frame is available, first the FID of that frame is read, including the complication of the
+* zero-FID protection sub-scheme in DAWA. Note that such a zero-FID is acknowledged at the end of
+* hcf_service_nic and that this depends on the IFB_RxLen initialization in the begin of hcf_service_nic.
+* The Assert validates the HCF assumption about Hermes implementation upon which the range of
+* Pseudo-RIDs is based.
+* Then the control fields up to the start of the 802.3 frame are read from the NIC into the lookahead buffer.
+* The status field is converted to native Endianess.
+* The length is, after implicit Endianess conversion if needed, and adjustment for the 14 bytes of the
+* 802.3 MAC header, stored in IFB_RxLen.
+* In MAC Monitor mode, 802.11 control frames with a TOTAL length of 14 are received, so without this
+* length adjustment, IFB_RxLen could not be used to distinguish these frames from "no frame".
+* No MIC calculation processes are associated with the reading of these Control fields.
*26: This length test feels like superfluous robustness against malformed frames, but it turned out to be
-* needed in the real (hostile) world.
-* The decapsulation check needs sufficient data to represent DA, SA, L, SNAP and Type which amounts to
-* 22 bytes. In MAC Monitor mode, 802.11 control frames with a smaller length are received. To prevent
-* that the implementation goes haywire, a check on the length is needed.
-* The actual decapsulation takes place on the fly in the copying process by overwriting the SNAP header.
-* Note that in case of decapsulation the SNAP header is not passed to the MSF, hence IFB_RxLen must be
-* compensated for the SNAP header length.
-* The 22 bytes needed for decapsulation are (more than) sufficient for the exceptional handling of the
-* MIC algorithm of the L-field (replacing the 2 byte L-field with 4 0x00 bytes).
-*30: The 12 in the no-SSN branch corresponds with the get_frag, the 2 with the IPW of the SSN branch
+* needed in the real (hostile) world.
+* The decapsulation check needs sufficient data to represent DA, SA, L, SNAP and Type which amounts to
+* 22 bytes. In MAC Monitor mode, 802.11 control frames with a smaller length are received. To prevent
+* that the implementation goes haywire, a check on the length is needed.
+* The actual decapsulation takes place on the fly in the copying process by overwriting the SNAP header.
+* Note that in case of decapsulation the SNAP header is not passed to the MSF, hence IFB_RxLen must be
+* compensated for the SNAP header length.
+* The 22 bytes needed for decapsulation are (more than) sufficient for the exceptional handling of the
+* MIC algorithm of the L-field (replacing the 2 byte L-field with 4 0x00 bytes).
+*30: The 12 in the no-WPA branch corresponds with the get_frag, the 2 with the IPW of the WPA branch
*32: If Hermes reported MIC-presence, than the MIC engine is initialized with the non-dummy MIC calculation
-* routine address and appropriate key.
+* routine address and appropriate key.
*34: The 8 bytes after the DA, SA, L are read and it is checked whether decapsulation is needed i.e.:
-* - the Hermes reported Tunnel encapsulation or
-* - the Hermes reported 1042 Encapsulation and hcf_encap reports that the HCF would not have used
-* 1042 as the encapsulation mechanism
-* Note that the first field of the RxFS in bufp has Native Endianess due to the conversion done by the
-* BE_PAR in get_frag.
+* - the Hermes reported Tunnel encapsulation or
+* - the Hermes reported 1042 Encapsulation and hcf_encap reports that the HCF would not have used
+* 1042 as the encapsulation mechanism
+* Note that the first field of the RxFS in bufp has Native Endianess due to the conversion done by the
+* BE_PAR in get_frag.
*36: The Type field is the only word kept (after moving) of the just read 8 bytes, it is moved to the
-* L-field. The original L-field and 6 byte SNAP header are discarded, so IFB_RxLen and buf_addr must
-* be adjusted by 8.
+* L-field. The original L-field and 6 byte SNAP header are discarded, so IFB_RxLen and buf_addr must
+* be adjusted by 8.
*40: Determine how much of the frame (starting with DA) fits in the Lookahead buffer, then read the not-yet
-* read data into the lookahead buffer.
-* If the lookahead buffer contains the complete message, check the MIC. The majority considered this
-* I/F more appropriate then have the MSF call hcf_get_data only to check the MIC.
+* read data into the lookahead buffer.
+* If the lookahead buffer contains the complete message, check the MIC. The majority considered this
+* I/F more appropriate then have the MSF call hcf_get_data only to check the MIC.
*44: Since the complete message is copied from NIC RAM to PC RAM, the Rx can be acknowledged to the Hermes
-* to optimize the flow ( a better chance to get new Rx data in the next pass through hcf_service_nic ).
-* This acknowledgement can not be done via hcf_action( HCF_ACT_RX_ACK ) because this also clears
-* IFB_RxLEN thus corrupting the I/F to the MSF.
+* to optimize the flow ( a better chance to get new Rx data in the next pass through hcf_service_nic ).
+* This acknowledgement can not be done via hcf_action( HCF_ACT_RX_ACK ) because this also clears
+* IFB_RxLEN thus corrupting the I/F to the MSF.
*;?: In case of DMA (compiled in and activated):
*54: Limiting the number of places where the F/W is acked (e.g. the merging of the Rx-ACK with the other
-* ACKs), is supposed to diminish the potential of race conditions in the F/W.
-* Note 1: The CMD event is acknowledged in cmd_cmpl
-* Note 2: HREG_EV_ACK_REG_READY is 0x0000 for H-I (and hopefully H-II.5)
-* Note 3: The ALLOC event is acknowledged in get_fid (except for the initialization flow)
+* ACKs), is supposed to diminish the potential of race conditions in the F/W.
+* Note 1: The CMD event is acknowledged in cmd_cmpl
+* Note 2: HREG_EV_ACK_REG_READY is 0x0000 for H-I (and hopefully H-II.5)
+* Note 3: The ALLOC event is acknowledged in get_fid (except for the initialization flow)
*
*.NOTICE
* The Non-DMA HREG_EV_RX is handled different compared with the other F/W events.
@@ -3047,51 +2926,51 @@ or
*
*.NOTICE
* The minimum size for Len must supply space for:
-* - an F/W dependent number of bytes of Control Info field including the 802.11 Header field
-* - Destination Address
-* - Source Address
-* - Length field
-* - [ SNAP Header]
-* - [ Ethernet-II Type]
+* - an F/W dependent number of bytes of Control Info field including the 802.11 Header field
+* - Destination Address
+* - Source Address
+* - Length field
+* - [ SNAP Header]
+* - [ Ethernet-II Type]
* This results in 68 for Hermes-I and 80 for Hermes-II
* This way the minimum amount of information is available needed by the HCF to determine whether the frame
* must be decapsulated.
-*.ENDDOC END DOCUMENTATION
+*.ENDDOC END DOCUMENTATION
*
************************************************************************************************************/
int
hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len )
{
-int rc = HCF_SUCCESS;
-hcf_16 stat;
-wci_bufp buf_addr;
-hcf_16 i;
+ int rc = HCF_SUCCESS;
+ hcf_16 stat;
+ wci_bufp buf_addr;
+ hcf_16 i;
- HCFLOGENTRY( HCF_TRACE_SERVICE_NIC, ifbp->IFB_IntOffCnt )
- HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic )
- HCFASSERT_INT
+ HCFLOGENTRY( HCF_TRACE_SERVICE_NIC, ifbp->IFB_IntOffCnt );
+ HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic );
+ HCFASSERT_INT;
- ifbp->IFB_LinkStat = 0; // ;? to be obsoleted ASAP /* 1*/
- ifbp->IFB_DSLinkStat &= ~CFG_LINK_STAT_CHANGE; /* 1*/
- (void)hcf_action( ifbp, HCF_ACT_RX_ACK ); /* 2*/
- if ( ifbp->IFB_CardStat == 0 && ( stat = IPW( HREG_EV_STAT ) ) != 0xFFFF ) { /* 4*/
+ ifbp->IFB_LinkStat = 0; // ;? to be obsoleted ASAP /* 1*/
+ ifbp->IFB_DSLinkStat &= ~CFG_LINK_STAT_CHANGE; /* 1*/
+ (void)hcf_action( ifbp, HCF_ACT_RX_ACK ); /* 2*/
+ if ( ifbp->IFB_CardStat == 0 && ( stat = IPW( HREG_EV_STAT ) ) != 0xFFFF ) { /* 4*/
/* IF_NOT_DMA( HCFASSERT( !( stat & ~HREG_EV_BASIC_MASK, stat ) )
* IF_NOT_USE_DMA( HCFASSERT( !( stat & ~HREG_EV_BASIC_MASK, stat ) )
* IF_USE_DMA( HCFASSERT( !( stat & ~( HREG_EV_BASIC_MASK ^ ( HREG_EV_...DMA.... ), stat ) )
*/
- /* 8*/
+ /* 8*/
if ( ifbp->IFB_RscInd == 0 && stat & HREG_EV_ALLOC ) { //Note: IFB_RscInd is ALWAYS 1 for DMA
ifbp->IFB_RscInd = 1;
}
- IF_TALLY( if ( stat & HREG_EV_INFO_DROP ) ifbp->IFB_HCF_Tallies.NoBufInfo++; )
+ IF_TALLY( if ( stat & HREG_EV_INFO_DROP ) { ifbp->IFB_HCF_Tallies.NoBufInfo++; } );
#if (HCF_EXT) & HCF_EXT_INT_TICK
if ( stat & HREG_EV_TICK ) {
ifbp->IFB_TickCnt++;
}
#if 0 // (HCF_SLEEP) & HCF_DDS
if ( ifbp->IFB_TickCnt == 3 && ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) {
-CFG_DDS_TICK_TIME_STRCT ltv;
+ CFG_DDS_TICK_TIME_STRCT ltv;
// 2 second period (with 1 tick uncertanty) in not-connected mode -->go into DS_OOR
hcf_action( ifbp, HCF_ACT_SLEEP );
ifbp->IFB_DSLinkStat |= CFG_LINK_STAT_DS_OOR; //set OutOfRange
@@ -3100,7 +2979,7 @@ CFG_DDS_TICK_TIME_STRCT ltv;
ltv.tick_time = ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_TIMER ) + 0x10 ) *64; //78 is more right
hcf_put_info( ifbp, (LTVP)&ltv );
printk( "<5>Preparing for sleep, link_status: %04X, timer : %d\n",
- ifbp->IFB_DSLinkStat, ltv.tick_time );//;?remove me 1 day
+ ifbp->IFB_DSLinkStat, ltv.tick_time );//;?remove me 1 day
ifbp->IFB_TickCnt++; //;?just to make sure we do not keep on printing above message
if ( ltv.tick_time < 300 * 125 ) ifbp->IFB_DSLinkStat += 0x0010;
@@ -3112,7 +2991,7 @@ CFG_DDS_TICK_TIME_STRCT ltv;
}
#if (HCF_EXT) & HCF_EXT_INT_TX_EX
if ( stat & HREG_EV_TX_EXT && ( i = IPW( HREG_TX_COMPL_FID ) ) != 0 /*DAWA*/ ) {
- DAWA_ZERO_FID( HREG_TX_COMPL_FID )
+ DAWA_ZERO_FID( HREG_TX_COMPL_FID );
(void)setup_bap( ifbp, i, 0, IO_IN );
get_frag( ifbp, &ifbp->IFB_TxFsStat, HFS_SWSUP BE_PAR(1) );
}
@@ -3121,110 +3000,103 @@ CFG_DDS_TICK_TIME_STRCT ltv;
#if HCF_DMA
if ( !( ifbp->IFB_CntlOpt & USE_DMA ) ) //!! be aware of the logical indentations
#endif // HCF_DMA
-/*16*/ if ( stat & HREG_EV_RX && ( ifbp->IFB_RxFID = IPW( HREG_RX_FID ) ) != 0 ) { //if 0 then DAWA_ACK
- HCFASSERT( bufp, len )
- HCFASSERT( len >= HFS_DAT + 2, len )
- DAWA_ZERO_FID( HREG_RX_FID )
- HCFASSERT( ifbp->IFB_RxFID < CFG_PROD_DATA, ifbp->IFB_RxFID)
- (void)setup_bap( ifbp, ifbp->IFB_RxFID, 0, IO_IN );
- get_frag( ifbp, bufp, HFS_ADDR_DEST BE_PAR(1) );
- ifbp->IFB_lap = buf_addr = bufp + HFS_ADDR_DEST;
- ifbp->IFB_RxLen = (hcf_16)(bufp[HFS_DAT_LEN] + (bufp[HFS_DAT_LEN+1]<<8) + 2*6 + 2);
-/*26*/ if ( ifbp->IFB_RxLen >= 22 ) { // convenient for MIC calculation (5 DWs + 1 "skipped" W)
- //. get DA,SA,Len/Type and (SNAP,Type or 8 data bytes)
-/*30*/ get_frag( ifbp, buf_addr, 22 BE_PAR(0) );
-/*32*/ CALC_RX_MIC( bufp, -1 ); //. initialize MIC
- CALC_RX_MIC( buf_addr, HCF_DASA_SIZE ); //. MIC over DA, SA
- CALC_RX_MIC( null_addr, 4 ); //. MIC over (virtual) priority field
- CALC_RX_MIC( buf_addr+14, 8 ); //. skip Len, MIC over SNAP,Type or 8 data bytes)
- buf_addr += 22;
-#if (HCF_TYPE) & HCF_TYPE_CCX
-//!!be careful do not use positive test on HCF_ACT_CCX_OFF, because IFB_CKIPStat is initially 0
- if( ifbp->IFB_CKIPStat != HCF_ACT_CCX_ON )
-#endif // HCF_TYPE_CCX
- {
+ /*16*/ if ( stat & HREG_EV_RX && ( ifbp->IFB_RxFID = IPW( HREG_RX_FID ) ) != 0 ) { //if 0 then DAWA_ACK
+ HCFASSERT( bufp, len );
+ HCFASSERT( len >= HFS_DAT + 2, len );
+ DAWA_ZERO_FID( HREG_RX_FID );
+ HCFASSERT( ifbp->IFB_RxFID < CFG_PROD_DATA, ifbp->IFB_RxFID);
+ (void)setup_bap( ifbp, ifbp->IFB_RxFID, 0, IO_IN );
+ get_frag( ifbp, bufp, HFS_ADDR_DEST BE_PAR(1) );
+ ifbp->IFB_lap = buf_addr = bufp + HFS_ADDR_DEST;
+ ifbp->IFB_RxLen = (hcf_16)(bufp[HFS_DAT_LEN] + (bufp[HFS_DAT_LEN+1]<<8) + 2*6 + 2);
+ /*26*/ if ( ifbp->IFB_RxLen >= 22 ) { // convenient for MIC calculation (5 DWs + 1 "skipped" W)
+ //. get DA,SA,Len/Type and (SNAP,Type or 8 data bytes)
+ /*30*/ get_frag( ifbp, buf_addr, 22 BE_PAR(0) );
+ /*32*/ CALC_RX_MIC( bufp, -1 ); //. initialize MIC
+ CALC_RX_MIC( buf_addr, HCF_DASA_SIZE ); //. MIC over DA, SA
+ CALC_RX_MIC( null_addr, 4 ); //. MIC over (virtual) priority field
+ CALC_RX_MIC( buf_addr+14, 8 ); //. skip Len, MIC over SNAP,Type or 8 data bytes)
+ buf_addr += 22;
#if (HCF_ENCAP) == HCF_ENC
- HCFASSERT( len >= HFS_DAT + 2 + sizeof(snap_header), len )
-/*34*/ i = *(wci_recordp)&bufp[HFS_STAT] & ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR );
+ HCFASSERT( len >= HFS_DAT + 2 + sizeof(snap_header), len );
+ /*34*/ i = *(wci_recordp)&bufp[HFS_STAT] & ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR );
if ( i == HFS_STAT_TUNNEL ||
- ( i == HFS_STAT_1042 && hcf_encap( (wci_bufp)&bufp[HFS_TYPE] ) != ENC_TUNNEL ) ) {
- //. copy E-II Type to 802.3 LEN field
-/*36*/ bufp[HFS_LEN ] = bufp[HFS_TYPE ];
+ ( i == HFS_STAT_1042 && hcf_encap( (wci_bufp)&bufp[HFS_TYPE] ) != ENC_TUNNEL ) ) {
+ //. copy E-II Type to 802.3 LEN field
+ /*36*/ bufp[HFS_LEN ] = bufp[HFS_TYPE ];
bufp[HFS_LEN+1] = bufp[HFS_TYPE+1];
- //. discard Snap by overwriting with data
+ //. discard Snap by overwriting with data
ifbp->IFB_RxLen -= (HFS_TYPE - HFS_LEN);
buf_addr -= ( HFS_TYPE - HFS_LEN ); // this happens to bring us at a DW boundary of 36
}
#endif // HCF_ENC
}
- }
-/*40*/ ifbp->IFB_lal = min( (hcf_16)(len - HFS_ADDR_DEST), ifbp->IFB_RxLen );
- i = ifbp->IFB_lal - ( buf_addr - ( bufp + HFS_ADDR_DEST ) );
- get_frag( ifbp, buf_addr, i BE_PAR(0) );
- CALC_RX_MIC( buf_addr, i );
+ /*40*/ ifbp->IFB_lal = min( (hcf_16)(len - HFS_ADDR_DEST), ifbp->IFB_RxLen );
+ i = ifbp->IFB_lal - ( buf_addr - ( bufp + HFS_ADDR_DEST ) );
+ get_frag( ifbp, buf_addr, i BE_PAR(0) );
+ CALC_RX_MIC( buf_addr, i );
#if (HCF_TYPE) & HCF_TYPE_WPA
- if ( ifbp->IFB_lal == ifbp->IFB_RxLen ) {
- rc = check_mic( ifbp );
- }
+ if ( ifbp->IFB_lal == ifbp->IFB_RxLen ) {
+ rc = check_mic( ifbp );
+ }
#endif // HCF_TYPE_WPA
-/*44*/ if ( len - HFS_ADDR_DEST >= ifbp->IFB_RxLen ) {
- ifbp->IFB_RxFID = 0;
- } else { /* IFB_RxFID is cleared, so you do not get another Rx_Ack at next entry of hcf_service_nic */
- stat &= (hcf_16)~HREG_EV_RX; //don't ack Rx if processing not yet completed
+ /*44*/ if ( len - HFS_ADDR_DEST >= ifbp->IFB_RxLen ) {
+ ifbp->IFB_RxFID = 0;
+ } else { /* IFB_RxFID is cleared, so you do not get another Rx_Ack at next entry of hcf_service_nic */
+ stat &= (hcf_16)~HREG_EV_RX; //don't ack Rx if processing not yet completed
+ }
}
- }
// in case of DMA: signal availability of rx and/or tx packets to MSF
- IF_USE_DMA( ifbp->IFB_DmaPackets |= stat & ( HREG_EV_RDMAD | HREG_EV_TDMAD ); )
+ IF_USE_DMA( ifbp->IFB_DmaPackets |= stat & ( HREG_EV_RDMAD | HREG_EV_TDMAD ) );
// rlav : pending HREG_EV_RDMAD or HREG_EV_TDMAD events get acknowledged here.
-/*54*/ stat &= (hcf_16)~( HREG_EV_SLEEP_REQ | HREG_EV_CMD | HREG_EV_ACK_REG_READY | HREG_EV_ALLOC | HREG_EV_FW_DMA );
-//a positive mask would be easier to understand /*54*/ stat &= (hcf_16)~( HREG_EV_SLEEP_REQ | HREG_EV_CMD | HREG_EV_ACK_REG_READY | HREG_EV_ALLOC | HREG_EV_FW_DMA );
- IF_USE_DMA( stat &= (hcf_16)~HREG_EV_RX; )
+ /*54*/ stat &= (hcf_16)~( HREG_EV_SLEEP_REQ | HREG_EV_CMD | HREG_EV_ACK_REG_READY | HREG_EV_ALLOC | HREG_EV_FW_DMA );
+//a positive mask would be easier to understand /*54*/ stat &= (hcf_16)~( HREG_EV_SLEEP_REQ | HREG_EV_CMD | HREG_EV_ACK_REG_READY | HREG_EV_ALLOC | HREG_EV_FW_DMA );
+ IF_USE_DMA( stat &= (hcf_16)~HREG_EV_RX );
if ( stat ) {
- DAWA_ACK( stat ); /*DAWA*/
+ DAWA_ACK( stat ); /*DAWA*/
}
}
- HCFLOGEXIT( HCF_TRACE_SERVICE_NIC )
+ HCFLOGEXIT( HCF_TRACE_SERVICE_NIC );
return rc;
} // hcf_service_nic
-#endif // HCF_DL_ONLY
/************************************************************************************************************
-************************** H C F S U P P O R T R O U T I N E S ******************************************
-************************************************************************************************************/
+ ************************** H C F S U P P O R T R O U T I N E S ******************************************
+ ************************************************************************************************************/
/************************************************************************************************************
-*
-*.SUBMODULE void calc_mic( hcf_32* p, hcf_32 m )
-*.PURPOSE calculate MIC on a quad byte.
-*
-*.ARGUMENTS
-* p address of the MIC
-* m 32 bit value to be processed by the MIC calculation engine
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* calc_mic is the implementation of the MIC algorithm. It is a monkey-see monkey-do copy of
-* Michael::appendByte()
-* of Appendix C of ..........
-*
-*
-*.DIAGRAM
-*
-*.NOTICE
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void calc_mic( hcf_32* p, hcf_32 m )
+ *.PURPOSE calculate MIC on a quad byte.
+ *
+ *.ARGUMENTS
+ * p address of the MIC
+ * m 32 bit value to be processed by the MIC calculation engine
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * calc_mic is the implementation of the MIC algorithm. It is a monkey-see monkey-do copy of
+ * Michael::appendByte()
+ * of Appendix C of ..........
+ *
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
#if (HCF_TYPE) & HCF_TYPE_WPA
#define ROL32( A, n ) ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
#define ROR32( A, n ) ROL32( (A), 32-(n) )
-#define L *p
-#define R *(p+1)
+#define L *p
+#define R *(p+1)
void
calc_mic( hcf_32* p, hcf_32 m )
@@ -3250,38 +3122,38 @@ calc_mic( hcf_32* p, hcf_32 m )
#if (HCF_TYPE) & HCF_TYPE_WPA
/************************************************************************************************************
-*
-*.SUBMODULE void calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len )
-*.PURPOSE calculate MIC on a single fragment.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* bufp (byte) address of buffer
-* len length in bytes of buffer specified by bufp
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* calc_mic_rx_frag ........
-*
-* The MIC is located in the IFB.
-* The MIC is separate for Tx and Rx, thus allowing hcf_send_msg to occur between hcf_service_nic and
-* hcf_rcv_msg.
-*
-*
-*.DIAGRAM
-*
-*.NOTICE
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len )
+ *.PURPOSE calculate MIC on a single fragment.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * bufp (byte) address of buffer
+ * len length in bytes of buffer specified by bufp
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * calc_mic_rx_frag ........
+ *
+ * The MIC is located in the IFB.
+ * The MIC is separate for Tx and Rx, thus allowing hcf_send_msg to occur between hcf_service_nic and
+ * hcf_rcv_msg.
+ *
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
void
calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len )
{
-static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumulate 4 bytes input for MIC engine
-int i;
+ static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumulate 4 bytes input for MIC engine
+ int i;
- if ( len == -1 ) { //initialize MIC housekeeping
+ if ( len == -1 ) { //initialize MIC housekeeping
i = *(wci_recordp)&p[HFS_STAT];
/* i = CNV_SHORTP_TO_LITTLE(&p[HFS_STAT]); should not be neede to prevent alignment poroblems
* since len == -1 if and only if p is lookahaead buffer which MUST be word aligned
@@ -3289,12 +3161,12 @@ int i;
*/
if ( ( i & HFS_STAT_MIC ) == 0 ) {
- ifbp->IFB_MICRxCarry = 0xFFFF; //suppress MIC calculation
+ ifbp->IFB_MICRxCarry = 0xFFFF; //suppress MIC calculation
} else {
ifbp->IFB_MICRxCarry = 0;
-//* Note that "coincidentally" the bit positions used in HFS_STAT
-//* correspond with the offset of the key in IFB_MICKey
- i = ( i & HFS_STAT_MIC_KEY_ID ) >> 10; /* coincidentally no shift needed for i itself */
+//* Note that "coincidentally" the bit positions used in HFS_STAT
+//* correspond with the offset of the key in IFB_MICKey
+ i = ( i & HFS_STAT_MIC_KEY_ID ) >> 10; /* coincidentally no shift needed for i itself */
ifbp->IFB_MICRx[0] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICRxKey[i ]);
ifbp->IFB_MICRx[1] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICRxKey[i+1]);
}
@@ -3308,11 +3180,11 @@ int i;
ifbp->IFB_MICRxCarry = 4;
len -= 4;
}
- } else while ( ifbp->IFB_MICRxCarry < 4 && len ) { //note for hcf_16 applies: 0xFFFF > 4
- x.x8[ifbp->IFB_MICRxCarry++] = *p++;
- len--;
- }
- while ( ifbp->IFB_MICRxCarry == 4 ) { //contrived so we have only 1 call to calc_mic so we could bring it in-line
+ } else while ( ifbp->IFB_MICRxCarry < 4 && len ) { //note for hcf_16 applies: 0xFFFF > 4
+ x.x8[ifbp->IFB_MICRxCarry++] = *p++;
+ len--;
+ }
+ while ( ifbp->IFB_MICRxCarry == 4 ) { //contrived so we have only 1 call to calc_mic so we could bring it in-line
calc_mic( ifbp->IFB_MICRx, x.x32 );
x.x32 = CNV_LONGP_TO_LITTLE(p);
p += 4;
@@ -3328,92 +3200,92 @@ int i;
#if (HCF_TYPE) & HCF_TYPE_WPA
/************************************************************************************************************
-*
-*.SUBMODULE void calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len )
-*.PURPOSE calculate MIC on a single fragment.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* bufp (byte) address of buffer
-* len length in bytes of buffer specified by bufp
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* calc_mic_tx_frag ........
-*
-* The MIC is located in the IFB.
-* The MIC is separate for Tx and Rx, thus allowing hcf_send_msg to occur between hcf_service_nic and
-* hcf_rcv_msg.
-*
-*
-*.DIAGRAM
-*
-*.NOTICE
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len )
+ *.PURPOSE calculate MIC on a single fragment.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * bufp (byte) address of buffer
+ * len length in bytes of buffer specified by bufp
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * calc_mic_tx_frag ........
+ *
+ * The MIC is located in the IFB.
+ * The MIC is separate for Tx and Rx, thus allowing hcf_send_msg to occur between hcf_service_nic and
+ * hcf_rcv_msg.
+ *
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
void
calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len )
{
-static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumulate 4 bytes input for MIC engine
+ static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumulate 4 bytes input for MIC engine
- //if initialization request
+ //if initialization request
if ( len == -1 ) {
- //. presume MIC calculation disabled
+ //. presume MIC calculation disabled
ifbp->IFB_MICTxCarry = 0xFFFF;
- //. if MIC calculation enabled
+ //. if MIC calculation enabled
if ( ifbp->IFB_MICTxCntl ) {
- //. . clear MIC carry
+ //. . clear MIC carry
ifbp->IFB_MICTxCarry = 0;
- //. . initialize MIC-engine
- ifbp->IFB_MICTx[0] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICTxKey[0]); /*Tx always uses Key 0 */
+ //. . initialize MIC-engine
+ ifbp->IFB_MICTx[0] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICTxKey[0]); /*Tx always uses Key 0 */
ifbp->IFB_MICTx[1] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICTxKey[1]);
}
- //else
+ //else
} else {
- //. if MIC enabled (Tx) / if MIC present (Rx)
- //. and no carry from previous calc_mic_frag
+ //. if MIC enabled (Tx) / if MIC present (Rx)
+ //. and no carry from previous calc_mic_frag
if ( ifbp->IFB_MICTxCarry == 0 ) {
- //. . preset accu with 4 bytes from buffer
+ //. . preset accu with 4 bytes from buffer
x.x32 = CNV_LONGP_TO_LITTLE(p);
- //. . adjust pointer accordingly
+ //. . adjust pointer accordingly
p += 4;
- //. . if buffer contained less then 4 bytes
+ //. . if buffer contained less then 4 bytes
if ( len < 4 ) {
- //. . . promote valid bytes in accu to carry
- //. . . flag accu to contain incomplete double word
+ //. . . promote valid bytes in accu to carry
+ //. . . flag accu to contain incomplete double word
ifbp->IFB_MICTxCarry = (hcf_16)len;
- //. . else
+ //. . else
} else {
- //. . . flag accu to contain complete double word
+ //. . . flag accu to contain complete double word
ifbp->IFB_MICTxCarry = 4;
- //. . adjust remaining buffer length
+ //. . adjust remaining buffer length
len -= 4;
}
- //. else if MIC enabled
- //. and if carry bytes from previous calc_mic_tx_frag
- //. . move (1-3) bytes from carry into accu
- } else while ( ifbp->IFB_MICTxCarry < 4 && len ) { /* note for hcf_16 applies: 0xFFFF > 4 */
- x.x8[ifbp->IFB_MICTxCarry++] = *p++;
- len--;
- }
- //. while accu contains complete double word
- //. and MIC enabled
+ //. else if MIC enabled
+ //. and if carry bytes from previous calc_mic_tx_frag
+ //. . move (1-3) bytes from carry into accu
+ } else while ( ifbp->IFB_MICTxCarry < 4 && len ) { /* note for hcf_16 applies: 0xFFFF > 4 */
+ x.x8[ifbp->IFB_MICTxCarry++] = *p++;
+ len--;
+ }
+ //. while accu contains complete double word
+ //. and MIC enabled
while ( ifbp->IFB_MICTxCarry == 4 ) {
- //. . pass accu to MIC engine
+ //. . pass accu to MIC engine
calc_mic( ifbp->IFB_MICTx, x.x32 );
- //. . copy next 4 bytes from buffer to accu
+ //. . copy next 4 bytes from buffer to accu
x.x32 = CNV_LONGP_TO_LITTLE(p);
- //. . adjust buffer pointer
+ //. . adjust buffer pointer
p += 4;
- //. . if buffer contained less then 4 bytes
- //. . . promote valid bytes in accu to carry
- //. . . flag accu to contain incomplete double word
+ //. . if buffer contained less then 4 bytes
+ //. . . promote valid bytes in accu to carry
+ //. . . flag accu to contain incomplete double word
if ( len < 4 ) {
ifbp->IFB_MICTxCarry = (hcf_16)len;
}
- //. . adjust remaining buffer length
+ //. . adjust remaining buffer length
len -= 4;
}
}
@@ -3423,381 +3295,379 @@ static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumula
#if HCF_PROT_TIME
/************************************************************************************************************
-*
-*.SUBMODULE void calibrate( IFBP ifbp )
-*.PURPOSE calibrates the S/W protection counter against the Hermes Timer tick.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* calibrates the S/W protection counter against the Hermes Timer tick
-* IFB_TickIni is the value used to initialize the S/W protection counter such that the expiration period
-* more or less independent of the processor speed. If IFB_TickIni is not yet calibrated, it is done now.
-* This calibration is "reasonably" accurate because the Hermes is in a quiet state as a result of the
-* Initialize command.
-*
-*
-*.DIAGRAM
-*
-*1: IFB_TickIni is initialized at INI_TICK_INI by hcf_connect. If calibrate succeeds, IFB_TickIni is
-* guaranteed to be changed. As a consequence there will be only 1 shot at calibration (regardless of the
-* number of init calls) under normal circumstances.
-*2: Calibration is done HCF_PROT_TIME_CNT times. This diminish the effects of jitter and interference,
-* especially in a pre-emptive environment. HCF_PROT_TIME_CNT is in the range of 16 through 32 and derived
-* from the HCF_PROT_TIME specified by the MSF programmer. The divisor needed to scale HCF_PROT_TIME into the
-* 16-32 range, is used as a multiplicator after the calibration, to scale the found value back to the
-* requested range. This way a compromise is achieved between accuracy and duration of the calibration
-* process.
-*3: Acknowledge the Timer Tick Event.
-* Each cycle is limited to at most INI_TICK_INI samples of the TimerTick status of the Hermes.
-* Since the start of calibrate is unrelated to the Hermes Internal Timer, the first interval may last from 0
-* to the normal interval, all subsequent intervals should be the full length of the Hermes Tick interval.
-* The Hermes Timer Tick is not reprogrammed by the HCF, hence it is running at the default of 10 k
-* microseconds.
-*4: If the Timer Tick Event is continuously up (prot_cnt still has the value INI_TICK_INI) or no Timer Tick
-* Event occurred before the protection counter expired, reset IFB_TickIni to INI_TICK_INI,
-* set the defunct bit of IFB_CardStat (thus rendering the Hermes inoperable) and exit the calibrate routine.
-*8: ifbp->IFB_TickIni is multiplied to scale the found value back to the requested range as explained under 2.
-*
-*.NOTICE
-* o Although there are a number of viewpoints possible, calibrate() uses as error strategy that a single
-* failure of the Hermes TimerTick is considered fatal.
-* o There is no hard and concrete time-out value defined for Hermes activities. The default 1 seconds is
-* believed to be sufficiently "relaxed" for real life and to be sufficiently short to be still useful in an
-* environment with humans.
-* o Note that via IFB_DefunctStat time outs in cmd_wait and in hcfio_string block all Hermes access till the
-* next init so functions which call a mix of cmd_wait and hcfio_string only need to check the return status
-* of the last call
-* o The return code is preset at Time out.
-* The additional complication that no calibrated value for the protection count can be assumed since
-* calibrate() does not yet have determined a calibrated value (a catch 22), is handled by setting the
-* initial value at INI_TICK_INI (by hcf_connect). This approach is considered safe, because:
-* - the HCF does not use the pipeline mechanism of Hermes commands.
-* - the likelihood of failure (the only time when protection count is relevant) is small.
-* - the time will be sufficiently large on a fast machine (busy bit drops on good NIC before counter
-* expires)
-* - the time will be sufficiently small on a slow machine (counter expires on bad NIC before the end user
-* switches the power off in despair
-* The time needed to wrap a 32 bit counter around is longer than many humans want to wait, hence the more or
-* less arbitrary value of 0x40000L is chosen, assuming it does not take too long on an XT and is not too
-* short on a scream-machine.
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void calibrate( IFBP ifbp )
+ *.PURPOSE calibrates the S/W protection counter against the Hermes Timer tick.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * calibrates the S/W protection counter against the Hermes Timer tick
+ * IFB_TickIni is the value used to initialize the S/W protection counter such that the expiration period
+ * more or less independent of the processor speed. If IFB_TickIni is not yet calibrated, it is done now.
+ * This calibration is "reasonably" accurate because the Hermes is in a quiet state as a result of the
+ * Initialize command.
+ *
+ *
+ *.DIAGRAM
+ *
+ *1: IFB_TickIni is initialized at INI_TICK_INI by hcf_connect. If calibrate succeeds, IFB_TickIni is
+ * guaranteed to be changed. As a consequence there will be only 1 shot at calibration (regardless of the
+ * number of init calls) under normal circumstances.
+ *2: Calibration is done HCF_PROT_TIME_CNT times. This diminish the effects of jitter and interference,
+ * especially in a pre-emptive environment. HCF_PROT_TIME_CNT is in the range of 16 through 32 and derived
+ * from the HCF_PROT_TIME specified by the MSF programmer. The divisor needed to scale HCF_PROT_TIME into the
+ * 16-32 range, is used as a multiplicator after the calibration, to scale the found value back to the
+ * requested range. This way a compromise is achieved between accuracy and duration of the calibration
+ * process.
+ *3: Acknowledge the Timer Tick Event.
+ * Each cycle is limited to at most INI_TICK_INI samples of the TimerTick status of the Hermes.
+ * Since the start of calibrate is unrelated to the Hermes Internal Timer, the first interval may last from 0
+ * to the normal interval, all subsequent intervals should be the full length of the Hermes Tick interval.
+ * The Hermes Timer Tick is not reprogrammed by the HCF, hence it is running at the default of 10 k
+ * microseconds.
+ *4: If the Timer Tick Event is continuously up (prot_cnt still has the value INI_TICK_INI) or no Timer Tick
+ * Event occurred before the protection counter expired, reset IFB_TickIni to INI_TICK_INI,
+ * set the defunct bit of IFB_CardStat (thus rendering the Hermes inoperable) and exit the calibrate routine.
+ *8: ifbp->IFB_TickIni is multiplied to scale the found value back to the requested range as explained under 2.
+ *
+ *.NOTICE
+ * o Although there are a number of viewpoints possible, calibrate() uses as error strategy that a single
+ * failure of the Hermes TimerTick is considered fatal.
+ * o There is no hard and concrete time-out value defined for Hermes activities. The default 1 seconds is
+ * believed to be sufficiently "relaxed" for real life and to be sufficiently short to be still useful in an
+ * environment with humans.
+ * o Note that via IFB_DefunctStat time outs in cmd_wait and in hcfio_string block all Hermes access till the
+ * next init so functions which call a mix of cmd_wait and hcfio_string only need to check the return status
+ * of the last call
+ * o The return code is preset at Time out.
+ * The additional complication that no calibrated value for the protection count can be assumed since
+ * calibrate() does not yet have determined a calibrated value (a catch 22), is handled by setting the
+ * initial value at INI_TICK_INI (by hcf_connect). This approach is considered safe, because:
+ * - the HCF does not use the pipeline mechanism of Hermes commands.
+ * - the likelihood of failure (the only time when protection count is relevant) is small.
+ * - the time will be sufficiently large on a fast machine (busy bit drops on good NIC before counter
+ * expires)
+ * - the time will be sufficiently small on a slow machine (counter expires on bad NIC before the end user
+ * switches the power off in despair
+ * The time needed to wrap a 32 bit counter around is longer than many humans want to wait, hence the more or
+ * less arbitrary value of 0x40000L is chosen, assuming it does not take too long on an XT and is not too
+ * short on a scream-machine.
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC void
calibrate( IFBP ifbp )
{
-int cnt = HCF_PROT_TIME_CNT;
-hcf_32 prot_cnt;
+ int cnt = HCF_PROT_TIME_CNT;
+ hcf_32 prot_cnt;
HCFTRACE( ifbp, HCF_TRACE_CALIBRATE );
- if ( ifbp->IFB_TickIni == INI_TICK_INI ) { /*1*/
- ifbp->IFB_TickIni = 0; /*2*/
- while ( cnt-- ) {
- prot_cnt = INI_TICK_INI;
- OPW( HREG_EV_ACK, HREG_EV_TICK ); /*3*/
- while ( (IPW( HREG_EV_STAT ) & HREG_EV_TICK) == 0 && --prot_cnt ) {
- ifbp->IFB_TickIni++;
- }
- if ( prot_cnt == 0 || prot_cnt == INI_TICK_INI ) { /*4*/
- ifbp->IFB_TickIni = INI_TICK_INI;
- ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_TIMER;
- ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT;
- HCFASSERT( DO_ASSERT, prot_cnt )
- }
+ if ( ifbp->IFB_TickIni == INI_TICK_INI ) { /*1*/
+ ifbp->IFB_TickIni = 0; /*2*/
+ while ( cnt-- ) {
+ prot_cnt = INI_TICK_INI;
+ OPW( HREG_EV_ACK, HREG_EV_TICK ); /*3*/
+ while ( (IPW( HREG_EV_STAT ) & HREG_EV_TICK) == 0 && --prot_cnt ) {
+ ifbp->IFB_TickIni++;
}
- ifbp->IFB_TickIni <<= HCF_PROT_TIME_SHFT; /*8*/
+ if ( prot_cnt == 0 || prot_cnt == INI_TICK_INI ) { /*4*/
+ ifbp->IFB_TickIni = INI_TICK_INI;
+ ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_TIMER;
+ ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT;
+ HCFASSERT( DO_ASSERT, prot_cnt );
+ }
+ }
+ ifbp->IFB_TickIni <<= HCF_PROT_TIME_SHFT; /*8*/
}
HCFTRACE( ifbp, HCF_TRACE_CALIBRATE | HCF_TRACE_EXIT );
} // calibrate
#endif // HCF_PROT_TIME
-#if (HCF_DL_ONLY) == 0
#if (HCF_TYPE) & HCF_TYPE_WPA
/************************************************************************************************************
-*
-*.SUBMODULE int check_mic( IFBP ifbp )
-*.PURPOSE verifies the MIC of a received non-USB frame.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS
-* HCF_SUCCESS
-* HCF_ERR_MIC
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-*
-*4: test whether or not a MIC is reported by the Hermes
-*14: the calculated MIC and the received MIC are compared, the return status is set when there is a mismatch
-*
-*.NOTICE
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int check_mic( IFBP ifbp )
+ *.PURPOSE verifies the MIC of a received non-USB frame.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ * HCF_ERR_MIC
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ *
+ *4: test whether or not a MIC is reported by the Hermes
+ *14: the calculated MIC and the received MIC are compared, the return status is set when there is a mismatch
+ *
+ *.NOTICE
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
int
check_mic( IFBP ifbp )
{
-int rc = HCF_SUCCESS;
-hcf_32 x32[2]; //* area to save rcvd 8 bytes MIC
+ int rc = HCF_SUCCESS;
+ hcf_32 x32[2]; //* area to save rcvd 8 bytes MIC
- //if MIC present in RxFS
+ //if MIC present in RxFS
if ( *(wci_recordp)&ifbp->IFB_lap[-HFS_ADDR_DEST] & HFS_STAT_MIC ) {
- //or if ( ifbp->IFB_MICRxCarry != 0xFFFF )
- CALC_RX_MIC( mic_pad, 8 ); //. process up to 3 remaining bytes of data and append 5 to 8 bytes of padding to MIC calculation
+ //or if ( ifbp->IFB_MICRxCarry != 0xFFFF )
+ CALC_RX_MIC( mic_pad, 8 ); //. process up to 3 remaining bytes of data and append 5 to 8 bytes of padding to MIC calculation
get_frag( ifbp, (wci_bufp)x32, 8 BE_PAR(0));//. get 8 byte MIC from NIC
- //. if calculated and received MIC do not match
- //. . set status at HCF_ERR_MIC
-/*14*/ if ( x32[0] != CNV_LITTLE_TO_LONG(ifbp->IFB_MICRx[0]) ||
- x32[1] != CNV_LITTLE_TO_LONG(ifbp->IFB_MICRx[1]) ) {
+ //. if calculated and received MIC do not match
+ //. . set status at HCF_ERR_MIC
+ /*14*/ if ( x32[0] != CNV_LITTLE_TO_LONG(ifbp->IFB_MICRx[0]) ||
+ x32[1] != CNV_LITTLE_TO_LONG(ifbp->IFB_MICRx[1]) ) {
rc = HCF_ERR_MIC;
}
}
- //return status
+ //return status
return rc;
} // check_mic
#endif // HCF_TYPE_WPA
-#endif // HCF_DL_ONLY
/************************************************************************************************************
-*
-*.SUBMODULE int cmd_cmpl( IFBP ifbp )
-*.PURPOSE waits for Hermes Command Completion.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS
-* IFB_DefunctStat
-* HCF_ERR_TIME_OUT
-* HCF_ERR_DEFUNCT_CMD_SEQ
-* HCF_SUCCESS
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-*
-*2: Once cmd_cmpl is called, the Busy option bit in IFB_Cmd must be cleared
-*4: If Status register and command code don't match either:
-* - the Hermes and Host are out of sync ( a fatal error)
-* - error bits are reported via the Status Register.
-* Out of sync is considered fatal and brings the HCF in Defunct mode
-* Errors reported via the Status Register should be caused by sequence violations in Hermes command
-* sequences and hence these bugs should have been found during engineering testing. Since there is no
-* strategy to cope with this problem, it might as well be ignored at run time. Note that for any particular
-* situation where a strategy is formulated to handle the consequences of a particular bug causing a
-* particular Error situation reported via the Status Register, the bug should be removed rather than adding
-* logic to cope with the consequences of the bug.
-* There have been HCF versions where an error report via the Status Register even brought the HCF in defunct
-* mode (although it was not yet named like that at that time). This is particular undesirable behavior for a
-* general library.
-* Simply reporting the error (as "interesting") is debatable. There also have been HCF versions with this
-* strategy using the "vague" HCF_FAILURE code.
-* The error is reported via:
-* - MiscErr tally of the HCF Tally set
-* - the (informative) fields IFB_ErrCmd and IFB_ErrQualifier
-* - the assert mechanism
-*8: Here the Defunct case and the Status error are separately treated
-*
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int cmd_cmpl( IFBP ifbp )
+ *.PURPOSE waits for Hermes Command Completion.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS
+ * IFB_DefunctStat
+ * HCF_ERR_TIME_OUT
+ * HCF_ERR_DEFUNCT_CMD_SEQ
+ * HCF_SUCCESS
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ *
+ *2: Once cmd_cmpl is called, the Busy option bit in IFB_Cmd must be cleared
+ *4: If Status register and command code don't match either:
+ * - the Hermes and Host are out of sync ( a fatal error)
+ * - error bits are reported via the Status Register.
+ * Out of sync is considered fatal and brings the HCF in Defunct mode
+ * Errors reported via the Status Register should be caused by sequence violations in Hermes command
+ * sequences and hence these bugs should have been found during engineering testing. Since there is no
+ * strategy to cope with this problem, it might as well be ignored at run time. Note that for any particular
+ * situation where a strategy is formulated to handle the consequences of a particular bug causing a
+ * particular Error situation reported via the Status Register, the bug should be removed rather than adding
+ * logic to cope with the consequences of the bug.
+ * There have been HCF versions where an error report via the Status Register even brought the HCF in defunct
+ * mode (although it was not yet named like that at that time). This is particular undesirable behavior for a
+ * general library.
+ * Simply reporting the error (as "interesting") is debatable. There also have been HCF versions with this
+ * strategy using the "vague" HCF_FAILURE code.
+ * The error is reported via:
+ * - MiscErr tally of the HCF Tally set
+ * - the (informative) fields IFB_ErrCmd and IFB_ErrQualifier
+ * - the assert mechanism
+ *8: Here the Defunct case and the Status error are separately treated
+ *
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
cmd_cmpl( IFBP ifbp )
{
-PROT_CNT_INI
-int rc = HCF_SUCCESS;
-hcf_16 stat;
+ PROT_CNT_INI;
+ int rc = HCF_SUCCESS;
+ hcf_16 stat;
- HCFLOGENTRY( HCF_TRACE_CMD_CPL, ifbp->IFB_Cmd )
- ifbp->IFB_Cmd &= ~HCMD_BUSY; /* 2 */
- HCF_WAIT_WHILE( (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 ); /* 4 */
+ HCFLOGENTRY( HCF_TRACE_CMD_CPL, ifbp->IFB_Cmd );
+ ifbp->IFB_Cmd &= ~HCMD_BUSY; /* 2 */
+ HCF_WAIT_WHILE( (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 ); /* 4 */
stat = IPW( HREG_STAT );
#if HCF_PROT_TIME
if ( prot_cnt == 0 ) {
- IF_TALLY( ifbp->IFB_HCF_Tallies.MiscErr++; )
+ IF_TALLY( ifbp->IFB_HCF_Tallies.MiscErr++ );
rc = HCF_ERR_TIME_OUT;
- HCFASSERT( DO_ASSERT, ifbp->IFB_Cmd )
+ HCFASSERT( DO_ASSERT, ifbp->IFB_Cmd );
} else
#endif // HCF_PROT_TIME
{
DAWA_ACK( HREG_EV_CMD );
-/*4*/ if ( stat != (ifbp->IFB_Cmd & HCMD_CMD_CODE) ) {
-/*8*/ if ( ( (stat ^ ifbp->IFB_Cmd ) & HCMD_CMD_CODE) != 0 ) {
+ /*4*/ if ( stat != (ifbp->IFB_Cmd & HCMD_CMD_CODE) ) {
+ /*8*/ if ( ( (stat ^ ifbp->IFB_Cmd ) & HCMD_CMD_CODE) != 0 ) {
rc = ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_CMD_SEQ;
ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT;
}
- IF_TALLY( ifbp->IFB_HCF_Tallies.MiscErr++; )
+ IF_TALLY( ifbp->IFB_HCF_Tallies.MiscErr++ );
ifbp->IFB_ErrCmd = stat;
ifbp->IFB_ErrQualifier = IPW( HREG_RESP_0 );
- HCFASSERT( DO_ASSERT, MERGE_2( IPW( HREG_PARAM_0 ), ifbp->IFB_Cmd ) )
- HCFASSERT( DO_ASSERT, MERGE_2( ifbp->IFB_ErrQualifier, ifbp->IFB_ErrCmd ) )
+ HCFASSERT( DO_ASSERT, MERGE_2( IPW( HREG_PARAM_0 ), ifbp->IFB_Cmd ) );
+ HCFASSERT( DO_ASSERT, MERGE_2( ifbp->IFB_ErrQualifier, ifbp->IFB_ErrCmd ) );
}
}
- HCFASSERT( rc == HCF_SUCCESS, rc)
- HCFLOGEXIT( HCF_TRACE_CMD_CPL )
+ HCFASSERT( rc == HCF_SUCCESS, rc);
+ HCFLOGEXIT( HCF_TRACE_CMD_CPL );
return rc;
} // cmd_cmpl
/************************************************************************************************************
-*
-*.SUBMODULE int cmd_exe( IFBP ifbp, int cmd_code, int par_0 )
-*.PURPOSE Executes synchronous part of Hermes Command and - optionally - waits for Command Completion.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* cmd_code
-* par_0
-*
-*.RETURNS
-* IFB_DefunctStat
-* HCF_ERR_DEFUNCT_CMD_SEQ
-* HCF_SUCCESS
-* HCF_ERR_TO_BE_ADDED <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-*
-*.DESCRIPTION
-* Executes synchronous Hermes Command and waits for Command Completion
-*
-* The general HCF strategy is to wait for command completion. As a consequence:
-* - the read of the busy bit before writing the command register is superfluous
-* - the Hermes requirement that no Inquiry command may be executed if there is still an unacknowledged
-* Inquiry command outstanding, is automatically met.
-* The Tx command uses the "Busy" bit in the cmd_code parameter to deviate from this general HCF strategy.
-* The idea is that by not busy-waiting on completion of this frequently used command the processor
-* utilization is diminished while using the busy-wait on all other seldom used commands the flow is kept
-* simple.
-*
-*
-*
-*.DIAGRAM
-*
-*1: skip the body of cmd_exe when in defunct mode or when - based on the S/W Support register write and
-* read back test - there is apparently no NIC.
-* Note: we gave up on the "old" strategy to write the S/W Support register at magic only when needed. Due to
-* the intricateness of Hermes F/W varieties ( which behave differently as far as corruption of the S/W
-* Support register is involved), the increasing number of Hermes commands which do an implicit initialize
-* (thus modifying the S/W Support register) and the workarounds of some OS/Support S/W induced aspects (e.g.
-* the System Soft library at WinNT which postpones the actual mapping of I/O space up to 30 seconds after
-* giving the go-ahead), the "magic" strategy is now reduced to a simple write and read back. This means that
-* problems like a bug tramping over the memory mapped Hermes registers will no longer be noticed as side
-* effect of the S/W Support register check.
-*2: check whether the preceding command skipped the busy wait and if so, check for command completion
-*
-*.NOTICE
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int cmd_exe( IFBP ifbp, int cmd_code, int par_0 )
+ *.PURPOSE Executes synchronous part of Hermes Command and - optionally - waits for Command Completion.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * cmd_code
+ * par_0
+ *
+ *.RETURNS
+ * IFB_DefunctStat
+ * HCF_ERR_DEFUNCT_CMD_SEQ
+ * HCF_SUCCESS
+ * HCF_ERR_TO_BE_ADDED <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ *
+ *.DESCRIPTION
+ * Executes synchronous Hermes Command and waits for Command Completion
+ *
+ * The general HCF strategy is to wait for command completion. As a consequence:
+ * - the read of the busy bit before writing the command register is superfluous
+ * - the Hermes requirement that no Inquiry command may be executed if there is still an unacknowledged
+ * Inquiry command outstanding, is automatically met.
+ * The Tx command uses the "Busy" bit in the cmd_code parameter to deviate from this general HCF strategy.
+ * The idea is that by not busy-waiting on completion of this frequently used command the processor
+ * utilization is diminished while using the busy-wait on all other seldom used commands the flow is kept
+ * simple.
+ *
+ *
+ *
+ *.DIAGRAM
+ *
+ *1: skip the body of cmd_exe when in defunct mode or when - based on the S/W Support register write and
+ * read back test - there is apparently no NIC.
+ * Note: we gave up on the "old" strategy to write the S/W Support register at magic only when needed. Due to
+ * the intricateness of Hermes F/W varieties ( which behave differently as far as corruption of the S/W
+ * Support register is involved), the increasing number of Hermes commands which do an implicit initialize
+ * (thus modifying the S/W Support register) and the workarounds of some OS/Support S/W induced aspects (e.g.
+ * the System Soft library at WinNT which postpones the actual mapping of I/O space up to 30 seconds after
+ * giving the go-ahead), the "magic" strategy is now reduced to a simple write and read back. This means that
+ * problems like a bug tramping over the memory mapped Hermes registers will no longer be noticed as side
+ * effect of the S/W Support register check.
+ *2: check whether the preceding command skipped the busy wait and if so, check for command completion
+ *
+ *.NOTICE
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
-cmd_exe( IFBP ifbp, hcf_16 cmd_code, hcf_16 par_0 ) //if HCMD_BUSY of cmd_code set, then do NOT wait for completion
+cmd_exe( IFBP ifbp, hcf_16 cmd_code, hcf_16 par_0 ) //if HCMD_BUSY of cmd_code set, then do NOT wait for completion
{
-int rc;
+ int rc;
- HCFLOGENTRY( HCF_TRACE_CMD_EXE, cmd_code )
- HCFASSERT( (cmd_code & HCMD_CMD_CODE) != HCMD_TX || cmd_code & HCMD_BUSY, cmd_code ) //Tx must have Busy bit set
+ HCFLOGENTRY( HCF_TRACE_CMD_EXE, cmd_code );
+ HCFASSERT( (cmd_code & HCMD_CMD_CODE) != HCMD_TX || cmd_code & HCMD_BUSY, cmd_code ); //Tx must have Busy bit set
OPW( HREG_SW_0, HCF_MAGIC );
- if ( IPW( HREG_SW_0 ) == HCF_MAGIC ) { /* 1 */
+ if ( IPW( HREG_SW_0 ) == HCF_MAGIC ) { /* 1 */
rc = ifbp->IFB_DefunctStat;
}
else rc = HCF_ERR_NO_NIC;
if ( rc == HCF_SUCCESS ) {
//;?is this a hot idea, better MEASURE performance impact
-/*2*/ if ( ifbp->IFB_Cmd & HCMD_BUSY ) {
+ /*2*/ if ( ifbp->IFB_Cmd & HCMD_BUSY ) {
rc = cmd_cmpl( ifbp );
}
OPW( HREG_PARAM_0, par_0 );
OPW( HREG_CMD, cmd_code &~HCMD_BUSY );
ifbp->IFB_Cmd = cmd_code;
- if ( (cmd_code & HCMD_BUSY) == 0 ) { //;?is this a hot idea, better MEASURE performance impact
+ if ( (cmd_code & HCMD_BUSY) == 0 ) { //;?is this a hot idea, better MEASURE performance impact
rc = cmd_cmpl( ifbp );
}
}
- HCFASSERT( rc == HCF_SUCCESS, MERGE_2( rc, cmd_code ) )
- HCFLOGEXIT( HCF_TRACE_CMD_EXE )
+ HCFASSERT( rc == HCF_SUCCESS, MERGE_2( rc, cmd_code ) );
+ HCFLOGEXIT( HCF_TRACE_CMD_EXE );
return rc;
} // cmd_exe
/************************************************************************************************************
-*
-*.SUBMODULE int download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp )
-*.PURPOSE downloads F/W image into NIC and initiates execution of the downloaded F/W.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* ltvp specifies the pseudo-RID (as defined by WCI)
-*
-*.RETURNS
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-*1: First, Ack everything to unblock a (possibly) blocked cmd pipe line
-* Note 1: it is very likely that an Alloc event is pending and very well possible that a (Send) Cmd event is
-* pending
-* Note 2: it is assumed that this strategy takes away the need to ack every conceivable event after an
-* Hermes Initialize
-*
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp )
+ *.PURPOSE downloads F/W image into NIC and initiates execution of the downloaded F/W.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * ltvp specifies the pseudo-RID (as defined by WCI)
+ *
+ *.RETURNS
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ *1: First, Ack everything to unblock a (possibly) blocked cmd pipe line
+ * Note 1: it is very likely that an Alloc event is pending and very well possible that a (Send) Cmd event is
+ * pending
+ * Note 2: it is assumed that this strategy takes away the need to ack every conceivable event after an
+ * Hermes Initialize
+ *
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
-download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp ) //Hermes-II download (volatile only)
+download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp ) //Hermes-II download (volatile only)
{
-hcf_16 i;
-int rc = HCF_SUCCESS;
-wci_bufp cp;
-hcf_io io_port = ifbp->IFB_IOBase + HREG_AUX_DATA;
+ hcf_16 i;
+ int rc = HCF_SUCCESS;
+ wci_bufp cp;
+ hcf_io io_port = ifbp->IFB_IOBase + HREG_AUX_DATA;
- HCFLOGENTRY( HCF_TRACE_DL, ltvp->typ )
+ HCFLOGENTRY( HCF_TRACE_DL, ltvp->typ );
#if (HCF_TYPE) & HCF_TYPE_PRELOADED
- HCFASSERT( DO_ASSERT, ltvp->mode )
+ HCFASSERT( DO_ASSERT, ltvp->mode );
#else
- //if initial "program" LTV
+ //if initial "program" LTV
if ( ifbp->IFB_DLMode == CFG_PROG_STOP && ltvp->mode == CFG_PROG_VOLATILE) {
- //. switch Hermes to initial mode
-/*1*/ OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ );
- rc = cmd_exe( ifbp, HCMD_INI, 0 ); /* HCMD_INI can not be part of init() because that is called on
- * other occasions as well */
+ //. switch Hermes to initial mode
+ /*1*/ OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ );
+ rc = cmd_exe( ifbp, HCMD_INI, 0 ); /* HCMD_INI can not be part of init() because that is called on
+ * other occasions as well */
rc = init( ifbp );
}
- //if final "program" LTV
+ //if final "program" LTV
if ( ltvp->mode == CFG_PROG_STOP && ifbp->IFB_DLMode == CFG_PROG_VOLATILE) {
- //. start tertiary (or secondary)
+ //. start tertiary (or secondary)
OPW( HREG_PARAM_1, (hcf_16)(ltvp->nic_addr >> 16) );
rc = cmd_exe( ifbp, HCMD_EXECUTE, (hcf_16) ltvp->nic_addr );
if (rc == HCF_SUCCESS) {
- rc = init( ifbp ); /*;? do we really want to skip init if cmd_exe failed, i.e.
- * IFB_FW_Comp_Id is than possibly incorrect */
- }
- //else (non-final)
+ rc = init( ifbp ); /*;? do we really want to skip init if cmd_exe failed, i.e.
+ * IFB_FW_Comp_Id is than possibly incorrect */
+ }
+ //else (non-final)
} else {
- //. if mode == Readback SEEPROM
-#if 0 //;? as long as the next if contains a hard coded 0, might as well leave it out even more obvious
+ //. if mode == Readback SEEPROM
+#if 0 //;? as long as the next if contains a hard coded 0, might as well leave it out even more obvious
if ( 0 /*len is definitely not want we want;?*/ && ltvp->mode == CFG_PROG_SEEPROM_READBACK ) {
OPW( HREG_PARAM_1, (hcf_16)(ltvp->nic_addr >> 16) );
- OPW( HREG_PARAM_2, MUL_BY_2(ltvp->len - 4));
- //. . perform Hermes prog cmd with appropriate mode bits
+ OPW( HREG_PARAM_2, (hcf_16)((ltvp->len - 4) << 1) );
+ //. . perform Hermes prog cmd with appropriate mode bits
rc = cmd_exe( ifbp, HCMD_PROGRAM | ltvp->mode, (hcf_16)ltvp->nic_addr );
- //. . set up NIC RAM addressability according Resp0-1
+ //. . set up NIC RAM addressability according Resp0-1
OPW( HREG_AUX_PAGE, IPW( HREG_RESP_1) );
OPW( HREG_AUX_OFFSET, IPW( HREG_RESP_0) );
- //. . set up L-field of LTV according Resp2
+ //. . set up L-field of LTV according Resp2
i = ( IPW( HREG_RESP_2 ) + 1 ) / 2; // i contains max buffer size in words, a probably not very useful piece of information ;?
/*Nico's code based on i is the "real amount of data available"
if ( ltvp->len - 4 < i ) rc = HCF_ERR_LEN;
@@ -3810,126 +3680,125 @@ hcf_io io_port = ifbp->IFB_IOBase + HREG_AUX_DATA;
ltvp->len = i + 4;
}
*/
- //. . copy data from NIC via AUX port to LTV
- cp = (wci_bufp)ltvp->host_addr; /*IN_PORT_STRING_8_16 macro may modify its parameters*/
+ //. . copy data from NIC via AUX port to LTV
+ cp = (wci_bufp)ltvp->host_addr; /*IN_PORT_STRING_8_16 macro may modify its parameters*/
i = ltvp->len - 4;
- IN_PORT_STRING_8_16( io_port, cp, i ); //!!!WORD length, cp MUST be a char pointer // $$ char
- //. else (non-final programming)
+ IN_PORT_STRING_8_16( io_port, cp, i ); //!!!WORD length, cp MUST be a char pointer // $$ char
+ //. else (non-final programming)
} else
#endif //;? as long as the above if contains a hard coded 0, might as well leave it out even more obvious
- { //. . get number of words to program
- HCFASSERT( ltvp->segment_size, *ltvp->host_addr )
+ { //. . get number of words to program
+ HCFASSERT( ltvp->segment_size, *ltvp->host_addr );
i = ltvp->segment_size/2;
- //. . copy data (words) from LTV via AUX port to NIC
- cp = (wci_bufp)ltvp->host_addr; //OUT_PORT_STRING_8_16 macro may modify its parameters
- //. . if mode == volatile programming
+ //. . copy data (words) from LTV via AUX port to NIC
+ cp = (wci_bufp)ltvp->host_addr; //OUT_PORT_STRING_8_16 macro may modify its parameters
+ //. . if mode == volatile programming
if ( ltvp->mode == CFG_PROG_VOLATILE ) {
- //. . . set up NIC RAM addressability via AUX port
+ //. . . set up NIC RAM addressability via AUX port
OPW( HREG_AUX_PAGE, (hcf_16)(ltvp->nic_addr >> 16 << 9 | (ltvp->nic_addr & 0xFFFF) >> 7 ) );
OPW( HREG_AUX_OFFSET, (hcf_16)(ltvp->nic_addr & 0x007E) );
- OUT_PORT_STRING_8_16( io_port, cp, i ); //!!!WORD length, cp MUST be a char pointer
+ OUT_PORT_STRING_8_16( io_port, cp, i ); //!!!WORD length, cp MUST be a char pointer
}
}
}
- ifbp->IFB_DLMode = ltvp->mode; //save state in IFB_DLMode
+ ifbp->IFB_DLMode = ltvp->mode; //save state in IFB_DLMode
#endif // HCF_TYPE_PRELOADED
- HCFASSERT( rc == HCF_SUCCESS, rc )
- HCFLOGEXIT( HCF_TRACE_DL )
+ HCFASSERT( rc == HCF_SUCCESS, rc );
+ HCFLOGEXIT( HCF_TRACE_DL );
return rc;
} // download
#if (HCF_ASSERT) & HCF_ASSERT_PRINTF
/**************************************************
-* Certain Hermes-II firmware versions can generate
-* debug information. This debug information is
-* contained in a buffer in nic-RAM, and can be read
-* via the aux port.
-**************************************************/
+ * Certain Hermes-II firmware versions can generate
+ * debug information. This debug information is
+ * contained in a buffer in nic-RAM, and can be read
+ * via the aux port.
+ **************************************************/
HCF_STATIC int
fw_printf(IFBP ifbp, CFG_FW_PRINTF_STRCT FAR *ltvp)
{
- int rc = HCF_SUCCESS;
- hcf_16 fw_cnt;
-// hcf_32 DbMsgBuffer = 0x29D2, DbMsgCount= 0x000029D0;
-// hcf_16 DbMsgSize=0x00000080;
- hcf_32 DbMsgBuffer;
- CFG_FW_PRINTF_BUFFER_LOCATION_STRCT *p = &ifbp->IFB_FwPfBuff;
- ltvp->len = 1;
- if ( p->DbMsgSize != 0 ) {
- // first, check the counter in nic-RAM and compare it to the latest counter value of the HCF
- OPW( HREG_AUX_PAGE, (hcf_16)(p->DbMsgCount >> 7) );
- OPW( HREG_AUX_OFFSET, (hcf_16)(p->DbMsgCount & 0x7E) );
- fw_cnt = ((IPW( HREG_AUX_DATA) >>1 ) & ((hcf_16)p->DbMsgSize - 1));
- if ( fw_cnt != ifbp->IFB_DbgPrintF_Cnt ) {
-// DbgPrint("fw_cnt=%d IFB_DbgPrintF_Cnt=%d\n", fw_cnt, ifbp->IFB_DbgPrintF_Cnt);
- DbMsgBuffer = p->DbMsgBuffer + ifbp->IFB_DbgPrintF_Cnt * 6; // each entry is 3 words
- OPW( HREG_AUX_PAGE, (hcf_16)(DbMsgBuffer >> 7) );
- OPW( HREG_AUX_OFFSET, (hcf_16)(DbMsgBuffer & 0x7E) );
- ltvp->msg_id = IPW(HREG_AUX_DATA);
- ltvp->msg_par = IPW(HREG_AUX_DATA);
- ltvp->msg_tstamp = IPW(HREG_AUX_DATA);
- ltvp->len = 4;
- ifbp->IFB_DbgPrintF_Cnt++;
- ifbp->IFB_DbgPrintF_Cnt &= (p->DbMsgSize - 1);
- }
- }
- return rc;
+ int rc = HCF_SUCCESS;
+ hcf_16 fw_cnt;
+// hcf_32 DbMsgBuffer = 0x29D2, DbMsgCount= 0x000029D0;
+// hcf_16 DbMsgSize=0x00000080;
+ hcf_32 DbMsgBuffer;
+ CFG_FW_PRINTF_BUFFER_LOCATION_STRCT *p = &ifbp->IFB_FwPfBuff;
+ ltvp->len = 1;
+ if ( p->DbMsgSize != 0 ) {
+ // first, check the counter in nic-RAM and compare it to the latest counter value of the HCF
+ OPW( HREG_AUX_PAGE, (hcf_16)(p->DbMsgCount >> 7) );
+ OPW( HREG_AUX_OFFSET, (hcf_16)(p->DbMsgCount & 0x7E) );
+ fw_cnt = ((IPW( HREG_AUX_DATA) >>1 ) & ((hcf_16)p->DbMsgSize - 1));
+ if ( fw_cnt != ifbp->IFB_DbgPrintF_Cnt ) {
+// DbgPrint("fw_cnt=%d IFB_DbgPrintF_Cnt=%d\n", fw_cnt, ifbp->IFB_DbgPrintF_Cnt);
+ DbMsgBuffer = p->DbMsgBuffer + ifbp->IFB_DbgPrintF_Cnt * 6; // each entry is 3 words
+ OPW( HREG_AUX_PAGE, (hcf_16)(DbMsgBuffer >> 7) );
+ OPW( HREG_AUX_OFFSET, (hcf_16)(DbMsgBuffer & 0x7E) );
+ ltvp->msg_id = IPW(HREG_AUX_DATA);
+ ltvp->msg_par = IPW(HREG_AUX_DATA);
+ ltvp->msg_tstamp = IPW(HREG_AUX_DATA);
+ ltvp->len = 4;
+ ifbp->IFB_DbgPrintF_Cnt++;
+ ifbp->IFB_DbgPrintF_Cnt &= (p->DbMsgSize - 1);
+ }
+ }
+ return rc;
};
#endif // HCF_ASSERT_PRINTF
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.SUBMODULE hcf_16 get_fid( IFBP ifbp )
-*.PURPOSE get allocated FID for either transmit or notify.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS
-* 0 no FID available
-* <>0 FID number
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-* The preference is to use a "pending" alloc. If no alloc is pending, then - if available - the "spare" FID
-* is used.
-* If the spare FID is used, IFB_RscInd (representing the spare FID) must be cleared
-* If the pending alloc is used, the alloc event must be acknowledged to the Hermes.
-* In case the spare FID was depleted and the IFB_RscInd has been "faked" as pseudo resource with a 0x0001
-* value by hcf_service_nic, IFB_RscInd has to be "corrected" again to its 0x0000 value.
-*
-* Note that due to the Hermes-II H/W problems which are intended to be worked around by DAWA, the Alloc bit
-* in the Event register is no longer a reliable indication of the presence/absence of a FID. The "Clear FID"
-* part of the DAWA logic, together with the choice of the definition of the return information from get_fid,
-* handle this automatically, i.e. without additional code in get_fid.
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE hcf_16 get_fid( IFBP ifbp )
+ *.PURPOSE get allocated FID for either transmit or notify.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS
+ * 0 no FID available
+ * <>0 FID number
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ * The preference is to use a "pending" alloc. If no alloc is pending, then - if available - the "spare" FID
+ * is used.
+ * If the spare FID is used, IFB_RscInd (representing the spare FID) must be cleared
+ * If the pending alloc is used, the alloc event must be acknowledged to the Hermes.
+ * In case the spare FID was depleted and the IFB_RscInd has been "faked" as pseudo resource with a 0x0001
+ * value by hcf_service_nic, IFB_RscInd has to be "corrected" again to its 0x0000 value.
+ *
+ * Note that due to the Hermes-II H/W problems which are intended to be worked around by DAWA, the Alloc bit
+ * in the Event register is no longer a reliable indication of the presence/absence of a FID. The "Clear FID"
+ * part of the DAWA logic, together with the choice of the definition of the return information from get_fid,
+ * handle this automatically, i.e. without additional code in get_fid.
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC hcf_16
get_fid( IFBP ifbp )
{
-hcf_16 fid = 0;
+ hcf_16 fid = 0;
#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0
-PROT_CNT_INI
+ PROT_CNT_INI;
#endif // HCF_TYPE_HII5
- IF_DMA( HCFASSERT(!(ifbp->IFB_CntlOpt & USE_DMA), ifbp->IFB_CntlOpt) )
+ IF_DMA( HCFASSERT(!(ifbp->IFB_CntlOpt & USE_DMA), ifbp->IFB_CntlOpt) );
if ( IPW( HREG_EV_STAT) & HREG_EV_ALLOC) {
fid = IPW( HREG_ALLOC_FID );
- HCFASSERT( fid, ifbp->IFB_RscInd )
- DAWA_ZERO_FID( HREG_ALLOC_FID )
+ HCFASSERT( fid, ifbp->IFB_RscInd );
+ DAWA_ZERO_FID( HREG_ALLOC_FID );
#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0
HCF_WAIT_WHILE( ( IPW( HREG_EV_STAT ) & HREG_EV_ACK_REG_READY ) == 0 );
- HCFASSERT( prot_cnt, IPW( HREG_EV_STAT ) )
+ HCFASSERT( prot_cnt, IPW( HREG_EV_STAT ) );
#endif // HCF_TYPE_HII5
- DAWA_ACK( HREG_EV_ALLOC ); //!!note that HREG_EV_ALLOC is written only once
+ DAWA_ACK( HREG_EV_ALLOC ); //!!note that HREG_EV_ALLOC is written only once
// 180 degree error in logic ;? #if ALLOC_15
if ( ifbp->IFB_RscInd == 1 ) {
ifbp->IFB_RscInd = 0;
@@ -3943,120 +3812,119 @@ PROT_CNT_INI
}
return fid;
} // get_fid
-#endif // HCF_DL_ONLY
/************************************************************************************************************
-*
-*.SUBMODULE void get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
-*.PURPOSE reads with 16/32 bit I/O via BAP1 port from NIC RAM to Host memory.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* bufp (byte) address of buffer
-* len length in bytes of buffer specified by bufp
-* word_len Big Endian only: number of leading bytes to swap in pairs
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* process the single byte (if applicable) read by the previous get_frag and copy len (or len-1) bytes from
-* NIC to bufp.
-* On a Big Endian platform, the parameter word_len controls the number of leading bytes whose endianess is
-* converted (i.e. byte swapped)
-*
-*
-*.DIAGRAM
-*10: The PCMCIA card can be removed in the middle of the transfer. By depositing a "magic number" in the
-* HREG_SW_0 register of the Hermes at initialization time and by verifying this register, it can be
-* determined whether the card is still present. The return status is set accordingly.
-* Clearing the buffer is a (relative) cheap way to prevent that failing I/O results in run-away behavior
-* because the garbage in the buffer is interpreted by the caller irrespective of the return status (e.g.
-* hcf_service_nic has this behavior).
-*
-*.NOTICE
-* It turns out DOS ODI uses zero length fragments. The HCF code can cope with it, but as a consequence, no
-* Assert on len is possible
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
+ *.PURPOSE reads with 16/32 bit I/O via BAP1 port from NIC RAM to Host memory.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * bufp (byte) address of buffer
+ * len length in bytes of buffer specified by bufp
+ * word_len Big Endian only: number of leading bytes to swap in pairs
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * process the single byte (if applicable) read by the previous get_frag and copy len (or len-1) bytes from
+ * NIC to bufp.
+ * On a Big Endian platform, the parameter word_len controls the number of leading bytes whose endianess is
+ * converted (i.e. byte swapped)
+ *
+ *
+ *.DIAGRAM
+ *10: The PCMCIA card can be removed in the middle of the transfer. By depositing a "magic number" in the
+ * HREG_SW_0 register of the Hermes at initialization time and by verifying this register, it can be
+ * determined whether the card is still present. The return status is set accordingly.
+ * Clearing the buffer is a (relative) cheap way to prevent that failing I/O results in run-away behavior
+ * because the garbage in the buffer is interpreted by the caller irrespective of the return status (e.g.
+ * hcf_service_nic has this behavior).
+ *
+ *.NOTICE
+ * It turns out DOS ODI uses zero length fragments. The HCF code can cope with it, but as a consequence, no
+ * Assert on len is possible
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC void
get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
{
-hcf_io io_port = ifbp->IFB_IOBase + HREG_DATA_1; //BAP data register
-wci_bufp p = bufp; //working pointer
-int i; //prevent side effects from macro
-int j;
+ hcf_io io_port = ifbp->IFB_IOBase + HREG_DATA_1; //BAP data register
+ wci_bufp p = bufp; //working pointer
+ int i; //prevent side effects from macro
+ int j;
- HCFASSERT( ((hcf_32)bufp & (HCF_ALIGN-1) ) == 0, (hcf_32)bufp )
+ HCFASSERT( ((hcf_32)bufp & (HCF_ALIGN-1) ) == 0, (hcf_32)bufp );
-/*1: here recovery logic for intervening BAP access between hcf_service_nic and hcf_rcv_msg COULD be added
- * if current access is RxInitial
- * . persistent_offset += len
+/*1: here recovery logic for intervening BAP access between hcf_service_nic and hcf_rcv_msg COULD be added
+ * if current access is RxInitial
+ * . persistent_offset += len
*/
i = len;
- //if buffer length > 0 and carry from previous get_frag
+ //if buffer length > 0 and carry from previous get_frag
if ( i && ifbp->IFB_CarryIn ) {
- //. move carry to buffer
- //. adjust buffer length and pointer accordingly
+ //. move carry to buffer
+ //. adjust buffer length and pointer accordingly
*p++ = (hcf_8)(ifbp->IFB_CarryIn>>8);
i--;
- //. clear carry flag
+ //. clear carry flag
ifbp->IFB_CarryIn = 0;
}
#if (HCF_IO) & HCF_IO_32BITS
//skip zero-length I/O, single byte I/O and I/O not worthwhile (i.e. less than 6 bytes)for DW logic
- //if buffer length >= 6 and 32 bits I/O support
+ //if buffer length >= 6 and 32 bits I/O support
if ( !(ifbp->IFB_CntlOpt & USE_16BIT) && i >= 6 ) {
-hcf_32 FAR *p4; //prevent side effects from macro
- if ( ( (hcf_32)p & 0x1 ) == 0 ) { //. if buffer at least word aligned
- if ( (hcf_32)p & 0x2 ) { //. . if buffer not double word aligned
- //. . . read single word to get double word aligned
+ hcf_32 FAR *p4; //prevent side effects from macro
+ if ( ( (hcf_32)p & 0x1 ) == 0 ) { //. if buffer at least word aligned
+ if ( (hcf_32)p & 0x2 ) { //. . if buffer not double word aligned
+ //. . . read single word to get double word aligned
*(wci_recordp)p = IN_PORT_WORD( io_port );
- //. . . adjust buffer length and pointer accordingly
+ //. . . adjust buffer length and pointer accordingly
p += 2;
i -= 2;
}
- //. . read as many double word as possible
+ //. . read as many double word as possible
p4 = (hcf_32 FAR *)p;
j = i/4;
IN_PORT_STRING_32( io_port, p4, j );
- //. . adjust buffer length and pointer accordingly
+ //. . adjust buffer length and pointer accordingly
p += i & ~0x0003;
i &= 0x0003;
}
}
#endif // HCF_IO_32BITS
- //if no 32-bit support OR byte aligned OR 1-3 bytes left
+ //if no 32-bit support OR byte aligned OR 1-3 bytes left
if ( i ) {
- //. read as many word as possible in "alignment safe" way
+ //. read as many word as possible in "alignment safe" way
j = i/2;
IN_PORT_STRING_8_16( io_port, p, j );
- //. if 1 byte left
+ //. if 1 byte left
if ( i & 0x0001 ) {
- //. . read 1 word
+ //. . read 1 word
ifbp->IFB_CarryIn = IN_PORT_WORD( io_port );
- //. . store LSB in last char of buffer
+ //. . store LSB in last char of buffer
bufp[len-1] = (hcf_8)ifbp->IFB_CarryIn;
- //. . save MSB in carry, set carry flag
+ //. . save MSB in carry, set carry flag
ifbp->IFB_CarryIn |= 0x1;
}
}
#if HCF_BIG_ENDIAN
- HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len )
- HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp )
- HCFASSERT( word_len <= len, MERGE2( word_len, len ) )
+ HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len );
+ HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp );
+ HCFASSERT( word_len <= len, MERGE2( word_len, len ) );
//see put_frag for an alternative implementation, but be careful about what are int's and what are
//hcf_16's
- if ( word_len ) { //. if there is anything to convert
-hcf_8 c;
- c = bufp[1]; //. . convert the 1st hcf_16
+ if ( word_len ) { //. if there is anything to convert
+ hcf_8 c;
+ c = bufp[1]; //. . convert the 1st hcf_16
bufp[1] = bufp[0];
bufp[0] = c;
- if ( word_len > 1 ) { //. . if there is to convert more than 1 word ( i.e 2 )
- c = bufp[3]; //. . . convert the 2nd hcf_16
+ if ( word_len > 1 ) { //. . if there is to convert more than 1 word ( i.e 2 )
+ c = bufp[3]; //. . . convert the 2nd hcf_16
bufp[3] = bufp[2];
bufp[2] = c;
}
@@ -4065,108 +3933,108 @@ hcf_8 c;
} // get_frag
/************************************************************************************************************
-*
-*.SUBMODULE int init( IFBP ifbp )
-*.PURPOSE Handles common initialization aspects (H-I init, calibration, config.mngmt, allocation).
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS
-* HCF_ERR_INCOMP_PRI
-* HCF_ERR_INCOMP_FW
-* HCF_ERR_TIME_OUT
-* >>hcf_get_info
-* HCF_ERR_NO_NIC
-* HCF_ERR_LEN
-*
-*.DESCRIPTION
-* init will successively:
-* - in case of a (non-preloaded) H-I, initialize the NIC
-* - calibrate the S/W protection timer against the Hermes Timer
-* - collect HSI, "active" F/W Configuration Management Information
-* - in case active F/W is Primary F/W: collect Primary F/W Configuration Management Information
-* - check HSI and Primary F/W compatibility with the HCF
-* - in case active F/W is Station or AP F/W: check Station or AP F/W compatibility with the HCF
-* - in case active F/W is not Primary F/W: allocate FIDs to be used in transmit/notify process
-*
-*
-*.DIAGRAM
-*2: drop all error status bits in IFB_CardStat since they are expected to be re-evaluated.
-*4: Ack everything except HREG_EV_SLEEP_REQ. It is very likely that an Alloc event is pending and
-* very well possible that a Send Cmd event is pending. Acking HREG_EV_SLEEP_REQ is handled by hcf_action(
-* HCF_ACT_INT_ON ) !!!
-*10: Calibrate the S/W time-out protection mechanism by calling calibrate(). Note that possible errors
-* in the calibration process are nor reported by init but will show up via the defunct mechanism in
-* subsequent hcf-calls.
-*14: usb_check_comp() is called to have the minimal visual clutter for the legacy H-I USB dongle
-* compatibility check.
-*16: The following configuration management related information is retrieved from the NIC:
-* - HSI supplier
-* - F/W Identity
-* - F/W supplier
-* if appropriate:
-* - PRI Identity
-* - PRI supplier
-* appropriate means on H-I: always
-* and on H-II if F/W supplier reflects a primary (i.e. only after an Hermes Reset or Init
-* command).
-* QUESTION ;? !!!!!! should, For each of the above RIDs the Endianess is converted to native Endianess.
-* Only the return code of the first hcf_get_info is used. All hcf_get_info calls are made, regardless of
-* the success or failure of the 1st hcf_get_info. The assumptions are:
-* - if any call fails, they all fail, so remembering the result of the 1st call is adequate
-* - a failing call will overwrite the L-field with a 0x0000 value, which services both as an
-* error indication for the values cached in the IFB as making mmd_check_comp fail.
-* In case of H-I, when getting the F/W identity fails, the F/W is assumed to be H-I AP F/W pre-dating
-* version 9.0 and the F/W Identity and Supplier are faked accordingly.
-* In case of H-II, the Primary, Station and AP Identity are merged into a single F/W Identity.
-* The same applies to the Supplier information. As a consequence the PRI information can no longer be
-* retrieved when a Tertiary runs. To accommodate MSFs and Utilities who depend on PRI information being
-* available at any time, this information is cached in the IFB. In this cache the generic "F/W" value of
-* the typ-fields is overwritten with the specific (legacy) "PRI" values. To actually re-route the (legacy)
-* PRI request via hcf_get_info, the xxxx-table must be set. In case of H-I, this caching, modifying and
-* re-routing is not needed because PRI information is always available directly from the NIC. For
-* consistency the caching fields in the IFB are filled with the PRI information anyway.
-*18: mdd_check_comp() is called to check the Supplier Variant and Range of the Host-S/W I/F (HSI) and the
-* Primary Firmware Variant and Range against the Top and Bottom level supported by this HCF. If either of
-* these tests fails, the CARD_STAT_INCOMP_PRI bit of IFB_CardStat is set
-* Note: There should always be a primary except during production, so this makes the HCF in its current form
-* unsuitable for manufacturing test systems like the FTS. This can be remedied by an adding a test like
-* ifbp->IFB_PRISup.id == COMP_ID_PRI
-*20: In case there is Tertiary F/W and this F/W is Station F/W, the Supplier Variant and Range of the Station
-* Firmware function as retrieved from the Hermes is checked against the Top and Bottom level supported by
-* this HCF.
-* Note: ;? the tertiary F/W compatibility checks could be moved to the DHF, which already has checked the
-* CFI and MFI compatibility of the image with the NIC before the image was downloaded.
-*28: In case of non-Primary F/W: allocates and acknowledge a (TX or Notify) FID and allocates without
-* acknowledge another (TX or Notify) FID (the so-called 1.5 alloc scheme) with the following steps:
-* - execute the allocate command by calling cmd_exe
-* - wait till either the alloc event or a time-out occurs
-* - regardless whether the alloc event occurs, call get_fid to
-* - read the FID and save it in IFB_RscInd to be used as "spare FID"
-* - acknowledge the alloc event
-* - do another "half" allocate to complete the "1.5 Alloc scheme"
-* Note that above 3 steps do not harm and thus give the "cheapest" acceptable strategy.
-* If a time-out occurred, then report time out status (after all)
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int init( IFBP ifbp )
+ *.PURPOSE Handles common initialization aspects (H-I init, calibration, config.mngmt, allocation).
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS
+ * HCF_ERR_INCOMP_PRI
+ * HCF_ERR_INCOMP_FW
+ * HCF_ERR_TIME_OUT
+ * >>hcf_get_info
+ * HCF_ERR_NO_NIC
+ * HCF_ERR_LEN
+ *
+ *.DESCRIPTION
+ * init will successively:
+ * - in case of a (non-preloaded) H-I, initialize the NIC
+ * - calibrate the S/W protection timer against the Hermes Timer
+ * - collect HSI, "active" F/W Configuration Management Information
+ * - in case active F/W is Primary F/W: collect Primary F/W Configuration Management Information
+ * - check HSI and Primary F/W compatibility with the HCF
+ * - in case active F/W is Station or AP F/W: check Station or AP F/W compatibility with the HCF
+ * - in case active F/W is not Primary F/W: allocate FIDs to be used in transmit/notify process
+ *
+ *
+ *.DIAGRAM
+ *2: drop all error status bits in IFB_CardStat since they are expected to be re-evaluated.
+ *4: Ack everything except HREG_EV_SLEEP_REQ. It is very likely that an Alloc event is pending and
+ * very well possible that a Send Cmd event is pending. Acking HREG_EV_SLEEP_REQ is handled by hcf_action(
+ * HCF_ACT_INT_ON ) !!!
+ *10: Calibrate the S/W time-out protection mechanism by calling calibrate(). Note that possible errors
+ * in the calibration process are nor reported by init but will show up via the defunct mechanism in
+ * subsequent hcf-calls.
+ *14: usb_check_comp() is called to have the minimal visual clutter for the legacy H-I USB dongle
+ * compatibility check.
+ *16: The following configuration management related information is retrieved from the NIC:
+ * - HSI supplier
+ * - F/W Identity
+ * - F/W supplier
+ * if appropriate:
+ * - PRI Identity
+ * - PRI supplier
+ * appropriate means on H-I: always
+ * and on H-II if F/W supplier reflects a primary (i.e. only after an Hermes Reset or Init
+ * command).
+ * QUESTION ;? !!!!!! should, For each of the above RIDs the Endianess is converted to native Endianess.
+ * Only the return code of the first hcf_get_info is used. All hcf_get_info calls are made, regardless of
+ * the success or failure of the 1st hcf_get_info. The assumptions are:
+ * - if any call fails, they all fail, so remembering the result of the 1st call is adequate
+ * - a failing call will overwrite the L-field with a 0x0000 value, which services both as an
+ * error indication for the values cached in the IFB as making mmd_check_comp fail.
+ * In case of H-I, when getting the F/W identity fails, the F/W is assumed to be H-I AP F/W pre-dating
+ * version 9.0 and the F/W Identity and Supplier are faked accordingly.
+ * In case of H-II, the Primary, Station and AP Identity are merged into a single F/W Identity.
+ * The same applies to the Supplier information. As a consequence the PRI information can no longer be
+ * retrieved when a Tertiary runs. To accommodate MSFs and Utilities who depend on PRI information being
+ * available at any time, this information is cached in the IFB. In this cache the generic "F/W" value of
+ * the typ-fields is overwritten with the specific (legacy) "PRI" values. To actually re-route the (legacy)
+ * PRI request via hcf_get_info, the xxxx-table must be set. In case of H-I, this caching, modifying and
+ * re-routing is not needed because PRI information is always available directly from the NIC. For
+ * consistency the caching fields in the IFB are filled with the PRI information anyway.
+ *18: mdd_check_comp() is called to check the Supplier Variant and Range of the Host-S/W I/F (HSI) and the
+ * Primary Firmware Variant and Range against the Top and Bottom level supported by this HCF. If either of
+ * these tests fails, the CARD_STAT_INCOMP_PRI bit of IFB_CardStat is set
+ * Note: There should always be a primary except during production, so this makes the HCF in its current form
+ * unsuitable for manufacturing test systems like the FTS. This can be remedied by an adding a test like
+ * ifbp->IFB_PRISup.id == COMP_ID_PRI
+ *20: In case there is Tertiary F/W and this F/W is Station F/W, the Supplier Variant and Range of the Station
+ * Firmware function as retrieved from the Hermes is checked against the Top and Bottom level supported by
+ * this HCF.
+ * Note: ;? the tertiary F/W compatibility checks could be moved to the DHF, which already has checked the
+ * CFI and MFI compatibility of the image with the NIC before the image was downloaded.
+ *28: In case of non-Primary F/W: allocates and acknowledge a (TX or Notify) FID and allocates without
+ * acknowledge another (TX or Notify) FID (the so-called 1.5 alloc scheme) with the following steps:
+ * - execute the allocate command by calling cmd_exe
+ * - wait till either the alloc event or a time-out occurs
+ * - regardless whether the alloc event occurs, call get_fid to
+ * - read the FID and save it in IFB_RscInd to be used as "spare FID"
+ * - acknowledge the alloc event
+ * - do another "half" allocate to complete the "1.5 Alloc scheme"
+ * Note that above 3 steps do not harm and thus give the "cheapest" acceptable strategy.
+ * If a time-out occurred, then report time out status (after all)
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
init( IFBP ifbp )
{
-int rc = HCF_SUCCESS;
+ int rc = HCF_SUCCESS;
- HCFLOGENTRY( HCF_TRACE_INIT, 0 )
+ HCFLOGENTRY( HCF_TRACE_INIT, 0 );
- ifbp->IFB_CardStat = 0; /* 2*/
- OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ ); /* 4*/
- IF_PROT_TIME( calibrate( ifbp ); ) /*10*/
+ ifbp->IFB_CardStat = 0; /* 2*/
+ OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ ); /* 4*/
+ IF_PROT_TIME( calibrate( ifbp ) ); /*10*/
#if 0 // OOR
- ifbp->IFB_FWIdentity.len = 2; //misuse the IFB space for a put
+ ifbp->IFB_FWIdentity.len = 2; //misuse the IFB space for a put
ifbp->IFB_FWIdentity.typ = CFG_TICK_TIME;
- ifbp->IFB_FWIdentity.comp_id = (1000*1000)/1024 + 1; //roughly 1 second
+ ifbp->IFB_FWIdentity.comp_id = (1000*1000)/1024 + 1; //roughly 1 second
hcf_put_info( ifbp, (LTVP)&ifbp->IFB_FWIdentity.len );
#endif // OOR
ifbp->IFB_FWIdentity.len = sizeof(CFG_FW_IDENTITY_STRCT)/sizeof(hcf_16) - 1;
@@ -4179,8 +4047,8 @@ int rc = HCF_SUCCESS;
ifbp->IFB_FWIdentity.version_major = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWIdentity.version_major );
ifbp->IFB_FWIdentity.version_minor = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWIdentity.version_minor );
#endif // HCF_BIG_ENDIAN
-#if defined MSF_COMPONENT_ID /*14*/
- if ( rc == HCF_SUCCESS ) { /*16*/
+#if defined MSF_COMPONENT_ID /*14*/
+ if ( rc == HCF_SUCCESS ) { /*16*/
ifbp->IFB_HSISup.len = sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1;
ifbp->IFB_HSISup.typ = CFG_NIC_HSI_SUP_RANGE;
rc = hcf_get_info( ifbp, (LTVP)&ifbp->IFB_HSISup.len );
@@ -4207,133 +4075,132 @@ int rc = HCF_SUCCESS;
ifbp->IFB_FWSup.top = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWSup.top );
#endif // HCF_BIG_ENDIAN
- if ( ifbp->IFB_FWSup.id == COMP_ID_PRI ) { /* 20*/
-int i = sizeof( CFG_FW_IDENTITY_STRCT) + sizeof(CFG_SUP_RANGE_STRCT );
+ if ( ifbp->IFB_FWSup.id == COMP_ID_PRI ) { /* 20*/
+ int i = sizeof( CFG_FW_IDENTITY_STRCT) + sizeof(CFG_SUP_RANGE_STRCT );
while ( i-- ) ((hcf_8*)(&ifbp->IFB_PRIIdentity))[i] = ((hcf_8*)(&ifbp->IFB_FWIdentity))[i];
ifbp->IFB_PRIIdentity.typ = CFG_PRI_IDENTITY;
ifbp->IFB_PRISup.typ = CFG_PRI_SUP_RANGE;
xxxx[xxxx_PRI_IDENTITY_OFFSET] = &ifbp->IFB_PRIIdentity.len;
xxxx[xxxx_PRI_IDENTITY_OFFSET+1] = &ifbp->IFB_PRISup.len;
}
- if ( !mmd_check_comp( (void*)&cfg_drv_act_ranges_hsi, &ifbp->IFB_HSISup) /* 22*/
+ if ( !mmd_check_comp( (void*)&cfg_drv_act_ranges_hsi, &ifbp->IFB_HSISup) /* 22*/
#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0
//;? the PRI compatibility check is only relevant for DHF
- || !mmd_check_comp( (void*)&cfg_drv_act_ranges_pri, &ifbp->IFB_PRISup)
+ || !mmd_check_comp( (void*)&cfg_drv_act_ranges_pri, &ifbp->IFB_PRISup)
#endif // HCF_TYPE_PRELOADED
- ) {
+ ) {
ifbp->IFB_CardStat = CARD_STAT_INCOMP_PRI;
rc = HCF_ERR_INCOMP_PRI;
}
- if ( ( ifbp->IFB_FWSup.id == COMP_ID_STA && !mmd_check_comp( (void*)&cfg_drv_act_ranges_sta, &ifbp->IFB_FWSup) ) ||
- ( ifbp->IFB_FWSup.id == COMP_ID_APF && !mmd_check_comp( (void*)&cfg_drv_act_ranges_apf, &ifbp->IFB_FWSup) )
- ) { /* 24 */
+ if ( ( ifbp->IFB_FWSup.id == COMP_ID_STA && !mmd_check_comp( (void*)&cfg_drv_act_ranges_sta, &ifbp->IFB_FWSup) ) ||
+ ( ifbp->IFB_FWSup.id == COMP_ID_APF && !mmd_check_comp( (void*)&cfg_drv_act_ranges_apf, &ifbp->IFB_FWSup) )
+ ) { /* 24 */
ifbp->IFB_CardStat |= CARD_STAT_INCOMP_FW;
rc = HCF_ERR_INCOMP_FW;
}
}
#endif // MSF_COMPONENT_ID
-#if (HCF_DL_ONLY) == 0 /* 28 */
+
if ( rc == HCF_SUCCESS && ifbp->IFB_FWIdentity.comp_id >= COMP_ID_FW_STA ) {
-PROT_CNT_INI
+ PROT_CNT_INI;
/**************************************************************************************
- * rlav: the DMA engine needs the host to cause a 'hanging alloc event' for it to consume.
- * not sure if this is the right spot in the HCF, thinking about hcf_enable...
- **************************************************************************************/
+ * rlav: the DMA engine needs the host to cause a 'hanging alloc event' for it to consume.
+ * not sure if this is the right spot in the HCF, thinking about hcf_enable...
+ **************************************************************************************/
rc = cmd_exe( ifbp, HCMD_ALLOC, 0 );
// 180 degree error in logic ;? #if ALLOC_15
-// ifbp->IFB_RscInd = 1; //let's hope that by the time hcf_send_msg isa called, there will be a FID
+// ifbp->IFB_RscInd = 1; //let's hope that by the time hcf_send_msg isa called, there will be a FID
//#else
if ( rc == HCF_SUCCESS ) {
HCF_WAIT_WHILE( (IPW( HREG_EV_STAT ) & HREG_EV_ALLOC) == 0 );
- IF_PROT_TIME( HCFASSERT(prot_cnt, IPW( HREG_EV_STAT ) ) /*NOP*/;)
+ IF_PROT_TIME( HCFASSERT(prot_cnt, IPW( HREG_EV_STAT )) );
#if HCF_DMA
if ( ! ( ifbp->IFB_CntlOpt & USE_DMA ) )
#endif // HCF_DMA
{
ifbp->IFB_RscInd = get_fid( ifbp );
- HCFASSERT( ifbp->IFB_RscInd, 0 )
+ HCFASSERT( ifbp->IFB_RscInd, 0 );
cmd_exe( ifbp, HCMD_ALLOC, 0 );
- IF_PROT_TIME( if ( prot_cnt == 0 ) rc = HCF_ERR_TIME_OUT; )
+ IF_PROT_TIME( if ( prot_cnt == 0 ) rc = HCF_ERR_TIME_OUT );
}
}
//#endif // ALLOC_15
}
-#endif // HCF_DL_ONLY
- HCFASSERT( rc == HCF_SUCCESS, rc )
- HCFLOGEXIT( HCF_TRACE_INIT )
+
+ HCFASSERT( rc == HCF_SUCCESS, rc );
+ HCFLOGEXIT( HCF_TRACE_INIT );
return rc;
} // init
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.SUBMODULE void isr_info( IFBP ifbp )
-*.PURPOSE handles link events.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-*1: First the FID number corresponding with the InfoEvent is determined.
-* Note the complication of the zero-FID protection sub-scheme in DAWA.
-* Next the L-field and the T-field are fetched into scratch buffer info.
-*2: In case of tallies, the 16 bits Hermes values are accumulated in the IFB into 32 bits values. Info[0]
-* is (expected to be) HCF_NIC_TAL_CNT + 1. The contraption "while ( info[0]-- >1 )" rather than
-* "while ( --info[0] )" is used because it is dangerous to determine the length of the Value field by
-* decrementing info[0]. As a result of a bug in some version of the F/W, info[0] may be 0, resulting
-* in a very long loop in the pre-decrement logic.
-*4: In case of a link status frame, the information is copied to the IFB field IFB_linkStat
-*6: All other than Tallies (including "unknown" ones) are checked against the selection set by the MSF
-* via CFG_RID_LOG. If a match is found or the selection set has the wild-card type (i.e non-NULL buffer
-* pointer at the terminating zero-type), the frame is copied to the (type-specific) log buffer.
-* Note that to accumulate tallies into IFB AND to log them or to log a frame when a specific match occures
-* AND based on the wild-card selection, you have to call setup_bap again after the 1st copy.
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void isr_info( IFBP ifbp )
+ *.PURPOSE handles link events.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ *1: First the FID number corresponding with the InfoEvent is determined.
+ * Note the complication of the zero-FID protection sub-scheme in DAWA.
+ * Next the L-field and the T-field are fetched into scratch buffer info.
+ *2: In case of tallies, the 16 bits Hermes values are accumulated in the IFB into 32 bits values. Info[0]
+ * is (expected to be) HCF_NIC_TAL_CNT + 1. The contraption "while ( info[0]-- >1 )" rather than
+ * "while ( --info[0] )" is used because it is dangerous to determine the length of the Value field by
+ * decrementing info[0]. As a result of a bug in some version of the F/W, info[0] may be 0, resulting
+ * in a very long loop in the pre-decrement logic.
+ *4: In case of a link status frame, the information is copied to the IFB field IFB_linkStat
+ *6: All other than Tallies (including "unknown" ones) are checked against the selection set by the MSF
+ * via CFG_RID_LOG. If a match is found or the selection set has the wild-card type (i.e non-NULL buffer
+ * pointer at the terminating zero-type), the frame is copied to the (type-specific) log buffer.
+ * Note that to accumulate tallies into IFB AND to log them or to log a frame when a specific match occures
+ * AND based on the wild-card selection, you have to call setup_bap again after the 1st copy.
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC void
isr_info( IFBP ifbp )
{
-hcf_16 info[2], fid;
+ hcf_16 info[2], fid;
#if (HCF_EXT) & HCF_EXT_INFO_LOG
-RID_LOGP ridp = ifbp->IFB_RIDLogp; //NULL or pointer to array of RID_LOG structures (terminated by zero typ)
+ RID_LOGP ridp = ifbp->IFB_RIDLogp; //NULL or pointer to array of RID_LOG structures (terminated by zero typ)
#endif // HCF_EXT_INFO_LOG
- HCFTRACE( ifbp, HCF_TRACE_ISR_INFO ); /* 1 */
+ HCFTRACE( ifbp, HCF_TRACE_ISR_INFO ); /* 1 */
fid = IPW( HREG_INFO_FID );
- DAWA_ZERO_FID( HREG_INFO_FID )
+ DAWA_ZERO_FID( HREG_INFO_FID );
if ( fid ) {
(void)setup_bap( ifbp, fid, 0, IO_IN );
get_frag( ifbp, (wci_bufp)info, 4 BE_PAR(2) );
- HCFASSERT( info[0] <= HCF_MAX_LTV + 1, MERGE_2( info[1], info[0] ) ) //;? a smaller value makes more sense
-#if (HCF_TALLIES) & HCF_TALLIES_NIC //Hermes tally support
+ HCFASSERT( info[0] <= HCF_MAX_LTV + 1, MERGE_2( info[1], info[0] ) ); //;? a smaller value makes more sense
+#if (HCF_TALLIES) & HCF_TALLIES_NIC //Hermes tally support
if ( info[1] == CFG_TALLIES ) {
-hcf_32 *p;
-/*2*/ if ( info[0] > HCF_NIC_TAL_CNT ) {
+ hcf_32 *p;
+ /*2*/ if ( info[0] > HCF_NIC_TAL_CNT ) {
info[0] = HCF_NIC_TAL_CNT + 1;
}
p = (hcf_32*)&ifbp->IFB_NIC_Tallies;
- while ( info[0]-- >1 ) *p++ += IPW( HREG_DATA_1 ); //request may return zero length
+ while ( info[0]-- >1 ) *p++ += IPW( HREG_DATA_1 ); //request may return zero length
}
else
#endif // HCF_TALLIES_NIC
{
-/*4*/ if ( info[1] == CFG_LINK_STAT ) {
+ /*4*/ if ( info[1] == CFG_LINK_STAT ) {
ifbp->IFB_LinkStat = IPW( HREG_DATA_1 );
}
#if (HCF_EXT) & HCF_EXT_INFO_LOG
-/*6*/ while ( 1 ) {
+ /*6*/ while ( 1 ) {
if ( ridp->typ == 0 || ridp->typ == info[1] ) {
if ( ridp->bufp ) {
- HCFASSERT( ridp->len >= 2, ridp->typ )
- ridp->bufp[0] = min((hcf_16)(ridp->len - 1), info[0] ); //save L
- ridp->bufp[1] = info[1]; //save T
+ HCFASSERT( ridp->len >= 2, ridp->typ );
+ ridp->bufp[0] = min((hcf_16)(ridp->len - 1), info[0] ); //save L
+ ridp->bufp[1] = info[1]; //save T
get_frag( ifbp, (wci_bufp)&ridp->bufp[2], (ridp->bufp[0] - 1)*2 BE_PAR(0) );
}
break;
@@ -4346,84 +4213,82 @@ hcf_32 *p;
}
return;
} // isr_info
-#endif // HCF_DL_ONLY
//
//
// #endif // HCF_TALLIES_NIC
-// /*4*/ if ( info[1] == CFG_LINK_STAT ) {
-// ifbp->IFB_DSLinkStat = IPW( HREG_DATA_1 ) | CFG_LINK_STAT_CHANGE; //corrupts BAP !! ;?
-// ifbp->IFB_LinkStat = ifbp->IFB_DSLinkStat & CFG_LINK_STAT_FW; //;? to be obsoleted
-// printk( "<4>linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day
+// /*4*/ if ( info[1] == CFG_LINK_STAT ) {
+// ifbp->IFB_DSLinkStat = IPW( HREG_DATA_1 ) | CFG_LINK_STAT_CHANGE; //corrupts BAP !! ;?
+// ifbp->IFB_LinkStat = ifbp->IFB_DSLinkStat & CFG_LINK_STAT_FW; //;? to be obsoleted
+// printk( "<4>linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day
// #if (HCF_SLEEP) & HCF_DDS
-// if ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) { //even values are disconnected etc.
-// ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty)
-// printk( "<5>isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day
-// }
+// if ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) { //even values are disconnected etc.
+// ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty)
+// printk( "<5>isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day
+// }
// #endif // HCF_DDS
-// }
+// }
// #if (HCF_EXT) & HCF_EXT_INFO_LOG
-// /*6*/ while ( 1 ) {
-// if ( ridp->typ == 0 || ridp->typ == info[1] ) {
-// if ( ridp->bufp ) {
-// HCFASSERT( ridp->len >= 2, ridp->typ )
-// (void)setup_bap( ifbp, fid, 2, IO_IN ); //restore BAP for tallies, linkstat and specific type followed by wild card
-// ridp->bufp[0] = min( ridp->len - 1, info[0] ); //save L
-// get_frag( ifbp, (wci_bufp)&ridp->bufp[1], ridp->bufp[0]*2 BE_PAR(0) );
-// }
-// break; //;?this break is no longer needed due to setup_bap but lets concentrate on DDS first
-// }
-// ridp++;
-// }
+// /*6*/ while ( 1 ) {
+// if ( ridp->typ == 0 || ridp->typ == info[1] ) {
+// if ( ridp->bufp ) {
+// HCFASSERT( ridp->len >= 2, ridp->typ );
+// (void)setup_bap( ifbp, fid, 2, IO_IN ); //restore BAP for tallies, linkstat and specific type followed by wild card
+// ridp->bufp[0] = min( ridp->len - 1, info[0] ); //save L
+// get_frag( ifbp, (wci_bufp)&ridp->bufp[1], ridp->bufp[0]*2 BE_PAR(0) );
+// }
+// break; //;?this break is no longer needed due to setup_bap but lets concentrate on DDS first
+// }
+// ridp++;
+// }
// #endif // HCF_EXT_INFO_LOG
-// }
-// HCFTRACE( ifbp, HCF_TRACE_ISR_INFO | HCF_TRACE_EXIT );
+// }
+// HCFTRACE( ifbp, HCF_TRACE_ISR_INFO | HCF_TRACE_EXIT );
//
//
//
//
-// return;
+// return;
//} // isr_info
-//#endif // HCF_DL_ONLY
/************************************************************************************************************
-*
-*.SUBMODULE void mdd_assert( IFBP ifbp, unsigned int line_number, hcf_32 q )
-*.PURPOSE filters assert on level and interfaces to the MSF supplied msf_assert routine.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* line_number line number of the line which caused the assert
-* q qualifier, additional information which may give a clue about the problem
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-*
-*.NOTICE
-* mdd_assert has been through a turmoil, renaming hcf_assert to assert and hcf_assert again and supporting off
-* and on being called from the MSF level and other ( immature ) ModularDriverDevelopment modules like DHF and
-* MMD.
+ *
+ *.SUBMODULE void mdd_assert( IFBP ifbp, unsigned int line_number, hcf_32 q )
+ *.PURPOSE filters assert on level and interfaces to the MSF supplied msf_assert routine.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * line_number line number of the line which caused the assert
+ * q qualifier, additional information which may give a clue about the problem
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ * mdd_assert has been through a turmoil, renaming hcf_assert to assert and hcf_assert again and supporting off
+ * and on being called from the MSF level and other ( immature ) ModularDriverDevelopment modules like DHF and
+ * MMD.
* !!!! The assert routine is not an hcf_..... routine in the sense that it may be called by the MSF,
- * however it is called from mmd.c and dhf.c, so it must be external.
- * To prevent namespace pollution it needs a prefix, to prevent that MSF programmers think that
- * they are allowed to call the assert logic, the prefix HCF can't be used, so MDD is selected!!!!
+ * however it is called from mmd.c and dhf.c, so it must be external.
+ * To prevent namespace pollution it needs a prefix, to prevent that MSF programmers think that
+ * they are allowed to call the assert logic, the prefix HCF can't be used, so MDD is selected!!!!
*
-* When called from the DHF module the line number is incremented by DHF_FILE_NAME_OFFSET and when called from
-* the MMD module by MMD_FILE_NAME_OFFSET.
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ * When called from the DHF module the line number is incremented by DHF_FILE_NAME_OFFSET and when called from
+ * the MMD module by MMD_FILE_NAME_OFFSET.
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
#if HCF_ASSERT
void
mdd_assert( IFBP ifbp, unsigned int line_number, hcf_32 q )
{
-hcf_16 run_time_flag = ifbp->IFB_AssertLvl;
+ hcf_16 run_time_flag = ifbp->IFB_AssertLvl;
if ( run_time_flag /* > ;?????? */ ) { //prevent recursive behavior, later to be extended to level filtering
ifbp->IFB_AssertQualifier = q;
@@ -4440,74 +4305,74 @@ hcf_16 run_time_flag = ifbp->IFB_AssertLvl;
OPW( HREG_SW_2, (hcf_16)(q >> 16 ) );
#endif // HCF_ASSERT_SW_SUP
-#if (HCF_EXT) & HCF_EXT_MB && (HCF_ASSERT) & HCF_ASSERT_MB
- ifbp->IFB_AssertLvl = 0; // prevent recursive behavior
+#if (HCF_ASSERT) & HCF_ASSERT_MB
+ ifbp->IFB_AssertLvl = 0; // prevent recursive behavior
hcf_put_info( ifbp, (LTVP)&ifbp->IFB_AssertStrct );
- ifbp->IFB_AssertLvl = run_time_flag; // restore appropriate filter level
-#endif // HCF_EXT_MB / HCF_ASSERT_MB
+ ifbp->IFB_AssertLvl = run_time_flag; // restore appropriate filter level
+#endif // HCF_ASSERT_MB
}
} // mdd_assert
#endif // HCF_ASSERT
/************************************************************************************************************
-*
-*.SUBMODULE void put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
-*.PURPOSE writes with 16/32 bit I/O via BAP1 port from Host memory to NIC RAM.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* bufp (byte) address of buffer
-* len length in bytes of buffer specified by bufp
-* word_len Big Endian only: number of leading bytes to swap in pairs
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* process the single byte (if applicable) not yet written by the previous put_frag and copy len
-* (or len-1) bytes from bufp to NIC.
-*
-*
-*.DIAGRAM
-*
-*.NOTICE
-* It turns out DOS ODI uses zero length fragments. The HCF code can cope with it, but as a consequence, no
-* Assert on len is possible
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
+ *.PURPOSE writes with 16/32 bit I/O via BAP1 port from Host memory to NIC RAM.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * bufp (byte) address of buffer
+ * len length in bytes of buffer specified by bufp
+ * word_len Big Endian only: number of leading bytes to swap in pairs
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * process the single byte (if applicable) not yet written by the previous put_frag and copy len
+ * (or len-1) bytes from bufp to NIC.
+ *
+ *
+ *.DIAGRAM
+ *
+ *.NOTICE
+ * It turns out DOS ODI uses zero length fragments. The HCF code can cope with it, but as a consequence, no
+ * Assert on len is possible
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC void
put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
{
-hcf_io io_port = ifbp->IFB_IOBase + HREG_DATA_1; //BAP data register
-int i; //prevent side effects from macro
-hcf_16 j;
- HCFASSERT( ((hcf_32)bufp & (HCF_ALIGN-1) ) == 0, (hcf_32)bufp )
+ hcf_io io_port = ifbp->IFB_IOBase + HREG_DATA_1; //BAP data register
+ int i; //prevent side effects from macro
+ hcf_16 j;
+ HCFASSERT( ((hcf_32)bufp & (HCF_ALIGN-1) ) == 0, (hcf_32)bufp );
#if HCF_BIG_ENDIAN
- HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len )
- HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp )
- HCFASSERT( word_len <= len, MERGE_2( word_len, len ) )
+ HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len );
+ HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp );
+ HCFASSERT( word_len <= len, MERGE_2( word_len, len ) );
- if ( word_len ) { //if there is anything to convert
- //. convert and write the 1st hcf_16
+ if ( word_len ) { //if there is anything to convert
+ //. convert and write the 1st hcf_16
j = bufp[1] | bufp[0]<<8;
OUT_PORT_WORD( io_port, j );
- //. update pointer and counter accordingly
+ //. update pointer and counter accordingly
len -= 2;
bufp += 2;
- if ( word_len > 1 ) { //. if there is to convert more than 1 word ( i.e 2 )
- //. . convert and write the 2nd hcf_16
- j = bufp[1] | bufp[0]<<8; /*bufp is already incremented by 2*/
+ if ( word_len > 1 ) { //. if there is to convert more than 1 word ( i.e 2 )
+ //. . convert and write the 2nd hcf_16
+ j = bufp[1] | bufp[0]<<8; /*bufp is already incremented by 2*/
OUT_PORT_WORD( io_port, j );
- //. . update pointer and counter accordingly
+ //. . update pointer and counter accordingly
len -= 2;
bufp += 2;
}
}
#endif // HCF_BIG_ENDIAN
i = len;
- if ( i && ifbp->IFB_CarryOut ) { //skip zero-length
+ if ( i && ifbp->IFB_CarryOut ) { //skip zero-length
j = ((*bufp)<<8) + ( ifbp->IFB_CarryOut & 0xFF );
OUT_PORT_WORD( io_port, j );
bufp++; i--;
@@ -4515,35 +4380,35 @@ hcf_16 j;
}
#if (HCF_IO) & HCF_IO_32BITS
//skip zero-length I/O, single byte I/O and I/O not worthwhile (i.e. less than 6 bytes)for DW logic
- //if buffer length >= 6 and 32 bits I/O support
+ //if buffer length >= 6 and 32 bits I/O support
if ( !(ifbp->IFB_CntlOpt & USE_16BIT) && i >= 6 ) {
-hcf_32 FAR *p4; //prevent side effects from macro
- if ( ( (hcf_32)bufp & 0x1 ) == 0 ) { //. if buffer at least word aligned
- if ( (hcf_32)bufp & 0x2 ) { //. . if buffer not double word aligned
- //. . . write a single word to get double word aligned
- j = *(wci_recordp)bufp; //just to help ease writing macros with embedded assembly
+ hcf_32 FAR *p4; //prevent side effects from macro
+ if ( ( (hcf_32)bufp & 0x1 ) == 0 ) { //. if buffer at least word aligned
+ if ( (hcf_32)bufp & 0x2 ) { //. . if buffer not double word aligned
+ //. . . write a single word to get double word aligned
+ j = *(wci_recordp)bufp; //just to help ease writing macros with embedded assembly
OUT_PORT_WORD( io_port, j );
- //. . . adjust buffer length and pointer accordingly
+ //. . . adjust buffer length and pointer accordingly
bufp += 2; i -= 2;
}
- //. . write as many double word as possible
+ //. . write as many double word as possible
p4 = (hcf_32 FAR *)bufp;
j = (hcf_16)i/4;
OUT_PORT_STRING_32( io_port, p4, j );
- //. . adjust buffer length and pointer accordingly
+ //. . adjust buffer length and pointer accordingly
bufp += i & ~0x0003;
i &= 0x0003;
}
}
#endif // HCF_IO_32BITS
- //if no 32-bit support OR byte aligned OR 1 word left
+ //if no 32-bit support OR byte aligned OR 1 word left
if ( i ) {
- //. if odd number of bytes left
+ //. if odd number of bytes left
if ( i & 0x0001 ) {
- //. . save left over byte (before bufp is corrupted) in carry, set carry flag
- ifbp->IFB_CarryOut = (hcf_16)bufp[i-1] | 0x0100; //note that i and bufp are always simultaneously modified, &bufp[i-1] is invariant
+ //. . save left over byte (before bufp is corrupted) in carry, set carry flag
+ ifbp->IFB_CarryOut = (hcf_16)bufp[i-1] | 0x0100; //note that i and bufp are always simultaneously modified, &bufp[i-1] is invariant
}
- //. write as many word as possible in "alignment safe" way
+ //. write as many word as possible in "alignment safe" way
j = (hcf_16)i/2;
OUT_PORT_STRING_8_16( io_port, bufp, j );
}
@@ -4551,117 +4416,117 @@ hcf_32 FAR *p4; //prevent side effects from macro
/************************************************************************************************************
-*
-*.SUBMODULE void put_frag_finalize( IFBP ifbp )
-*.PURPOSE cleanup after put_frag for trailing odd byte and MIC transfer to NIC.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-*
-*.RETURNS N.A.
-*
-*.DESCRIPTION
-* finalize the MIC calculation with the padding pattern, output the last byte (if applicable)
-* of the message and the MIC to the TxFS
-*
-*
-*.DIAGRAM
-*2: 1 byte of the last put_frag may be still in IFB_CarryOut ( the put_frag carry holder ), so ........
-* 1 - 3 bytes of the last put_frag may be still in IFB_tx_32 ( the MIC engine carry holder ), so ........
-* The call to the MIC calculation routine feeds these remaining bytes (if any) of put_frag and the
-* just as many bytes of the padding as needed to the MIC calculation engine. Note that the "unneeded" pad
-* bytes simply end up in the MIC engine carry holder and are never used.
-*8: write the remainder of the MIC and possible some garbage to NIC RAM
-* Note: i is always 4 (a loop-invariant of the while in point 2)
-*
-*.NOTICE
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE void put_frag_finalize( IFBP ifbp )
+ *.PURPOSE cleanup after put_frag for trailing odd byte and MIC transfer to NIC.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ *
+ *.RETURNS N.A.
+ *
+ *.DESCRIPTION
+ * finalize the MIC calculation with the padding pattern, output the last byte (if applicable)
+ * of the message and the MIC to the TxFS
+ *
+ *
+ *.DIAGRAM
+ *2: 1 byte of the last put_frag may be still in IFB_CarryOut ( the put_frag carry holder ), so ........
+ * 1 - 3 bytes of the last put_frag may be still in IFB_tx_32 ( the MIC engine carry holder ), so ........
+ * The call to the MIC calculation routine feeds these remaining bytes (if any) of put_frag and the
+ * just as many bytes of the padding as needed to the MIC calculation engine. Note that the "unneeded" pad
+ * bytes simply end up in the MIC engine carry holder and are never used.
+ *8: write the remainder of the MIC and possible some garbage to NIC RAM
+ * Note: i is always 4 (a loop-invariant of the while in point 2)
+ *
+ *.NOTICE
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC void
put_frag_finalize( IFBP ifbp )
{
#if (HCF_TYPE) & HCF_TYPE_WPA
- if ( ifbp->IFB_MICTxCarry != 0xFFFF) { //if MIC calculation active
- CALC_TX_MIC( mic_pad, 8); //. feed (up to 8 bytes of) virtual padding to MIC engine
- //. write (possibly) trailing byte + (most of) MIC
+ if ( ifbp->IFB_MICTxCarry != 0xFFFF) { //if MIC calculation active
+ CALC_TX_MIC( mic_pad, 8); //. feed (up to 8 bytes of) virtual padding to MIC engine
+ //. write (possibly) trailing byte + (most of) MIC
put_frag( ifbp, (wci_bufp)ifbp->IFB_MICTx, 8 BE_PAR(0) );
}
#endif // HCF_TYPE_WPA
- put_frag( ifbp, null_addr, 1 BE_PAR(0) ); //write (possibly) trailing data or MIC byte
+ put_frag( ifbp, null_addr, 1 BE_PAR(0) ); //write (possibly) trailing data or MIC byte
} // put_frag_finalize
/************************************************************************************************************
-*
-*.SUBMODULE int put_info( IFBP ifbp, LTVP ltvp )
-*.PURPOSE support routine to handle the "basic" task of hcf_put_info to pass RIDs to the NIC.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* ltvp address in NIC RAM where LVT-records are located
-*
-*.RETURNS
-* HCF_SUCCESS
-* >>put_frag
-* >>cmd_wait
-*
-*.DESCRIPTION
-*
-*
-*.DIAGRAM
-*20: do not write RIDs to NICs which have incompatible Firmware
-*24: If the RID does not exist, the L-field is set to zero.
-* Note that some RIDs can not be read, e.g. the pseudo RIDs for direct Hermes commands and CFG_DEFAULT_KEYS
-*28: If the RID is written successful, pass it to the NIC by means of an Access Write command
-*
-*.NOTICE
-* The mechanism to HCF_ASSERT on invalid typ-codes in the LTV record is based on the following strategy:
-* - some codes (e.g. CFG_REG_MB) are explicitly handled by the HCF which implies that these codes
-* are valid. These codes are already consumed by hcf_put_info.
-* - all other codes are passed to the Hermes. Before the put action is executed, hcf_get_info is called
-* with an LTV record with a value of 1 in the L-field and the intended put action type in the Typ-code
-* field. If the put action type is valid, it is also valid as a get action type code - except
-* for CFG_DEFAULT_KEYS and CFG_ADD_TKIP_DEFAULT_KEY - so the HCF_ASSERT logic of hcf_get_info should
-* not catch.
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int put_info( IFBP ifbp, LTVP ltvp )
+ *.PURPOSE support routine to handle the "basic" task of hcf_put_info to pass RIDs to the NIC.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * ltvp address in NIC RAM where LVT-records are located
+ *
+ *.RETURNS
+ * HCF_SUCCESS
+ * >>put_frag
+ * >>cmd_wait
+ *
+ *.DESCRIPTION
+ *
+ *
+ *.DIAGRAM
+ *20: do not write RIDs to NICs which have incompatible Firmware
+ *24: If the RID does not exist, the L-field is set to zero.
+ * Note that some RIDs can not be read, e.g. the pseudo RIDs for direct Hermes commands and CFG_DEFAULT_KEYS
+ *28: If the RID is written successful, pass it to the NIC by means of an Access Write command
+ *
+ *.NOTICE
+ * The mechanism to HCF_ASSERT on invalid typ-codes in the LTV record is based on the following strategy:
+ * - some codes (e.g. CFG_REG_MB) are explicitly handled by the HCF which implies that these codes
+ * are valid. These codes are already consumed by hcf_put_info.
+ * - all other codes are passed to the Hermes. Before the put action is executed, hcf_get_info is called
+ * with an LTV record with a value of 1 in the L-field and the intended put action type in the Typ-code
+ * field. If the put action type is valid, it is also valid as a get action type code - except
+ * for CFG_DEFAULT_KEYS and CFG_ADD_TKIP_DEFAULT_KEY - so the HCF_ASSERT logic of hcf_get_info should
+ * not catch.
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
-put_info( IFBP ifbp, LTVP ltvp )
+put_info( IFBP ifbp, LTVP ltvp )
{
-int rc = HCF_SUCCESS;
+ int rc = HCF_SUCCESS;
- HCFASSERT( ifbp->IFB_CardStat == 0, MERGE_2( ltvp->typ, ifbp->IFB_CardStat ) )
- HCFASSERT( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX, ltvp->typ )
+ HCFASSERT( ifbp->IFB_CardStat == 0, MERGE_2( ltvp->typ, ifbp->IFB_CardStat ) );
+ HCFASSERT( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX, ltvp->typ );
- if ( ifbp->IFB_CardStat == 0 && /* 20*/
- ( ( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX ) ||
- ( CFG_RID_ENG_MIN <= ltvp->typ /* && ltvp->typ <= 0xFFFF */ ) ) ) {
+ if ( ifbp->IFB_CardStat == 0 && /* 20*/
+ ( ( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX ) ||
+ ( CFG_RID_ENG_MIN <= ltvp->typ /* && ltvp->typ <= 0xFFFF */ ) ) ) {
#if HCF_ASSERT //FCC8, FCB0, FCB4, FCB6, FCB7, FCB8, FCC0, FCC4, FCBC, FCBD, FCBE, FCBF
- {
- hcf_16 t = ltvp->typ;
- LTV_STRCT x = { 2, t, {0} }; /*24*/
- hcf_get_info( ifbp, (LTVP)&x );
- if ( x.len == 0 &&
- ( t != CFG_DEFAULT_KEYS && t != CFG_ADD_TKIP_DEFAULT_KEY && t != CFG_REMOVE_TKIP_DEFAULT_KEY &&
- t != CFG_ADD_TKIP_MAPPED_KEY && t != CFG_REMOVE_TKIP_MAPPED_KEY &&
- t != CFG_HANDOVER_ADDR && t != CFG_DISASSOCIATE_ADDR &&
- t != CFG_FCBC && t != CFG_FCBD && t != CFG_FCBE && t != CFG_FCBF &&
- t != CFG_DEAUTHENTICATE_ADDR
- )
- ) {
- HCFASSERT( DO_ASSERT, ltvp->typ )
+ {
+ hcf_16 t = ltvp->typ;
+ LTV_STRCT x = { 2, t, {0} }; /*24*/
+ hcf_get_info( ifbp, (LTVP)&x );
+ if ( x.len == 0 &&
+ ( t != CFG_DEFAULT_KEYS && t != CFG_ADD_TKIP_DEFAULT_KEY && t != CFG_REMOVE_TKIP_DEFAULT_KEY &&
+ t != CFG_ADD_TKIP_MAPPED_KEY && t != CFG_REMOVE_TKIP_MAPPED_KEY &&
+ t != CFG_HANDOVER_ADDR && t != CFG_DISASSOCIATE_ADDR &&
+ t != CFG_FCBC && t != CFG_FCBD && t != CFG_FCBE && t != CFG_FCBF &&
+ t != CFG_DEAUTHENTICATE_ADDR
+ )
+ ) {
+ HCFASSERT( DO_ASSERT, ltvp->typ );
+ }
}
- }
#endif // HCF_ASSERT
rc = setup_bap( ifbp, ltvp->typ, 0, IO_OUT );
put_frag( ifbp, (wci_bufp)ltvp, 2*ltvp->len + 2 BE_PAR(2) );
-/*28*/ if ( rc == HCF_SUCCESS ) {
+ /*28*/ if ( rc == HCF_SUCCESS ) {
rc = cmd_exe( ifbp, HCMD_ACCESS + HCMD_ACCESS_WRITE, ltvp->typ );
}
}
@@ -4669,214 +4534,209 @@ int rc = HCF_SUCCESS;
} // put_info
-#if (HCF_DL_ONLY) == 0
/************************************************************************************************************
-*
-*.SUBMODULE int put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp )
-*.PURPOSE accumulates a ( series of) buffers into a single Info block into the MailBox.
-*
-*.ARGUMENTS
-* ifbp address of the Interface Block
-* ltvp address of structure specifying the "type" and the fragments of the information to be synthesized
-* as an LTV into the MailBox
-*
-*.RETURNS
-*
-*.DESCRIPTION
-* If the data does not fit (including no MailBox is available), the IFB_MBTally is incremented and an
-* error status is returned.
-* HCF_ASSERT does not catch.
-* Calling put_info_mb when their is no MailBox available, is considered a design error in the MSF.
-*
-* Note that there is always at least 1 word of unused space in the mail box.
-* As a consequence:
-* - no problem in pointer arithmetic (MB_RP == MB_WP means unambiguously mail box is completely empty
-* - There is always free space to write an L field with a value of zero after each MB_Info block. This
-* allows for an easy scan mechanism in the "get MB_Info block" logic.
-*
-*
-*.DIAGRAM
-*1: Calculate L field of the MBIB, i.e. 1 for the T-field + the cumulative length of the fragments.
-*2: The free space in the MailBox is calculated (2a: free part from Write Ptr to Read Ptr, 2b: free part
-* turns out to wrap around) . If this space suffices to store the number of words reflected by len (T-field
-* + Value-field) plus the additional MailBox Info L-field + a trailing 0 to act as the L-field of a trailing
-* dummy or empty LTV record, then a MailBox Info block is build in the MailBox consisting of
-* - the value len in the first word
-* - type in the second word
-* - a copy of the contents of the fragments in the second and higher word
-*
-*4: Since put_info_mb() can more or less directly be called from the MSF level, the I/F must be robust
-* against out-of-range variables. As failsafe coding, the MB update is skipped by changing tlen to 0 if
-* len == 0; This will indirectly cause an assert as result of the violation of the next if clause.
-*6: Check whether the free space in MailBox suffices (this covers the complete absence of the MailBox).
-* Note that len is unsigned, so even MSF I/F violation works out O.K.
-* The '2' in the expression "len+2" is used because 1 word is needed for L itself and 1 word is needed
-* for the zero-sentinel
-*8: update MailBox Info length report to MSF with "oldest" MB Info Block size. Be careful here, if you get
-* here before the MailBox is registered, you can't read from the buffer addressed by IFB_MBp (it is the
-* Null buffer) so don't move this code till the end of this routine but keep it where there is garuanteed
-* a buffer.
-*
-*.NOTICE
-* boundary testing depends on the fact that IFB_MBSize is guaranteed to be zero if no MailBox is present,
-* and to a lesser degree, that IFB_MBWp = IFB_MBRp = 0
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
-#if (HCF_EXT) & HCF_EXT_MB
+ *
+ *.SUBMODULE int put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp )
+ *.PURPOSE accumulates a ( series of) buffers into a single Info block into the MailBox.
+ *
+ *.ARGUMENTS
+ * ifbp address of the Interface Block
+ * ltvp address of structure specifying the "type" and the fragments of the information to be synthesized
+ * as an LTV into the MailBox
+ *
+ *.RETURNS
+ *
+ *.DESCRIPTION
+ * If the data does not fit (including no MailBox is available), the IFB_MBTally is incremented and an
+ * error status is returned.
+ * HCF_ASSERT does not catch.
+ * Calling put_info_mb when their is no MailBox available, is considered a design error in the MSF.
+ *
+ * Note that there is always at least 1 word of unused space in the mail box.
+ * As a consequence:
+ * - no problem in pointer arithmetic (MB_RP == MB_WP means unambiguously mail box is completely empty
+ * - There is always free space to write an L field with a value of zero after each MB_Info block. This
+ * allows for an easy scan mechanism in the "get MB_Info block" logic.
+ *
+ *
+ *.DIAGRAM
+ *1: Calculate L field of the MBIB, i.e. 1 for the T-field + the cumulative length of the fragments.
+ *2: The free space in the MailBox is calculated (2a: free part from Write Ptr to Read Ptr, 2b: free part
+ * turns out to wrap around) . If this space suffices to store the number of words reflected by len (T-field
+ * + Value-field) plus the additional MailBox Info L-field + a trailing 0 to act as the L-field of a trailing
+ * dummy or empty LTV record, then a MailBox Info block is build in the MailBox consisting of
+ * - the value len in the first word
+ * - type in the second word
+ * - a copy of the contents of the fragments in the second and higher word
+ *
+ *4: Since put_info_mb() can more or less directly be called from the MSF level, the I/F must be robust
+ * against out-of-range variables. As failsafe coding, the MB update is skipped by changing tlen to 0 if
+ * len == 0; This will indirectly cause an assert as result of the violation of the next if clause.
+ *6: Check whether the free space in MailBox suffices (this covers the complete absence of the MailBox).
+ * Note that len is unsigned, so even MSF I/F violation works out O.K.
+ * The '2' in the expression "len+2" is used because 1 word is needed for L itself and 1 word is needed
+ * for the zero-sentinel
+ *8: update MailBox Info length report to MSF with "oldest" MB Info Block size. Be careful here, if you get
+ * here before the MailBox is registered, you can't read from the buffer addressed by IFB_MBp (it is the
+ * Null buffer) so don't move this code till the end of this routine but keep it where there is garuanteed
+ * a buffer.
+ *
+ *.NOTICE
+ * boundary testing depends on the fact that IFB_MBSize is guaranteed to be zero if no MailBox is present,
+ * and to a lesser degree, that IFB_MBWp = IFB_MBRp = 0
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp )
{
-int rc = HCF_SUCCESS;
-hcf_16 i; //work counter
-hcf_16 *dp; //destination pointer (in MailBox)
-wci_recordp sp; //source pointer
-hcf_16 len; //total length to copy to MailBox
-hcf_16 tlen; //free length/working length/offset in WMP frame
+ int rc = HCF_SUCCESS;
+ hcf_16 i; //work counter
+ hcf_16 *dp; //destination pointer (in MailBox)
+ wci_recordp sp; //source pointer
+ hcf_16 len; //total length to copy to MailBox
+ hcf_16 tlen; //free length/working length/offset in WMP frame
if ( ifbp->IFB_MBp == NULL ) return rc; //;?not sufficient
- HCFASSERT( ifbp->IFB_MBp != NULL, 0 ) //!!!be careful, don't get into an endless recursion
- HCFASSERT( ifbp->IFB_MBSize, 0 )
+ HCFASSERT( ifbp->IFB_MBp != NULL, 0 ); //!!!be careful, don't get into an endless recursion
+ HCFASSERT( ifbp->IFB_MBSize, 0 );
- len = 1; /* 1 */
+ len = 1; /* 1 */
for ( i = 0; i < ltvp->frag_cnt; i++ ) {
len += ltvp->frag_buf[i].frag_len;
}
if ( ifbp->IFB_MBRp > ifbp->IFB_MBWp ) {
- tlen = ifbp->IFB_MBRp - ifbp->IFB_MBWp; /* 2a*/
+ tlen = ifbp->IFB_MBRp - ifbp->IFB_MBWp; /* 2a*/
} else {
if ( ifbp->IFB_MBRp == ifbp->IFB_MBWp ) {
- ifbp->IFB_MBRp = ifbp->IFB_MBWp = 0; // optimize Wrapping
+ ifbp->IFB_MBRp = ifbp->IFB_MBWp = 0; // optimize Wrapping
}
- tlen = ifbp->IFB_MBSize - ifbp->IFB_MBWp; /* 2b*/
- if ( ( tlen <= len + 2 ) && ( len + 2 < ifbp->IFB_MBRp ) ) { //if trailing space is too small but
- // leading space is sufficiently large
- ifbp->IFB_MBp[ifbp->IFB_MBWp] = 0xFFFF; //flag dummy LTV to fill the trailing space
- ifbp->IFB_MBWp = 0; //reset WritePointer to begin of MailBox
- tlen = ifbp->IFB_MBRp; //get new available space size
+ tlen = ifbp->IFB_MBSize - ifbp->IFB_MBWp; /* 2b*/
+ if ( ( tlen <= len + 2 ) && ( len + 2 < ifbp->IFB_MBRp ) ) { //if trailing space is too small but
+ // leading space is sufficiently large
+ ifbp->IFB_MBp[ifbp->IFB_MBWp] = 0xFFFF; //flag dummy LTV to fill the trailing space
+ ifbp->IFB_MBWp = 0; //reset WritePointer to begin of MailBox
+ tlen = ifbp->IFB_MBRp; //get new available space size
}
}
dp = &ifbp->IFB_MBp[ifbp->IFB_MBWp];
if ( len == 0 ) {
tlen = 0; //;? what is this good for
}
- if ( len + 2 >= tlen ){ /* 6 */
+ if ( len + 2 >= tlen ){ /* 6 */
//Do Not ASSERT, this is a normal condition
- IF_TALLY( ifbp->IFB_HCF_Tallies.NoBufMB++; ) /*NOP to cover against analomies with empty compound*/;
+ IF_TALLY( ifbp->IFB_HCF_Tallies.NoBufMB++ );
rc = HCF_ERR_LEN;
} else {
- *dp++ = len; //write Len (= size of T+V in words to MB_Info block
- *dp++ = ltvp->base_typ; //write Type to MB_Info block
- ifbp->IFB_MBWp += len + 1; //update WritePointer of MailBox
- for ( i = 0; i < ltvp->frag_cnt; i++ ) { // process each of the fragments
+ *dp++ = len; //write Len (= size of T+V in words to MB_Info block
+ *dp++ = ltvp->base_typ; //write Type to MB_Info block
+ ifbp->IFB_MBWp += len + 1; //update WritePointer of MailBox
+ for ( i = 0; i < ltvp->frag_cnt; i++ ) { // process each of the fragments
sp = ltvp->frag_buf[i].frag_addr;
len = ltvp->frag_buf[i].frag_len;
while ( len-- ) *dp++ = *sp++;
}
- ifbp->IFB_MBp[ifbp->IFB_MBWp] = 0; //to assure get_info for CFG_MB_INFO stops
- ifbp->IFB_MBInfoLen = ifbp->IFB_MBp[ifbp->IFB_MBRp]; /* 8 */
+ ifbp->IFB_MBp[ifbp->IFB_MBWp] = 0; //to assure get_info for CFG_MB_INFO stops
+ ifbp->IFB_MBInfoLen = ifbp->IFB_MBp[ifbp->IFB_MBRp]; /* 8 */
}
return rc;
} // put_info_mb
-#endif // HCF_EXT_MB
-#endif // HCF_DL_ONLY
-
/************************************************************************************************************
-*
-*.SUBMODULE int setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type )
-*.PURPOSE set up data access to NIC RAM via BAP_1.
-*
-*.ARGUMENTS
-* ifbp address of I/F Block
-* fid FID/RID
-* offset !!even!! offset in FID/RID
-* type IO_IN, IO_OUT
-*
-*.RETURNS
-* HCF_SUCCESS O.K
-* HCF_ERR_NO_NIC card is removed
-* HCF_ERR_DEFUNCT_TIME_OUT Fatal malfunction detected
-* HCF_ERR_DEFUNCT_..... if and only if IFB_DefunctStat <> 0
-*
-*.DESCRIPTION
-*
-* A non-zero return status indicates:
-* - the NIC is considered nonoperational, e.g. due to a time-out of some Hermes activity in the past
-* - BAP_1 could not properly be initialized
-* - the card is removed before completion of the data transfer
-* In all other cases, a zero is returned.
-* BAP Initialization failure indicates an H/W error which is very likely to signal complete H/W failure.
-* Once a BAP Initialization failure has occurred all subsequent interactions with the Hermes will return a
-* "defunct" status till the Hermes is re-initialized by means of an hcf_connect.
-*
-* A BAP is a set of registers (Offset, Select and Data) offering read/write access to a particular FID or
-* RID. This access is based on a auto-increment feature.
-* There are two BAPs but these days the HCF uses only BAP_1 and leaves BAP_0 to the PCI Busmastering H/W.
-*
-* The BAP-mechanism is based on the Busy bit in the Offset register (see the Hermes definition). The waiting
-* for Busy must occur between writing the Offset register and accessing the Data register. The
-* implementation to wait for the Busy bit drop after each write to the Offset register, implies that the
-* requirement that the Busy bit is low before the Select register is written, is automatically met.
-* BAP-setup may be time consuming (e.g. 380 usec for large offsets occurs frequently). The wait for Busy bit
-* drop is protected by a loop counter, which is initialized with IFB_TickIni, which is calibrated in init.
-*
-* The NIC I/F is optimized for word transfer and can only handle word transfer at a word boundary in NIC
-* RAM. The intended solution for transfer of a single byte has multiple H/W flaws. There have been different
-* S/W Workaround strategies. RID access is hcf_16 based by "nature", so no byte access problems. For Tx/Rx
-* FID access, the byte logic became obsolete by absorbing it in the double word oriented nature of the MIC
-* feature.
-*
-*
-*.DIAGRAM
-*
-*2: the test on rc checks whether the HCF went into "defunct" mode ( e.g. BAP initialization or a call to
-* cmd_wait did ever fail).
-*4: the select register and offset register are set
-* the offset register is monitored till a successful condition (no busy bit) is detected or till the
-* (calibrated) protection counter expires
-* If the counter expires, this is reflected in IFB_DefunctStat, so all subsequent calls to setup_bap fail
-* immediately ( see 2)
-*6: initialization of the carry as used by pet/get_frag
-*8: HREG_OFFSET_ERR is ignored as error because:
-* a: the Hermes is robust against it
-* b: it is not known what causes it (probably a bug), hence no strategy can be specified which level is
-* to handle this error in which way. In the past, it could be induced by the MSF level, e.g. by calling
-* hcf_rcv_msg while there was no Rx-FID available. Since this is an MSF-error which is caught by ASSERT,
-* there is no run-time action required by the HCF.
-* Lumping the Offset error in with the Busy bit error, as has been done in the past turns out to be a
-* disaster or a life saver, just depending on what the cause of the error is. Since no prediction can be
-* done about the future, it is "felt" to be the best strategy to ignore this error. One day the code was
-* accompanied by the following comment:
-* // ignore HREG_OFFSET_ERR, someone, supposedly the MSF programmer ;) made a bug. Since we don't know
-* // what is going on, we might as well go on - under management pressure - by ignoring it
-*
-*.ENDDOC END DOCUMENTATION
-*
-************************************************************************************************************/
+ *
+ *.SUBMODULE int setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type )
+ *.PURPOSE set up data access to NIC RAM via BAP_1.
+ *
+ *.ARGUMENTS
+ * ifbp address of I/F Block
+ * fid FID/RID
+ * offset !!even!! offset in FID/RID
+ * type IO_IN, IO_OUT
+ *
+ *.RETURNS
+ * HCF_SUCCESS O.K
+ * HCF_ERR_NO_NIC card is removed
+ * HCF_ERR_DEFUNCT_TIME_OUT Fatal malfunction detected
+ * HCF_ERR_DEFUNCT_..... if and only if IFB_DefunctStat <> 0
+ *
+ *.DESCRIPTION
+ *
+ * A non-zero return status indicates:
+ * - the NIC is considered nonoperational, e.g. due to a time-out of some Hermes activity in the past
+ * - BAP_1 could not properly be initialized
+ * - the card is removed before completion of the data transfer
+ * In all other cases, a zero is returned.
+ * BAP Initialization failure indicates an H/W error which is very likely to signal complete H/W failure.
+ * Once a BAP Initialization failure has occurred all subsequent interactions with the Hermes will return a
+ * "defunct" status till the Hermes is re-initialized by means of an hcf_connect.
+ *
+ * A BAP is a set of registers (Offset, Select and Data) offering read/write access to a particular FID or
+ * RID. This access is based on a auto-increment feature.
+ * There are two BAPs but these days the HCF uses only BAP_1 and leaves BAP_0 to the PCI Busmastering H/W.
+ *
+ * The BAP-mechanism is based on the Busy bit in the Offset register (see the Hermes definition). The waiting
+ * for Busy must occur between writing the Offset register and accessing the Data register. The
+ * implementation to wait for the Busy bit drop after each write to the Offset register, implies that the
+ * requirement that the Busy bit is low before the Select register is written, is automatically met.
+ * BAP-setup may be time consuming (e.g. 380 usec for large offsets occurs frequently). The wait for Busy bit
+ * drop is protected by a loop counter, which is initialized with IFB_TickIni, which is calibrated in init.
+ *
+ * The NIC I/F is optimized for word transfer and can only handle word transfer at a word boundary in NIC
+ * RAM. The intended solution for transfer of a single byte has multiple H/W flaws. There have been different
+ * S/W Workaround strategies. RID access is hcf_16 based by "nature", so no byte access problems. For Tx/Rx
+ * FID access, the byte logic became obsolete by absorbing it in the double word oriented nature of the MIC
+ * feature.
+ *
+ *
+ *.DIAGRAM
+ *
+ *2: the test on rc checks whether the HCF went into "defunct" mode ( e.g. BAP initialization or a call to
+ * cmd_wait did ever fail).
+ *4: the select register and offset register are set
+ * the offset register is monitored till a successful condition (no busy bit) is detected or till the
+ * (calibrated) protection counter expires
+ * If the counter expires, this is reflected in IFB_DefunctStat, so all subsequent calls to setup_bap fail
+ * immediately ( see 2)
+ *6: initialization of the carry as used by pet/get_frag
+ *8: HREG_OFFSET_ERR is ignored as error because:
+ * a: the Hermes is robust against it
+ * b: it is not known what causes it (probably a bug), hence no strategy can be specified which level is
+ * to handle this error in which way. In the past, it could be induced by the MSF level, e.g. by calling
+ * hcf_rcv_msg while there was no Rx-FID available. Since this is an MSF-error which is caught by ASSERT,
+ * there is no run-time action required by the HCF.
+ * Lumping the Offset error in with the Busy bit error, as has been done in the past turns out to be a
+ * disaster or a life saver, just depending on what the cause of the error is. Since no prediction can be
+ * done about the future, it is "felt" to be the best strategy to ignore this error. One day the code was
+ * accompanied by the following comment:
+ * // ignore HREG_OFFSET_ERR, someone, supposedly the MSF programmer ;) made a bug. Since we don't know
+ * // what is going on, we might as well go on - under management pressure - by ignoring it
+ *
+ *.ENDDOC END DOCUMENTATION
+ *
+ ************************************************************************************************************/
HCF_STATIC int
setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type )
{
-PROT_CNT_INI
-int rc;
+ PROT_CNT_INI;
+ int rc;
HCFTRACE( ifbp, HCF_TRACE_STRIO );
rc = ifbp->IFB_DefunctStat;
- if (rc == HCF_SUCCESS) { /*2*/
- OPW( HREG_SELECT_1, fid ); /*4*/
+ if (rc == HCF_SUCCESS) { /*2*/
+ OPW( HREG_SELECT_1, fid ); /*4*/
OPW( HREG_OFFSET_1, offset );
if ( type == IO_IN ) {
ifbp->IFB_CarryIn = 0;
}
else ifbp->IFB_CarryOut = 0;
HCF_WAIT_WHILE( IPW( HREG_OFFSET_1) & HCMD_BUSY );
- HCFASSERT( !( IPW( HREG_OFFSET_1) & HREG_OFFSET_ERR ), MERGE_2( fid, offset ) ) /*8*/
+ HCFASSERT( !( IPW( HREG_OFFSET_1) & HREG_OFFSET_ERR ), MERGE_2( fid, offset ) ); /*8*/
if ( prot_cnt == 0 ) {
- HCFASSERT( DO_ASSERT, MERGE_2( fid, offset ) )
+ HCFASSERT( DO_ASSERT, MERGE_2( fid, offset ) );
rc = ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_TIME_OUT;
ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT;
}
diff --git a/drivers/staging/wlags49_h2/hcf.h b/drivers/staging/wlags49_h2/hcf.h
index 2cd5739..0009947 100644
--- a/drivers/staging/wlags49_h2/hcf.h
+++ b/drivers/staging/wlags49_h2/hcf.h
@@ -301,13 +301,11 @@ typedef struct {
#if (HCF_EXT) & HCF_EXT_INT_TICK
int IFB_TickCnt; // Hermes Timer Tick Counter
#endif // HCF_EXT_INT_TICK
-#if (HCF_EXT) & HCF_EXT_MB
hcf_16 *IFB_MBp; // pointer to the MailBox
hcf_16 IFB_MBSize; // size of the MailBox
hcf_16 IFB_MBWp; // zero-based write index into the MailBox
hcf_16 IFB_MBRp; // zero-based read index into the MailBox
hcf_16 IFB_MBInfoLen; // contents of L-field of the oldest available MailBoxInfoBlock
-#endif // HCF_EXT_MB
#if (HCF_TYPE) & HCF_TYPE_WPA
hcf_16 IFB_MICTxCntl; // MIC bit and Key index in TxControl field of TxFS
hcf_32 IFB_MICTxKey[2]; // calculating key
@@ -335,12 +333,7 @@ typedef struct {
CFG_FW_PRINTF_BUFFER_LOCATION_STRCT IFB_FwPfBuff;
#endif // HCF_ASSERT_PRINTF
#endif // HCF_ASSERT
-#if ! defined HCF_INT_OFF
hcf_16 volatile IFB_IntOffCnt; // 0xFFFF based HCF_ACT_INT_OFF nesting counter, DeepSleep flag
-#endif // HCF_INT_OFF
-#if (HCF_TYPE) & HCF_TYPE_CCX
- hcf_16 IFB_CKIPStat; // CKIP Status flag
-#endif // HCF_TYPE_CCX
#if (HCF_TALLIES) & ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) //Hermes and/or HCF tally support
hcf_32 IFB_Silly_you_should_align; //;?
hcf_16 IFB_TallyLen; // Tally length (to build an LTV)
@@ -382,9 +375,6 @@ typedef IFB_STRCT* IFBP;
EXTERN_C int hcf_action (IFBP ifbp, hcf_16 cmd );
EXTERN_C int hcf_connect (IFBP ifbp, hcf_io io_base );
-#if (HCF_ENCAP) & HCF_ENC_SUP
-EXTERN_C hcf_8 hcf_encap (wci_bufp type );
-#endif // HCF_ENC_SUP
EXTERN_C int hcf_get_info (IFBP ifbp, LTVP ltvp );
EXTERN_C int hcf_service_nic (IFBP ifbp, wci_bufp bufp, unsigned int len );
EXTERN_C int hcf_cntl (IFBP ifbp, hcf_16 cmd );
diff --git a/drivers/staging/wlags49_h2/hcfcfg.h b/drivers/staging/wlags49_h2/hcfcfg.h
index 83475b1..7545bc5 100644
--- a/drivers/staging/wlags49_h2/hcfcfg.h
+++ b/drivers/staging/wlags49_h2/hcfcfg.h
@@ -300,493 +300,6 @@ typedef unsigned long hcf_32;
#define HCF_TALLIES_HCF 0x0002 // HCF Tallies accumulated in IFB
#define HCF_TALLIES_RESET 0x8000 // Tallies in IFB are reset when reported via hcf_get_info
-
-/************************************************************************************************/
-/****************************** M I N I P O R T N D I S *************************************/
-/************************************************************************************************/
-
-#if defined WVLAN_41 || defined WVLAN_48 || defined WVLAN_52 || defined _WIN32_WCE
-
-#ifndef WVLAN_46
-#define HCF_EXT (HCF_EXT_INFO_LOG | HCF_EXT_MB | HCF_EXT_NIC_ACCESS )
-#else
-#define HCF_EXT ( HCF_EXT_TX_CONT | HCF_EXT_INFO_LOG | HCF_EXT_MB | HCF_EXT_NIC_ACCESS )
-#endif
-#define HCF_DLV 1 //H-I legacy, superfluous for H-II
-
-#ifdef _WIN32_WCE
-#define HCF_IO HCF_IO_MEM
-#define HCF_DMA 0 // To enable DMA
-#endif
-
-#if _VARIANT == 7
-#define HCF_SLEEP HCF_CDS
-#endif // _VARIANT == 7
-
-#if _VARIANT == 5 || _VARIANT == 6
-#define _WARP
-#define _AES
-#define HCF_SLEEP HCF_CDS
-#if _VARIANT == 6
-//! #define _RSN
-#endif // _VARIANT == 6
-#ifndef _WIN32_WCE
-#define HCF_IO HCF_IO_32BITS
-#define HCF_DMA 1 // To enable DMA
-#endif
-#endif // _VARIANT == 5 || _VARIANT == 6
-
-
-//HWi for migration purposes I defined a define which will be TRUE for ALL drivers
-//Meaning that _CCX defined code which we think will get a all driver OK flag can be defined from _CCX to _CCX_OK
-#if defined WVLAN_48 // && !defined _WIN32_WCE
-#if _VARIANT == 4 || _VARIANT == 6
-#define _CCX_OK 1
-#endif // _VARIANT == 4 || _VARIANT == 6
-#endif // WVLAN_48
-
-//#if !defined WVLAN_46
-#if defined WVLAN_48
-#if _VARIANT == 4 || _VARIANT == 6
-#define _CCX
-#define HCF_MAX_MSG_CKIP_PADDING 86 //, use 86 for rx fragmentation. 28 is enuf for MIC+PPK encapsulation
-#define HCF_MAX_MSG ( 1514 + HCF_MAX_MSG_CKIP_PADDING ) // need extra padding for CKIP (need to subtract 28 for NDIS)
-#endif // _VARIANT == 4 || _VARIANT == 6
-#endif // WVLAN_48
-//#endif // WVLAN_46
-
-#if !defined WVLAN_46
-#define _PEEK
-#endif
-
-#ifndef _WIN32_WCE
-// ASSERT already used by WinCE...
-#ifdef ASSERT
-#undef ASSERT
-#define ASSERT(x) ASSERTDEBUGMSG((x), (TEXT("SIMULATE ASSERT:")))
-#endif
-#endif
-
-
-#if defined WVLAN_41
-#define MSF_COMPONENT_ID COMP_ID_MINIPORT_NDIS_31
-#endif // WVLAN_41
-#if defined WVLAN_48 && !defined _WIN32_WCE
-#define MSF_COMPONENT_ID COMP_ID_MINIPORT_NDIS_50
-#endif // WVLAN_48 / _WIN32_WCE
-#if defined WVLAN_52 && !defined _WIN32_WCE
-#define MSF_COMPONENT_ID COMP_ID_MINIPORT_NDIS_40
-#endif // WVLAN_52 / _WIN32_WCE
-#if defined WVLAN_46
-#define MSF_COMPONENT_ID COMP_ID_WIN_CE
-#endif // _WIN32_WCE
-
-#define MSF_COMPONENT_VAR _VARIANT
-
-#define T1__HCF_TYPE (HCF_TYPE_NONE)
-
-#define T2__HCF_TYPE (T1__HCF_TYPE)
-
-#ifdef _WARP
-#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5 | HCF_TYPE_WARP )
-#else
-#if _VARIANT == 7
-#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5)
-#else // _VARIANT == 7
-#define T3__HCF_TYPE (T2__HCF_TYPE)
-#endif // _VARIANT == 7
-#endif // _WARP
-
-#ifdef _CCX_OK
-#define T4__HCF_TYPE (T3__HCF_TYPE | HCF_TYPE_CCX)
-#else
-#define T4__HCF_TYPE (T3__HCF_TYPE)
-#endif // _CCX_OK
-
-//not suitable for H-II #define HCF_CFG_STA_1_BOTTOM 16
-
-// Default WPA in ON for all drivers except for WARP driver
-#ifdef _WARP
-#define T5__HCF_TYPE (T4__HCF_TYPE)
-#else // _WARP
-#define T5__HCF_TYPE (T4__HCF_TYPE | HCF_TYPE_WPA)
-#endif // _WARP
-
-#define HCF_TYPE (T5__HCF_TYPE)
-
-// This is needed to get aux_ctrl() from the HCF for WlFreezeAndDump()
-#if (defined DBG && DBG != 0)
-#ifndef STATIC
-#define STATIC
-#endif
-#endif
-
-#if !defined SOFTRONICS_CODE && !defined _APIDLL && !defined _WIN32_WCE
-#include <ndis.h>
-#endif // SOFTRONICS_CODE / _APIDLL / _WIN32_WCE
-#if defined _WIN32_WCE
-#include <windows.h>
-#include <winnt.h>
-#endif // _WIN32_WCE
-#include "version.h"
-
-#define MSF_COMPONENT_MAJOR_VER TPI_MAJOR_VERSION
-#define MSF_COMPONENT_MINOR_VER TPI_MINOR_VERSION
-
-#if !defined _APIDLL && !defined _WIN32_WCE
-
-__inline UCHAR NDIS_IN_BYTE( ULONG port )
-{
- UCHAR value;
- NdisRawReadPortUchar(port , &value);
- return (value);
-}
-
-__inline ULONG NDIS_IN_LONG( ULONG port )
-{
- ULONG value;
- NdisRawReadPortUlong(port , &value);
- return (value);
-}
-__inline USHORT NDIS_IN_WORD( ULONG port )
-{
- USHORT value;
- NdisRawReadPortUshort(port , &value);
- return (value);
-}
-
-#define IN_PORT_DWORD(port) NDIS_IN_LONG( (ULONG) (port) )
-#define IN_PORT_WORD(port) NDIS_IN_WORD( (ULONG) (port) )
-#define OUT_PORT_DWORD(port, value) NdisRawWritePortUlong((ULONG) (port) , value)
-#define OUT_PORT_WORD(port, value) NdisRawWritePortUshort((ULONG) (port) , (USHORT) (value))
-
-#define IN_PORT_STRING_8_16(port, addr, len) IN_PORT_STRING_16(port, addr, len)
-#define OUT_PORT_STRING_8_16(port, addr, len) OUT_PORT_STRING_16(port, addr, len)
-
-#define IN_PORT_STRING_32(port, addr, len) { \
- NdisRawReadPortBufferUlong(port, addr, (len)); \
-}
-
-#define OUT_PORT_STRING_32(port, addr, len) { \
- NdisRawWritePortBufferUlong(port, addr, (len)); \
-}
-
-#define IN_PORT_STRING_16(port, addr, len) NdisRawReadPortBufferUshort(port, addr, (len));
-#define OUT_PORT_STRING_16(port, addr, len) NdisRawWritePortBufferUshort(port, addr, (len));
-
-#endif // _APIDLL / _WIN32_WCE
-
-#if defined _WIN32_WCE
-
-#define HCF_ALIGN 2
-#define HCF_MEM_IO 1 // overrule standard Port I/O with Memory mapped I/O
-#define HCF_PROT_TIME 49
-
-#define IN_PORT_BYTE CE_IN_PORT_BYTE
-#define OUT_PORT_BYTE CE_OUT_PORT_BYTE
-#define IN_PORT_WORD CE_IN_PORT_WORD
-#define OUT_PORT_WORD CE_OUT_PORT_WORD
-#define IN_PORT_STRING_16 CE_IN_PORT_STRING
-#define OUT_PORT_STRING_16 CE_OUT_PORT_STRING
-
-extern hcf_8 CE_IN_PORT_BYTE(hcf_32 port);
-extern void CE_OUT_PORT_BYTE(hcf_32 port, hcf_8 value);
-extern hcf_16 CE_IN_PORT_WORD(hcf_32 port);
-extern void CE_OUT_PORT_WORD(hcf_32 port, hcf_16 value);
-extern void CE_IN_PORT_STRING(hcf_32 port, void *addr, hcf_16 len);
-extern void CE_OUT_PORT_STRING(hcf_32 port, void *addr, hcf_16 len);
-
-
-#endif
-
-#if defined _DEBUG || (defined DBG && DBG != 0)
-#define HCF_ASSERT ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN | HCF_ASSERT_PRINTF ) //0xC001
-//#define HCF_ASSERT ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN | HCF_ASSERT_PRINTF | HCF_ASSERT_MB ) //just to test
-#endif // _DEBUG || DBG
-
-#if defined DEBUG || defined _DEBUG || (defined DBG && DBG != 0)
-#ifdef _WIN32_WCE
-#define DBGA2W(DBGSTR) CeConvertAnsiToUnicodeLen((char*)DBGSTR)
-#define OUTPUTDEBUGMSG(dprintf_exp) ((void)((! ZONE_DEBUG) ? 0:ce_debug_out dprintf_exp))
-#define ASSERTDEBUGMSG(cond, dprintf_exp) ((void)((cond) ? 0:ce_debug_out dprintf_exp))
-
-#define ZONE_ERROR DEBUGZONE(0)
-#define ZONE_WARN DEBUGZONE(1)
-#define ZONE_FUNCTION DEBUGZONE(2)
-#define ZONE_INIT DEBUGZONE(3)
-#define ZONE_INTR DEBUGZONE(4)
-#define ZONE_RCV DEBUGZONE(5)
-#define ZONE_XMIT DEBUGZONE(6)
-#define ZONE_ASSERT DEBUGZONE(7)
-#define ZONE_DEBUG DEBUGZONE(8)
-#define ZONE_OEM DEBUGZONE(9)
-#define ZONE_HCF DEBUGZONE(10)
-#define ZONE_PORTIO DEBUGZONE(11)
-#define ZONE_LOGTOFILE DEBUGZONE(15)
-
-#else // !(_WIN32_WCE)
-
-#define OUTPUTDEBUGMSG(dprintf_exp) ((void) (DbgPrint dprintf_exp))
-// the assertdebugmsg macro will print filename, line followed by a caller-defined text, when cond == 0
-#define ASSERTDEBUGMSG(cond, print) ((void)((cond) ? 0: (DbgPrint("%s %s:%d - ", print, __FILE__, __LINE__))))
-
-#define ZONE_ERROR 1
-#define ZONE_WARN 1
-#define ZONE_FUNCTION 1
-#define ZONE_INIT 1
-#define ZONE_INTR 1
-#define ZONE_RCV 1
-#define ZONE_XMIT 1
-#define ZONE_ASSERT 1
-#define ZONE_DEBUG 1
-#define ZONE_OEM 1
-#define ZONE_HCF 1
-#define ZONE_PORTIO 1
-#define ZONE_LOGTOFILE 1
-
-#endif // _WIN32_WCE
-#ifndef DBGA2W
-#define DBGA2W
-#endif // DBGA2W
-
-#else // !(defined DEBUG || defined _DEBUG || (defined DBG && DBG != 0) )
-#define OUTPUTDEBUGMSG(dprintf_exp)
-#define ASSERTDEBUGMSG(cond, dprintf_exp)
-#endif // DEBUG / DBG
-
-#if !defined HCF_MAX_MSG_CKIP_PADDING
-#define HCF_MAX_MSG_CKIP_PADDING 0
-#endif // HCF_MAX_MSG_CKIP_PADDING
-
-#if !defined HCF_MAX_MSG
-#define HCF_MAX_MSG 1514
-#endif // HCF_MAX_MSG
-
-#define HCF_LEGACY 1 //;?nv je moet wat
-
-#endif //WVLAN_41 / WVLAN_48 / WVLAN_52 / _WIN32_WCE
-
-
-/************************************************************************************************/
-/**************************** P A C K E T D R I V E R ***************************************/
-/********************************** D O S O D I *********************************************/
-/************************************************************************************************/
-
-#if defined WVLAN_42 || defined WVLAN_43
-
-#pragma warning ( disable: 4001 )
-#define FAR __far //segmented 16 bits mode
-#define BASED __based(__segname("_CODE")) //force all the "const" structures in the CODE segment
-
-//#define HCF_IO 0 //no DMA, no 32 bits
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#define HCF_EXT HCF_EXT_MB
-#define HCF_PROT_TIME 49 //49*10240 microseconds H/W failure protection timer
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-/******************************** CONFIGURATION MANAGEMENT *****************************************/
-#ifdef WVLAN_42
-#define MSF_COMPONENT_ID COMP_ID_PACKET
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER 6
-#define MSF_COMPONENT_MINOR_VER 12
-#endif // WVLAN_42
-
-#ifdef WVLAN_43
-#define MSF_COMPONENT_ID COMP_ID_ODI_16
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER 6
-#define MSF_COMPONENT_MINOR_VER 10
-#endif // WVLAN_43
-
-/************************************** INPUT / OUTPUT **********************************************/
-#ifndef H_2_INC
-#include <stdio.h>
-#include <conio.h>
-#if 1 //temorary use functions defined in hcf.c
-#ifndef _DEBUG
-#pragma intrinsic( _inp, _inpw, _outp, _outpw )
-#endif // _DEBUG
-
-#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value ))
-
-#if 1 // C implementation which let the processor handle the word-at-byte-boundary problem
-#define IN_PORT_STRING_8_16( port, addr, n) while (n--) \
- { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); ((hcf_8 FAR*)addr)+=2; }
-#define OUT_PORT_STRING_8_16( port, addr, n) while (n--) \
- { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; ((hcf_8 FAR*)addr)+=2; }
-#elif 0 // C implementation which handles the word-at-byte-boundary problem
-#define IN_PORT_STRING_8_16( port, addr, n) while ( n-- ) \
- { hcf_16 i = IN_PORT_WORD(port); *((hcf_8 FAR*)addr)++ = (hcf_8)i; *((hcf_8 FAR*)addr)++ = (hcf_8)(i>>8);}
-#define OUT_PORT_STRING_8_16( port, addr, n) while ( n-- ) \
- { OUT_PORT_WORD( port, *((hcf_8 FAR*)addr) | *(((hcf_8 FAR*)addr)+1)<<8 ); (hcf_8 FAR*)addr+=2; }
-#else // Assembler implementation
-#define IN_PORT_STRING_8_16( port, addr, n) __asm \
-{ \
- __asm push di \
- __asm push es \
- __asm mov cx,n \
- __asm les di,addr \
- __asm mov dx,port \
- __asm rep insw \
- __asm pop es \
- __asm pop di \
-}
-
-#define OUT_PORT_STRING_8_16( port, addr, n) __asm \
-{ \
- __asm push si \
- __asm push ds \
- __asm mov cx,n \
- __asm lds si,addr \
- __asm mov dx,port \
- __asm rep outsw \
- __asm pop ds \
- __asm pop si \
-}
-
-#endif // Asm or C implementation
-#define IN_PORT_STRING_32( port, addr, n) { int n2 = 2*n; IN_PORT_STRING_8_16(port, addr, n2) }
-#define OUT_PORT_STRING_32( port, addr, n) { int n2 = 2*n; OUT_PORT_STRING_8_16(port, addr, n2) }
-#endif // 0 //temorary use functions defined in hcf.c
-#endif // H_2_INC
-
-#endif // WVLAN_42 / WVLAN_43
-
-
-
-/************************************************************************************************/
-/**************************** D O S H - I / II L O A D E R **********************************/
-/************************************************************************************************/
-
-#if defined H0_LDR || defined H1_LDR || defined H2_LDR || defined H5_LDR
-
-#if defined H0_LDR //implies H-I
-#define HCF_DLV 0 //H-I legacy, meaningless under H-II
-#define HCF_DLNV 1 //H-I legacy, meaningless under H-II
-#endif // H0_LDR
-
-#if defined H1_LDR //implies H-I
-#define HCF_DLV 1 //H-I legacy, meaningless under H-II
-#define HCF_DLNV 0 //H-I legacy, meaningless under H-II
-#endif // H1_LDR / H2_LDR
-
-//#if defined H2_LDR : not needed, H-II defaults are O.K for H2_LDR
-
-#ifdef H5_LDR
-#define HCF_TYPE (HCF_TYPE_HII5 | HCF_TYPE_WARP )
-//;? why does only this subset of the H_LDRs need HCF_TYPE to be defined here
-#endif
-
-#define HCF_ASSERT HCF_ASSERT_LNK_MSF_RTN //support dynamic linking of msf_assert routine
-#define HCF_ENCAP 0
-#define HCF_INT_ON 0
-#define HCF_TALLIES 0
-
-#define MSF_COMPONENT_ID COMP_ID_ODI_16 //;?By lack of any better
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER 0
-#define MSF_COMPONENT_MINOR_VER 0
-
-#include <stdio.h>
-#include <conio.h>
-#if defined NDEBUG
-#pragma intrinsic( _inp, _inpw, _outp, _outpw )
-#endif // NDEBUG
-
-#if 0 //use 0 to replace I/O Macros with logging facility
-#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value ))
-#define IN_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); (cast)addr += 2; }
-#define OUT_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; (cast)addr += 2; }
-#endif //use 0 to replace I/O Macros with logging facility
-
-#endif // H0_LDR / H1_LDR / H2_LDR
-
-
-
-/************************************************************************************************/
-/**************************** H C F D E M O P R O G R A M ***********************************/
-/************************************************************************************************/
-
-#if defined HCF_DEMO
-
-#define HCF_DLV 1 //;?should become the default !defaults to 1 anyway for H-II
-//#define HCF_DLNV 0 //defaults to 0 anyway for H-II
-
-#define HCF_ASSERT HCF_ASSERT_LNK_MSF_RTN //support dynamic linking of msf_assert routine
-
-#define HCF_ENCAP 0
-#define HCF_INT_ON 0
-#define HCF_TALLIES ( HCF_TALLIES_NIC | HCF_TALLIES_HCF )
-
-//#define MSF_COMPONENT_ID NO configuration management
-
-#include <stdio.h>
-#include <conio.h>
-#if defined NDEBUG
-#pragma intrinsic( _inp, _inpw, _outp, _outpw )
-#endif // NDEBUG
-
-#if 0 //use 0 to replace I/O Macros with logging facility
-#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value ))
-#define IN_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); (cast)addr += 2; }
-#define OUT_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; (cast)addr += 2; }
-#endif //use 0 to replace I/O Macros with logging facility
-
-#endif // HCF_DEMO
-
-
-
-/************************************************************************************************/
-/*********************************** M A C O S **********************************************/
-/************************************************************************************************/
-
-#if defined WVLAN_45
-
-#include "Version.h"
-
-#define MSF_COMPONENT_ID COMP_ID_MAC_OS
-#define MSF_COMPONENT_VAR VARIANT
-#define MSF_COMPONENT_MAJOR_VER VERSION_MAJOR
-#define MSF_COMPONENT_MINOR_VER VERSION_MINOR
-
-#define MAC_OS 1
-
-#define HCF_BIG_ENDIAN 1 // selects Big Endian (a.k.a. Motorola), most significant byte first
-
-#if defined DEBUG
-#define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox
-#endif // DEBUG
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-extern volatile unsigned char *MacIOaddr;
-extern hcf_16 IN_PORT_WORD(hcf_16 port);
-extern void OUT_PORT_WORD(hcf_16 port, hcf_16 value);
-extern void IN_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len);
-extern void OUT_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len);
-
-#define SwapBytes(t) (((t) >> 8) + (((t) & 0xff) << 8))
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // WVLAN_45
-
-
-
/************************************************************************************************/
/****************************************** L I N U X *****************************************/
/************************************************************************************************/
@@ -803,16 +316,25 @@ extern void OUT_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len);
//#define HCF_SLEEP (HCF_CDS | HCF_DDS )
#define HCF_SLEEP (HCF_CDS)
-//#define HCF_TYPE (HCF_TYPE_HII5|HCF_TYPE_STA|HCF_TYPE_AP)
+/* Note: Non-WARP firmware all support WPA. However the original Agere
+ * linux driver does not enable WPA. Enabling WPA here causes whatever
+ * preliminary WPA logic to be included, some of which may be specific
+ * to HERMESI.
+ *
+ * Various comment are clear that WARP and WPA are not compatible
+ * (which may just mean WARP does WPA in a different fashion).
+ */
+
+/* #define HCF_TYPE (HCF_TYPE_HII5|HCF_TYPE_STA|HCF_TYPE_AP) */
#ifdef HERMES25
#ifdef WARP
#define HCF_TYPE ( HCF_TYPE_WARP | HCF_TYPE_HII5 )
#else
-#define HCF_TYPE HCF_TYPE_HII5
-#endif // WARP
+#define HCF_TYPE (HCF_TYPE_HII5 | HCF_TYPE_WPA)
+#endif /* WARP */
#else
-#define HCF_TYPE HCF_TYPE_NONE
-#endif // HERMES25
+#define HCF_TYPE HCF_TYPE_WPA
+#endif /* HERMES25 */
#ifdef ENABLE_DMA
#define HCF_DMA 1
@@ -934,16 +456,6 @@ extern void OUT_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len);
#define IN_PORT_STRING_8_16(port, addr, len) IN_PORT_STRING_16(port, addr, len)
#define OUT_PORT_STRING_8_16(port, addr, len) OUT_PORT_STRING_16(port, addr, len)
-
-#ifndef OUTPUTDEBUGMSG
-#define OUTPUTDEBUGMSG(dprintf_exp)
-#endif
-
-
-#ifndef ASSERTDEBUGMSG
-#define ASSERTDEBUGMSG(cond, dprintf_exp)
-#endif
-
#ifndef CFG_SCAN_CHANNELS_2GHZ
#define CFG_SCAN_CHANNELS_2GHZ 0xFCC2
#endif /* CFG_SCAN_CHANNELS_2GHZ */
@@ -951,1043 +463,6 @@ extern void OUT_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len);
#define HCF_MAX_MSG 1600 //get going ;?
#endif // WVLAN_49
-
-
-/************************************************************************************************/
-/********************************************* Q N X ******************************************/
-/************************************************************************************************/
-
-#if defined __QNX__ || defined WVLAN_50
-
-#define MSF_COMPONENT_ID 0 //Although there is no DUI support, we need this to get ...
-#define MSF_COMPONENT_VAR 0 //...compatibilty check to function
-#define MSF_COMPONENT_MAJOR_VER 0 //...;?this is worth looking into to make this a more
-#define MSF_COMPONENT_MINOR_VER 0 //..."defined" I/F so OEMers can figure out what to do
-
-#include <conio.h>
-
-#define IN_PORT_WORD(port) ((hcf_16)inpw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) (outpw( (hcf_io)(port), (hcf_16) (value) ))
-/*
-#define IN_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { *(hcf_16*)addr = IN_PORT_WORD( port ); (cast)addr += 2; }
-#define OUT_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16*)addr ) ; (cast)addr += 2; }
-*/
-
-#endif // QNX / WVLAN_50
-
-
-
-/************************************************************************************************/
-/********************************************* B E O S ****************************************/
-/************************************************************************************************/
-
-#if defined __BEOS__
-
-#define MSF_COMPONENT_ID 0 //Although there is no DUI support, we need this to get ...
-#define MSF_COMPONENT_VAR 0 //...compatibilty check to function
-#define MSF_COMPONENT_MAJOR_VER 0 //...;?this is worth looking into to make this a more
-#define MSF_COMPONENT_MINOR_VER 0 //..."defined" I/F so OEMers can figure out what to do
-
-#include <drivers/Drivers.h>
-#include <drivers/KernelExport.h>
-
-uint8 read_io_8 (int);
-void write_io_8 (int, uint8);
-uint16 read_io_16 (int);
-void write_io_16 (int, uint16);
-
-#define IN_PORT_WORD(port) ((hcf_16)read_io_16( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) (write_io_16( (hcf_io)(port), (hcf_16) (value) ))
-/*
-#define IN_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { *(hcf_16*)addr = IN_PORT_WORD( port ); (cast)addr += 2; }
-#define OUT_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16*)addr ) ; (cast)addr += 2; }
-*/
-#endif // __BEOS__
-
-
-
-/************************************************************************************************/
-/******************************** U S B D O N G L E *****************************************/
-/************************************************************************************************/
-
-#if defined USB
-#include "gpif.h"
-
-#define MSF_COMPONENT_MAJOR_VER 0
-#define MSF_COMPONENT_MINOR_VER 1
-
-#define IN_PORT_WORD(port) (Hermes_IO_Read( (hcf_8)(port)))
-#define OUT_PORT_WORD(port, value) (Hermes_IO_Write( (hcf_8)port, /*(hcf_16)*/(value) ) )
-/* !!!! NOTE USB supports only 16-bits I/O and no 8-bits I/O
- * as a consequence the IN_/OUT_PORT_STRING_16 macros use hcf_16* rather than hcf_8 pointers
- * to get more optimal code
- * therefore the pointers are incremented by 1 (which means two "bytes") rather than by 2
- */
-//#define IN_PORT_STRING_16( port, addr, n) while ( n-- ) { *((hcf_16*)addr)++ = IN_PORT_WORD( port ); }
-//#define OUT_PORT_STRING_16( port, addr, n) while ( n-- ) { OUT_PORT_WORD( port, *((hcf_16*)addr)++ ); }
-#define IN_PORT_STRING_16( port, dst, n) while ( n-- ) { *dst++ = IN_PORT_WORD( port ); }
-#define OUT_PORT_STRING_16( port, src, n) while ( n-- ) { OUT_PORT_WORD( port, *src++ ); }
-
-//#define HCF_TYPE ( HCF_TYPE_AP | HCF_TYPE_WPA )
-#define HCF_TYPE HCF_TYPE_WPA
-
-#endif // USB
-
-
-/************************************************************************************************/
-/****************************************** FreeBSD *******************************************/
-/************************************************************************************************/
-
-#if defined __FREE_BSD__
-
-#define MSF_COMPONENT_ID COMP_ID_FreeBSD
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER 1
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#include <machine/cpufunc.h>
-
-#define IN_PORT_WORD(port) ((hcf_16)inw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) (outw((hcf_io)(port), (hcf_16)(value)))
-
-/*
-#define IN_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { *(hcf_16*)addr = IN_PORT_WORD( port ); (cast)addr += 2; }
-#define OUT_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16*)addr ) ; (cast)addr += 2; }
-*/
-#endif // __FREE_BSD__
-
-
-
-/************************************************************************************************/
-/********************************* W A V E P O I N T ******************************************/
-/************************************************************************************************/
-
-#if defined WVLAN_81 /* BORLANDC */
-
-#define EXTERN_C extern // needed because DHF uses this instead of 'extern'
-
-#define MSF_COMPONENT_ID COMP_ID_AP1
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER 4
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_PROT_TIME 49 //49*10240 microseconds H/W failure protection timer
-
-//#define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox /* debug build only */
-
-#if !defined FAR
-#define FAR far // segmented 16 bits mode
-#endif // FAR
-
-#define IN_PORT_WORD(port) (inport( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) (outport( (hcf_io)(port), value ))
-
-#define IN_PORT_STRING_16(port, addr, len) \
- asm { push di; push es; mov cx,len; les di,addr; mov dx,port; rep insw; pop es; pop di }
-
-#define OUT_PORT_STRING_16(port, addr, len) \
- asm { push si; push ds; mov cx,len; lds si,addr; mov dx,port; rep outsw; pop ds; pop si }
-
-#endif // WVLAN_81
-
-
-/************************************************************************************************/
-/******************************** W A V E L A U N C H *****************************************/
-/************************************************************************************************/
-
-#if defined WVLAUNCH
-
-#include "DriverX.h"
-extern HWDEVICE* g_pDevice;
-
-//#define MSF_COMPONENT_ID 0 //;? to get around browser problem
-
-#define IN_PORT_WORD(port) HwInpw( g_pDevice, port )
-#define OUT_PORT_WORD(port, value) HwOutpw( g_pDevice, port, value )
-
-
-// C implementation which let the processor handle the word-at-byte-boundary problem
-/*
-#define IN_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); (cast)addr += 2; }
-#define OUT_PORT_STRING_16( port, addr, n) \
- while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; (cast)addr += 2; }
-*/
-#endif // WVLAUNCH
-
-
-
-/************************************************************************************************/
-/************************************* W C I T S T *********************************************/
-/************************************************************************************************/
-
-#if defined WCITST
-#define MSF_COMPONENT_ID 0 //Although there is no DUI support, we need this to get ...
-#define MSF_COMPONENT_VAR 0 //...compatibilty check to function
-#define MSF_COMPONENT_MAJOR_VER 0 //...;?this is worth looking into to make this a more
-#define MSF_COMPONENT_MINOR_VER 0 //..."defined" I/F so OEMers can figure out what to do
-
-//#define HCF_ENCAP HCF_ENC_NONE //to get going
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#define HCF_TYPE (HCF_TYPE_WPA | HCF_TYPE_PRELOADED) // Hermes-I for HCF6, II for HCF7
-#define HCF_DMA 1
-//#define LLB //!!!!MIC Debug Only
-#if defined LLB && !((HCF_TYPE) & HCF_TYPE_WPA)
-err: no LLB unless SSN;
-#endif // LLB / HCF_TYPE_WPA
-//#define HCF_ALIGN 2
-#define HCF_DLV 1 //just to change memory layout ????;?
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#define HCF_ASSERT HCF_ASSERT_SW_SUP // logging via Hermes support registerr
-//#define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox
-
-#if defined __GNUC__
-#include "stdio.h"
-//#include "unistd.h" //ioperm libc5
-#include "sys/io.h" //ioperm glibc
-#define extern //see IO Port Programming mini-HOWTO
-//#include "asm/io.h" //
-#define IN_PORT_WORD(port) inw( (hcf_io)(port) )
-#define IN_PORT_DWORD(port) inl( (hcf_io)(port) )
-#define OUT_PORT_WORD(port, value) outw( (hcf_io)(port), (hcf_16)(value) )
-#define OUT_PORT_DWORD(port, value) outl( (hcf_io)(port), (hcf_16)(value) )
-#else
-#pragma warning ( disable: 4001 )
-#define FAR __far // segmented 16 bits mode
-
-#include <stdio.h>
-#include <conio.h>
-#ifndef _DEBUG
-#pragma intrinsic( _inp, _inpw, _outp, _outpw )
-#endif // _DEBUG
-
-#ifdef LOG
-extern FILE* utm_logfile;
-hcf_16 ipw( hcf_16 port );
-hcf_8 ipb( hcf_16 port );
-void opw( hcf_16 port, hcf_16 value );
-void opb( hcf_16 port, hcf_8 value );
-
-#define IN_PORT_WORD(port) ipw( (hcf_io)(port) )
-#define OUT_PORT_WORD(port, value) opw( (hcf_io)(port), (hcf_16)(value) )
-#else // LOG
-#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value ))
-#endif // LOG
-
-#if 1 //ASM example
-#define IN_PORT_STRING_16( port, addr, len) __asm \
-{ \
- __asm push di \
- __asm push es \
- __asm mov cx,len \
- __asm les di,addr \
- __asm mov dx,port \
- __asm rep insw \
- __asm pop es \
- __asm pop di \
-}
-
-#define OUT_PORT_STRING_16( port, addr, len) __asm \
-{ \
- __asm push si \
- __asm push ds \
- __asm mov cx,len \
- __asm lds si,addr \
- __asm mov dx,port \
- __asm rep outsw \
- __asm pop ds \
- __asm pop si \
-}
-
-#endif // asm example
-
-#endif // __GCC__
-
-#if ! defined IN_PORT_STRING_16
-#define IN_PORT_STRING_16( port, addr, n) while (n--) \
- { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); ((hcf_16 FAR*)addr)++; }
-#define OUT_PORT_STRING_16( port, addr, n) while (n--) \
- { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ); ((hcf_16 FAR*)addr)++; }
-#endif // IN_PORT_STRING_16
-
-#endif // WCITST
-
-
-/************************************************************************************************/
-/******************************* Motorola Power PC 800 family *********************************/
-/************************************************************************************************/
-/* known users: LH@I
- */
-
-#if defined I_MPC8XX
-
-#define MSF_COMPONENT_VAR 0
-#define MSF_COMPONENT_ID 0
-#define MSF_COMPONENT_MAJOR_VER 1
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_HSI_VAR 1
-
-#define HCF_BIG_ENDIAN 1
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#include "o_portbl.h"
-#include "ipcmcia.h"
-typedef o_uint8_t hcf_8;
-typedef o_uint16_t hcf_16;
-typedef o_uint32_t hcf_32;
-
-/***************************************************************************/
-
-
-#ifdef _lint
-#else
-asm hcf_16 IN_PORT_WORD(int port)
-{
-% reg port
- lhbrx r3,r0,port
- eieio
-}
-#endif // _lint
-
-
-#ifdef _lint
-#else
-asm void OUT_PORT_WORD(int port, hcf_16 value)
-{
-% reg port, value
- sthbrx value,r0,port
- eieio
-}
-#endif // _lint
-
-/***************************************************************************/
-
-#define IN_PORT_STRING_16(port, addr, len) \
- { \
- unsigned l = (len); \
- hcf_16 *d = (volatile hcf_16 *)(addr); \
- while (l--) \
- { \
- *d++ = *(volatile hcf_16 *)(port); \
- EIEIO(); \
- } \
- }
-
-#define OUT_PORT_STRING_16(port, addr, len) \
- { \
- unsigned l = (len); \
- hcf_16 *s = (volatile hcf_16 *)(addr); \
- while (l--) \
- { \
- *(volatile hcf_16 *)(port) = *s++; \
- EIEIO(); \
- } \
- }
-
-#endif // I_MPC8XX
-
-
-
-/************************************************************************************************/
-/********************************** Diab or High C 29K **************************************/
-/************************************************************************************************/
-/* known users: GK@C
- */
-
-#if defined _AM29K
-
-#define MSF_COMPONENT_VAR 0
-#define MSF_COMPONENT_ID COMP_ID_AP1
-#define MSF_COMPONENT_MAJOR_VER 1
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_BIG_ENDIAN 1
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#define SwapBytes(t) /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/
-
-#if defined __ppc
- #ifndef __GNUC__
- #define __asm__ asm
- #endif
-
- #if ! defined _lint
- #define EIEIO() __asm__(" eieio")
- #else
- #define EIEIO()
- #endif
-
- static hcf_16 IN_PORT_WORD(int port) {
- hcf_16 value = *(volatile hcf_16 *)(port); EIEIO();
- value = SwapBytes(value);
- return value;
- }
-
- #define OUT_PORT_WORD(port, value) \
- { *(volatile hcf_16 *)(port) = SwapBytes(value); EIEIO(); }
-#else
- #define IN_PORT_WORD(port) (*(volatile hcf_16 *)(port))
- #define OUT_PORT_WORD(port, value) (*(volatile hcf_16 *)(port) = (value))
-#endif // __ppc
-
-/***************************************************************************/
-
-#define IN_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 t, *d = (volatile hcf_16 *)(addr); \
- while (l--) { \
- t = IN_PORT_WORD(port); \
- *d++ = SwapBytes(t); \
- } \
- }
-
-#define OUT_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 t, *s = (volatile hcf_16 *)(addr); \
- while (l--) { \
- t = *s++; \
- OUT_PORT_WORD(port, SwapBytes(t)); \
- } \
- }
-
-#if PRODUCT == 9150
- #define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox
- #undef MSF_COMPONENT_ID
-#endif // 9150
-
-#endif // _AM29K
-
-
-
-/************************************************************************************************/
-/***************************************** MPC860 **********************************************/
-/************************************************************************************************/
-/* known users: RR
- */
-
-#if defined CPU
-#if CPU == PPC860
-
-#define MSF_COMPONENT_VAR 0
-#define MSF_COMPONENT_ID 0
-#define MSF_COMPONENT_MAJOR_VER 1
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_BIG_ENDIAN 1
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#define SwapBytes(t) /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/
-
-#ifndef __GNUC__
- #define __asm__ asm
-#endif
-
-#if ! defined _lint
- #define EIEIO() __asm__(" eieio")
-#else
- #define EIEIO()
-#endif
-
-static hcf_16 IN_PORT_WORD(int port) {
- hcf_16 value = *(volatile hcf_16 *)(port); EIEIO();
- value = SwapBytes(value);
- return value;
- #ifdef __GNUC__
- /* the following serves to avoid the compiler warnings that
- * IN_PORT_WORD() is not used in some files */
- (void)IN_PORT_WORD;
- #endif
-}
-
-#define OUT_PORT_WORD(port, value) \
- { *(volatile hcf_16 *)(port) = SwapBytes(value); EIEIO(); }
-
-/***************************************************************************/
-
-#define IN_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 t; \
- volatile hcf_16 *d = (volatile hcf_16 *)(addr); \
- while (l--) { \
- t = IN_PORT_WORD(port); \
- *d++ = SwapBytes(t); \
- } \
- }
-
-#define OUT_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 t; \
- volatile hcf_16 *s = (volatile hcf_16 *)(addr); \
- while (l--) { \
- t = *s++; \
- OUT_PORT_WORD(port, SwapBytes(t)); \
- } \
- }
-
-#if PRODUCT == 9150
- #define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox
- #undef MSF_COMPONENT_ID
-#endif
-
-#endif /* PPC860 */
-#endif /* CPU */
-
-
-
-/************************************************************************************************/
-/**************************** Microtec Research 80X86 Compiler *********************************/
-/************************************************************************************************/
-
-#if 0
-
-//#undef HCF_TYPE // Hermes-I Station F/W without SSN support
-
-#define MSF_COMPONENT_VAR 0
-#define MSF_COMPONENT_ID 0
-#define MSF_COMPONENT_MAJOR_VER 1
-#define MSF_COMPONENT_MINOR_VER 0
-
-extern int far inp( int );
-extern void far outp( int, int );
-extern int far inpw( int );
-extern void far outpw( int, int );
-
-#define IN_PORT_WORD(port) ((hcf_16)inpw( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) ((void)outpw( (hcf_io)(port), value ))
-
-#define IN_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 *d = (hcf_16 *)(addr); \
- while (l--) *d++ = IN_PORT_WORD(port); \
- }
-
-#define OUT_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 *s = (hcf_16 *)(addr); \
- while (l--) OUT_PORT_WORD(port, *s++); \
- }
-#endif /* Microtec 80X86 C Compiler */
-
-
-
-/************************************************************************************************/
-/****************************** W A V E L A N E C ********************************************/
-/************************************************************************************************/
-/* known users: KM
- */
-
-#ifdef mc68302
-
-#define MSF_COMPONENT_ID COMP_ID_EC
-
-#include <version.h>
-
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER MAJOR_VERSION
-#define MSF_COMPONENT_MINOR_VER MINOR_VERSION
-
-#define HCF_BIG_ENDIAN 1
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#define SwapBytes(t) /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/
-
-#define PCMCIA_ADDRESS 0xc80000UL
-
-#define IN_PORT_2BYTES(port) (*(hcf_16 *)(port))
-#if 0
-static hcf_16 IN_PORT_WORD(hcf_32 port) // should be hcf_io, not hcf_32
-{
- hcf_16 word = IN_PORT_2BYTES(port);
- return SwapBytes(word);
-}
-#else
-static hcf_16 swap_var;
-#define IN_PORT_WORD(port) \
- (((swap_var = IN_PORT_2BYTES(port)) >> 8) + (((swap_var) & 0xff) << 8))
-#endif
-#define OUT_PORT_2BYTES(port, value) (*(hcf_16 *)(port) = (hcf_16)(value))
-#define OUT_PORT_WORD(port, value) OUT_PORT_2BYTES(port, SwapBytes(value))
-
-/*
-#define IN_PORT_STRING_16(port, addr, len) \
- while ((len)--) {*(hcf_16 *)(addr) = IN_PORT_2BYTES(port); ((cast)addr) += 2; }
-#define OUT_PORT_STRING_16(port, addr, len) \
- while ((len)--) {OUT_PORT_2BYTES((port), *(hcf_16 *)(addr)) ; ((cast)addr) += 2; }
-*/
-
-#endif /* mc68302 */
-
-
-
-/************************************************************************************************/
-/********************************* NGAP ***************************************/
-/************************************************************************************************/
-
-#if defined __VX_WORKS__ /* VxWorks */
-
-#if defined WLC_STATION
-//#undef HCF_TYPE /* Hermes-I Station F/W without SSN support */
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDSTA
-#else
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDAP
-#endif // WLC_STATION
-
-#define HCF_YIELD (taskDelay(0) == 0)
-
-#define MSF_COMPONENT_VAR 1
-#define MSF_COMPONENT_MAJOR_VER 1
-#define MSF_COMPONENT_MINOR_VER 0
-
-// #define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox
-
-#if defined PC486BSP
-
-#define IN_PORT_WORD(port) (sysInWord ((hcf_io)(port)))
-#define OUT_PORT_WORD(port, value) (sysOutWord ((hcf_io)(port), (hcf_16) (value)))
-#define IN_PORT_STRING_16(port, addr, n) (sysInWordString ((hcf_io)(port), addr, n))
-#define OUT_PORT_STRING_16(port, addr, n) (sysOutWordString ((hcf_io)(port), addr, n))
-
-#elif defined AS2000BSP
-
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-/* Define PCI stuff here. */
-unsigned short sysRead16( unsigned short *port );
-void sysWrite16( unsigned short *port, unsigned short value );
-
-#define PCI_IN_BYTE( port ) \
- *(unsigned char *)( port )
-
-#define PCI_IN_WORD( port ) \
- sysRead16( (unsigned short *)( port ) )
-
-#define PCI_OUT_BYTE( port, value ) \
- *(unsigned char *)( port ) = (unsigned char)( value )
-
-#define PCI_OUT_WORD( port, value ) \
- sysWrite16( (unsigned short *)( port ), (unsigned short)( value ) )
-
-#define IN_PORT_WORD( port ) \
- PCI_IN_WORD( port )
-
-#define OUT_PORT_WORD( port, value ) \
- PCI_OUT_WORD( port, value )
-
-#define IN_PORT_STRING_16( port, buf, len ) \
- do { \
- hcf_16 *p; \
- \
- for ( p = (hcf_16 *)(buf); p < &( (hcf_16 *)(buf) )[ (int)len ]; p++ ) { \
- *p = PCI_IN_WORD( port ); \
- } \
- } while ( 0 )
-
-#define OUT_PORT_STRING_16( port, buf, len ) \
- do { \
- const hcf_16 *p; \
- \
- for ( p = (const hcf_16 *)( buf ); p < &( (const hcf_16 *)(buf) )[ (int)len ]; p++ ) { \
- PCI_OUT_WORD( port, *p ); \
- } \
- } while ( 0 )
-
-#elif defined FADS860BSP /* elif defined AS2000BSP */
-
-#define HCF_BIG_ENDIAN 1
-
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#ifndef __GNUC__
- #define __asm__ asm
-#endif
-
-#if ! defined _lint
- #define EIEIO() __asm__(" eieio")
-#else
- #define EIEIO()
-#endif
-
-static hcf_16 IN_PORT_WORD(int port) {
- hcf_16 value = *(volatile hcf_16 *)(port); EIEIO();
- value = ((value & 0xff00) >> 8) + ((value & 0x00ff) << 8);
-/* value = CNV_LITTLE_TO_SHORT(value); */
- return value;
- #ifdef __GNUC__
- /* the following serves to avoid the compiler warnings that
- * IN_PORT_WORD() is not used in some files */
- (void)IN_PORT_WORD;
- #endif
-}
-
-#define OUT_PORT_WORD(port, value) \
- { *(volatile hcf_16 *)(port) = CNV_SHORT_TO_LITTLE(value); EIEIO(); }
-
-/***********************************************************************/
-
-#define IN_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- volatile hcf_16 *d = (volatile hcf_16 *)(addr); \
- while (l--) { \
- *d++ = *(volatile hcf_16 *)(port); \
- EIEIO(); \
- } \
- }
-
-#define OUT_PORT_STRING_16( port, addr, len) { \
- unsigned l = (len); \
- volatile hcf_16 *s = (volatile hcf_16 *)(addr); \
- while (l--) { \
- *(volatile hcf_16 *)(port) = *s++; \
- EIEIO(); \
- } \
- }
-
-#elif defined DAYTONABSP
-
-#define HCF_BIG_ENDIAN 1
-
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#ifndef __GNUC__
- #define __asm__ asm
-#endif
-
-#define IN_PORT_WORD(port) (sysOrinocoInWord((unsigned long)(port)))
-#define OUT_PORT_WORD(port,value) (sysOrinocoOutWord((unsigned long)(port), (unsigned short)(value)))
-
-#define IN_PORT_STRING_16(port,addr,len) (sysOrinocoInString((port), (addr), (len)))
-#define OUT_PORT_STRING_16(port,addr,len) (sysOrinocoOutString((port), (addr), (len)))
-
-extern unsigned char sysOrinocoInByte (unsigned long port);
-extern unsigned short sysOrinocoInWord (unsigned long port);
-extern void sysOrinocoInString (unsigned long port, void *addr, unsigned short len);
-
-extern void sysOrinocoOutByte (unsigned long port, unsigned char value);
-extern void sysOrinocoOutWord (unsigned long port, unsigned short value);
-extern void sysOrinocoOutString (unsigned long port, void *addr, unsigned short len);
-
-#elif defined ALPHA_BSP
-
-#define HCF_BIG_ENDIAN 1
-
-#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O
-
-#ifndef __GNUC__
- #define __asm__ asm
-#endif
-
-#define IN_PORT_WORD(port) (sysOrinocoInWord((unsigned long)(port)))
-#define OUT_PORT_WORD(port,value) (sysOrinocoOutWord((unsigned long)(port), (unsigned short)(value)))
-
-#define IN_PORT_STRING_16(port,addr,len) (sysOrinocoInString((port), (addr), (len)))
-#define OUT_PORT_STRING_16(port,addr,len) (sysOrinocoOutString((port), (addr), (len)))
-
-extern unsigned char sysOrinocoInByte (unsigned long port);
-extern unsigned short sysOrinocoInWord (unsigned long port);
-extern void sysOrinocoInString (unsigned long port, void *addr, unsigned short len);
-
-extern void sysOrinocoOutByte (unsigned long port, unsigned char value);
-extern void sysOrinocoOutWord (unsigned long port, unsigned short value);
-extern void sysOrinocoOutString (unsigned long port, void *addr, unsigned short len);
-
-#else
-
-err: /* commented here */ /* "BSP is not defined..." */
-
-#endif /* else PC486BSP */
-
-#endif // __VX_WORKS__
-
-
-
-/************************************************************************************************/
-/****************************** VXWORKS. Motorola Sandpoint PowerPC 824X ***********************/
-/************************************************************************************************/
-#ifdef __VX_WORKS_SANDPOINT_824X__
-
-#include <vxWorks.h>
-#include <sysLib.h>
-#include <taskLib.h>
-
-#ifdef WVLAN_53
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDSTA
-#endif /* WVLAN_53 */
-
-#ifdef WVLAN_54
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDAP
-#endif /* WVLAN_54 */
-
-#ifdef WVLAN_56
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_END
-#endif /* WVLAN_56 */
-
-#if !defined MSF_COMPONENT_ID
-#error "you must define an MSF component ID: WVLAN_53, WVLAN_54, WVLAN_56"
-#endif
-
-#define MSF_COMPONENT_VAR 1
-
-#define HCF_EXT HCF_EXT_INFO_LOG
-#define HCF_SLEEP ( HCF_CDS | HCF_DDS )
-//#define HCF_SLEEP ( HCF_DDS )
-
-#ifndef HCF_ACT_WAKEUP
-#define HCF_ACT_WAKEUP 0x1D
-#endif // HCF_ACT_WAKEUP
-
-#if defined FATNIC | defined BEAGLE_H253
-#define T1__HCF_TYPE HCF_TYPE_STA
-#else
-#define T1__HCF_TYPE HCF_TYPE_AP | HCF_TYPE_STA
-#endif
-
-#ifdef HERMES_USB
-#define T2__HCF_TYPE (T1__HCF_TYPE | HCF_TYPE_USB)
-#else // HERMES_USB
-#define T2__HCF_TYPE (T1__HCF_TYPE)
-#endif // HERMES_USB
-
-#ifdef _WARP
-#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5)
-#else // _WARP
-#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_WPA | HCF_TYPE_HII)
-#endif // WARP
-
-#ifdef _CCX
-#define T4__HCF_TYPE (T3__HCF_TYPE | HCF_TYPE_CCX)
-#else // _WARP
-#define T4__HCF_TYPE (T3__HCF_TYPE)
-#endif // _CCX
-
-#define T5__HCF_TYPE (T4__HCF_TYPE)
-
-// Default to TYPE_AP + SSN!
-#define HCF_TYPE (T5__HCF_TYPE )
-
-
-
-#define MSF_COMPONENT_MAJOR_VER 2
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_IO HCF_IO_MEM
-#define HCF_DMA 0
-#define HCF_MEM_IO 1
-#define HCF_BIG_ENDIAN 1
-
-//#define support_32bits 1
-
-#define IN_PORT_WORD(port) (sysInWord( (hcf_io)(port) ))
-#define OUT_PORT_WORD(port, value) (sysOutWord( (hcf_io)(port), (hcf_16)(value) ))
-#define IN_PORT_DWORD(port) (sysInLong( (hcf_io)(port) ))
-#define OUT_PORT_DWORD(port, value) (sysOutLong( (hcf_io)(port), (hcf_16)(value) ))
-#define IN_PORT_STRING_16(port, dst, n) (sysInWordString((hcf_io)(port), (hcf_16 *)dst, n))
-#define OUT_PORT_STRING_16(port, src, n) (sysOutWordString((hcf_io)(port), (hcf_16 *)src, n))
-
-#ifdef WVLAN_DEBUG
-#define DBG 1
-#define _DEBUG 1
-#endif
-
-/* we'll need to add these prints someday */
-#define OUTPUTDEBUGMSG(dprintf_exp)
-#define ASSERTDEBUGMSG(cond, dprintf_exp)
-
-#define HCF_INTERFACE_CONNECT(ifbp)
-#define HCF_INTERFACE_DISCONNECT(ifbp)
-#define HCF_ENTER_INTERFACE_FUNCT(ibfb)
-#define HCF_LEAVE_INTERFACE_FUNCT(ifbp)
-
-#define CNV_END_INT(w) ( ((hcf_16)(w) & 0x00FF) << 8 | ((hcf_16)(w) & 0xFF00) >> 8 )
-#define CNV_LITTLE_TO_INT(w) CNV_END_INT(w)
-#define CNV_INT_TO_LITTLE(w) CNV_LITTLE_TO_INT(w)
-
-#endif /* __VX_WORKS_SANDPOINT_824X__ */
-
-/************************************************************************************************/
-/************************************* VXWORKS. ARM T8300 IPPhone *****************************/
-/************************************************************************************************/
-#if defined( IPT_T8300 ) || defined( IPT_T8307 )
-
-#include <vxWorks.h>
-#include <sysLib.h>
-#include <taskLib.h>
-
-#define HCF_ALIGN 4 /* default to 4 byte alignment */
-
-#define BEAGLE_H253 /* Hermes 2.5.3 build, better to be in the project file */
-#define OOR_DDS /* Hermes 2.5.3 build, better to be in the project file */
-#define FATNIC
-
-
-#ifdef WVLAN_53
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDSTA
-#endif /* WVLAN_53 */
-
-#ifdef WVLAN_54
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDAP
-#endif /* WVLAN_54 */
-
-#ifdef WVLAN_56
-#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_END
-#endif /* WVLAN_56 */
-
-#if !defined MSF_COMPONENT_ID
-#error "you must define an MSF component ID: WVLAN_53, WVLAN_54, WVLAN_56"
-#endif
-
-#define MSF_COMPONENT_VAR 1
-
-#define HCF_EXT HCF_EXT_INFO_LOG
-//#define HCF_EXT HCF_EXT_INFO_LOG | HCF_EXT_MB
-#define HCF_SLEEP ( HCF_CDS | HCF_DDS )
-//#define HCF_SLEEP ( HCF_DDS )
-
-#ifndef HCF_ACT_WAKEUP
-#define HCF_ACT_WAKEUP 0x1D
-#endif // HCF_ACT_WAKEUP
-
-#if defined FATNIC || defined BEAGLE_H253
-#define T1__HCF_TYPE HCF_TYPE_STA
-#else
-//#define T1__HCF_TYPE HCF_TYPE_AP | HCF_TYPE_STA
-#define T1__HCF_TYPE HCF_TYPE_STA /* dz, Station code only */
-#endif
-
-#ifdef HERMES_USB
-#define T2__HCF_TYPE (T1__HCF_TYPE | HCF_TYPE_USB)
-#else // HERMES_USB
-#define T2__HCF_TYPE (T1__HCF_TYPE)
-#endif // HERMES_USB
-
-#ifdef _WARP
-#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5)
-#else // _WARP
-#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_WPA | HCF_TYPE_HII)
-//#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII) /* dz. no WPA support at this time, test code */
-#endif // WARP
-
-#ifdef _CCX
-#define T4__HCF_TYPE (T3__HCF_TYPE | HCF_TYPE_CCX)
-#else // _WARP
-#define T4__HCF_TYPE (T3__HCF_TYPE)
-#endif // _CCX
-
-#define T5__HCF_TYPE (T4__HCF_TYPE)
-
-// Default to TYPE_AP + SSN!
-#define HCF_TYPE (T5__HCF_TYPE )
-
-
-#define MSF_COMPONENT_MAJOR_VER 2
-#define MSF_COMPONENT_MINOR_VER 0
-
-#define HCF_IO HCF_IO_MEM
-#define HCF_DMA 0
-#define HCF_MEM_IO 1
-
-
-/* Endian is determined by vxWorks project compile option */
-#if (_BYTE_ORDER == _BIG_ENDIAN)
-#undef HCF_LITTLE_ENDIAN
-#define HCF_BIG_ENDIAN 1
-#endif
-
-
-#define CNV_END(w) ( ((hcf_16)(w) & 0x00FF) << 8 | ((hcf_16)(w) & 0xFF00) >> 8 )
-#if defined HCF_BIG_ENDIAN
-//******************************************** B I G E N D I A N *******************************************
-#define CNV_LITTLE_TO_INT(w) CNV_END(w) // endianess conversion needed
-#define CNV_BIG_TO_INT(w) (w) // no endianess conversion needed
-#else
-//****************************************** L I T T L E E N D I A N ****************************************
-#define CNV_LITTLE_TO_INT(w) (w) // no endianess conversion needed
-#define CNV_BIG_TO_INT(w) CNV_END(w) // endianess conversion needed
-#endif // HCF_BIG_ENDIAN
-
-// conversion macros which can be expressed in other macros
-#define CNV_INT_TO_LITTLE(w) CNV_LITTLE_TO_INT(w)
-#define CNV_INT_TO_BIG(w) CNV_BIG_TO_INT(w)
-
-
-
-#define IN_PORT_WORD( port ) *((volatile hcf_16 *)( port ))
-#define OUT_PORT_WORD( port, value ) *((volatile hcf_16 *)( port )) = ((hcf_16)( value ))
-//#define IN_PORT_BYTE( port ) *((volatile hcf_8 *)( port ))
-
-#define IN_PORT_STRING( port, addr, len) { \
- unsigned l = len; \
- hcf_16 *d = (hcf_16 *)(addr); \
- hcf_16 t; \
- while (l--) { \
- t = IN_PORT_WORD(port); \
- *d++ = CNV_LITTLE_TO_INT(t); \
- } \
-} // IN_PORT_STRING
-
-#define OUT_PORT_STRING( port, addr, len) { \
- unsigned l = (len); \
- hcf_16 *s = (hcf_16 *)(addr); \
- hcf_16 t; \
- while (l--) { \
- t = *s++; \
- t = CNV_LITTLE_TO_INT(t); \
- OUT_PORT_WORD(port, t); \
- } \
-} // OUT_PORT_STRING
-
-#define IN_PORT_STRING_16(port, dst, n) { \
- unsigned l = (n); \
- hcf_16 *d = (hcf_16 *)(dst); \
- while (l--) { \
- *d++ = IN_PORT_WORD(port); \
- } \
-} // IN_PORT_STRING_16
-
-#define OUT_PORT_STRING_16(port, src, n) { \
- hcf_16 t; \
- int l = (n); \
- hcf_16 *s = (hcf_16 *)(src); \
- while (l--) { \
- t = *s++; \
- OUT_PORT_WORD(port, t); \
- } \
-} // OUT_PORT_STRING_16
-
-/* #define HCF_YIELD (taskDelay(0) == 0) */
-
-
-
-#ifdef WVLAN_DEBUG
-#define DBG 1
-#define _DEBUG 1
-#endif
-
-/* we'll need to add these prints someday */
-#define OUTPUTDEBUGMSG(dprintf_exp)
-#define ASSERTDEBUGMSG(cond, dprintf_exp)
-
-#define HCF_INTERFACE_CONNECT(ifbp)
-#define HCF_INTERFACE_DISCONNECT(ifbp)
-#define HCF_ENTER_INTERFACE_FUNCT(ibfb)
-#define HCF_LEAVE_INTERFACE_FUNCT(ifbp)
-
-#define sysInWord(offsetAddr) IN_PORT_WORD(offsetAddr)
-#define sysInByte(offsetAddr) IN_PORT_BYTE(offsetAddr)
-#define sysOutWord(addr, value) OUT_PORT_WORD(addr, value)
-
-#endif /*IPT_T8300 */
-
/************************************************************************************************************/
/*********************************** **************************************/
/************************************************************************************************************/
@@ -2003,10 +478,6 @@ err: /* commented here */ /* "BSP is not defined..." */
#define HCF_BIG_ENDIAN 0
#endif // HCF_BIG_ENDIAN
-#if ! defined HCF_DL_ONLY
-#define HCF_DL_ONLY 0
-#endif // HCF_DL_ONLY
-
#if ! defined HCF_DMA
#define HCF_DMA 0
#endif // HCF_DMA
@@ -2015,14 +486,6 @@ err: /* commented here */ /* "BSP is not defined..." */
#define HCF_ENCAP HCF_ENC
#endif // HCF_ENCAP
-#if ! defined HCF_ENTRY
-#define HCF_ENTRY( ifbp )
-#endif // HCF_ENTRY
-
-#if ! defined HCF_EXIT
-#define HCF_EXIT( ifbp )
-#endif // HCF_EXIT
-
#if ! defined HCF_EXT
#define HCF_EXT 0
#endif // HCF_EXT
@@ -2064,11 +527,6 @@ err: /* commented here */ /* "BSP is not defined..." */
#define HCF_BIG_ENDIAN 1 //just for convenience of generating cfg_hcf_opt
#endif // HCF_BIG_ENDIAN
-#if HCF_DL_ONLY
-#undef HCF_DL_ONLY
-#define HCF_DL_ONLY 1 //just for convenience of generating cfg_hcf_opt
-#endif // HCF_DL_ONLY
-
#if HCF_DMA
#undef HCF_DMA
#define HCF_DMA 1 //just for convenience of generating cfg_hcf_opt
@@ -2244,21 +702,9 @@ err: primary variants 1 and 2 correspond with H-I only;
#define TEXT(x) x
#endif // TEXT
-#if !defined _TCHAR_DEFINED
-#define TCHAR char
-#endif // _TCHAR_DEFINED
-
/************************************************************************************************************/
/*********************** C O N F L I C T D E T E C T I O N & R E S O L U T I O N ************************/
/************************************************************************************************************/
-#if defined HCF_LITTLE_ENDIAN
-err: HCF_LITTLE_ENDIAN is obsolete;
-#endif // HCF_LITTLE_ENDIAN
-
-#if defined HCF_INT_OFF
-err: HCF_INT_OFF is obsolete;
-#endif //HCF_INT_OFF
-
#if HCF_ALIGN != 1 && HCF_ALIGN != 2 && HCF_ALIGN != 4 && HCF_ALIGN != 8
err: invalid value for HCF_ALIGN;
#endif // HCF_ALIGN
@@ -2276,10 +722,6 @@ err: these macros are not used consistently;
err: invalid value for HCF_BIG_ENDIAN;
#endif // HCF_BIG_ENDIAN
-#if HCF_DL_ONLY != 0 && HCF_DL_ONLY != 1
-err: invalid value for HCF_DL_ONLY;
-#endif // HCF_DL_ONLY
-
#if HCF_DMA != 0 && HCF_DMA != 1
err: invalid value for HCF_DMA;
#endif // HCF_DMA
diff --git a/drivers/staging/wlags49_h2/hcfdef.h b/drivers/staging/wlags49_h2/hcfdef.h
index cb1966d..a62b53a 100644
--- a/drivers/staging/wlags49_h2/hcfdef.h
+++ b/drivers/staging/wlags49_h2/hcfdef.h
@@ -1,286 +1,249 @@
-
-// vim:tw=110:ts=4:
#ifndef HCFDEFC_H
#define HCFDEFC_H 1
/*************************************************************************************************
-*
-* FILE : HCFDEF.H
-*
-* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.8 $
-* Original: 2004/05/28 14:05:35 Revision: 1.59 Tag: hcf7_t20040602_01
-* Original: 2004/05/13 15:31:45 Revision: 1.53 Tag: hcf7_t7_20040513_01
-* Original: 2004/04/15 09:24:42 Revision: 1.44 Tag: hcf7_t7_20040415_01
-* Original: 2004/04/13 14:22:45 Revision: 1.43 Tag: t7_20040413_01
-* Original: 2004/04/01 15:32:55 Revision: 1.40 Tag: t7_20040401_01
-* Original: 2004/03/10 15:39:28 Revision: 1.36 Tag: t20040310_01
-* Original: 2004/03/03 14:10:12 Revision: 1.34 Tag: t20040304_01
-* Original: 2004/03/02 09:27:12 Revision: 1.32 Tag: t20040302_03
-* Original: 2004/02/24 13:00:29 Revision: 1.29 Tag: t20040224_01
-* Original: 2004/02/18 17:13:57 Revision: 1.26 Tag: t20040219_01
-*
-* AUTHOR : Nico Valster
-*
-* SPECIFICATION: ...........
-*
-* DESC : Definitions and Prototypes for HCF only
-*
-**************************************************************************************************
-*
-*
-* SOFTWARE LICENSE
-*
-* This software is provided subject to the following terms and conditions,
-* which you should read carefully before using the software. Using this
-* software indicates your acceptance of these terms and conditions. If you do
-* not agree with these terms and conditions, do not use the software.
-*
-* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved
-* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved
-* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved
-* All rights reserved.
-*
-* Redistribution and use in source or binary forms, with or without
-* modifications, are permitted provided that the following conditions are met:
-*
-* . Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following Disclaimer as comments in the code as
-* well as in the documentation and/or other materials provided with the
-* distribution.
-*
-* . Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following Disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* . Neither the name of Agere Systems Inc. nor the names of the contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* Disclaimer
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
-* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
-* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
-* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-* ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-* DAMAGE.
-*
-*
-*************************************************************************************************/
+ *
+ * FILE : HCFDEF.H
+ *
+ * DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.8 $
+ * Original: 2004/05/28 14:05:35 Revision: 1.59 Tag: hcf7_t20040602_01
+ * Original: 2004/05/13 15:31:45 Revision: 1.53 Tag: hcf7_t7_20040513_01
+ * Original: 2004/04/15 09:24:42 Revision: 1.44 Tag: hcf7_t7_20040415_01
+ * Original: 2004/04/13 14:22:45 Revision: 1.43 Tag: t7_20040413_01
+ * Original: 2004/04/01 15:32:55 Revision: 1.40 Tag: t7_20040401_01
+ * Original: 2004/03/10 15:39:28 Revision: 1.36 Tag: t20040310_01
+ * Original: 2004/03/03 14:10:12 Revision: 1.34 Tag: t20040304_01
+ * Original: 2004/03/02 09:27:12 Revision: 1.32 Tag: t20040302_03
+ * Original: 2004/02/24 13:00:29 Revision: 1.29 Tag: t20040224_01
+ * Original: 2004/02/18 17:13:57 Revision: 1.26 Tag: t20040219_01
+ *
+ * AUTHOR : Nico Valster
+ *
+ * SPECIFICATION: ...........
+ *
+ * DESC : Definitions and Prototypes for HCF only
+ *
+ **************************************************************************************************
+ *
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved
+ * COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved
+ * COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following Disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ *************************************************************************************************/
/************************************************************************************************/
/********************************* P R E F I X E S ********************************************/
/************************************************************************************************/
-//IFB_ Interface Block
-//HCMD_ Hermes Command
-//HFS_ Hermes (Transmit/Receive) Frame Structure
-//HREG_ Hermes Register
+//IFB_ Interface Block
+//HCMD_ Hermes Command
+//HFS_ Hermes (Transmit/Receive) Frame Structure
+//HREG_ Hermes Register
/*************************************************************************************************/
-#if 0 //
-#define BIT0 0x0001
-#define BIT1 0x0002
-#define BIT2 0x0004
-#define BIT3 0x0008
-#define BIT4 0x0010
-#define BIT5 0x0020
-#define BIT6 0x0040
-#define BIT7 0x0080
-#define BIT8 0x0100
-#define BIT9 0x0200
-#define BIT10 0x0400
-#define BIT11 0x0800
-#define BIT12 0x1000
-#define BIT13 0x2000
-#define BIT14 0x4000
-#define BIT15 0x8000
-#define BIT16 0x00010000
-#define BIT17 0x00020000
-#define BIT18 0x00040000
-#define BIT19 0x00080000
-#define BIT20 0x00100000
-#define BIT21 0x00200000
-#define BIT22 0x00400000
-#define BIT23 0x00800000
-#define BIT24 0x01000000
-#define BIT25 0x02000000
-#define BIT26 0x04000000
-#define BIT27 0x08000000
-#define BIT28 0x10000000
-#define BIT29 0x20000000
-#define BIT30 0x40000000
-#define BIT31 0x80000000
-#endif // 0
-
/************************************************************************************************/
/********************************* GENERAL EQUATES **********************************************/
/************************************************************************************************/
-#define HCF_MAGIC 0x7D37 // "}7" Handle validation
+#define HCF_MAGIC 0x7D37 // "}7" Handle validation
-#define PLUG_DATA_OFFSET 0x00000800 //needed by some test tool on top of H-II NDIS driver
+#define PLUG_DATA_OFFSET 0x00000800 //needed by some test tool on top of H-II NDIS driver
-#define INI_TICK_INI 0x00040000L
+#define INI_TICK_INI 0x00040000L
-#define IO_IN 0 //hcfio_in_string
-#define IO_OUT 1 //hcfio_out_string
+#define IO_IN 0 //hcfio_in_string
+#define IO_OUT 1 //hcfio_out_string
//DO_ASSERT, create an artificial FALSE to force an ASSERT without the nasty compiler warning
-#define DO_ASSERT ( assert_ifbp->IFB_Magic != HCF_MAGIC && assert_ifbp->IFB_Magic == HCF_MAGIC )
-#define NT_ASSERT 0x0000 //, NEVER_TESTED
-#define NEVER_TESTED MERGE_2( 0xEFFE, 0xFEEF )
-#define SE_ASSERT 0x5EFF /* Side Effect, HCFASSERT invokation which are only called for the
- * side effect and which should never trigger */
-#define DHF_FILE_NAME_OFFSET 10000 //to distinguish DHF from HCF asserts by means of line number
-#define MMD_FILE_NAME_OFFSET 20000 //to distinguish MMD from HCF asserts by means of line number
+#define DO_ASSERT ( assert_ifbp->IFB_Magic != HCF_MAGIC && assert_ifbp->IFB_Magic == HCF_MAGIC )
+#define NT_ASSERT 0x0000 //, NEVER_TESTED
+#define NEVER_TESTED MERGE_2( 0xEFFE, 0xFEEF )
+#define SE_ASSERT 0x5EFF /* Side Effect, HCFASSERT invokation which are only called for the
+ * side effect and which should never trigger */
+#define DHF_FILE_NAME_OFFSET 10000 //to distinguish DHF from HCF asserts by means of line number
+#define MMD_FILE_NAME_OFFSET 20000 //to distinguish MMD from HCF asserts by means of line number
// trace codes used to
// 1: profile execution times via HCF_TRACE and HCF_TRACE_VALUE
// 2: hierarchical flow information via HCFLOGENTRY / HCFLOGEXIT
-//#define HCF_TRACE_CONNECT useless
-//#define HCF_TRACE_DISCONNECT useless
-#define HCF_TRACE_ACTION 0x0000 // 0x0001
-#define HCF_TRACE_CNTL 0x0001 // 0x0002
-#define HCF_TRACE_DMA_RX_GET 0x0002 // 0x0004
-#define HCF_TRACE_DMA_RX_PUT 0x0003 // 0x0008
-#define HCF_TRACE_DMA_TX_GET 0x0004 // 0x0010
-#define HCF_TRACE_DMA_TX_PUT 0x0005 // 0x0020
-#define HCF_TRACE_GET_INFO 0x0006 // 0x0040
-#define HCF_TRACE_PUT_INFO 0x0007 // 0x0080
-#define HCF_TRACE_RCV_MSG 0x0008 // 0x0100
-#define HCF_TRACE_SEND_MSG 0x0009 // 0x0200
-#define HCF_TRACE_SERVICE_NIC 0x000A // 0x0400
+//#define HCF_TRACE_CONNECT useless
+//#define HCF_TRACE_DISCONNECT useless
+#define HCF_TRACE_ACTION 0x0000 // 0x0001
+#define HCF_TRACE_CNTL 0x0001 // 0x0002
+#define HCF_TRACE_DMA_RX_GET 0x0002 // 0x0004
+#define HCF_TRACE_DMA_RX_PUT 0x0003 // 0x0008
+#define HCF_TRACE_DMA_TX_GET 0x0004 // 0x0010
+#define HCF_TRACE_DMA_TX_PUT 0x0005 // 0x0020
+#define HCF_TRACE_GET_INFO 0x0006 // 0x0040
+#define HCF_TRACE_PUT_INFO 0x0007 // 0x0080
+#define HCF_TRACE_RCV_MSG 0x0008 // 0x0100
+#define HCF_TRACE_SEND_MSG 0x0009 // 0x0200
+#define HCF_TRACE_SERVICE_NIC 0x000A // 0x0400
// #define HCF_TRACE_ 0x000C // 0x1000
// #define HCF_TRACE_ 0x000D // 0x2000
// #define HCF_TRACE_ 0x000E // 0x4000
// #define HCF_TRACE_ 0x000F // 0x8000
-// ============================================ HCF_TRACE_... codes below 0x0010 are asserted on re-entry
-#define HCF_TRACE_ACTION_KLUDGE 0x0010 /* once you start introducing kludges there is no end to it
- * this is an escape to do not assert on re-entrancy problem caused
- * by HCF_ACT_INT_FORCE_ON used to get Microsofts NDIS drivers going
- */
-#define HCF_TRACE_STRIO 0x0020
-#define HCF_TRACE_ALLOC 0X0021
-#define HCF_TRACE_DL 0X0023
-#define HCF_TRACE_ISR_INFO 0X0024
-#define HCF_TRACE_CALIBRATE 0x0026
-
-#define HCF_TRACE_CMD_CPL 0x0040
-#define HCF_TRACE_CMD_EXE 0x0041
-#define HCF_TRACE_GET_FID 0x0042
-#define HCF_TRACE_GET_FRAG 0x0043
-#define HCF_TRACE_INIT 0x0044
-#define HCF_TRACE_PUT_FRAG 0x0045
-#define HCF_TRACE_SETUP_BAP 0x0046
-
-#define HCF_TRACE_EXIT 0x8000 // Keil C warns "long constant truncated to int"
-
-//#define BAP_0 HREG_DATA_0 //Used by DMA controller to access NIC RAM
-#define BAP_1 HREG_DATA_1 //Used by HCF to access NIC RAM
+// ============================================ HCF_TRACE_... codes below 0x0010 are asserted on re-entry
+#define HCF_TRACE_ACTION_KLUDGE 0x0010 /* once you start introducing kludges there is no end to it
+ * this is an escape to do not assert on re-entrancy problem caused
+ * by HCF_ACT_INT_FORCE_ON used to get Microsofts NDIS drivers going
+ */
+#define HCF_TRACE_STRIO 0x0020
+#define HCF_TRACE_ALLOC 0X0021
+#define HCF_TRACE_DL 0X0023
+#define HCF_TRACE_ISR_INFO 0X0024
+#define HCF_TRACE_CALIBRATE 0x0026
+
+#define HCF_TRACE_CMD_CPL 0x0040
+#define HCF_TRACE_CMD_EXE 0x0041
+#define HCF_TRACE_GET_FID 0x0042
+#define HCF_TRACE_GET_FRAG 0x0043
+#define HCF_TRACE_INIT 0x0044
+#define HCF_TRACE_PUT_FRAG 0x0045
+#define HCF_TRACE_SETUP_BAP 0x0046
+
+#define HCF_TRACE_EXIT 0x8000 // Keil C warns "long constant truncated to int"
+
+//#define BAP_0 HREG_DATA_0 //Used by DMA controller to access NIC RAM
+#define BAP_1 HREG_DATA_1 //Used by HCF to access NIC RAM
//************************* Hermes Receive/Transmit Frame Structures
//HFS_STAT
//see MMD.H for HFS_STAT_ERR
-#define HFS_STAT_MSG_TYPE 0xE000 //Hermes reported Message Type
-#define HFS_STAT_MIC_KEY_ID 0x1800 //MIC key used (if any)
-#define HFS_STAT_1042 0x2000 //RFC1042 Encoded
-#define HFS_STAT_TUNNEL 0x4000 //Bridge-Tunnel Encoded
-#define HFS_STAT_WMP_MSG 0x6000 //WaveLAN-II Management Protocol Frame
+#define HFS_STAT_MSG_TYPE 0xE000 //Hermes reported Message Type
+#define HFS_STAT_MIC_KEY_ID 0x1800 //MIC key used (if any)
+#define HFS_STAT_1042 0x2000 //RFC1042 Encoded
+#define HFS_STAT_TUNNEL 0x4000 //Bridge-Tunnel Encoded
+#define HFS_STAT_WMP_MSG 0x6000 //WaveLAN-II Management Protocol Frame
#if (HCF_TYPE) & HCF_TYPE_WPA
-#define HFS_STAT_MIC 0x0010 //Frame contains MIC //;? re-instate when F/W ready
+#define HFS_STAT_MIC 0x0010 //Frame contains MIC //;? re-instate when F/W ready
#endif
//************************* Hermes Register Offsets and Command bits
-#define HREG_IO_RANGE 0x80 //I/O Range used by Hermes
+#define HREG_IO_RANGE 0x80 //I/O Range used by Hermes
//************************* Command/Status
-#define HREG_CMD 0x00 //
-#define HCMD_CMD_CODE 0x3F
-#define HREG_PARAM_0 0x02 //
-#define HREG_PARAM_1 0x04 //
-#define HREG_PARAM_2 0x06 //
-#define HREG_STAT 0x08 //
-#define HREG_STAT_CMD_CODE 0x003F //
-#define HREG_STAT_DIAG_ERR 0x0100
-#define HREG_STAT_INQUIRE_ERR 0x0500
-#define HREG_STAT_CMD_RESULT 0x7F00 //
-#define HREG_RESP_0 0x0A //
-#define HREG_RESP_1 0x0C //
-#define HREG_RESP_2 0x0E //
+#define HREG_CMD 0x00 //
+#define HCMD_CMD_CODE 0x3F
+#define HREG_PARAM_0 0x02 //
+#define HREG_PARAM_1 0x04 //
+#define HREG_PARAM_2 0x06 //
+#define HREG_STAT 0x08 //
+#define HREG_STAT_CMD_CODE 0x003F //
+#define HREG_STAT_DIAG_ERR 0x0100
+#define HREG_STAT_INQUIRE_ERR 0x0500
+#define HREG_STAT_CMD_RESULT 0x7F00 //
+#define HREG_RESP_0 0x0A //
+#define HREG_RESP_1 0x0C //
+#define HREG_RESP_2 0x0E //
//************************* FID Management
-#define HREG_INFO_FID 0x10 //
-#define HREG_RX_FID 0x20 //
-#define HREG_ALLOC_FID 0x22 //
-#define HREG_TX_COMPL_FID 0x24 //
+#define HREG_INFO_FID 0x10 //
+#define HREG_RX_FID 0x20 //
+#define HREG_ALLOC_FID 0x22 //
+#define HREG_TX_COMPL_FID 0x24 //
//************************* BAP
//20031030 HWi Inserted this again because the dongle code uses this (GPIF.C)
-//#define HREG_SELECT_0 0x18 //
-//#define HREG_OFFSET_0 0x1C //
-//#define HREG_DATA_0 0x36 //
+//#define HREG_SELECT_0 0x18 //
+//#define HREG_OFFSET_0 0x1C //
+//#define HREG_DATA_0 0x36 //
-//#define HREG_OFFSET_BUSY 0x8000 // use HCMD_BUSY
-#define HREG_OFFSET_ERR 0x4000 //
-//rsrvd #define HREG_OFFSET_DATA_OFFSET 0x0FFF //
+//#define HREG_OFFSET_BUSY 0x8000 // use HCMD_BUSY
+#define HREG_OFFSET_ERR 0x4000 //
+//rsrvd #define HREG_OFFSET_DATA_OFFSET 0x0FFF //
-#define HREG_SELECT_1 0x1A //
-#define HREG_OFFSET_1 0x1E //
-#define HREG_DATA_1 0x38 //
+#define HREG_SELECT_1 0x1A //
+#define HREG_OFFSET_1 0x1E //
+#define HREG_DATA_1 0x38 //
//************************* Event
-#define HREG_EV_STAT 0x30 //
-#define HREG_INT_EN 0x32 //
-#define HREG_EV_ACK 0x34 //
+#define HREG_EV_STAT 0x30 //
+#define HREG_INT_EN 0x32 //
+#define HREG_EV_ACK 0x34 //
-#define HREG_EV_TICK 0x8000 //Auxiliary Timer Tick
-//#define HREG_EV_RES 0x4000 //H-I only: H/W error (Wait Time-out)
-#define HREG_EV_INFO_DROP 0x2000 //WMAC did not have sufficient RAM to build Unsollicited Frame
+#define HREG_EV_TICK 0x8000 //Auxiliary Timer Tick
+//#define HREG_EV_RES 0x4000 //H-I only: H/W error (Wait Time-out)
+#define HREG_EV_INFO_DROP 0x2000 //WMAC did not have sufficient RAM to build Unsollicited Frame
#if (HCF_TYPE) & HCF_TYPE_HII5
-#define HREG_EV_ACK_REG_READY 0x0000
+#define HREG_EV_ACK_REG_READY 0x0000
#else
-#define HREG_EV_ACK_REG_READY 0x1000 //Workaround Kludge bit for H-II (not H-II.5)
+#define HREG_EV_ACK_REG_READY 0x1000 //Workaround Kludge bit for H-II (not H-II.5)
#endif // HCF_TYPE_HII5
#if (HCF_SLEEP) & ( HCF_CDS | HCF_DDS )
-#define HREG_EV_SLEEP_REQ 0x0800
+#define HREG_EV_SLEEP_REQ 0x0800
#else
-#define HREG_EV_SLEEP_REQ 0x0000
+#define HREG_EV_SLEEP_REQ 0x0000
#endif // HCF_CDS / HCF_DDS
#if HCF_DMA
-//#define HREG_EV_LPESC 0x0400 // firmware sets this bit and clears it, not for host usage.
-#define HREG_EV_RDMAD 0x0200 // rx frame in host memory
-#define HREG_EV_TDMAD 0x0100 // tx frame in host memory processed
-//#define HREG_EV_RXDMA 0x0040 // firmware kicks off DMA engine (bit is not for host usage)
-//#define HREG_EV_TXDMA 0x0020 // firmware kicks off DMA engine (bit is not for host usage)
-#define HREG_EV_FW_DMA 0x0460 // firmware / DMA engine I/F (bits are not for host usage)
+//#define HREG_EV_LPESC 0x0400 // firmware sets this bit and clears it, not for host usage.
+#define HREG_EV_RDMAD 0x0200 // rx frame in host memory
+#define HREG_EV_TDMAD 0x0100 // tx frame in host memory processed
+//#define HREG_EV_RXDMA 0x0040 // firmware kicks off DMA engine (bit is not for host usage)
+//#define HREG_EV_TXDMA 0x0020 // firmware kicks off DMA engine (bit is not for host usage)
+#define HREG_EV_FW_DMA 0x0460 // firmware / DMA engine I/F (bits are not for host usage)
#else
-#define HREG_EV_FW_DMA 0x0000
+#define HREG_EV_FW_DMA 0x0000
#endif // HCF_DMA
-#define HREG_EV_INFO 0x0080 // Asynchronous Information Frame
-#define HREG_EV_CMD 0x0010 // Command completed, Status and Response available
-#define HREG_EV_ALLOC 0x0008 // Asynchronous part of Allocation/Reclaim completed
-#define HREG_EV_TX_EXC 0x0004 // Asynchronous Transmission unsuccessful completed
-#define HREG_EV_TX 0x0002 // Asynchronous Transmission successful completed
-#define HREG_EV_RX 0x0001 // Asynchronous Receive Frame
-
-#define HREG_EV_TX_EXT ( (HCF_EXT) & (HCF_EXT_INT_TX_EX | HCF_EXT_INT_TICK ) )
- /* HREG_EV_TX_EXT := 0x0000 or HREG_EV_TX_EXC and/or HREG_EV_TICK
- * could be extended with HREG_EV_TX */
+#define HREG_EV_INFO 0x0080 // Asynchronous Information Frame
+#define HREG_EV_CMD 0x0010 // Command completed, Status and Response available
+#define HREG_EV_ALLOC 0x0008 // Asynchronous part of Allocation/Reclaim completed
+#define HREG_EV_TX_EXC 0x0004 // Asynchronous Transmission unsuccessful completed
+#define HREG_EV_TX 0x0002 // Asynchronous Transmission successful completed
+#define HREG_EV_RX 0x0001 // Asynchronous Receive Frame
+
+#define HREG_EV_TX_EXT ( (HCF_EXT) & (HCF_EXT_INT_TX_EX | HCF_EXT_INT_TICK ) )
+/* HREG_EV_TX_EXT := 0x0000 or HREG_EV_TX_EXC and/or HREG_EV_TICK
+ * could be extended with HREG_EV_TX */
#if HCF_EXT_INT_TX_EX != HREG_EV_TX_EXC
err: these values should match;
#endif // HCF_EXT_INT_TX_EX / HREG_EV_TX_EXC
@@ -290,97 +253,97 @@ err: these values should match;
#endif // HCF_EXT_INT_TICK / HREG_EV_TICK
//************************* Host Software
-#define HREG_SW_0 0x28 //
-#define HREG_SW_1 0x2A //
-#define HREG_SW_2 0x2C //
-//rsrvd #define HREG_SW_3 0x2E //
+#define HREG_SW_0 0x28 //
+#define HREG_SW_1 0x2A //
+#define HREG_SW_2 0x2C //
+//rsrvd #define HREG_SW_3 0x2E //
//************************* Control and Auxiliary Port
-#define HREG_IO 0x12
-#define HREG_IO_SRESET 0x0001
-#define HREG_IO_WAKEUP_ASYNC 0x0002
-#define HREG_IO_WOKEN_UP 0x0004
-#define HREG_CNTL 0x14 //
-//#define HREG_CNTL_WAKEUP_SYNC 0x0001
-#define HREG_CNTL_AUX_ENA_STAT 0xC000
-#define HREG_CNTL_AUX_DIS_STAT 0x0000
-#define HREG_CNTL_AUX_ENA_CNTL 0x8000
-#define HREG_CNTL_AUX_DIS_CNTL 0x4000
-#define HREG_CNTL_AUX_DSD 0x2000
-#define HREG_CNTL_AUX_ENA (HREG_CNTL_AUX_ENA_CNTL | HREG_CNTL_AUX_DIS_CNTL )
-#define HREG_SPARE 0x16 //
-#define HREG_AUX_PAGE 0x3A //
-#define HREG_AUX_OFFSET 0x3C //
-#define HREG_AUX_DATA 0x3E //
+#define HREG_IO 0x12
+#define HREG_IO_SRESET 0x0001
+#define HREG_IO_WAKEUP_ASYNC 0x0002
+#define HREG_IO_WOKEN_UP 0x0004
+#define HREG_CNTL 0x14 //
+//#define HREG_CNTL_WAKEUP_SYNC 0x0001
+#define HREG_CNTL_AUX_ENA_STAT 0xC000
+#define HREG_CNTL_AUX_DIS_STAT 0x0000
+#define HREG_CNTL_AUX_ENA_CNTL 0x8000
+#define HREG_CNTL_AUX_DIS_CNTL 0x4000
+#define HREG_CNTL_AUX_DSD 0x2000
+#define HREG_CNTL_AUX_ENA (HREG_CNTL_AUX_ENA_CNTL | HREG_CNTL_AUX_DIS_CNTL )
+#define HREG_SPARE 0x16 //
+#define HREG_AUX_PAGE 0x3A //
+#define HREG_AUX_OFFSET 0x3C //
+#define HREG_AUX_DATA 0x3E //
#if HCF_DMA
//************************* DMA (bus mastering)
- // Be careful to use these registers only at a genuine 32 bits NIC
- // On 16 bits NICs, these addresses are mapped into the range 0x00 through 0x3F with all consequences
- // thereof, e.g. HREG_DMA_CTRL register maps to HREG_CMD.
-#define HREG_DMA_CTRL 0x0040
-#define HREG_TXDMA_PTR32 0x0044
-#define HREG_TXDMA_PRIO_PTR32 0x0048
-#define HREG_TXDMA_HIPRIO_PTR32 0x004C
-#define HREG_RXDMA_PTR32 0x0050
-#define HREG_CARDDETECT_1 0x007C // contains 7D37
-#define HREG_CARDDETECT_2 0x007E // contains 7DE7
-#define HREG_FREETIMER 0x0058
-#define HREG_DMA_RX_CNT 0x0026
+// Be careful to use these registers only at a genuine 32 bits NIC
+// On 16 bits NICs, these addresses are mapped into the range 0x00 through 0x3F with all consequences
+// thereof, e.g. HREG_DMA_CTRL register maps to HREG_CMD.
+#define HREG_DMA_CTRL 0x0040
+#define HREG_TXDMA_PTR32 0x0044
+#define HREG_TXDMA_PRIO_PTR32 0x0048
+#define HREG_TXDMA_HIPRIO_PTR32 0x004C
+#define HREG_RXDMA_PTR32 0x0050
+#define HREG_CARDDETECT_1 0x007C // contains 7D37
+#define HREG_CARDDETECT_2 0x007E // contains 7DE7
+#define HREG_FREETIMER 0x0058
+#define HREG_DMA_RX_CNT 0x0026
/******************************************************************************
-* Defines for the bits in the DmaControl register (@40h)
-******************************************************************************/
-#define HREG_DMA_CTRL_RXHWEN 0x80000000 // high word enable bit
-#define HREG_DMA_CTRL_RXRESET 0x40000000 // tx dma init bit
-#define HREG_DMA_CTRL_RXBAP1 BIT29
-#define HREG_DMA_CTRL_RX_STALLED BIT28
-#define HREG_DMA_CTRL_RXAUTOACK_DMADONE BIT27 // no host involvement req. for TDMADONE event
-#define HREG_DMA_CTRL_RXAUTOACK_INFO BIT26 // no host involvement req. for alloc event
-#define HREG_DMA_CTRL_RXAUTOACK_DMAEN 0x02000000 // no host involvement req. for TxDMAen event
-#define HREG_DMA_CTRL_RXAUTOACK_RX 0x01000000 // no host involvement req. for tx event
-#define HREG_DMA_CTRL_RX_BUSY BIT23 // read only bit
-//#define HREG_DMA_CTRL_RX_RBUFCONT_PLAIN 0 // bits 21..20
-//#define HREG_DMA_CTRL_RX_MODE_PLAIN_DMA 0 // mode 0
-#define HREG_DMA_CTRL_RX_MODE_SINGLE_PACKET 0x00010000 // mode 1
-#define HREG_DMA_CTRL_RX_MODE_MULTI_PACKET 0x00020000 // mode 2
-//#define HREG_DMA_CTRL_RX_MODE_DISABLE (0x00020000|0x00010000) // disable tx dma engine
-#define HREG_DMA_CTRL_TXHWEN 0x8000 // low word enable bit
-#define HREG_DMA_CTRL_TXRESET 0x4000 // rx dma init bit
-#define HREG_DMA_CTRL_TXBAP1 BIT13
-#define HREG_DMA_CTRL_TXAUTOACK_DMADONE BIT11 // no host involvement req. for RxDMADONE event
-#define HREG_DMA_CTRL_TXAUTOACK_DMAEN 0x00000400 // no host involvement req. for RxDMAen event
-#define HREG_DMA_CTRL_TXAUTOACK_DMAALLOC 0x00000200 // no host involvement req. for info event
-#define HREG_DMA_CTRL_TXAUTOACK_TX 0x00000100 // no host involvement req. for rx event
-#define HREG_DMA_CTRL_TX_BUSY BIT7 // read only bit
-//#define HREG_DMA_CTRL_TX_TBUFCONT_PLAIN 0 // bits 6..5
-//#define HREG_DMA_CTRL_TX_MODE_PLAIN_DMA 0 // mode 0
-#define HREG_DMA_CTRL_TX_MODE_SINGLE_PACKET BIT0 // mode 1
-#define HREG_DMA_CTRL_TX_MODE_MULTI_PACKET 0x00000002 // mode 2
-//#define HREG_DMA_CTRL_TX_MODE_DISABLE (0x00000001|0x00000002) // disable tx dma engine
+ * Defines for the bits in the DmaControl register (@40h)
+ ******************************************************************************/
+#define HREG_DMA_CTRL_RXHWEN 0x80000000 // high word enable bit
+#define HREG_DMA_CTRL_RXRESET 0x40000000 // tx dma init bit
+#define HREG_DMA_CTRL_RXBAP1 BIT29
+#define HREG_DMA_CTRL_RX_STALLED BIT28
+#define HREG_DMA_CTRL_RXAUTOACK_DMADONE BIT27 // no host involvement req. for TDMADONE event
+#define HREG_DMA_CTRL_RXAUTOACK_INFO BIT26 // no host involvement req. for alloc event
+#define HREG_DMA_CTRL_RXAUTOACK_DMAEN 0x02000000 // no host involvement req. for TxDMAen event
+#define HREG_DMA_CTRL_RXAUTOACK_RX 0x01000000 // no host involvement req. for tx event
+#define HREG_DMA_CTRL_RX_BUSY BIT23 // read only bit
+//#define HREG_DMA_CTRL_RX_RBUFCONT_PLAIN 0 // bits 21..20
+//#define HREG_DMA_CTRL_RX_MODE_PLAIN_DMA 0 // mode 0
+#define HREG_DMA_CTRL_RX_MODE_SINGLE_PACKET 0x00010000 // mode 1
+#define HREG_DMA_CTRL_RX_MODE_MULTI_PACKET 0x00020000 // mode 2
+//#define HREG_DMA_CTRL_RX_MODE_DISABLE (0x00020000|0x00010000) // disable tx dma engine
+#define HREG_DMA_CTRL_TXHWEN 0x8000 // low word enable bit
+#define HREG_DMA_CTRL_TXRESET 0x4000 // rx dma init bit
+#define HREG_DMA_CTRL_TXBAP1 BIT13
+#define HREG_DMA_CTRL_TXAUTOACK_DMADONE BIT11 // no host involvement req. for RxDMADONE event
+#define HREG_DMA_CTRL_TXAUTOACK_DMAEN 0x00000400 // no host involvement req. for RxDMAen event
+#define HREG_DMA_CTRL_TXAUTOACK_DMAALLOC 0x00000200 // no host involvement req. for info event
+#define HREG_DMA_CTRL_TXAUTOACK_TX 0x00000100 // no host involvement req. for rx event
+#define HREG_DMA_CTRL_TX_BUSY BIT7 // read only bit
+//#define HREG_DMA_CTRL_TX_TBUFCONT_PLAIN 0 // bits 6..5
+//#define HREG_DMA_CTRL_TX_MODE_PLAIN_DMA 0 // mode 0
+#define HREG_DMA_CTRL_TX_MODE_SINGLE_PACKET BIT0 // mode 1
+#define HREG_DMA_CTRL_TX_MODE_MULTI_PACKET 0x00000002 // mode 2
+//#define HREG_DMA_CTRL_TX_MODE_DISABLE (0x00000001|0x00000002) // disable tx dma engine
//configuration DWORD to configure DMA for mode2 operation, using BAP0 as the DMA BAP.
#define DMA_CTRLSTAT_GO (HREG_DMA_CTRL_RXHWEN | HREG_DMA_CTRL_RX_MODE_MULTI_PACKET | \
HREG_DMA_CTRL_RXAUTOACK_DMAEN | HREG_DMA_CTRL_RXAUTOACK_RX | \
HREG_DMA_CTRL_TXHWEN | /*;?HREG_DMA_CTRL_TX_TBUFCONT_PLAIN |*/ \
- HREG_DMA_CTRL_TX_MODE_MULTI_PACKET | HREG_DMA_CTRL_TXAUTOACK_DMAEN |\
+ HREG_DMA_CTRL_TX_MODE_MULTI_PACKET | HREG_DMA_CTRL_TXAUTOACK_DMAEN | \
HREG_DMA_CTRL_TXAUTOACK_DMAALLOC)
//configuration DWORD to reset both the Tx and Rx DMA engines
#define DMA_CTRLSTAT_RESET (HREG_DMA_CTRL_RXHWEN | HREG_DMA_CTRL_RXRESET | HREG_DMA_CTRL_TXHWEN | HREG_DMA_CTRL_TXRESET)
-//#define DESC_DMA_OWNED 0x80000000 // BIT31
-#define DESC_DMA_OWNED 0x8000 // BIT31
-#define DESC_SOP 0x8000 // BIT15
-#define DESC_EOP 0x4000 // BIT14
+//#define DESC_DMA_OWNED 0x80000000 // BIT31
+#define DESC_DMA_OWNED 0x8000 // BIT31
+#define DESC_SOP 0x8000 // BIT15
+#define DESC_EOP 0x4000 // BIT14
-#define DMA_RX 0
-#define DMA_TX 1
+#define DMA_RX 0
+#define DMA_TX 1
-// #define IFB_RxFirstDesc IFB_FirstDesc[DMA_RX]
-// #define IFB_TxFirstDesc IFB_FirstDesc[DMA_TX]
-// #define IFB_RxLastDesc IFB_LastDesc[DMA_RX]
-// #define IFB_TxLastDesc IFB_LastDesc[DMA_TX]
+// #define IFB_RxFirstDesc IFB_FirstDesc[DMA_RX]
+// #define IFB_TxFirstDesc IFB_FirstDesc[DMA_TX]
+// #define IFB_RxLastDesc IFB_LastDesc[DMA_RX]
+// #define IFB_TxLastDesc IFB_LastDesc[DMA_TX]
#endif // HCF_DMA
//
@@ -390,96 +353,96 @@ err: these values should match;
// Hermes Command Codes and Qualifier bits
-#define HCMD_BUSY 0x8000 // Busy bit, applicable for all commands
-#define HCMD_INI 0x0000 //
-#define HCMD_ENABLE HCF_CNTL_ENABLE // 0x0001
-#define HCMD_DISABLE HCF_CNTL_DISABLE // 0x0002
-#define HCMD_CONNECT HCF_CNTL_CONNECT // 0x0003
-#define HCMD_EXECUTE 0x0004 //
-#define HCMD_DISCONNECT HCF_CNTL_DISCONNECT // 0x0005
-#define HCMD_SLEEP 0x0006 //
-#define HCMD_CONTINUE HCF_CNTL_CONTINUE // 0x0007
-#define HCMD_RETRY 0x0100 // Retry bit
-#define HCMD_ALLOC 0x000A //
-#define HCMD_TX 0x000B //
-#define HCMD_RECL 0x0100 // Reclaim bit, applicable for Tx and Inquire
-#define HCMD_INQUIRE 0x0011 //
-#define HCMD_ACCESS 0x0021 //
-#define HCMD_ACCESS_WRITE 0x0100 // Write bit
-#define HCMD_PROGRAM 0x0022 //
-#define HCMD_READ_MIF 0x0030
-#define HCMD_WRITE_MIF 0x0031
-#define HCMD_THESEUS 0x0038
-#define HCMD_STARTPREAMBLE 0x0E00 // Start continuous preamble Tx
-#define HCMD_STOP 0x0F00 // Stop Theseus test mode
+#define HCMD_BUSY 0x8000 // Busy bit, applicable for all commands
+#define HCMD_INI 0x0000 //
+#define HCMD_ENABLE HCF_CNTL_ENABLE // 0x0001
+#define HCMD_DISABLE HCF_CNTL_DISABLE // 0x0002
+#define HCMD_CONNECT HCF_CNTL_CONNECT // 0x0003
+#define HCMD_EXECUTE 0x0004 //
+#define HCMD_DISCONNECT HCF_CNTL_DISCONNECT // 0x0005
+#define HCMD_SLEEP 0x0006 //
+#define HCMD_CONTINUE HCF_CNTL_CONTINUE // 0x0007
+#define HCMD_RETRY 0x0100 // Retry bit
+#define HCMD_ALLOC 0x000A //
+#define HCMD_TX 0x000B //
+#define HCMD_RECL 0x0100 // Reclaim bit, applicable for Tx and Inquire
+#define HCMD_INQUIRE 0x0011 //
+#define HCMD_ACCESS 0x0021 //
+#define HCMD_ACCESS_WRITE 0x0100 // Write bit
+#define HCMD_PROGRAM 0x0022 //
+#define HCMD_READ_MIF 0x0030
+#define HCMD_WRITE_MIF 0x0031
+#define HCMD_THESEUS 0x0038
+#define HCMD_STARTPREAMBLE 0x0E00 // Start continuous preamble Tx
+#define HCMD_STOP 0x0F00 // Stop Theseus test mode
//Configuration Management
//
-#define CFG_DRV_ACT_RANGES_PRI_3_BOTTOM 1 // Default Bottom Compatibility for Primary Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_PRI_3_TOP 1 // Default Top Compatibility for Primary Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_PRI_3_BOTTOM 1 // Default Bottom Compatibility for Primary Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_PRI_3_TOP 1 // Default Top Compatibility for Primary Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_HSI_4_BOTTOM 1 // Default Bottom Compatibility for H/W - driver I/F
-#define CFG_DRV_ACT_RANGES_HSI_4_TOP 1 // Default Top Compatibility for H/W - driver I/F
+#define CFG_DRV_ACT_RANGES_HSI_4_BOTTOM 1 // Default Bottom Compatibility for H/W - driver I/F
+#define CFG_DRV_ACT_RANGES_HSI_4_TOP 1 // Default Top Compatibility for H/W - driver I/F
-#define CFG_DRV_ACT_RANGES_HSI_5_BOTTOM 1 // Default Bottom Compatibility for H/W - driver I/F
-#define CFG_DRV_ACT_RANGES_HSI_5_TOP 1 // Default Top Compatibility for H/W - driver I/F
+#define CFG_DRV_ACT_RANGES_HSI_5_BOTTOM 1 // Default Bottom Compatibility for H/W - driver I/F
+#define CFG_DRV_ACT_RANGES_HSI_5_TOP 1 // Default Top Compatibility for H/W - driver I/F
#if (HCF_TYPE) & HCF_TYPE_WPA
-#define CFG_DRV_ACT_RANGES_APF_1_BOTTOM 16 // Default Bottom Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_1_TOP 16 // Default Top Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_1_BOTTOM 16 // Default Bottom Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_1_TOP 16 // Default Top Compatibility for AP Firmware - driver I/F
#else //;? is this REALLY O.K.
-#define CFG_DRV_ACT_RANGES_APF_1_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_1_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_1_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_1_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F
#endif // HCF_TYPE_WPA
-#define CFG_DRV_ACT_RANGES_APF_2_BOTTOM 2 // Default Bottom Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_2_TOP 2 // Default Top Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_2_BOTTOM 2 // Default Bottom Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_2_TOP 2 // Default Top Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_3_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_3_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_3_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_3_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_4_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_APF_4_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_4_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_APF_4_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F
#if (HCF_TYPE) & HCF_TYPE_HII5
-#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM 6 // Default Bottom Compatibility for Station Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_STA_2_TOP 6 // Default Top Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM 6 // Default Bottom Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_2_TOP 6 // Default Top Compatibility for Station Firmware - driver I/F
#else // (HCF_TYPE) & HCF_TYPE_HII5
-#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_STA_2_TOP 2 // Default Top Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_2_TOP 2 // Default Top Compatibility for Station Firmware - driver I/F
#endif // (HCF_TYPE) & HCF_TYPE_HII5
-#define CFG_DRV_ACT_RANGES_STA_3_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_STA_3_TOP 1 // Default Top Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_3_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_3_TOP 1 // Default Top Compatibility for Station Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_STA_4_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F
-#define CFG_DRV_ACT_RANGES_STA_4_TOP 1 // Default Top Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_4_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F
+#define CFG_DRV_ACT_RANGES_STA_4_TOP 1 // Default Top Compatibility for Station Firmware - driver I/F
//---------------------------------------------------------------------------------------------------------------------
#if defined HCF_CFG_PRI_1_TOP || defined HCF_CFG_PRI_1_BOTTOM
-err: PRI_1 not supported for H-I; // Compatibility for Primary Firmware - driver I/F
+err: PRI_1 not supported for H-I; // Compatibility for Primary Firmware - driver I/F
#endif // HCF_CFG_PRI_1_TOP / HCF_CFG_PRI_1_BOTTOM
#if defined HCF_CFG_PRI_2_TOP || defined HCF_CFG_PRI_2_BOTTOM
-err: PRI_2 not supported for H-I; // Compatibility for Primary Firmware - driver I/F
+err: PRI_2 not supported for H-I; // Compatibility for Primary Firmware - driver I/F
#endif // HCF_CFG_PRI_2_TOP / HCF_CFG_PRI_2_BOTTOM
-#ifdef HCF_CFG_PRI_3_TOP // Top Compatibility for Primary Firmware - driver I/F
-#if HCF_CFG_PRI_3_TOP == 0 || \
+#ifdef HCF_CFG_PRI_3_TOP // Top Compatibility for Primary Firmware - driver I/F
+#if HCF_CFG_PRI_3_TOP == 0 || \
CFG_DRV_ACT_RANGES_PRI_3_BOTTOM <= HCF_CFG_PRI_3_TOP && HCF_CFG_PRI_3_TOP <= CFG_DRV_ACT_RANGES_PRI_3_TOP
#undef CFG_DRV_ACT_RANGES_PRI_3_TOP
-#define CFG_DRV_ACT_RANGES_PRI_3_TOP HCF_CFG_PRI_3_TOP
+#define CFG_DRV_ACT_RANGES_PRI_3_TOP HCF_CFG_PRI_3_TOP
#else
err: ;
#endif
#endif // HCF_CFG_PRI_3_TOP
-#ifdef HCF_CFG_PRI_3_BOTTOM // Bottom Compatibility for Primary Firmware - driver I/F
+#ifdef HCF_CFG_PRI_3_BOTTOM // Bottom Compatibility for Primary Firmware - driver I/F
#if CFG_DRV_ACT_RANGES_PRI_3_BOTTOM <= HCF_CFG_PRI_3_BOTTOM && HCF_CFG_PRI_3_BOTTOM <= CFG_DRV_ACT_RANGES_PRI_3_TOP
#undef CFG_DRV_ACT_RANGES_PRI_3_BOTTOM
-#define CFG_DRV_ACT_RANGES_PRI_3_BOTTOM HCF_CFG_PRI_3_BOTTOM
+#define CFG_DRV_ACT_RANGES_PRI_3_BOTTOM HCF_CFG_PRI_3_BOTTOM
#else
err: ;
#endif
@@ -488,77 +451,77 @@ err: ;
//---------------------------------------------------------------------------------------------------------------------
#if defined HCF_CFG_HSI_0_TOP || defined HCF_CFG_HSI_0_BOTTOM
-err: HSI_0 not supported for H-I; // Compatibility for HSI I/F
+err: HSI_0 not supported for H-I; // Compatibility for HSI I/F
#endif // HCF_CFG_HSI_0_TOP / HCF_CFG_HSI_0_BOTTOM
#if defined HCF_CFG_HSI_1_TOP || defined HCF_CFG_HSI_1_BOTTOM
-err: HSI_1 not supported for H-I; // Compatibility for HSI I/F
+err: HSI_1 not supported for H-I; // Compatibility for HSI I/F
#endif // HCF_CFG_HSI_1_TOP / HCF_CFG_HSI_1_BOTTOM
#if defined HCF_CFG_HSI_2_TOP || defined HCF_CFG_HSI_2_BOTTOM
-err: HSI_2 not supported for H-I; // Compatibility for HSI I/F
+err: HSI_2 not supported for H-I; // Compatibility for HSI I/F
#endif // HCF_CFG_HSI_2_TOP / HCF_CFG_HSI_2_BOTTOM
#if defined HCF_CFG_HSI_3_TOP || defined HCF_CFG_HSI_3_BOTTOM
-err: HSI_3 not supported for H-I; // Compatibility for HSI I/F
+err: HSI_3 not supported for H-I; // Compatibility for HSI I/F
#endif // HCF_CFG_HSI_3_TOP / HCF_CFG_HSI_3_BOTTOM
-#ifdef HCF_CFG_HSI_4_TOP // Top Compatibility for HSI I/F
-#if HCF_CFG_HSI_4_TOP == 0 || \
+#ifdef HCF_CFG_HSI_4_TOP // Top Compatibility for HSI I/F
+#if HCF_CFG_HSI_4_TOP == 0 || \
CFG_DRV_ACT_RANGES_HSI_4_BOTTOM <= CF_CFG_HSI_4_TOP && HCF_CFG_HSI_4_TOP <= CFG_DRV_ACT_RANGES_HSI_4_TOP
#undef CFG_DRV_ACT_RANGES_HSI_4_TOP
-#define CFG_DRV_ACT_RANGES_HSI_4_TOP HCF_CFG_HSI_4_TOP
+#define CFG_DRV_ACT_RANGES_HSI_4_TOP HCF_CFG_HSI_4_TOP
#else
err: ;
#endif
#endif // HCF_CFG_HSI_4_TOP
-#ifdef HCF_CFG_HSI_4_BOTTOM // Bottom Compatibility for HSI I/F
+#ifdef HCF_CFG_HSI_4_BOTTOM // Bottom Compatibility for HSI I/F
#if CFG_DRV_ACT_RANGES_HSI_4_BOTTOM <= HCF_CFG_HSI_4_BOTTOM && HCF_CFG_HSI_4_BOTTOM <= CFG_DRV_ACT_RANGES_HSI_4_TOP
#undef CFG_DRV_ACT_RANGES_HSI_4_BOTTOM
-#define CFG_DRV_ACT_RANGES_HSI_4_BOTTOM HCF_CFG_HSI_4_BOTTOM
+#define CFG_DRV_ACT_RANGES_HSI_4_BOTTOM HCF_CFG_HSI_4_BOTTOM
#else
err: ;
#endif
#endif // HCF_CFG_HSI_4_BOTTOM
-#ifdef HCF_CFG_HSI_5_TOP // Top Compatibility for HSI I/F
-#if HCF_CFG_HSI_5_TOP == 0 || \
+#ifdef HCF_CFG_HSI_5_TOP // Top Compatibility for HSI I/F
+#if HCF_CFG_HSI_5_TOP == 0 || \
CFG_DRV_ACT_RANGES_HSI_5_BOTTOM <= CF_CFG_HSI_5_TOP && HCF_CFG_HSI_5_TOP <= CFG_DRV_ACT_RANGES_HSI_5_TOP
#undef CFG_DRV_ACT_RANGES_HSI_5_TOP
-#define CFG_DRV_ACT_RANGES_HSI_5_TOP HCF_CFG_HSI_5_TOP
+#define CFG_DRV_ACT_RANGES_HSI_5_TOP HCF_CFG_HSI_5_TOP
#else
err: ;
#endif
#endif // HCF_CFG_HSI_5_TOP
-#ifdef HCF_CFG_HSI_5_BOTTOM // Bottom Compatibility for HSI I/F
+#ifdef HCF_CFG_HSI_5_BOTTOM // Bottom Compatibility for HSI I/F
#if CFG_DRV_ACT_RANGES_HSI_5_BOTTOM <= HCF_CFG_HSI_5_BOTTOM && HCF_CFG_HSI_5_BOTTOM <= CFG_DRV_ACT_RANGES_HSI_5_TOP
#undef CFG_DRV_ACT_RANGES_HSI_5_BOTTOM
-#define CFG_DRV_ACT_RANGES_HSI_5_BOTTOM HCF_CFG_HSI_5_BOTTOM
+#define CFG_DRV_ACT_RANGES_HSI_5_BOTTOM HCF_CFG_HSI_5_BOTTOM
#else
err: ;
#endif
#endif // HCF_CFG_HSI_5_BOTTOM
//---------------------------------------------------------------------------------------------------------------------
#if defined HCF_CFG_APF_1_TOP || defined HCF_CFG_APF_1_BOTTOM
-err: APF_1 not supported for H-I; // Compatibility for AP Firmware - driver I/F
+err: APF_1 not supported for H-I; // Compatibility for AP Firmware - driver I/F
#endif // HCF_CFG_APF_1_TOP / HCF_CFG_APF_1_BOTTOM
-#ifdef HCF_CFG_APF_2_TOP // Top Compatibility for AP Firmware - driver I/F
-#if HCF_CFG_APF_2_TOP == 0 || \
+#ifdef HCF_CFG_APF_2_TOP // Top Compatibility for AP Firmware - driver I/F
+#if HCF_CFG_APF_2_TOP == 0 || \
CFG_DRV_ACT_RANGES_APF_2_BOTTOM <= HCF_CFG_APF_2_TOP && HCF_CFG_APF_2_TOP <= CFG_DRV_ACT_RANGES_APF_2_TOP
#undef CFG_DRV_ACT_RANGES_APF_2_TOP
-#define CFG_DRV_ACT_RANGES_APF_2_TOP HCF_CFG_APF_2_TOP
+#define CFG_DRV_ACT_RANGES_APF_2_TOP HCF_CFG_APF_2_TOP
#else
err: ;
#endif
#endif // HCF_CFG_APF_TOP
-#ifdef HCF_CFG_APF_2_BOTTOM // Bottom Compatibility for AP Firmware - driver I/F
+#ifdef HCF_CFG_APF_2_BOTTOM // Bottom Compatibility for AP Firmware - driver I/F
#if CFG_DRV_ACT_RANGES_APF_2_BOTTOM <= HCF_CFG_APF_2_BOTTOM && HCF_CFG_APF_2_BOTTOM <= CFG_DRV_ACT_RANGES_APF_2_TOP
#undef CFG_DRV_ACT_RANGES_APF_2_BOTTOM
-#define CFG_DRV_ACT_RANGES_APF_2_BOTTOM HCF_CFG_APF_2_BOTTOM
+#define CFG_DRV_ACT_RANGES_APF_2_BOTTOM HCF_CFG_APF_2_BOTTOM
#else
err: ;
#endif
@@ -566,23 +529,23 @@ err: ;
//---------------------------------------------------------------------------------------------------------------------
#if defined HCF_CFG_STA_1_TOP || defined HCF_CFG_STA_1_BOTTOM
-err: STA_1 not supported for H-I; // Compatibility for Station Firmware - driver I/F
+err: STA_1 not supported for H-I; // Compatibility for Station Firmware - driver I/F
#endif // HCF_CFG_STA_1_TOP / HCF_CFG_STA_1_BOTTOM
-#ifdef HCF_CFG_STA_2_TOP // Top Compatibility for Station Firmware - driver I/F
-#if HCF_CFG_STA_2_TOP == 0 || \
+#ifdef HCF_CFG_STA_2_TOP // Top Compatibility for Station Firmware - driver I/F
+#if HCF_CFG_STA_2_TOP == 0 || \
CFG_DRV_ACT_RANGES_STA_2_BOTTOM <= HCF_CFG_STA_2_TOP && HCF_CFG_STA_2_TOP <= CFG_DRV_ACT_RANGES_STA_2_TOP
#undef CFG_DRV_ACT_RANGES_STA_2_TOP
-#define CFG_DRV_ACT_RANGES_STA_2_TOP HCF_CFG_STA_2_TOP
+#define CFG_DRV_ACT_RANGES_STA_2_TOP HCF_CFG_STA_2_TOP
#else
err: ;
#endif
#endif // HCF_CFG_STA_TOP
-#ifdef HCF_CFG_STA_2_BOTTOM // Bottom Compatibility for Station Firmware - driver I/F
+#ifdef HCF_CFG_STA_2_BOTTOM // Bottom Compatibility for Station Firmware - driver I/F
#if CFG_DRV_ACT_RANGES_STA_2_BOTTOM <= HCF_CFG_STA_2_BOTTOM && HCF_CFG_STA_2_BOTTOM <= CFG_DRV_ACT_RANGES_STA_2_TOP
#undef CFG_DRV_ACT_RANGES_STA_2_BOTTOM
-#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM HCF_CFG_STA_2_BOTTOM
+#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM HCF_CFG_STA_2_BOTTOM
#else
err: ;
#endif
@@ -594,91 +557,81 @@ err: ;
/************************************************************************************************/
#ifdef HCF_SLEEP
-#if defined MSF_WAIT
-err: MSF should no longer supply this macro;
-#else
-#define MSF_WAIT(x) \
- { PROT_CNT_INI \
- HCF_WAIT_WHILE( ( IPW( HREG_IO ) & HREG_IO_WOKEN_UP ) == 0 ); \
- HCFASSERT( prot_cnt, IPW( HREG_IO ) ) \
- }
-#endif // MSF_WAIT
+#define MSF_WAIT(x) do { \
+ PROT_CNT_INI; \
+ HCF_WAIT_WHILE((IPW(HREG_IO) & HREG_IO_WOKEN_UP) == 0); \
+ HCFASSERT( prot_cnt, IPW( HREG_IO ) ); \
+ } while (0)
#else
-#define MSF_WAIT(x) /*NOP*/
+#define MSF_WAIT(x) do { } while (0)
#endif // HCF_SLEEP
-#define LOF(x) (sizeof(x)/sizeof(hcf_16)-1)
-
-#define MUL_BY_2( x ) ( (x) << 1 ) //used to multiply by 2
-#define DIV_BY_2( x ) ( (x) >> 1 ) //used to divide by 2
+#define LOF(x) (sizeof(x)/sizeof(hcf_16)-1)
//resolve problems on for some 16 bits compilers to create 32 bit values
-#define MERGE_2( hw, lw ) ( ( ((hcf_32)(hw)) << 16 ) | ((hcf_16)(lw)) )
+#define MERGE_2( hw, lw ) ( ( ((hcf_32)(hw)) << 16 ) | ((hcf_16)(lw)) )
#if ! defined HCF_STATIC
-#define HCF_STATIC static
-#endif // HCF_STATIC
+#define HCF_STATIC static
+#endif // HCF_STATIC
#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0
-#define DAWA_ACK( mask) { \
- OPW( HREG_EV_ACK, mask | HREG_EV_ACK_REG_READY ); \
- OPW( HREG_EV_ACK, (mask & ~HREG_EV_ALLOC) | HREG_EV_ACK_REG_READY ); }
-#define DAWA_ZERO_FID(reg) OPW( reg, 0 );
+#define DAWA_ACK( mask) do { \
+ OPW( HREG_EV_ACK, mask | HREG_EV_ACK_REG_READY ); \
+ OPW( HREG_EV_ACK, (mask & ~HREG_EV_ALLOC) | HREG_EV_ACK_REG_READY ); \
+ } while (0)
+#define DAWA_ZERO_FID(reg) OPW( reg, 0 )
#else
-#define DAWA_ACK( mask) OPW( HREG_EV_ACK, mask );
-#define DAWA_ZERO_FID(reg)
+#define DAWA_ACK( mask) OPW( HREG_EV_ACK, mask )
+#define DAWA_ZERO_FID(reg) do { } while (0)
#endif // HCF_TYPE_HII5
#if (HCF_TYPE) & HCF_TYPE_WPA
-#define CALC_RX_MIC( p, len ) calc_mic_rx_frag( ifbp, p, len )
-#define CALC_TX_MIC( p, len ) calc_mic_tx_frag( ifbp, p, len )
-#define IF_SSN(x) x
-#define IF_NOT_SSN(x)
+#define CALC_RX_MIC( p, len ) calc_mic_rx_frag( ifbp, p, len )
+#define CALC_TX_MIC( p, len ) calc_mic_tx_frag( ifbp, p, len )
#else
-#define CALC_RX_MIC( p, len )
-#define CALC_TX_MIC( p, len )
+#define CALC_RX_MIC( p, len )
+#define CALC_TX_MIC( p, len )
#define MIC_RX_RTN( mic, dw )
#define MIC_TX_RTN( mic, dw )
-#define IF_SSN(x)
-#define IF_NOT_SSN(x) x
#endif // HCF_TYPE_WPA
-#if HCF_TALLIES & HCF_TALLIES_HCF //HCF tally support
-#define IF_TALLY(x) x
+#if HCF_TALLIES & HCF_TALLIES_HCF //HCF tally support
+#define IF_TALLY(x) do { x; } while (0)
#else
-#define IF_TALLY(x)
+#define IF_TALLY(x) do { } while (0)
#endif // HCF_TALLIES_HCF
#if HCF_DMA
-#define IF_DMA(x) x
-#define IF_NOT_DMA(x)
-#define IF_USE_DMA(x) if ( ifbp->IFB_CntlOpt & USE_DMA ) x
-#define IF_NOT_USE_DMA(x) if ( !(ifbp->IFB_CntlOpt & USE_DMA) ) x
+#define IF_DMA(x) do { x; } while(0)
+#define IF_NOT_DMA(x) do { } while(0)
+#define IF_USE_DMA(x) if ( ifbp->IFB_CntlOpt & USE_DMA ) { x; }
+#define IF_NOT_USE_DMA(x) if ( !(ifbp->IFB_CntlOpt & USE_DMA) ) { x; }
#else
-#define IF_DMA(x)
-#define IF_NOT_DMA(x) x
-#define IF_USE_DMA(x)
-#define IF_NOT_USE_DMA(x) x
+#define IF_DMA(x) do { } while(0)
+#define IF_NOT_DMA(x) do { x; } while(0)
+#define IF_USE_DMA(x) do { } while(0)
+#define IF_NOT_USE_DMA(x) do { x; } while(0)
#endif // HCF_DMA
#define IPW(x) ((hcf_16)IN_PORT_WORD( ifbp->IFB_IOBase + (x) ) )
#define OPW(x, y) OUT_PORT_WORD( ifbp->IFB_IOBase + (x), y )
- /* make sure the implementation of HCF_WAIT_WHILE is such that there may be multiple HCF_WAIT_WHILE calls
- * in a row and that when one fails all subsequent fail immediately without reinitialization of prot_cnt
- */
+/* make sure the implementation of HCF_WAIT_WHILE is such that there may be multiple HCF_WAIT_WHILE calls
+ * in a row and that when one fails all subsequent fail immediately without reinitialization of prot_cnt
+ */
#if HCF_PROT_TIME == 0
-#define PROT_CNT_INI
-#define IF_PROT_TIME(x)
+#define PROT_CNT_INI do { } while(0)
+#define IF_PROT_TIME(x) do { } while(0)
#if defined HCF_YIELD
-#define HCF_WAIT_WHILE( x ) while ( (x) && (HCF_YIELD) ) /*NOP*/;
+#define HCF_WAIT_WHILE( x ) do { } while( (x) && (HCF_YIELD) )
#else
-#define HCF_WAIT_WHILE( x ) while ( x ) /*NOP*/;
+#define HCF_WAIT_WHILE( x ) do { } while ( x )
#endif // HCF_YIELD
#else
-#define PROT_CNT_INI hcf_32 prot_cnt = ifbp->IFB_TickIni;
-#define IF_PROT_TIME(x) x
+#define PROT_CNT_INI hcf_32 prot_cnt = ifbp->IFB_TickIni
+#define IF_PROT_TIME(x) do { x; } while(0)
#if defined HCF_YIELD
#define HCF_WAIT_WHILE( x ) while ( prot_cnt && (x) && (HCF_YIELD) ) prot_cnt--;
#else
@@ -697,7 +650,7 @@ err: you used an invalid bitmask;
#endif // HCF_EX_INT
#if 0 //get compiler going
-#if HCF_EX_INT_TICK != HREG_EV_TICK
+#if HCF_EX_INT_TICK != HREG_EV_TICK
;? out dated checking
err: someone redefined these macros while the implemenation assumes they are equal;
#endif
@@ -721,39 +674,37 @@ err: someone redefined these macros while the implemenation assumes they are equ
* on the if-statement
*/
#if HCF_ASSERT
-#define HCFASSERT(x,q) {if (!(x)) {mdd_assert( ifbp, __LINE__ , q );}}
+#define HCFASSERT(x,q) do { if (!(x)) {mdd_assert(ifbp, __LINE__, q );} } while(0)
#define MMDASSERT(x,q) {if (!(x)) {mdd_assert( assert_ifbp, __LINE__ + FILE_NAME_OFFSET, q );}}
-#define HCFLOGENTRY( where, what ) \
-{if ( (ifbp->IFB_AssertWhere = where) <= 15 ) { \
- HCF_ENTRY( ifbp ); \
- HCFASSERT( (ifbp->IFB_AssertTrace & 1<<((where)&0xF)) == 0, ifbp->IFB_AssertTrace ); \
- ifbp->IFB_AssertTrace |= 1<<((where)&0xF); \
- } \
-HCFTRACE(ifbp, where ) \
-HCFTRACEVALUE(ifbp, what ) \
-}
-
-#define HCFLOGEXIT( where ) \
-{if ( (ifbp->IFB_AssertWhere = where) <= 15 ) { \
- HCF_EXIT( ifbp ); \
- ifbp->IFB_AssertTrace &= ~(1<<((where)&0xF)); \
- } \
-HCFTRACE(ifbp, (where)|HCF_TRACE_EXIT ) \
-}
+#define HCFLOGENTRY( where, what ) do { \
+ if ( (ifbp->IFB_AssertWhere = where) <= 15 ) { \
+ HCFASSERT( (ifbp->IFB_AssertTrace & 1<<((where)&0xF)) == 0, ifbp->IFB_AssertTrace ); \
+ ifbp->IFB_AssertTrace |= 1<<((where)&0xF); \
+ } \
+ HCFTRACE(ifbp, where ); \
+ HCFTRACEVALUE(ifbp, what ); \
+ } while (0)
+
+#define HCFLOGEXIT( where ) do { \
+ if ( (ifbp->IFB_AssertWhere = where) <= 15 ) { \
+ ifbp->IFB_AssertTrace &= ~(1<<((where)&0xF)); \
+ } \
+ HCFTRACE(ifbp, (where)|HCF_TRACE_EXIT ); \
+ } while (0)
#else // HCF_ASSERT
-#define HCFASSERT( x, q )
+#define HCFASSERT( x, q ) do { } while(0)
#define MMDASSERT( x, q )
-#define HCFLOGENTRY( where, what ) {HCF_ENTRY( ifbp );}
-#define HCFLOGEXIT( where ) {HCF_EXIT( ifbp );}
+#define HCFLOGENTRY( where, what ) do { } while(0)
+#define HCFLOGEXIT( where ) do { } while(0)
#endif // HCF_ASSERT
#if HCF_INT_ON
/* ;? HCFASSERT_INT
* #if (HCF_SLEEP) & HCF_DDS
* #define HCFASSERT_INT HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFF && ifbp->IFB_IntOffCnt != 0xFFFE, \
- * ifbp->IFB_IntOffCnt )
+ * ifbp->IFB_IntOffCnt )
* #else
*/
#define HCFASSERT_INT HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFF, ifbp->IFB_IntOffCnt )
@@ -764,18 +715,18 @@ HCFTRACE(ifbp, (where)|HCF_TRACE_EXIT ) \
#if defined HCF_TRACE
-#define HCFTRACE(ifbp, where ) {OPW( HREG_SW_1, where );}
-//#define HCFTRACE(ifbp, where ) {HCFASSERT( DO_ASSERT, where );}
-#define HCFTRACEVALUE(ifbp, what ) {OPW( HREG_SW_2, what );}
+#define HCFTRACE(ifbp, where ) do {OPW( HREG_SW_1, where );} while(0)
+//#define HCFTRACE(ifbp, where ) {HCFASSERT( DO_ASSERT, where );}
+#define HCFTRACEVALUE(ifbp, what ) do {OPW( HREG_SW_2, what );} while (0)
//#define HCFTRACEVALUE(ifbp, what ) {HCFASSERT( DO_ASSERT, what );}
#else
-#define HCFTRACE(ifbp, where )
-#define HCFTRACEVALUE(ifbp, what )
+#define HCFTRACE(ifbp, where ) do { } while(0)
+#define HCFTRACEVALUE(ifbp, what ) do { } while(0)
#endif // HCF_TRACE
#if HCF_BIG_ENDIAN
-#define BE_PAR(x) ,x
+#define BE_PAR(x) ,x
#else
#define BE_PAR(x)
#endif // HCF_BIG_ENDIAN
@@ -789,13 +740,13 @@ HCFTRACE(ifbp, (where)|HCF_TRACE_EXIT ) \
/************************************************************************************************/
#if HCF_ASSERT
-extern IFBP BASED assert_ifbp; //to make asserts easily work under MMD and DHF
-EXTERN_C void mdd_assert (IFBP ifbp, unsigned int line_number, hcf_32 q );
+extern IFBP BASED assert_ifbp; //to make asserts easily work under MMD and DHF
+EXTERN_C void mdd_assert (IFBP ifbp, unsigned int line_number, hcf_32 q );
#endif //HCF_ASSERT
-#if ! ( (HCF_IO) & HCF_IO_32BITS ) // defined 16 bits only
+#if ! ( (HCF_IO) & HCF_IO_32BITS ) // defined 16 bits only
#undef OUT_PORT_STRING_32
#undef IN_PORT_STRING_32
#endif // HCF_IO
-#endif //HCFDEFC_H
+#endif //HCFDEFC_H
diff --git a/drivers/staging/wlags49_h2/mdd.h b/drivers/staging/wlags49_h2/mdd.h
index 5aa9eb8..b02e3ea 100644
--- a/drivers/staging/wlags49_h2/mdd.h
+++ b/drivers/staging/wlags49_h2/mdd.h
@@ -444,7 +444,7 @@ XX1( CFG_DEFAULT_KEYS, KEY_STRCT, key[4] ) /*defines set of encryption keys
tx_mic_key[4], rx_mic_key[4] ) /* */
X6( CFG_ADD_TKIP_MAPPED_KEY, bssid[3], tkip_key[8], \
tsc[4], rsc[4], tx_mic_key[4], rx_mic_key[4] ) /* */
- X1( CFG_SET_SSN_AUTHENTICATION_SUITE, \
+ X1( CFG_SET_WPA_AUTHENTICATION_SUITE, \
ssn_authentication_suite ) /* */
X1( CFG_REMOVE_TKIP_DEFAULT_KEY,tkip_key_id ) /* */
X1( CFG_TICK_TIME, tick_time ) /*Auxiliary Timer tick interval */
@@ -525,7 +525,7 @@ X2( CFG_WOL_PATTERNS, nPatterns, buffer[WOL_BUF_SIZE] ) /*[STA] WakeOnLan pat
X1( CFG_OWN_MAC_ADDR, mac_addr[3] ) /*[AP] Unique local node MAC Address */
X3( CFG_PCF_INFO, medium_occupancy_limit, \
cfp_period, cfp_max_duration ) /*[AP] Point Coordination Function capability info */
- X1( CFG_CUR_SSN_INFO_ELEMENT, ssn_info_element[1] ) /* */
+ X1( CFG_CUR_WPA_INFO_ELEMENT, ssn_info_element[1] ) /* */
X4( CFG_CUR_TKIP_IV_INFO, \
tkip_seq_cnt0[4], tkip_seq_cnt1[4], \
tkip_seq_cnt2[4], tkip_seq_cnt3[4] ) /* */
@@ -802,7 +802,7 @@ XX1( CFG_SCAN, SCAN_RS_STRCT, scan_result[32] ) /*Scan results *
#define CFG_PCF_INFO 0xFD87 //[AP] Point Coordination Function capability info
//*RESERVED* #define CFG_HIGHEST_BASIC_RATE 0xFD88 //
#define CFG_CUR_COUNTRY_INFO 0xFD89 //
-#define CFG_CUR_SSN_INFO_ELEMENT 0xFD8A //
+#define CFG_CUR_WPA_INFO_ELEMENT 0xFD8A //
#define CFG_CUR_TKIP_IV_INFO 0xFD8B //
#define CFG_CUR_ASSOC_REQ_INFO 0xFD8C //
#define CFG_CUR_ASSOC_RESP_INFO 0xFD8D //
@@ -893,20 +893,20 @@ XX1( CFG_SCAN, SCAN_RS_STRCT, scan_result[32] ) /*Scan results *
//HFS_TX_CNTL
/* Note that the HCF_.... System Constants influence the HFS_.... values below
- * H-I H-I | H-II H-II H-II.5
- * WPA | WPA
- * HFS_TX_CNTL_TX_OK 0002 0002 | 0002 0002 N/A <<<<<<<<deprecated
- * HFS_TX_CNTL_TX_EX 0004 0004 | 0004 0004 N/A
- * HFS_TX_CNTL_MIC N/A 0010 | N/A 0010 N/A
- * HFS_TX_CNTL_TID N/A N/A | N/A N/A 000F
- * HFS_TX_CNTL_SERVICE_CLASS N/A N/A | N/A N/A 00C0
- * HFS_TX_CNTL_PORT 0700 0700 | 0700 0700 0700
- * HFS_TX_CNTL_MIC_KEY_ID 1800 1800 | 0000 1800 N/A
- * HFS_TX_CNTL_CKIP 0000 0000 | 0000 2000 2000
- * HFS_TX_CNTL_TX_DELAY 4000 4000 | 4000 4000 N/A
- * HFS_TX_CNTL_ACTION N/A N/A | N/A N/A 4000
- * ==== ==== | ==== ==== ====
- * 5F06 5F16 | 4706 7F06 67CF
+ * H-I H-I | H-II H-II H-II.5
+ * WPA | WPA
+ * HFS_TX_CNTL_TX_OK 0002 0002 | 0002 0002 N/A <<<<<<<<deprecated
+ * HFS_TX_CNTL_TX_EX 0004 0004 | 0004 0004 N/A
+ * HFS_TX_CNTL_MIC N/A 0010 | N/A 0010 N/A
+ * HFS_TX_CNTL_TID N/A N/A | N/A N/A 000F
+ * HFS_TX_CNTL_SERVICE_CLASS N/A N/A | N/A N/A 00C0
+ * HFS_TX_CNTL_PORT 0700 0700 | 0700 0700 0700
+ * HFS_TX_CNTL_MIC_KEY_ID 1800 1800 | 0000 1800 N/A
+ * HFS_TX_CNTL_CKIP 0000 0000 | 0000 2000 2000
+ * HFS_TX_CNTL_TX_DELAY 4000 4000 | 4000 4000 N/A
+ * HFS_TX_CNTL_ACTION N/A N/A | N/A N/A 4000
+ * ==== ==== | ==== ==== ====
+ * 5F06 5F16 | 4706 7F06 67CF
*
* HCF_TX_CNTL_MASK specifies the bits allowed on the Host I/F
* note: bit 0x4000 has different meaning for H-II and H-II.5
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index a3a727c..2faee2d 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -82,6 +82,7 @@
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
@@ -501,117 +502,3 @@ int wl_adapter_is_open(struct net_device *dev)
return link->open;
} /* wl_adapter_is_open */
/*============================================================================*/
-
-
-#if DBG
-
-/*******************************************************************************
- * DbgEvent()
- *******************************************************************************
- *
- * DESCRIPTION:
- *
- * Converts the card serivces events to text for debugging.
- *
- * PARAMETERS:
- *
- * mask - a integer representing the error(s) being reported by Card
- * Services.
- *
- * RETURNS:
- *
- * a pointer to a string describing the error(s)
- *
- ******************************************************************************/
-const char *DbgEvent(int mask)
-{
- static char DbgBuffer[256];
- char *pBuf;
- /*--------------------------------------------------------------------*/
-
- pBuf = DbgBuffer;
- *pBuf = '\0';
-
-
- if (mask & CS_EVENT_WRITE_PROTECT)
- strcat(pBuf, "WRITE_PROTECT ");
-
- if (mask & CS_EVENT_CARD_LOCK)
- strcat(pBuf, "CARD_LOCK ");
-
- if (mask & CS_EVENT_CARD_INSERTION)
- strcat(pBuf, "CARD_INSERTION ");
-
- if (mask & CS_EVENT_CARD_REMOVAL)
- strcat(pBuf, "CARD_REMOVAL ");
-
- if (mask & CS_EVENT_BATTERY_DEAD)
- strcat(pBuf, "BATTERY_DEAD ");
-
- if (mask & CS_EVENT_BATTERY_LOW)
- strcat(pBuf, "BATTERY_LOW ");
-
- if (mask & CS_EVENT_READY_CHANGE)
- strcat(pBuf, "READY_CHANGE ");
-
- if (mask & CS_EVENT_CARD_DETECT)
- strcat(pBuf, "CARD_DETECT ");
-
- if (mask & CS_EVENT_RESET_REQUEST)
- strcat(pBuf, "RESET_REQUEST ");
-
- if (mask & CS_EVENT_RESET_PHYSICAL)
- strcat(pBuf, "RESET_PHYSICAL ");
-
- if (mask & CS_EVENT_CARD_RESET)
- strcat(pBuf, "CARD_RESET ");
-
- if (mask & CS_EVENT_REGISTRATION_COMPLETE)
- strcat(pBuf, "REGISTRATION_COMPLETE ");
-
- /* if (mask & CS_EVENT_RESET_COMPLETE)
- strcat(pBuf, "RESET_COMPLETE "); */
-
- if (mask & CS_EVENT_PM_SUSPEND)
- strcat(pBuf, "PM_SUSPEND ");
-
- if (mask & CS_EVENT_PM_RESUME)
- strcat(pBuf, "PM_RESUME ");
-
- if (mask & CS_EVENT_INSERTION_REQUEST)
- strcat(pBuf, "INSERTION_REQUEST ");
-
- if (mask & CS_EVENT_EJECTION_REQUEST)
- strcat(pBuf, "EJECTION_REQUEST ");
-
- if (mask & CS_EVENT_MTD_REQUEST)
- strcat(pBuf, "MTD_REQUEST ");
-
- if (mask & CS_EVENT_ERASE_COMPLETE)
- strcat(pBuf, "ERASE_COMPLETE ");
-
- if (mask & CS_EVENT_REQUEST_ATTENTION)
- strcat(pBuf, "REQUEST_ATTENTION ");
-
- if (mask & CS_EVENT_CB_DETECT)
- strcat(pBuf, "CB_DETECT ");
-
- if (mask & CS_EVENT_3VCARD)
- strcat(pBuf, "3VCARD ");
-
- if (mask & CS_EVENT_XVCARD)
- strcat(pBuf, "XVCARD ");
-
-
- if (*pBuf) {
- pBuf[strlen(pBuf) - 1] = '\0';
- } else {
- if (mask != 0x0)
- sprintf(pBuf, "<<0x%08x>>", mask);
- }
-
- return pBuf;
-} /* DbgEvent */
-/*============================================================================*/
-
-#endif /* DBG */
diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h
index cd129b3..5753408 100644
--- a/drivers/staging/wlags49_h2/wl_internal.h
+++ b/drivers/staging/wlags49_h2/wl_internal.h
@@ -67,7 +67,6 @@
/*******************************************************************************
* include files
******************************************************************************/
-#include <linux/version.h>
#ifdef BUS_PCMCIA
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
@@ -75,15 +74,8 @@
#include <pcmcia/ds.h>
#endif // BUS_PCMCIA
-#ifdef HAS_WIRELESS_EXTENSIONS
#include <linux/wireless.h>
-#if WIRELESS_EXT > 13
#include <net/iw_handler.h>
-#endif // WIRELESS_EXT > 13
-#define USE_DBM
-#define RETURN_CURRENT_NETWORKNAME
-#define USE_FREQUENCY
-#endif // HAS_WIRELESS_EXTENSIONS/
#include <linux/list.h>
@@ -891,7 +883,7 @@ struct wl_private
int is_registered;
int is_handling_int;
int firmware_present;
- char sysfsCreated;
+ bool sysfsCreated;
CFG_DRV_INFO_STRCT driverInfo;
CFG_IDENTITY_STRCT driverIdentity;
CFG_FW_IDENTITY_STRCT StationIdentity;
@@ -988,16 +980,15 @@ struct wl_private
#ifdef USE_WDS
WVLAN_WDS_IF wds_port[NUM_WDS_PORTS];
#endif // USE_WDS
+
+ /* Track whether the card is using WEP encryption or WPA
+ * so we know what to disable next time through.
+ * IW_ENCODE_ALG_NONE, IW_ENCODE_ALG_WEP, IW_ENCODE_ALG_TKIP
+ */
+ int wext_enc;
}; // wl_private
-#ifdef HAVE_NETDEV_PRIV
#define wl_priv(dev) ((struct wl_private *) netdev_priv(dev))
-#else
-extern inline struct wl_private *wl_priv(struct net_device *dev)
-{
- return dev->priv;
-}
-#endif
/********************************************************************/
/* Locking and synchronization functions */
diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c
index 6d45ab3..483eee1 100644
--- a/drivers/staging/wlags49_h2/wl_main.c
+++ b/drivers/staging/wlags49_h2/wl_main.c
@@ -1993,8 +1993,10 @@ int wl_put_ltv( struct wl_private *lp )
lp->ltvRecord.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->AuthKeyMgmtSuite );
hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
- /* WEP Keys */
- wl_set_wep_keys( lp );
+
+ /* If WEP (or no) keys are being used, write (or clear) them */
+ if (lp->wext_enc != IW_ENCODE_ALG_TKIP)
+ wl_set_wep_keys(lp);
/* Country Code */
/* countryInfo, ltvCountryInfo, CFG_CNF_COUNTRY_INFO */
diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c
index cf917e6..5a2b334 100644
--- a/drivers/staging/wlags49_h2/wl_netdev.c
+++ b/drivers/staging/wlags49_h2/wl_netdev.c
@@ -217,7 +217,7 @@ int wl_config( struct net_device *dev, struct ifmap *map )
/* The only thing we care about here is a port change. Since this not needed,
ignore the request. */
- DBG_TRACE( DbgInfo, "%s: %s called.\n", dev->name, __FUNC__ );
+ DBG_TRACE(DbgInfo, "%s: %s called.\n", dev->name, __func__);
DBG_LEAVE( DbgInfo );
return 0;
@@ -1179,7 +1179,7 @@ static const struct net_device_ops wl_netdev_ops =
.ndo_set_config = &wl_config,
.ndo_get_stats = &wl_stats,
- .ndo_set_multicast_list = &wl_multicast,
+ .ndo_set_rx_mode = &wl_multicast,
.ndo_init = &wl_insert,
.ndo_open = &wl_adapter_open,
diff --git a/drivers/staging/wlags49_h2/wl_priv.c b/drivers/staging/wlags49_h2/wl_priv.c
index 260d4f0..b3d2e17 100644
--- a/drivers/staging/wlags49_h2/wl_priv.c
+++ b/drivers/staging/wlags49_h2/wl_priv.c
@@ -570,6 +570,7 @@ int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp )
ltv_t *pLtv;
bool_t ltvAllocated = FALSE;
ENCSTRCT sEncryption;
+ size_t len;
#ifdef USE_WDS
hcf_16 hcfPort = HCF_PORT_0;
@@ -686,7 +687,8 @@ int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp )
break;
case CFG_CNF_OWN_NAME:
memset( lp->StationName, 0, sizeof( lp->StationName ));
- memcpy( (void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
+ len = min_t(size_t, pLtv->u.u16[0], sizeof(lp->StationName));
+ strlcpy(lp->StationName, &pLtv->u.u8[2], len);
pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] );
break;
case CFG_CNF_LOAD_BALANCING:
@@ -1800,6 +1802,7 @@ int wvlan_set_station_nickname(struct net_device *dev,
{
struct wl_private *lp = wl_priv(dev);
unsigned long flags;
+ size_t len;
int ret = 0;
/*------------------------------------------------------------------------*/
@@ -1810,8 +1813,8 @@ int wvlan_set_station_nickname(struct net_device *dev,
wl_lock(lp, &flags);
memset( lp->StationName, 0, sizeof( lp->StationName ));
-
- memcpy( lp->StationName, extra, wrqu->data.length);
+ len = min_t(size_t, wrqu->data.length, sizeof(lp->StationName));
+ strlcpy(lp->StationName, extra, len);
/* Commit the adapter parameters */
wl_apply( lp );
diff --git a/drivers/staging/wlags49_h2/wl_sysfs.c b/drivers/staging/wlags49_h2/wl_sysfs.c
index 9b833b3..1508f04 100644
--- a/drivers/staging/wlags49_h2/wl_sysfs.c
+++ b/drivers/staging/wlags49_h2/wl_sysfs.c
@@ -120,17 +120,19 @@ static struct attribute_group wlags_group = {
void register_wlags_sysfs(struct net_device *net)
{
- struct device *dev = &(net->dev);
- struct wl_private *lp = wl_priv(net);
-
- lp->sysfsCreated = sysfs_create_group(&dev->kobj, &wlags_group);
+ struct device *dev = &(net->dev);
+ struct wl_private *lp = wl_priv(net);
+ int err;
+ err = sysfs_create_group(&dev->kobj, &wlags_group);
+ if (!err)
+ lp->sysfsCreated = true;
}
void unregister_wlags_sysfs(struct net_device *net)
{
- struct device *dev = &(net->dev);
- struct wl_private *lp = wl_priv(net);
+ struct device *dev = &(net->dev);
+ struct wl_private *lp = wl_priv(net);
- if (lp->sysfsCreated)
- sysfs_remove_group(&dev->kobj, &wlags_group);
+ if (lp->sysfsCreated)
+ sysfs_remove_group(&dev->kobj, &wlags_group);
}
diff --git a/drivers/staging/wlags49_h2/wl_version.h b/drivers/staging/wlags49_h2/wl_version.h
index a5e604c..fd37040 100644
--- a/drivers/staging/wlags49_h2/wl_version.h
+++ b/drivers/staging/wlags49_h2/wl_version.h
@@ -66,7 +66,6 @@
* include files
******************************************************************************/
//#include <linux/config.h>
-#include <linux/version.h>
#ifndef CONFIG_MODVERSIONS
#define __NO_VERSION__
@@ -144,7 +143,8 @@ err: define bus type;
" for " BUS_TYPE ", " \
MODULE_DATE " by " VENDOR_NAME
-#define WIRELESS_SUPPORT 15 // The version of wireless extensions we support
+/* The version of wireless extensions we support */
+#define WIRELESS_SUPPORT 21
//#define DBG_MOD_NAME DRIVER_NAME ":" BUS_TYPE ":" HW_TYPE ":" FW_TYPE
#define DBG_MOD_NAME MODULE_NAME
@@ -158,9 +158,6 @@ err: define bus type;
* There doesn't seem to be a difference for PCMCIA and PCI anymore, at least
* for PCMCIA the same defines are needed now as previously only used for PCI
*/
-#if USE_WEXT
-#define HAS_WIRELESS_EXTENSIONS
-#endif // USE_WEXT
#define NEW_MULTICAST
#define ALLOC_SKB(len) dev_alloc_skb(len+2)
diff --git a/drivers/staging/wlags49_h2/wl_wext.c b/drivers/staging/wlags49_h2/wl_wext.c
index 522a310..8ac5e10 100644
--- a/drivers/staging/wlags49_h2/wl_wext.c
+++ b/drivers/staging/wlags49_h2/wl_wext.c
@@ -75,20 +75,6 @@
#include <wl_wext.h>
#include <wl_priv.h>
-
-
-/* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS
- #including linux/wireless.h), then these functions do not need to be included
- in the build. */
-#ifdef WIRELESS_EXT
-
-#define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
- iwe_stream_add_event(info, buf, end, iwe, len)
-#define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
- iwe_stream_add_point(info, buf, end, iwe, msg)
-
-
-
/*******************************************************************************
* global definitions
******************************************************************************/
@@ -97,7 +83,223 @@ extern dbg_info_t *DbgInfo;
#endif // DBG
+/* Set up the LTV to program the appropriate key */
+static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
+ int set_tx, u8 *seq, u8 *key, size_t key_len)
+{
+ int ret = -EINVAL;
+ int buf_idx = 0;
+ hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
+ { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
+
+ DBG_ENTER(DbgInfo);
+
+ /*
+ * Check the key index here; if 0, load as Pairwise Key, otherwise,
+ * load as a group key. Note that for the Hermes, the RIDs for
+ * group/pairwise keys are different from each other and different
+ * than the default WEP keys as well.
+ */
+ switch (key_idx) {
+ case 0:
+ ltv->len = 28;
+ ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
+
+ /* Load the BSSID */
+ memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
+ buf_idx += ETH_ALEN;
+
+ /* Load the TKIP key */
+ memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
+ buf_idx += 16;
+
+ /* Load the TSC */
+ memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
+ buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
+
+ /* Load the RSC */
+ memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
+ buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
+
+ /* Load the TxMIC key */
+ memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
+ buf_idx += 8;
+
+ /* Load the RxMIC key */
+ memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
+
+ ret = 0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ ltv->len = 26;
+ ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
+
+ /* Load the key Index */
+
+ /* If this is a Tx Key, set bit 8000 */
+ if (set_tx)
+ key_idx |= 0x8000;
+ ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
+ buf_idx += 2;
+
+ /* Load the RSC */
+ memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
+ buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
+
+ /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
+ CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
+ memcpy(&ltv->u.u8[buf_idx], key, key_len);
+ buf_idx += key_len;
+
+ /* Load the TSC */
+ memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
+
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+
+ DBG_LEAVE(DbgInfo);
+ return ret;
+}
+
+/* Set up the LTV to clear the appropriate key */
+static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
+{
+ int ret;
+
+ switch (key_idx) {
+ case 0:
+ if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
+ ltv->len = 7;
+ ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
+ memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
+ ret = 0;
+ }
+ break;
+ case 1:
+ case 2:
+ case 3:
+ /* Clear the Group TKIP keys by index */
+ ltv->len = 2;
+ ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
+ ltv->u.u16[0] = cpu_to_le16(key_idx);
+
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/* Set the WEP keys in the wl_private structure */
+static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
+ u8 *key, size_t key_len,
+ bool enable, bool set_tx)
+{
+ hcf_8 encryption_state = lp->EnableEncryption;
+ int tk = lp->TransmitKeyID - 1; /* current key */
+ int ret = 0;
+
+ /* Is encryption supported? */
+ if (!wl_has_wep(&(lp->hcfCtx))) {
+ DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+ DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
+ key, key_len);
+
+ /* Check the size of the key */
+ switch (key_len) {
+ case MIN_KEY_SIZE:
+ case MAX_KEY_SIZE:
+
+ /* Check the index */
+ if ((key_idx < 0) || (key_idx >= MAX_KEYS))
+ key_idx = tk;
+
+ /* Cleanup */
+ memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
+
+ /* Copy the key in the driver */
+ memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
+
+ /* Set the length */
+ lp->DefaultKeys.key[key_idx].len = key_len;
+
+ DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
+ DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
+ lp->DefaultKeys.key[key_idx].key,
+ lp->DefaultKeys.key[key_idx].len, key_idx);
+
+ /* Enable WEP (if possible) */
+ if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
+ lp->EnableEncryption = 1;
+
+ break;
+
+ case 0:
+ /* Do we want to just set the current transmit key? */
+ if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
+ DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
+ lp->DefaultKeys.key[key_idx].len);
+
+ if (lp->DefaultKeys.key[key_idx].len > 0) {
+ lp->TransmitKeyID = key_idx + 1;
+ lp->EnableEncryption = 1;
+ } else {
+ DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
+ ret = -EINVAL;
+ }
+ }
+ break;
+
+ default:
+ DBG_WARNING(DbgInfo, "Invalid Key length\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Read the flags */
+ if (enable) {
+ lp->EnableEncryption = 1;
+ lp->wext_enc = IW_ENCODE_ALG_WEP;
+ } else {
+ lp->EnableEncryption = 0; /* disable encryption */
+ lp->wext_enc = IW_ENCODE_ALG_NONE;
+ }
+
+ DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
+ DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
+ DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
+
+ /* Write the changes to the card */
+ if (ret == 0) {
+ DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
+ lp->TransmitKeyID);
+
+ if (lp->EnableEncryption == encryption_state) {
+ if (key_len != 0) {
+ /* Dynamic WEP key update */
+ wl_set_wep_keys(lp);
+ }
+ } else {
+ /* To switch encryption on/off, soft reset is
+ * required */
+ wl_apply(lp);
+ }
+ }
+
+out:
+ return ret;
+}
/*******************************************************************************
* wireless_commit()
@@ -324,16 +526,8 @@ static int wireless_get_frequency(struct net_device *dev, struct iw_request_info
if( ret == HCF_SUCCESS ) {
hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
-#ifdef USE_FREQUENCY
-
freq->m = wl_get_freq_from_chan( channel ) * 100000;
freq->e = 1;
-#else
-
- freq->m = channel;
- freq->e = 0;
-
-#endif /* USE_FREQUENCY */
}
wl_act_int_on( lp );
@@ -460,8 +654,6 @@ retry:
/* Link quality */
-#ifdef USE_DBM
-
range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
/* If the value returned in /proc/net/wireless is greater than the maximum range,
@@ -470,13 +662,6 @@ retry:
range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
-#else
-
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 100;
-
-#endif /* USE_DBM */
/* Set available rates */
@@ -508,8 +693,6 @@ retry:
/* Encryption */
-#if WIRELESS_EXT > 8
-
/* Holding the lock too long, make a gap to allow other processes */
wl_unlock(lp, &flags);
wl_lock( lp, &flags );
@@ -526,26 +709,17 @@ retry:
range->max_encoding_tokens = MAX_KEYS;
}
-#endif /* WIRELESS_EXT > 8 */
-
/* Tx Power Info */
range->txpower_capa = IW_TXPOW_MWATT;
range->num_txpower = 1;
range->txpower[0] = RADIO_TX_POWER_MWATT;
-#if WIRELESS_EXT > 10
-
/* Wireless Extension Info */
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = WIRELESS_SUPPORT;
// Retry Limits and Lifetime - NOT SUPPORTED
-#endif
-
-
-#if WIRELESS_EXT > 11
-
/* Holding the lock too long, make a gap to allow other processes */
wl_unlock(lp, &flags);
wl_lock( lp, &flags );
@@ -555,18 +729,18 @@ retry:
range->avg_qual = lp->wstats.qual;
DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
-#endif
-
/* Event capability (kernel + driver) */
- range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
- IW_EVENT_CAPA_MASK(SIOCGIWAP) |
- IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
- range->event_capa[1] = IW_EVENT_CAPA_K_1;
- range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
- IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
- IW_EVENT_CAPA_MASK(IWEVEXPIRED));
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
+ range->scan_capa = IW_SCAN_CAPA_NONE;
out_unlock:
wl_act_int_on( lp );
@@ -1075,9 +1249,6 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in
/* Copy the information into the user buffer */
data->length = pName->length;
- /* NOTE: Null terminating is necessary for proper display of the SSID in
- the wireless tools */
- data->length = pName->length + 1;
if( pName->length < HCF_MAX_NAME_LEN ) {
pName->name[pName->length] = '\0';
}
@@ -1087,7 +1258,6 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in
#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
//;?should we return an error status in AP mode
-#ifdef RETURN_CURRENT_NETWORKNAME
/* if desired is null ("any"), return current or "any" */
if( pName->name[0] == '\0' ) {
@@ -1104,11 +1274,7 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in
pName->length = CNV_LITTLE_TO_INT( pName->length );
/* Copy the information into the user buffer */
- data->length = pName->length + 1;
- if( pName->length < HCF_MAX_NAME_LEN ) {
- pName->name[pName->length] = '\0';
- }
-
+ data->length = pName->length;
data->flags = 1;
} else {
ret = -EFAULT;
@@ -1116,11 +1282,8 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in
}
}
-#endif // RETURN_CURRENT_NETWORKNAME
#endif // HCF_STA
- data->length--;
-
if (pName->length > IW_ESSID_MAX_SIZE) {
ret = -EFAULT;
goto out_unlock;
@@ -1169,156 +1332,39 @@ static int wireless_set_encode(struct net_device *dev, struct iw_request_info *i
{
struct wl_private *lp = wl_priv(dev);
unsigned long flags;
- int ret = 0;
-
-#if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
- hcf_8 encryption_state;
-#endif // WIRELESS_EXT > 8
- /*------------------------------------------------------------------------*/
-
+ int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
+ int ret = 0;
+ bool enable = true;
- DBG_FUNC( "wireless_set_encode" );
- DBG_ENTER( DbgInfo );
+ DBG_ENTER(DbgInfo);
- if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
+ if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
ret = -EBUSY;
goto out;
}
- wl_lock( lp, &flags );
-
- wl_act_int_off( lp );
-
- /* Is encryption supported? */
- if( !wl_has_wep( &( lp->hcfCtx ))) {
- DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
- ret = -EOPNOTSUPP;
- goto out_unlock;
- }
-
- DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
- keybuf, erq->length,
- erq->flags);
-
- /* Save state of Encryption switch */
- encryption_state = lp->EnableEncryption;
-
- /* Basic checking: do we have a key to set? */
- if((erq->length) != 0) {
- int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
- int tk = lp->TransmitKeyID - 1; // current key
-
-
- /* Check the size of the key */
- switch(erq->length) {
- case 0:
- break;
-
- case MIN_KEY_SIZE:
- case MAX_KEY_SIZE:
-
- /* Check the index */
- if(( index < 0 ) || ( index >= MAX_KEYS )) {
- index = tk;
- }
-
- /* Cleanup */
- memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
-
- /* Copy the key in the driver */
- memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
-
- /* Set the length */
- lp->DefaultKeys.key[index].len = erq->length;
-
- DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
- DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
- lp->DefaultKeys.key[index].len, index );
-
- /* Enable WEP (if possible) */
- if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
- lp->EnableEncryption = 1;
- }
-
- break;
-
- default:
- DBG_WARNING( DbgInfo, "Invalid Key length\n" );
- ret = -EINVAL;
- goto out_unlock;
- }
- } else {
- int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
-
-
- /* Do we want to just set the current transmit key? */
- if(( index >= 0 ) && ( index < MAX_KEYS )) {
- DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
- lp->DefaultKeys.key[index].len );
-
- if( lp->DefaultKeys.key[index].len > 0 ) {
- lp->TransmitKeyID = index + 1;
- lp->EnableEncryption = 1;
- } else {
- DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
- DBG_LEAVE( DbgInfo );
- ret = -EINVAL;
- }
- }
- }
-
- /* Read the flags */
- if( erq->flags & IW_ENCODE_DISABLED ) {
- lp->EnableEncryption = 0; // disable encryption
- } else {
- lp->EnableEncryption = 1;
- }
-
- if( erq->flags & IW_ENCODE_RESTRICTED ) {
- DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
- ret = -EINVAL; // Invalid
- }
+ if (erq->flags & IW_ENCODE_DISABLED)
+ enable = false;
- DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
- DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
- DBG_TRACE( DbgInfo, "erq->length : %d\n",
- erq->length);
- DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
- erq->flags);
+ wl_lock(lp, &flags);
- /* Write the changes to the card */
- if( ret == 0 ) {
- DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
- lp->TransmitKeyID );
+ wl_act_int_off(lp);
- if( lp->EnableEncryption == encryption_state ) {
- if( erq->length != 0 ) {
- /* Dynamic WEP key update */
- wl_set_wep_keys( lp );
- }
- } else {
- /* To switch encryption on/off, soft reset is required */
- wl_apply( lp );
- }
- }
+ ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
+ enable, true);
/* Send an event that Encryption has been set */
- wl_wext_event_encode( dev );
-
-out_unlock:
+ if (ret == 0)
+ wl_wext_event_encode(dev);
- wl_act_int_on( lp );
+ wl_act_int_on(lp);
wl_unlock(lp, &flags);
out:
- DBG_LEAVE( DbgInfo );
+ DBG_LEAVE(DbgInfo);
return ret;
-} // wireless_set_encode
-/*============================================================================*/
-
-
-
+}
/*******************************************************************************
* wireless_get_encode()
@@ -2023,11 +2069,9 @@ static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request
goto out;
}
-#if WIRELESS_EXT > 8
if( rts->disabled ) {
rthr = 2347;
}
-#endif /* WIRELESS_EXT > 8 */
if(( rthr < 256 ) || ( rthr > 2347 )) {
ret = -EINVAL;
@@ -2095,12 +2139,8 @@ static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request
rts->value = lp->RTSThreshold;
-#if WIRELESS_EXT > 8
-
rts->disabled = ( rts->value == 2347 );
-#endif /* WIRELESS_EXT > 8 */
-
rts->fixed = 1;
wl_act_int_on( lp );
@@ -2527,8 +2567,6 @@ out:
-#if WIRELESS_EXT > 13
-
/*******************************************************************************
* wireless_set_scan()
*******************************************************************************
@@ -2737,8 +2775,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
iwe.len = IW_EV_ADDR_LEN;
- buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
-
+ buf = iwe_stream_add_event(info, buf, buf_end,
+ &iwe, IW_EV_ADDR_LEN);
/* Use the mode to indicate if it's a station or AP */
/* Won't always be an AP if in IBSS mode */
@@ -2754,8 +2792,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
iwe.len = IW_EV_UINT_LEN;
- buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
-
+ buf = iwe_stream_add_event(info, buf, buf_end,
+ &iwe, IW_EV_UINT_LEN);
/* Any quality information */
memset(&iwe, 0, sizeof(iwe));
@@ -2767,7 +2805,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
iwe.len = IW_EV_QUAL_LEN;
- buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
+ buf = iwe_stream_add_event(info, buf, buf_end,
+ &iwe, IW_EV_QUAL_LEN);
/* ESSID information */
@@ -2778,7 +2817,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
iwe.u.data.length = probe_resp->rawData[1];
iwe.u.data.flags = 1;
- buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
+ buf = iwe_stream_add_point(info, buf, buf_end,
+ &iwe, &probe_resp->rawData[2]);
}
@@ -2796,7 +2836,7 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
iwe.u.data.flags |= IW_ENCODE_DISABLED;
}
- buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
+ buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
/* Frequency Info */
@@ -2807,10 +2847,10 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
iwe.u.freq.e = 0;
- buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
+ buf = iwe_stream_add_event(info, buf, buf_end,
+ &iwe, IW_EV_FREQ_LEN);
-#if WIRELESS_EXT > 14
/* Custom info (Beacon Interval) */
memset( &iwe, 0, sizeof( iwe ));
memset( msg, 0, sizeof( msg ));
@@ -2819,27 +2859,25 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf
sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
iwe.u.data.length = strlen( msg );
- buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
+ buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
- /* Custom info (WPA-IE) */
+ /* WPA-IE */
wpa_ie = NULL;
wpa_ie_len = 0;
wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
if( wpa_ie != NULL ) {
- memset( &iwe, 0, sizeof( iwe ));
- memset( msg, 0, sizeof( msg ));
+ memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
- iwe.u.data.length = strlen( msg );
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = wpa_ie_len;
- buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
+ buf = iwe_stream_add_point(info, buf, buf_end,
+ &iwe, wpa_ie);
}
/* Add other custom info in formatted string format as needed... */
-#endif
}
data->length = buf - extra;
@@ -2856,10 +2894,24 @@ out:
} // wireless_get_scan
/*============================================================================*/
-#endif // WIRELESS_EXT > 13
-
-
-#if WIRELESS_EXT > 17
+#if DBG
+static const char * const auth_names[] = {
+ "IW_AUTH_WPA_VERSION",
+ "IW_AUTH_CIPHER_PAIRWISE",
+ "IW_AUTH_CIPHER_GROUP",
+ "IW_AUTH_KEY_MGMT",
+ "IW_AUTH_TKIP_COUNTERMEASURES",
+ "IW_AUTH_DROP_UNENCRYPTED",
+ "IW_AUTH_80211_AUTH_ALG",
+ "IW_AUTH_WPA_ENABLED",
+ "IW_AUTH_RX_UNENCRYPTED_EAPOL",
+ "IW_AUTH_ROAMING_CONTROL",
+ "IW_AUTH_PRIVACY_INVOKED",
+ "IW_AUTH_CIPHER_GROUP_MGMT",
+ "IW_AUTH_MFP",
+ "Unsupported"
+};
+#endif
static int wireless_set_auth(struct net_device *dev,
struct iw_request_info *info,
@@ -2867,14 +2919,15 @@ static int wireless_set_auth(struct net_device *dev,
{
struct wl_private *lp = wl_priv(dev);
unsigned long flags;
- int ret;
- int iwa_idx = data->flags & IW_AUTH_INDEX;
- int iwa_val = data->value;
+ ltv_t ltv;
+ int ret;
+ int iwa_idx = data->flags & IW_AUTH_INDEX;
+ int iwa_val = data->value;
DBG_FUNC( "wireless_set_auth" );
DBG_ENTER( DbgInfo );
- if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
+ if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
ret = -EBUSY;
goto out;
}
@@ -2883,89 +2936,102 @@ static int wireless_set_auth(struct net_device *dev,
wl_act_int_off( lp );
+ if (iwa_idx > IW_AUTH_MFP)
+ iwa_idx = IW_AUTH_MFP + 1;
+ DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
switch (iwa_idx) {
- case IW_AUTH_WPA_VERSION:
- DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
- /* We do support WPA only; how should DISABLED be treated? */
- if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
- ret = 0;
- else
- ret = -EINVAL;
- break;
-
- case IW_AUTH_WPA_ENABLED:
- DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
- if (iwa_val)
- lp->EnableEncryption = 2;
- else
- lp->EnableEncryption = 0;
+ case IW_AUTH_WPA_VERSION:
+ /* We do support WPA */
+ if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
+ (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
ret = 0;
- break;
+ else
+ ret = -EINVAL;
+ break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
- lp->driverEnable = !iwa_val;
- if(lp->driverEnable)
- hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
- else
- hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
- ret = 0;
- break;
+ case IW_AUTH_WPA_ENABLED:
+ DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
+ if (iwa_val)
+ lp->EnableEncryption = 2;
+ else
+ lp->EnableEncryption = 0;
- case IW_AUTH_DROP_UNENCRYPTED:
- DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
- /* We do not actually do anything here, just to silence
- * wpa_supplicant */
- ret = 0;
- break;
+ /* Write straight to the card */
+ ltv.len = 2;
+ ltv.typ = CFG_CNF_ENCRYPTION;
+ ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
+ ret = hcf_put_info(&lp->hcfCtx, (LTVP)&ltv);
- case IW_AUTH_CIPHER_PAIRWISE:
- DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
- /* not implemented, return an error */
- ret = -EINVAL;
- break;
+ break;
- case IW_AUTH_CIPHER_GROUP:
- DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
- /* not implemented, return an error */
- ret = -EINVAL;
- break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
- case IW_AUTH_KEY_MGMT:
- DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
- /* not implemented, return an error */
- ret = -EINVAL;
- break;
+ /* Immediately disable card */
+ lp->driverEnable = !iwa_val;
+ if (lp->driverEnable)
+ hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
+ else
+ hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
+ ret = 0;
+ break;
- case IW_AUTH_80211_AUTH_ALG:
- DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
- /* not implemented, return an error */
+ case IW_AUTH_MFP:
+ /* Management Frame Protection not supported.
+ * Only fail if set to required.
+ */
+ if (iwa_val == IW_AUTH_MFP_REQUIRED)
ret = -EINVAL;
- break;
+ else
+ ret = 0;
+ break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
- /* not implemented, return an error */
- ret = -EINVAL;
- break;
+ case IW_AUTH_KEY_MGMT:
- case IW_AUTH_ROAMING_CONTROL:
- DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
- /* not implemented, return an error */
- ret = -EINVAL;
- break;
+ /* Record required management suite.
+ * Will take effect on next commit */
+ if (iwa_val != 0)
+ lp->AuthKeyMgmtSuite = 4;
+ else
+ lp->AuthKeyMgmtSuite = 0;
- case IW_AUTH_PRIVACY_INVOKED:
- DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
- /* not implemented, return an error */
- ret = -EINVAL;
- break;
+ ret = -EINPROGRESS;
+ break;
- default:
- DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
- /* return an error */
+ case IW_AUTH_80211_AUTH_ALG:
+
+ /* Just record whether open or shared is required.
+ * Will take effect on next commit */
+ ret = -EINPROGRESS;
+
+ if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
+ lp->authentication = 1;
+ else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
+ lp->authentication = 0;
+ else
ret = -EINVAL;
- break;
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ /* Only needed for AP */
+ lp->ExcludeUnencrypted = iwa_val;
+ ret = -EINPROGRESS;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_ROAMING_CONTROL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ /* Not used. May need to do something with
+ * CIPHER_PAIRWISE and CIPHER_GROUP*/
+ ret = -EINPROGRESS;
+ break;
+
+ default:
+ DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
+ /* return an error */
+ ret = -EOPNOTSUPP;
+ break;
}
wl_act_int_on( lp );
@@ -2979,290 +3045,176 @@ out:
/*============================================================================*/
-
-static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
- int set_tx, u8 *seq, u8 *key, size_t key_len)
+static void flush_tx(struct wl_private *lp)
{
- int ret = -EINVAL;
- // int count = 0;
- int buf_idx = 0;
- hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
- { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
-
- DBG_FUNC( "hermes_set_key" );
- DBG_ENTER( DbgInfo );
+ ltv_t ltv;
+ int count;
/*
- * Check the key index here; if 0, load as Pairwise Key, otherwise,
- * load as a group key. Note that for the Hermes, the RIDs for
- * group/pariwise keys are different from each other and different
- * than the default WEP keys as well.
- */
- switch (alg)
- {
- case IW_ENCODE_ALG_TKIP:
- DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
-#if 0
- /*
- * Make sure that there is no data queued up in the firmware
- * before setting the TKIP keys. If this check is not
- * performed, some data may be sent out with incorrect MIC
- * and cause synchronizarion errors with the AP
- */
- /* Check every 1ms for 100ms */
- for( count = 0; count < 100; count++ )
- {
- usleep( 1000 );
+ * Make sure that there is no data queued up in the firmware
+ * before setting the TKIP keys. If this check is not
+ * performed, some data may be sent out with incorrect MIC
+ * and cause synchronizarion errors with the AP
+ */
+ /* Check every 1ms for 100ms */
+ for (count = 0; count < 100; count++) {
+ udelay(1000);
+
+ ltv.len = 2;
+ ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
+ ltv.u.u16[0] = 0;
+
+ hcf_get_info(&(lp->hcfCtx), (LTVP)&ltv);
+
+ if (ltv.u.u16[0] == 0)
+ break;
+ }
+
+ if (count >= 100)
+ DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
- ltv.len = 2;
- ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
- ltv.u.u16[0] = 0;
+}
- wl_get_info( sock, &ltv, ifname );
+static int wireless_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf)
+{
+ struct wl_private *lp = wl_priv(dev);
+ unsigned long flags;
+ int ret;
+ int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
+ ltv_t ltv;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
+ bool enable = true;
+ bool set_tx = false;
- if( ltv.u.u16[0] == 0 )
- {
- break;
- }
- }
+ DBG_ENTER(DbgInfo);
- if( count == 100 )
- {
- wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
- }
-#endif
+ if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
+ ret = -EBUSY;
+ goto out;
+ }
- switch (key_idx) {
- case 0:
- ltv->len = 28;
- ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ enable = false;
+ }
- /* Load the BSSID */
- memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
- buf_idx += ETH_ALEN;
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ set_tx = true;
- /* Load the TKIP key */
- memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
- buf_idx += 16;
+ wl_lock(lp, &flags);
- /* Load the TSC */
- memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
- buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
+ wl_act_int_off(lp);
- /* Load the RSC */
- memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
- buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
+ memset(&ltv, 0, sizeof(ltv));
- /* Load the TxMIC key */
- memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
- buf_idx += 8;
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_TKIP:
+ DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
- /* Load the RxMIC key */
- memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
+ if (sizeof(ext->rx_seq) != 8) {
+ DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
+ DBG_LEAVE(DbgInfo);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
- ret = 0;
- break;
- case 1:
- case 2:
- case 3:
- ltv->len = 26;
- ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
+ ret = hermes_set_tkip_keys(&ltv, key_idx, ext->addr.sa_data,
+ set_tx,
+ ext->rx_seq, ext->key, ext->key_len);
- /* Load the key Index */
- ltv->u.u16[buf_idx] = key_idx;
- /* If this is a Tx Key, set bit 8000 */
- if(set_tx)
- ltv->u.u16[buf_idx] |= 0x8000;
- buf_idx += 2;
+ if (ret != 0) {
+ DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
+ goto out_unlock;
+ }
- /* Load the RSC */
- memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
- buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
+ flush_tx(lp);
- /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
- CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
- memcpy(&ltv->u.u8[buf_idx], key, key_len);
- buf_idx += key_len;
+ lp->wext_enc = IW_ENCODE_ALG_TKIP;
- /* Load the TSC */
- memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
+ /* Write the key */
+ ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
+ break;
- ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
+ case IW_ENCODE_ALG_WEP:
+ DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
- ret = 0;
- break;
- default:
- break;
+ if (erq->flags & IW_ENCODE_RESTRICTED) {
+ DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
+ ret = -EINVAL;
+ goto out_unlock;
}
- break;
+ ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
+ enable, set_tx);
- case IW_ENCODE_ALG_WEP:
- DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
break;
case IW_ENCODE_ALG_CCMP:
- DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
+ DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
+ ret = -EOPNOTSUPP;
break;
case IW_ENCODE_ALG_NONE:
- DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
- switch (key_idx) {
- case 0:
- if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
- //if (addr != NULL) {
- ltv->len = 7;
- ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
- memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
- ret = 0;
- }
- break;
- case 1:
- case 2:
- case 3:
- /* Clear the Group TKIP keys by index */
- ltv->len = 2;
- ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
- ltv->u.u16[0] = key_idx;
-
+ DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
+
+ if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
+ ret = hermes_clear_tkip_keys(&ltv, key_idx,
+ ext->addr.sa_data);
+ flush_tx(lp);
+ lp->wext_enc = IW_ENCODE_ALG_NONE;
+ ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
+
+ } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
+ ret = hermes_set_wep_keys(lp, key_idx,
+ ext->key, ext->key_len,
+ false, false);
+ } else {
ret = 0;
- break;
- default:
- break;
}
+
break;
+
default:
DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
+ ret = -EOPNOTSUPP;
break;
}
- DBG_LEAVE( DbgInfo );
- return ret;
-} // hermes_set_key
-/*============================================================================*/
-
-
-
-static int wireless_set_encodeext (struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *keybuf)
-{
- struct wl_private *lp = wl_priv(dev);
- unsigned long flags;
- int ret;
- int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
- ltv_t ltv;
- struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
-
- DBG_FUNC( "wireless_set_encodeext" );
- DBG_ENTER( DbgInfo );
-
- if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
- ret = -EBUSY;
- goto out;
- }
-
- if (sizeof(ext->rx_seq) != 8) {
- DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
- DBG_LEAVE(DbgInfo);
- return -EINVAL;
- }
-
- /* Handle WEP keys via the old set encode procedure */
- if(ext->alg == IW_ENCODE_ALG_WEP) {
- struct iw_point wep_erq;
- char *wep_keybuf;
-
- /* Build request structure */
- wep_erq.flags = erq->flags; // take over flags with key index
- wep_erq.length = ext->key_len; // take length from extended key info
- wep_keybuf = ext->key; // pointer to the key text
-
- /* Call wireless_set_encode tot handle the WEP key */
- ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
- goto out;
- }
-
- /* Proceed for extended encode functions for WAP and NONE */
- wl_lock( lp, &flags );
-
- wl_act_int_off( lp );
-
- memset(&ltv, 0, sizeof(ltv));
- ret = hermes_set_key(&ltv, ext->alg, key_idx, ext->addr.sa_data,
- ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
- ext->rx_seq, ext->key, ext->key_len);
-
- if (ret != 0) {
- DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
- goto out_unlock;
- }
-
- /* Put the key in HCF */
- ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
-
out_unlock:
- if(ret == HCF_SUCCESS) {
- DBG_TRACE( DbgInfo, "Put key info succes\n");
- } else {
- DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
- }
- wl_act_int_on( lp );
+ wl_act_int_on(lp);
wl_unlock(lp, &flags);
out:
- DBG_LEAVE( DbgInfo );
+ DBG_LEAVE(DbgInfo);
return ret;
-} // wireless_set_encodeext
+}
/*============================================================================*/
-static int wireless_get_genie(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
+static int wireless_set_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
{
- struct wl_private *lp = wl_priv(dev);
- unsigned long flags;
int ret = 0;
- ltv_t ltv;
-
- DBG_FUNC( "wireless_get_genie" );
- DBG_ENTER( DbgInfo );
-
- if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
- ret = -EBUSY;
- goto out;
- }
-
- wl_lock( lp, &flags );
-
- wl_act_int_off( lp );
-
- memset(&ltv, 0, sizeof(ltv));
- ltv.len = 2;
- ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
- lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
- ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
- ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
-
- wl_act_int_on( lp );
+ DBG_ENTER(DbgInfo);
- wl_unlock(lp, &flags);
+ /* We can't write this to the card, but apparently this
+ * operation needs to succeed */
+ ret = 0;
-out:
- DBG_LEAVE( DbgInfo );
+ DBG_LEAVE(DbgInfo);
return ret;
}
/*============================================================================*/
-#endif // WIRELESS_EXT > 17
-
/*******************************************************************************
* wl_wireless_stats()
*******************************************************************************
@@ -3316,7 +3268,6 @@ struct iw_statistics * wl_wireless_stats( struct net_device *dev )
if( status == HCF_SUCCESS ) {
pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
-#ifdef USE_DBM
pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
@@ -3325,23 +3276,6 @@ struct iw_statistics * wl_wireless_stats( struct net_device *dev )
IW_QUAL_LEVEL_UPDATED |
IW_QUAL_NOISE_UPDATED |
IW_QUAL_DBM);
-#else
- pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
- HCF_MIN_COMM_QUALITY,
- HCF_MAX_COMM_QUALITY );
-
- pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
- HCF_MIN_SIGNAL_LEVEL,
- HCF_MAX_SIGNAL_LEVEL );
-
- pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
- HCF_MIN_NOISE_LEVEL,
- HCF_MAX_NOISE_LEVEL );
-
- pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
- IW_QUAL_LEVEL_UPDATED |
- IW_QUAL_NOISE_UPDATED);
-#endif /* USE_DBM */
} else {
memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
}
@@ -3512,7 +3446,6 @@ inline void wl_spy_gather( struct net_device *dev, u_char *mac )
******************************************************************************/
void wl_wext_event_freq( struct net_device *dev )
{
-#if WIRELESS_EXT > 13
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
/*------------------------------------------------------------------------*/
@@ -3524,7 +3457,6 @@ void wl_wext_event_freq( struct net_device *dev )
wrqu.freq.e = 0;
wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
-#endif /* WIRELESS_EXT > 13 */
return;
} // wl_wext_event_freq
@@ -3554,7 +3486,6 @@ void wl_wext_event_freq( struct net_device *dev )
******************************************************************************/
void wl_wext_event_mode( struct net_device *dev )
{
-#if WIRELESS_EXT > 13
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
/*------------------------------------------------------------------------*/
@@ -3569,7 +3500,6 @@ void wl_wext_event_mode( struct net_device *dev )
}
wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
-#endif /* WIRELESS_EXT > 13 */
return;
} // wl_wext_event_mode
@@ -3599,7 +3529,6 @@ void wl_wext_event_mode( struct net_device *dev )
******************************************************************************/
void wl_wext_event_essid( struct net_device *dev )
{
-#if WIRELESS_EXT > 13
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
/*------------------------------------------------------------------------*/
@@ -3616,7 +3545,6 @@ void wl_wext_event_essid( struct net_device *dev )
wrqu.essid.flags = 1;
wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
-#endif /* WIRELESS_EXT > 13 */
return;
} // wl_wext_event_essid
@@ -3646,7 +3574,6 @@ void wl_wext_event_essid( struct net_device *dev )
******************************************************************************/
void wl_wext_event_encode( struct net_device *dev )
{
-#if WIRELESS_EXT > 13
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
int index = 0;
@@ -3688,7 +3615,6 @@ void wl_wext_event_encode( struct net_device *dev )
wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
lp->DefaultKeys.key[index].key );
-#endif /* WIRELESS_EXT > 13 */
return;
} // wl_wext_event_encode
@@ -3718,7 +3644,6 @@ void wl_wext_event_encode( struct net_device *dev )
******************************************************************************/
void wl_wext_event_ap( struct net_device *dev )
{
-#if WIRELESS_EXT > 13
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
int status;
@@ -3747,8 +3672,6 @@ void wl_wext_event_ap( struct net_device *dev )
wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
}
-#endif /* WIRELESS_EXT > 13 */
-
return;
} // wl_wext_event_ap
/*============================================================================*/
@@ -3776,7 +3699,6 @@ void wl_wext_event_ap( struct net_device *dev )
******************************************************************************/
void wl_wext_event_scan_complete( struct net_device *dev )
{
-#if WIRELESS_EXT > 13
union iwreq_data wrqu;
/*------------------------------------------------------------------------*/
@@ -3785,7 +3707,6 @@ void wl_wext_event_scan_complete( struct net_device *dev )
wrqu.addr.sa_family = ARPHRD_ETHER;
wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
-#endif /* WIRELESS_EXT > 13 */
return;
} // wl_wext_event_scan_complete
@@ -3815,7 +3736,6 @@ void wl_wext_event_scan_complete( struct net_device *dev )
******************************************************************************/
void wl_wext_event_new_sta( struct net_device *dev )
{
-#if WIRELESS_EXT > 14
union iwreq_data wrqu;
/*------------------------------------------------------------------------*/
@@ -3826,7 +3746,6 @@ void wl_wext_event_new_sta( struct net_device *dev )
memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
wrqu.addr.sa_family = ARPHRD_ETHER;
wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
-#endif /* WIRELESS_EXT > 14 */
return;
} // wl_wext_event_new_sta
@@ -3856,7 +3775,6 @@ void wl_wext_event_new_sta( struct net_device *dev )
******************************************************************************/
void wl_wext_event_expired_sta( struct net_device *dev )
{
-#if WIRELESS_EXT > 14
union iwreq_data wrqu;
/*------------------------------------------------------------------------*/
@@ -3866,7 +3784,6 @@ void wl_wext_event_expired_sta( struct net_device *dev )
memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
wrqu.addr.sa_family = ARPHRD_ETHER;
wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
-#endif /* WIRELESS_EXT > 14 */
return;
} // wl_wext_event_expired_sta
@@ -3895,10 +3812,9 @@ void wl_wext_event_expired_sta( struct net_device *dev )
******************************************************************************/
void wl_wext_event_mic_failed( struct net_device *dev )
{
-#if WIRELESS_EXT > 14
- char msg[512];
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
+ struct iw_michaelmicfailure wxmic;
int key_idx;
char *addr1;
char *addr2;
@@ -3920,31 +3836,17 @@ void wl_wext_event_mic_failed( struct net_device *dev )
DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
hdr->status );
- memset( &wrqu, 0, sizeof( wrqu ));
- memset( msg, 0, sizeof( msg ));
-
-
- /* Because MIC failures are not part of the Wireless Extensions yet, they
- must be passed as a string using an IWEVCUSTOM event. In order for the
- event to be effective, the string format must be known by both the
- driver and the supplicant. The following is the string format used by the
- hostap project's WPA supplicant, and will be used here until the Wireless
- Extensions interface adds this support:
+ memset(&wrqu, 0, sizeof(wrqu));
+ memset(&wxmic, 0, sizeof(wxmic));
- MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
- */
+ wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
+ wxmic.flags |= (addr1[0] & 1) ?
+ IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
+ wxmic.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
- /* NOTE: Format of MAC address (using colons to separate bytes) may cause
- a problem in future versions of the supplicant, if they ever
- actually parse these parameters */
-#if DBG
- sprintf(msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast "
- "addr=%pM)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
- addr2);
-#endif
- wrqu.data.length = strlen( msg );
- wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
-#endif /* WIRELESS_EXT > 14 */
+ wrqu.data.length = sizeof(wxmic);
+ wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
return;
} // wl_wext_event_mic_failed
@@ -3974,8 +3876,6 @@ void wl_wext_event_mic_failed( struct net_device *dev )
******************************************************************************/
void wl_wext_event_assoc_ie( struct net_device *dev )
{
-#if WIRELESS_EXT > 14
- char msg[512];
union iwreq_data wrqu;
struct wl_private *lp = wl_priv(dev);
int status;
@@ -3986,7 +3886,6 @@ void wl_wext_event_assoc_ie( struct net_device *dev )
memset( &wrqu, 0, sizeof( wrqu ));
- memset( msg, 0, sizeof( msg ));
/* Retrieve the Association Request IE */
lp->ltvRecord.len = 45;
@@ -3999,24 +3898,18 @@ void wl_wext_event_assoc_ie( struct net_device *dev )
memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
wpa_ie = wl_parse_wpa_ie( &data, &length );
- /* Because this event (Association WPA-IE) is not part of the Wireless
- Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
- In order for the event to be effective, the string format must be known
- by both the driver and the supplicant. The following is the string format
- used by the hostap project's WPA supplicant, and will be used here until
- the Wireless Extensions interface adds this support:
-
- ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
- */
-
if( length != 0 )
{
- sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
- wrqu.data.length = strlen( msg );
- wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
+ wrqu.data.length = wpa_ie[1] + 2;
+ wireless_send_event(dev, IWEVASSOCREQIE,
+ &wrqu, wpa_ie);
+
+ /* This bit is a hack. We send the respie
+ * event at the same time */
+ wireless_send_event(dev, IWEVASSOCRESPIE,
+ &wrqu, wpa_ie);
}
}
-#endif /* WIRELESS_EXT > 14 */
return;
} // wl_wext_event_assoc_ie
@@ -4025,66 +3918,39 @@ void wl_wext_event_assoc_ie( struct net_device *dev )
static const iw_handler wl_handler[] =
{
- (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
- (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
- (iw_handler) NULL, /* SIOCSIWNWID */
- (iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
- (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
- (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
- (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
- (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
- (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
- (iw_handler) NULL , /* SIOCSIWRANGE */
- (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
- (iw_handler) NULL , /* SIOCSIWPRIV */
- (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
- (iw_handler) NULL , /* SIOCSIWSTATS */
- (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
- iw_handler_set_spy, /* SIOCSIWSPY */
- iw_handler_get_spy, /* SIOCGIWSPY */
- NULL, /* SIOCSIWTHRSPY */
- NULL, /* SIOCGIWTHRSPY */
- (iw_handler) NULL, /* SIOCSIWAP */
+ IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
+ IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
+ IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
+ IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
+ IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
+ IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
+ IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
+ IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
+ IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
+ IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
+ IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
- (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
-#else
- (iw_handler) NULL, /* SIOCGIWAP */
+ IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
#endif
- (iw_handler) NULL, /* SIOCSIWMLME */
- (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
- (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
- (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
- (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
- (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
- (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
- (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
- (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
- (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
- (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
- (iw_handler) NULL, /* SIOCSIWFRAG */
- (iw_handler) NULL, /* SIOCGIWFRAG */
- (iw_handler) NULL, /* SIOCSIWTXPOW */
- (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
- (iw_handler) NULL, /* SIOCSIWRETRY */
- (iw_handler) NULL, /* SIOCGIWRETRY */
- (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
- (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
- (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
- (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
- (iw_handler) NULL, /* SIOCGIWGENIE */
- (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
- (iw_handler) NULL, /* SIOCGIWAUTH */
- (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
- (iw_handler) NULL, /* SIOCGIWENCODEEXT */
- (iw_handler) NULL, /* SIOCSIWPMKSA */
- (iw_handler) NULL, /* -- hole -- */
+ IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
+ IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
+ IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
+ IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
+ IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
+ IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
+ IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
+ IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
+ IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
+ IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
+ IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
+ IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
+ IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
+ IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
+ IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
+ IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
+ IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
+ IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
+ IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
};
static const iw_handler wl_private_handler[] =
@@ -4120,5 +3986,3 @@ const struct iw_handler_def wl_iw_handler_def =
.standard = (iw_handler *) wl_handler,
.get_wireless_stats = wl_get_wireless_stats,
};
-
-#endif // WIRELESS_EXT
diff --git a/drivers/staging/wlags49_h2/wl_wext.h b/drivers/staging/wlags49_h2/wl_wext.h
index 39d39a4..a713058 100644
--- a/drivers/staging/wlags49_h2/wl_wext.h
+++ b/drivers/staging/wlags49_h2/wl_wext.h
@@ -62,9 +62,6 @@
#define __WL_WEXT_H__
-#ifdef WIRELESS_EXT
-
-
/*******************************************************************************
* function protoypes
******************************************************************************/
@@ -88,9 +85,4 @@ void wl_wext_event_assoc_ie( struct net_device *dev );
extern const struct iw_handler_def wl_iw_handler_def;
-#else
-#error WIRELESS_EXT
-#endif // WIRELESS_EXT
-
-
#endif // __WL_WEXT_H__
diff --git a/drivers/staging/wlags49_h25/Makefile b/drivers/staging/wlags49_h25/Makefile
index 7d4b563..6e0159d 100644
--- a/drivers/staging/wlags49_h25/Makefile
+++ b/drivers/staging/wlags49_h25/Makefile
@@ -11,11 +11,9 @@
#
# If you want to build AP support (untested), comment out -DSTA_ONLY
-INSTALLDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless
ccflags-y := -I$(KERNELDIR)/include
ccflags-y += -I$(src) \
-DBUS_PCMCIA \
- -DUSE_WPA \
-DUSE_WEXT \
-DSTA_ONLY \
-DWVLAN_49 \
@@ -39,10 +37,6 @@ $(WLNAME)-y += ap_h25.o
endif
endif
-# If KERNELRELEASE is defined, we've been invoked from the
-# kernel build system and can use its language.
-ifneq ($(KERNELRELEASE),)
-
obj-m += $(WLNAME).o
$(WLNAME)-y += wl_profile.o \
@@ -59,23 +53,3 @@ $(WLNAME)-y += wl_profile.o \
$(WLNAME)-$(CONFIG_SYSFS) += wl_sysfs.o
-# Otherwise we were called directly from the command
-# line; invoke the kernel build system.
-else
- KERNELDIR ?= /lib/modules/$(shell uname -r)/build
- PWD := $(shell pwd)
-
-default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
-endif
-
-clean:
- rm -fr *.o *.ko *.mod.c *.mod.o .*.*.cmd Module.symvers \
- Module.markers modules.order .tmp_versions
-
-install: default
- -rmmod $(WLNAME)
- install -d $(INSTALLDIR)
- install -m 0644 -o root -g root $(WLNAME).ko $(INSTALLDIR)
- /sbin/depmod -aq
-
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index b0af292..14bfeb2 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -715,7 +715,7 @@ static const struct net_device_ops p80211_netdev_ops = {
.ndo_stop = p80211knetdev_stop,
.ndo_get_stats = p80211knetdev_get_stats,
.ndo_start_xmit = p80211knetdev_hard_start_xmit,
- .ndo_set_multicast_list = p80211knetdev_set_multicast_list,
+ .ndo_set_rx_mode = p80211knetdev_set_multicast_list,
.ndo_do_ioctl = p80211knetdev_do_ioctl,
.ndo_set_mac_address = p80211knetdev_set_mac_address,
.ndo_tx_timeout = p80211knetdev_tx_timeout,
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index 729d03d..3c40096 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -442,9 +442,9 @@ int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
{
int i;
- for (i = 0; i < *nfchunks; i++) {
+ for (i = 0; i < *nfchunks; i++)
kfree(fchunk[i].data);
- }
+
*nfchunks = 0;
memset(fchunk, 0, sizeof(*fchunk));
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 21f25a2..417aea5 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -50,7 +50,6 @@
* --------------------------------------------------------------------
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
index c85ff5e..13d9bc2 100644
--- a/drivers/staging/xgifb/TODO
+++ b/drivers/staging/xgifb/TODO
@@ -5,7 +5,6 @@ Arnaud
TODO:
- clean ups
-- fix build warnings when module
- sort out dup ids with SiS driver
- remove useless/wrong/unused #ifdef/code/...
- fix printk usages
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
index f6cd22d..71aebe3 100644
--- a/drivers/staging/xgifb/XGI_main.h
+++ b/drivers/staging/xgifb/XGI_main.h
@@ -11,12 +11,6 @@
#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
-#define VER_MAJOR 0
-#define VER_MINOR 8
-#define VER_LEVEL 1
-
-#define DRIVER_DESC "XGI Volari Frame Buffer Module Version 0.8.1"
-
#ifndef PCI_VENDOR_ID_XG
#define PCI_VENDOR_ID_XG 0x18CA
#endif
@@ -37,12 +31,6 @@
#define PCI_DEVICE_ID_XG_27 0x027
#endif
-
-
-#define XGI_IOTYPE1 void __iomem
-#define XGI_IOTYPE2 __iomem
-#define XGIINITSTATIC static
-
static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = {
{PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0},
@@ -58,61 +46,29 @@ static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = {
MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
/* To be included in fb.h */
-#ifndef FB_ACCEL_XGI_GLAMOUR_2
-#define FB_ACCEL_XGI_GLAMOUR_2 40 /* XGI 315, 650, 740 */
-#endif
#ifndef FB_ACCEL_XGI_XABRE
#define FB_ACCEL_XGI_XABRE 41 /* XGI 330 ("Xabre") */
#endif
-#define MAX_ROM_SCAN 0x10000
-
-#define SEQ_ADR 0x14
#define SEQ_DATA 0x15
-#define DAC_ADR 0x18
-#define DAC_DATA 0x19
-#define CRTC_ADR 0x24
-#define CRTC_DATA 0x25
-#define DAC2_ADR (0x16-0x30)
-#define DAC2_DATA (0x17-0x30)
-#define VB_PART1_ADR (0x04-0x30)
-#define VB_PART1_DATA (0x05-0x30)
-#define VB_PART2_ADR (0x10-0x30)
-#define VB_PART2_DATA (0x11-0x30)
-#define VB_PART3_ADR (0x12-0x30)
-#define VB_PART3_DATA (0x13-0x30)
-#define VB_PART4_ADR (0x14-0x30)
-#define VB_PART4_DATA (0x15-0x30)
-
-#define XGISR XGI_Pr.P3c4
-#define XGICR XGI_Pr.P3d4
-#define XGIDACA XGI_Pr.P3c8
-#define XGIDACD XGI_Pr.P3c9
-#define XGIPART1 XGI_Pr.Part1Port
-#define XGIPART2 XGI_Pr.Part2Port
-#define XGIPART3 XGI_Pr.Part3Port
-#define XGIPART4 XGI_Pr.Part4Port
-#define XGIPART5 XGI_Pr.Part5Port
+
+#define XGISR (xgifb_info->dev_info.P3c4)
+#define XGICR (xgifb_info->dev_info.P3d4)
+#define XGIDACA (xgifb_info->dev_info.P3c8)
+#define XGIDACD (xgifb_info->dev_info.P3c9)
+#define XGIPART1 (xgifb_info->dev_info.Part1Port)
+#define XGIPART2 (xgifb_info->dev_info.Part2Port)
+#define XGIPART3 (xgifb_info->dev_info.Part3Port)
+#define XGIPART4 (xgifb_info->dev_info.Part4Port)
+#define XGIPART5 (xgifb_info->dev_info.Part5Port)
#define XGIDAC2A XGIPART5
#define XGIDAC2D (XGIPART5 + 1)
-#define XGIMISCR (XGI_Pr.RelIO + 0x1c)
-#define XGIINPSTAT (XGI_Pr.RelIO + 0x2a)
#define IND_XGI_PASSWORD 0x05 /* SRs */
-#define IND_XGI_COLOR_MODE 0x06
#define IND_XGI_RAMDAC_CONTROL 0x07
#define IND_XGI_DRAM_SIZE 0x14
-#define IND_XGI_SCRATCH_REG_16 0x16
-#define IND_XGI_SCRATCH_REG_17 0x17
-#define IND_XGI_SCRATCH_REG_1A 0x1A
#define IND_XGI_MODULE_ENABLE 0x1E
#define IND_XGI_PCI_ADDRESS_SET 0x20
-#define IND_XGI_TURBOQUEUE_ADR 0x26
-#define IND_XGI_TURBOQUEUE_SET 0x27
-#define IND_XGI_POWER_ON_TRAP 0x38
-#define IND_XGI_POWER_ON_TRAP2 0x39
-#define IND_XGI_CMDQUEUE_SET 0x26
-#define IND_XGI_CMDQUEUE_THRESHOLD 0x27
#define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */
#define IND_XGI_SCRATCH_REG_CR31 0x31
@@ -120,23 +76,10 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
#define IND_XGI_SCRATCH_REG_CR33 0x33
#define IND_XGI_LCD_PANEL 0x36
#define IND_XGI_SCRATCH_REG_CR37 0x37
-#define IND_XGI_AGP_IO_PAD 0x48
-#define IND_BRI_DRAM_STATUS 0x63 /* PCI config memory size offset */
-
-#define MMIO_QUEUE_PHYBASE 0x85C0
-#define MMIO_QUEUE_WRITEPORT 0x85C4
-#define MMIO_QUEUE_READPORT 0x85C8
-
-#define IND_XGI_CRT2_WRITE_ENABLE_300 0x24
#define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F
#define XGI_PASSWORD 0x86 /* SR05 */
-#define XGI_INTERLACED_MODE 0x20 /* SR06 */
-#define XGI_8BPP_COLOR_MODE 0x0
-#define XGI_15BPP_COLOR_MODE 0x1
-#define XGI_16BPP_COLOR_MODE 0x2
-#define XGI_32BPP_COLOR_MODE 0x4
#define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */
#define XGI_DRAM_SIZE_1MB 0x00
@@ -148,27 +91,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
#define XGI_DRAM_SIZE_64MB 0x06
#define XGI_DRAM_SIZE_128MB 0x07
#define XGI_DRAM_SIZE_256MB 0x08
-#define XGI_DATA_BUS_MASK 0x02
-#define XGI_DATA_BUS_64 0x00
-#define XGI_DATA_BUS_128 0x01
-#define XGI_DUAL_CHANNEL_MASK 0x0C
-#define XGI_SINGLE_CHANNEL_1_RANK 0x0
-#define XGI_SINGLE_CHANNEL_2_RANK 0x1
-#define XGI_ASYM_DDR 0x02
-#define XGI_DUAL_CHANNEL_1_RANK 0x3
-
-#define XGI550_DRAM_SIZE_MASK 0x3F /* 550/650/740 SR14 */
-#define XGI550_DRAM_SIZE_4MB 0x00
-#define XGI550_DRAM_SIZE_8MB 0x01
-#define XGI550_DRAM_SIZE_16MB 0x03
-#define XGI550_DRAM_SIZE_24MB 0x05
-#define XGI550_DRAM_SIZE_32MB 0x07
-#define XGI550_DRAM_SIZE_64MB 0x0F
-#define XGI550_DRAM_SIZE_96MB 0x17
-#define XGI550_DRAM_SIZE_128MB 0x1F
-#define XGI550_DRAM_SIZE_256MB 0x3F
-
-#define XGI_SCRATCH_REG_1A_MASK 0x10
#define XGI_ENABLE_2D 0x40 /* SR1E */
@@ -176,7 +98,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
#define XGI_PCI_ADDR_ENABLE 0x80
#define XGI_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
-#define XGI_MODE_SELECT_CRT2 0x02
#define XGI_VB_OUTPUT_COMPOSITE 0x04
#define XGI_VB_OUTPUT_SVIDEO 0x08
#define XGI_VB_OUTPUT_SCART 0x10
@@ -199,118 +120,34 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR)
#define XGI_EXTERNAL_CHIP_MASK 0x0E /* CR37 */
-#define XGI_EXTERNAL_CHIP_XGI301 0x01 /* in CR37 << 1 ! */
-#define XGI_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */
-#define XGI_EXTERNAL_CHIP_TRUMPION 0x03 /* in CR37 << 1 ! */
-#define XGI_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04 /* in CR37 << 1 ! */
-#define XGI_EXTERNAL_CHIP_CHRONTEL 0x05 /* in CR37 << 1 ! */
#define XGI310_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */
#define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 /* in CR37 << 1 ! */
-#define XGI_AGP_2X 0x20 /* CR48 */
-
-#define BRI_DRAM_SIZE_MASK 0x70 /* PCI bridge config data */
-#define BRI_DRAM_SIZE_2MB 0x00
-#define BRI_DRAM_SIZE_4MB 0x01
-#define BRI_DRAM_SIZE_8MB 0x02
-#define BRI_DRAM_SIZE_16MB 0x03
-#define BRI_DRAM_SIZE_32MB 0x04
-#define BRI_DRAM_SIZE_64MB 0x05
-
-#define SR_BUFFER_SIZE 5
-#define CR_BUFFER_SIZE 5
-
/* ------------------- Global Variables ----------------------------- */
-/* Fbcon variables */
-static struct fb_info *fb_info;
-
-
-static int video_type = FB_TYPE_PACKED_PIXELS;
-
-static struct fb_var_screeninfo default_var = {
- .xres = 0,
- .yres = 0,
- .xres_virtual = 0,
- .yres_virtual = 0,
- .xoffset = 0,
- .yoffset = 0,
- .bits_per_pixel = 0,
- .grayscale = 0,
- .red = {0, 8, 0},
- .green = {0, 8, 0},
- .blue = {0, 8, 0},
- .transp = {0, 0, 0},
- .nonstd = 0,
- .activate = FB_ACTIVATE_NOW,
- .height = -1,
- .width = -1,
- .accel_flags = 0,
- .pixclock = 0,
- .left_margin = 0,
- .right_margin = 0,
- .upper_margin = 0,
- .lower_margin = 0,
- .hsync_len = 0,
- .vsync_len = 0,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo XGIfb_fix = {
- .id = "XGI",
- .type = FB_TYPE_PACKED_PIXELS,
- .xpanstep = 1,
- .ypanstep = 1,
-};
-static char myid[20];
-static u32 pseudo_palette[17];
-
-
/* display status */
-static int XGIfb_off = 0;
-static int XGIfb_crt1off = 0;
+static int XGIfb_crt1off;
static int XGIfb_forcecrt1 = -1;
-static int XGIfb_userom = 0;
-/*static int XGIfb_useoem = -1; */
+static int XGIfb_userom ;
/* global flags */
-static int XGIfb_registered;
-static int XGIfb_tvmode = 0;
-static int XGIfb_pdc = 0;
-static int enable_dstn = 0;
+static int XGIfb_tvmode;
+static int enable_dstn;
static int XGIfb_ypan = -1;
-
-static int XGIfb_CRT2_write_enable = 0;
-
/* TW: CRT2 type (for overriding autodetection) */
static int XGIfb_crt2type = -1;
/* PR: Tv plug type (for overriding autodetection) */
static int XGIfb_tvplug = -1;
-static unsigned char XGIfb_detectedpdc = 0;
-
-static unsigned char XGIfb_detectedlcda = 0xff;
-
-
-
-
/* TW: For ioctl XGIFB_GET_INFO */
/* XGIfb_info XGIfbinfo; */
-/* TW: Hardware extension; contains data on hardware */
-static struct xgi_hw_device_info XGIhw_ext;
-
-/* TW: XGI private structure */
-static struct vb_device_info XGI_Pr;
-
#define MD_XGI300 1
#define MD_XGI315 2
/* mode table */
-/* NOT const - will be patched for 1280x960 mode number chaos reasons */
-static struct _XGIbios_mode {
+static const struct _XGIbios_mode {
char name[15];
u8 mode_no;
u16 vesa_mode_no_1; /* "XGI defined" VESA mode number */
@@ -323,9 +160,6 @@ static struct _XGIbios_mode {
u16 rows;
u8 chipset;
} XGIbios_mode[] = {
-#define MODE_INDEX_NONE 0 /* TW: index for mode=none */
- {"none", 0xFF, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0,
- MD_XGI300|MD_XGI315}, /* TW: for mode "none" */
{"320x240x16", 0x56, 0x0000, 0x0000, 320, 240, 16, 1, 40, 15,
MD_XGI315},
{"320x480x8", 0x5A, 0x0000, 0x0000, 320, 480, 8, 1, 40, 30,
@@ -365,11 +199,9 @@ static struct _XGIbios_mode {
MD_XGI300|MD_XGI315},
{"800x480x32", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30,
MD_XGI300|MD_XGI315},
-#define DEFAULT_MODE 21 /* TW: index for 800x600x8 */
-#define DEFAULT_LCDMODE 21 /* TW: index for 800x600x8 */
-#define DEFAULT_TVMODE 21 /* TW: index for 800x600x8 */
{"800x600x8", 0x30, 0x0103, 0x0103, 800, 600, 8, 1, 100, 37,
MD_XGI300|MD_XGI315},
+#define DEFAULT_MODE 20 /* index for 800x600x16 */
{"800x600x16", 0x47, 0x0114, 0x0114, 800, 600, 16, 1, 100, 37,
MD_XGI300|MD_XGI315},
{"800x600x24", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37,
@@ -424,9 +256,8 @@ static struct _XGIbios_mode {
MD_XGI315},
{"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48,
MD_XGI315},
-#define MODEINDEX_1280x960 48
{"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60,
- MD_XGI300|MD_XGI315}, /* TW: Modenumbers being patched */
+ MD_XGI300|MD_XGI315},
{"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60,
MD_XGI300|MD_XGI315},
{"1280x960x24", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60,
@@ -476,16 +307,6 @@ static struct _XGIbios_mode {
{"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
};
-/* mode-related variables */
-#ifdef MODULE
-static int xgifb_mode_idx = 1;
-#else
-static int xgifb_mode_idx = -1; /* Use a default mode if we are
- inside the kernel */
-#endif
-static u8 XGIfb_mode_no = 0;
-static u8 XGIfb_rate_idx = 0;
-
/* TW: CR36 evaluation */
static const unsigned short XGI300paneltype[] = {
LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
@@ -505,19 +326,19 @@ static const struct _XGI_crt2type {
int tvplug_no;
} XGI_crt2type[] = {
{"NONE", 0, -1},
- {"LCD", DISPTYPE_LCD, -1},
- {"TV", DISPTYPE_TV, -1},
- {"VGA", DISPTYPE_CRT2, -1},
- {"SVIDEO", DISPTYPE_TV, TVPLUG_SVIDEO},
- {"COMPOSITE", DISPTYPE_TV, TVPLUG_COMPOSITE},
- {"SCART", DISPTYPE_TV, TVPLUG_SCART},
+ {"LCD", XGIFB_DISP_LCD, -1},
+ {"TV", XGIFB_DISP_TV, -1},
+ {"VGA", XGIFB_DISP_CRT, -1},
+ {"SVIDEO", XGIFB_DISP_TV, TVPLUG_SVIDEO},
+ {"COMPOSITE", XGIFB_DISP_TV, TVPLUG_COMPOSITE},
+ {"SCART", XGIFB_DISP_TV, TVPLUG_SCART},
{"none", 0, -1},
- {"lcd", DISPTYPE_LCD, -1},
- {"tv", DISPTYPE_TV, -1},
- {"vga", DISPTYPE_CRT2, -1},
- {"svideo", DISPTYPE_TV, TVPLUG_SVIDEO},
- {"composite", DISPTYPE_TV, TVPLUG_COMPOSITE},
- {"scart", DISPTYPE_TV, TVPLUG_SCART},
+ {"lcd", XGIFB_DISP_LCD, -1},
+ {"tv", XGIFB_DISP_TV, -1},
+ {"vga", XGIFB_DISP_CRT, -1},
+ {"svideo", XGIFB_DISP_TV, TVPLUG_SVIDEO},
+ {"composite", XGIFB_DISP_TV, TVPLUG_COMPOSITE},
+ {"scart", XGIFB_DISP_TV, TVPLUG_SCART},
{"\0", -1, -1}
};
@@ -740,6 +561,5 @@ static const struct _XGI_TV_filter {
};
static int filter = -1;
-static unsigned char filter_tb;
#endif
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index cadec2a..277e408 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -5,7 +5,6 @@
*/
/* #include <linux/config.h> */
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -29,10 +28,6 @@
#include <linux/types.h>
#include <linux/proc_fs.h>
-#ifndef XGIFB_PAN
-#define XGIFB_PAN
-#endif
-
#include <linux/io.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
@@ -46,15 +41,17 @@
#include "vb_setmode.h"
#define Index_CR_GPIO_Reg1 0x48
-#define Index_CR_GPIO_Reg2 0x49
#define Index_CR_GPIO_Reg3 0x4a
#define GPIOG_EN (1<<6)
-#define GPIOG_WRITE (1<<6)
#define GPIOG_READ (1<<1)
#define XGIFB_ROM_SIZE 65536
+static char *mode;
+static int vesa = -1;
+static unsigned int refresh_rate;
+
/* -------------------- Macro definitions ---------------------------- */
#undef XGIFBDEBUG
@@ -144,9 +141,6 @@ static inline void dumpVGAReg(void)
}
#endif
-/* data for XGI components */
-struct video_info xgi_video_info;
-
#if 1
#define DEBUGPRN(x)
#else
@@ -391,44 +385,6 @@ static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
}
-/* ------------ Interface for init & mode switching code ------------- */
-
-static unsigned char XGIfb_query_VGA_config_space(
- struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
- unsigned long set, unsigned long *value)
-{
- static struct pci_dev *pdev = NULL;
- static unsigned char init = 0, valid_pdev = 0;
-
- if (!set)
- DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
- else
- DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
-
- if (!init) {
- init = 1;
- pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
- pdev);
- if (pdev) {
- valid_pdev = 1;
- pci_dev_put(pdev);
- }
- }
-
- if (!valid_pdev) {
- printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
- xgi_video_info.chip_id);
- return 0;
- }
-
- if (set == 0)
- pci_read_config_dword(pdev, offset, (u32 *) value);
- else
- pci_write_config_dword(pdev, offset, (u32)(*value));
-
- return 1;
-}
-
/* ------------------ Internal helper routines ----------------- */
static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
@@ -446,48 +402,26 @@ static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
&& (XGIbios_mode[XGIfb_mode_idx].yres
== XGI21_LCDCapList[0].LVDSVDE)
&& (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
- XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
found_mode = 1;
break;
}
XGIfb_mode_idx++;
}
if (!found_mode)
- XGIfb_mode_idx = 0;
+ XGIfb_mode_idx = -1;
return XGIfb_mode_idx;
}
-static void XGIfb_search_mode(const char *name)
+static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
+ const char *name)
{
int i = 0, j = 0, l;
- if (name == NULL) {
- printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
- xgifb_mode_idx = DEFAULT_MODE;
- if ((xgi_video_info.chip == XG21)
- && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
- == DISPTYPE_LCD)) {
- xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
- }
- return;
- }
-
- if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
- printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
- xgifb_mode_idx = DEFAULT_MODE;
- if ((xgi_video_info.chip == XG21)
- && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
- == DISPTYPE_LCD)) {
- xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
- }
- return;
- }
-
while (XGIbios_mode[i].mode_no != 0) {
l = min(strlen(name), strlen(XGIbios_mode[i].name));
if (!strncmp(name, XGIbios_mode[i].name, l)) {
- xgifb_mode_idx = i;
+ xgifb_info->mode_idx = i;
j = 1;
break;
}
@@ -497,82 +431,66 @@ static void XGIfb_search_mode(const char *name)
printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
}
-static void XGIfb_search_vesamode(unsigned int vesamode)
+static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
+ unsigned int vesamode)
{
int i = 0, j = 0;
- if (vesamode == 0) {
-
- printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
- xgifb_mode_idx = DEFAULT_MODE;
- if ((xgi_video_info.chip == XG21)
- && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
- == DISPTYPE_LCD)) {
- xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
- }
- return;
- }
+ if (vesamode == 0)
+ goto invalid;
vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
while (XGIbios_mode[i].mode_no != 0) {
if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
(XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
- xgifb_mode_idx = i;
+ xgifb_info->mode_idx = i;
j = 1;
break;
}
i++;
}
+
+invalid:
if (!j)
printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
}
-static int XGIfb_GetXG21LVDSData(void)
+static int XGIfb_GetXG21LVDSData(struct xgifb_video_info *xgifb_info)
{
u8 tmp;
- unsigned char *pData;
+ void __iomem *data = xgifb_info->mmio_vbase + 0x20000;
int i, j, k;
tmp = xgifb_reg_get(XGISR, 0x1e);
xgifb_reg_set(XGISR, 0x1e, tmp | 4);
- pData = xgi_video_info.mmio_vbase + 0x20000;
- if ((pData[0x0] == 0x55) &&
- (pData[0x1] == 0xAA) &&
- (pData[0x65] & 0x1)) {
- i = pData[0x316] | (pData[0x317] << 8);
- j = pData[i - 1];
+ if ((readb(data) == 0x55) &&
+ (readb(data + 1) == 0xAA) &&
+ (readb(data + 0x65) & 0x1)) {
+ i = readw(data + 0x316);
+ j = readb(data + i - 1);
if (j == 0xff)
j = 1;
k = 0;
do {
- XGI21_LCDCapList[k].LVDS_Capability = pData[i]
- | (pData[i + 1] << 8);
- XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
- + 3] << 8);
- XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
- + 5] << 8);
- XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
- + 7] << 8);
- XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
- + 9] << 8);
- XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
- + 11] << 8);
- XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
- + 13] << 8);
- XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
- | (pData[i + 15] << 8);
- XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
- | (pData[i + 17] << 8);
- XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
- XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
- XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
- XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
- XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
- XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
- XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
+ XGI21_LCDCapList[k].LVDS_Capability = readw(data + i);
+ XGI21_LCDCapList[k].LVDSHT = readw(data + i + 2);
+ XGI21_LCDCapList[k].LVDSVT = readw(data + i + 4);
+ XGI21_LCDCapList[k].LVDSHDE = readw(data + i + 6);
+ XGI21_LCDCapList[k].LVDSVDE = readw(data + i + 8);
+ XGI21_LCDCapList[k].LVDSHFP = readw(data + i + 10);
+ XGI21_LCDCapList[k].LVDSVFP = readw(data + i + 12);
+ XGI21_LCDCapList[k].LVDSHSYNC = readw(data + i + 14);
+ XGI21_LCDCapList[k].LVDSVSYNC = readw(data + i + 16);
+ XGI21_LCDCapList[k].VCLKData1 = readb(data + i + 18);
+ XGI21_LCDCapList[k].VCLKData2 = readb(data + i + 19);
+ XGI21_LCDCapList[k].PSC_S1 = readb(data + i + 20);
+ XGI21_LCDCapList[k].PSC_S2 = readb(data + i + 21);
+ XGI21_LCDCapList[k].PSC_S3 = readb(data + i + 22);
+ XGI21_LCDCapList[k].PSC_S4 = readb(data + i + 23);
+ XGI21_LCDCapList[k].PSC_S5 = readb(data + i + 24);
i += 25;
j--;
k++;
@@ -583,13 +501,13 @@ static int XGIfb_GetXG21LVDSData(void)
return 0;
}
-static int XGIfb_validate_mode(int myindex)
+static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
{
u16 xres, yres;
+ struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
- if (xgi_video_info.chip == XG21) {
- if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
- == DISPTYPE_LCD) {
+ if (xgifb_info->chip == XG21) {
+ if (xgifb_info->display2 == XGIFB_DISP_LCD) {
xres = XGI21_LCDCapList[0].LVDSHDE;
yres = XGI21_LCDCapList[0].LVDSVDE;
if (XGIbios_mode[myindex].xres > xres)
@@ -608,15 +526,15 @@ static int XGIfb_validate_mode(int myindex)
}
/* FIXME: for now, all is valid on XG27 */
- if (xgi_video_info.chip == XG27)
+ if (xgifb_info->chip == XG27)
return myindex;
if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
return -1;
- switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
- case DISPTYPE_LCD:
- switch (XGIhw_ext.ulCRT2LCDType) {
+ switch (xgifb_info->display2) {
+ case XGIFB_DISP_LCD:
+ switch (hw_info->ulCRT2LCDType) {
case LCD_640x480:
xres = 640;
yres = 480;
@@ -672,13 +590,13 @@ static int XGIfb_validate_mode(int myindex)
return -1;
if (XGIbios_mode[myindex].yres > yres)
return -1;
- if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
- (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
+ if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
+ (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
switch (XGIbios_mode[myindex].xres) {
case 512:
if (XGIbios_mode[myindex].yres != 512)
return -1;
- if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
+ if (hw_info->ulCRT2LCDType == LCD_1024x600)
return -1;
break;
case 640:
@@ -696,13 +614,13 @@ static int XGIfb_validate_mode(int myindex)
(XGIbios_mode[myindex].yres != 768))
return -1;
if ((XGIbios_mode[myindex].yres == 600) &&
- (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
+ (hw_info->ulCRT2LCDType != LCD_1024x600))
return -1;
break;
case 1152:
if ((XGIbios_mode[myindex].yres) != 768)
return -1;
- if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
+ if (hw_info->ulCRT2LCDType != LCD_1152x768)
return -1;
break;
case 1280:
@@ -710,7 +628,7 @@ static int XGIfb_validate_mode(int myindex)
(XGIbios_mode[myindex].yres != 1024))
return -1;
if ((XGIbios_mode[myindex].yres == 768) &&
- (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
+ (hw_info->ulCRT2LCDType != LCD_1280x768))
return -1;
break;
case 1400:
@@ -748,7 +666,7 @@ static int XGIfb_validate_mode(int myindex)
(XGIbios_mode[myindex].yres != 1024))
return -1;
if (XGIbios_mode[myindex].yres == 960) {
- if (XGIhw_ext.ulCRT2LCDType ==
+ if (hw_info->ulCRT2LCDType ==
LCD_1400x1050)
return -1;
}
@@ -766,28 +684,28 @@ static int XGIfb_validate_mode(int myindex)
}
}
break;
- case DISPTYPE_TV:
+ case XGIFB_DISP_TV:
switch (XGIbios_mode[myindex].xres) {
case 512:
case 640:
case 800:
break;
case 720:
- if (xgi_video_info.TV_type == TVMODE_NTSC) {
+ if (xgifb_info->TV_type == TVMODE_NTSC) {
if (XGIbios_mode[myindex].yres != 480)
return -1;
- } else if (xgi_video_info.TV_type == TVMODE_PAL) {
+ } else if (xgifb_info->TV_type == TVMODE_PAL) {
if (XGIbios_mode[myindex].yres != 576)
return -1;
}
/* TW: LVDS/CHRONTEL does not support 720 */
- if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
- xgi_video_info.hasVB == HASVB_CHRONTEL) {
+ if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL ||
+ xgifb_info->hasVB == HASVB_CHRONTEL) {
return -1;
}
break;
case 1024:
- if (xgi_video_info.TV_type == TVMODE_NTSC) {
+ if (xgifb_info->TV_type == TVMODE_NTSC) {
if (XGIbios_mode[myindex].bpp == 32)
return -1;
}
@@ -796,10 +714,12 @@ static int XGIfb_validate_mode(int myindex)
return -1;
}
break;
- case DISPTYPE_CRT2:
+ case XGIFB_DISP_CRT:
if (XGIbios_mode[myindex].xres > 1280)
return -1;
break;
+ case XGIFB_DISP_NONE:
+ break;
}
return myindex;
@@ -824,49 +744,52 @@ static void XGIfb_search_crt2type(const char *name)
printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
}
-static u8 XGIfb_search_refresh_rate(unsigned int rate)
+static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info,
+ unsigned int rate)
{
u16 xres, yres;
int i = 0;
- xres = XGIbios_mode[xgifb_mode_idx].xres;
- yres = XGIbios_mode[xgifb_mode_idx].yres;
+ xres = XGIbios_mode[xgifb_info->mode_idx].xres;
+ yres = XGIbios_mode[xgifb_info->mode_idx].yres;
- XGIfb_rate_idx = 0;
+ xgifb_info->rate_idx = 0;
while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
if ((XGIfb_vrate[i].xres == xres) &&
(XGIfb_vrate[i].yres == yres)) {
if (XGIfb_vrate[i].refresh == rate) {
- XGIfb_rate_idx = XGIfb_vrate[i].idx;
+ xgifb_info->rate_idx = XGIfb_vrate[i].idx;
break;
} else if (XGIfb_vrate[i].refresh > rate) {
if ((XGIfb_vrate[i].refresh - rate) <= 3) {
DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
rate, XGIfb_vrate[i].refresh);
- XGIfb_rate_idx = XGIfb_vrate[i].idx;
- xgi_video_info.refresh_rate =
+ xgifb_info->rate_idx =
+ XGIfb_vrate[i].idx;
+ xgifb_info->refresh_rate =
XGIfb_vrate[i].refresh;
} else if (((rate - XGIfb_vrate[i - 1].refresh)
<= 2) && (XGIfb_vrate[i].idx
!= 1)) {
DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
rate, XGIfb_vrate[i-1].refresh);
- XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
- xgi_video_info.refresh_rate =
+ xgifb_info->rate_idx =
+ XGIfb_vrate[i - 1].idx;
+ xgifb_info->refresh_rate =
XGIfb_vrate[i - 1].refresh;
}
break;
} else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
rate, XGIfb_vrate[i].refresh);
- XGIfb_rate_idx = XGIfb_vrate[i].idx;
+ xgifb_info->rate_idx = XGIfb_vrate[i].idx;
break;
}
}
i++;
}
- if (XGIfb_rate_idx > 0) {
- return XGIfb_rate_idx;
+ if (xgifb_info->rate_idx > 0) {
+ return xgifb_info->rate_idx;
} else {
printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n",
rate, xres, yres);
@@ -892,13 +815,14 @@ static void XGIfb_search_tvstd(const char *name)
/* ----------- FBDev related routines for all series ----------- */
-static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
+static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
+ struct fb_var_screeninfo *var)
{
switch (var->bits_per_pixel) {
case 8:
var->red.offset = var->green.offset = var->blue.offset = 0;
var->red.length = var->green.length = var->blue.length = 6;
- xgi_video_info.video_cmap_len = 256;
+ xgifb_info->video_cmap_len = 256;
break;
case 16:
var->red.offset = 11;
@@ -909,7 +833,7 @@ static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
- xgi_video_info.video_cmap_len = 16;
+ xgifb_info->video_cmap_len = 16;
break;
case 32:
var->red.offset = 16;
@@ -920,45 +844,45 @@ static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
- xgi_video_info.video_cmap_len = 16;
+ xgifb_info->video_cmap_len = 16;
break;
}
}
/* --------------------- SetMode routines ------------------------- */
-static void XGIfb_pre_setmode(void)
+static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
{
u8 cr30 = 0, cr31 = 0;
cr31 = xgifb_reg_get(XGICR, 0x31);
cr31 &= ~0x60;
- switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
- case DISPTYPE_CRT2:
+ switch (xgifb_info->display2) {
+ case XGIFB_DISP_CRT:
cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
cr31 |= XGI_DRIVER_MODE;
break;
- case DISPTYPE_LCD:
+ case XGIFB_DISP_LCD:
cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
cr31 |= XGI_DRIVER_MODE;
break;
- case DISPTYPE_TV:
- if (xgi_video_info.TV_type == TVMODE_HIVISION)
+ case XGIFB_DISP_TV:
+ if (xgifb_info->TV_type == TVMODE_HIVISION)
cr30 = (XGI_VB_OUTPUT_HIVISION
| XGI_SIMULTANEOUS_VIEW_ENABLE);
- else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
+ else if (xgifb_info->TV_plug == TVPLUG_SVIDEO)
cr30 = (XGI_VB_OUTPUT_SVIDEO
| XGI_SIMULTANEOUS_VIEW_ENABLE);
- else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
+ else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE)
cr30 = (XGI_VB_OUTPUT_COMPOSITE
| XGI_SIMULTANEOUS_VIEW_ENABLE);
- else if (xgi_video_info.TV_plug == TVPLUG_SCART)
+ else if (xgifb_info->TV_plug == TVPLUG_SCART)
cr30 = (XGI_VB_OUTPUT_SCART
| XGI_SIMULTANEOUS_VIEW_ENABLE);
cr31 |= XGI_DRIVER_MODE;
- if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
+ if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL)
cr31 |= 0x01;
else
cr31 &= ~0x01;
@@ -970,10 +894,11 @@ static void XGIfb_pre_setmode(void)
xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
- xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
+ xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33,
+ (xgifb_info->rate_idx & 0x0F));
}
-static void XGIfb_post_setmode(void)
+static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
{
u8 reg;
unsigned char doit = 1;
@@ -983,21 +908,21 @@ static void XGIfb_post_setmode(void)
xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
*test*
*/
- if (xgi_video_info.video_bpp == 8) {
+ if (xgifb_info->video_bpp == 8) {
/* TW: We can't switch off CRT1 on LVDS/Chrontel
* in 8bpp Modes */
- if ((xgi_video_info.hasVB == HASVB_LVDS) ||
- (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
+ if ((xgifb_info->hasVB == HASVB_LVDS) ||
+ (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) {
doit = 0;
}
/* TW: We can't switch off CRT1 on 301B-DH
* in 8bpp Modes if using LCD */
- if (xgi_video_info.disp_state & DISPTYPE_LCD)
+ if (xgifb_info->display2 == XGIFB_DISP_LCD)
doit = 0;
}
/* TW: We can't switch off CRT1 if bridge is in slave mode */
- if (xgi_video_info.hasVB != HASVB_NONE) {
+ if (xgifb_info->hasVB != HASVB_NONE) {
reg = xgifb_reg_get(XGIPART1, 0x00);
if ((reg & 0x50) == 0x10)
@@ -1016,49 +941,54 @@ static void XGIfb_post_setmode(void)
xgifb_reg_and(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
- if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
- == HASVB_301)) {
+ if (xgifb_info->display2 == XGIFB_DISP_TV &&
+ xgifb_info->hasVB == HASVB_301) {
reg = xgifb_reg_get(XGIPART4, 0x01);
if (reg < 0xB0) { /* Set filter for XGI301 */
- switch (xgi_video_info.video_width) {
+ int filter_tb;
+
+ switch (xgifb_info->video_width) {
case 320:
- filter_tb = (xgi_video_info.TV_type ==
+ filter_tb = (xgifb_info->TV_type ==
TVMODE_NTSC) ? 4 : 12;
break;
case 640:
- filter_tb = (xgi_video_info.TV_type ==
+ filter_tb = (xgifb_info->TV_type ==
TVMODE_NTSC) ? 5 : 13;
break;
case 720:
- filter_tb = (xgi_video_info.TV_type ==
+ filter_tb = (xgifb_info->TV_type ==
TVMODE_NTSC) ? 6 : 14;
break;
case 800:
- filter_tb = (xgi_video_info.TV_type ==
+ filter_tb = (xgifb_info->TV_type ==
TVMODE_NTSC) ? 7 : 15;
break;
default:
+ filter_tb = 0;
filter = -1;
break;
}
- xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+ xgifb_reg_or(XGIPART1,
+ IND_XGI_CRT2_WRITE_ENABLE_315,
+ 0x01);
- if (xgi_video_info.TV_type == TVMODE_NTSC) {
+ if (xgifb_info->TV_type == TVMODE_NTSC) {
xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
- if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+ if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
xgifb_reg_and(XGIPART2, 0x30, 0xdf);
- } else if (xgi_video_info.TV_plug
+ } else if (xgifb_info->TV_plug
== TVPLUG_COMPOSITE) {
xgifb_reg_or(XGIPART2, 0x30, 0x20);
- switch (xgi_video_info.video_width) {
+ switch (xgifb_info->video_width) {
case 640:
xgifb_reg_set(XGIPART2,
0x35,
@@ -1104,20 +1034,20 @@ static void XGIfb_post_setmode(void)
}
}
- } else if (xgi_video_info.TV_type == TVMODE_PAL) {
+ } else if (xgifb_info->TV_type == TVMODE_PAL) {
xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
- if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+ if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
xgifb_reg_and(XGIPART2, 0x30, 0xDF);
- } else if (xgi_video_info.TV_plug
+ } else if (xgifb_info->TV_plug
== TVPLUG_COMPOSITE) {
xgifb_reg_or(XGIPART2, 0x30, 0x20);
- switch (xgi_video_info.video_width) {
+ switch (xgifb_info->video_width) {
case 640:
xgifb_reg_set(XGIPART2,
0x35,
@@ -1204,7 +1134,8 @@ static void XGIfb_post_setmode(void)
static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
struct fb_info *info)
{
-
+ struct xgifb_video_info *xgifb_info = info->par;
+ struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
unsigned int htotal = var->left_margin + var->xres + var->right_margin
+ var->hsync_len;
unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
@@ -1242,58 +1173,61 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
if (var->pixclock && htotal && vtotal) {
drate = 1000000000 / var->pixclock;
hrate = (drate * 1000) / htotal;
- xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
+ xgifb_info->refresh_rate = (unsigned int) (hrate * 2
/ vtotal);
} else {
- xgi_video_info.refresh_rate = 60;
+ xgifb_info->refresh_rate = 60;
}
printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
var->xres,
var->yres,
var->bits_per_pixel,
- xgi_video_info.refresh_rate);
+ xgifb_info->refresh_rate);
- old_mode = xgifb_mode_idx;
- xgifb_mode_idx = 0;
+ old_mode = xgifb_info->mode_idx;
+ xgifb_info->mode_idx = 0;
- while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
- && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
- if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
- && (XGIbios_mode[xgifb_mode_idx].yres
- == var->yres)
- && (XGIbios_mode[xgifb_mode_idx].bpp
+ while ((XGIbios_mode[xgifb_info->mode_idx].mode_no != 0) &&
+ (XGIbios_mode[xgifb_info->mode_idx].xres <= var->xres)) {
+ if ((XGIbios_mode[xgifb_info->mode_idx].xres == var->xres) &&
+ (XGIbios_mode[xgifb_info->mode_idx].yres == var->yres) &&
+ (XGIbios_mode[xgifb_info->mode_idx].bpp
== var->bits_per_pixel)) {
- XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
found_mode = 1;
break;
}
- xgifb_mode_idx++;
+ xgifb_info->mode_idx++;
}
if (found_mode)
- xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+ xgifb_info->mode_idx = XGIfb_validate_mode(xgifb_info,
+ xgifb_info->mode_idx);
else
- xgifb_mode_idx = -1;
+ xgifb_info->mode_idx = -1;
- if (xgifb_mode_idx < 0) {
+ if (xgifb_info->mode_idx < 0) {
printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n",
var->xres, var->yres, var->bits_per_pixel);
- xgifb_mode_idx = old_mode;
+ xgifb_info->mode_idx = old_mode;
return -EINVAL;
}
- if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
- XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
- xgi_video_info.refresh_rate = 60;
+ if (XGIfb_search_refresh_rate(xgifb_info,
+ xgifb_info->refresh_rate) == 0) {
+ xgifb_info->rate_idx =
+ XGIbios_mode[xgifb_info->mode_idx].rate_idx;
+ xgifb_info->refresh_rate = 60;
}
if (isactive) {
- XGIfb_pre_setmode();
- if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
+ XGIfb_pre_setmode(xgifb_info);
+ if (XGISetModeNew(hw_info,
+ XGIbios_mode[xgifb_info->mode_idx].mode_no)
+ == 0) {
printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
- XGIfb_mode_no);
+ XGIbios_mode[xgifb_info->mode_idx].mode_no);
return -EINVAL;
}
info->fix.line_length = ((info->var.xres_virtual
@@ -1306,85 +1240,77 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
0x0E,
(info->fix.line_length & 0xff00) >> 8);
- XGIfb_post_setmode();
+ XGIfb_post_setmode(xgifb_info);
DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
- XGIbios_mode[xgifb_mode_idx].xres,
- XGIbios_mode[xgifb_mode_idx].yres,
- XGIbios_mode[xgifb_mode_idx].bpp,
- xgi_video_info.refresh_rate);
-
- xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
- xgi_video_info.video_vwidth = info->var.xres_virtual;
- xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
- xgi_video_info.video_vheight = info->var.yres_virtual;
- xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
- xgi_video_info.org_x = xgi_video_info.org_y = 0;
- xgi_video_info.video_linelength = info->var.xres_virtual
- * (xgi_video_info.video_bpp >> 3);
- switch (xgi_video_info.video_bpp) {
+ XGIbios_mode[xgifb_info->mode_idx].xres,
+ XGIbios_mode[xgifb_info->mode_idx].yres,
+ XGIbios_mode[xgifb_info->mode_idx].bpp,
+ xgifb_info->refresh_rate);
+
+ xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
+ xgifb_info->video_vwidth = info->var.xres_virtual;
+ xgifb_info->video_width =
+ XGIbios_mode[xgifb_info->mode_idx].xres;
+ xgifb_info->video_vheight = info->var.yres_virtual;
+ xgifb_info->video_height =
+ XGIbios_mode[xgifb_info->mode_idx].yres;
+ xgifb_info->org_x = xgifb_info->org_y = 0;
+ xgifb_info->video_linelength = info->var.xres_virtual
+ * (xgifb_info->video_bpp >> 3);
+ switch (xgifb_info->video_bpp) {
case 8:
- xgi_video_info.DstColor = 0x0000;
- xgi_video_info.XGI310_AccelDepth = 0x00000000;
- xgi_video_info.video_cmap_len = 256;
+ xgifb_info->DstColor = 0x0000;
+ xgifb_info->XGI310_AccelDepth = 0x00000000;
+ xgifb_info->video_cmap_len = 256;
#if defined(__powerpc__)
cr_data = xgifb_reg_get(XGICR, 0x4D);
xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
#endif
break;
case 16:
- xgi_video_info.DstColor = 0x8000;
- xgi_video_info.XGI310_AccelDepth = 0x00010000;
+ xgifb_info->DstColor = 0x8000;
+ xgifb_info->XGI310_AccelDepth = 0x00010000;
#if defined(__powerpc__)
cr_data = xgifb_reg_get(XGICR, 0x4D);
xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
#endif
- xgi_video_info.video_cmap_len = 16;
+ xgifb_info->video_cmap_len = 16;
break;
case 32:
- xgi_video_info.DstColor = 0xC000;
- xgi_video_info.XGI310_AccelDepth = 0x00020000;
- xgi_video_info.video_cmap_len = 16;
+ xgifb_info->DstColor = 0xC000;
+ xgifb_info->XGI310_AccelDepth = 0x00020000;
+ xgifb_info->video_cmap_len = 16;
#if defined(__powerpc__)
cr_data = xgifb_reg_get(XGICR, 0x4D);
xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
#endif
break;
default:
- xgi_video_info.video_cmap_len = 16;
+ xgifb_info->video_cmap_len = 16;
printk(KERN_ERR "XGIfb: Unsupported depth %d",
- xgi_video_info.video_bpp);
+ xgifb_info->video_bpp);
break;
}
}
- XGIfb_bpp_to_var(var); /*update ARGB info*/
+ XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
DEBUGPRN("End of do_set_var");
dumpVGAReg();
return 0;
}
-#ifdef XGIFB_PAN
-static int XGIfb_pan_var(struct fb_var_screeninfo *var)
+static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
+ struct xgifb_video_info *xgifb_info = info->par;
unsigned int base;
/* printk("Inside pan_var"); */
- if (var->xoffset > (var->xres_virtual - var->xres)) {
- /* printk("Pan: xo: %d xv %d xr %d\n",
- var->xoffset, var->xres_virtual, var->xres); */
- return -EINVAL;
- }
- if (var->yoffset > (var->yres_virtual - var->yres)) {
- /* printk("Pan: yo: %d yv %d yr %d\n",
- var->yoffset, var->yres_virtual, var->yres); */
- return -EINVAL;
- }
- base = var->yoffset * var->xres_virtual + var->xoffset;
+ base = var->yoffset * info->var.xres_virtual + var->xoffset;
/* calculate base bpp dep. */
- switch (var->bits_per_pixel) {
+ switch (info->var.bits_per_pixel) {
case 16:
base >>= 1;
break;
@@ -1404,8 +1330,8 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var)
xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
- if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
- xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+ if (xgifb_info->display2 != XGIFB_DISP_NONE) {
+ xgifb_reg_or(XGIPART1, IND_XGI_CRT2_WRITE_ENABLE_315, 0x01);
xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
@@ -1417,7 +1343,6 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var)
/* printk("End of pan_var"); */
return 0;
}
-#endif
static int XGIfb_open(struct fb_info *info, int user)
{
@@ -1450,6 +1375,8 @@ static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info)
{
+ struct xgifb_video_info *xgifb_info = info->par;
+
if (regno >= XGIfb_get_cmap_len(&info->var))
return 1;
@@ -1459,7 +1386,7 @@ static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
outb((red >> 10), XGIDACD);
outb((green >> 10), XGIDACD);
outb((blue >> 10), XGIDACD);
- if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ if (xgifb_info->display2 != XGIFB_DISP_NONE) {
outb(regno, XGIDAC2A);
outb((red >> 8), XGIDAC2D);
outb((green >> 8), XGIDAC2D);
@@ -1487,30 +1414,28 @@ static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
+ struct xgifb_video_info *xgifb_info = info->par;
+
DEBUGPRN("inside get_fix");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, myid);
-
- fix->smem_start = xgi_video_info.video_base;
+ fix->smem_start = xgifb_info->video_base;
- fix->smem_len = xgi_video_info.video_size;
+ fix->smem_len = xgifb_info->video_size;
- fix->type = video_type;
+ fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
- if (xgi_video_info.video_bpp == 8)
+ if (xgifb_info->video_bpp == 8)
fix->visual = FB_VISUAL_PSEUDOCOLOR;
else
fix->visual = FB_VISUAL_DIRECTCOLOR;
fix->xpanstep = 0;
-#ifdef XGIFB_PAN
if (XGIfb_ypan)
fix->ypanstep = 1;
-#endif
fix->ywrapstep = 0;
- fix->line_length = xgi_video_info.video_linelength;
- fix->mmio_start = xgi_video_info.mmio_base;
- fix->mmio_len = xgi_video_info.mmio_size;
+ fix->line_length = xgifb_info->video_linelength;
+ fix->mmio_start = xgifb_info->mmio_base;
+ fix->mmio_len = xgifb_info->mmio_size;
fix->accel = FB_ACCEL_XGI_XABRE;
DEBUGPRN("end of get_fix");
@@ -1532,6 +1457,7 @@ static int XGIfb_set_par(struct fb_info *info)
static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
+ struct xgifb_video_info *xgifb_info = info->par;
unsigned int htotal = var->left_margin + var->xres + var->right_margin
+ var->hsync_len;
unsigned int vtotal = 0;
@@ -1562,15 +1488,15 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (var->pixclock && htotal && vtotal) {
drate = 1000000000 / var->pixclock;
hrate = (drate * 1000) / htotal;
- xgi_video_info.refresh_rate =
+ xgifb_info->refresh_rate =
(unsigned int) (hrate * 2 / vtotal);
printk(KERN_DEBUG
"%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
"%s: drate=%d, hrate=%d, refresh_rate=%d\n",
__func__, var->pixclock, htotal, vtotal,
- __func__, drate, hrate, xgi_video_info.refresh_rate);
+ __func__, drate, hrate, xgifb_info->refresh_rate);
} else {
- xgi_video_info.refresh_rate = 60;
+ xgifb_info->refresh_rate = 60;
}
/*
@@ -1592,7 +1518,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if ((XGIbios_mode[search_idx].xres == var->xres) &&
(XGIbios_mode[search_idx].yres == var->yres) &&
(XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
- if (XGIfb_validate_mode(search_idx) > 0) {
+ if (XGIfb_validate_mode(xgifb_info, search_idx) > 0) {
found_mode = 1;
break;
}
@@ -1610,7 +1536,8 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
(var->yres <= XGIbios_mode[search_idx].yres) &&
(var->bits_per_pixel ==
XGIbios_mode[search_idx].bpp)) {
- if (XGIfb_validate_mode(search_idx) > 0) {
+ if (XGIfb_validate_mode(xgifb_info,
+ search_idx) > 0) {
found_mode = 1;
break;
}
@@ -1633,7 +1560,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* TW: TODO: Check the refresh rate */
/* Adapt RGB settings */
- XGIfb_bpp_to_var(var);
+ XGIfb_bpp_to_var(xgifb_info, var);
/* Sanity check for offsets */
if (var->xoffset < 0)
@@ -1649,7 +1576,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
} /* else { */
/* TW: Now patch yres_virtual if we use panning */
/* May I do this? */
- /* var->yres_virtual = xgi_video_info.heapstart /
+ /* var->yres_virtual = xgifb_info->heapstart /
(var->xres * (var->bits_per_pixel >> 3)); */
/* if (var->yres_virtual <= var->yres) { */
/* TW: Paranoia check */
@@ -1674,7 +1601,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return 0;
}
-#ifdef XGIFB_PAN
static int XGIfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -1682,9 +1608,9 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
/* printk("\nInside pan_display:\n"); */
- if (var->xoffset > (var->xres_virtual - var->xres))
+ if (var->xoffset > (info->var.xres_virtual - info->var.xres))
return -EINVAL;
- if (var->yoffset > (var->yres_virtual - var->yres))
+ if (var->yoffset > (info->var.yres_virtual - info->var.yres))
return -EINVAL;
if (var->vmode & FB_VMODE_YWRAP) {
@@ -1697,7 +1623,7 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
> info->var.yres_virtual)
return -EINVAL;
}
- err = XGIfb_pan_var(var);
+ err = XGIfb_pan_var(var, info);
if (err < 0)
return err;
@@ -1711,10 +1637,10 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
/* printk("End of pan_display\n"); */
return 0;
}
-#endif
static int XGIfb_blank(int blank, struct fb_info *info)
{
+ struct xgifb_video_info *xgifb_info = info->par;
u8 reg;
reg = xgifb_reg_get(XGICR, 0x17);
@@ -1737,9 +1663,7 @@ static struct fb_ops XGIfb_ops = {
.fb_check_var = XGIfb_check_var,
.fb_set_par = XGIfb_set_par,
.fb_setcolreg = XGIfb_setcolreg,
-#ifdef XGIFB_PAN
.fb_pan_display = XGIfb_pan_display,
-#endif
.fb_blank = XGIfb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
@@ -1751,51 +1675,51 @@ static struct fb_ops XGIfb_ops = {
/* for XGI 315/550/650/740/330 */
-static int XGIfb_get_dram_size(void)
+static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
{
u8 ChannelNum, tmp;
u8 reg = 0;
/* xorg driver sets 32MB * 1 channel */
- if (xgi_video_info.chip == XG27)
+ if (xgifb_info->chip == XG27)
xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51);
reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE);
switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
case XGI_DRAM_SIZE_1MB:
- xgi_video_info.video_size = 0x100000;
+ xgifb_info->video_size = 0x100000;
break;
case XGI_DRAM_SIZE_2MB:
- xgi_video_info.video_size = 0x200000;
+ xgifb_info->video_size = 0x200000;
break;
case XGI_DRAM_SIZE_4MB:
- xgi_video_info.video_size = 0x400000;
+ xgifb_info->video_size = 0x400000;
break;
case XGI_DRAM_SIZE_8MB:
- xgi_video_info.video_size = 0x800000;
+ xgifb_info->video_size = 0x800000;
break;
case XGI_DRAM_SIZE_16MB:
- xgi_video_info.video_size = 0x1000000;
+ xgifb_info->video_size = 0x1000000;
break;
case XGI_DRAM_SIZE_32MB:
- xgi_video_info.video_size = 0x2000000;
+ xgifb_info->video_size = 0x2000000;
break;
case XGI_DRAM_SIZE_64MB:
- xgi_video_info.video_size = 0x4000000;
+ xgifb_info->video_size = 0x4000000;
break;
case XGI_DRAM_SIZE_128MB:
- xgi_video_info.video_size = 0x8000000;
+ xgifb_info->video_size = 0x8000000;
break;
case XGI_DRAM_SIZE_256MB:
- xgi_video_info.video_size = 0x10000000;
+ xgifb_info->video_size = 0x10000000;
break;
default:
return -1;
}
tmp = (reg & 0x0c) >> 2;
- switch (xgi_video_info.chip) {
+ switch (xgifb_info->chip) {
case XG20:
case XG21:
case XG27:
@@ -1831,25 +1755,25 @@ static int XGIfb_get_dram_size(void)
break;
}
- xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
+ xgifb_info->video_size = xgifb_info->video_size * ChannelNum;
/* PLiad fixed for benchmarking and fb set */
- /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
- /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
+ /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */
+ /* xgifb_info->video_size = 0x1000000; */ /* benchmark */
printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
reg,
- xgi_video_info.video_size, ChannelNum);
+ xgifb_info->video_size, ChannelNum);
return 0;
}
-static void XGIfb_detect_VB(void)
+static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
{
u8 cr32, temp = 0;
- xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
+ xgifb_info->TV_plug = xgifb_info->TV_type = 0;
- switch (xgi_video_info.hasVB) {
+ switch (xgifb_info->hasVB) {
case HASVB_LVDS_CHRONTEL:
case HASVB_CHRONTEL:
break;
@@ -1872,35 +1796,35 @@ static void XGIfb_detect_VB(void)
if (XGIfb_crt2type != -1)
/* TW: Override with option */
- xgi_video_info.disp_state = XGIfb_crt2type;
+ xgifb_info->display2 = XGIfb_crt2type;
else if (cr32 & XGI_VB_TV)
- xgi_video_info.disp_state = DISPTYPE_TV;
+ xgifb_info->display2 = XGIFB_DISP_TV;
else if (cr32 & XGI_VB_LCD)
- xgi_video_info.disp_state = DISPTYPE_LCD;
+ xgifb_info->display2 = XGIFB_DISP_LCD;
else if (cr32 & XGI_VB_CRT2)
- xgi_video_info.disp_state = DISPTYPE_CRT2;
+ xgifb_info->display2 = XGIFB_DISP_CRT;
else
- xgi_video_info.disp_state = 0;
+ xgifb_info->display2 = XGIFB_DISP_NONE;
if (XGIfb_tvplug != -1)
/* PR/TW: Override with option */
- xgi_video_info.TV_plug = XGIfb_tvplug;
+ xgifb_info->TV_plug = XGIfb_tvplug;
else if (cr32 & XGI_VB_HIVISION) {
- xgi_video_info.TV_type = TVMODE_HIVISION;
- xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+ xgifb_info->TV_type = TVMODE_HIVISION;
+ xgifb_info->TV_plug = TVPLUG_SVIDEO;
} else if (cr32 & XGI_VB_SVIDEO)
- xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+ xgifb_info->TV_plug = TVPLUG_SVIDEO;
else if (cr32 & XGI_VB_COMPOSITE)
- xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
+ xgifb_info->TV_plug = TVPLUG_COMPOSITE;
else if (cr32 & XGI_VB_SCART)
- xgi_video_info.TV_plug = TVPLUG_SCART;
+ xgifb_info->TV_plug = TVPLUG_SCART;
- if (xgi_video_info.TV_type == 0) {
+ if (xgifb_info->TV_type == 0) {
temp = xgifb_reg_get(XGICR, 0x38);
if (temp & 0x10)
- xgi_video_info.TV_type = TVMODE_PAL;
+ xgifb_info->TV_type = TVMODE_PAL;
else
- xgi_video_info.TV_type = TVMODE_NTSC;
+ xgifb_info->TV_type = TVMODE_NTSC;
}
/* TW: Copy forceCRT1 option to CRT1off if option is given */
@@ -1912,37 +1836,37 @@ static void XGIfb_detect_VB(void)
}
}
-static int XGIfb_has_VB(void)
+static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
{
u8 vb_chipid;
vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
switch (vb_chipid) {
case 0x01:
- xgi_video_info.hasVB = HASVB_301;
+ xgifb_info->hasVB = HASVB_301;
break;
case 0x02:
- xgi_video_info.hasVB = HASVB_302;
+ xgifb_info->hasVB = HASVB_302;
break;
default:
- xgi_video_info.hasVB = HASVB_NONE;
+ xgifb_info->hasVB = HASVB_NONE;
return 0;
}
return 1;
}
-static void XGIfb_get_VB_type(void)
+static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
{
u8 reg;
- if (!XGIfb_has_VB()) {
+ if (!XGIfb_has_VB(xgifb_info)) {
reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
case XGI310_EXTERNAL_CHIP_LVDS:
- xgi_video_info.hasVB = HASVB_LVDS;
+ xgifb_info->hasVB = HASVB_LVDS;
break;
case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
- xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
+ xgifb_info->hasVB = HASVB_LVDS_CHRONTEL;
break;
default:
break;
@@ -1950,49 +1874,47 @@ static void XGIfb_get_VB_type(void)
}
}
-XGIINITSTATIC int __init XGIfb_setup(char *options)
+static int __init xgifb_optval(char *fullopt, int validx)
{
- char *this_opt;
+ unsigned long lres;
- xgi_video_info.refresh_rate = 0;
+ if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
+ pr_err("xgifb: invalid value for option: %s\n", fullopt);
+ return 0;
+ }
+ return lres;
+}
- printk(KERN_INFO "XGIfb: Options %s\n", options);
+static int __init XGIfb_setup(char *options)
+{
+ char *this_opt;
if (!options || !*options)
return 0;
+ pr_info("xgifb: options: %s\n", options);
+
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
if (!strncmp(this_opt, "mode:", 5)) {
- XGIfb_search_mode(this_opt + 5);
- } else if (!strncmp(this_opt, "vesa:", 5)) {
- XGIfb_search_vesamode(simple_strtoul(
- this_opt + 5, NULL, 0));
- } else if (!strncmp(this_opt, "mode:", 5)) {
- XGIfb_search_mode(this_opt + 5);
+ mode = this_opt + 5;
} else if (!strncmp(this_opt, "vesa:", 5)) {
- XGIfb_search_vesamode(simple_strtoul(
- this_opt + 5, NULL, 0));
+ vesa = xgifb_optval(this_opt, 5);
} else if (!strncmp(this_opt, "vrate:", 6)) {
- xgi_video_info.refresh_rate = simple_strtoul(
- this_opt + 6, NULL, 0);
+ refresh_rate = xgifb_optval(this_opt, 6);
} else if (!strncmp(this_opt, "rate:", 5)) {
- xgi_video_info.refresh_rate = simple_strtoul(
- this_opt + 5, NULL, 0);
- } else if (!strncmp(this_opt, "off", 3)) {
- XGIfb_off = 1;
+ refresh_rate = xgifb_optval(this_opt, 5);
} else if (!strncmp(this_opt, "crt1off", 7)) {
XGIfb_crt1off = 1;
} else if (!strncmp(this_opt, "filter:", 7)) {
- filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
+ filter = xgifb_optval(this_opt, 7);
} else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
XGIfb_search_crt2type(this_opt + 14);
} else if (!strncmp(this_opt, "forcecrt1:", 10)) {
- XGIfb_forcecrt1 = (int)simple_strtoul(
- this_opt + 10, NULL, 0);
+ XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
} else if (!strncmp(this_opt, "tvmode:", 7)) {
XGIfb_search_tvstd(this_opt + 7);
} else if (!strncmp(this_opt, "tvstandard:", 11)) {
@@ -2000,32 +1922,15 @@ XGIINITSTATIC int __init XGIfb_setup(char *options)
} else if (!strncmp(this_opt, "dstn", 4)) {
enable_dstn = 1;
/* TW: DSTN overrules forcecrt2type */
- XGIfb_crt2type = DISPTYPE_LCD;
- } else if (!strncmp(this_opt, "pdc:", 4)) {
- XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
- if (XGIfb_pdc & ~0x3c) {
- printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
- XGIfb_pdc = 0;
- }
+ XGIfb_crt2type = XGIFB_DISP_LCD;
} else if (!strncmp(this_opt, "noypan", 6)) {
XGIfb_ypan = 0;
} else if (!strncmp(this_opt, "userom:", 7)) {
- XGIfb_userom = (int)simple_strtoul(
- this_opt + 7, NULL, 0);
- /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
- /* XGIfb_useoem = (int)simple_strtoul(
- this_opt + 7, NULL, 0); */
+ XGIfb_userom = xgifb_optval(this_opt, 7);
} else {
- XGIfb_search_mode(this_opt);
- /* printk(KERN_INFO "XGIfb: Invalid option %s\n",
- this_opt); */
+ mode = this_opt;
}
-
- /* TW: Panning only with acceleration */
- XGIfb_ypan = 0;
-
}
- printk("\nxgifb: outa xgifb_setup 3450");
return 0;
}
@@ -2057,44 +1962,46 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
u8 reg, reg1;
u8 CR48, CR38;
int ret;
+ bool xgi21_drvlcdcaplist = false;
+ struct fb_info *fb_info;
+ struct xgifb_video_info *xgifb_info;
+ struct xgi_hw_device_info *hw_info;
- if (XGIfb_off)
- return -ENXIO;
-
- XGIfb_registered = 0;
-
- memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
- fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
+ fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev);
if (!fb_info)
return -ENOMEM;
- xgi_video_info.chip_id = pdev->device;
+ xgifb_info = fb_info->par;
+ hw_info = &xgifb_info->hw_info;
+ xgifb_info->fb_info = fb_info;
+ xgifb_info->chip_id = pdev->device;
pci_read_config_byte(pdev,
PCI_REVISION_ID,
- &xgi_video_info.revision_id);
- XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
-
- xgi_video_info.pcibus = pdev->bus->number;
- xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
- xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
- xgi_video_info.subsysvendor = pdev->subsystem_vendor;
- xgi_video_info.subsysdevice = pdev->subsystem_device;
-
- xgi_video_info.video_base = pci_resource_start(pdev, 0);
- xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
- xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
- xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
- XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
+ &xgifb_info->revision_id);
+ hw_info->jChipRevision = xgifb_info->revision_id;
+
+ xgifb_info->pcibus = pdev->bus->number;
+ xgifb_info->pcislot = PCI_SLOT(pdev->devfn);
+ xgifb_info->pcifunc = PCI_FUNC(pdev->devfn);
+ xgifb_info->subsysvendor = pdev->subsystem_vendor;
+ xgifb_info->subsysdevice = pdev->subsystem_device;
+
+ xgifb_info->video_base = pci_resource_start(pdev, 0);
+ xgifb_info->mmio_base = pci_resource_start(pdev, 1);
+ xgifb_info->mmio_size = pci_resource_len(pdev, 1);
+ xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
+ hw_info->pjIOAddress = (unsigned char *)xgifb_info->vga_base;
/* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
- (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
+ (unsigned long)pci_resource_start(pdev, 2),
+ xgifb_info->dev_info.RelIO);
if (pci_enable_device(pdev)) {
ret = -EIO;
goto error;
}
- XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
+ XGIRegInit(&xgifb_info->dev_info, (unsigned long)hw_info->pjIOAddress);
xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD);
@@ -2105,417 +2012,413 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
goto error;
}
- switch (xgi_video_info.chip_id) {
+ switch (xgifb_info->chip_id) {
case PCI_DEVICE_ID_XG_20:
xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
if (CR48&GPIOG_READ)
- xgi_video_info.chip = XG21;
+ xgifb_info->chip = XG21;
else
- xgi_video_info.chip = XG20;
- XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ xgifb_info->chip = XG20;
break;
case PCI_DEVICE_ID_XG_40:
- xgi_video_info.chip = XG40;
- XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ xgifb_info->chip = XG40;
break;
case PCI_DEVICE_ID_XG_41:
- xgi_video_info.chip = XG41;
- XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ xgifb_info->chip = XG41;
break;
case PCI_DEVICE_ID_XG_42:
- xgi_video_info.chip = XG42;
- XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ xgifb_info->chip = XG42;
break;
case PCI_DEVICE_ID_XG_27:
- xgi_video_info.chip = XG27;
- XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ xgifb_info->chip = XG27;
break;
default:
ret = -ENODEV;
goto error;
}
- printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
- XGIhw_ext.jChipType = xgi_video_info.chip;
+ printk("XGIfb:chipid = %x\n", xgifb_info->chip);
+ hw_info->jChipType = xgifb_info->chip;
- if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
- XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
- if (XGIhw_ext.pjVirtualRomBase)
+ if ((xgifb_info->chip == XG21) || (XGIfb_userom)) {
+ hw_info->pjVirtualRomBase = xgifb_copy_rom(pdev);
+ if (hw_info->pjVirtualRomBase)
printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",
- XGIhw_ext.pjVirtualRomBase);
+ hw_info->pjVirtualRomBase);
else
printk(KERN_INFO "XGIfb: Video ROM not found\n");
} else {
- XGIhw_ext.pjVirtualRomBase = NULL;
+ hw_info->pjVirtualRomBase = NULL;
printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
}
- XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
- if (XGIfb_get_dram_size()) {
+ if (XGIfb_get_dram_size(xgifb_info)) {
printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
ret = -ENODEV;
goto error;
}
- if ((xgifb_mode_idx < 0) ||
- ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
- /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
- xgifb_reg_or(XGISR,
- IND_XGI_PCI_ADDRESS_SET,
- (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
- /* Enable 2D accelerator engine */
- xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
- }
+ /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
+ xgifb_reg_or(XGISR,
+ IND_XGI_PCI_ADDRESS_SET,
+ (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
+ /* Enable 2D accelerator engine */
+ xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
- XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
+ hw_info->ulVideoMemorySize = xgifb_info->video_size;
- if (!request_mem_region(xgi_video_info.video_base,
- xgi_video_info.video_size,
+ if (!request_mem_region(xgifb_info->video_base,
+ xgifb_info->video_size,
"XGIfb FB")) {
printk("unable request memory size %x",
- xgi_video_info.video_size);
+ xgifb_info->video_size);
printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
ret = -ENODEV;
goto error;
}
- if (!request_mem_region(xgi_video_info.mmio_base,
- xgi_video_info.mmio_size,
+ if (!request_mem_region(xgifb_info->mmio_base,
+ xgifb_info->mmio_size,
"XGIfb MMIO")) {
printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
ret = -ENODEV;
goto error_0;
}
- xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
- ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
- xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
- xgi_video_info.mmio_size);
+ xgifb_info->video_vbase = hw_info->pjVideoMemoryAddress =
+ ioremap(xgifb_info->video_base, xgifb_info->video_size);
+ xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
+ xgifb_info->mmio_size);
printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
- xgi_video_info.video_base,
- xgi_video_info.video_vbase,
- xgi_video_info.video_size / 1024);
+ xgifb_info->video_base,
+ xgifb_info->video_vbase,
+ xgifb_info->video_size / 1024);
printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
- xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
- xgi_video_info.mmio_size / 1024);
+ xgifb_info->mmio_base, xgifb_info->mmio_vbase,
+ xgifb_info->mmio_size / 1024);
printk("XGIfb: XGIInitNew() ...");
- if (XGIInitNew(&XGIhw_ext))
+ pci_set_drvdata(pdev, xgifb_info);
+ if (XGIInitNew(pdev))
printk("OK\n");
else
printk("Fail\n");
- xgi_video_info.mtrr = (unsigned int) 0;
-
- if ((xgifb_mode_idx < 0) ||
- ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
- xgi_video_info.hasVB = HASVB_NONE;
- if ((xgi_video_info.chip == XG20) ||
- (xgi_video_info.chip == XG27)) {
- xgi_video_info.hasVB = HASVB_NONE;
- } else if (xgi_video_info.chip == XG21) {
- CR38 = xgifb_reg_get(XGICR, 0x38);
- if ((CR38&0xE0) == 0xC0) {
- xgi_video_info.disp_state = DISPTYPE_LCD;
- if (!XGIfb_GetXG21LVDSData()) {
- int m;
- for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
- if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
- (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
- xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
- }
- }
- }
- } else if ((CR38&0xE0) == 0x60) {
- xgi_video_info.hasVB = HASVB_CHRONTEL;
- } else {
- xgi_video_info.hasVB = HASVB_NONE;
- }
+ xgifb_info->mtrr = (unsigned int) 0;
+
+ xgifb_info->hasVB = HASVB_NONE;
+ if ((xgifb_info->chip == XG20) ||
+ (xgifb_info->chip == XG27)) {
+ xgifb_info->hasVB = HASVB_NONE;
+ } else if (xgifb_info->chip == XG21) {
+ CR38 = xgifb_reg_get(XGICR, 0x38);
+ if ((CR38&0xE0) == 0xC0) {
+ xgifb_info->display2 = XGIFB_DISP_LCD;
+ if (!XGIfb_GetXG21LVDSData(xgifb_info))
+ xgi21_drvlcdcaplist = true;
+ } else if ((CR38&0xE0) == 0x60) {
+ xgifb_info->hasVB = HASVB_CHRONTEL;
} else {
- XGIfb_get_VB_type();
+ xgifb_info->hasVB = HASVB_NONE;
}
+ } else {
+ XGIfb_get_VB_type(xgifb_info);
+ }
- XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-
- XGIhw_ext.ulExternalChip = 0;
+ hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
- switch (xgi_video_info.hasVB) {
- case HASVB_301:
- reg = xgifb_reg_get(XGIPART4, 0x01);
- if (reg >= 0xE0) {
- XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
- printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
- } else if (reg >= 0xD0) {
- XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
- printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
- }
- /* else if (reg >= 0xB0) {
- XGIhw_ext.ujVBChipID = VB_CHIP_301B;
- reg1 = xgifb_reg_get(XGIPART4, 0x23);
- printk("XGIfb: XGI301B bridge detected\n");
- } */
- else {
- XGIhw_ext.ujVBChipID = VB_CHIP_301;
- printk("XGIfb: XGI301 bridge detected\n");
- }
- break;
- case HASVB_302:
- reg = xgifb_reg_get(XGIPART4, 0x01);
- if (reg >= 0xE0) {
- XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
- printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
- } else if (reg >= 0xD0) {
- XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
- printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
- } else if (reg >= 0xB0) {
- reg1 = xgifb_reg_get(XGIPART4, 0x23);
-
- XGIhw_ext.ujVBChipID = VB_CHIP_302B;
+ hw_info->ulExternalChip = 0;
- } else {
- XGIhw_ext.ujVBChipID = VB_CHIP_302;
- printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
- }
- break;
- case HASVB_LVDS:
- XGIhw_ext.ulExternalChip = 0x1;
- printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
- break;
- case HASVB_TRUMPION:
- XGIhw_ext.ulExternalChip = 0x2;
- printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
- break;
- case HASVB_CHRONTEL:
- XGIhw_ext.ulExternalChip = 0x4;
- printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
- break;
- case HASVB_LVDS_CHRONTEL:
- XGIhw_ext.ulExternalChip = 0x5;
- printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
- break;
- default:
- printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
- break;
+ switch (xgifb_info->hasVB) {
+ case HASVB_301:
+ reg = xgifb_reg_get(XGIPART4, 0x01);
+ if (reg >= 0xE0) {
+ hw_info->ujVBChipID = VB_CHIP_302LV;
+ printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
+ } else if (reg >= 0xD0) {
+ hw_info->ujVBChipID = VB_CHIP_301LV;
+ printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
}
-
- if (xgi_video_info.hasVB != HASVB_NONE)
- XGIfb_detect_VB();
-
- if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
- if (XGIfb_crt1off)
- xgi_video_info.disp_state |= DISPMODE_SINGLE;
- else
- xgi_video_info.disp_state |= (DISPMODE_MIRROR |
- DISPTYPE_CRT1);
- } else {
- xgi_video_info.disp_state = DISPMODE_SINGLE |
- DISPTYPE_CRT1;
+ /* else if (reg >= 0xB0) {
+ hw_info->ujVBChipID = VB_CHIP_301B;
+ reg1 = xgifb_reg_get(XGIPART4, 0x23);
+ printk("XGIfb: XGI301B bridge detected\n");
+ } */
+ else {
+ hw_info->ujVBChipID = VB_CHIP_301;
+ printk("XGIfb: XGI301 bridge detected\n");
}
+ break;
+ case HASVB_302:
+ reg = xgifb_reg_get(XGIPART4, 0x01);
+ if (reg >= 0xE0) {
+ hw_info->ujVBChipID = VB_CHIP_302LV;
+ printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
+ } else if (reg >= 0xD0) {
+ hw_info->ujVBChipID = VB_CHIP_301LV;
+ printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
+ } else if (reg >= 0xB0) {
+ reg1 = xgifb_reg_get(XGIPART4, 0x23);
- if (xgi_video_info.disp_state & DISPTYPE_LCD) {
- if (!enable_dstn) {
- reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
- reg &= 0x0f;
- XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
+ hw_info->ujVBChipID = VB_CHIP_302B;
- } else {
- /* TW: FSTN/DSTN */
- XGIhw_ext.ulCRT2LCDType = LCD_320x480;
- }
+ } else {
+ hw_info->ujVBChipID = VB_CHIP_302;
+ printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
}
+ break;
+ case HASVB_LVDS:
+ hw_info->ulExternalChip = 0x1;
+ printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
+ break;
+ case HASVB_TRUMPION:
+ hw_info->ulExternalChip = 0x2;
+ printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
+ break;
+ case HASVB_CHRONTEL:
+ hw_info->ulExternalChip = 0x4;
+ printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
+ break;
+ case HASVB_LVDS_CHRONTEL:
+ hw_info->ulExternalChip = 0x5;
+ printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
+ break;
+ default:
+ printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
+ break;
+ }
- XGIfb_detectedpdc = 0;
+ if (xgifb_info->hasVB != HASVB_NONE)
+ XGIfb_detect_VB(xgifb_info);
- XGIfb_detectedlcda = 0xff;
+ if (xgifb_info->display2 == XGIFB_DISP_LCD) {
+ if (!enable_dstn) {
+ reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
+ reg &= 0x0f;
+ hw_info->ulCRT2LCDType = XGI310paneltype[reg];
- /* TW: Try to find about LCDA */
+ } else {
+ /* TW: FSTN/DSTN */
+ hw_info->ulCRT2LCDType = LCD_320x480;
+ }
+ }
- if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
- (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
- (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
- int tmp;
- tmp = xgifb_reg_get(XGICR, 0x34);
- if (tmp <= 0x13) {
+ if ((hw_info->ujVBChipID == VB_CHIP_302B) ||
+ (hw_info->ujVBChipID == VB_CHIP_301LV) ||
+ (hw_info->ujVBChipID == VB_CHIP_302LV)) {
+ int tmp;
+ tmp = xgifb_reg_get(XGICR, 0x34);
+ if (tmp <= 0x13) {
+ /* Currently on LCDA?
+ *(Some BIOSes leave CR38) */
+ tmp = xgifb_reg_get(XGICR, 0x38);
+ if ((tmp & 0x03) == 0x03) {
+ /* XGI_Pr.XGI_UseLCDA = 1; */
+ } else {
/* Currently on LCDA?
- *(Some BIOSes leave CR38) */
- tmp = xgifb_reg_get(XGICR, 0x38);
- if ((tmp & 0x03) == 0x03) {
+ *(Some newer BIOSes set D0 in CR35) */
+ tmp = xgifb_reg_get(XGICR, 0x35);
+ if (tmp & 0x01) {
/* XGI_Pr.XGI_UseLCDA = 1; */
} else {
- /* Currently on LCDA?
- *(Some newer BIOSes set D0 in CR35) */
- tmp = xgifb_reg_get(XGICR, 0x35);
- if (tmp & 0x01) {
- /* XGI_Pr.XGI_UseLCDA = 1; */
- } else {
- tmp = xgifb_reg_get(XGICR,
- 0x30);
- if (tmp & 0x20) {
- tmp = xgifb_reg_get(
- XGIPART1, 0x13);
- if (tmp & 0x04) {
- /* XGI_Pr.XGI_UseLCDA = 1; */
- }
+ tmp = xgifb_reg_get(XGICR,
+ 0x30);
+ if (tmp & 0x20) {
+ tmp = xgifb_reg_get(
+ XGIPART1, 0x13);
+ if (tmp & 0x04) {
+ /* XGI_Pr.XGI_UseLCDA = 1; */
}
}
}
}
-
}
- if (xgifb_mode_idx >= 0)
- xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+ }
+
+ xgifb_info->mode_idx = -1;
- if (xgifb_mode_idx < 0) {
- switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
- case DISPTYPE_LCD:
- xgifb_mode_idx = DEFAULT_LCDMODE;
- if (xgi_video_info.chip == XG21)
- xgifb_mode_idx =
- XGIfb_GetXG21DefaultLVDSModeIdx();
- break;
- case DISPTYPE_TV:
- xgifb_mode_idx = DEFAULT_TVMODE;
- break;
- default:
- xgifb_mode_idx = DEFAULT_MODE;
+ if (mode)
+ XGIfb_search_mode(xgifb_info, mode);
+ else if (vesa != -1)
+ XGIfb_search_vesamode(xgifb_info, vesa);
+
+ if (xgifb_info->mode_idx >= 0)
+ xgifb_info->mode_idx =
+ XGIfb_validate_mode(xgifb_info, xgifb_info->mode_idx);
+
+ if (xgifb_info->mode_idx < 0) {
+ if (xgifb_info->display2 == XGIFB_DISP_LCD &&
+ xgifb_info->chip == XG21)
+ xgifb_info->mode_idx =
+ XGIfb_GetXG21DefaultLVDSModeIdx();
+ else
+ xgifb_info->mode_idx = DEFAULT_MODE;
+ }
+
+ if (xgifb_info->mode_idx < 0) {
+ dev_err(&pdev->dev, "no supported video mode found\n");
+ goto error_1;
+ }
+
+ if (xgi21_drvlcdcaplist) {
+ int m;
+
+ for (m = 0; m < ARRAY_SIZE(XGI21_LCDCapList); m++)
+ if ((XGI21_LCDCapList[m].LVDSHDE ==
+ XGIbios_mode[xgifb_info->mode_idx].xres) &&
+ (XGI21_LCDCapList[m].LVDSVDE ==
+ XGIbios_mode[xgifb_info->mode_idx].yres)) {
+ xgifb_reg_set(xgifb_info->dev_info.P3d4,
+ 0x36,
+ m);
break;
}
- }
+ }
- XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
+ /* yilin set default refresh rate */
+ xgifb_info->refresh_rate = refresh_rate;
+ if (xgifb_info->refresh_rate == 0)
+ xgifb_info->refresh_rate = 60;
+ if (XGIfb_search_refresh_rate(xgifb_info,
+ xgifb_info->refresh_rate) == 0) {
+ xgifb_info->rate_idx =
+ XGIbios_mode[xgifb_info->mode_idx].rate_idx;
+ xgifb_info->refresh_rate = 60;
+ }
- /* yilin set default refresh rate */
- if (xgi_video_info.refresh_rate == 0)
- xgi_video_info.refresh_rate = 60;
- if (XGIfb_search_refresh_rate(
- xgi_video_info.refresh_rate) == 0) {
- XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
- xgi_video_info.refresh_rate = 60;
- }
+ xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
+ xgifb_info->video_vwidth =
+ xgifb_info->video_width =
+ XGIbios_mode[xgifb_info->mode_idx].xres;
+ xgifb_info->video_vheight =
+ xgifb_info->video_height =
+ XGIbios_mode[xgifb_info->mode_idx].yres;
+ xgifb_info->org_x = xgifb_info->org_y = 0;
+ xgifb_info->video_linelength =
+ xgifb_info->video_width *
+ (xgifb_info->video_bpp >> 3);
+ switch (xgifb_info->video_bpp) {
+ case 8:
+ xgifb_info->DstColor = 0x0000;
+ xgifb_info->XGI310_AccelDepth = 0x00000000;
+ xgifb_info->video_cmap_len = 256;
+ break;
+ case 16:
+ xgifb_info->DstColor = 0x8000;
+ xgifb_info->XGI310_AccelDepth = 0x00010000;
+ xgifb_info->video_cmap_len = 16;
+ break;
+ case 32:
+ xgifb_info->DstColor = 0xC000;
+ xgifb_info->XGI310_AccelDepth = 0x00020000;
+ xgifb_info->video_cmap_len = 16;
+ break;
+ default:
+ xgifb_info->video_cmap_len = 16;
+ printk(KERN_INFO "XGIfb: Unsupported depth %d",
+ xgifb_info->video_bpp);
+ break;
+ }
- xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
- xgi_video_info.video_vwidth =
- xgi_video_info.video_width =
- XGIbios_mode[xgifb_mode_idx].xres;
- xgi_video_info.video_vheight =
- xgi_video_info.video_height =
- XGIbios_mode[xgifb_mode_idx].yres;
- xgi_video_info.org_x = xgi_video_info.org_y = 0;
- xgi_video_info.video_linelength =
- xgi_video_info.video_width *
- (xgi_video_info.video_bpp >> 3);
- switch (xgi_video_info.video_bpp) {
- case 8:
- xgi_video_info.DstColor = 0x0000;
- xgi_video_info.XGI310_AccelDepth = 0x00000000;
- xgi_video_info.video_cmap_len = 256;
- break;
- case 16:
- xgi_video_info.DstColor = 0x8000;
- xgi_video_info.XGI310_AccelDepth = 0x00010000;
- xgi_video_info.video_cmap_len = 16;
- break;
- case 32:
- xgi_video_info.DstColor = 0xC000;
- xgi_video_info.XGI310_AccelDepth = 0x00020000;
- xgi_video_info.video_cmap_len = 16;
- break;
- default:
- xgi_video_info.video_cmap_len = 16;
- printk(KERN_INFO "XGIfb: Unsupported depth %d",
- xgi_video_info.video_bpp);
- break;
+ printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
+ xgifb_info->video_width,
+ xgifb_info->video_height,
+ xgifb_info->video_bpp,
+ xgifb_info->refresh_rate);
+
+ fb_info->var.red.length = 8;
+ fb_info->var.green.length = 8;
+ fb_info->var.blue.length = 8;
+ fb_info->var.activate = FB_ACTIVATE_NOW;
+ fb_info->var.height = -1;
+ fb_info->var.width = -1;
+ fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+ fb_info->var.xres = xgifb_info->video_width;
+ fb_info->var.xres_virtual = xgifb_info->video_width;
+ fb_info->var.yres = xgifb_info->video_height;
+ fb_info->var.yres_virtual = xgifb_info->video_height;
+ fb_info->var.bits_per_pixel = xgifb_info->video_bpp;
+
+ XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
+
+ fb_info->var.pixclock = (u32) (1000000000 /
+ XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info,
+ hw_info,
+ XGIbios_mode[xgifb_info->mode_idx].mode_no,
+ xgifb_info->rate_idx));
+
+ if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info,
+ XGIbios_mode[xgifb_info->mode_idx].mode_no,
+ xgifb_info->rate_idx,
+ &fb_info->var.left_margin,
+ &fb_info->var.right_margin,
+ &fb_info->var.upper_margin,
+ &fb_info->var.lower_margin,
+ &fb_info->var.hsync_len,
+ &fb_info->var.vsync_len,
+ &fb_info->var.sync,
+ &fb_info->var.vmode)) {
+
+ if ((fb_info->var.vmode & FB_VMODE_MASK) ==
+ FB_VMODE_INTERLACED) {
+ fb_info->var.yres <<= 1;
+ fb_info->var.yres_virtual <<= 1;
+ } else if ((fb_info->var.vmode & FB_VMODE_MASK) ==
+ FB_VMODE_DOUBLE) {
+ fb_info->var.pixclock >>= 1;
+ fb_info->var.yres >>= 1;
+ fb_info->var.yres_virtual >>= 1;
}
- printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
- xgi_video_info.video_width,
- xgi_video_info.video_height,
- xgi_video_info.video_bpp,
- xgi_video_info.refresh_rate);
-
- default_var.xres =
- default_var.xres_virtual =
- xgi_video_info.video_width;
- default_var.yres =
- default_var.yres_virtual =
- xgi_video_info.video_height;
- default_var.bits_per_pixel = xgi_video_info.video_bpp;
-
- XGIfb_bpp_to_var(&default_var);
-
- default_var.pixclock = (u32) (1000000000 /
- XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
- XGIfb_mode_no, XGIfb_rate_idx));
-
- if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
- XGIfb_mode_no, XGIfb_rate_idx,
- &default_var.left_margin, &default_var.right_margin,
- &default_var.upper_margin, &default_var.lower_margin,
- &default_var.hsync_len, &default_var.vsync_len,
- &default_var.sync, &default_var.vmode)) {
-
- if ((default_var.vmode & FB_VMODE_MASK) ==
- FB_VMODE_INTERLACED) {
- default_var.yres <<= 1;
- default_var.yres_virtual <<= 1;
- } else if ((default_var.vmode & FB_VMODE_MASK) ==
- FB_VMODE_DOUBLE) {
- default_var.pixclock >>= 1;
- default_var.yres >>= 1;
- default_var.yres_virtual >>= 1;
- }
+ }
- }
+ strncpy(fb_info->fix.id, "XGI", sizeof(fb_info->fix.id) - 1);
+ fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+ fb_info->fix.xpanstep = 1;
+ fb_info->fix.ypanstep = 1;
- fb_info->flags = FBINFO_FLAG_DEFAULT;
- fb_info->var = default_var;
- fb_info->fix = XGIfb_fix;
- fb_info->par = &xgi_video_info;
- fb_info->screen_base = xgi_video_info.video_vbase;
- fb_info->fbops = &XGIfb_ops;
- XGIfb_get_fix(&fb_info->fix, -1, fb_info);
- fb_info->pseudo_palette = pseudo_palette;
+ fb_info->flags = FBINFO_FLAG_DEFAULT;
+ fb_info->screen_base = xgifb_info->video_vbase;
+ fb_info->fbops = &XGIfb_ops;
+ XGIfb_get_fix(&fb_info->fix, -1, fb_info);
+ fb_info->pseudo_palette = xgifb_info->pseudo_palette;
- fb_alloc_cmap(&fb_info->cmap, 256 , 0);
+ fb_alloc_cmap(&fb_info->cmap, 256 , 0);
#ifdef CONFIG_MTRR
- xgi_video_info.mtrr = mtrr_add(
- (unsigned int) xgi_video_info.video_base,
- (unsigned int) xgi_video_info.video_size,
- MTRR_TYPE_WRCOMB, 1);
- if (xgi_video_info.mtrr)
- printk(KERN_INFO "XGIfb: Added MTRRs\n");
+ xgifb_info->mtrr = mtrr_add(xgifb_info->video_base,
+ xgifb_info->video_size, MTRR_TYPE_WRCOMB, 1);
+ if (xgifb_info->mtrr >= 0)
+ dev_info(&pdev->dev, "added MTRR\n");
#endif
- if (register_framebuffer(fb_info) < 0) {
- ret = -EINVAL;
- goto error_1;
- }
-
- XGIfb_registered = 1;
-
- printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
- fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
-
+ if (register_framebuffer(fb_info) < 0) {
+ ret = -EINVAL;
+ goto error_mtrr;
}
dumpVGAReg();
return 0;
+error_mtrr:
+#ifdef CONFIG_MTRR
+ if (xgifb_info->mtrr >= 0)
+ mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
+ xgifb_info->video_size);
+#endif /* CONFIG_MTRR */
error_1:
- iounmap(xgi_video_info.mmio_vbase);
- iounmap(xgi_video_info.video_vbase);
- release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
+ iounmap(xgifb_info->mmio_vbase);
+ iounmap(xgifb_info->video_vbase);
+ release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
error_0:
- release_mem_region(xgi_video_info.video_base,
- xgi_video_info.video_size);
+ release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
error:
- vfree(XGIhw_ext.pjVirtualRomBase);
+ vfree(hw_info->pjVirtualRomBase);
framebuffer_release(fb_info);
return ret;
}
@@ -2526,13 +2429,20 @@ error:
static void __devexit xgifb_remove(struct pci_dev *pdev)
{
+ struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
+ struct fb_info *fb_info = xgifb_info->fb_info;
+
unregister_framebuffer(fb_info);
- iounmap(xgi_video_info.mmio_vbase);
- iounmap(xgi_video_info.video_vbase);
- release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
- release_mem_region(xgi_video_info.video_base,
- xgi_video_info.video_size);
- vfree(XGIhw_ext.pjVirtualRomBase);
+#ifdef CONFIG_MTRR
+ if (xgifb_info->mtrr >= 0)
+ mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
+ xgifb_info->video_size);
+#endif /* CONFIG_MTRR */
+ iounmap(xgifb_info->mmio_vbase);
+ iounmap(xgifb_info->video_vbase);
+ release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
+ release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
+ vfree(xgifb_info->hw_info.pjVirtualRomBase);
framebuffer_release(fb_info);
pci_set_drvdata(pdev, NULL);
}
@@ -2544,7 +2454,7 @@ static struct pci_driver xgifb_driver = {
.remove = __devexit_p(xgifb_remove)
};
-XGIINITSTATIC int __init xgifb_init(void)
+static int __init xgifb_init(void)
{
char *option = NULL;
@@ -2555,9 +2465,7 @@ XGIINITSTATIC int __init xgifb_init(void)
return pci_register_driver(&xgifb_driver);
}
-#ifndef MODULE
module_init(xgifb_init);
-#endif
/*****************************************************/
/* MODULE */
@@ -2565,154 +2473,32 @@ module_init(xgifb_init);
#ifdef MODULE
-static char *mode = NULL;
-static int vesa = 0;
-static unsigned int rate = 0;
-static unsigned int mem = 0;
-static char *forcecrt2type = NULL;
-static int forcecrt1 = -1;
-static int pdc = -1;
-static int pdc1 = -1;
-static int noypan = -1;
-static int userom = -1;
-static int useoem = -1;
-static char *tvstandard = NULL;
-static int nocrt2rate = 0;
-static int scalelcd = -1;
-static char *specialtiming = NULL;
-static int lvdshl = -1;
-static int tvxposoffset = 0, tvyposoffset = 0;
-#if !defined(__i386__) && !defined(__x86_64__)
-static int resetcard = 0;
-static int videoram = 0;
-#endif
-
MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XGITECH , Others");
-module_param(mem, int, 0);
-module_param(noypan, int, 0);
-module_param(userom, int, 0);
-module_param(useoem, int, 0);
module_param(mode, charp, 0);
module_param(vesa, int, 0);
-module_param(rate, int, 0);
-module_param(forcecrt1, int, 0);
-module_param(forcecrt2type, charp, 0);
-module_param(scalelcd, int, 0);
-module_param(pdc, int, 0);
-module_param(pdc1, int, 0);
-module_param(specialtiming, charp, 0);
-module_param(lvdshl, int, 0);
-module_param(tvstandard, charp, 0);
-module_param(tvxposoffset, int, 0);
-module_param(tvyposoffset, int, 0);
module_param(filter, int, 0);
-module_param(nocrt2rate, int, 0);
-#if !defined(__i386__) && !defined(__x86_64__)
-module_param(resetcard, int, 0);
-module_param(videoram, int, 0);
-#endif
-
-MODULE_PARM_DESC(noypan,
- "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- "will be performed by redrawing the screen. (default: 0)\n");
MODULE_PARM_DESC(mode,
- "\nSelects the desired default display mode in the format XxYxDepth,\n"
- "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
- "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
- "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+ "\nSelects the desired default display mode in the format XxYxDepth,\n"
+ "eg. 1024x768x16.\n");
MODULE_PARM_DESC(vesa,
- "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
- "0x117 (default: 0x0103)\n");
-
-MODULE_PARM_DESC(rate,
- "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
- "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
- "will be ignored (default: 60)\n");
-
-MODULE_PARM_DESC(forcecrt1,
- "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
- "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
- "0=CRT1 OFF) (default: [autodetected])\n");
-
-MODULE_PARM_DESC(forcecrt2type,
- "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
- "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
- "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
- "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
- "be used instead of TV to override the TV detection. Furthermore, on systems\n"
- "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
- "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
- "depends on the very hardware in use. (default: [autodetected])\n");
-
-MODULE_PARM_DESC(scalelcd,
- "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
- "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
- "show black bars around the image, TMDS panels will probably do the scaling\n"
- "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
-
-MODULE_PARM_DESC(pdc,
- "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
- "should detect this correctly in most cases; however, sometimes this is not\n"
- "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
- "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
- "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
- "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
-
-MODULE_PARM_DESC(pdc1,
- "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
- "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
- "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
- "implemented yet.\n");
-
-MODULE_PARM_DESC(specialtiming,
- "\nPlease refer to documentation for more information on this option.\n");
-
-MODULE_PARM_DESC(lvdshl,
- "\nPlease refer to documentation for more information on this option.\n");
-
-MODULE_PARM_DESC(tvstandard,
- "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
- "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
-
-MODULE_PARM_DESC(tvxposoffset,
- "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
- "Default: 0\n");
-
-MODULE_PARM_DESC(tvyposoffset,
- "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
- "Default: 0\n");
+ "\nSelects the desired default display mode by VESA mode number, eg.\n"
+ "0x117.\n");
MODULE_PARM_DESC(filter,
"\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
"(Possible values 0-7, default: [no filter])\n");
-MODULE_PARM_DESC(nocrt2rate,
- "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
- "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
-
-static int __init xgifb_init_module(void)
-{
- printk("\nXGIfb_init_module");
- if (mode)
- XGIfb_search_mode(mode);
- else if (vesa != -1)
- XGIfb_search_vesamode(vesa);
-
- return xgifb_init();
-}
-
static void __exit xgifb_remove_module(void)
{
pci_unregister_driver(&xgifb_driver);
printk(KERN_DEBUG "xgifb: Module unloaded\n");
}
-module_init(xgifb_init_module);
module_exit(xgifb_remove_module);
#endif /* /MODULE */
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
index 45b6015..7611846 100644
--- a/drivers/staging/xgifb/XGIfb.h
+++ b/drivers/staging/xgifb/XGIfb.h
@@ -3,15 +3,15 @@
#include <linux/ioctl.h>
#include <linux/types.h>
-#define DISPTYPE_CRT1 0x00000008L
-#define DISPTYPE_CRT2 0x00000004L
-#define DISPTYPE_LCD 0x00000002L
-#define DISPTYPE_TV 0x00000001L
-#define DISPTYPE_DISP1 DISPTYPE_CRT1
-#define DISPTYPE_DISP2 (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
-#define DISPMODE_SINGLE 0x00000020L
-#define DISPMODE_MIRROR 0x00000010L
-#define DISPMODE_DUALVIEW 0x00000040L
+#include "vb_struct.h"
+#include "vgatypes.h"
+
+enum xgifb_display_type {
+ XGIFB_DISP_NONE = 0,
+ XGIFB_DISP_CRT,
+ XGIFB_DISP_LCD,
+ XGIFB_DISP_TV,
+};
#define HASVB_NONE 0x00
#define HASVB_301 0x01
@@ -19,13 +19,8 @@
#define HASVB_TRUMPION 0x04
#define HASVB_LVDS_CHRONTEL 0x10
#define HASVB_302 0x20
-#define HASVB_303 0x40
#define HASVB_CHRONTEL 0x80
-#ifndef XGIFB_ID
-#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */
-#endif
-
enum XGI_CHIP_TYPE {
XG40 = 32,
XG41,
@@ -47,11 +42,6 @@ enum xgi_tvtype {
};
enum xgi_tv_plug { /* vicki@030226 */
-/* TVPLUG_Legacy = 0, */
-/* TVPLUG_COMPOSITE, */
-/* TVPLUG_SVIDEO, */
-/* TVPLUG_SCART, */
-/* TVPLUG_TOTAL */
TVPLUG_UNKNOWN = 0,
TVPLUG_COMPOSITE = 1,
TVPLUG_SVIDEO = 2,
@@ -64,14 +54,23 @@ enum xgi_tv_plug { /* vicki@030226 */
TVPLUG_TOTAL
};
-struct video_info {
+struct xgifb_video_info {
+ struct fb_info *fb_info;
+ struct xgi_hw_device_info hw_info;
+ struct vb_device_info dev_info;
+
+ int mode_idx;
+ int rate_idx;
+
+ u32 pseudo_palette[17];
+
int chip_id;
unsigned int video_size;
unsigned long video_base;
- char *video_vbase;
+ void __iomem *video_vbase;
unsigned long mmio_base;
unsigned long mmio_size;
- char *mmio_vbase;
+ void __iomem *mmio_vbase;
unsigned long vga_base;
unsigned long mtrr;
@@ -86,7 +85,7 @@ struct video_info {
int video_linelength;
unsigned int refresh_rate;
- unsigned long disp_state;
+ enum xgifb_display_type display2; /* the second display output type */
unsigned char hasVB;
unsigned char TV_type;
unsigned char TV_plug;
@@ -108,7 +107,4 @@ struct video_info {
char reserved[236];
};
-
-extern struct video_info xgi_video_info;
-
#endif
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
index 339c071..5beeef9 100644
--- a/drivers/staging/xgifb/vb_def.h
+++ b/drivers/staging/xgifb/vb_def.h
@@ -3,261 +3,48 @@
#ifndef _INITDEF_
#define _INITDEF_
-#ifndef NewScratch
-#define NewScratch
-#endif
-/* shampoo */
-
-#define SEQ_ADDRESS_PORT 0x0014
-#define SEQ_DATA_PORT 0x0015
-#define MISC_OUTPUT_REG_READ_PORT 0x001C
-#define MISC_OUTPUT_REG_WRITE_PORT 0x0012
-#define GRAPH_DATA_PORT 0x1F
-#define GRAPH_ADDRESS_PORT 0x1E
-#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */
-#define CRTC_ADDRESS_PORT_COLOR 0x0024
-#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013
-#define PCI_COMMAND 0x04
-
-/* ~shampoo */
-
-
-#define VB_XGI301 0x0001 /*301b*/
-#define VB_XGI301B 0x0002
-#define VB_XGI302B 0x0004
-#define VB_XGI301LV 0x0008 /*301lv*/
-#define VB_XGI302LV 0x0010
#define VB_XGI301C 0x0020 /* for 301C */
-#define VB_NoLCD 0x8000
/*end 301b*/
-#define VB_YPbPrInfo 0x07 /*301lv*/
-#define VB_YPbPr525i 0x00
#define VB_YPbPr525p 0x01
#define VB_YPbPr750p 0x02
#define VB_YPbPr1080i 0x03
-/* #define CRT1Len 17 */
#define LVDSCRT1Len 15
-#define CHTVRegDataLen 5
-
-/* #define ModeInfoFlag 0x07 */
-/* #define IsTextMode 0x07 */
-/* #define ModeText 0x00 */
-/* #define ModeCGA 0x01 */
-/* #define ModeEGA 0x02 */
-/* #define ModeVGA 0x03 */
-/* #define Mode15Bpp 0x04 */
-/* #define Mode16Bpp 0x05 */
-/* #define Mode24Bpp 0x06 */
-/* #define Mode32Bpp 0x07 */
-
-/* #define DACInfoFlag 0x18 */
-/* #define MemoryInfoFlag 0x1E0 */
-/* #define MemorySizeShift 0x05 */
-
-#define Charx8Dot 0x0200
-#define LineCompareOff 0x0400
-#define CRT2Mode 0x0800
-#define HalfDCLK 0x1000
-#define NoSupportSimuTV 0x2000
-#define DoubleScanMode 0x8000
-
-#define SupportAllCRT2 0x0078
-#define SupportTV 0x0008
-#define SupportHiVisionTV 0x0010
-#define SupportLCD 0x0020
-#define SupportRAMDAC2 0x0040
-#define NoSupportTV 0x0070
-#define NoSupportHiVisionTV 0x0060
-#define NoSupportLCD 0x0058
+
#define SupportCHTV 0x0800
#define SupportCRT2in301C 0x0100 /* for 301C */
-#define SupportTV1024 0x0800 /*301b*/
-#define SupportYPbPr 0x1000 /*301lv*/
-#define InterlaceMode 0x0080
-#define SyncPP 0x0000
-#define SyncPN 0x4000
-#define SyncNP 0x8000
-/* #define SyncNN 0xc000 */
-#define ECLKindex0 0x0000
-#define ECLKindex1 0x0100
-#define ECLKindex2 0x0200
-#define ECLKindex3 0x0300
-#define ECLKindex4 0x0400
-
-#define SetSimuScanMode 0x0001
-#define SwitchToCRT2 0x0002
-/* #define SetCRT2ToTV 0x009C */
-#define SetCRT2ToAVIDEO 0x0004
-#define SetCRT2ToSVIDEO 0x0008
-#define SetCRT2ToSCART 0x0010
-#define SetCRT2ToLCD 0x0020
-#define SetCRT2ToRAMDAC 0x0040
-#define SetCRT2ToHiVisionTV 0x0080
-#define SetNTSCTV 0x0000
-/* #define SetPALTV 0x0100 */
-#define SetInSlaveMode 0x0200
-#define SetNotSimuMode 0x0400
-#define SetNotSimuTVMode 0x0400
-#define SetDispDevSwitch 0x0800
-#define LoadDACFlag 0x1000
-#define DisableCRT2Display 0x2000
-#define DriverMode 0x4000
-#define HotKeySwitch 0x8000
#define SetCHTVOverScan 0x8000
-/* #define SetCRT2ToLCDA 0x8000 301b */
#define PanelRGB18Bit 0x0100
#define PanelRGB24Bit 0x0000
-#define TVOverScan 0x10
-#define TVOverScanShift 4
-#define ClearBufferFlag 0x20
-#define EnableDualEdge 0x01 /*301b*/
-#define SetToLCDA 0x02
-
-#define YPbPrModeInfo 0x38
-/* #define YPbPrMode525i 0x00 */
-/* #define YPbPrMode525p 0x08 */
-/* #define YPbPrMode750p 0x10 */
-/* #define YPbPrMode1080i 0x18 */
-
-#define SetSCARTOutput 0x01
-#define BoardTVType 0x02
-#define EnablePALMN 0x40
-/* #define ProgrammingCRT2 0x01 */
-/* #define TVSimuMode 0x02 */
-/* #define RPLLDIV2XO 0x04 */
-/* #define LCDVESATiming 0x08 */
-/* #define EnableLVDSDDA 0x10 */
-#define SetDispDevSwitchFlag 0x20
-#define CheckWinDos 0x40
-#define SetJDOSMode 0x80
-
#define Panel320x480 0x07 /*fstn*/
/* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */
#define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */
-#define PanelRefInfo 0x60
#define Panel800x600 0x01
#define Panel1024x768 0x02
#define Panel1024x768x75 0x22
#define Panel1280x1024 0x03
#define Panel1280x1024x75 0x23
#define Panel640x480 0x04
-#define Panel1024x600 0x05
-#define Panel1152x864 0x06
#define Panel1280x960 0x07
-#define Panel1152x768 0x08
#define Panel1400x1050 0x09
-#define Panel1280x768 0x0A
#define Panel1600x1200 0x0B
#define PanelRef60Hz 0x00
#define PanelRef75Hz 0x20
-#define LCDRGB18Bit 0x01
-
-#define ExtChipTrumpion 0x06
-#define ExtChipCH7005 0x08
-#define ExtChipMitacTV 0x0a
-#define LCDNonExpanding 0x10
-#define LCDNonExpandingShift 4
-#define LCDSync 0x20
-#define LCDSyncBit 0xe0
-#define LCDSyncShift 6
-
-/* #define DDC2DelayTime 300 */
#define CRT2DisplayFlag 0x2000
-/* #define LCDDataLen 8 */
-/* #define HiTVDataLen 12 */
-/* #define TVDataLen 16 */
-/* #define SetPALTV 0x0100 */
-#define HalfDCLK 0x1000
-#define NTSCHT 1716
-#define NTSCVT 525
-#define PALHT 1728
-#define PALVT 625
-#define StHiTVHT 892
-#define StHiTVVT 1126
-#define StHiTextTVHT 1000
-#define StHiTextTVVT 1126
-#define ExtHiTVHT 2100
-#define ExtHiTVVT 1125
-
-#define St750pTVHT 1716
-#define St750pTVVT 525
-#define Ext750pTVHT 1716
-#define Ext750pTVVT 525
-#define St525pTVHT 1716
-#define St525pTVVT 525
-#define Ext525pTVHT 1716
-#define Ext525pTVVT 525
-#define St525iTVHT 1716
-#define St525iTVVT 525
-#define Ext525iTVHT 1716
-#define Ext525iTVVT 525
-
-#define VCLKStartFreq 25
-#define SoftDramType 0x80
-#define VCLK40 0x04
-
-#define VCLK162 0x21
-
-#define LCDRGB18Bit 0x01
-#define LoadDACFlag 0x1000
-#define AfterLockCRT2 0x4000
-#define SetCRT2ToAVIDEO 0x0004
-#define SetCRT2ToSCART 0x0010
-#define Ext2StructSize 5
-
#define YPbPr525iVCLK 0x03B
#define YPbPr525iVCLK_2 0x03A
-#define SwitchToCRT2 0x0002
-/* #define LCDVESATiming 0x08 */
-#define SetSCARTOutput 0x01
-#define AVIDEOSense 0x01
-#define SVIDEOSense 0x02
-#define SCARTSense 0x04
-#define LCDSense 0x08
-#define Monitor1Sense 0x20
-#define Monitor2Sense 0x10
-#define HiTVSense 0x40
-#define BoardTVType 0x02
-#define HotPlugFunction 0x08
-#define StStructSize 0x06
-
-
#define XGI_CRT2_PORT_00 (0x00 - 0x030)
#define XGI_CRT2_PORT_04 (0x04 - 0x030)
#define XGI_CRT2_PORT_10 (0x10 - 0x30)
#define XGI_CRT2_PORT_12 (0x12 - 0x30)
#define XGI_CRT2_PORT_14 (0x14 - 0x30)
-
-#define LCDNonExpanding 0x10
-#define ADR_CRT2PtrData 0x20E
-#define offset_Zurac 0x210
-#define ADR_LVDSDesPtrData 0x212
-#define ADR_LVDSCRT1DataPtr 0x214
-#define ADR_CHTVVCLKPtr 0x216
-#define ADR_CHTVRegDataPtr 0x218
-
-#define LVDSDataLen 6
-/* #define EnableLVDSDDA 0x10 */
-/* #define LVDSDesDataLen 3 */
-#define ActiveNonExpanding 0x40
-#define ActiveNonExpandingShift 6
-/* #define ActivePAL 0x20 */
-#define ActivePALShift 5
-/* #define ModeSwitchStatus 0x0F */
-#define SoftTVType 0x40
-#define SoftSettingAddr 0x52
-#define ModeSettingAddr 0x53
-
-/* #define SelectCRT1Rate 0x4 */
-
#define _PanelType00 0x00
#define _PanelType01 0x08
#define _PanelType02 0x10
@@ -275,173 +62,26 @@
#define _PanelType0E 0x70
#define _PanelType0F 0x78
-/* 1: XGI is primary vga 0:XGI is secondary vga */
-#define PRIMARY_VGA 0
-#define BIOSIDCodeAddr 0x235
-#define OEMUtilIDCodeAddr 0x237
-#define VBModeIDTableAddr 0x239
-#define OEMTVPtrAddr 0x241
-#define PhaseTableAddr 0x243
-#define NTSCFilterTableAddr 0x245
-#define PALFilterTableAddr 0x247
-#define OEMLCDPtr_1Addr 0x249
-#define OEMLCDPtr_2Addr 0x24B
-#define LCDHPosTable_1Addr 0x24D
-#define LCDHPosTable_2Addr 0x24F
-#define LCDVPosTable_1Addr 0x251
-#define LCDVPosTable_2Addr 0x253
-#define OEMLCDPIDTableAddr 0x255
-
-#define VBModeStructSize 5
-#define PhaseTableSize 4
-#define FilterTableSize 4
-#define LCDHPosTableSize 7
-#define LCDVPosTableSize 5
-#define OEMLVDSPIDTableSize 4
-#define LVDSHPosTableSize 4
-#define LVDSVPosTableSize 6
-
-#define VB_ModeID 0
-#define VB_TVTableIndex 1
-#define VB_LCDTableIndex 2
-#define VB_LCDHIndex 3
-#define VB_LCDVIndex 4
-
-#define OEMLCDEnable 0x0001
-#define OEMLCDDelayEnable 0x0002
-#define OEMLCDPOSEnable 0x0004
-#define OEMTVEnable 0x0100
-#define OEMTVDelayEnable 0x0200
-#define OEMTVFlickerEnable 0x0400
-#define OEMTVPhaseEnable 0x0800
-#define OEMTVFilterEnable 0x1000
-
-#define OEMLCDPanelIDSupport 0x0080
-
-/* #define LCDVESATiming 0x0001 //LCD Info CR37 */
-/* #define EnableLVDSDDA 0x0002 */
-#define EnableScalingLCD 0x0008
-#define SetPWDEnable 0x0004
-#define SetLCDtoNonExpanding 0x0010
-/* #define SetLCDPolarity 0x00E0 */
-#define SetLCDDualLink 0x0100
-#define SetLCDLowResolution 0x0200
-#define SetLCDStdMode 0x0400
-#define SetTVStdMode 0x0200
-#define SetTVLowResolution 0x0400
/* =============================================================
for 310
============================================================== */
-#define SoftDRAMType 0x80
-#define SoftSetting_OFFSET 0x52
-#define SR07_OFFSET 0x7C
-#define SR15_OFFSET 0x7D
-#define SR16_OFFSET 0x81
-#define SR17_OFFSET 0x85
-#define SR19_OFFSET 0x8D
-#define SR1F_OFFSET 0x99
-#define SR21_OFFSET 0x9A
-#define SR22_OFFSET 0x9B
-#define SR23_OFFSET 0x9C
-#define SR24_OFFSET 0x9D
-#define SR25_OFFSET 0x9E
-#define SR31_OFFSET 0x9F
-#define SR32_OFFSET 0xA0
-#define SR33_OFFSET 0xA1
-
-#define CR40_OFFSET 0xA2
-#define SR25_1_OFFSET 0xF6
-#define CR49_OFFSET 0xF7
-
-#define VB310Data_1_2_Offset 0xB6
-#define VB310Data_4_D_Offset 0xB7
-#define VB310Data_4_E_Offset 0xB8
-#define VB310Data_4_10_Offset 0xBB
-
-#define RGBSenseDataOffset 0xBD
-#define YCSenseDataOffset 0xBF
-#define VideoSenseDataOffset 0xC1
-#define OutputSelectOffset 0xF3
-
-#define ECLK_MCLK_DISTANCE 0x14
-#define VBIOSTablePointerStart 0x200
-#define StandTablePtrOffset (VBIOSTablePointerStart+0x02)
-#define EModeIDTablePtrOffset (VBIOSTablePointerStart+0x04)
-#define CRT1TablePtrOffset (VBIOSTablePointerStart+0x06)
-#define ScreenOffsetPtrOffset (VBIOSTablePointerStart+0x08)
-#define VCLKDataPtrOffset (VBIOSTablePointerStart+0x0A)
-#define MCLKDataPtrOffset (VBIOSTablePointerStart+0x0E)
-#define CRT2PtrDataPtrOffset (VBIOSTablePointerStart+0x10)
-#define TVAntiFlickPtrOffset (VBIOSTablePointerStart+0x12)
-#define TVDelayPtr1Offset (VBIOSTablePointerStart+0x14)
-#define TVPhaseIncrPtr1Offset (VBIOSTablePointerStart+0x16)
-#define TVYFilterPtr1Offset (VBIOSTablePointerStart+0x18)
-#define LCDDelayPtr1Offset (VBIOSTablePointerStart+0x20)
-#define TVEdgePtr1Offset (VBIOSTablePointerStart+0x24)
-#define CRT2Delay1Offset (VBIOSTablePointerStart+0x28)
-#define LCDDataDesOffset (VBIOSTablePointerStart-0x02)
-#define LCDDataPtrOffset (VBIOSTablePointerStart+0x2A)
-#define LCDDesDataPtrOffset (VBIOSTablePointerStart+0x2C)
/* add LCDDataList for GetLCDPtr */
#define LCDDataList (VBIOSTablePointerStart+0x22)
-/* add TVDataList for GetTVPtr */
-#define TVDataList (VBIOSTablePointerStart+0x36)
/* */
/* Modify from 310.inc */
/* */
/* */
-
-#define ShowMsgFlag 0x20 /* SoftSetting */
-#define ShowVESAFlag 0x10
-#define HotPlugFunction 0x08
#define ModeSoftSetting 0x04
-#define TVSoftSetting 0x02
-#define LCDSoftSetting 0x01
-#define GatingCRTinLCDA 0x10
-#define SetHiTVOutput 0x08
-#define SetYPbPrOutput 0x04
#define BoardTVType 0x02
-#define SetSCARTOutput 0x01
-
-/* TVModeSetting, Others as same as CR30 */
-#define ModeSettingYPbPr 0x02
-
-/* TVModeSetting same as CR35 */
-
-/* LCDModeSetting same as CR37 */
-
-#define EnableNewTVFont 0x10 /* MiscCapability */
-
-#define EnableLCDOutput 0x80 /* LCDCfgSetting */
#define SoftDRAMType 0x80 /* DRAMSetting */
-#define SoftDRAMConfig 0x40
-#define MosSelDRAMType 0x20
-#define SDRAM 000h
-#define SGRAM 0x01
-#define ESDRAM 0x02
-
-#define EnableAGPCfgSetting 0x01 /* AGPCfgSetting */
/* ---------------- SetMode Stack */
#define CRT1Len 15
#define VCLKLen 4
-#define DefThreshold 0x0100
-#define ExtRegsSize ((57+8+37+70+63+28+768+1)/64+1)
-
-#define VGA_XGI315 0x0001 /* VGA Type Info */
-#define VGA_SNewis315e 0x0002 /* 315 series */
-#define VGA_XGI550 0x0004
-#define VGA_XGI640 0x0008
-#define VGA_XGI740 0x0010
-#define VGA_XGI650 0x0020
-#define VGA_XGI650M 0x0040
-#define VGA_XGI651 0x0080
#define VGA_XGI340 0x0001 /* 340 series */
-#define VGA_XGI330 0x0001 /* 330 series */
-#define VGA_XGI660 0x0001 /* 660 series */
#define VB_XGI301 0x0001 /* VB Type Info */
#define VB_XGI301B 0x0002 /* 301 series */
@@ -450,34 +90,16 @@
#define VB_XGI301LV 0x0008
#define VB_XGI302LV 0x0010
#define VB_LVDS_NS 0x0001 /* 3rd party chip */
-#define VB_CH7017 0x0002
-#define VB_CH7007 0x0080 /* [Billy] 07/05/03 */
-/* #define VB_LVDS_SI 0x0004 */
#define ModeInfoFlag 0x0007
-#define IsTextMode 0x0007
#define ModeText 0x0000
-#define ModeCGA 0x0001
#define ModeEGA 0x0002 /* 16 colors mode */
#define ModeVGA 0x0003 /* 256 colors mode */
-#define Mode15Bpp 0x0004 /* 15 Bpp Color Mode */
-#define Mode16Bpp 0x0005 /* 16 Bpp Color Mode */
-#define Mode24Bpp 0x0006 /* 24 Bpp Color Mode */
-#define Mode32Bpp 0x0007 /* 32 Bpp Color Mode */
#define DACInfoFlag 0x0018
-#define MONODAC 0x0000
-#define CGADAC 0x0008
-#define EGADAC 0x0010
-#define VGADAC 0x0018
#define MemoryInfoFlag 0x01e0
#define MemorySizeShift 5
-#define Need1MSize 0x0000
-#define Need2MSize 0x0020
-#define Need4MSize 0x0060
-#define Need8MSize 0x00e0
-#define Need16MSize 0x01e0
#define Charx8Dot 0x0200
#define LineCompareOff 0x0400
@@ -487,11 +109,7 @@
#define DoubleScanMode 0x8000
/* -------------- Ext_InfoFlag */
-#define SupportModeInfo 0x0007
-#define Support256 0x0003
-#define Support15Bpp 0x0004
#define Support16Bpp 0x0005
-#define Support24Bpp 0x0006
#define Support32Bpp 0x0007
#define SupportAllCRT2 0x0078
@@ -513,7 +131,6 @@
/* -------------- SetMode Stack/Scratch */
#define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */
#define SwitchToCRT2 0x0002
-#define SetCRT2ToTV1 0x009C
#define SetCRT2ToTV 0x089C
#define SetCRT2ToAVIDEO 0x0004
#define SetCRT2ToSVIDEO 0x0008
@@ -524,23 +141,14 @@
#define SetCRT2ToLCDA 0x0100
#define SetInSlaveMode 0x0200
#define SetNotSimuMode 0x0400
-#define HKEventMode 0x0800
#define SetCRT2ToYPbPr 0x0800
#define LoadDACFlag 0x1000
#define DisableCRT2Display 0x2000
#define DriverMode 0x4000
#define SetCRT2ToDualEdge 0x8000
-#define HotKeySwitch 0x8000
#define ProgrammingCRT2 0x0001 /* Set Flag */
-#define EnableVCMode 0x0002
-#define SetHKEventMode 0x0004
#define ReserveTVOption 0x0008
-#define DisableRelocateIO 0x0010
-#define Win9xDOSMode 0x0020
-#define JDOSMode 0x0040
-/* #define SetWin9xforJap 0x0080 // not used now */
-/* #define SetWin9xforKorea 0x0100 // not used now */
#define GatingCRT 0x0800
#define DisableChB 0x1000
#define EnableChB 0x2000
@@ -552,15 +160,11 @@
#define SetNTSCJ 0x0002
#define SetPALMTV 0x0004
#define SetPALNTV 0x0008
-#define SetCHTVUnderScan 0x0000
-/* #define SetCHTVOverScan 0x0010 */
#define SetYPbPrMode525i 0x0020
#define SetYPbPrMode525p 0x0040
#define SetYPbPrMode750p 0x0080
#define SetYPbPrMode1080i 0x0100
-#define SetTVStdMode 0x0200
#define SetTVLowResolution 0x0400
-#define SetTVSimuMode 0x0800
#define TVSimuMode 0x0800
#define RPLLDIV2XO 0x1000
#define NTSC1024x768 0x2000
@@ -571,38 +175,20 @@
#define EnableScalingLCD 0x0008
#define SetPWDEnable 0x0004
#define SetLCDtoNonExpanding 0x0010
-#define SetLCDPolarity 0x00e0
#define SetLCDDualLink 0x0100
#define SetLCDLowResolution 0x0200
#define SetLCDStdMode 0x0400
/* LCD Capability shampoo */
#define DefaultLCDCap 0x80ea
-#define RLVDSDHL00 0x0000
-#define RLVDSDHL01 0x0001
-#define RLVDSDHL10 0x0002 /* default */
-#define RLVDSDHL11 0x0003
#define EnableLCD24bpp 0x0004 /* default */
#define DisableLCD24bpp 0x0000
-#define RLVDSClkSFT0 0x0000
-#define RLVDSClkSFT1 0x0008 /* default */
-#define EnableLVDSDCBal 0x0010
-#define DisableLVDSDCBal 0x0000 /* default */
-#define SinglePolarity 0x0020 /* default */
-#define MultiPolarity 0x0000
#define LCDPolarity 0x00c0 /* default: SyncNN */
-#define LCDSingleLink 0x0000 /* default */
#define LCDDualLink 0x0100
#define EnableSpectrum 0x0200
-#define DisableSpectrum 0x0000 /* default */
#define PWDEnable 0x0400
-#define PWDDisable 0x0000 /* default */
-#define PWMEnable 0x0800
-#define PWMDisable 0x0000 /* default */
#define EnableVBCLKDRVLOW 0x4000
-#define EnableVBCLKDRVHigh 0x0000 /* default */
#define EnablePLLSPLOW 0x8000
-#define EnablePLLSPHigh 0x0000 /* default */
#define LCDBToA 0x20 /* LCD SetFlag */
#define StLCDBToA 0x40
@@ -616,187 +202,51 @@
#define Monitor1Sense 0x20
#define HiTVSense 0x40
-#ifdef NewScratch
#define YPbPrSense 0x80 /* NEW SCRATCH */
-#endif
#define TVSense 0xc7
#define TVOverScan 0x10 /* CR35 */
-#define TVOverScanShift 4
-#ifdef NewScratch
-#define NTSCMode 0x00
-#define PALMode 0x00
-#define NTSCJMode 0x02
-#define PALMNMode 0x0c
#define YPbPrMode 0xe0
#define YPbPrMode525i 0x00
#define YPbPrMode525p 0x20
#define YPbPrMode750p 0x40
#define YPbPrMode1080i 0x60
-#else /* Old Scratch */
-#define ClearBufferFlag 0x20
-#endif
#define LCDRGB18Bit 0x01 /* CR37 */
#define LCDNonExpanding 0x10
-#define LCDNonExpandingShift 4
#define LCDSync 0x20
#define LCDSyncBit 0xe0 /* H/V polarity & sync ID */
-#define LCDSyncShift 6
-#ifdef NewScratch
#define ScalingLCD 0x08
-#else /* Old Scratch */
-#define ExtChipType 0x0e
-#define ExtChip301 0x02
-#define ExtChipLVDS 0x04
-#define ExtChipCH7019 0x06
-#define ScalingLCD 0x10
-#endif
#define EnableDualEdge 0x01 /* CR38 */
#define SetToLCDA 0x02
-#ifdef NewScratch
#define SetYPbPr 0x04
-#define DisableChannelA 0x08
-#define DisableChannelB 0x10
-#define ExtChipType 0xe0
-#define ExtChip301 0x20
-#define ExtChipLVDS 0x40
-#define ExtChipCH7019 0x60
-#else /* Old Scratch */
-#define YPbPrSense 0x04
-#define SetYPbPr 0x08
-#define YPbPrMode 0x30
-#define YPbPrMode525i 0x00
-#define YPbPrMode525p 0x10
-#define YPbPrMode750p 0x20
-#define YPbPrMode1080i 0x30
-#define PALMNMode 0xc0
-#endif
-#define BacklightControlBit 0x01 /* CR3A */
-#define Win9xforJap 0x40
-#define Win9xforKorea 0x80
-
-#define ForceMDBits 0x07 /* CR3B */
-#define ForceMD_JDOS 0x00
-#define ForceMD_640x400T 0x01
-#define ForceMD_640x350T 0x02
-#define ForceMD_720x400T 0x03
-#define ForceMD_640x480E 0x04
-#define ForceMD_640x400E 0x05
-#define ForceP1Bit 0x10
-#define ForceP2Bit 0x20
-#define EnableForceMDinBIOS 0x40
-#define EnableForceMDinDrv 0x80
-
-#ifdef NewScratch /* New Scratch */
/* ---------------------- VUMA Information */
-#define LCDSettingFromCMOS 0x04 /* CR3C */
-#define TVSettingFromCMOS 0x08
#define DisplayDeviceFromCMOS 0x10
-#define HKSupportInSBIOS 0x20
-#define OSDSupportInSBIOS 0x40
-#define DisableLogo 0x80
/* ---------------------- HK Evnet Definition */
-#define HKEvent 0x0f /* CR3D */
-#define HK_ModeSwitch 0x01
-#define HK_Expanding 0x02
-#define HK_OverScan 0x03
-#define HK_Brightness 0x04
-#define HK_Contrast 0x05
-#define HK_Mute 0x06
-#define HK_Volume 0x07
#define ModeSwitchStatus 0xf0
#define ActiveCRT1 0x10
#define ActiveLCD 0x0020
#define ActiveTV 0x40
#define ActiveCRT2 0x80
-#define TVSwitchStatus 0x1f /* CR3E */
#define ActiveAVideo 0x01
#define ActiveSVideo 0x02
#define ActiveSCART 0x04
#define ActiveHiTV 0x08
#define ActiveYPbPr 0x10
-#define EnableHKEvent 0x01 /* CR3F */
-#define EnableOSDEvent 0x02
-#define StartOSDEvent 0x04
-#define IgnoreHKEvent 0x08
-#define IgnoreOSDEvent 0x10
-#else /* Old Scratch */
-#define OSD_SBIOS 0x02 /* SR17 */
-#define DisableLogo 0x04
-#define SelectKDOS 0x08
-#define KorWinMode 0x10
-#define KorMode3Bit 0x0020
-#define PSCCtrlBit 0x40
-#define NPSCCtrlBitShift 6
-#define BlueScreenBit 0x80
-
-#define HKEvent 0x0f /* CR79 */
-#define HK_ModeSwitch 0x01
-#define HK_Expanding 0x02
-#define HK_OverScan 0x03
-#define HK_Brightness 0x04
-#define HK_Contrast 0x05
-#define HK_Mute 0x06
-#define HK_Volume 0x07
-#define ActivePAL 0x0020
-#define ActivePALShift 5
-#define ActiveNonExpanding 0x40
-#define ActiveNonExpandingShift 6
-#define ActiveOverScan 0x80
-#define ActiveOverScanShift 7
-
-#define ModeSwitchStatus 0x0b /* SR15 */
-#define ActiveCRT1 0x01
-#define ActiveLCD 0x02
-#define ActiveCRT2 0x08
-
-#define TVSwitchStatus 0xf0 /* SR16 */
-#define TVConfigShift 3
-#define ActiveTV 0x01
-#define ActiveYPbPr 0x04
-#define ActiveAVideo 0x10
-#define ActiveSVideo 0x0020
-#define ActiveSCART 0x40
-#define ActiveHiTV 0x80
-
-#define EnableHKEvent 0x01 /* CR7A */
-#define EnableOSDEvent 0x02
-#define StartOSDEvent 0x04
-#define CMOSSupport 0x08
-#define HotKeySupport 0x10
-#define IngoreHKOSDEvent 0x20
-#endif
-
-/* //------------- Misc. Definition */
-#define SelectCRT1Rate 00h
-/* #define SelectCRT2Rate 04h */
-
-#define DDC1DelayTime 1000
-#ifdef TRUMPION
-#define DDC2DelayTime 15
-#else
-#define DDC2DelayTime 150
-#endif
-
-#define R_FACTOR 04Dh
-#define G_FACTOR 097h
-#define B_FACTOR 01Ch
/* --------------------------------------------------------- */
/* translated from asm code 301def.h */
/* */
/* --------------------------------------------------------- */
#define LCDDataLen 8
-#define HiTVDataLen 12
#define TVDataLen 12
#define LVDSCRT1Len_H 8
#define LVDSCRT1Len_V 7
@@ -806,7 +256,6 @@
#define LVDSDesDataLen2 8
#define LCDDesDataLen2 8
#define CHTVRegLen 16
-#define CHLVRegLen 12
#define StHiTVHT 892
#define StHiTVVT 1126
@@ -817,7 +266,6 @@
#define NTSCHT 1716
#define NTSCVT 525
#define NTSC1024x768HT 1908
-#define NTSC1024x768VT 525
#define PALHT 1728
#define PALVT 625
@@ -828,8 +276,6 @@
#define YPbPrTV750pHT 1650
#define YPbPrTV750pVT 750
-#define CRT2VCLKSel 0xc0
-
#define CRT2Delay1 0x04 /* XGI301 */
#define CRT2Delay2 0x0A /* 301B,302 */
@@ -846,57 +292,41 @@
#define VCLK52_406 0x09
#define VCLK56_25 0x0A
#define VCLK65 0x0B
-#define VCLK67_765 0x0C
#define VCLK68_179 0x0D
#define VCLK72_852 0x0E
#define VCLK75 0x0F
-#define VCLK75_8 0x10
#define VCLK78_75 0x11
#define VCLK79_411 0x12
#define VCLK83_95 0x13
-#define VCLK84_8 0x14
#define VCLK86_6 0x15
#define VCLK94_5 0x16
-#define VCLK104_998 0x17
-#define VCLK105_882 0x18
#define VCLK108_2 0x19
-#define VCLK109_175 0x1A
#define VCLK113_309 0x1B
#define VCLK116_406 0x1C
-#define VCLK132_258 0x1D
#define VCLK135_5 0x1E
#define VCLK139_054 0x1F
#define VCLK157_5 0x20
#define VCLK162 0x21
#define VCLK175 0x22
#define VCLK189 0x23
-#define VCLK194_4 0x24
#define VCLK202_5 0x25
#define VCLK229_5 0x26
#define VCLK234 0x27
-#define VCLK252_699 0x28
#define VCLK254_817 0x29
-#define VCLK265_728 0x2A
#define VCLK266_952 0x2B
#define VCLK269_655 0x2C
-#define VCLK272_042 0x2D
#define VCLK277_015 0x2E
-#define VCLK286_359 0x2F
#define VCLK291_132 0x30
#define VCLK291_766 0x31
-#define VCLK309_789 0x32
#define VCLK315_195 0x33
#define VCLK323_586 0x34
#define VCLK330_615 0x35
-#define VCLK332_177 0x36
#define VCLK340_477 0x37
#define VCLK375_847 0x38
#define VCLK388_631 0x39
#define VCLK125_999 0x51
#define VCLK148_5 0x52
-#define VCLK178_992 0x54
#define VCLK217_325 0x55
-#define VCLK299_505 0x56
#define YPbPr750pVCLK 0x57
#define TVVCLKDIV2 0x3A
@@ -906,45 +336,13 @@
#define HiTVSimuVCLK 0x3E
#define HiTVTextVCLK 0x3F
#define VCLK39_77 0x40
-/* #define YPbPr750pVCLK 0x0F */
#define YPbPr525pVCLK 0x3A
-/* #define ;;YPbPr525iVCLK 0x3B */
-/* #define ;;YPbPr525iVCLK_2 0x3A */
#define NTSC1024VCLK 0x41
-#define VCLK25_175_41 0x42 /* ; ScaleLCD */
-#define VCLK25_175_42 0x43
-#define VCLK28_322_43 0x44
-#define VCLK40_44 0x45
-#define VCLKQVGA_1 0x46 /* ; QVGA */
-#define VCLKQVGA_2 0x47
-#define VCLKQVGA_3 0x48
#define VCLK35_2 0x49 /* ; 800x480 */
#define VCLK122_61 0x4A
#define VCLK80_350 0x4B
#define VCLK107_385 0x4C
-#define CHTVVCLK30_2 0x50 /* ;;CHTV */
-#define CHTVVCLK28_1 0x51
-#define CHTVVCLK43_6 0x52
-#define CHTVVCLK26_4 0x53
-#define CHTVVCLK24_6 0x54
-#define CHTVVCLK47_8 0x55
-#define CHTVVCLK31_5 0x56
-#define CHTVVCLK26_2 0x57
-#define CHTVVCLK39 0x58
-#define CHTVVCLK36 0x59
-
-#define CH7007TVVCLK30_2 0x00 /* [Billy] 2007/05/18 For CH7007 */
-#define CH7007TVVCLK28_1 0x01
-#define CH7007TVVCLK43_6 0x02
-#define CH7007TVVCLK26_4 0x03
-#define CH7007TVVCLK24_6 0x04
-#define CH7007TVVCLK47_8 0x05
-#define CH7007TVVCLK31_5 0x06
-#define CH7007TVVCLK26_2 0x07
-#define CH7007TVVCLK39 0x08
-#define CH7007TVVCLK36 0x09
-
#define RES320x200 0x00
#define RES320x240 0x01
#define RES400x300 0x02
@@ -1018,5 +416,4 @@
#define RES1280x960x85 0x46
#define RES1280x960x120 0x47
-#define LFBDRAMTrap 0x30
#endif
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
index 7e1f76a..b1a2573 100644
--- a/drivers/staging/xgifb/vb_ext.c
+++ b/drivers/staging/xgifb/vb_ext.c
@@ -1,4 +1,3 @@
-#include <linux/version.h>
#include <linux/io.h>
#include <linux/types.h>
#include "XGIfb.h"
diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
index 814a446..0b1f55b 100644
--- a/drivers/staging/xgifb/vb_ext.h
+++ b/drivers/staging/xgifb/vb_ext.h
@@ -1,26 +1,6 @@
#ifndef _VBEXT_
#define _VBEXT_
-struct DWORDREGS {
- unsigned long Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp;
-};
-
-struct WORDREGS {
- unsigned short ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si,
- hi_si, di, hi_di, bp, hi_bp;
-};
-
-struct BYTEREGS {
- unsigned char al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch,
- hi_cl, hi_ch, dl, dh, hi_dl, hi_dh;
-};
-
-typedef union _X86_REGS {
- struct DWORDREGS e;
- struct WORDREGS x;
- struct BYTEREGS h;
-} X86_REGS, *PX86_REGS;
-
extern void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo);
extern unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 33c6876..9e890a1 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -1,8 +1,8 @@
-#include "vgatypes.h"
-
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/delay.h> /* udelay */
+#include <linux/pci.h>
+
+#include "vgatypes.h"
#include "XGIfb.h"
#include "vb_def.h"
@@ -15,15 +15,13 @@
#include <linux/io.h>
-static unsigned char XGINew_ChannelAB, XGINew_DataBusWidth;
-
-static unsigned short XGINew_DDRDRAM_TYPE340[4][5] = {
+static const unsigned short XGINew_DDRDRAM_TYPE340[4][5] = {
{ 2, 13, 9, 64, 0x45},
{ 2, 12, 9, 32, 0x35},
{ 2, 12, 8, 16, 0x31},
{ 2, 11, 8, 8, 0x21} };
-static unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
+static const unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
{ 2, 14, 11, 128, 0x5D},
{ 2, 14, 10, 64, 0x59},
{ 2, 13, 11, 64, 0x4D},
@@ -37,8 +35,6 @@ static unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
{ 2, 12, 9, 8, 0x35},
{ 2, 12, 8, 4, 0x31} };
-static int XGINew_RAMType;
-
static unsigned char
XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
@@ -112,14 +108,18 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
}
udelay(60);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+ xgifb_reg_set(P3c4,
+ 0x18,
+ pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
xgifb_reg_set(P3c4, 0x19, 0x01);
xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[0]);
xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[1]);
mdelay(1);
xgifb_reg_set(P3c4, 0x1B, 0x03);
udelay(500);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+ xgifb_reg_set(P3c4,
+ 0x18,
+ pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
xgifb_reg_set(P3c4, 0x19, 0x00);
xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[2]);
xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[3]);
@@ -132,23 +132,23 @@ static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4,
0x28,
- pVBInfo->MCLKData[XGINew_RAMType].SR28);
+ pVBInfo->MCLKData[pVBInfo->ram_type].SR28);
xgifb_reg_set(pVBInfo->P3c4,
0x29,
- pVBInfo->MCLKData[XGINew_RAMType].SR29);
+ pVBInfo->MCLKData[pVBInfo->ram_type].SR29);
xgifb_reg_set(pVBInfo->P3c4,
0x2A,
- pVBInfo->MCLKData[XGINew_RAMType].SR2A);
+ pVBInfo->MCLKData[pVBInfo->ram_type].SR2A);
xgifb_reg_set(pVBInfo->P3c4,
0x2E,
- pVBInfo->ECLKData[XGINew_RAMType].SR2E);
+ pVBInfo->ECLKData[pVBInfo->ram_type].SR2E);
xgifb_reg_set(pVBInfo->P3c4,
0x2F,
- pVBInfo->ECLKData[XGINew_RAMType].SR2F);
+ pVBInfo->ECLKData[pVBInfo->ram_type].SR2F);
xgifb_reg_set(pVBInfo->P3c4,
0x30,
- pVBInfo->ECLKData[XGINew_RAMType].SR30);
+ pVBInfo->ECLKData[pVBInfo->ram_type].SR30);
/* [Vicent] 2004/07/07,
* When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
@@ -156,12 +156,12 @@ static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
* Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz,
* Set SR32 D[1:0] = 10b */
if (HwDeviceExtension->jChipType == XG42) {
- if ((pVBInfo->MCLKData[XGINew_RAMType].SR28 == 0x1C) &&
- (pVBInfo->MCLKData[XGINew_RAMType].SR29 == 0x01) &&
- (((pVBInfo->ECLKData[XGINew_RAMType].SR2E == 0x1C) &&
- (pVBInfo->ECLKData[XGINew_RAMType].SR2F == 0x01)) ||
- ((pVBInfo->ECLKData[XGINew_RAMType].SR2E == 0x22) &&
- (pVBInfo->ECLKData[XGINew_RAMType].SR2F == 0x01))))
+ if ((pVBInfo->MCLKData[pVBInfo->ram_type].SR28 == 0x1C) &&
+ (pVBInfo->MCLKData[pVBInfo->ram_type].SR29 == 0x01) &&
+ (((pVBInfo->ECLKData[pVBInfo->ram_type].SR2E == 0x1C) &&
+ (pVBInfo->ECLKData[pVBInfo->ram_type].SR2F == 0x01)) ||
+ ((pVBInfo->ECLKData[pVBInfo->ram_type].SR2E == 0x22) &&
+ (pVBInfo->ECLKData[pVBInfo->ram_type].SR2F == 0x01))))
xgifb_reg_set(pVBInfo->P3c4,
0x32,
((unsigned char) xgifb_reg_get(
@@ -174,8 +174,7 @@ static void XGINew_DDRII_Bootup_XG27(
unsigned long P3c4, struct vb_device_info *pVBInfo)
{
unsigned long P3d4 = P3c4 + 0x10;
- XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension,
- pVBInfo);
+ pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
/* Set Double Frequency */
@@ -250,8 +249,7 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
{
unsigned long P3d4 = P3c4 + 0x10;
- XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension,
- pVBInfo);
+ pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
xgifb_reg_set(P3d4, 0x97, 0x11); /* CR97 */
@@ -307,7 +305,9 @@ static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4,
xgifb_reg_set(P3c4, 0x16, 0x00);
xgifb_reg_set(P3c4, 0x16, 0x80);
udelay(60);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+ xgifb_reg_set(P3c4,
+ 0x18,
+ pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
/* xgifb_reg_set(P3c4, 0x18, 0x31); */
xgifb_reg_set(P3c4, 0x19, 0x01);
xgifb_reg_set(P3c4, 0x16, 0x03);
@@ -316,7 +316,9 @@ static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4,
xgifb_reg_set(P3c4, 0x1B, 0x03);
udelay(500);
/* xgifb_reg_set(P3c4, 0x18, 0x31); */
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+ xgifb_reg_set(P3c4,
+ 0x18,
+ pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
xgifb_reg_set(P3c4, 0x19, 0x00);
xgifb_reg_set(P3c4, 0x16, 0x03);
xgifb_reg_set(P3c4, 0x16, 0x83);
@@ -333,13 +335,13 @@ static void XGINew_DDR1x_DefaultRegister(
XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
xgifb_reg_set(P3d4,
0x82,
- pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
+ pVBInfo->CR40[11][pVBInfo->ram_type]); /* CR82 */
xgifb_reg_set(P3d4,
0x85,
- pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
+ pVBInfo->CR40[12][pVBInfo->ram_type]); /* CR85 */
xgifb_reg_set(P3d4,
0x86,
- pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
+ pVBInfo->CR40[13][pVBInfo->ram_type]); /* CR86 */
xgifb_reg_set(P3d4, 0x98, 0x01);
xgifb_reg_set(P3d4, 0x9A, 0x02);
@@ -354,15 +356,15 @@ static void XGINew_DDR1x_DefaultRegister(
/* CR82 */
xgifb_reg_set(P3d4,
0x82,
- pVBInfo->CR40[11][XGINew_RAMType]);
+ pVBInfo->CR40[11][pVBInfo->ram_type]);
/* CR85 */
xgifb_reg_set(P3d4,
0x85,
- pVBInfo->CR40[12][XGINew_RAMType]);
+ pVBInfo->CR40[12][pVBInfo->ram_type]);
/* CR86 */
xgifb_reg_set(P3d4,
0x86,
- pVBInfo->CR40[13][XGINew_RAMType]);
+ pVBInfo->CR40[13][pVBInfo->ram_type]);
break;
default:
xgifb_reg_set(P3d4, 0x82, 0x88);
@@ -373,7 +375,7 @@ static void XGINew_DDR1x_DefaultRegister(
xgifb_reg_get(P3d4, 0x86);
xgifb_reg_set(P3d4,
0x86,
- pVBInfo->CR40[13][XGINew_RAMType]);
+ pVBInfo->CR40[13][pVBInfo->ram_type]);
xgifb_reg_set(P3d4, 0x82, 0x77);
xgifb_reg_set(P3d4, 0x85, 0x00);
@@ -386,11 +388,11 @@ static void XGINew_DDR1x_DefaultRegister(
/* CR85 */
xgifb_reg_set(P3d4,
0x85,
- pVBInfo->CR40[12][XGINew_RAMType]);
+ pVBInfo->CR40[12][pVBInfo->ram_type]);
/* CR82 */
xgifb_reg_set(P3d4,
0x82,
- pVBInfo->CR40[11][XGINew_RAMType]);
+ pVBInfo->CR40[11][pVBInfo->ram_type]);
break;
}
@@ -415,16 +417,18 @@ static void XGINew_DDR2_DefaultRegister(
xgifb_reg_set(P3d4, 0x86, 0x88);
xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */
/* CR86 */
- xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]);
+ xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][pVBInfo->ram_type]);
xgifb_reg_set(P3d4, 0x82, 0x77);
xgifb_reg_set(P3d4, 0x85, 0x00);
xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
xgifb_reg_set(P3d4, 0x85, 0x88);
xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
- xgifb_reg_set(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
+ xgifb_reg_set(P3d4,
+ 0x85,
+ pVBInfo->CR40[12][pVBInfo->ram_type]); /* CR85 */
if (HwDeviceExtension->jChipType == XG27)
/* CR82 */
- xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]);
+ xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][pVBInfo->ram_type]);
else
xgifb_reg_set(P3d4, 0x82, 0xA8); /* CR82 */
@@ -444,15 +448,15 @@ static void XGINew_SetDRAMDefaultRegister340(
unsigned long P3d4 = Port, P3c4 = Port - 0x10;
- xgifb_reg_set(P3d4, 0x6D, pVBInfo->CR40[8][XGINew_RAMType]);
- xgifb_reg_set(P3d4, 0x68, pVBInfo->CR40[5][XGINew_RAMType]);
- xgifb_reg_set(P3d4, 0x69, pVBInfo->CR40[6][XGINew_RAMType]);
- xgifb_reg_set(P3d4, 0x6A, pVBInfo->CR40[7][XGINew_RAMType]);
+ xgifb_reg_set(P3d4, 0x6D, pVBInfo->CR40[8][pVBInfo->ram_type]);
+ xgifb_reg_set(P3d4, 0x68, pVBInfo->CR40[5][pVBInfo->ram_type]);
+ xgifb_reg_set(P3d4, 0x69, pVBInfo->CR40[6][pVBInfo->ram_type]);
+ xgifb_reg_set(P3d4, 0x6A, pVBInfo->CR40[7][pVBInfo->ram_type]);
temp2 = 0;
for (i = 0; i < 4; i++) {
/* CR6B DQS fine tune delay */
- temp = pVBInfo->CR6B[XGINew_RAMType][i];
+ temp = pVBInfo->CR6B[pVBInfo->ram_type][i];
for (j = 0; j < 4; j++) {
temp1 = ((temp >> (2 * j)) & 0x03) << 2;
temp2 |= temp1;
@@ -467,7 +471,7 @@ static void XGINew_SetDRAMDefaultRegister340(
temp2 = 0;
for (i = 0; i < 4; i++) {
/* CR6E DQM fine tune delay */
- temp = pVBInfo->CR6E[XGINew_RAMType][i];
+ temp = pVBInfo->CR6E[pVBInfo->ram_type][i];
for (j = 0; j < 4; j++) {
temp1 = ((temp >> (2 * j)) & 0x03) << 2;
temp2 |= temp1;
@@ -486,7 +490,7 @@ static void XGINew_SetDRAMDefaultRegister340(
temp2 = 0;
for (i = 0; i < 8; i++) {
/* CR6F DQ fine tune delay */
- temp = pVBInfo->CR6F[XGINew_RAMType][8 * k + i];
+ temp = pVBInfo->CR6F[pVBInfo->ram_type][8 * k + i];
for (j = 0; j < 4; j++) {
temp1 = (temp >> (2 * j)) & 0x03;
temp2 |= temp1;
@@ -500,12 +504,16 @@ static void XGINew_SetDRAMDefaultRegister340(
temp3 += 0x01;
}
- xgifb_reg_set(P3d4, 0x80, pVBInfo->CR40[9][XGINew_RAMType]); /* CR80 */
- xgifb_reg_set(P3d4, 0x81, pVBInfo->CR40[10][XGINew_RAMType]); /* CR81 */
+ xgifb_reg_set(P3d4,
+ 0x80,
+ pVBInfo->CR40[9][pVBInfo->ram_type]); /* CR80 */
+ xgifb_reg_set(P3d4,
+ 0x81,
+ pVBInfo->CR40[10][pVBInfo->ram_type]); /* CR81 */
temp2 = 0x80;
/* CR89 terminator type select */
- temp = pVBInfo->CR89[XGINew_RAMType][0];
+ temp = pVBInfo->CR89[pVBInfo->ram_type][0];
for (j = 0; j < 4; j++) {
temp1 = (temp >> (2 * j)) & 0x03;
temp2 |= temp1;
@@ -515,45 +523,49 @@ static void XGINew_SetDRAMDefaultRegister340(
temp2 += 0x10;
}
- temp = pVBInfo->CR89[XGINew_RAMType][1];
+ temp = pVBInfo->CR89[pVBInfo->ram_type][1];
temp1 = temp & 0x03;
temp2 |= temp1;
xgifb_reg_set(P3d4, 0x89, temp2);
- temp = pVBInfo->CR40[3][XGINew_RAMType];
+ temp = pVBInfo->CR40[3][pVBInfo->ram_type];
temp1 = temp & 0x0F;
temp2 = (temp >> 4) & 0x07;
temp3 = temp & 0x80;
xgifb_reg_set(P3d4, 0x45, temp1); /* CR45 */
xgifb_reg_set(P3d4, 0x99, temp2); /* CR99 */
xgifb_reg_or(P3d4, 0x40, temp3); /* CR40_D[7] */
- xgifb_reg_set(P3d4, 0x41, pVBInfo->CR40[0][XGINew_RAMType]); /* CR41 */
+ xgifb_reg_set(P3d4,
+ 0x41,
+ pVBInfo->CR40[0][pVBInfo->ram_type]); /* CR41 */
if (HwDeviceExtension->jChipType == XG27)
xgifb_reg_set(P3d4, 0x8F, *pVBInfo->pCR8F); /* CR8F */
for (j = 0; j <= 6; j++) /* CR90 - CR96 */
xgifb_reg_set(P3d4, (0x90 + j),
- pVBInfo->CR40[14 + j][XGINew_RAMType]);
+ pVBInfo->CR40[14 + j][pVBInfo->ram_type]);
for (j = 0; j <= 2; j++) /* CRC3 - CRC5 */
xgifb_reg_set(P3d4, (0xC3 + j),
- pVBInfo->CR40[21 + j][XGINew_RAMType]);
+ pVBInfo->CR40[21 + j][pVBInfo->ram_type]);
for (j = 0; j < 2; j++) /* CR8A - CR8B */
xgifb_reg_set(P3d4, (0x8A + j),
- pVBInfo->CR40[1 + j][XGINew_RAMType]);
+ pVBInfo->CR40[1 + j][pVBInfo->ram_type]);
if ((HwDeviceExtension->jChipType == XG41) ||
(HwDeviceExtension->jChipType == XG42))
xgifb_reg_set(P3d4, 0x8C, 0x87);
- xgifb_reg_set(P3d4, 0x59, pVBInfo->CR40[4][XGINew_RAMType]); /* CR59 */
+ xgifb_reg_set(P3d4,
+ 0x59,
+ pVBInfo->CR40[4][pVBInfo->ram_type]); /* CR59 */
xgifb_reg_set(P3d4, 0x83, 0x09); /* CR83 */
xgifb_reg_set(P3d4, 0x87, 0x00); /* CR87 */
xgifb_reg_set(P3d4, 0xCF, *pVBInfo->pCRCF); /* CRCF */
- if (XGINew_RAMType) {
+ if (pVBInfo->ram_type) {
/* xgifb_reg_set(P3c4, 0x17, 0xC0); */ /* SR17 DDRII */
xgifb_reg_set(P3c4, 0x17, 0x80); /* SR17 DDRII */
if (HwDeviceExtension->jChipType == XG27)
@@ -571,11 +583,13 @@ static void XGINew_SetDRAMDefaultRegister340(
xgifb_reg_set(P3d4, 0xB0, 0x80); /* DDRII Dual frequency mode */
XGINew_DDR2_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
}
- xgifb_reg_set(P3c4, 0x1B, pVBInfo->SR15[3][XGINew_RAMType]); /* SR1B */
+ xgifb_reg_set(P3c4,
+ 0x1B,
+ pVBInfo->SR15[3][pVBInfo->ram_type]); /* SR1B */
}
static void XGINew_SetDRAMSizingType(int index,
- unsigned short DRAMTYPE_TABLE[][5],
+ const unsigned short DRAMTYPE_TABLE[][5],
struct vb_device_info *pVBInfo)
{
unsigned short data;
@@ -587,14 +601,14 @@ static void XGINew_SetDRAMSizingType(int index,
}
static unsigned short XGINew_SetDRAMSizeReg(int index,
- unsigned short DRAMTYPE_TABLE[][5],
+ const unsigned short DRAMTYPE_TABLE[][5],
struct vb_device_info *pVBInfo)
{
unsigned short data = 0, memsize = 0;
int RankSize;
unsigned char ChannelNo;
- RankSize = DRAMTYPE_TABLE[index][3] * XGINew_DataBusWidth / 32;
+ RankSize = DRAMTYPE_TABLE[index][3] * pVBInfo->ram_bus / 32;
data = xgifb_reg_get(pVBInfo->P3c4, 0x13);
data &= 0x80;
@@ -603,10 +617,10 @@ static unsigned short XGINew_SetDRAMSizeReg(int index,
data = 0;
- if (XGINew_ChannelAB == 3)
+ if (pVBInfo->ram_channel == 3)
ChannelNo = 4;
else
- ChannelNo = XGINew_ChannelAB;
+ ChannelNo = pVBInfo->ram_channel;
if (ChannelNo * RankSize <= 256) {
while ((RankSize >>= 1) > 0)
@@ -620,8 +634,8 @@ static unsigned short XGINew_SetDRAMSizeReg(int index,
(xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) |
(data & 0xF0));
- /* data |= XGINew_ChannelAB << 2; */
- /* data |= (XGINew_DataBusWidth / 64) << 1; */
+ /* data |= pVBInfo->ram_channel << 2; */
+ /* data |= (pVBInfo->ram_bus / 64) << 1; */
/* xgifb_reg_set(pVBInfo->P3c4, 0x14, data); */
/* should delay */
@@ -631,14 +645,14 @@ static unsigned short XGINew_SetDRAMSizeReg(int index,
}
static unsigned short XGINew_SetDRAMSize20Reg(int index,
- unsigned short DRAMTYPE_TABLE[][5],
+ const unsigned short DRAMTYPE_TABLE[][5],
struct vb_device_info *pVBInfo)
{
unsigned short data = 0, memsize = 0;
int RankSize;
unsigned char ChannelNo;
- RankSize = DRAMTYPE_TABLE[index][3] * XGINew_DataBusWidth / 8;
+ RankSize = DRAMTYPE_TABLE[index][3] * pVBInfo->ram_bus / 8;
data = xgifb_reg_get(pVBInfo->P3c4, 0x13);
data &= 0x80;
@@ -647,10 +661,10 @@ static unsigned short XGINew_SetDRAMSize20Reg(int index,
data = 0;
- if (XGINew_ChannelAB == 3)
+ if (pVBInfo->ram_channel == 3)
ChannelNo = 4;
else
- ChannelNo = XGINew_ChannelAB;
+ ChannelNo = pVBInfo->ram_channel;
if (ChannelNo * RankSize <= 256) {
while ((RankSize >>= 1) > 0)
@@ -665,8 +679,8 @@ static unsigned short XGINew_SetDRAMSize20Reg(int index,
(data & 0xF0));
udelay(15);
- /* data |= XGINew_ChannelAB << 2; */
- /* data |= (XGINew_DataBusWidth / 64) << 1; */
+ /* data |= pVBInfo->ram_channel << 2; */
+ /* data |= (pVBInfo->ram_bus / 64) << 1; */
/* xgifb_reg_set(pVBInfo->P3c4, 0x14, data); */
/* should delay */
@@ -680,12 +694,13 @@ static int XGINew_ReadWriteRest(unsigned short StopAddr,
{
int i;
unsigned long Position = 0;
+ void __iomem *fbaddr = pVBInfo->FBAddr;
- *((unsigned long *) (pVBInfo->FBAddr + Position)) = Position;
+ writel(Position, fbaddr + Position);
for (i = StartAddr; i <= StopAddr; i++) {
Position = 1 << i;
- *((unsigned long *) (pVBInfo->FBAddr + Position)) = Position;
+ writel(Position, fbaddr + Position);
}
udelay(500); /* [Vicent] 2004/04/16.
@@ -693,13 +708,12 @@ static int XGINew_ReadWriteRest(unsigned short StopAddr,
Position = 0;
- if ((*(unsigned long *) (pVBInfo->FBAddr + Position)) != Position)
+ if (readl(fbaddr + Position) != Position)
return 0;
for (i = StartAddr; i <= StopAddr; i++) {
Position = 1 << i;
- if ((*(unsigned long *) (pVBInfo->FBAddr + Position)) !=
- Position)
+ if (readl(fbaddr + Position) != Position)
return 0;
}
return 1;
@@ -730,14 +744,14 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
case XG21:
data = xgifb_reg_get(pVBInfo->P3d4, 0x97);
data = data & 0x01;
- XGINew_ChannelAB = 1; /* XG20 "JUST" one channel */
+ pVBInfo->ram_channel = 1; /* XG20 "JUST" one channel */
if (data == 0) { /* Single_32_16 */
if ((HwDeviceExtension->ulVideoMemorySize - 1)
> 0x1000000) {
- XGINew_DataBusWidth = 32; /* 32 bits */
+ pVBInfo->ram_bus = 32; /* 32 bits */
/* 22bit + 2 rank + 32bit */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
@@ -766,7 +780,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
if ((HwDeviceExtension->ulVideoMemorySize - 1) >
0x800000) {
- XGINew_DataBusWidth = 16; /* 16 bits */
+ pVBInfo->ram_bus = 16; /* 16 bits */
/* 22bit + 2 rank + 16bit */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41);
@@ -784,7 +798,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
} else { /* Dual_16_8 */
if ((HwDeviceExtension->ulVideoMemorySize - 1) >
0x800000) {
- XGINew_DataBusWidth = 16; /* 16 bits */
+ pVBInfo->ram_bus = 16; /* 16 bits */
/* (0x31:12x8x2) 22bit + 2 rank */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
/* 0x41:16Mx16 bit*/
@@ -815,7 +829,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
if ((HwDeviceExtension->ulVideoMemorySize - 1) >
0x400000) {
- XGINew_DataBusWidth = 8; /* 8 bits */
+ pVBInfo->ram_bus = 8; /* 8 bits */
/* (0x31:12x8x2) 22bit + 2 rank */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
/* 0x30:8Mx8 bit*/
@@ -834,21 +848,21 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
break;
case XG27:
- XGINew_DataBusWidth = 16; /* 16 bits */
- XGINew_ChannelAB = 1; /* Single channel */
+ pVBInfo->ram_bus = 16; /* 16 bits */
+ pVBInfo->ram_channel = 1; /* Single channel */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x51); /* 32Mx16 bit*/
break;
case XG41:
if (XGINew_CheckFrequence(pVBInfo) == 1) {
- XGINew_DataBusWidth = 32; /* 32 bits */
- XGINew_ChannelAB = 3; /* Quad Channel */
+ pVBInfo->ram_bus = 32; /* 32 bits */
+ pVBInfo->ram_channel = 3; /* Quad Channel */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4C);
if (XGINew_ReadWriteRest(25, 23, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 2; /* Dual channels */
+ pVBInfo->ram_channel = 2; /* Dual channels */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x48);
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
@@ -859,7 +873,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 3;
+ pVBInfo->ram_channel = 3;
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x3C);
@@ -873,15 +887,15 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
else
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x39);
} else { /* DDR */
- XGINew_DataBusWidth = 64; /* 64 bits */
- XGINew_ChannelAB = 2; /* Dual channels */
+ pVBInfo->ram_bus = 64; /* 64 bits */
+ pVBInfo->ram_channel = 2; /* Dual channels */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x5A);
if (XGINew_ReadWriteRest(25, 24, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 1; /* Single channels */
+ pVBInfo->ram_channel = 1; /* Single channels */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
@@ -892,14 +906,14 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 2; /* Dual channels */
+ pVBInfo->ram_channel = 2; /* Dual channels */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4A);
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 1; /* Single channels */
+ pVBInfo->ram_channel = 1; /* Single channels */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x42);
if (XGINew_ReadWriteRest(8, 4, pVBInfo) == 1)
@@ -919,8 +933,8 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
It's Different from Other XG40 Series.
*/
if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII, DDR2x */
- XGINew_DataBusWidth = 32; /* 32 bits */
- XGINew_ChannelAB = 2; /* 2 Channel */
+ pVBInfo->ram_bus = 32; /* 32 bits */
+ pVBInfo->ram_channel = 2; /* 2 Channel */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x44);
@@ -932,7 +946,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 1; /* Single Channel */
+ pVBInfo->ram_channel = 1; /* Single Channel */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x40);
@@ -943,8 +957,8 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x30);
}
} else { /* DDR */
- XGINew_DataBusWidth = 64; /* 64 bits */
- XGINew_ChannelAB = 1; /* 1 channels */
+ pVBInfo->ram_bus = 64; /* 64 bits */
+ pVBInfo->ram_channel = 1; /* 1 channels */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
@@ -961,15 +975,15 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
default: /* XG40 */
if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII */
- XGINew_DataBusWidth = 32; /* 32 bits */
- XGINew_ChannelAB = 3;
+ pVBInfo->ram_bus = 32; /* 32 bits */
+ pVBInfo->ram_channel = 3;
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4C);
if (XGINew_ReadWriteRest(25, 23, pVBInfo) == 1)
return;
- XGINew_ChannelAB = 2; /* 2 channels */
+ pVBInfo->ram_channel = 2; /* 2 channels */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x48);
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
@@ -979,14 +993,14 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x3C);
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1) {
- XGINew_ChannelAB = 3; /* 4 channels */
+ pVBInfo->ram_channel = 3; /* 4 channels */
} else {
- XGINew_ChannelAB = 2; /* 2 channels */
+ pVBInfo->ram_channel = 2; /* 2 channels */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x38);
}
} else { /* DDR */
- XGINew_DataBusWidth = 64; /* 64 bits */
- XGINew_ChannelAB = 2; /* 2 channels */
+ pVBInfo->ram_bus = 64; /* 64 bits */
+ pVBInfo->ram_channel = 2; /* 2 channels */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x5A);
@@ -1022,7 +1036,7 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
if (memsize == 0)
continue;
- addr = memsize + (XGINew_ChannelAB - 2) + 20;
+ addr = memsize + (pVBInfo->ram_channel - 2) + 20;
if ((HwDeviceExtension->ulVideoMemorySize - 1) <
(unsigned long) (1 << addr))
continue;
@@ -1042,7 +1056,7 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
if (memsize == 0)
continue;
- addr = memsize + (XGINew_ChannelAB - 2) + 20;
+ addr = memsize + (pVBInfo->ram_channel - 2) + 20;
if ((HwDeviceExtension->ulVideoMemorySize - 1) <
(unsigned long) (1 << addr))
continue;
@@ -1429,8 +1443,10 @@ static unsigned char GetXG27FPBits(struct vb_device_info *pVBInfo)
return temp;
}
-unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
+unsigned char XGIInitNew(struct pci_dev *pdev)
{
+ struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
+ struct xgi_hw_device_info *HwDeviceExtension = &xgifb_info->hw_info;
struct vb_device_info VBINF;
struct vb_device_info *pVBInfo = &VBINF;
unsigned char i, temp = 0, temp1;
@@ -1439,8 +1455,6 @@ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
/* unsigned long j, k; */
- unsigned long Temp;
-
pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
@@ -1552,8 +1566,7 @@ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
/* 3.SetMemoryClock
- XGINew_RAMType = (int)XGINew_GetXG20DRAMType(HwDeviceExtension,
- pVBInfo);
+ pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
*/
printk("11");
@@ -1580,6 +1593,8 @@ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
printk("12");
if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
+ u32 Temp;
+
/* Set AGP Rate */
/*
temp1 = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
@@ -1646,10 +1661,7 @@ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
/* if (ChipsetID == 0x25308086) */
/* xgifb_reg_set(pVBInfo->P3d4, 0x77, 0xF0); */
- HwDeviceExtension->pQueryVGAConfigSpace(HwDeviceExtension,
- 0x50,
- 0,
- &Temp); /* Get */
+ pci_read_config_dword(pdev, 0x50, &Temp);
Temp >>= 20;
Temp &= 0xF;
@@ -1733,15 +1745,6 @@ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
printk("183");
/* XGINew_DetectMonitor(HwDeviceExtension); */
- pVBInfo->IF_DEF_CH7007 = 0;
- if ((HwDeviceExtension->jChipType == XG21) &&
- (pVBInfo->IF_DEF_CH7007)) {
- printk("184");
- /* sense CRT2 */
- XGI_GetSenseStatus(HwDeviceExtension, pVBInfo);
- printk("185");
-
- }
if (HwDeviceExtension->jChipType == XG21) {
printk("186");
@@ -1764,8 +1767,7 @@ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
}
printk("19");
- XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension,
- pVBInfo);
+ pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
XGINew_SetDRAMDefaultRegister340(HwDeviceExtension,
pVBInfo->P3d4,
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
index 6b77230..a27b4fe 100644
--- a/drivers/staging/xgifb/vb_init.h
+++ b/drivers/staging/xgifb/vb_init.h
@@ -1,6 +1,6 @@
#ifndef _VBINIT_
#define _VBINIT_
-extern unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension);
+extern unsigned char XGIInitNew(struct pci_dev *pdev);
extern struct XGI21_LVDSCapStruct XGI21_LCDCapList[13];
#endif
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index 2669b1b..81c0cc4 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -2,24 +2,21 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/types.h>
-#include <linux/version.h>
#include "XGIfb.h"
#include "vb_def.h"
#include "vgatypes.h"
#include "vb_struct.h"
+#include "vb_init.h"
#include "vb_util.h"
#include "vb_table.h"
#include "vb_setmode.h"
#define IndexMask 0xff
-#ifndef XGI_MASK_DUAL_CHIP
-#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */
-#endif
-static unsigned short XGINew_MDA_DAC[] = {
+static const unsigned short XGINew_MDA_DAC[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
@@ -29,7 +26,7 @@ static unsigned short XGINew_MDA_DAC[] = {
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F};
-static unsigned short XGINew_CGA_DAC[] = {
+static const unsigned short XGINew_CGA_DAC[] = {
0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
@@ -39,7 +36,7 @@ static unsigned short XGINew_CGA_DAC[] = {
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F};
-static unsigned short XGINew_EGA_DAC[] = {
+static const unsigned short XGINew_EGA_DAC[] = {
0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
@@ -49,7 +46,7 @@ static unsigned short XGINew_EGA_DAC[] = {
0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F};
-static unsigned short XGINew_VGA_DAC[] = {
+static const unsigned short XGINew_VGA_DAC[] = {
0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
@@ -145,11 +142,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
pVBInfo->TimingV = (struct XGI_TimingVStruct *) XGI_TimingV;
pVBInfo->UpdateCRT1 = (struct XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table;
- pVBInfo->CHTVVCLKUNTSC = XGI330_CHTVVCLKUNTSC;
- pVBInfo->CHTVVCLKONTSC = XGI330_CHTVVCLKONTSC;
- pVBInfo->CHTVVCLKUPAL = XGI330_CHTVVCLKUPAL;
- pVBInfo->CHTVVCLKOPAL = XGI330_CHTVVCLKOPAL;
-
/* 310 customization related */
if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType & VB_XGI302LV))
pVBInfo->LCDCapList = XGI_LCDDLCapList;
@@ -208,19 +200,6 @@ static unsigned char XGI_GetModePtr(unsigned short ModeNo,
return index; /* Get pVBInfo->StandTable index */
}
-/*
-unsigned char XGI_SetBIOSData(unsigned short ModeNo,
- unsigned short ModeIdIndex) {
- return (0);
-}
-*/
-
-/* unsigned char XGI_ClearBankRegs(unsigned short ModeNo,
- unsigned short ModeIdIndex) {
- return( 0 ) ;
-}
-*/
-
static void XGI_SetSeqRegs(unsigned short ModeNo,
unsigned short StandTableIndex,
unsigned short ModeIdIndex,
@@ -491,11 +470,6 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
}
}
} else { /* for LVDS */
- if (pVBInfo->IF_DEF_CH7005 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- tempax |= SupportCHTV;
- }
-
if (pVBInfo->VBInfo & SetCRT2ToLCD) {
tempax |= SupportLCD;
@@ -1002,65 +976,10 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
}
}
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetXG21LCD */
-/* Input : */
-/* Output : FCLK duty cycle, FCLK delay compensation */
-/* Description : All values set zero */
-/* --------------------------------------------------------------------- */
-static void XGI_SetXG21LCD(struct vb_device_info *pVBInfo,
- unsigned short RefreshRateTableIndex, unsigned short ModeNo)
-{
- unsigned short Data, Temp, b3CC;
- unsigned short XGI_P3cc;
-
- XGI_P3cc = pVBInfo->P3cc;
-
- xgifb_reg_set(pVBInfo->P3d4, 0x2E, 0x00);
- xgifb_reg_set(pVBInfo->P3d4, 0x2F, 0x00);
- xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x00);
- xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x00);
- if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) {
- xgifb_reg_set(pVBInfo->P3d4, 0x2E, *pVBInfo->pCR2E);
- xgifb_reg_set(pVBInfo->P3d4, 0x2F, *pVBInfo->pCR2F);
- xgifb_reg_set(pVBInfo->P3d4, 0x46, *pVBInfo->pCR46);
- xgifb_reg_set(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47);
- }
-
- Temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
-
- if (Temp & 0x01) {
- xgifb_reg_or(pVBInfo->P3c4, 0x06, 0x40); /* 18 bits FP */
- xgifb_reg_or(pVBInfo->P3c4, 0x09, 0x40);
- }
-
- xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
-
- xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20);
- xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80);
-
- if (ModeNo <= 0x13) {
- b3CC = (unsigned char) inb(XGI_P3cc);
- if (b3CC & 0x40)
- /* Hsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
- if (b3CC & 0x80)
- /* Vsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
- } else {
- Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- if (Data & 0x4000)
- /* Hsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
- if (Data & 0x8000)
- /* Vsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
- }
-}
-
-static void XGI_SetXG27LCD(struct vb_device_info *pVBInfo,
- unsigned short RefreshRateTableIndex,
- unsigned short ModeNo)
+static void xgifb_set_lcd(int chip_id,
+ struct vb_device_info *pVBInfo,
+ unsigned short RefreshRateTableIndex,
+ unsigned short ModeNo)
{
unsigned short Data, Temp, b3CC;
unsigned short XGI_P3cc;
@@ -1072,10 +991,12 @@ static void XGI_SetXG27LCD(struct vb_device_info *pVBInfo,
xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x00);
xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x00);
- Temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
- if ((Temp & 0x03) == 0) { /* dual 12 */
- xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x13);
- xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x13);
+ if (chip_id == XG27) {
+ Temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
+ if ((Temp & 0x03) == 0) { /* dual 12 */
+ xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x13);
+ xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x13);
+ }
}
if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) {
@@ -1085,7 +1006,16 @@ static void XGI_SetXG27LCD(struct vb_device_info *pVBInfo,
xgifb_reg_set(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47);
}
- XGI_SetXG27FPBits(pVBInfo);
+ if (chip_id == XG27) {
+ XGI_SetXG27FPBits(pVBInfo);
+ } else {
+ Temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
+ if (Temp & 0x01) {
+ /* 18 bits FP */
+ xgifb_reg_or(pVBInfo->P3c4, 0x06, 0x40);
+ xgifb_reg_or(pVBInfo->P3c4, 0x09, 0x40);
+ }
+ }
xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
@@ -1337,8 +1267,6 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
- unsigned short tempbx;
-
unsigned short LCDXlat1VCLK[4] = { VCLK65 + 2,
VCLK65 + 2,
VCLK65 + 2,
@@ -1359,7 +1287,6 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
unsigned short CRT2Index, VCLKIndex;
unsigned short modeflag, resinfo;
- unsigned char *CHTVVCLKPtr = NULL;
if (ModeNo <= 0x13) {
/* si+St_ResInfo */
@@ -1460,47 +1387,15 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
else
VCLKIndex = CRT2Index;
- if (pVBInfo->IF_DEF_CH7005 == 1) {
- if (!(pVBInfo->VBInfo & SetCRT2ToLCD)) {
- VCLKIndex &= 0x1f;
- tempbx = 0;
-
- if (pVBInfo->VBInfo & SetPALTV)
- tempbx += 2;
-
- if (pVBInfo->VBInfo & SetCHTVOverScan)
- tempbx += 1;
-
- switch (tempbx) {
- case 0:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC;
- break;
- case 1:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC;
- break;
- case 2:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL;
- break;
- case 3:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL;
- break;
- default:
- break;
- }
-
- VCLKIndex = CHTVVCLKPtr[VCLKIndex];
- }
- } else {
- VCLKIndex = VCLKIndex >> 6;
- if ((pVBInfo->LCDResInfo == Panel800x600) ||
- (pVBInfo->LCDResInfo == Panel320x480))
- VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
- else if ((pVBInfo->LCDResInfo == Panel1024x768) ||
- (pVBInfo->LCDResInfo == Panel1024x768x75))
- VCLKIndex = LVDSXlat2VCLK[VCLKIndex];
- else
- VCLKIndex = LVDSXlat3VCLK[VCLKIndex];
- }
+ VCLKIndex = VCLKIndex >> 6;
+ if ((pVBInfo->LCDResInfo == Panel800x600) ||
+ (pVBInfo->LCDResInfo == Panel320x480))
+ VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
+ else if ((pVBInfo->LCDResInfo == Panel1024x768) ||
+ (pVBInfo->LCDResInfo == Panel1024x768x75))
+ VCLKIndex = LVDSXlat2VCLK[VCLKIndex];
+ else
+ VCLKIndex = LVDSXlat3VCLK[VCLKIndex];
}
/* VCLKIndex = VCLKIndex&IndexMask; */
@@ -1772,60 +1667,6 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
}
-/*
-void XGI_VesaLowResolution(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short modeflag;
-
- if (ModeNo > 0x13)
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- else
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-
- if (ModeNo > 0x13) {
- if (modeflag & DoubleScanMode) {
- if (modeflag & HalfDCLK) {
- if (pVBInfo->VBType & VB_XGI301B |
- VB_XGI302B |
- VB_XGI301LV |
- VB_XGI302LV |
- VB_XGI301C)) {
- if (!(pVBInfo->VBInfo &
- SetCRT2ToRAMDAC)) {
- if (pVBInfo->VBInfo &
- SetInSlaveMode) {
- xgifb_reg_and_or(
- pVBInfo->P3c4,
- 0x01,
- 0xf7,
- 0x00);
- xgifb_reg_and_or(
- pVBInfo->P3c4,
- 0x0f,
- 0x7f,
- 0x00);
- return;
- }
- }
- }
- xgifb_reg_and_or(pVBInfo->P3c4,
- 0x0f,
- 0xff,
- 0x80);
- xgifb_reg_and_or(pVBInfo->P3c4,
- 0x01,
- 0xf7,
- 0x00);
- return;
- }
- }
- }
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0f, 0x7f, 0x00);
-}
-*/
-
static void XGI_WriteDAC(unsigned short dl,
unsigned short ah,
unsigned short al,
@@ -1860,7 +1701,8 @@ static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
unsigned short data, data2, time, i, j, k, m, n, o, si, di, bx, dl, al,
- ah, dh, *table = NULL;
+ ah, dh;
+ const unsigned short *table = NULL;
if (ModeNo <= 0x13)
data = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
@@ -2062,10 +1904,8 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
switch (tempbx) {
case 0:
- tempdi = XGI_EPLLCDCRT1Ptr_H;
- break;
case 1:
- tempdi = XGI_EPLLCDCRT1Ptr_V;
+ tempdi = xgifb_epllcd_crt1;
break;
case 2:
tempdi = XGI_EPLLCDDataPtr;
@@ -2315,10 +2155,8 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
return &XGI_CetLCD1280x1024Data[tempal];
break;
case 6:
- return &XGI_ExtLCD1400x1050Data[tempal];
- break;
case 7:
- return &XGI_StLCD1400x1050Data[tempal];
+ return &xgifb_lcd_1400x1050[tempal];
break;
case 8:
return &XGI_CetLCD1400x1050Data[tempal];
@@ -2342,10 +2180,8 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
return &XGI_CetLCD1024x768x75Data[tempal];
break;
case 15:
- return &XGI_ExtLCD1280x1024x75Data[tempal];
- break;
case 16:
- return &XGI_StLCD1280x1024x75Data[tempal];
+ return &xgifb_lcd_1280x1024x75[tempal];
break;
case 17:
return &XGI_CetLCD1280x1024x75Data[tempal];
@@ -2389,18 +2225,12 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
return &XGI_CetLCDDes1280x1024Data[tempal];
break;
case 6:
- if ((pVBInfo->VBType & VB_XGI301LV) ||
- (pVBInfo->VBType & VB_XGI302LV))
- return &XGI_ExtLCDDLDes1400x1050Data[tempal];
- else
- return &XGI_ExtLCDDes1400x1050Data[tempal];
- break;
case 7:
if ((pVBInfo->VBType & VB_XGI301LV) ||
(pVBInfo->VBType & VB_XGI302LV))
- return &XGI_StLCDDLDes1400x1050Data[tempal];
+ return &xgifb_lcddldes_1400x1050[tempal];
else
- return &XGI_StLCDDes1400x1050Data[tempal];
+ return &xgifb_lcddes_1400x1050[tempal];
break;
case 8:
return &XGI_CetLCDDes1400x1050Data[tempal];
@@ -2426,27 +2256,19 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
return &XGI_NoScalingDesData[tempal];
break;
case 13:
- return &XGI_ExtLCDDes1024x768x75Data[tempal];
- break;
case 14:
- return &XGI_StLCDDes1024x768x75Data[tempal];
+ return &xgifb_lcddes_1024x768x75[tempal];
break;
case 15:
return &XGI_CetLCDDes1024x768x75Data[tempal];
break;
case 16:
- if ((pVBInfo->VBType & VB_XGI301LV) ||
- (pVBInfo->VBType & VB_XGI302LV))
- return &XGI_ExtLCDDLDes1280x1024x75Data[tempal];
- else
- return &XGI_ExtLCDDes1280x1024x75Data[tempal];
- break;
case 17:
if ((pVBInfo->VBType & VB_XGI301LV) ||
(pVBInfo->VBType & VB_XGI302LV))
- return &XGI_StLCDDLDes1280x1024x75Data[tempal];
+ return &xgifb_lcddldes_1280x1024x75[tempal];
else
- return &XGI_StLCDDes1280x1024x75Data[tempal];
+ return &xgifb_lcddes_1280x1024x75[tempal];
break;
case 18:
if ((pVBInfo->VBType & VB_XGI301LV) ||
@@ -2500,18 +2322,13 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
switch (tempbx) {
case 0:
tempdi = NULL; /*EPLCHTVCRT1Ptr_H;*/
- if (pVBInfo->IF_DEF_CH7007 == 1)
- tempdi = XGI_EPLCHTVCRT1Ptr;
-
break;
case 1:
tempdi = NULL; /*EPLCHTVCRT1Ptr_V;*/
- if (pVBInfo->IF_DEF_CH7007 == 1)
- tempdi = XGI_EPLCHTVCRT1Ptr;
-
break;
case 2:
- tempdi = XGI_EPLCHTVDataPtr;
+ case 6:
+ tempdi = xgifb_chrontel_tv;
break;
case 3:
tempdi = NULL;
@@ -2522,9 +2339,6 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
case 5:
tempdi = NULL;
break;
- case 6:
- tempdi = XGI_EPLCHTVRegPtr;
- break;
default:
break;
}
@@ -2626,7 +2440,6 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
{
unsigned short tempbx;
struct XGI330_LVDSDataStruct *LCDPtr = NULL;
- struct XGI330_CHTVDataStruct *TVPtr = NULL;
tempbx = 2;
@@ -2639,17 +2452,6 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
pVBInfo->HT = LCDPtr->LCDHT;
pVBInfo->VT = LCDPtr->LCDVT;
}
- if (pVBInfo->IF_DEF_CH7017 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- TVPtr = (struct XGI330_CHTVDataStruct *) XGI_GetTVPtr(
- tempbx, ModeNo, ModeIdIndex,
- RefreshRateTableIndex, pVBInfo);
- pVBInfo->VGAHT = TVPtr->VGAHT;
- pVBInfo->VGAVT = TVPtr->VGAVT;
- pVBInfo->HT = TVPtr->LCDHT;
- pVBInfo->VT = TVPtr->LCDVT;
- }
- }
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
if (!(pVBInfo->LCDInfo & (SetLCDtoNonExpanding
@@ -2682,9 +2484,6 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned short tempbx, i;
struct XGI_LVDSCRT1HDataStruct *LCDPtr = NULL;
struct XGI_LVDSCRT1VDataStruct *LCDPtr1 = NULL;
- /* struct XGI330_CHTVDataStruct *TVPtr = NULL; */
- struct XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
- struct XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
if (ModeNo <= 0x13)
index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2693,113 +2492,36 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
index = index & IndexMask;
- if ((pVBInfo->IF_DEF_ScaleLCD == 0) ||
- ((pVBInfo->IF_DEF_ScaleLCD == 1) &&
- (!(pVBInfo->LCDInfo & EnableScalingLCD)))) {
- tempbx = 0;
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- LCDPtr = (struct XGI_LVDSCRT1HDataStruct *)
- XGI_GetLcdPtr(tempbx, ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
-
- for (i = 0; i < 8; i++)
- pVBInfo->TimingH[0].data[i] = LCDPtr[0].Reg[i];
- }
-
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- CH7007TV_TimingHPtr =
- (struct XGI_CH7007TV_TimingHStruct *)
- XGI_GetTVPtr(
- tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
-
- for (i = 0; i < 8; i++)
- pVBInfo->TimingH[0].data[i] =
- CH7007TV_TimingHPtr[0].data[i];
- }
- }
-
- /* if (pVBInfo->IF_DEF_CH7017 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- TVPtr = (struct XGI330_CHTVDataStruct *)
- XGI_GetTVPtr(
- tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
- }
- */
-
- XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
-
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- xgifb_reg_set(pVBInfo->P3c4, 0x2E,
- CH7007TV_TimingHPtr[0].data[8]);
- xgifb_reg_set(pVBInfo->P3c4, 0x2F,
- CH7007TV_TimingHPtr[0].data[9]);
- }
-
- tempbx = 1;
+ tempbx = 0;
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- LCDPtr1 = (struct XGI_LVDSCRT1VDataStruct *)
- XGI_GetLcdPtr(
- tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
- for (i = 0; i < 7; i++)
- pVBInfo->TimingV[0].data[i] = LCDPtr1[0].Reg[i];
- }
-
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- CH7007TV_TimingVPtr =
- (struct XGI_CH7007TV_TimingVStruct *)
- XGI_GetTVPtr(
- tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
+ if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ LCDPtr = (struct XGI_LVDSCRT1HDataStruct *)
+ XGI_GetLcdPtr(tempbx, ModeNo,
+ ModeIdIndex,
+ RefreshRateTableIndex,
+ pVBInfo);
- for (i = 0; i < 7; i++)
- pVBInfo->TimingV[0].data[i] =
- CH7007TV_TimingVPtr[0].data[i];
- }
- }
- /* if (pVBInfo->IF_DEF_CH7017 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- TVPtr = (struct XGI330_CHTVDataStruct *)
- XGI_GetTVPtr(tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
- }
- */
+ for (i = 0; i < 8; i++)
+ pVBInfo->TimingH[0].data[i] = LCDPtr[0].Reg[i];
+ }
- XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
+ XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- xgifb_reg_and_or(pVBInfo->P3c4, 0x33, ~0x01,
- CH7007TV_TimingVPtr[0].data[7] & 0x01);
- xgifb_reg_set(pVBInfo->P3c4, 0x34,
- CH7007TV_TimingVPtr[0].data[8]);
- xgifb_reg_set(pVBInfo->P3c4, 0x3F,
- CH7007TV_TimingVPtr[0].data[9]);
+ tempbx = 1;
- }
+ if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ LCDPtr1 = (struct XGI_LVDSCRT1VDataStruct *)
+ XGI_GetLcdPtr(
+ tempbx,
+ ModeNo,
+ ModeIdIndex,
+ RefreshRateTableIndex,
+ pVBInfo);
+ for (i = 0; i < 7; i++)
+ pVBInfo->TimingV[0].data[i] = LCDPtr1[0].Reg[i];
}
+
+ XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
}
static unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
@@ -2888,287 +2610,263 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
else
modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- if (!(pVBInfo->SetFlag & Win9xDOSMode)) {
- if ((pVBInfo->IF_DEF_CH7017 == 0) || (pVBInfo->VBInfo
- & (SetCRT2ToLCD | SetCRT2ToLCDA))) {
- if (pVBInfo->IF_DEF_OEMUtil == 1) {
- tempbx = 8;
- LCDPtr = (struct XGI330_LCDDataDesStruct *)
- XGI_GetLcdPtr(tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
- }
-
- if ((pVBInfo->IF_DEF_OEMUtil == 0) ||
- (LCDPtr == NULL)) {
- tempbx = 3;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- LCDPtr1 =
- (struct XGI330_LCDDataDesStruct2 *)
- XGI_GetLcdPtr(
- tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
- else
- LCDPtr =
- (struct XGI330_LCDDataDesStruct *)
- XGI_GetLcdPtr(
- tempbx,
- ModeNo,
- ModeIdIndex,
- RefreshRateTableIndex,
- pVBInfo);
- }
+ tempbx = 3;
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ LCDPtr1 =
+ (struct XGI330_LCDDataDesStruct2 *)
+ XGI_GetLcdPtr(
+ tempbx,
+ ModeNo,
+ ModeIdIndex,
+ RefreshRateTableIndex,
+ pVBInfo);
+ else
+ LCDPtr =
+ (struct XGI330_LCDDataDesStruct *)
+ XGI_GetLcdPtr(
+ tempbx,
+ ModeNo,
+ ModeIdIndex,
+ RefreshRateTableIndex,
+ pVBInfo);
- XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
- push1 = tempbx;
- push2 = tempax;
+ XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
+ push1 = tempbx;
+ push2 = tempax;
+
+ /* GetLCDResInfo */
+ if ((pVBInfo->LCDResInfo == Panel1024x768) ||
+ (pVBInfo->LCDResInfo == Panel1024x768x75)) {
+ tempax = 1024;
+ tempbx = 768;
+ } else if ((pVBInfo->LCDResInfo == Panel1280x1024) ||
+ (pVBInfo->LCDResInfo == Panel1280x1024x75)) {
+ tempax = 1280;
+ tempbx = 1024;
+ } else if (pVBInfo->LCDResInfo == Panel1400x1050) {
+ tempax = 1400;
+ tempbx = 1050;
+ } else {
+ tempax = 1600;
+ tempbx = 1200;
+ }
- /* GetLCDResInfo */
- if ((pVBInfo->LCDResInfo == Panel1024x768) ||
- (pVBInfo->LCDResInfo == Panel1024x768x75)) {
- tempax = 1024;
- tempbx = 768;
- } else if ((pVBInfo->LCDResInfo == Panel1280x1024) ||
- (pVBInfo->LCDResInfo == Panel1280x1024x75)) {
- tempax = 1280;
- tempbx = 1024;
- } else if (pVBInfo->LCDResInfo == Panel1400x1050) {
- tempax = 1400;
- tempbx = 1050;
- } else {
- tempax = 1600;
- tempbx = 1200;
- }
+ if (pVBInfo->LCDInfo & SetLCDtoNonExpanding) {
+ pVBInfo->HDE = tempax;
+ pVBInfo->VDE = tempbx;
+ pVBInfo->VGAHDE = tempax;
+ pVBInfo->VGAVDE = tempbx;
+ }
- if (pVBInfo->LCDInfo & SetLCDtoNonExpanding) {
- pVBInfo->HDE = tempax;
- pVBInfo->VDE = tempbx;
- pVBInfo->VGAHDE = tempax;
- pVBInfo->VGAVDE = tempbx;
- }
+ tempax = pVBInfo->HT;
- if ((pVBInfo->IF_DEF_ScaleLCD == 1) &&
- (pVBInfo->LCDInfo & EnableScalingLCD)) {
- tempax = pVBInfo->HDE;
- tempbx = pVBInfo->VDE;
- }
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ tempbx = LCDPtr1->LCDHDES;
+ else
+ tempbx = LCDPtr->LCDHDES;
- tempax = pVBInfo->HT;
+ tempcx = pVBInfo->HDE;
+ tempbx = tempbx & 0x0fff;
+ tempcx += tempbx;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempbx = LCDPtr1->LCDHDES;
- else
- tempbx = LCDPtr->LCDHDES;
+ if (tempcx >= tempax)
+ tempcx -= tempax;
- tempcx = pVBInfo->HDE;
- tempbx = tempbx & 0x0fff;
- tempcx += tempbx;
+ xgifb_reg_set(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
- if (tempcx >= tempax)
- tempcx -= tempax;
+ tempcx = tempcx >> 3;
+ tempbx = tempbx >> 3;
- xgifb_reg_set(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
+ xgifb_reg_set(pVBInfo->Part1Port, 0x16,
+ (unsigned short) (tempbx & 0xff));
+ xgifb_reg_set(pVBInfo->Part1Port, 0x17,
+ (unsigned short) (tempcx & 0xff));
- tempcx = tempcx >> 3;
- tempbx = tempbx >> 3;
+ tempax = pVBInfo->HT;
- xgifb_reg_set(pVBInfo->Part1Port, 0x16,
- (unsigned short) (tempbx & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x17,
- (unsigned short) (tempcx & 0xff));
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ tempbx = LCDPtr1->LCDHRS;
+ else
+ tempbx = LCDPtr->LCDHRS;
- tempax = pVBInfo->HT;
+ tempcx = push2;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempbx = LCDPtr1->LCDHRS;
- else
- tempbx = LCDPtr->LCDHRS;
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ tempcx = LCDPtr1->LCDHSync;
- tempcx = push2;
+ tempcx += tempbx;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempcx = LCDPtr1->LCDHSync;
+ if (tempcx >= tempax)
+ tempcx -= tempax;
- tempcx += tempbx;
+ tempax = tempbx & 0x07;
+ tempax = tempax >> 5;
+ tempcx = tempcx >> 3;
+ tempbx = tempbx >> 3;
- if (tempcx >= tempax)
- tempcx -= tempax;
+ tempcx &= 0x1f;
+ tempax |= tempcx;
- tempax = tempbx & 0x07;
- tempax = tempax >> 5;
- tempcx = tempcx >> 3;
- tempbx = tempbx >> 3;
+ xgifb_reg_set(pVBInfo->Part1Port, 0x15, tempax);
+ xgifb_reg_set(pVBInfo->Part1Port, 0x14,
+ (unsigned short) (tempbx & 0xff));
- tempcx &= 0x1f;
- tempax |= tempcx;
+ tempax = pVBInfo->VT;
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ tempbx = LCDPtr1->LCDVDES;
+ else
+ tempbx = LCDPtr->LCDVDES;
+ tempcx = pVBInfo->VDE;
- xgifb_reg_set(pVBInfo->Part1Port, 0x15, tempax);
- xgifb_reg_set(pVBInfo->Part1Port, 0x14,
- (unsigned short) (tempbx & 0xff));
+ tempbx = tempbx & 0x0fff;
+ tempcx += tempbx;
+ if (tempcx >= tempax)
+ tempcx -= tempax;
- tempax = pVBInfo->VT;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempbx = LCDPtr1->LCDVDES;
- else
- tempbx = LCDPtr->LCDVDES;
- tempcx = pVBInfo->VDE;
+ xgifb_reg_set(pVBInfo->Part1Port, 0x1b,
+ (unsigned short) (tempbx & 0xff));
+ xgifb_reg_set(pVBInfo->Part1Port, 0x1c,
+ (unsigned short) (tempcx & 0xff));
- tempbx = tempbx & 0x0fff;
- tempcx += tempbx;
- if (tempcx >= tempax)
- tempcx -= tempax;
+ tempbx = (tempbx >> 8) & 0x07;
+ tempcx = (tempcx >> 8) & 0x07;
- xgifb_reg_set(pVBInfo->Part1Port, 0x1b,
- (unsigned short) (tempbx & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x1c,
- (unsigned short) (tempcx & 0xff));
+ xgifb_reg_set(pVBInfo->Part1Port, 0x1d,
+ (unsigned short) ((tempcx << 3)
+ | tempbx));
- tempbx = (tempbx >> 8) & 0x07;
- tempcx = (tempcx >> 8) & 0x07;
+ tempax = pVBInfo->VT;
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ tempbx = LCDPtr1->LCDVRS;
+ else
+ tempbx = LCDPtr->LCDVRS;
- xgifb_reg_set(pVBInfo->Part1Port, 0x1d,
- (unsigned short) ((tempcx << 3)
- | tempbx));
+ /* tempbx = tempbx >> 4; */
+ tempcx = push1;
- tempax = pVBInfo->VT;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempbx = LCDPtr1->LCDVRS;
- else
- tempbx = LCDPtr->LCDVRS;
+ if (pVBInfo->LCDInfo & EnableScalingLCD)
+ tempcx = LCDPtr1->LCDVSync;
- /* tempbx = tempbx >> 4; */
- tempcx = push1;
+ tempcx += tempbx;
+ if (tempcx >= tempax)
+ tempcx -= tempax;
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempcx = LCDPtr1->LCDVSync;
+ xgifb_reg_set(pVBInfo->Part1Port, 0x18,
+ (unsigned short) (tempbx & 0xff));
+ xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f,
+ (unsigned short) (tempcx & 0x0f));
- tempcx += tempbx;
- if (tempcx >= tempax)
- tempcx -= tempax;
+ tempax = ((tempbx >> 8) & 0x07) << 3;
- xgifb_reg_set(pVBInfo->Part1Port, 0x18,
- (unsigned short) (tempbx & 0xff));
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f,
- (unsigned short) (tempcx & 0x0f));
+ tempbx = pVBInfo->VGAVDE;
+ if (tempbx != pVBInfo->VDE)
+ tempax |= 0x40;
- tempax = ((tempbx >> 8) & 0x07) << 3;
+ if (pVBInfo->LCDInfo & EnableLVDSDDA)
+ tempax |= 0x40;
- tempbx = pVBInfo->VGAVDE;
- if (tempbx != pVBInfo->VDE)
- tempax |= 0x40;
+ xgifb_reg_and_or(pVBInfo->Part1Port, 0x1a, 0x07,
+ tempax);
- if (pVBInfo->LCDInfo & EnableLVDSDDA)
- tempax |= 0x40;
+ tempcx = pVBInfo->VGAVT;
+ tempbx = pVBInfo->VDE;
+ tempax = pVBInfo->VGAVDE;
+ tempcx -= tempax;
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x1a, 0x07,
- tempax);
+ temp = tempax; /* 0430 ylshieh */
+ temp1 = (temp << 18) / tempbx;
- tempcx = pVBInfo->VGAVT;
- tempbx = pVBInfo->VDE;
- tempax = pVBInfo->VGAVDE;
- tempcx -= tempax;
+ tempdx = (unsigned short) ((temp << 18) % tempbx);
- temp = tempax; /* 0430 ylshieh */
- temp1 = (temp << 18) / tempbx;
+ if (tempdx != 0)
+ temp1 += 1;
- tempdx = (unsigned short) ((temp << 18) % tempbx);
+ temp2 = temp1;
+ push3 = temp2;
- if (tempdx != 0)
- temp1 += 1;
+ xgifb_reg_set(pVBInfo->Part1Port, 0x37,
+ (unsigned short) (temp2 & 0xff));
+ xgifb_reg_set(pVBInfo->Part1Port, 0x36,
+ (unsigned short) ((temp2 >> 8) & 0xff));
- temp2 = temp1;
- push3 = temp2;
+ tempbx = (unsigned short) (temp2 >> 16);
+ tempax = tempbx & 0x03;
- xgifb_reg_set(pVBInfo->Part1Port, 0x37,
- (unsigned short) (temp2 & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x36,
- (unsigned short) ((temp2 >> 8) & 0xff));
+ tempbx = pVBInfo->VGAVDE;
+ if (tempbx == pVBInfo->VDE)
+ tempax |= 0x04;
- tempbx = (unsigned short) (temp2 >> 16);
- tempax = tempbx & 0x03;
+ xgifb_reg_set(pVBInfo->Part1Port, 0x35, tempax);
- tempbx = pVBInfo->VGAVDE;
- if (tempbx == pVBInfo->VDE)
- tempax |= 0x04;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x35, tempax);
-
- if (pVBInfo->VBType & VB_XGI301C) {
- temp2 = push3;
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x3c,
- (unsigned short) (temp2 & 0xff));
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x3b,
- (unsigned short) ((temp2 >> 8) &
- 0xff));
- tempbx = (unsigned short) (temp2 >> 16);
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x3a,
- ~0xc0,
- (unsigned short) ((tempbx &
- 0xff) << 6));
-
- tempcx = pVBInfo->VGAVDE;
- if (tempcx == pVBInfo->VDE)
- xgifb_reg_and_or(pVBInfo->Part4Port,
- 0x30, ~0x0c, 0x00);
- else
- xgifb_reg_and_or(pVBInfo->Part4Port,
- 0x30, ~0x0c, 0x08);
- }
+ if (pVBInfo->VBType & VB_XGI301C) {
+ temp2 = push3;
+ xgifb_reg_set(pVBInfo->Part4Port,
+ 0x3c,
+ (unsigned short) (temp2 & 0xff));
+ xgifb_reg_set(pVBInfo->Part4Port,
+ 0x3b,
+ (unsigned short) ((temp2 >> 8) &
+ 0xff));
+ tempbx = (unsigned short) (temp2 >> 16);
+ xgifb_reg_and_or(pVBInfo->Part4Port, 0x3a,
+ ~0xc0,
+ (unsigned short) ((tempbx &
+ 0xff) << 6));
+
+ tempcx = pVBInfo->VGAVDE;
+ if (tempcx == pVBInfo->VDE)
+ xgifb_reg_and_or(pVBInfo->Part4Port,
+ 0x30, ~0x0c, 0x00);
+ else
+ xgifb_reg_and_or(pVBInfo->Part4Port,
+ 0x30, ~0x0c, 0x08);
+ }
- tempcx = pVBInfo->VGAHDE;
- tempbx = pVBInfo->HDE;
+ tempcx = pVBInfo->VGAHDE;
+ tempbx = pVBInfo->HDE;
- temp1 = tempcx << 16;
+ temp1 = tempcx << 16;
- tempax = (unsigned short) (temp1 / tempbx);
+ tempax = (unsigned short) (temp1 / tempbx);
- if ((tempbx & 0xffff) == (tempcx & 0xffff))
- tempax = 65535;
+ if ((tempbx & 0xffff) == (tempcx & 0xffff))
+ tempax = 65535;
- temp3 = tempax;
- temp1 = pVBInfo->VGAHDE << 16;
+ temp3 = tempax;
+ temp1 = pVBInfo->VGAHDE << 16;
- temp1 /= temp3;
- temp3 = temp3 << 16;
- temp1 -= 1;
+ temp1 /= temp3;
+ temp3 = temp3 << 16;
+ temp1 -= 1;
- temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
+ temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
- tempax = (unsigned short) (temp3 & 0xff);
- xgifb_reg_set(pVBInfo->Part1Port, 0x1f, tempax);
+ tempax = (unsigned short) (temp3 & 0xff);
+ xgifb_reg_set(pVBInfo->Part1Port, 0x1f, tempax);
- temp1 = pVBInfo->VGAVDE << 18;
- temp1 = temp1 / push3;
- tempbx = (unsigned short) (temp1 & 0xffff);
+ temp1 = pVBInfo->VGAVDE << 18;
+ temp1 = temp1 / push3;
+ tempbx = (unsigned short) (temp1 & 0xffff);
- if (pVBInfo->LCDResInfo == Panel1024x768)
- tempbx -= 1;
+ if (pVBInfo->LCDResInfo == Panel1024x768)
+ tempbx -= 1;
- tempax = ((tempbx >> 8) & 0xff) << 3;
- tempax |= (unsigned short) ((temp3 >> 8) & 0x07);
- xgifb_reg_set(pVBInfo->Part1Port, 0x20,
- (unsigned short) (tempax & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x21,
- (unsigned short) (tempbx & 0xff));
+ tempax = ((tempbx >> 8) & 0xff) << 3;
+ tempax |= (unsigned short) ((temp3 >> 8) & 0x07);
+ xgifb_reg_set(pVBInfo->Part1Port, 0x20,
+ (unsigned short) (tempax & 0xff));
+ xgifb_reg_set(pVBInfo->Part1Port, 0x21,
+ (unsigned short) (tempbx & 0xff));
- temp3 = temp3 >> 16;
+ temp3 = temp3 >> 16;
- if (modeflag & HalfDCLK)
- temp3 = temp3 >> 1;
+ if (modeflag & HalfDCLK)
+ temp3 = temp3 >> 1;
- xgifb_reg_set(pVBInfo->Part1Port, 0x22,
- (unsigned short) ((temp3 >> 8) & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x23,
- (unsigned short) (temp3 & 0xff));
- }
- }
+ xgifb_reg_set(pVBInfo->Part1Port, 0x22,
+ (unsigned short) ((temp3 >> 8) & 0xff));
+ xgifb_reg_set(pVBInfo->Part1Port, 0x23,
+ (unsigned short) (temp3 & 0xff));
}
/* --------------------------------------------------------------------- */
@@ -3183,11 +2881,6 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
unsigned short index;
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if (pVBInfo->IF_DEF_ScaleLCD == 1) {
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- return;
- }
-
/* index = XGI_GetLCDCapPtr(pVBInfo); */
index = XGI_GetLCDCapPtr1(pVBInfo);
@@ -3208,9 +2901,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
{
unsigned short index, modeflag;
- unsigned short tempbx;
unsigned char tempal;
- unsigned char *CHTVVCLKPtr = NULL;
if (ModeNo <= 0x13)
/* si+St_ResInfo */
@@ -3268,95 +2959,8 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
if (pVBInfo->VBInfo & SetCRT2ToTV)
return tempal;
}
- /* else if ((pVBInfo->IF_DEF_CH7017==1) &&
- (pVBInfo->VBType&VB_CH7017)) {
- if (ModeNo<=0x13)
- *tempal = pVBInfo->SModeIDTable[ModeIdIndex].
- St_CRT2CRTC;
- else
- *tempal = pVBInfo->RefIndex[
- RefreshRateTableIndex].Ext_CRT2CRTC;
- *tempal = *tempal & 0x1F;
- tempbx = 0;
- if (pVBInfo->TVInfo & SetPALTV)
- tempbx = tempbx + 2;
- if (pVBInfo->TVInfo & SetCHTVOverScan)
- tempbx++;
- tempbx = tempbx << 1;
- } */
} /* {End of VB} */
- if ((pVBInfo->IF_DEF_CH7007 == 1) &&
- (pVBInfo->VBType & VB_CH7007)) { /* [Billy] 07/05/08 CH7007 */
- /* VideoDebugPrint((
- 0,
- "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
- if ((pVBInfo->VBInfo & SetCRT2ToTV)) {
- if (ModeNo <= 0x13) {
- tempal = pVBInfo->SModeIDTable[ModeIdIndex].
- St_CRT2CRTC;
- } else {
- tempal = pVBInfo->RefIndex[
- RefreshRateTableIndex].Ext_CRT2CRTC;
- }
-
- tempal = tempal & 0x0F;
- tempbx = 0;
-
- if (pVBInfo->TVInfo & SetPALTV)
- tempbx = tempbx + 2;
-
- if (pVBInfo->TVInfo & SetCHTVOverScan)
- tempbx++;
-
- /** tempbx = tempbx << 1; CH7007 ? **/
-
- /* [Billy]07/05/29 CH7007 */
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- switch (tempbx) {
- case 0:
- CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC;
- break;
- case 1:
- CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC;
- break;
- case 2:
- CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL;
- break;
- case 3:
- CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL;
- break;
- default:
- break;
-
- }
- }
- /* else {
- switch(tempbx) {
- case 0:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC;
- break;
- case 1:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC;
- break;
- case 2:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL;
- break;
- case 3:
- CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL;
- break;
- default:
- break;
- }
- }
- */
-
- tempal = CHTVVCLKPtr[tempal];
- return tempal;
- }
-
- }
-
tempal = (unsigned char) inb((pVBInfo->P3ca + 0x02));
tempal = tempal >> 2;
tempal &= 0x03;
@@ -3375,13 +2979,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
unsigned char *di_1, struct vb_device_info *pVBInfo)
{
- if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 2007/05/16 */
- /* VideoDebugPrint((
- 0,
- "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
- *di_0 = (unsigned char) XGI_CH7007VCLKData[tempal].SR2B;
- *di_1 = (unsigned char) XGI_CH7007VCLKData[tempal].SR2C;
- } else if (pVBInfo->VBType & (VB_XGI301 | VB_XGI301B | VB_XGI302B
+ if (pVBInfo->VBType & (VB_XGI301 | VB_XGI301B | VB_XGI302B
| VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) && (pVBInfo->SetFlag
& ProgrammingCRT2)) {
@@ -3409,10 +3007,7 @@ static void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex,
for (i = 0; i < 4; i++) {
xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30,
(unsigned short) (0x10 * i));
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- xgifb_reg_set(pVBInfo->P3c4, 0x2b, di_0);
- xgifb_reg_set(pVBInfo->P3c4, 0x2c, di_1);
- } else if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA))
+ if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA))
&& (!(pVBInfo->VBInfo & SetInSlaveMode))) {
xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0);
xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1);
@@ -3527,10 +3122,6 @@ void XGI_GetVBType(struct vb_device_info *pVBInfo)
{
unsigned short flag, tempbx, tempah;
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- pVBInfo->VBType = VB_CH7007;
- return;
- }
if (pVBInfo->IF_DEF_LVDS == 0) {
tempbx = VB_XGI302B;
flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00);
@@ -3567,13 +3158,6 @@ void XGI_GetVBType(struct vb_device_info *pVBInfo)
}
pVBInfo->VBType = tempbx;
}
- /*
- else if (pVBInfo->IF_DEF_CH7017 == 1)
- pVBInfo->VBType = VB_CH7017;
- else //LVDS
- pVBInfo->VBType = VB_LVDS_NS;
- */
-
}
void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
@@ -3631,17 +3215,6 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
SetCRT2ToLCDA;
}
}
- } else if (pVBInfo->IF_DEF_CH7017 == 1) {
- if (pVBInfo->VBType & VB_CH7017) {
- if (temp & EnableDualEdge) {
- tempbx |=
- SetCRT2ToDualEdge;
-
- if (temp & SetToLCDA)
- tempbx |=
- SetCRT2ToLCDA;
- }
- }
}
}
}
@@ -3651,11 +3224,7 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
if (((pVBInfo->IF_DEF_LVDS == 0) &&
((pVBInfo->VBType & VB_XGI301LV) ||
(pVBInfo->VBType & VB_XGI302LV) ||
- (pVBInfo->VBType & VB_XGI301C))) ||
- ((pVBInfo->IF_DEF_CH7017 == 1) &&
- (pVBInfo->VBType & VB_CH7017)) ||
- ((pVBInfo->IF_DEF_CH7007 == 1) &&
- (pVBInfo->VBType & VB_CH7007))) {
+ (pVBInfo->VBType & VB_XGI301C)))) {
if (temp & SetYPbPr) { /* temp = CR38 */
if (pVBInfo->IF_DEF_HiVision == 1) {
/* shampoo add for new
@@ -3694,15 +3263,7 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
temp = 0x017C;
}
} else { /* 3nd party chip */
- if (pVBInfo->IF_DEF_CH7017 == 1)
- temp = (SetCRT2ToTV |
- SetCRT2ToLCD |
- SetCRT2ToLCDA);
- /* [Billy] 07/05/03 */
- else if (pVBInfo->IF_DEF_CH7007 == 1)
- temp = SetCRT2ToTV;
- else
- temp = SetCRT2ToLCD;
+ temp = SetCRT2ToLCD;
}
if (!(tempbx & temp)) {
@@ -3790,34 +3351,6 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
tempbx |= (SetInSlaveMode |
SetSimuScanMode);
}
-
- if (pVBInfo->IF_DEF_VideoCapture == 1) {
- if (((HwDeviceExtension->jChipType ==
- XG40) &&
- (pVBInfo->Set_VGAType == XG40)) ||
- ((HwDeviceExtension->jChipType ==
- XG41) &&
- (pVBInfo->Set_VGAType == XG41)) ||
- ((HwDeviceExtension->jChipType ==
- XG42) &&
- (pVBInfo->Set_VGAType == XG42)) ||
- ((HwDeviceExtension->jChipType ==
- XG45) &&
- (pVBInfo->Set_VGAType == XG45))) {
- if (ModeNo <= 13) {
- if (!(tempbx &
- SetCRT2ToRAMDAC)) {
- /*CRT2 not need
- * to support*/
- tempbx &=
- (0x00FF |
- (~SetInSlaveMode));
- pVBInfo->SetFlag
- |= EnableVCMode;
- }
- }
- }
- }
}
/* LCD+TV can't support in slave mode
@@ -3884,20 +3417,6 @@ void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
*/
}
- if (pVBInfo->IF_DEF_CH7017 == 1) {
- tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
-
- if (tempbx & TVOverScan)
- tempbx |= SetCHTVOverScan;
- }
-
- if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/04 */
- tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
-
- if (tempbx & TVOverScan)
- tempbx |= SetCHTVOverScan;
- }
-
if (pVBInfo->IF_DEF_LVDS == 0) {
if (pVBInfo->VBInfo & SetCRT2ToSCART)
tempbx |= SetPALTV;
@@ -4004,9 +3523,6 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
/* End of LCD75 */
- if (pVBInfo->IF_DEF_OEMUtil == 1)
- pVBInfo->LCDTypeInfo = (temp & 0xf0) >> 4;
-
if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)))
return 0;
@@ -4016,9 +3532,6 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
temp &= (ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable);
- if ((pVBInfo->IF_DEF_ScaleLCD == 1) && (temp & LCDNonExpanding))
- temp &= ~EnableScalingLCD;
-
tempbx |= temp;
LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo);
@@ -4032,11 +3545,6 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
}
}
- if (pVBInfo->IF_DEF_CH7017 == 1) {
- if (tempax & LCDDualLink)
- tempbx |= SetLCDDualLink;
- }
-
if (pVBInfo->IF_DEF_LVDS == 0) {
if ((pVBInfo->LCDResInfo == Panel1400x1050) && (pVBInfo->VBInfo
& SetCRT2ToLCD) && (ModeNo > 0x13) && (resinfo
@@ -4078,16 +3586,6 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
pVBInfo->LCDInfo = tempbx;
- if (pVBInfo->IF_DEF_PWD == 1) {
- if (pVBInfo->LCDInfo & SetPWDEnable) {
- if ((pVBInfo->VBType & VB_XGI302LV) ||
- (pVBInfo->VBType & VB_XGI301C)) {
- if (!(tempax & PWDEnable))
- pVBInfo->LCDInfo &= ~SetPWDEnable;
- }
- }
- }
-
if (pVBInfo->IF_DEF_LVDS == 0) {
if (tempax & (LockLCDBToA | StLCDBToA)) {
if (pVBInfo->VBInfo & SetInSlaveMode) {
@@ -4170,102 +3668,6 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
return 1;
}
-/* win2000 MM adapter not support standard mode! */
-
-#if 0
-static unsigned char XGINew_CheckMemorySize(
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short memorysize, modeflag, temp, temp1, tmp;
-
- /*
- if ((HwDeviceExtension->jChipType == XGI_650) ||
- (HwDeviceExtension->jChipType == XGI_650M)) {
- return 1;
- }
- */
-
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- /* ModeType = modeflag&ModeInfoFlag; // Get mode type */
-
- memorysize = modeflag & MemoryInfoFlag;
- memorysize = memorysize > MemorySizeShift;
- memorysize++; /* Get memory size */
-
- temp = xgifb_reg_get(pVBInfo->P3c4, 0x14); /* Get DRAM Size */
- tmp = temp;
-
- if (HwDeviceExtension->jChipType == XG40) {
- /* memory size per channel SR14[7:4] */
- temp = 1 << ((temp & 0x0F0) >> 4);
- if ((tmp & 0x0c) == 0x0C) { /* Qual channels */
- temp <<= 2;
- } else if ((tmp & 0x0c) == 0x08) { /* Dual channels */
- temp <<= 1;
- }
- } else if (HwDeviceExtension->jChipType == XG42) {
- /* memory size per channel SR14[7:4] */
- temp = 1 << ((temp & 0x0F0) >> 4);
- if ((tmp & 0x04) == 0x04) { /* Dual channels */
- temp <<= 1;
- }
- } else if (HwDeviceExtension->jChipType == XG45) {
- /* memory size per channel SR14[7:4] */
- temp = 1 << ((temp & 0x0F0) >> 4);
- if ((tmp & 0x0c) == 0x0C) { /* Qual channels */
- temp <<= 2;
- } else if ((tmp & 0x0c) == 0x08) { /* triple channels */
- temp1 = temp;
- temp <<= 1;
- temp += temp1;
- } else if ((tmp & 0x0c) == 0x04) { /* Dual channels */
- temp <<= 1;
- }
- }
- if (temp < memorysize)
- return 0;
- else
- return 1;
-}
-#endif
-
-/*
-void XGINew_IsLowResolution(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- unsigned char XGINew_CheckMemorySize(
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short data ;
- unsigned short ModeFlag ;
-
- data = xgifb_reg_get(pVBInfo->P3c4, 0x0F);
- data &= 0x7F;
- xgifb_reg_set(pVBInfo->P3c4, 0x0F, data);
-
- if (ModeNo > 0x13) {
- ModeFlag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- if ((ModeFlag & HalfDCLK) && (ModeFlag & DoubleScanMode)) {
- data = xgifb_reg_get(pVBInfo->P3c4, 0x0F);
- data |= 0x80;
- xgifb_reg_set(pVBInfo->P3c4, 0x0F, data);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x01);
- data &= 0xF7;
- xgifb_reg_set(pVBInfo->P3c4, 0x01, data);
- }
- }
-}
-*/
-
static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
{
unsigned char ujRet = 0;
@@ -4349,10 +3751,6 @@ void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
}
- /* [Billy] 07/05/23 For CH7007 */
- if (pVBInfo->IF_DEF_CH7007 == 1) {
- }
-
if (pXGIHWDE->jChipType == XG27) {
if (pVBInfo->IF_DEF_LVDS == 1) {
if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
@@ -4389,12 +3787,6 @@ void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE,
}
}
- if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/23 For CH7007 */
- /* if (IsCH7007TVMode(pVBInfo) == 0) */
- {
- }
- }
-
if (pXGIHWDE->jChipType == XG27) {
if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
/* LVDS backlight off */
@@ -4419,20 +3811,9 @@ static void XGI_WaitDisply(struct vb_device_info *pVBInfo)
break;
}
-#if 0
-static void XGI_WaitDisplay(struct vb_device_info *pVBInfo)
-{
- while (!(inb(pVBInfo->P3da) & 0x01))
- ;
- while (inb(pVBInfo->P3da) & 0x01)
- ;
-}
-#endif
-
static void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
{
- if (!(pVBInfo->SetFlag & Win9xDOSMode))
- xgifb_reg_or(pVBInfo->Part1Port, 0x01, 0x40);
+ xgifb_reg_or(pVBInfo->Part1Port, 0x01, 0x40);
}
static void XGI_SaveCRT2Info(unsigned short ModeNo,
@@ -5027,11 +4408,6 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
tempcx = (pVBInfo->VGAVT - 1);
temp = tempcx & 0x00FF;
- if (pVBInfo->IF_DEF_CH7005 == 1) {
- if (pVBInfo->VBInfo & 0x0C)
- temp--;
- }
-
xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
tempbx = pVBInfo->VGAVDE - 1;
temp = tempbx & 0x00FF;
@@ -6177,27 +5553,24 @@ static struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
tempbx = pVBInfo->VDE;
}
- if (tempax < tempbx)
- return &EnlargeTap4Timing[0];
- else if (tempax == tempbx)
- return &NoScaleTap4Timing[0]; /* 1:1 */
+ if (tempax <= tempbx)
+ return &xgifb_tap4_timing[0];
else
- Tap4TimingPtr = NTSCTap4Timing; /* NTSC */
+ Tap4TimingPtr = xgifb_ntsc_525_tap4_timing; /* NTSC */
if (pVBInfo->TVInfo & SetPALTV)
Tap4TimingPtr = PALTap4Timing;
if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
- if (pVBInfo->TVInfo & SetYPbPrMode525i)
- Tap4TimingPtr = YPbPr525iTap4Timing;
- if (pVBInfo->TVInfo & SetYPbPrMode525p)
- Tap4TimingPtr = YPbPr525pTap4Timing;
+ if ((pVBInfo->TVInfo & SetYPbPrMode525i) ||
+ (pVBInfo->TVInfo & SetYPbPrMode525p))
+ Tap4TimingPtr = xgifb_ntsc_525_tap4_timing;
if (pVBInfo->TVInfo & SetYPbPrMode750p)
Tap4TimingPtr = YPbPr750pTap4Timing;
}
if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
- Tap4TimingPtr = HiTVTap4Timing;
+ Tap4TimingPtr = xgifb_tap4_timing;
i = 0;
while (Tap4TimingPtr[i].DE != 0xFFFF) {
@@ -6217,10 +5590,6 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
if (!(pVBInfo->VBType & VB_XGI301C))
return;
-#ifndef Tap4
- xgifb_reg_and(pVBInfo->Part2Port, 0x4E, 0xEB); /* Disable Tap4 */
-#else /* Tap4 Setting */
-
Tap4TimingPtr = XGI_GetTap4Ptr(0, pVBInfo); /* Set Horizontal Scaling */
for (i = 0x80, j = 0; i <= 0xBF; i++, j++)
xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
@@ -6242,7 +5611,6 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
else
/* Enable H.Scaling */
xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10);
-#endif
}
static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
@@ -6743,204 +6111,10 @@ void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
}
-static void XGI_SetXG21LVDSPara(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char temp, Miscdata;
- unsigned short xres, yres, modeflag, resindex, lvdstableindex;
- unsigned short LVDSHT, LVDSHBS, LVDSHRS, LVDSHRE, LVDSHBE;
- unsigned short LVDSVT, LVDSVBS, LVDSVRS, LVDSVRE, LVDSVBE;
- unsigned short value;
-
- lvdstableindex = XGI_GetLVDSOEMTableIndex(pVBInfo);
-
- temp = (unsigned char) ((pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDS_Capability &
- (LCDPolarity << 8)) >> 8);
- temp &= LCDPolarity;
- Miscdata = (unsigned char) inb(pVBInfo->P3cc);
-
- outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
-
- temp = (unsigned char) (pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDS_Capability & LCDPolarity);
- /* SR35[7] FP VSync polarity */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80);
- /* SR30[5] FP HSync polarity */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1);
-
- XGI_SetXG21FPBits(pVBInfo);
- resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
- if (ModeNo <= 0x13) {
- xres = pVBInfo->StResInfo[resindex].HTotal;
- yres = pVBInfo->StResInfo[resindex].VTotal;
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- if (!(modeflag & Charx8Dot))
- xres = xres * 8 / 9;
-
- LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
-
- LVDSHBS = xres + (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE
- - xres) / 2;
- if ((ModeNo <= 0x13) && (modeflag & HalfDCLK))
- LVDSHBS -= xres / 4;
-
- if (LVDSHBS > LVDSHT)
- LVDSHBS -= LVDSHT;
-
- LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP;
- if (LVDSHRS > LVDSHT)
- LVDSHRS -= LVDSHT;
-
- LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC;
- if (LVDSHRE > LVDSHT)
- LVDSHRE -= LVDSHT;
-
- LVDSHBE = LVDSHBS + LVDSHT
- - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE;
-
- LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
-
- LVDSVBS = yres + (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE
- - yres) / 2;
- if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
- LVDSVBS += yres / 2;
-
- if (LVDSVBS > LVDSVT)
- LVDSVBS -= LVDSVT;
-
- LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP;
- if (LVDSVRS > LVDSVT)
- LVDSVRS -= LVDSVT;
-
- LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC;
- if (LVDSVRE > LVDSVT)
- LVDSVRE -= LVDSVT;
-
- LVDSVBE = LVDSVBS + LVDSVT
- - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
-
- temp = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
- xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
-
- if (!(modeflag & Charx8Dot))
- xgifb_reg_or(pVBInfo->P3c4, 0x1, 0x1);
-
- /* HT SR0B[1:0] CR00 */
- value = (LVDSHT >> 3) - 5;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
- xgifb_reg_set(pVBInfo->P3d4, 0x0, (value & 0xFF));
-
- /* HBS SR0B[5:4] CR02 */
- value = (LVDSHBS >> 3) - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
- xgifb_reg_set(pVBInfo->P3d4, 0x2, (value & 0xFF));
-
- /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
- value = (LVDSHBE >> 3) - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
-
- /* HRS SR0B[7:6] CR04 */
- value = (LVDSHRS >> 3) + 2;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
- xgifb_reg_set(pVBInfo->P3d4, 0x4, (value & 0xFF));
-
- /* Panel HRS SR2F[1:0] SR2E[7:0] */
- value--;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, (value & 0xFF));
-
- /* HRE SR0C[2] CR05[4:0] */
- value = (LVDSHRE >> 3) + 2;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
-
- /* Panel HRE SR2F[7:2] */
- value--;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
-
- /* VT SR0A[0] CR07[5][0] CR06 */
- value = LVDSVT - 2;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
- xgifb_reg_set(pVBInfo->P3d4, 0x06, (value & 0xFF));
-
- /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
- value = LVDSVBS - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
- xgifb_reg_set(pVBInfo->P3d4, 0x15, (value & 0xFF));
-
- /* VBE SR0A[4] CR16 */
- value = LVDSVBE - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
- xgifb_reg_set(pVBInfo->P3d4, 0x16, (value & 0xFF));
-
- /* VRS SR0A[3] CR7[7][2] CR10 */
- value = LVDSVRS - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
- xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
-
- /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0x03, (value & 0x600) >> 9);
- xgifb_reg_set(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
-
- /* VRE SR0A[5] CR11[3:0] */
- value = LVDSVRE - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
-
- /* Panel VRE SR3F[7:2] *//* SR3F[7] has to be 0, h/w bug */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, (value << 2) & 0x7C);
-
- for (temp = 0, value = 0; temp < 3; temp++) {
-
- xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2B,
- pVBInfo->XG21_LVDSCapList[lvdstableindex].
- VCLKData1);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2C,
- pVBInfo->XG21_LVDSCapList[lvdstableindex].
- VCLKData2);
- value += 0x10;
- }
-
- if (!(modeflag & Charx8Dot)) {
- inb(pVBInfo->P3da); /* reset 3da */
- outb(0x13, pVBInfo->P3c0); /* set index */
- /* set data, panning = 0, shift left 1 dot*/
- outb(0x00, pVBInfo->P3c0);
-
- inb(pVBInfo->P3da); /* Enable Attribute */
- outb(0x20, pVBInfo->P3c0);
-
- inb(pVBInfo->P3da); /* reset 3da */
- }
-
-}
-
-/* no shadow case */
-static void XGI_SetXG27LVDSPara(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
+static void xgifb_set_lvds(int chip_id,
+ unsigned short ModeNo,
+ unsigned short ModeIdIndex,
+ struct vb_device_info *pVBInfo)
{
unsigned char temp, Miscdata;
unsigned short xres, yres, modeflag, resindex, lvdstableindex;
@@ -6964,7 +6138,11 @@ static void XGI_SetXG27LVDSPara(unsigned short ModeNo,
/* SR30[5] FP HSync polarity */
xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1);
- XGI_SetXG27FPBits(pVBInfo);
+ if (chip_id == XG27)
+ XGI_SetXG27FPBits(pVBInfo);
+ else
+ XGI_SetXG21FPBits(pVBInfo);
+
resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
if (ModeNo <= 0x13) {
xres = pVBInfo->StResInfo[resindex].HTotal;
@@ -7091,9 +6269,18 @@ static void XGI_SetXG27LVDSPara(unsigned short ModeNo,
xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
- /* Panel VRS SR35[2:0] SR34[7:0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, (value & 0x700) >> 8);
- xgifb_reg_set(pVBInfo->P3c4, 0x34, value & 0xFF);
+ if (chip_id == XG27) {
+ /* Panel VRS SR35[2:0] SR34[7:0] */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07,
+ (value & 0x700) >> 8);
+ xgifb_reg_set(pVBInfo->P3c4, 0x34, value & 0xFF);
+ } else {
+ /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0x03,
+ (value & 0x600) >> 9);
+ xgifb_reg_set(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
+ xgifb_reg_and_or(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
+ }
/* VRE SR0A[5] CR11[3:0] */
value = LVDSVRE - 1;
@@ -7101,7 +6288,13 @@ static void XGI_SetXG27LVDSPara(unsigned short ModeNo,
xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
/* Panel VRE SR3F[7:2] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, (value << 2) & 0xFC);
+ if (chip_id == XG27)
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
+ (value << 2) & 0xFC);
+ else
+ /* SR3F[7] has to be 0, h/w bug */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
+ (value << 2) & 0x7C);
for (temp = 0, value = 0; temp < 3; temp++) {
@@ -7210,30 +6403,6 @@ void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
{
unsigned short tempah = 0;
- if (pVBInfo->SetFlag == Win9xDOSMode)
- return;
-
- /*
- if (CH7017) {
- if (!(pVBInfo->VBInfo &
- (SetCRT2ToLCD | SetCRT2toLCDA)) ||
- (XGI_DisableChISLCD(pVBInfo))) {
- if (!XGI_IsLCDON(pVBInfo)) {
- if (DISCHARGE) {
- tempbx = XGINew_GetCH7005(0x61);
- // first time we power up
- if (tempbx < 0x01)
- // and disable power sequence
- XGINew_SetCH7005(0x0066);
- else
- // leave VDD on - disable power
- XGINew_SetCH7005(0x5f66);
- }
- }
- }
- }
- */
-
if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
| VB_XGI302LV | VB_XGI301C)) {
tempah = 0x3F;
@@ -7713,28 +6882,16 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
case 0x02:
case 0x05:
case 0x0D:
- filterPtr = PALMYFilter1;
- break;
-
case 0x03:
- filterPtr = PALNYFilter1;
+ filterPtr = xgifb_palmn_yfilter1;
break;
case 0x08:
case 0x0C:
- filterPtr = NTSCYFilter2;
- break;
-
case 0x0A:
- filterPtr = PALMYFilter2;
- break;
-
case 0x0B:
- filterPtr = PALNYFilter2;
- break;
-
case 0x09:
- filterPtr = PALYFilter2;
+ filterPtr = xgifb_yfilter2;
break;
default:
@@ -7783,9 +6940,6 @@ static void XGI_OEM310Setting(unsigned short ModeNo,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- if (pVBInfo->SetFlag & Win9xDOSMode)
- return;
-
/* GetPart1IO(); */
XGI_SetDelayComp(pVBInfo);
@@ -8034,13 +7188,6 @@ static void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension,
}
-void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx;
- tempbx = 0;
-}
-
void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
@@ -8138,13 +7285,6 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
else
modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- if (pVBInfo->IF_DEF_CH7005 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (modeflag & HalfDCLK)
- return 0;
- }
- }
-
if (ModeNo < 0x14)
return 0xFFFF;
@@ -8159,11 +7299,6 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
index--;
if (pVBInfo->SetFlag & ProgrammingCRT2) {
- if (pVBInfo->IF_DEF_CH7005 == 1) {
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- index = 0;
- }
-
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
if (pVBInfo->IF_DEF_LVDS == 0) {
if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
@@ -8402,16 +7537,6 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
{
unsigned short tempah;
- if (pVBInfo->SetFlag == Win9xDOSMode) {
- if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
- | VB_XGI302LV | VB_XGI301C)) {
- XGI_DisplayOn(HwDeviceExtension, pVBInfo);
- return;
- } else
- /* LVDS or CH7017 */
- return;
- }
-
if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
| VB_XGI302LV | VB_XGI301C)) {
if (!(pVBInfo->SetFlag & DisableChA)) {
@@ -8512,11 +7637,6 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
/* EnablePart4_1F */
xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah);
- if (pVBInfo->SetFlag & Win9xDOSMode) {
- XGI_DisplayOn(HwDeviceExtension, pVBInfo);
- return;
- }
-
if (!(pVBInfo->SetFlag & DisableChA)) {
XGI_VBLongWait(pVBInfo);
if (!(pVBInfo->SetFlag & GatingCRT)) {
@@ -8630,21 +7750,12 @@ static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
RefreshRateTableIndex);
- if (HwDeviceExtension->jChipType == XG27)
- XGI_SetXG27LCD(pVBInfo, RefreshRateTableIndex,
- ModeNo);
- else
- XGI_SetXG21LCD(pVBInfo, RefreshRateTableIndex,
- ModeNo);
+ xgifb_set_lcd(HwDeviceExtension->jChipType,
+ pVBInfo, RefreshRateTableIndex, ModeNo);
- if (pVBInfo->IF_DEF_LVDS == 1) {
- if (HwDeviceExtension->jChipType == XG27)
- XGI_SetXG27LVDSPara(ModeNo,
- ModeIdIndex, pVBInfo);
- else
- XGI_SetXG21LVDSPara(ModeNo,
- ModeIdIndex, pVBInfo);
- }
+ if (pVBInfo->IF_DEF_LVDS == 1)
+ xgifb_set_lvds(HwDeviceExtension->jChipType,
+ ModeNo, ModeIdIndex, pVBInfo);
/* P. ON */
/* xgifb_reg_or(pVBInfo->P3d4, 0x48, 0x20); */
}
@@ -8672,14 +7783,7 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
pVBInfo->IF_DEF_LVDS = 0;
- pVBInfo->IF_DEF_CH7005 = 0;
pVBInfo->IF_DEF_LCDA = 1;
- pVBInfo->IF_DEF_CH7017 = 0;
- pVBInfo->IF_DEF_CH7007 = 0; /* [Billy] 2007/05/14 */
- pVBInfo->IF_DEF_VideoCapture = 0;
- pVBInfo->IF_DEF_ScaleLCD = 0;
- pVBInfo->IF_DEF_OEMUtil = 0;
- pVBInfo->IF_DEF_PWD = 0;
if (HwDeviceExtension->jChipType >= XG20) { /* kuku 2004/06/25 */
pVBInfo->IF_DEF_YPbPr = 0;
@@ -8749,7 +7853,6 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo);
XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo);
XGI_DisableBridge(HwDeviceExtension, pVBInfo);
- /* XGI_OpenCRTC(HwDeviceExtension, pVBInfo); */
if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) {
XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
@@ -8809,8 +7912,7 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
}
pVBInfo->SetFlag = 0;
- if (pVBInfo->IF_DEF_CH7007 != 1)
- pVBInfo->VBInfo = DisableCRT2Display;
+ pVBInfo->VBInfo = DisableCRT2Display;
XGI_DisplayOff(HwDeviceExtension, pVBInfo);
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index 377d27c..f9ade6f 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -1,16 +1,6 @@
#ifndef _VB_STRUCT_
#define _VB_STRUCT_
-#ifdef _INITNEW_
-#define EXTERN
-#else
-#define EXTERN extern
-#endif
-
-struct XGI_PanelDelayTblStruct {
- unsigned char timer[2];
-};
-
struct XGI_LCDDataStruct {
unsigned short RVBHCMAX;
unsigned short RVBHCFACT;
@@ -45,24 +35,6 @@ struct XGI_TVDataStruct {
unsigned char RY4COE;
};
-struct XGI_LVDSDataStruct {
- unsigned short VGAHT;
- unsigned short VGAVT;
- unsigned short LCDHT;
- unsigned short LCDVT;
-};
-
-struct XGI_LVDSDesStruct {
- unsigned short LCDHDES;
- unsigned short LCDVDES;
-};
-
-struct XGI_LVDSCRT1DataStruct {
- unsigned char CR[15];
-};
-
-/*add for LCDA*/
-
struct XGI_StStruct {
unsigned char St_ModeID;
unsigned short St_ModeFlag;
@@ -146,10 +118,6 @@ struct XGI_ModeResInfoStruct {
unsigned char YChar;
};
-struct XGI_LCDNBDesStruct {
- unsigned char NB[12];
-};
-
/*add for new UNIVGABIOS*/
struct XGI_LCDDesStruct {
unsigned short LCDHDES;
@@ -165,12 +133,6 @@ struct XGI_LCDDataTablStruct {
unsigned short DATAPTR;
};
-struct XGI_TVTablDataStruct {
- unsigned short MASK;
- unsigned short CAP;
- unsigned short DATAPTR;
-};
-
struct XGI330_LCDDataDesStruct {
unsigned short LCDHDES;
unsigned short LCDHRS;
@@ -246,22 +208,10 @@ struct XGI_TimingVStruct {
unsigned char data[7];
};
-struct XGI_CH7007TV_TimingHStruct {
- unsigned char data[10];
-};
-
-struct XGI_CH7007TV_TimingVStruct {
- unsigned char data[10];
-};
-
struct XGI_XG21CRT1Struct {
unsigned char ModeID, CR02, CR03, CR15, CR16;
};
-struct XGI330_CHTVRegDataStruct {
- unsigned char Reg[16];
-};
-
struct XGI330_LCDCapStruct {
unsigned char LCD_ID;
unsigned short LCD_Capability;
@@ -324,18 +274,6 @@ struct XGI301C_Tap4TimingStruct {
unsigned char Reg[64]; /* C0-FF */
};
-struct XGI_New_StandTableStruct {
- unsigned char CRT_COLS;
- unsigned char ROWS;
- unsigned char CHAR_HEIGHT;
- unsigned short CRT_LEN;
- unsigned char SR[4];
- unsigned char MISC;
- unsigned char CRTC[0x19];
- unsigned char ATTR[0x14];
- unsigned char GRC[9];
-};
-
struct vb_device_info {
unsigned char ISXPDOS;
unsigned long P3c4, P3d4, P3c0, P3ce, P3c2, P3cc;
@@ -350,12 +288,10 @@ struct vb_device_info {
unsigned short ModeType;
/* ,IF_DEF_FSTN; add for dstn */
unsigned short IF_DEF_LVDS, IF_DEF_TRUMPION, IF_DEF_DSTN;
- unsigned short IF_DEF_CRT2Monitor, IF_DEF_VideoCapture;
- unsigned short IF_DEF_LCDA, IF_DEF_CH7017, IF_DEF_YPbPr,
- IF_DEF_ScaleLCD, IF_DEF_OEMUtil, IF_DEF_PWD;
+ unsigned short IF_DEF_CRT2Monitor;
+ unsigned short IF_DEF_LCDA, IF_DEF_YPbPr;
unsigned short IF_DEF_ExpLink;
- unsigned short IF_DEF_CH7005, IF_DEF_HiVision;
- unsigned short IF_DEF_CH7007; /* Billy 2007/05/03 */
+ unsigned short IF_DEF_HiVision;
unsigned short LCDResInfo, LCDTypeInfo, VBType;/*301b*/
unsigned short VBInfo, TVInfo, LCDInfo, Set_VGAType;
unsigned short VBExtInfo;/*301lv*/
@@ -364,7 +300,7 @@ struct vb_device_info {
unsigned short SelectCRT2Rate;
unsigned char *ROMAddr;
- unsigned char *FBAddr;
+ void __iomem *FBAddr;
unsigned long BaseAddr;
unsigned long RelIO;
@@ -420,10 +356,6 @@ struct vb_device_info {
unsigned char *XGI_TVDelayList;
unsigned char *XGI_TVDelayList2;
- unsigned char *CHTVVCLKUNTSC;
- unsigned char *CHTVVCLKONTSC;
- unsigned char *CHTVVCLKUPAL;
- unsigned char *CHTVVCLKOPAL;
unsigned char *NTSCTiming;
unsigned char *PALTiming;
unsigned char *HiTVExtTiming;
@@ -460,23 +392,10 @@ struct vb_device_info {
struct XGI_StResInfoStruct *StResInfo;
struct XGI_ModeResInfoStruct *ModeResInfo;
struct XGI_XG21CRT1Struct *UpdateCRT1;
-}; /* _struct vb_device_info */
+ int ram_type;
+ int ram_channel;
+ int ram_bus;
+}; /* _struct vb_device_info */
-struct TimingInfo {
- unsigned short Horizontal_ACTIVE;
- unsigned short Horizontal_FP;
- unsigned short Horizontal_SYNC;
- unsigned short Horizontal_BP;
- unsigned short Vertical_ACTIVE;
- unsigned short Vertical_FP;
- unsigned short Vertical_SYNC;
- unsigned short Vertical_BP;
- double DCLK;
- unsigned char FrameRate;
- unsigned char Interlace;
- unsigned short Margin;
-};
-
-#define _VB_STRUCT_
#endif /* _VB_STRUCT_ */
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index d10de48..b81ac77 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -1,5 +1,3 @@
-#define Tap4
-
/* yilin modify for xgi20 */
static struct XGI_MCLKDataStruct XGI340New_MCLKData[] = {
{0x16, 0x01, 0x01, 166},
@@ -109,62 +107,12 @@ static unsigned char XGI340_CR6B[8][4] = {
{0x00, 0x00, 0x00, 0x00}
};
-static unsigned char XGI340_CR6E[8][4] = {
- {0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00},
- {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 unsigned char XGI340_CR6E[8][4];
+
+static unsigned char XGI340_CR6F[8][32];
+
+static unsigned char XGI340_CR89[8][2];
-static unsigned char XGI340_CR6F[8][32] = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 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 unsigned char XGI340_CR89[8][2] = {
- {0x00, 0x00},
- {0x00, 0x00},
- {0x00, 0x00},
- {0x00, 0x00},
- {0x00, 0x00},
- {0x00, 0x00},
- {0x00, 0x00},
- {0x00, 0x00}
-};
/* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
static unsigned char XGI340_AGPReg[12] = {
0x28, 0x23, 0x00, 0x20, 0x00, 0x20,
@@ -173,41 +121,10 @@ static unsigned char XGI340_AGPReg[12] = {
static unsigned char XGI340_SR16[4] = {0x03, 0x83, 0x03, 0x83};
-#if 0
-static unsigned char XGI330_SR15_1[8][8] = {
- {0x0, 0x0, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00},
- {0x5, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00},
- {0xba, 0xba, 0xba, 0xba, 0xBA, 0xBA, 0x00, 0x00},
- {0x55, 0x57, 0x57, 0xAB, 0xAB, 0xAB, 0x00, 0x00},
- {0x60, 0x34, 0x34, 0x34, 0x34, 0x34, 0x00, 0x00},
- {0x0, 0x80, 0x80, 0x80, 0x83, 0x83, 0x00, 0x00},
- {0x50, 0x50, 0x50, 0x3C, 0x3C, 0x3C, 0x00, 0x00},
- {0x0, 0xa5, 0xfb, 0xf6, 0xF6, 0xF6, 0x00, 0x00}
-};
-
-static unsigned char XGI330_cr40_1[15][8] = {
- {0x66, 0x40, 0x40, 0x28, 0x24, 0x24, 0x00, 0x00},
- {0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00},
- {0x00, 0xf0, 0xf0, 0xf0, 0xF0, 0xF0, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x88, 0x88, 0x88, 0xAA, 0xAC, 0xAC, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x00, 0xA2, 0x00, 0x00, 0xA2, 0xA2, 0x00, 0x00},
-};
-#endif
-
-static unsigned char XGI330_sr25[] = {0x00, 0x0};
+static unsigned char XGI330_sr25[2];
static unsigned char XGI330_sr31 = 0xc0;
static unsigned char XGI330_sr32 = 0x11;
-static unsigned char XGI330_SR33 = 0x00;
+static unsigned char XGI330_SR33;
static unsigned char XG40_CRCF = 0x13;
static unsigned char XG40_DRAMTypeDefinition = 0xFF ;
@@ -816,13 +733,9 @@ static struct XGI_StandTableStruct XGI330_StandTable[] = {
}
};
-static struct XGI_TimingHStruct XGI_TimingH[] = {
- { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
-};
+static struct XGI_TimingHStruct XGI_TimingH[1];
-static struct XGI_TimingVStruct XGI_TimingV[] = {
- { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
-};
+static struct XGI_TimingVStruct XGI_TimingV[1];
static struct XGI_XG21CRT1Struct XGI_UpdateCRT1Table[] = {
{0x01, 0x27, 0x91, 0x8f, 0xc0}, /* 00 */
@@ -1007,112 +920,6 @@ static struct XGI_CRT1TableStruct XGI_CRT1Table[] = {
0x03, 0xDE, 0xC0, 0x84, 0xBF, 0x04, 0x90} } /* 0x47 */
};
-#if 0
-static struct XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
- /* Index: 000h, 001h, 002h, 004h, 003h, 005h, 006h, 007h,
- 008h, 015h, 01Fh, 00Ch, 00Dh, 00Eh, 00Fh, 010h */
- /* 00 (640x200,640x400) */
- { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } },
- /* 01 (640x350) */
- { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } },
- /* 02 (720x400) */
- { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } },
- /* 03 (720x350) */
- { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } },
- /* 04 (640x480) ;;5/6/02 */
- { {0x6A, 0x77, 0xBB, 0x6E, 0x84, 0x2E, 0x02, 0x5A,
- 0x04, 0x00, 0x80, 0x20, 0x7E, 0x80, 0x97, 0x00 } },
- /* 05 (800x600) ;;1/12/02 */
- { {0xCF, 0x77, 0xB7, 0xC8, 0x84, 0x3B, 0x02, 0x5A,
- 0x04, 0x00, 0x80, 0x19, 0x88, 0xAE, 0xA3, 0x00 } },
- /* 06 (1024x768) ;;5/6/02 */
- { {0xEE, 0x77, 0xBB, 0x66, 0x87, 0x32, 0x01, 0x5A,
- 0x04, 0x00, 0x80, 0x1B, 0xD4, 0x2F, 0x6F, 0x00 } }
-};
-
-static struct XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[] = {
- /* Index: 000h, 001h, 002h, 004h, 003h, 005h, 006h, 007h,
- 008h, 015h, 01Fh, 00Ch, 00Dh, 00Eh, 00Fh, 010h */
- /* 00 (640x200,640x400) */
- { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00, 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 01 (640x350) */
- { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00 , 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 02 (720x400) */
- { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00 , 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 03 (720x350) */
- { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00 , 0x50,
- 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 04 (640x480) ;;5/6/02 */
- { {0x69, 0x77, 0xBB, 0x6E, 0x84, 0x1E, 0x00 , 0x5A,
- 0x04, 0x00, 0x80, 0x25, 0x1A, 0x80, 0x26, 0x00} },
- /* 05 (800x600) ;;5/6/02 */
- { {0xCE, 0x77, 0xB7, 0xB6, 0x83, 0x2C, 0x02 , 0x5A,
- 0x04, 0x00, 0x80, 0x1C, 0x00, 0x82, 0x97, 0x00} },
- /* 06 (1024x768) ;;5/6/02 */
- { {0xED, 0x77, 0xBB, 0x66, 0x8C, 0x21, 0x02 , 0x5A,
- 0x04, 0x00, 0x80, 0x1F, 0xA0, 0x7E, 0x73, 0x00} }
-};
-
-static struct XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[] = {
- /* Index: 000h, 001h, 002h, 004h, 003h, 005h, 006h, 007h,
- 008h, 015h, 01Fh, 00Ch, 00Dh, 00Eh, 00Fh, 010h */
- /* ; 00 (640x200,640x400) */
- { {0x41, 0x7F, 0xB7, 0x34, 0xAD, 0x50, 0x34, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* ; 01 (640x350) */
- { {0x41, 0x7F, 0xB7, 0x80, 0x85, 0x50, 0x00, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* ; 02 (720x400) */
- { {0x41, 0x7F, 0xB7, 0x34, 0xAD, 0x50, 0x34, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* ; 03 (720x350) */
- { {0x41, 0x7F, 0xB7, 0x12, 0x85, 0x50, 0x00, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* ; 04 (640x480) */
- { {0x61, 0x7F, 0xB7, 0x99, 0x84, 0x35, 0x04, 0x5A,
- 0x05, 0x00, 0x80, 0x26, 0x2A, 0x55, 0x5D, 0x00} },
- /* ; 05 (800x600) ;;1/12/02 */
- { {0xC3, 0x7F, 0xB7, 0x7A, 0x84, 0x40, 0x02, 0x5A,
- 0x05, 0x00, 0x80, 0x1F, 0x84, 0x3D, 0x28, 0x00} },
- /* ; 06 (1024x768) ;;1/12/02 */
- { {0xE5, 0x7F, 0xB7, 0x1D, 0xA7, 0x3E, 0x04, 0x5A,
- 0x05, 0x00, 0x80, 0x20, 0x3E, 0xE4, 0x22, 0x00} }
-};
-
-static struct XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[] = {
- /* Index: 000, 0x01, 0x02, 0x04, 0x03, 0x05, 0x06, 0x07,
- 0x08, 0x15, 0x1F, 0x0C, 0x0D, 0x0E, 0x0F, 0x10h */
- /* 00 (640x200,640x400) */
- { {0x41, 0x7F, 0xB7, 0x36, 0xAD, 0x50, 0x34, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 01 (640x350) */
- { {0x41, 0x7F, 0xB7, 0x86, 0x85, 0x50, 0x00, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 02 (720x400) */
- { {0x41, 0x7F, 0xB7, 0x36, 0xAD, 0x50, 0x34, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 03 (720x350) */
- { {0x41, 0x7F, 0xB7, 0x86, 0x85, 0x50, 0x00, 0x83,
- 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} },
- /* 04 (640x480) */
- { {0x61, 0x7F, 0xB7, 0x99, 0x84, 0x35, 0x04, 0x5A,
- 0x05, 0x00, 0x80, 0x26, 0x2A, 0x55, 0x5D, 0x00} },
- /* 05 (800x600) ;;1/12/02 */
- { {0xC1, 0x7F, 0xB7, 0x4D, 0x8C, 0x1E, 0x31, 0x5A,
- 0x05, 0x00, 0x80, 0x26, 0x78, 0x19, 0x34, 0x00} },
- /* 06 (1024x768) ;;1/12/02 */
- { {0xE4, 0x7F, 0xB7, 0x1E, 0xAF, 0x29, 0x37, 0x5A,
- 0x05, 0x00, 0x80, 0x25, 0x8C, 0xB2, 0x2A, 0x00} }
-};
-#endif
-
static unsigned char XGI_CH7017LV1024x768[] = {
0x60, 0x02, 0x00, 0x07, 0x40, 0xED,
0xA3, 0xC8, 0xC7, 0xAC, 0xE0, 0x02};
@@ -1151,16 +958,6 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[] = {
{1, 1, 1344, 806, 1344, 806}
};
-/*struct XGI330_LCDDataStruct XGI_St2LCD1024x768Data[] = {
- {62, 25, 800, 546, 1344, 806},
- {32, 15, 930, 546, 1344, 806},
- {62, 25, 800, 546, 1344, 806},
- {104, 45, 945, 496, 1344, 806},
- {62, 25, 800, 546, 1344, 806},
- {31, 18, 1008, 624, 1344, 806},
- {1, 1, 1344, 806, 1344, 806}
-};*/
-
static struct XGI330_LCDDataStruct XGI_CetLCD1024x768Data[] = {
{1, 1, 1344, 806, 1344, 806}, /* ; 00 (320x200,320x400,
640x200,640x400) */
@@ -1194,19 +991,6 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[] = {
{1, 1, 1688, 1066, 1688, 1066}
};
-#if 0
-static struct XGI330_LCDDataStruct XGI_St2LCD1280x1024Data[] = {
- {22, 5, 800, 510, 1650, 1088},
- {22, 5, 800, 510, 1650, 1088},
- {176, 45, 900, 510, 1650, 1088},
- {176, 45, 900, 510, 1650, 1088},
- {22, 5, 800, 510, 1650, 1088},
- {13, 5, 1024, 675, 1560, 1152},
- {16, 9, 1266, 804, 1688, 1072},
- {1, 1, 1688, 1066, 1688, 1066}
-};
-#endif
-
static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[] = {
{1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400,
640x200,640x400) */
@@ -1220,21 +1004,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[] = {
{1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */
};
-static struct XGI330_LCDDataStruct XGI_StLCD1400x1050Data[] = {
- {211, 100, 2100, 408, 1688, 1066}, /* 00 (320x200,320x400,
- 640x200,640x400) */
- {211, 64, 1536, 358, 1688, 1066}, /* 01 (320x350,640x350) */
- {211, 100, 2100, 408, 1688, 1066}, /* 02 (360x400,720x400) */
- {211, 64, 1536, 358, 1688, 1066}, /* 03 (720x350) */
- {211, 48, 840, 488, 1688, 1066}, /* 04 (640x480x60Hz) */
- {211, 72, 1008, 609, 1688, 1066}, /* 05 (800x600x60Hz) */
- {211, 128, 1400, 776, 1688, 1066}, /* 06 (1024x768x60Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz
- w/o Scaling) */
- {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */
-};
-
-static struct XGI330_LCDDataStruct XGI_ExtLCD1400x1050Data[] = {
+static struct XGI330_LCDDataStruct xgifb_lcd_1400x1050[] = {
{211, 100, 2100, 408, 1688, 1066}, /* 00 (320x200,320x400,
640x200,640x400) */
{211, 64, 1536, 358, 1688, 1066}, /* 01 (320x350,640x350) */
@@ -1315,19 +1085,6 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[] = {
{1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */
};
-#if 0
-static struct XGI330_LCDDataStruct XGI_StLCD1024x768x75Data[] = {
- {42, 25, 1536, 419, 1344, 806}, /* ; 00 (320x200,320x400,
- 640x200,640x400) */
- {48, 25, 1536, 369, 1344, 806}, /* ; 01 (320x350,640x350) */
- {42, 25, 1536, 419, 1344, 806}, /* ; 02 (360x400,720x400) */
- {48, 25, 1536, 369, 1344, 806}, /* ; 03 (720x350) */
- {8, 5, 1312, 500, 1312, 800}, /* ; 04 (640x480x75Hz) */
- {41, 25, 1024, 625, 1312, 800}, /* ; 05 (800x600x75Hz) */
- {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */
-};
-#endif
-
static struct XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[] = {
{1, 1, 1312, 800, 1312, 800}, /* ; 00 (320x200,320x400,
640x200,640x400) */
@@ -1339,19 +1096,7 @@ static struct XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[] = {
{1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */
};
-static struct XGI330_LCDDataStruct XGI_ExtLCD1280x1024x75Data[] = {
- {211, 60, 1024, 501, 1688, 1066}, /* ; 00 (320x200,320x400,
- 640x200,640x400) */
- {211, 60, 1024, 508, 1688, 1066}, /* ; 01 (320x350,640x350) */
- {211, 60, 1024, 501, 1688, 1066}, /* ; 02 (360x400,720x400) */
- {211, 60, 1024, 508, 1688, 1066}, /* ; 03 (720x350) */
- {211, 45, 768, 498, 1688, 1066}, /* ; 04 (640x480x75Hz) */
- {211, 75, 1024, 625, 1688, 1066}, /* ; 05 (800x600x75Hz) */
- {211, 120, 1280, 798, 1688, 1066}, /* ; 06 (1024x768x75Hz) */
- {1, 1, 1688, 1066, 1688, 1066} /* ; 07 (1280x1024x75Hz) */
-};
-
-static struct XGI330_LCDDataStruct XGI_StLCD1280x1024x75Data[] = {
+static struct XGI330_LCDDataStruct xgifb_lcd_1280x1024x75[] = {
{211, 60, 1024, 501, 1688, 1066}, /* ; 00 (320x200,320x400,
640x200,640x400) */
{211, 60, 1024, 508, 1688, 1066}, /* ; 01 (320x350,640x350) */
@@ -1487,7 +1232,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024Data[] = {
{9, 1337, 1065, 1024} /* 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1400x1050Data[] = {
+static struct XGI330_LCDDataDesStruct xgifb_lcddldes_1400x1050[] = {
{18, 1464, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
{18, 1464, 0, 1051}, /* 01 (320x350,640x350) */
{18, 1464, 0, 1051}, /* 02 (360x400,720x400) */
@@ -1499,31 +1244,7 @@ static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1400x1050Data[] = {
{18, 1464, 0, 1051} /* 08 (1400x1050x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1400x1050Data[] = {
- {18, 1464, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
- {18, 1464, 0, 1051}, /* 01 (320x350,640x350) */
- {18, 1464, 0, 1051}, /* 02 (360x400,720x400) */
- {18, 1464, 0, 1051}, /* 03 (720x350) */
- {18, 1464, 0, 1051}, /* 04 (640x480x60Hz) */
- {18, 1464, 0, 1051}, /* 05 (800x600x60Hz) */
- {18, 1464, 0, 1051}, /* 06 (1024x768x60Hz) */
- {1646, 1406, 1053, 1038}, /* 07 (1280x1024x60Hz) */
- {18, 1464, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static struct XGI330_LCDDataDesStruct XGI_StLCDDes1400x1050Data[] = {
- {9, 1455, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
- {9, 1455, 0, 1051}, /* 01 (320x350,640x350) */
- {9, 1455, 0, 1051}, /* 02 (360x400,720x400) */
- {9, 1455, 0, 1051}, /* 03 (720x350) */
- {9, 1455, 0, 1051}, /* 04 (640x480x60Hz) */
- {9, 1455, 0, 1051}, /* 05 (800x600x60Hz) */
- {9, 1455, 0, 1051}, /* 06 (1024x768x60Hz) */
- {1637, 1397, 1053, 1038}, /* 07 (1280x1024x60Hz) */
- {9, 1455, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1400x1050Data[] = {
+static struct XGI330_LCDDataDesStruct xgifb_lcddes_1400x1050[] = {
{9, 1455, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
{9, 1455, 0, 1051}, /* 01 (320x350,640x350) */
{9, 1455, 0, 1051}, /* 02 (360x400,720x400) */
@@ -1624,17 +1345,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[] = {
};
/* ;;1024x768x75Hz */
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768x75Data[] = {
- {9, 1049, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1049, 0, 769}, /* ; 01 (320x350,640x350) */
- {9, 1049, 0, 769}, /* ; 02 (360x400,720x400) */
- {9, 1049, 0, 769}, /* ; 03 (720x350) */
- {9, 1049, 0, 769}, /* ; 04 (640x480x75Hz) */
- {9, 1049, 0, 769}, /* ; 05 (800x600x75Hz) */
- {9, 1049, 0, 769} /* ; 06 (1024x768x75Hz) */
-};
-
-static struct XGI330_LCDDataDesStruct XGI_StLCDDes1024x768x75Data[] = {
+static struct XGI330_LCDDataDesStruct xgifb_lcddes_1024x768x75[] = {
{9, 1049, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1049, 0, 769}, /* ; 01 (320x350,640x350) */
{9, 1049, 0, 769}, /* ; 02 (360x400,720x400) */
@@ -1656,18 +1367,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768x75Data[] = {
};
/* ;;1280x1024x75Hz */
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024x75Data[] = {
- {18, 1314, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {18, 1314, 0, 1025}, /* ; 01 (320x350,640x350) */
- {18, 1314, 0, 1025}, /* ; 02 (360x400,720x400) */
- {18, 1314, 0, 1025}, /* ; 03 (720x350) */
- {18, 1314, 0, 1025}, /* ; 04 (640x480x60Hz) */
- {18, 1314, 0, 1025}, /* ; 05 (800x600x60Hz) */
- {18, 1314, 0, 1025}, /* ; 06 (1024x768x60Hz) */
- {18, 1314, 0, 1025} /* ; 07 (1280x1024x60Hz) */
-};
-
-static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024x75Data[] = {
+static struct XGI330_LCDDataDesStruct xgifb_lcddldes_1280x1024x75[] = {
{18, 1314, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
{18, 1314, 0, 1025}, /* ; 01 (320x350,640x350) */
{18, 1314, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -1691,18 +1391,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
};
/* ;;1280x1024x75Hz */
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024x75Data[] = {
- {9, 1305, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1305, 0, 1025}, /* ; 01 (320x350,640x350) */
- {9, 1305, 0, 1025}, /* ; 02 (360x400,720x400) */
- {9, 1305, 0, 1025}, /* ; 03 (720x350) */
- {9, 1305, 0, 1025}, /* ; 04 (640x480x60Hz) */
- {9, 1305, 0, 1025}, /* ; 05 (800x600x60Hz) */
- {9, 1305, 0, 1025}, /* ; 06 (1024x768x60Hz) */
- {9, 1305, 0, 1025} /* ; 07 (1280x1024x60Hz) */
-};
-
-static struct XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024x75Data[] = {
+static struct XGI330_LCDDataDesStruct xgifb_lcddes_1280x1024x75[] = {
{9, 1305, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1305, 0, 1025}, /* ; 01 (320x350,640x350) */
{9, 1305, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -2041,63 +1730,6 @@ static unsigned char XGI330_Ren750pGroup3[] = {
0x18, 0x1D, 0x23, 0x28, 0x4C, 0xAA, 0x01
};
-#if 0
-static struct XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[] = {
- { {0x00, 0x00} },
- { {0x00, 0x00} },
- { {0x00, 0x00} },
- { {0x00, 0x00} },
- { {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 struct XGI330_LVDSDataStruct XGI330_LVDS320x480Data_1[] = {
- {848, 433, 400, 525},
- {848, 389, 400, 525},
- {848, 433, 400, 525},
- {848, 389, 400, 525},
- {848, 518, 400, 525},
- {1056, 628, 400, 525},
- {400, 525, 400, 525},
- {800, 449, 1000, 644},
- {800, 525, 1000, 635}
-};
-
-static struct XGI330_LVDSDataStruct XGI330_LVDS800x600Data_1[] = {
- {848, 433, 1060, 629},
- {848, 389, 1060, 629},
- {848, 433, 1060, 629},
- {848, 389, 1060, 629},
- {848, 518, 1060, 629},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {800, 449, 1000, 644},
- {800, 525, 1000, 635}
-};
-
-static struct XGI330_LVDSDataStruct XGI330_LVDS800x600Data_2[] = {
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {800, 449, 1000, 644},
- {800, 525, 1000, 635}
-};
-#endif
-
static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[] = {
{ 960, 438, 1344, 806}, /* 00 (320x200,320x400,640x200,640x400) */
{ 960, 388, 1344, 806}, /* 01 (320x350,640x350) */
@@ -2143,79 +1775,7 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[] = {
{800, 449, 1280, 801},
{800, 525, 1280, 813}
};
-/*
-struct XGI330_LVDSDataStruct XGI_LVDS1280x768Data_1[] = {
- {768, 438, 1408, 806},
- {768, 388, 1408, 806},
- {768, 438, 1408, 806},
- {768, 388, 1408, 806},
- {768, 518, 1408, 806},
- {928, 638, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806}
-};
-
-struct XGI330_LVDSDataStruct XGI_LVDS1280x768Data_2[] = {
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806}
-};
-
-struct XGI330_LVDSDataStruct XGI_LVDS1280x768NData_1[] = {
- {704, 438, 1344, 806},
- {704, 388, 1344, 806},
- {704, 438, 1344, 806},
- {704, 388, 1344, 806},
- {704, 518, 1344, 806},
- {864, 638, 1344, 806},
- {1088, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806}
-};
-struct XGI330_LVDSDataStruct XGI_LVDS1280x768NData_2[] = {
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806}
-};
-
-struct XGI330_LVDSDataStruct XGI_LVDS1280x768SData_1[] = {
- {1048, 438, 1688, 806},
- {1048, 388, 1688, 806},
- {1148, 438, 1688, 806},
- {1148, 388, 1688, 806},
- {1048, 518, 1688, 806},
- {1208, 638, 1688, 806},
- {1432, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806}
-};
-
-struct XGI330_LVDSDataStruct XGI_LVDS1280x768SData_2[] = {
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806},
- {1688, 806, 1688, 806}
-};
-*/
static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[] = {
{928, 416, 1688, 1066},
{928, 366, 1688, 1066},
@@ -2502,20 +2062,6 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = {
{0, 1328, 0, 771, 112, 6} /* ; 0A (1280x768x75Hz) */
};
-#if 0
-static struct XGI330_LVDSDataStruct XGI330_LVDS640x480Data_1[] = {
- { 800, 449, 800, 449},
- { 800, 449, 800, 449},
- { 800, 449, 800, 449},
- { 800, 449, 800, 449},
- { 800, 525, 800, 525},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628},
- {1056, 628, 1056, 628}
-};
-#endif
-
static struct XGI330_CHTVDataStruct XGI_CHTVUNTSCData[] = {
{ 840, 600, 840, 600},
{ 840, 600, 840, 600},
@@ -2805,68 +2351,6 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = {
{ {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* ; 05 (x1024) */
};
-#if 0
-static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UNTSC[] = {
- { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
- 0xe8, 0x84, 0x8f, 0x57, 0x20, 0x00, 0x01, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
- 0xd0, 0x82, 0x5d, 0x57, 0x00, 0x00, 0x01, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
- 0xe8, 0x84, 0x8f, 0x57, 0x20, 0x00, 0x01, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
- 0xd0, 0x82, 0x5d, 0x57, 0x00, 0x00, 0x01, 0x00 } },
- { {0x5d, 0x4f, 0x81, 0x53, 0x9c, 0x56, 0xba,
- 0x18, 0x84, 0xdf, 0x57, 0x00, 0x00, 0x01, 0x00 } },
- { {0x80, 0x63, 0x84, 0x6c, 0x17, 0xec, 0xf0,
- x90, 0x8c, 0x57, 0xed, 0x20, 0x00, 0x06, 0x01 } }
-};
-
-static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1ONTSC[] = {
- { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
- 0xc0, 0x84, 0x8f, 0x0c, 0x20, 0x00, 0x01, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
- 0xb0, 0x8d, 0x5d, 0x0c, 0x00, 0x00, 0x01, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
- 0xc0, 0x84, 0x8f, 0x0c, 0x20, 0x00, 0x01, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
- 0xb0, 0x8d, 0x5d, 0x0c, 0x00, 0x00, 0x01, 0x00 } },
- { {0x5d, 0x4f, 0x81, 0x56, 0x9c, 0x0b, 0x3e,
- 0xe8, 0x84, 0xdf, 0x0c, 0x00, 0x00, 0x01, 0x00 } },
- { {0x7d, 0x63, 0x81, 0x6a, 0x16, 0xba, 0xf0,
- x7f, 0x86, 0x57, 0xbb, 0x00, 0x00, 0x06, 0x01 } }
-};
-
-static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UPAL[] = {
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xf8, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } },
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } },
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xf8, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } },
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x55, 0x80, 0xec, 0xba,
- 0x50, 0x84, 0xdf, 0xed, 0x00, 0x00, 0x05, 0x00 } },
- { {0x70, 0x63, 0x94, 0x68, 0x8d, 0x42, 0xf1,
- xc8, 0x8c, 0x57, 0xe9, 0x20, 0x00, 0x05, 0x01 } }
-};
-
-static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1OPAL[] = {
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xf0, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } },
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } },
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xf0, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } },
- { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
- 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } },
- { {0x64, 0x4f, 0x88, 0x55, 0x80, 0x6f, 0xba,
- 0x20, 0x83, 0xdf, 0x70, 0x00, 0x00, 0x05, 0x00 } },
- { {0x73, 0x63, 0x97, 0x69, 0x8e, 0xec, 0xf0,
- x90, 0x8c, 0x57, 0xed, 0x20, 0x00, 0x05, 0x01 } }
-};
-#endif
-
/*add for new UNIVGABIOS*/
static struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = {
{Panel1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCD1024x768Data */
@@ -2918,33 +2402,18 @@ static struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] = {
{0xFF, 0x0000, 0x0000, 0}
};
-static struct XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[] = {
- {Panel1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDSCRT11024x768_1_H */
- {Panel1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDSCRT11024x768_2_H */
- {Panel1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDSCRT11280x1024_1_H */
- {Panel1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDSCRT11280x1024_2_H */
- {Panel1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDSCRT11400x1050_1_H */
- {Panel1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDSCRT11400x1050_2_H */
- {Panel1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDSCRT11600x1200_1_H */
- {Panel1024x768x75, 0x0018, 0x0000, 7}, /* XGI_LVDSCRT11024x768_1_Hx75 */
- {Panel1024x768x75, 0x0018, 0x0010, 8}, /* XGI_LVDSCRT11024x768_2_Hx75 */
- {Panel1280x1024x75, 0x0018, 0x0000, 9}, /*XGI_LVDSCRT11280x1024_1_Hx75*/
- {Panel1280x1024x75, 0x0018, 0x0010, 10},/*XGI_LVDSCRT11280x1024_2_Hx75*/
- {0xFF, 0x0000, 0x0000, 0}
-};
-
-static struct XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[] = {
- {Panel1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDSCRT11024x768_1_V */
- {Panel1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDSCRT11024x768_2_V */
- {Panel1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDSCRT11280x1024_1_V */
- {Panel1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDSCRT11280x1024_2_V */
- {Panel1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDSCRT11400x1050_1_V */
- {Panel1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDSCRT11400x1050_2_V */
- {Panel1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDSCRT11600x1200_1_V */
- {Panel1024x768x75, 0x0018, 0x0000, 7}, /* XGI_LVDSCRT11024x768_1_Vx75 */
- {Panel1024x768x75, 0x0018, 0x0010, 8}, /* XGI_LVDSCRT11024x768_2_Vx75 */
- {Panel1280x1024x75, 0x0018, 0x0000, 9}, /*XGI_LVDSCRT11280x1024_1_Vx75*/
- {Panel1280x1024x75, 0x0018, 0x0010, 10},/*XGI_LVDSCRT11280x1024_2_Vx75*/
+static struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1[] = {
+ {Panel1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDSCRT11024x768_1 */
+ {Panel1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDSCRT11024x768_2 */
+ {Panel1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDSCRT11280x1024_1 */
+ {Panel1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDSCRT11280x1024_2 */
+ {Panel1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDSCRT11400x1050_1 */
+ {Panel1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDSCRT11400x1050_2 */
+ {Panel1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDSCRT11600x1200_1 */
+ {Panel1024x768x75, 0x0018, 0x0000, 7}, /* XGI_LVDSCRT11024x768_1x75 */
+ {Panel1024x768x75, 0x0018, 0x0010, 8}, /* XGI_LVDSCRT11024x768_2x75 */
+ {Panel1280x1024x75, 0x0018, 0x0000, 9}, /*XGI_LVDSCRT11280x1024_1x75*/
+ {Panel1280x1024x75, 0x0018, 0x0010, 10},/*XGI_LVDSCRT11280x1024_2x75*/
{0xFF, 0x0000, 0x0000, 0}
};
@@ -3007,43 +2476,12 @@ static struct XGI330_TVDataTablStruct XGI_TVDataTable[] = {
{0xffff, 0x0000, 12} /* END */
};
-#if 0
-static unsigned short TVLenList[] = {
- LVDSCRT1Len_H,
- LVDSCRT1Len_V,
- LVDSDataLen,
- 0,
- TVDataLen,
- 0,
- 0,
- CHTVRegLen
-};
-#endif
-
-/* Chrontel 7017 TV CRT1 Timing List */
-static struct XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[] = {
- {0x0011, 0x0000, 0}, /* XGI_CHTVCRT1UNTSC */
- {0x0011, 0x0010, 1}, /* XGI_CHTVCRT1ONTSC */
- {0x0011, 0x0001, 2}, /* XGI_CHTVCRT1UPAL */
- {0x0011, 0x0011, 3}, /* XGI_CHTVCRT1OPAL */
- {0xFFFF, 0x0000, 4}
-};
-
-/* ;;Chrontel 7017 TV Timing List */
-static struct XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[] = {
- {0x0011, 0x0000, 0}, /* XGI_CHTVUNTSCData */
- {0x0011, 0x0010, 1}, /* XGI_CHTVONTSCData */
- {0x0011, 0x0001, 2}, /* XGI_CHTVUPALData */
- {0x0011, 0x0011, 3}, /* XGI_CHTVOPALData */
- {0xFFFF, 0x0000, 4}
-};
-
-/* ;;Chrontel 7017 TV Reg. List */
-static struct XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[] = {
- {0x0011, 0x0000, 0}, /* XGI_CHTVRegUNTSC */
- {0x0011, 0x0010, 1}, /* XGI_CHTVRegONTSC */
- {0x0011, 0x0001, 2}, /* XGI_CHTVRegUPAL */
- {0x0011, 0x0011, 3}, /* XGI_CHTVRegOPAL */
+/* Chrontel 7017 TV List */
+static struct XGI330_TVDataTablStruct xgifb_chrontel_tv[] = {
+ {0x0011, 0x0000, 0}, /* UNTSC */
+ {0x0011, 0x0010, 1}, /* ONTSC */
+ {0x0011, 0x0001, 2}, /* UPAL */
+ {0x0011, 0x0011, 3}, /* OPAL */
{0xFFFF, 0x0000, 4}
};
@@ -3060,44 +2498,6 @@ static unsigned short LCDLenList[] = {
0
};
-#if 0
-/* 660, Dual link */
-static struct XGI330_LCDCapStruct XGI660_LCDDLCapList[] = {
-/* LCDCap1024x768 */
- {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
- 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024 */
- {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA,
- 0x053, 0x70, 0x03, VCLK108_2,
- 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1400x1050 */
- {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA,
- 0x053, 0x70, 0x03, VCLK108_2,
- 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1600x1200 */
- {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull,
- 0x053, 0xC0, 0x03, VCLK162,
- 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1024x768x75 */
- {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
- 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024x75 */
- {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA,
- 0x053, 0x90, 0x03, VCLK135_5,
- 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCapDefault */
- {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
- 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
-};
-#endif
-
/* Dual link only */
static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = {
/* LCDCap1024x768 */
@@ -3134,40 +2534,6 @@ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = {
0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
};
-#if 0
-static struct XGI330_LCDCapStruct XGI660_LCDCapList[] = {
-/* LCDCap1024x768 */
- {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
- 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024 */
- {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
- 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1400x1050 */
- {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
- 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1600x1200 */
- {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
- 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1024x768x75 */
- {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
- 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024x75 */
- {Panel1280x1024x75, + DefaultLCDCap, StLCDBToA,
- 0x053, 0x90, 0x03, VCLK135_5,
- 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCapDefault */
- {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
- 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
- 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
-};
-#endif
-
static struct XGI330_LCDCapStruct XGI_LCDCapList[] = {
/* LCDCap1024x768 */
{Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
@@ -3384,169 +2750,6 @@ static struct XGI_Ext2Struct XGI330_RefIndex[] = {
0x30, 0x47, 0x37, 1024, 768},/* 48 1024x768x160Hz */
};
-
-#if 0
-static struct XGI330_VCLKDataStruct XGI330_VCLKData[] = {
- {0x1b, 0xe1, 25}, /* 0x0 */
- {0x4e, 0xe4, 28}, /* 0x1 */
- {0x57, 0xe4, 31}, /* 0x2 */
- {0xc3, 0xc8, 36}, /* 0x3 */
- {0x42, 0xe2, 40}, /* 0x4 */
- {0xfe, 0xcd, 43}, /* 0x5 */
- {0x5d, 0xc4, 44}, /* 0x6 */
- {0x52, 0xe2, 49}, /* 0x7 */
- {0x53, 0xe2, 50}, /* 0x8 */
- {0x74, 0x67, 52}, /* 0x9 */
- {0x6d, 0x66, 56}, /* 0xa */
- {0x6c, 0xc3, 65}, /* 0xb */
- {0x46, 0x44, 67}, /* 0xc */
- {0xb1, 0x46, 68}, /* 0xd */
- {0xd3, 0x4a, 72}, /* 0xe */
- {0x29, 0x61, 75}, /* 0xf */
- {0x6e, 0x46, 76}, /* 0x10 */
- {0x2b, 0x61, 78}, /* 0x11 */
- {0x31, 0x42, 79}, /* 0x12 */
- {0xab, 0x44, 83}, /* 0x13 */
- {0x46, 0x25, 84}, /* 0x14 */
- {0x78, 0x29, 86}, /* 0x15 */
- {0x62, 0x44, 94}, /* 0x16 */
- {0x2b, 0x41, 104}, /* 0x17 */
- {0x3a, 0x23, 105}, /* 0x18 */
- {0x70, 0x44, 108}, /* 0x19 */
- {0x3c, 0x23, 109}, /* 0x1a */
- {0x5e, 0x43, 113}, /* 0x1b */
- {0xbc, 0x44, 116}, /* 0x1c */
- {0xe0, 0x46, 132}, /* 0x1d */
- {0x54, 0x42, 135}, /* 0x1e */
- {0xea, 0x2a, 139}, /* 0x1f */
- {0x41, 0x22, 157}, /* 0x20 */
- {0x70, 0x24, 162}, /* 0x21 */
- {0x30, 0x21, 175}, /* 0x22 */
- {0x4e, 0x22, 189}, /* 0x23 */
- {0xde, 0x26, 194}, /* 0x24 */
- {0x62, 0x06, 202}, /* 0x25 */
- {0x3f, 0x03, 229}, /* 0x26 */
- {0xb8, 0x06, 234}, /* 0x27 */
- {0x34, 0x02, 253}, /* 0x28 */
- {0x58, 0x04, 255}, /* 0x29 */
- {0x24, 0x01, 265}, /* 0x2a */
- {0x9b, 0x02, 267}, /* 0x2b */
- {0x70, 0x05, 270}, /* 0x2c */
- {0x25, 0x01, 272}, /* 0x2d */
- {0x9c, 0x02, 277}, /* 0x2e */
- {0x27, 0x01, 286}, /* 0x2f */
- {0x3c, 0x02, 291}, /* 0x30 */
- {0xef, 0x0a, 292}, /* 0x31 */
- {0xf6, 0x0a, 310}, /* 0x32 */
- {0x95, 0x01, 315}, /* 0x33 */
- {0xf0, 0x09, 324}, /* 0x34 */
- {0xfe, 0x0a, 331}, /* 0x35 */
- {0xf3, 0x09, 332}, /* 0x36 */
- {0xea, 0x08, 340}, /* 0x37 */
- {0xe8, 0x07, 376}, /* 0x38 */
- {0xde, 0x06, 389}, /* 0x39 */
- {0x52, 0x2a, 54}, /* 0x3a */
- {0x52, 0x6a, 27}, /* 0x3b */
- {0x62, 0x24, 70}, /* 0x3c */
- {0x62, 0x64, 70}, /* 0x3d */
- {0xa8, 0x4c, 30}, /* 0x3e */
- {0x20, 0x26, 33}, /* 0x3f */
- {0x31, 0xc2, 39}, /* 0x40 */
- {0x60, 0x36, 30}, /* 0x41 */
- {0x40, 0x4A, 28}, /* 0x42 */
- {0x9F, 0x46, 44}, /* 0x43 */
- {0x97, 0x2C, 26}, /* 0x44 */
- {0x44, 0xE4, 25}, /* 0x45 */
- {0x7E, 0x32, 47}, /* 0x46 */
- {0x08, 0x24, 31}, /* 0x47 */
- {0x97, 0x2c, 26}, /* 0x48 */
- {0xCE, 0x3c, 39}, /* 0x49 */
- {0x52, 0x4A, 36}, /* 0x4a */
- {0x2C, 0x61, 95}, /* 0x4b */
- {0x78, 0x27, 108}, /* 0x4c */
- {0x66, 0x43, 123}, /* 0x4d */
- {0x2c, 0x61, 80}, /* 0x4e */
- {0x3b, 0x61, 108} /* 0x4f */
-};
-
-static struct XGI_VBVCLKDataStruct XGI330_VBVCLKData[] = {
- {0x1b, 0xe1, 25}, /* 0x0 */
- {0x4e, 0xe4, 28}, /* 0x1 */
- {0x57, 0xe4, 31}, /* 0x2 */
- {0xc3, 0xc8, 36}, /* 0x3 */
- {0x42, 0x47, 40}, /* 0x4 */
- {0xfe, 0xcd, 43}, /* 0x5 */
- {0x5d, 0xc4, 44}, /* 0x6 */
- {0x52, 0x47, 49}, /* 0x7 */
- {0x53, 0x47, 50}, /* 0x8 */
- {0x74, 0x67, 52}, /* 0x9 */
- {0x6d, 0x66, 56}, /* 0xa */
- {0x5a, 0x64, 65}, /* 0xb */
- {0x46, 0x44, 67}, /* 0xc */
- {0xb1, 0x46, 68}, /* 0xd */
- {0xd3, 0x4a, 72}, /* 0xe */
- {0x29, 0x61, 75}, /* 0xf */
- {0x6d, 0x46, 75}, /* 0x10 */
- {0x41, 0x43, 78}, /* 0x11 */
- {0x31, 0x42, 79}, /* 0x12 */
- {0xab, 0x44, 83}, /* 0x13 */
- {0x46, 0x25, 84}, /* 0x14 */
- {0x78, 0x29, 86}, /* 0x15 */
- {0x62, 0x44, 94}, /* 0x16 */
- {0x2b, 0x22, 104}, /* 0x17 */
- {0x49, 0x24, 105}, /* 0x18 */
- {0xf8, 0x2f, 108}, /* 0x19 */
- {0x3c, 0x23, 109}, /* 0x1a */
- {0x5e, 0x43, 113}, /* 0x1b */
- {0xbc, 0x44, 116}, /* 0x1c */
- {0xe0, 0x46, 132}, /* 0x1d */
- {0xd4, 0x28, 135}, /* 0x1e */
- {0xea, 0x2a, 139}, /* 0x1f */
- {0x41, 0x22, 157}, /* 0x20 */
- {0x70, 0x24, 162}, /* 0x21 */
- {0x30, 0x21, 175}, /* 0x22 */
- {0x4e, 0x22, 189}, /* 0x23 */
- {0xde, 0x26, 194}, /* 0x24 */
- {0x70, 0x07, 202}, /* 0x25 */
- {0x3f, 0x03, 229}, /* 0x26 */
- {0xb8, 0x06, 234}, /* 0x27 */
- {0x34, 0x02, 253}, /* 0x28 */
- {0x58, 0x04, 255}, /* 0x29 */
- {0x24, 0x01, 265}, /* 0x2a */
- {0x9b, 0x02, 267}, /* 0x2b */
- {0x70, 0x05, 270}, /* 0x2c */
- {0x25, 0x01, 272}, /* 0x2d */
- {0x9c, 0x02, 277}, /* 0x2e */
- {0x27, 0x01, 286}, /* 0x2f */
- {0x3c, 0x02, 291}, /* 0x30 */
- {0xef, 0x0a, 292}, /* 0x31 */
- {0xf6, 0x0a, 310}, /* 0x32 */
- {0x95, 0x01, 315}, /* 0x33 */
- {0xf0, 0x09, 324}, /* 0x34 */
- {0xfe, 0x0a, 331}, /* 0x35 */
- {0xf3, 0x09, 332}, /* 0x36 */
- {0xea, 0x08, 340}, /* 0x37 */
- {0xe8, 0x07, 376}, /* 0x38 */
- {0xde, 0x06, 389}, /* 0x39 */
- {0x52, 0x2a, 54}, /* 0x3a */
- {0x52, 0x6a, 27}, /* 0x3b */
- {0x62, 0x24, 70}, /* 0x3c */
- {0x62, 0x64, 70}, /* 0x3d */
- {0xa8, 0x4c, 30}, /* 0x3e */
- {0x20, 0x26, 33}, /* 0x3f */
- {0x31, 0xc2, 39}, /* 0x40 */
- {0x2e, 0x48, 25}, /* 0x41 */
- {0x24, 0x46, 25}, /* 0x42 */
- {0x26, 0x64, 28}, /* 0x43 */
- {0x37, 0x64, 40}, /* 0x44 */
- {0xa1, 0x42, 108}, /* 0x45 */
- {0x37, 0x61, 100}, /* 0x46 */
- {0x78, 0x27, 108}, /* 0x47 */
- {0x5e, 0x64, 68}, /* 0x48 chiawen for fuj1280x768*/
- {0x70, 0x44, 108}, /* 0x49 chiawen for 1400x1050*/
-};
-#endif
-
static unsigned char XGI330_ScreenOffset[] = {
0x14, 0x19, 0x20, 0x28, 0x32, 0x40,
0x50, 0x64, 0x78, 0x80, 0x2d, 0x35,
@@ -3591,49 +2794,16 @@ static unsigned char XGI330_OutputSelect = 0x40;
static unsigned char XGI330_SoftSetting = 0x30;
static unsigned char XGI330_SR07 = 0x18;
-#if 0
-static unsigned char XGI330New_SR15[8][8] = {
- { 0x0, 0x4, 0x60, 0x60},
- { 0xf, 0xf, 0xf, 0xf},
- {0xba, 0xba, 0xba, 0xba},
- {0xa9, 0xa9, 0xac, 0xac},
- {0xa0, 0xa0, 0xa0, 0xa8},
- { 0x0, 0x0, 0x2, 0x2},
- {0x30, 0x30, 0x40, 0x40},
- { 0x0, 0xa5, 0xfb, 0xf6}
-};
-
-static unsigned char XGI330New_CR40[5][8] = {
- {0x77, 0x77, 0x44, 0x44},
- {0x77, 0x77, 0x44, 0x44},
- { 0x0, 0x0, 0x0, 0x0},
- {0x5b, 0x5b, 0xab, 0xab},
- { 0x0, 0x0, 0xf0, 0xf8}
-};
-#endif
-
static unsigned char XGI330_CR49[] = {0xaa, 0x88};
-static unsigned char XGI330_SR1F = 0x0;
+static unsigned char XGI330_SR1F;
static unsigned char XGI330_SR21 = 0xa3;
-#if 0
-static unsigned char XGI330_650_SR21 = 0xa7;
-#endif
static unsigned char XGI330_SR22 = 0xfb;
static unsigned char XGI330_SR23 = 0xf6;
static unsigned char XGI330_SR24 = 0xd;
-#if 0
-static unsigned char XGI660_SR21 = 0xa3;/* 2003.0312 */
-static unsigned char XGI660_SR22 = 0xf3;/* 2003.0312 */
-
-static unsigned char XGI330_LVDS_SR32 = 0x00; /* ynlai for 650 LVDS */
-static unsigned char XGI330_LVDS_SR33 = 0x00; /* chiawen for 650 LVDS */
-static unsigned char XGI330_650_SR31 = 0x40;
-static unsigned char XGI330_650_SR33 = 0x04;
-#endif
-static unsigned char XGI330_CRT2Data_1_2 = 0x0;
-static unsigned char XGI330_CRT2Data_4_D = 0x0;
-static unsigned char XGI330_CRT2Data_4_E = 0x0;
+static unsigned char XGI330_CRT2Data_1_2;
+static unsigned char XGI330_CRT2Data_4_D;
+static unsigned char XGI330_CRT2Data_4_E;
static unsigned char XGI330_CRT2Data_4_10 = 0x80;
static unsigned short XGI330_RGBSenseData = 0xd1;
static unsigned short XGI330_VideoSenseData = 0xb9;
@@ -3641,22 +2811,14 @@ static unsigned short XGI330_YCSenseData = 0xb3;
static unsigned short XGI330_RGBSenseData2 = 0x0190; /*301b*/
static unsigned short XGI330_VideoSenseData2 = 0x0110;
static unsigned short XGI330_YCSenseData2 = 0x016B;
-#if 0
-static unsigned char XGI330_NTSCPhase[] = {0x21, 0xed, 0x8a, 0x8};
-static unsigned char XGI330_PALPhase[] = {0x2a, 0x5, 0xd3, 0x0};
-static unsigned char XGI330_NTSCPhase2[] = {0x21, 0xF0, 0x7B, 0xD6};/*301b*/
-static unsigned char XGI330_PALPhase2[] = {0x2a, 0x09, 0x86, 0xe9};
-static unsigned char XGI330_PALMPhase[] = {0x21, 0xE4, 0x2E, 0x9B}; /*palmn*/
-static unsigned char XGI330_PALNPhase[] = {0x21, 0xF4, 0x3E, 0xBA};
-#endif
-static unsigned char XG40_I2CDefinition = 0x00 ;
+static unsigned char XG40_I2CDefinition;
static unsigned char XG20_CR97 = 0x10 ;
-static unsigned char XG21_DVOSetting = 0x00 ;
-static unsigned char XG21_CR2E = 0x00 ;
-static unsigned char XG21_CR2F = 0x00 ;
-static unsigned char XG21_CR46 = 0x00 ;
-static unsigned char XG21_CR47 = 0x00 ;
+static unsigned char XG21_DVOSetting;
+static unsigned char XG21_CR2E;
+static unsigned char XG21_CR2F;
+static unsigned char XG21_CR46;
+static unsigned char XG21_CR47;
static unsigned char XG27_CR97 = 0xC1 ;
static unsigned char XG27_SR36 = 0x30 ;
@@ -3664,68 +2826,10 @@ static unsigned char XG27_CR8F = 0x0C ;
static unsigned char XG27_CRD0[] = {
0, 0, 0, 0, 0, 0, 0, 0x82, 0x00, 0x66, 0x01, 0x00
};
-static unsigned char XG27_CRDE[] = {0, 0};
+static unsigned char XG27_CRDE[2];
static unsigned char XG27_SR40 = 0x04 ;
static unsigned char XG27_SR41 = 0x00 ;
-static unsigned char XGI330_CHTVVCLKUNTSC[] = {0x00};
-
-static unsigned char XGI330_CHTVVCLKONTSC[] = {0x00};
-
-static unsigned char XGI330_CHTVVCLKUPAL[] = {0x00};
-
-static unsigned char XGI330_CHTVVCLKOPAL[] = {0x00};
-
-static unsigned char XGI7007_CHTVVCLKUNTSC[] = {
- CH7007TVVCLK30_2,
- CH7007TVVCLK30_2,
- CH7007TVVCLK30_2,
- CH7007TVVCLK30_2,
- CH7007TVVCLK28_1,
- CH7007TVVCLK47_8
-};
-
-static unsigned char XGI7007_CHTVVCLKONTSC[] = {
- CH7007TVVCLK26_4,
- CH7007TVVCLK26_4,
- CH7007TVVCLK26_4,
- CH7007TVVCLK26_4,
- CH7007TVVCLK24_6,
- CH7007TVVCLK43_6
-};
-
-static unsigned char XGI7007_CHTVVCLKUPAL[] = {
- CH7007TVVCLK31_5,
- CH7007TVVCLK31_5,
- CH7007TVVCLK31_5,
- CH7007TVVCLK31_5,
- CH7007TVVCLK26_2,
- CH7007TVVCLK39
-};
-
-static unsigned char XGI7007_CHTVVCLKOPAL[] = {
- CH7007TVVCLK31_5,
- CH7007TVVCLK31_5,
- CH7007TVVCLK31_5,
- CH7007TVVCLK31_5,
- CH7007TVVCLK26_2,
- CH7007TVVCLK36
-};
-
-static struct XGI330_VCLKDataStruct XGI_CH7007VCLKData[] = {
- {0x60, 0x36, 30}, /* 0 30.2 MHZ */
- {0x40, 0x4A, 28}, /* 1 28.19 MHZ */
- {0x9F, 0x46, 44}, /* 2 43.6 MHZ */
- {0x97, 0x2C, 26}, /* 3 26.4 MHZ */
- {0x44, 0xE4, 25}, /* 4 24.6 MHZ */
- {0x7E, 0x32, 47}, /* 5 47.832 MHZ */
- {0x8A, 0x24, 31}, /* 6 31.5 MHZ */
- {0x97, 0x2C, 26}, /* 7 26.2 MHZ */
- {0xCE, 0x3C, 39}, /* 8 39 MHZ */
- {0x52, 0x4A, 36}, /* 9 36 MHZ */
- {0xFF, 0x00, 0} /* End mark */
-};
-
static struct XGI330_VCLKDataStruct XGI_VCLKData[] = {
/* SR2B,SR2C,SR2D */
{0x1B, 0xE1, 25}, /* 00 (25.175MHz) */
@@ -3805,21 +2909,6 @@ static struct XGI330_VCLKDataStruct XGI_VCLKData[] = {
{0x66, 0x43, 123}, /* 4A (122.61Mhz) */
{0x2C, 0x61, 80}, /* 4B (80.350Mhz) */
{0x3B, 0x61, 108}, /* 4C (107.385Mhz) */
-/*
- {0x60, 0x36, 30},// 4D (30.200MHz) }// No use
- {0x60, 0x36, 30},// 4E (30.200MHz) }// No use
- {0x60, 0x36, 30},// 4F (30.200MHz) }// No use
- {0x60, 0x36, 30},// 50 (30.200MHz) }// CHTV
- {0x40, 0x4A, 28},// 51 (28.190MHz)
- {0x9F, 0x46, 44},// 52 (43.600MHz)
- {0x97, 0x2C, 26},// 53 (26.400MHz)
- {0x44, 0xE4, 25},// 54 (24.600MHz)
- {0x7E, 0x32, 47},// 55 (47.832MHz)
- {0x8A, 0x24, 31},// 56 (31.500MHz)
- {0x97, 0x2C, 26},// 57 (26.200MHz)
- {0xCE, 0x3C, 39},// 58 (39.000MHz)
- {0x52, 0x4A, 36},// 59 (36.000MHz)
-*/
{0x69, 0x61, 191}, /* 4D (190.96MHz ) */
{0x4F, 0x22, 192}, /* 4E (192.069MHz) */
{0x28, 0x26, 322}, /* 4F (322.273MHz) */
@@ -3912,21 +3001,6 @@ static struct XGI330_VCLKDataStruct XGI_VBVCLKData[] = {
{0x66, 0x43, 123}, /* 4A (122.61Mhz) */
{0x2C, 0x61, 80 }, /* 4B (80.350Mhz) */
{0x3B, 0x61, 108}, /* 4C (107.385Mhz) */
-/*
- {0x60, 0x36, 30}, // 4D (30.200MHz) }// No use
- {0x60, 0x36, 30}, // 4E (30.200MHz) }// No use
- {0x60, 0x36, 30}, // 4F (30.200MHz) }// No use
- {0x60, 0x36, 30}, // 50 (30.200MHz) }// CHTV
- {0x40, 0x4A, 28}, // 51 (28.190MHz)
- {0x9F, 0x46, 44}, // 52 (43.600MHz)
- {0x97, 0x2C, 26}, // 53 (26.400MHz)
- {0x44, 0xE4, 25}, // 54 (24.600MHz)
- {0x7E, 0x32, 47}, // 55 (47.832MHz)
- {0x8A, 0x24, 31}, // 56 (31.500MHz)
- {0x97, 0x2C, 26}, // 57 (26.200MHz)
- {0xCE, 0x3C, 39}, // 58 (39.000MHz)
- {0x52, 0x4A, 36}, // 59 (36.000MHz)
-*/
{0x69, 0x61, 191}, /* 4D (190.96MHz ) */
{0x4F, 0x22, 192}, /* 4E (192.069MHz) */
{0x28, 0x26, 322}, /* 4F (322.273MHz) */
@@ -3941,38 +3015,6 @@ static struct XGI330_VCLKDataStruct XGI_VBVCLKData[] = {
{0xFF, 0x00, 0} /* End mark */
};
-#if 0
-static unsigned char XGI660_TVDelayList[] = {
- 0x44, /* ; 0 ExtNTSCDelay */
- 0x44, /* ; 1 StNTSCDelay */
- 0x44, /* ; 2 ExtPALDelay */
- 0x44, /* ; 3 StPALDelay */
- 0x44, /* ; 4 ExtHiTVDelay(1080i) */
- 0x44, /* ; 5 StHiTVDelay(1080i) */
- 0x44, /* ; 6 ExtYPbPrDelay(525i) */
- 0x44, /* ; 7 StYPbPrDealy(525i) */
- 0x44, /* ; 8 ExtYPbPrDelay(525p) */
- 0x44, /* ; 9 StYPbPrDealy(525p) */
- 0x44, /* ; A ExtYPbPrDelay(750p) */
- 0x44 /* ; B StYPbPrDealy(750p) */
-};
-
-static unsigned char XGI660_TVDelayList2[] = {
- 0x44, /* ; 0 ExtNTSCDelay */
- 0x44, /* ; 1 StNTSCDelay */
- 0x44, /* ; 2 ExtPALDelay */
- 0x44, /* ; 3 StPALDelay */
- 0x44, /* ; 4 ExtHiTVDelay */
- 0x44, /* ; 5 StHiTVDelay */
- 0x44, /* ; 6 ExtYPbPrDelay(525i) */
- 0x44, /* ; 7 StYPbPrDealy(525i) */
- 0x44, /* ; 8 ExtYPbPrDelay(525p) */
- 0x44, /* ; 9 StYPbPrDealy(525p) */
- 0x44, /* ; A ExtYPbPrDelay(750p) */
- 0x44 /* ; B StYPbPrDealy(750p) */
-};
-#endif
-
static unsigned char XGI301TVDelayList[] = {
0x22, /* ; 0 ExtNTSCDelay */
0x22, /* ; 1 StNTSCDelay */
@@ -4062,7 +3104,7 @@ static unsigned char PALYFilter1[] = {
0xFC, 0xFB, 0x14, 0x2A /* 6 : 800x gra. mode */
};
-static unsigned char PALMYFilter1[] = {
+static unsigned char xgifb_palmn_yfilter1[] = {
0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
0xEB, 0x04, 0x10, 0x18, /* 2 : 640x text mode */
@@ -4073,51 +3115,7 @@ static unsigned char PALMYFilter1[] = {
0xFF, 0xFF, 0xFF, 0xFF /* End of Table */
};
-static unsigned char PALNYFilter1[] = {
- 0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
- 0xEB, 0x04, 0x10, 0x18, /* 2 : 640x text mode */
- 0xF7, 0x06, 0x19, 0x14, /* 3 : 720x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 4 : 320x gra. mode */
- 0xEB, 0x04, 0x25, 0x18, /* 5 : 640x gra. mode */
- 0xEB, 0x15, 0x25, 0xF6, /* 6 : 800x gra. mode */
- 0xFF, 0xFF, 0xFF, 0xFF /* End of Table */
-};
-
-static unsigned char NTSCYFilter2[] = {
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 0 : 320x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 1 : 360x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 2 : 640x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 3 : 720x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 4 : 320x gra. mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 5 : 640x gra. mode */
- 0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38, /* 6 : 800x gra. mode */
- 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28 /* 7 : 1024xgra. mode */
-};
-
-static unsigned char PALYFilter2[] = {
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 0 : 320x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 1 : 360x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 2 : 640x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 3 : 720x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 4 : 320x gra. mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 5 : 640x gra. mode */
- 0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38, /* 6 : 800x gra. mode */
- 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28 /* 7 : 1024xgra. mode */
-};
-
-static unsigned char PALMYFilter2[] = {
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 0 : 320x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 1 : 360x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 2 : 640x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 3 : 720x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 4 : 320x gra. mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 5 : 640x gra. mode */
- 0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38, /* 6 : 800x gra. mode */
- 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28 /* 7 : 1024xgra. mode */
-};
-
-static unsigned char PALNYFilter2[] = {
+static unsigned char xgifb_yfilter2[] = {
0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 0 : 320x text mode */
0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 1 : 360x text mode */
0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 2 : 640x text mode */
@@ -4134,35 +3132,7 @@ static unsigned char XGI_NTSC1024AdjTime[] = {
0x58, 0xe4, 0x73, 0xd0, 0x13
};
-static struct XGI301C_Tap4TimingStruct HiTVTap4Timing[] = {
- {0, {
- 0x00, 0x20, 0x00, 0x00, 0x7F, 0x20, 0x02, 0x7F, /* ; C0-C7 */
- 0x7D, 0x20, 0x04, 0x7F, 0x7D, 0x1F, 0x06, 0x7E, /* ; C8-CF */
- 0x7C, 0x1D, 0x09, 0x7E, 0x7C, 0x1B, 0x0B, 0x7E, /* ; D0-D7 */
- 0x7C, 0x19, 0x0E, 0x7D, 0x7C, 0x17, 0x11, 0x7C, /* ; D8-DF */
- 0x7C, 0x14, 0x14, 0x7C, 0x7C, 0x11, 0x17, 0x7C, /* ; E0-E7 */
- 0x7D, 0x0E, 0x19, 0x7C, 0x7E, 0x0B, 0x1B, 0x7C, /* ; EA-EF */
- 0x7E, 0x09, 0x1D, 0x7C, 0x7F, 0x06, 0x1F, 0x7C, /* ; F0-F7 */
- 0x7F, 0x04, 0x20, 0x7D, 0x00, 0x02, 0x20, 0x7E /* ; F8-FF */
- }
- }
-};
-
-static struct XGI301C_Tap4TimingStruct EnlargeTap4Timing[] = {
- {0, {
- 0x00, 0x20, 0x00, 0x00, 0x7F, 0x20, 0x02, 0x7F, /* ; C0-C7 */
- 0x7D, 0x20, 0x04, 0x7F, 0x7D, 0x1F, 0x06, 0x7E, /* ; C8-CF */
- 0x7C, 0x1D, 0x09, 0x7E, 0x7C, 0x1B, 0x0B, 0x7E, /* ; D0-D7 */
- 0x7C, 0x19, 0x0E, 0x7D, 0x7C, 0x17, 0x11, 0x7C, /* ; D8-DF */
- 0x7C, 0x14, 0x14, 0x7C, 0x7C, 0x11, 0x17, 0x7C, /* ; E0-E7 */
- 0x7D, 0x0E, 0x19, 0x7C, 0x7E, 0x0B, 0x1B, 0x7C, /* ; EA-EF */
- 0x7E, 0x09, 0x1D, 0x7C, 0x7F, 0x06, 0x1F, 0x7C, /* ; F0-F7 */
- 0x7F, 0x04, 0x20, 0x7D, 0x00, 0x02, 0x20, 0x7E /* ; F8-FF */
- }
- }
-};
-
-static struct XGI301C_Tap4TimingStruct NoScaleTap4Timing[] = {
+static struct XGI301C_Tap4TimingStruct xgifb_tap4_timing[] = {
{0, {
0x00, 0x20, 0x00, 0x00, 0x7F, 0x20, 0x02, 0x7F, /* ; C0-C7 */
0x7D, 0x20, 0x04, 0x7F, 0x7D, 0x1F, 0x06, 0x7E, /* ; C8-CF */
@@ -4212,7 +3182,7 @@ static struct XGI301C_Tap4TimingStruct PALTap4Timing[] = {
}
};
-static struct XGI301C_Tap4TimingStruct NTSCTap4Timing[] = {
+static struct XGI301C_Tap4TimingStruct xgifb_ntsc_525_tap4_timing[] = {
{480, {
0x04, 0x1A, 0x04, 0x7E, 0x03, 0x1A, 0x06, 0x7D, /* ; C0-C7 */
0x01, 0x1A, 0x08, 0x7D, 0x00, 0x19, 0x0A, 0x7D, /* ; C8-CF */
@@ -4248,78 +3218,6 @@ static struct XGI301C_Tap4TimingStruct NTSCTap4Timing[] = {
}
};
-static struct XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[] = {
- {480, {
- 0x04, 0x1A, 0x04, 0x7E, 0x03, 0x1A, 0x06, 0x7D, /* ; C0-C7 */
- 0x01, 0x1A, 0x08, 0x7D, 0x00, 0x19, 0x0A, 0x7D, /* ; C8-CF */
- 0x7F, 0x19, 0x0C, 0x7C, 0x7E, 0x18, 0x0E, 0x7C, /* ; D0-D7 */
- 0x7E, 0x17, 0x10, 0x7B, 0x7D, 0x15, 0x12, 0x7C, /* ; D8-DF */
- 0x7D, 0x13, 0x13, 0x7D, 0x7C, 0x12, 0x15, 0x7D, /* ; E0-E7 */
- 0x7C, 0x10, 0x17, 0x7D, 0x7C, 0x0E, 0x18, 0x7E, /* ; EA-EF */
- 0x7D, 0x0C, 0x19, 0x7E, 0x7D, 0x0A, 0x19, 0x00, /* ; F0-F7 */
- 0x7D, 0x08, 0x1A, 0x01, 0x7E, 0x06, 0x1A, 0x02 /* ; F8-FF */
- }
- },
- {600, {
- 0x07, 0x14, 0x07, 0x7E, 0x06, 0x14, 0x09, 0x7D, /* ; C0-C7 */
- 0x05, 0x14, 0x0A, 0x7D, 0x04, 0x13, 0x0B, 0x7E, /* ; C8-CF */
- 0x03, 0x13, 0x0C, 0x7E, 0x02, 0x12, 0x0D, 0x7F, /* ; D0-D7 */
- 0x01, 0x12, 0x0E, 0x7F, 0x01, 0x11, 0x0F, 0x7F, /* ; D8-DF */
- 0x01, 0x10, 0x10, 0x00, 0x7F, 0x0F, 0x11, 0x01, /* ; E0-E7 */
- 0x7F, 0x0E, 0x12, 0x01, 0x7E, 0x0D, 0x12, 0x03, /* ; EA-EF */
- 0x7E, 0x0C, 0x13, 0x03, 0x7E, 0x0B, 0x13, 0x04, /* ; F0-F7 */
- 0x7E, 0x0A, 0x14, 0x04, 0x7D, 0x09, 0x14, 0x06 /* ; F8-FF */
- }
- },
- {0xFFFF, {
- 0x09, 0x0F, 0x09, 0x7F, 0x08, 0x0F, 0x09, 0x00, /* ; C0-C7 */
- 0x07, 0x0F, 0x0A, 0x00, 0x06, 0x0F, 0x0A, 0x01, /* ; C8-CF */
- 0x06, 0x0E, 0x0B, 0x01, 0x05, 0x0E, 0x0B, 0x02, /* ; D0-D7 */
- 0x04, 0x0E, 0x0C, 0x02, 0x04, 0x0D, 0x0C, 0x03, /* ; D8-DF */
- 0x03, 0x0D, 0x0D, 0x03, 0x02, 0x0C, 0x0D, 0x05, /* ; E0-E7 */
- 0x02, 0x0C, 0x0E, 0x04, 0x01, 0x0B, 0x0E, 0x06, /* ; EA-EF */
- 0x01, 0x0B, 0x0E, 0x06, 0x00, 0x0A, 0x0F, 0x07, /* ; F0-F7 */
- 0x00, 0x0A, 0x0F, 0x07, 0x00, 0x09, 0x0F, 0x08 /* ; F8-FF */
- }
- }
-};
-
-static struct XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[] = {
- {480, {
- 0x04, 0x1A, 0x04, 0x7E, 0x03, 0x1A, 0x06, 0x7D, /* ; C0-C7 */
- 0x01, 0x1A, 0x08, 0x7D, 0x00, 0x19, 0x0A, 0x7D, /* ; C8-CF */
- 0x7F, 0x19, 0x0C, 0x7C, 0x7E, 0x18, 0x0E, 0x7C, /* ; D0-D7 */
- 0x7E, 0x17, 0x10, 0x7B, 0x7D, 0x15, 0x12, 0x7C, /* ; D8-DF */
- 0x7D, 0x13, 0x13, 0x7D, 0x7C, 0x12, 0x15, 0x7D, /* ; E0-E7 */
- 0x7C, 0x10, 0x17, 0x7D, 0x7C, 0x0E, 0x18, 0x7E, /* ; EA-EF */
- 0x7D, 0x0C, 0x19, 0x7E, 0x7D, 0x0A, 0x19, 0x00, /* ; F0-F7 */
- 0x7D, 0x08, 0x1A, 0x01, 0x7E, 0x06, 0x1A, 0x02 /* ; F8-FF */
- }
- },
- {600, {
- 0x07, 0x14, 0x07, 0x7E, 0x06, 0x14, 0x09, 0x7D, /* ; C0-C7 */
- 0x05, 0x14, 0x0A, 0x7D, 0x04, 0x13, 0x0B, 0x7E, /* ; C8-CF */
- 0x03, 0x13, 0x0C, 0x7E, 0x02, 0x12, 0x0D, 0x7F, /* ; D0-D7 */
- 0x01, 0x12, 0x0E, 0x7F, 0x01, 0x11, 0x0F, 0x7F, /* ; D8-DF */
- 0x01, 0x10, 0x10, 0x00, 0x7F, 0x0F, 0x11, 0x01, /* ; E0-E7 */
- 0x7F, 0x0E, 0x12, 0x01, 0x7E, 0x0D, 0x12, 0x03, /* ; EA-EF */
- 0x7E, 0x0C, 0x13, 0x03, 0x7E, 0x0B, 0x13, 0x04, /* ; F0-F7 */
- 0x7E, 0x0A, 0x14, 0x04, 0x7D, 0x09, 0x14, 0x06 /* ; F8-FF */
- }
- },
- {0xFFFF, {
- 0x09, 0x0F, 0x09, 0x7F, 0x08, 0x0F, 0x09, 0x00, /* ; C0-C7 */
- 0x07, 0x0F, 0x0A, 0x00, 0x06, 0x0F, 0x0A, 0x01, /* ; C8-CF */
- 0x06, 0x0E, 0x0B, 0x01, 0x05, 0x0E, 0x0B, 0x02, /* ; D0-D7 */
- 0x04, 0x0E, 0x0C, 0x02, 0x04, 0x0D, 0x0C, 0x03, /* ; D8-DF */
- 0x03, 0x0D, 0x0D, 0x03, 0x02, 0x0C, 0x0D, 0x05, /* ; E0-E7 */
- 0x02, 0x0C, 0x0E, 0x04, 0x01, 0x0B, 0x0E, 0x06, /* ; EA-EF */
- 0x01, 0x0B, 0x0E, 0x06, 0x00, 0x0A, 0x0F, 0x07, /* ; F0-F7 */
- 0x00, 0x0A, 0x0F, 0x07, 0x00, 0x09, 0x0F, 0x08 /* ; F8-FF */
- }
- }
-};
-
static struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] = {
{0xFFFF, {
0x05, 0x19, 0x05, 0x7D, 0x03, 0x19, 0x06, 0x7E, /* ; C0-C7 */
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
index ea2b795..b5c9989 100644
--- a/drivers/staging/xgifb/vb_util.c
+++ b/drivers/staging/xgifb/vb_util.c
@@ -1,10 +1,11 @@
+#include <linux/io.h>
+#include <linux/types.h>
+
#include "vb_def.h"
#include "vgatypes.h"
#include "vb_struct.h"
#include "XGIfb.h"
-#include <linux/io.h>
-#include <linux/types.h>
#include "vb_util.h"
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
index 5aeb3a4..9b939b7 100644
--- a/drivers/staging/xgifb/vgatypes.h
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -47,18 +47,13 @@ enum XGI_LCD_TYPE {
};
#endif
-struct XGI_DSReg {
- unsigned char jIdx;
- unsigned char jVal;
-};
-
struct xgi_hw_device_info {
unsigned long ulExternalChip; /* NO VB or other video bridge*/
/* if ujVBChipID = VB_CHIP_UNKNOWN, */
unsigned char *pjVirtualRomBase; /* ROM image */
- unsigned char *pjVideoMemoryAddress;/* base virtual memory address */
+ void __iomem *pjVideoMemoryAddress;/* base virtual memory address */
/* of Linear VGA memory */
unsigned long ulVideoMemorySize; /* size, in bytes, of the
@@ -78,10 +73,6 @@ struct xgi_hw_device_info {
/* "XGI_VB_CHIP_TYPE" */
unsigned long ulCRT2LCDType; /* defined in the data structure type */
-
- unsigned char(*pQueryVGAConfigSpace)(struct xgi_hw_device_info *,
- unsigned long, unsigned long,
- unsigned long *);
};
/* Additional IOCTL for communication xgifb <> X driver */
diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig
index 06f741a..3bec4db 100644
--- a/drivers/staging/zram/Kconfig
+++ b/drivers/staging/zram/Kconfig
@@ -28,10 +28,3 @@ config ZRAM_DEBUG
help
This option adds additional debugging code to the compressed
RAM block device driver.
-
-config ZRAM_FOR_ANDROID
- bool "Optimize zram behavior for android"
- depends on ZRAM && ANDROID
- default n
- help
- This option enables modified zram behavior optimized for android
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 5258c78..e1a4994 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -32,10 +32,6 @@
#include <linux/lzo.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-#include <linux/swap.h>
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
#include "zram_drv.h"
@@ -44,7 +40,7 @@ static int zram_major;
struct zram *zram_devices;
/* Module params (documentation at end) */
-unsigned int num_devices;
+unsigned int zram_num_devices;
static void zram_stat_inc(u32 *v)
{
@@ -137,22 +133,6 @@ static void zram_set_disksize(struct zram *zram, size_t totalram_bytes)
zram->disksize &= PAGE_MASK;
}
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-/*
- * Swap header (1st page of swap device) contains information
- * about a swap file/partition. Prepare such a header for the
- * given ramzswap device so that swapon can identify it as a
- * swap partition.
- */
-static void setup_swap_header(struct zram *zram, union swap_header *s)
-{
- s->info.version = 1;
- s->info.last_page = (zram->disksize >> PAGE_SHIFT) - 1;
- s->info.nr_badpages = 0;
- memcpy(s->magic.magic, "SWAPSPACE2", 10);
-}
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
static void zram_free_page(struct zram *zram, size_t index)
{
u32 clen;
@@ -197,224 +177,355 @@ out:
zram->table[index].offset = 0;
}
-static void handle_zero_page(struct page *page)
+static void handle_zero_page(struct bio_vec *bvec)
{
+ struct page *page = bvec->bv_page;
void *user_mem;
user_mem = kmap_atomic(page, KM_USER0);
- memset(user_mem, 0, PAGE_SIZE);
+ memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
kunmap_atomic(user_mem, KM_USER0);
flush_dcache_page(page);
}
-static void handle_uncompressed_page(struct zram *zram,
- struct page *page, u32 index)
+static void handle_uncompressed_page(struct zram *zram, struct bio_vec *bvec,
+ u32 index, int offset)
{
+ struct page *page = bvec->bv_page;
unsigned char *user_mem, *cmem;
user_mem = kmap_atomic(page, KM_USER0);
- cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
- zram->table[index].offset;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER1);
- memcpy(user_mem, cmem, PAGE_SIZE);
- kunmap_atomic(user_mem, KM_USER0);
+ memcpy(user_mem + bvec->bv_offset, cmem + offset, bvec->bv_len);
kunmap_atomic(cmem, KM_USER1);
+ kunmap_atomic(user_mem, KM_USER0);
flush_dcache_page(page);
}
-static void zram_read(struct zram *zram, struct bio *bio)
+static inline int is_partial_io(struct bio_vec *bvec)
{
+ return bvec->bv_len != PAGE_SIZE;
+}
- int i;
- u32 index;
- struct bio_vec *bvec;
-
- zram_stat64_inc(zram, &zram->stats.num_reads);
- index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+ u32 index, int offset, struct bio *bio)
+{
+ int ret;
+ size_t clen;
+ struct page *page;
+ struct zobj_header *zheader;
+ unsigned char *user_mem, *cmem, *uncmem = NULL;
- bio_for_each_segment(bvec, bio, i) {
- int ret;
- size_t clen;
- struct page *page;
- struct zobj_header *zheader;
- unsigned char *user_mem, *cmem;
+ page = bvec->bv_page;
- page = bvec->bv_page;
+ if (zram_test_flag(zram, index, ZRAM_ZERO)) {
+ handle_zero_page(bvec);
+ return 0;
+ }
- if (zram_test_flag(zram, index, ZRAM_ZERO)) {
- handle_zero_page(page);
- index++;
- continue;
- }
+ /* Requested page is not present in compressed area */
+ if (unlikely(!zram->table[index].page)) {
+ pr_debug("Read before write: sector=%lu, size=%u",
+ (ulong)(bio->bi_sector), bio->bi_size);
+ handle_zero_page(bvec);
+ return 0;
+ }
- /* Requested page is not present in compressed area */
- if (unlikely(!zram->table[index].page)) {
- pr_debug("Read before write: sector=%lu, size=%u",
- (ulong)(bio->bi_sector), bio->bi_size);
- handle_zero_page(page);
- index++;
- continue;
- }
+ /* Page is stored uncompressed since it's incompressible */
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
+ handle_uncompressed_page(zram, bvec, index, offset);
+ return 0;
+ }
- /* Page is stored uncompressed since it's incompressible */
- if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
- handle_uncompressed_page(zram, page, index);
- index++;
- continue;
+ if (is_partial_io(bvec)) {
+ /* Use a temporary buffer to decompress the page */
+ uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+ if (!uncmem) {
+ pr_info("Error allocating temp memory!\n");
+ return -ENOMEM;
}
+ }
- user_mem = kmap_atomic(page, KM_USER0);
- clen = PAGE_SIZE;
+ user_mem = kmap_atomic(page, KM_USER0);
+ if (!is_partial_io(bvec))
+ uncmem = user_mem;
+ clen = PAGE_SIZE;
- cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
- zram->table[index].offset;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+ zram->table[index].offset;
- ret = lzo1x_decompress_safe(
- cmem + sizeof(*zheader),
- xv_get_object_size(cmem) - sizeof(*zheader),
- user_mem, &clen);
+ ret = lzo1x_decompress_safe(cmem + sizeof(*zheader),
+ xv_get_object_size(cmem) - sizeof(*zheader),
+ uncmem, &clen);
- kunmap_atomic(user_mem, KM_USER0);
- kunmap_atomic(cmem, KM_USER1);
+ if (is_partial_io(bvec)) {
+ memcpy(user_mem + bvec->bv_offset, uncmem + offset,
+ bvec->bv_len);
+ kfree(uncmem);
+ }
- /* Should NEVER happen. Return bio error if it does. */
- if (unlikely(ret != LZO_E_OK)) {
- pr_err("Decompression failed! err=%d, page=%u\n",
- ret, index);
- zram_stat64_inc(zram, &zram->stats.failed_reads);
- goto out;
- }
+ kunmap_atomic(cmem, KM_USER1);
+ kunmap_atomic(user_mem, KM_USER0);
- flush_dcache_page(page);
- index++;
+ /* Should NEVER happen. Return bio error if it does. */
+ if (unlikely(ret != LZO_E_OK)) {
+ pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+ zram_stat64_inc(zram, &zram->stats.failed_reads);
+ return ret;
}
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return;
+ flush_dcache_page(page);
-out:
- bio_io_error(bio);
+ return 0;
}
-static void zram_write(struct zram *zram, struct bio *bio)
+static int zram_read_before_write(struct zram *zram, char *mem, u32 index)
{
- int i;
- u32 index;
- struct bio_vec *bvec;
+ int ret;
+ size_t clen = PAGE_SIZE;
+ struct zobj_header *zheader;
+ unsigned char *cmem;
- zram_stat64_inc(zram, &zram->stats.num_writes);
- index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+ if (zram_test_flag(zram, index, ZRAM_ZERO) ||
+ !zram->table[index].page) {
+ memset(mem, 0, PAGE_SIZE);
+ return 0;
+ }
- bio_for_each_segment(bvec, bio, i) {
- int ret;
- u32 offset;
- size_t clen;
- struct zobj_header *zheader;
- struct page *page, *page_store;
- unsigned char *user_mem, *cmem, *src;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER0) +
+ zram->table[index].offset;
+
+ /* Page is stored uncompressed since it's incompressible */
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
+ memcpy(mem, cmem, PAGE_SIZE);
+ kunmap_atomic(cmem, KM_USER0);
+ return 0;
+ }
+
+ ret = lzo1x_decompress_safe(cmem + sizeof(*zheader),
+ xv_get_object_size(cmem) - sizeof(*zheader),
+ mem, &clen);
+ kunmap_atomic(cmem, KM_USER0);
+
+ /* Should NEVER happen. Return bio error if it does. */
+ if (unlikely(ret != LZO_E_OK)) {
+ pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+ zram_stat64_inc(zram, &zram->stats.failed_reads);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
+ int offset)
+{
+ int ret;
+ u32 store_offset;
+ size_t clen;
+ struct zobj_header *zheader;
+ struct page *page, *page_store;
+ unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
- page = bvec->bv_page;
- src = zram->compress_buffer;
+ page = bvec->bv_page;
+ src = zram->compress_buffer;
+ if (is_partial_io(bvec)) {
/*
- * System overwrites unused sectors. Free memory associated
- * with this sector now.
+ * This is a partial IO. We need to read the full page
+ * before to write the changes.
*/
- if (zram->table[index].page ||
- zram_test_flag(zram, index, ZRAM_ZERO))
- zram_free_page(zram, index);
-
- mutex_lock(&zram->lock);
-
- user_mem = kmap_atomic(page, KM_USER0);
- if (page_zero_filled(user_mem)) {
- kunmap_atomic(user_mem, KM_USER0);
- mutex_unlock(&zram->lock);
- zram_stat_inc(&zram->stats.pages_zero);
- zram_set_flag(zram, index, ZRAM_ZERO);
- index++;
- continue;
+ uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+ if (!uncmem) {
+ pr_info("Error allocating temp memory!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = zram_read_before_write(zram, uncmem, index);
+ if (ret) {
+ kfree(uncmem);
+ goto out;
}
+ }
+
+ /*
+ * System overwrites unused sectors. Free memory associated
+ * with this sector now.
+ */
+ if (zram->table[index].page ||
+ zram_test_flag(zram, index, ZRAM_ZERO))
+ zram_free_page(zram, index);
+
+ user_mem = kmap_atomic(page, KM_USER0);
- ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
- zram->compress_workmem);
+ if (is_partial_io(bvec))
+ memcpy(uncmem + offset, user_mem + bvec->bv_offset,
+ bvec->bv_len);
+ else
+ uncmem = user_mem;
+ if (page_zero_filled(uncmem)) {
kunmap_atomic(user_mem, KM_USER0);
+ if (is_partial_io(bvec))
+ kfree(uncmem);
+ zram_stat_inc(&zram->stats.pages_zero);
+ zram_set_flag(zram, index, ZRAM_ZERO);
+ ret = 0;
+ goto out;
+ }
- if (unlikely(ret != LZO_E_OK)) {
- mutex_unlock(&zram->lock);
- pr_err("Compression failed! err=%d\n", ret);
- zram_stat64_inc(zram, &zram->stats.failed_writes);
- goto out;
- }
+ ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
+ zram->compress_workmem);
- /*
- * Page is incompressible. Store it as-is (uncompressed)
- * since we do not want to return too many disk write
- * errors which has side effect of hanging the system.
- */
- if (unlikely(clen > max_zpage_size)) {
- clen = PAGE_SIZE;
- page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
- if (unlikely(!page_store)) {
- mutex_unlock(&zram->lock);
- pr_info("Error allocating memory for "
- "incompressible page: %u\n", index);
- zram_stat64_inc(zram,
- &zram->stats.failed_writes);
- goto out;
- }
-
- offset = 0;
- zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
- zram_stat_inc(&zram->stats.pages_expand);
- zram->table[index].page = page_store;
- src = kmap_atomic(page, KM_USER0);
- goto memstore;
- }
+ kunmap_atomic(user_mem, KM_USER0);
+ if (is_partial_io(bvec))
+ kfree(uncmem);
+
+ if (unlikely(ret != LZO_E_OK)) {
+ pr_err("Compression failed! err=%d\n", ret);
+ goto out;
+ }
- if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader),
- &zram->table[index].page, &offset,
- GFP_NOIO | __GFP_HIGHMEM)) {
- mutex_unlock(&zram->lock);
- pr_info("Error allocating memory for compressed "
- "page: %u, size=%zu\n", index, clen);
- zram_stat64_inc(zram, &zram->stats.failed_writes);
+ /*
+ * Page is incompressible. Store it as-is (uncompressed)
+ * since we do not want to return too many disk write
+ * errors which has side effect of hanging the system.
+ */
+ if (unlikely(clen > max_zpage_size)) {
+ clen = PAGE_SIZE;
+ page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+ if (unlikely(!page_store)) {
+ pr_info("Error allocating memory for "
+ "incompressible page: %u\n", index);
+ ret = -ENOMEM;
goto out;
}
+ store_offset = 0;
+ zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
+ zram_stat_inc(&zram->stats.pages_expand);
+ zram->table[index].page = page_store;
+ src = kmap_atomic(page, KM_USER0);
+ goto memstore;
+ }
+
+ if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader),
+ &zram->table[index].page, &store_offset,
+ GFP_NOIO | __GFP_HIGHMEM)) {
+ pr_info("Error allocating memory for compressed "
+ "page: %u, size=%zu\n", index, clen);
+ ret = -ENOMEM;
+ goto out;
+ }
+
memstore:
- zram->table[index].offset = offset;
+ zram->table[index].offset = store_offset;
- cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
- zram->table[index].offset;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+ zram->table[index].offset;
#if 0
- /* Back-reference needed for memory defragmentation */
- if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) {
- zheader = (struct zobj_header *)cmem;
- zheader->table_idx = index;
- cmem += sizeof(*zheader);
- }
+ /* Back-reference needed for memory defragmentation */
+ if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) {
+ zheader = (struct zobj_header *)cmem;
+ zheader->table_idx = index;
+ cmem += sizeof(*zheader);
+ }
#endif
- memcpy(cmem, src, clen);
+ memcpy(cmem, src, clen);
- kunmap_atomic(cmem, KM_USER1);
- if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
- kunmap_atomic(src, KM_USER0);
+ kunmap_atomic(cmem, KM_USER1);
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
+ kunmap_atomic(src, KM_USER0);
+
+ /* Update stats */
+ zram_stat64_add(zram, &zram->stats.compr_size, clen);
+ zram_stat_inc(&zram->stats.pages_stored);
+ if (clen <= PAGE_SIZE / 2)
+ zram_stat_inc(&zram->stats.good_compress);
+
+ return 0;
+
+out:
+ if (ret)
+ zram_stat64_inc(zram, &zram->stats.failed_writes);
+ return ret;
+}
+
+static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
+ int offset, struct bio *bio, int rw)
+{
+ int ret;
+
+ if (rw == READ) {
+ down_read(&zram->lock);
+ ret = zram_bvec_read(zram, bvec, index, offset, bio);
+ up_read(&zram->lock);
+ } else {
+ down_write(&zram->lock);
+ ret = zram_bvec_write(zram, bvec, index, offset);
+ up_write(&zram->lock);
+ }
+
+ return ret;
+}
+
+static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
+{
+ if (*offset + bvec->bv_len >= PAGE_SIZE)
+ (*index)++;
+ *offset = (*offset + bvec->bv_len) % PAGE_SIZE;
+}
+
+static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
+{
+ int i, offset;
+ u32 index;
+ struct bio_vec *bvec;
+
+ switch (rw) {
+ case READ:
+ zram_stat64_inc(zram, &zram->stats.num_reads);
+ break;
+ case WRITE:
+ zram_stat64_inc(zram, &zram->stats.num_writes);
+ break;
+ }
+
+ index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+ offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
- /* Update stats */
- zram_stat64_add(zram, &zram->stats.compr_size, clen);
- zram_stat_inc(&zram->stats.pages_stored);
- if (clen <= PAGE_SIZE / 2)
- zram_stat_inc(&zram->stats.good_compress);
+ bio_for_each_segment(bvec, bio, i) {
+ int max_transfer_size = PAGE_SIZE - offset;
+
+ if (bvec->bv_len > max_transfer_size) {
+ /*
+ * zram_bvec_rw() can only make operation on a single
+ * zram page. Split the bio vector.
+ */
+ struct bio_vec bv;
+
+ bv.bv_page = bvec->bv_page;
+ bv.bv_len = max_transfer_size;
+ bv.bv_offset = bvec->bv_offset;
+
+ if (zram_bvec_rw(zram, &bv, index, offset, bio, rw) < 0)
+ goto out;
+
+ bv.bv_len = bvec->bv_len - max_transfer_size;
+ bv.bv_offset += max_transfer_size;
+ if (zram_bvec_rw(zram, &bv, index+1, 0, bio, rw) < 0)
+ goto out;
+ } else
+ if (zram_bvec_rw(zram, bvec, index, offset, bio, rw)
+ < 0)
+ goto out;
- mutex_unlock(&zram->lock);
- index++;
+ update_position(&index, &offset, bvec);
}
set_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -426,17 +537,24 @@ out:
}
/*
- * Check if request is within bounds and page aligned.
+ * Check if request is within bounds and aligned on zram logical blocks.
*/
static inline int valid_io_request(struct zram *zram, struct bio *bio)
{
- if (unlikely(
- (bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) ||
- (bio->bi_sector & (SECTORS_PER_PAGE - 1)) ||
- (bio->bi_size & (PAGE_SIZE - 1)))) {
+ u64 start, end, bound;
+
+ /* unaligned request */
+ if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
+ return 0;
+ if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
+ return 0;
+ start = bio->bi_sector;
+ end = start + (bio->bi_size >> SECTOR_SHIFT);
+ bound = zram->disksize >> SECTOR_SHIFT;
+ /* out of range range */
+ if (unlikely(start >= bound || end > bound || start > end))
return 0;
- }
/* I/O request is valid */
return 1;
@@ -445,39 +563,37 @@ static inline int valid_io_request(struct zram *zram, struct bio *bio)
/*
* Handler function for all zram I/O requests.
*/
-static int zram_make_request(struct request_queue *queue, struct bio *bio)
+static void zram_make_request(struct request_queue *queue, struct bio *bio)
{
struct zram *zram = queue->queuedata;
+ if (unlikely(!zram->init_done) && zram_init_device(zram))
+ goto error;
+
+ down_read(&zram->init_lock);
+ if (unlikely(!zram->init_done))
+ goto error_unlock;
+
if (!valid_io_request(zram, bio)) {
zram_stat64_inc(zram, &zram->stats.invalid_io);
- bio_io_error(bio);
- return 0;
+ goto error_unlock;
}
- if (unlikely(!zram->init_done) && zram_init_device(zram)) {
- bio_io_error(bio);
- return 0;
- }
+ __zram_make_request(zram, bio, bio_data_dir(bio));
+ up_read(&zram->init_lock);
- switch (bio_data_dir(bio)) {
- case READ:
- zram_read(zram, bio);
- break;
-
- case WRITE:
- zram_write(zram, bio);
- break;
- }
+ return;
- return 0;
+error_unlock:
+ up_read(&zram->init_lock);
+error:
+ bio_io_error(bio);
}
-void zram_reset_device(struct zram *zram)
+void __zram_reset_device(struct zram *zram)
{
size_t index;
- mutex_lock(&zram->init_lock);
zram->init_done = 0;
/* Free various per-device buffers */
@@ -514,22 +630,24 @@ void zram_reset_device(struct zram *zram)
memset(&zram->stats, 0, sizeof(zram->stats));
zram->disksize = 0;
- mutex_unlock(&zram->init_lock);
+}
+
+void zram_reset_device(struct zram *zram)
+{
+ down_write(&zram->init_lock);
+ __zram_reset_device(zram);
+ up_write(&zram->init_lock);
}
int zram_init_device(struct zram *zram)
{
int ret;
size_t num_pages;
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- struct page *page;
- union swap_header *swap_header;
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
- mutex_lock(&zram->init_lock);
+ down_write(&zram->init_lock);
if (zram->init_done) {
- mutex_unlock(&zram->init_lock);
+ up_write(&zram->init_lock);
return 0;
}
@@ -539,39 +657,24 @@ int zram_init_device(struct zram *zram)
if (!zram->compress_workmem) {
pr_err("Error allocating compressor working memory!\n");
ret = -ENOMEM;
- goto fail;
+ goto fail_no_table;
}
zram->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1);
if (!zram->compress_buffer) {
pr_err("Error allocating compressor buffer space\n");
ret = -ENOMEM;
- goto fail;
+ goto fail_no_table;
}
num_pages = zram->disksize >> PAGE_SHIFT;
zram->table = vzalloc(num_pages * sizeof(*zram->table));
if (!zram->table) {
pr_err("Error allocating zram address table\n");
- /* To prevent accessing table entries during cleanup */
- zram->disksize = 0;
ret = -ENOMEM;
- goto fail;
+ goto fail_no_table;
}
-#ifdef CONFIG_ZRAM_FOR_ANDROID
- page = alloc_page(__GFP_ZERO);
- if (!page) {
- pr_err("Error allocating swap header page\n");
- ret = -ENOMEM;
- goto fail;
- }
- zram->table[0].page = page;
- zram_set_flag(zram, 0, ZRAM_UNCOMPRESSED);
- swap_header = kmap(page);
- setup_swap_header(zram, swap_header);
- kunmap(page);
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
/* zram devices sort of resembles non-rotational disks */
@@ -585,20 +688,23 @@ int zram_init_device(struct zram *zram)
}
zram->init_done = 1;
- mutex_unlock(&zram->init_lock);
+ up_write(&zram->init_lock);
pr_debug("Initialization done!\n");
return 0;
+fail_no_table:
+ /* To prevent accessing table entries during cleanup */
+ zram->disksize = 0;
fail:
- mutex_unlock(&zram->init_lock);
- zram_reset_device(zram);
-
+ __zram_reset_device(zram);
+ up_write(&zram->init_lock);
pr_err("Initialization failed: err=%d\n", ret);
return ret;
}
-void zram_slot_free_notify(struct block_device *bdev, unsigned long index)
+static void zram_slot_free_notify(struct block_device *bdev,
+ unsigned long index)
{
struct zram *zram;
@@ -614,17 +720,16 @@ static const struct block_device_operations zram_devops = {
static int create_device(struct zram *zram, int device_id)
{
- int ret = 0;
+ int ret = -ENOMEM;
- mutex_init(&zram->lock);
- mutex_init(&zram->init_lock);
+ init_rwsem(&zram->lock);
+ init_rwsem(&zram->init_lock);
spin_lock_init(&zram->stat64_lock);
zram->queue = blk_alloc_queue(GFP_KERNEL);
if (!zram->queue) {
pr_err("Error allocating disk queue for device %d\n",
device_id);
- ret = -ENOMEM;
goto out;
}
@@ -634,11 +739,9 @@ static int create_device(struct zram *zram, int device_id)
/* gendisk structure */
zram->disk = alloc_disk(1);
if (!zram->disk) {
- blk_cleanup_queue(zram->queue);
pr_warning("Error allocating disk structure for device %d\n",
device_id);
- ret = -ENOMEM;
- goto out;
+ goto out_free_queue;
}
zram->disk->major = zram_major;
@@ -667,11 +770,17 @@ static int create_device(struct zram *zram, int device_id)
&zram_disk_attr_group);
if (ret < 0) {
pr_warning("Error creating sysfs group");
- goto out;
+ goto out_free_disk;
}
zram->init_done = 0;
+ return 0;
+out_free_disk:
+ del_gendisk(zram->disk);
+ put_disk(zram->disk);
+out_free_queue:
+ blk_cleanup_queue(zram->queue);
out:
return ret;
}
@@ -694,9 +803,9 @@ static int __init zram_init(void)
{
int ret, dev_id;
- if (num_devices > max_num_devices) {
+ if (zram_num_devices > max_num_devices) {
pr_warning("Invalid value for num_devices: %u\n",
- num_devices);
+ zram_num_devices);
ret = -EINVAL;
goto out;
}
@@ -708,20 +817,20 @@ static int __init zram_init(void)
goto out;
}
- if (!num_devices) {
+ if (!zram_num_devices) {
pr_info("num_devices not specified. Using default: 1\n");
- num_devices = 1;
+ zram_num_devices = 1;
}
/* Allocate the device array and initialize each one */
- pr_info("Creating %u devices ...\n", num_devices);
- zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
+ pr_info("Creating %u devices ...\n", zram_num_devices);
+ zram_devices = kzalloc(zram_num_devices * sizeof(struct zram), GFP_KERNEL);
if (!zram_devices) {
ret = -ENOMEM;
goto unregister;
}
- for (dev_id = 0; dev_id < num_devices; dev_id++) {
+ for (dev_id = 0; dev_id < zram_num_devices; dev_id++) {
ret = create_device(&zram_devices[dev_id], dev_id);
if (ret)
goto free_devices;
@@ -744,12 +853,14 @@ static void __exit zram_exit(void)
int i;
struct zram *zram;
- for (i = 0; i < num_devices; i++) {
+ for (i = 0; i < zram_num_devices; i++) {
zram = &zram_devices[i];
+ get_disk(zram->disk);
destroy_device(zram);
if (zram->init_done)
zram_reset_device(zram);
+ put_disk(zram->disk);
}
unregister_blkdev(zram_major, "zram");
@@ -758,8 +869,8 @@ static void __exit zram_exit(void)
pr_debug("Cleanup done!\n");
}
-module_param(num_devices, uint, 0);
-MODULE_PARM_DESC(num_devices, "Number of zram devices");
+module_param(zram_num_devices, uint, 0);
+MODULE_PARM_DESC(zram_num_devices, "Number of zram devices");
module_init(zram_init);
module_exit(zram_exit);
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index 3ad9486..e5cd246 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -47,7 +47,7 @@ static const unsigned default_disksize_perc_ram = 25;
* Pages that compress to size greater than this are stored
* uncompressed in memory.
*/
-static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3;
+static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
/*
* NOTE: max_zpage_size must be less than or equal to:
@@ -61,7 +61,10 @@ static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3;
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)
-#define ZRAM_LOGICAL_BLOCK_SIZE 4096
+#define ZRAM_LOGICAL_BLOCK_SHIFT 12
+#define ZRAM_LOGICAL_BLOCK_SIZE (1 << ZRAM_LOGICAL_BLOCK_SHIFT)
+#define ZRAM_SECTOR_PER_LOGICAL_BLOCK \
+ (1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
/* Flags for zram pages (table[page_no].flags) */
enum zram_pageflags {
@@ -104,13 +107,13 @@ struct zram {
void *compress_buffer;
struct table *table;
spinlock_t stat64_lock; /* protect 64-bit stats */
- struct mutex lock; /* protect compression buffers against
- * concurrent writes */
+ struct rw_semaphore lock; /* protect compression buffers and table
+ * against concurrent read and writes */
struct request_queue *queue;
struct gendisk *disk;
int init_done;
- /* Prevent concurrent execution of device init and reset */
- struct mutex init_lock;
+ /* Prevent concurrent execution of device init, reset and R/W request */
+ struct rw_semaphore init_lock;
/*
* This is the limit on amount of *uncompressed* worth of data
* we can store in a disk.
@@ -121,12 +124,12 @@ struct zram {
};
extern struct zram *zram_devices;
-extern unsigned int num_devices;
+extern unsigned int zram_num_devices;
#ifdef CONFIG_SYSFS
extern struct attribute_group zram_disk_attr_group;
#endif
extern int zram_init_device(struct zram *zram);
-extern void zram_reset_device(struct zram *zram);
+extern void __zram_reset_device(struct zram *zram);
#endif
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c
index 8a23554..fc552d8 100644
--- a/drivers/staging/zram/zram_sysfs.c
+++ b/drivers/staging/zram/zram_sysfs.c
@@ -34,7 +34,7 @@ static struct zram *dev_to_zram(struct device *dev)
int i;
struct zram *zram = NULL;
- for (i = 0; i < num_devices; i++) {
+ for (i = 0; i < zram_num_devices; i++) {
zram = &zram_devices[i];
if (disk_to_dev(zram->disk) == dev)
break;
@@ -55,19 +55,23 @@ static ssize_t disksize_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
int ret;
+ u64 disksize;
struct zram *zram = dev_to_zram(dev);
+ ret = strict_strtoull(buf, 10, &disksize);
+ if (ret)
+ return ret;
+
+ down_write(&zram->init_lock);
if (zram->init_done) {
+ up_write(&zram->init_lock);
pr_info("Cannot change disksize for initialized device\n");
return -EBUSY;
}
- ret = strict_strtoull(buf, 10, &zram->disksize);
- if (ret)
- return ret;
-
- zram->disksize = PAGE_ALIGN(zram->disksize);
+ zram->disksize = PAGE_ALIGN(disksize);
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
+ up_write(&zram->init_lock);
return len;
}
@@ -80,42 +84,6 @@ static ssize_t initstate_show(struct device *dev,
return sprintf(buf, "%u\n", zram->init_done);
}
-#ifdef CONFIG_ZRAM_FOR_ANDROID
-extern int swapon(const char*specialfile, int swap_flags);
-
-static ssize_t initstate_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t len)
-{
- int ret;
- unsigned long do_init;
- struct zram *zram = dev_to_zram(dev);
-
- if (zram->init_done) {
- pr_info("the device is initialized device\n");
- return -EBUSY;
- }
-
- ret = strict_strtoul(buf, 10, &do_init);
- if (ret)
- return ret;
- if (!do_init)
- return -EINVAL;
-
- zram_init_device(zram);
- swapon("/dev/block/zram0", 0);
- return len;
-}
-#else
-static inline ssize_t initstate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- return 0;
-}
-#endif /* CONFIG_ZRAM_FOR_ANDROID */
-
-
static ssize_t reset_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
@@ -127,25 +95,38 @@ static ssize_t reset_store(struct device *dev,
zram = dev_to_zram(dev);
bdev = bdget_disk(zram->disk, 0);
+ if (!bdev)
+ return -ENOMEM;
+
/* Do not reset an active device! */
- if (bdev->bd_holders)
- return -EBUSY;
+ if (bdev->bd_holders) {
+ ret = -EBUSY;
+ goto out;
+ }
ret = strict_strtoul(buf, 10, &do_reset);
if (ret)
- return ret;
+ goto out;
- if (!do_reset)
- return -EINVAL;
+ if (!do_reset) {
+ ret = -EINVAL;
+ goto out;
+ }
/* Make sure all pending I/O is finished */
- if (bdev)
- fsync_bdev(bdev);
+ fsync_bdev(bdev);
+ bdput(bdev);
+ down_write(&zram->init_lock);
if (zram->init_done)
- zram_reset_device(zram);
+ __zram_reset_device(zram);
+ up_write(&zram->init_lock);
return len;
+
+out:
+ bdput(bdev);
+ return ret;
}
static ssize_t num_reads_show(struct device *dev,
@@ -216,17 +197,19 @@ static ssize_t mem_used_total_show(struct device *dev,
u64 val = 0;
struct zram *zram = dev_to_zram(dev);
+ down_read(&zram->init_lock);
if (zram->init_done) {
val = xv_get_total_size_bytes(zram->mem_pool) +
((u64)(zram->stats.pages_expand) << PAGE_SHIFT);
}
+ up_read(&zram->init_lock);
return sprintf(buf, "%llu\n", val);
}
static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
disksize_show, disksize_store);
-static DEVICE_ATTR(initstate, S_IRUGO | S_IWUSR, initstate_show, initstate_store);
+static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL);
static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL);
diff --git a/drivers/target/loopback/Kconfig b/drivers/target/loopback/Kconfig
index 57dcbc2..abe8ecb 100644
--- a/drivers/target/loopback/Kconfig
+++ b/drivers/target/loopback/Kconfig
@@ -3,9 +3,3 @@ config LOOPBACK_TARGET
help
Say Y here to enable the TCM Virtual SAS target and Linux/SCSI LLD
fabric loopback module.
-
-config LOOPBACK_TARGET_CDB_DEBUG
- bool "TCM loopback fabric module CDB debug code"
- depends on LOOPBACK_TARGET
- help
- Say Y here to enable the TCM loopback fabric module CDB debug code
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index f7c3cfb..5d1d4f2 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -31,7 +31,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_tcq.h>
#include <target/target_core_base.h>
#include <target/target_core_transport.h>
@@ -80,7 +79,7 @@ static struct se_cmd *tcm_loop_allocate_core_cmd(
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
if (!tl_cmd) {
- printk(KERN_ERR "Unable to allocate struct tcm_loop_cmd\n");
+ pr_err("Unable to allocate struct tcm_loop_cmd\n");
set_host_byte(sc, DID_ERROR);
return NULL;
}
@@ -114,39 +113,18 @@ static struct se_cmd *tcm_loop_allocate_core_cmd(
scsi_bufflen(sc), sc->sc_data_direction, sam_task_attr,
&tl_cmd->tl_sense_buf[0]);
- /*
- * Signal BIDI usage with T_TASK(cmd)->t_tasks_bidi
- */
if (scsi_bidi_cmnd(sc))
- T_TASK(se_cmd)->t_tasks_bidi = 1;
+ se_cmd->se_cmd_flags |= SCF_BIDI;
+
/*
* Locate the struct se_lun pointer and attach it to struct se_cmd
*/
- if (transport_get_lun_for_cmd(se_cmd, NULL, tl_cmd->sc->device->lun) < 0) {
+ if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) {
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
set_host_byte(sc, DID_NO_CONNECT);
return NULL;
}
- /*
- * Because some userspace code via scsi-generic do not memset their
- * associated read buffers, go ahead and do that here for type
- * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
- * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
- * by target core in transport_generic_allocate_tasks() ->
- * transport_generic_cmd_sequencer().
- */
- if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
- se_cmd->data_direction == DMA_FROM_DEVICE) {
- struct scatterlist *sg = scsi_sglist(sc);
- unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
-
- if (buf != NULL) {
- memset(buf, 0, sg->length);
- kunmap(sg_page(sg));
- }
- }
- transport_device_setup_cmd(se_cmd);
return se_cmd;
}
@@ -161,67 +139,53 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
struct tcm_loop_cmd, tl_se_cmd);
struct scsi_cmnd *sc = tl_cmd->sc;
- void *mem_ptr, *mem_bidi_ptr = NULL;
- u32 sg_no_bidi = 0;
+ struct scatterlist *sgl_bidi = NULL;
+ u32 sgl_bidi_count = 0;
int ret;
/*
* Allocate the necessary tasks to complete the received CDB+data
*/
- ret = transport_generic_allocate_tasks(se_cmd, tl_cmd->sc->cmnd);
- if (ret == -1) {
- /* Out of Resources */
- return PYX_TRANSPORT_LU_COMM_FAILURE;
- } else if (ret == -2) {
- /*
- * Handle case for SAM_STAT_RESERVATION_CONFLICT
- */
- if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
- return PYX_TRANSPORT_RESERVATION_CONFLICT;
- /*
- * Otherwise, return SAM_STAT_CHECK_CONDITION and return
- * sense data.
- */
- return PYX_TRANSPORT_USE_SENSE_REASON;
- }
+ ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd);
+ if (ret != 0)
+ return ret;
/*
- * Setup the struct scatterlist memory from the received
- * struct scsi_cmnd.
+ * For BIDI commands, pass in the extra READ buffer
+ * to transport_generic_map_mem_to_cmd() below..
*/
- if (scsi_sg_count(sc)) {
- se_cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM;
- mem_ptr = (void *)scsi_sglist(sc);
- /*
- * For BIDI commands, pass in the extra READ buffer
- * to transport_generic_map_mem_to_cmd() below..
- */
- if (T_TASK(se_cmd)->t_tasks_bidi) {
- struct scsi_data_buffer *sdb = scsi_in(sc);
-
- mem_bidi_ptr = (void *)sdb->table.sgl;
- sg_no_bidi = sdb->table.nents;
- }
- } else {
- /*
- * Used for DMA_NONE
- */
- mem_ptr = NULL;
+ if (se_cmd->se_cmd_flags & SCF_BIDI) {
+ struct scsi_data_buffer *sdb = scsi_in(sc);
+
+ sgl_bidi = sdb->table.sgl;
+ sgl_bidi_count = sdb->table.nents;
}
/*
- * Map the SG memory into struct se_mem->page linked list using the same
- * physical memory at sg->page_link.
+ * Because some userspace code via scsi-generic do not memset their
+ * associated read buffers, go ahead and do that here for type
+ * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
+ * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
+ * by target core in transport_generic_allocate_tasks() ->
+ * transport_generic_cmd_sequencer().
*/
- ret = transport_generic_map_mem_to_cmd(se_cmd, mem_ptr,
- scsi_sg_count(sc), mem_bidi_ptr, sg_no_bidi);
- if (ret < 0)
- return PYX_TRANSPORT_LU_COMM_FAILURE;
+ if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
+ se_cmd->data_direction == DMA_FROM_DEVICE) {
+ struct scatterlist *sg = scsi_sglist(sc);
+ unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
- return 0;
+ if (buf != NULL) {
+ memset(buf, 0, sg->length);
+ kunmap(sg_page(sg));
+ }
+ }
+
+ /* Tell the core about our preallocated memory */
+ return transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
+ scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
}
/*
* Called from struct target_core_fabric_ops->check_stop_free()
*/
-static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
+static int tcm_loop_check_stop_free(struct se_cmd *se_cmd)
{
/*
* Do not release struct se_cmd's containing a valid TMR
@@ -229,18 +193,16 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
* with transport_generic_free_cmd().
*/
if (se_cmd->se_tmr_req)
- return;
+ return 0;
/*
* Release the struct se_cmd, which will make a callback to release
* struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
*/
- transport_generic_free_cmd(se_cmd, 0, 1, 0);
+ transport_generic_free_cmd(se_cmd, 0);
+ return 1;
}
-/*
- * Called from struct target_core_fabric_ops->release_cmd_to_pool()
- */
-static void tcm_loop_deallocate_core_cmd(struct se_cmd *se_cmd)
+static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
{
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
struct tcm_loop_cmd, tl_se_cmd);
@@ -318,7 +280,7 @@ static int tcm_loop_queuecommand(
struct tcm_loop_hba *tl_hba;
struct tcm_loop_tpg *tl_tpg;
- TL_CDB_DEBUG("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
+ pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
" scsi_buf_len: %u\n", sc->device->host->host_no,
sc->device->id, sc->device->channel, sc->device->lun,
sc->cmnd[0], scsi_bufflen(sc));
@@ -327,6 +289,15 @@ static int tcm_loop_queuecommand(
*/
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
+ /*
+ * Ensure that this tl_tpg reference from the incoming sc->device->id
+ * has already been configured via tcm_loop_make_naa_tpg().
+ */
+ if (!tl_tpg->tl_hba) {
+ set_host_byte(sc, DID_NO_CONNECT);
+ sc->scsi_done(sc);
+ return 0;
+ }
se_tpg = &tl_tpg->tl_se_tpg;
/*
* Determine the SAM Task Attribute and allocate tl_cmd and
@@ -368,7 +339,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
*/
tl_nexus = tl_hba->tl_nexus;
if (!tl_nexus) {
- printk(KERN_ERR "Unable to perform device reset without"
+ pr_err("Unable to perform device reset without"
" active I_T Nexus\n");
return FAILED;
}
@@ -381,13 +352,13 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
if (!tl_cmd) {
- printk(KERN_ERR "Unable to allocate memory for tl_cmd\n");
+ pr_err("Unable to allocate memory for tl_cmd\n");
return FAILED;
}
tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
if (!tl_tmr) {
- printk(KERN_ERR "Unable to allocate memory for tl_tmr\n");
+ pr_err("Unable to allocate memory for tl_tmr\n");
goto release;
}
init_waitqueue_head(&tl_tmr->tl_tmr_wait);
@@ -402,14 +373,14 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
/*
* Allocate the LUN_RESET TMR
*/
- se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, (void *)tl_tmr,
- TMR_LUN_RESET);
+ se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr,
+ TMR_LUN_RESET, GFP_KERNEL);
if (IS_ERR(se_cmd->se_tmr_req))
goto release;
/*
* Locate the underlying TCM struct se_lun from sc->device->lun
*/
- if (transport_get_lun_for_tmr(se_cmd, sc->device->lun) < 0)
+ if (transport_lookup_tmr_lun(se_cmd, sc->device->lun) < 0)
goto release;
/*
* Queue the TMR to TCM Core and sleep waiting for tcm_loop_queue_tm_rsp()
@@ -425,7 +396,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
SUCCESS : FAILED;
release:
if (se_cmd)
- transport_generic_free_cmd(se_cmd, 1, 1, 0);
+ transport_generic_free_cmd(se_cmd, 1);
else
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
kfree(tl_tmr);
@@ -472,7 +443,7 @@ static int tcm_loop_driver_probe(struct device *dev)
sh = scsi_host_alloc(&tcm_loop_driver_template,
sizeof(struct tcm_loop_hba));
if (!sh) {
- printk(KERN_ERR "Unable to allocate struct scsi_host\n");
+ pr_err("Unable to allocate struct scsi_host\n");
return -ENODEV;
}
tl_hba->sh = sh;
@@ -491,7 +462,7 @@ static int tcm_loop_driver_probe(struct device *dev)
error = scsi_add_host(sh, &tl_hba->dev);
if (error) {
- printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
+ pr_err("%s: scsi_add_host failed\n", __func__);
scsi_host_put(sh);
return -ENODEV;
}
@@ -532,7 +503,7 @@ static int tcm_loop_setup_hba_bus(struct tcm_loop_hba *tl_hba, int tcm_loop_host
ret = device_register(&tl_hba->dev);
if (ret) {
- printk(KERN_ERR "device_register() failed for"
+ pr_err("device_register() failed for"
" tl_hba->dev: %d\n", ret);
return -ENODEV;
}
@@ -550,24 +521,24 @@ static int tcm_loop_alloc_core_bus(void)
tcm_loop_primary = root_device_register("tcm_loop_0");
if (IS_ERR(tcm_loop_primary)) {
- printk(KERN_ERR "Unable to allocate tcm_loop_primary\n");
+ pr_err("Unable to allocate tcm_loop_primary\n");
return PTR_ERR(tcm_loop_primary);
}
ret = bus_register(&tcm_loop_lld_bus);
if (ret) {
- printk(KERN_ERR "bus_register() failed for tcm_loop_lld_bus\n");
+ pr_err("bus_register() failed for tcm_loop_lld_bus\n");
goto dev_unreg;
}
ret = driver_register(&tcm_loop_driverfs);
if (ret) {
- printk(KERN_ERR "driver_register() failed for"
+ pr_err("driver_register() failed for"
"tcm_loop_driverfs\n");
goto bus_unreg;
}
- printk(KERN_INFO "Initialized TCM Loop Core Bus\n");
+ pr_debug("Initialized TCM Loop Core Bus\n");
return ret;
bus_unreg:
@@ -583,7 +554,7 @@ static void tcm_loop_release_core_bus(void)
bus_unregister(&tcm_loop_lld_bus);
root_device_unregister(tcm_loop_primary);
- printk(KERN_INFO "Releasing TCM Loop Core BUS\n");
+ pr_debug("Releasing TCM Loop Core BUS\n");
}
static char *tcm_loop_get_fabric_name(void)
@@ -611,7 +582,7 @@ static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_fabric_proto_ident(se_tpg);
default:
- printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+ pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
@@ -667,7 +638,7 @@ static u32 tcm_loop_get_pr_transport_id(
return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
default:
- printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+ pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
@@ -697,7 +668,7 @@ static u32 tcm_loop_get_pr_transport_id_len(
return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
default:
- printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+ pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
@@ -731,7 +702,7 @@ static char *tcm_loop_parse_pr_out_transport_id(
return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
default:
- printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+ pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
@@ -780,7 +751,7 @@ static struct se_node_acl *tcm_loop_tpg_alloc_fabric_acl(
tl_nacl = kzalloc(sizeof(struct tcm_loop_nacl), GFP_KERNEL);
if (!tl_nacl) {
- printk(KERN_ERR "Unable to allocate struct tcm_loop_nacl\n");
+ pr_err("Unable to allocate struct tcm_loop_nacl\n");
return NULL;
}
@@ -802,16 +773,6 @@ static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg)
return 1;
}
-static void tcm_loop_new_cmd_failure(struct se_cmd *se_cmd)
-{
- /*
- * Since TCM_loop is already passing struct scatterlist data from
- * struct scsi_cmnd, no more Linux/SCSI failure dependent state need
- * to be handled here.
- */
- return;
-}
-
static int tcm_loop_is_state_remove(struct se_cmd *se_cmd)
{
/*
@@ -900,7 +861,7 @@ static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
struct tcm_loop_cmd, tl_se_cmd);
struct scsi_cmnd *sc = tl_cmd->sc;
- TL_CDB_DEBUG("tcm_loop_queue_data_in() called for scsi_cmnd: %p"
+ pr_debug("tcm_loop_queue_data_in() called for scsi_cmnd: %p"
" cdb: 0x%02x\n", sc, sc->cmnd[0]);
sc->result = SAM_STAT_GOOD;
@@ -918,14 +879,14 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
struct tcm_loop_cmd, tl_se_cmd);
struct scsi_cmnd *sc = tl_cmd->sc;
- TL_CDB_DEBUG("tcm_loop_queue_status() called for scsi_cmnd: %p"
+ pr_debug("tcm_loop_queue_status() called for scsi_cmnd: %p"
" cdb: 0x%02x\n", sc, sc->cmnd[0]);
if (se_cmd->sense_buffer &&
((se_cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
(se_cmd->se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
- memcpy((void *)sc->sense_buffer, (void *)se_cmd->sense_buffer,
+ memcpy(sc->sense_buffer, se_cmd->sense_buffer,
SCSI_SENSE_BUFFERSIZE);
sc->result = SAM_STAT_CHECK_CONDITION;
set_driver_byte(sc, DRIVER_SENSE);
@@ -996,7 +957,7 @@ static int tcm_loop_port_link(
*/
scsi_add_device(tl_hba->sh, 0, tl_tpg->tl_tpgt, lun->unpacked_lun);
- printk(KERN_INFO "TCM_Loop_ConfigFS: Port Link Successful\n");
+ pr_debug("TCM_Loop_ConfigFS: Port Link Successful\n");
return 0;
}
@@ -1014,7 +975,7 @@ static void tcm_loop_port_unlink(
sd = scsi_device_lookup(tl_hba->sh, 0, tl_tpg->tl_tpgt,
se_lun->unpacked_lun);
if (!sd) {
- printk(KERN_ERR "Unable to locate struct scsi_device for %d:%d:"
+ pr_err("Unable to locate struct scsi_device for %d:%d:"
"%d\n", 0, tl_tpg->tl_tpgt, se_lun->unpacked_lun);
return;
}
@@ -1027,7 +988,7 @@ static void tcm_loop_port_unlink(
atomic_dec(&tl_tpg->tl_tpg_port_count);
smp_mb__after_atomic_dec();
- printk(KERN_INFO "TCM_Loop_ConfigFS: Port Unlink Successful\n");
+ pr_debug("TCM_Loop_ConfigFS: Port Unlink Successful\n");
}
/* End items for tcm_loop_port_cit */
@@ -1044,14 +1005,14 @@ static int tcm_loop_make_nexus(
int ret = -ENOMEM;
if (tl_tpg->tl_hba->tl_nexus) {
- printk(KERN_INFO "tl_tpg->tl_hba->tl_nexus already exists\n");
+ pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n");
return -EEXIST;
}
se_tpg = &tl_tpg->tl_se_tpg;
tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
if (!tl_nexus) {
- printk(KERN_ERR "Unable to allocate struct tcm_loop_nexus\n");
+ pr_err("Unable to allocate struct tcm_loop_nexus\n");
return -ENOMEM;
}
/*
@@ -1078,9 +1039,9 @@ static int tcm_loop_make_nexus(
* transport_register_session()
*/
__transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
- tl_nexus->se_sess, (void *)tl_nexus);
+ tl_nexus->se_sess, tl_nexus);
tl_tpg->tl_hba->tl_nexus = tl_nexus;
- printk(KERN_INFO "TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
+ pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
name);
return 0;
@@ -1106,13 +1067,13 @@ static int tcm_loop_drop_nexus(
return -ENODEV;
if (atomic_read(&tpg->tl_tpg_port_count)) {
- printk(KERN_ERR "Unable to remove TCM_Loop I_T Nexus with"
+ pr_err("Unable to remove TCM_Loop I_T Nexus with"
" active TPG port count: %d\n",
atomic_read(&tpg->tl_tpg_port_count));
return -EPERM;
}
- printk(KERN_INFO "TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
+ pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
tl_nexus->se_sess->se_node_acl->initiatorname);
/*
@@ -1168,7 +1129,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
* tcm_loop_make_nexus()
*/
if (strlen(page) >= TL_WWN_ADDR_LEN) {
- printk(KERN_ERR "Emulated NAA Sas Address: %s, exceeds"
+ pr_err("Emulated NAA Sas Address: %s, exceeds"
" max: %d\n", page, TL_WWN_ADDR_LEN);
return -EINVAL;
}
@@ -1177,7 +1138,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
ptr = strstr(i_port, "naa.");
if (ptr) {
if (tl_hba->tl_proto_id != SCSI_PROTOCOL_SAS) {
- printk(KERN_ERR "Passed SAS Initiator Port %s does not"
+ pr_err("Passed SAS Initiator Port %s does not"
" match target port protoid: %s\n", i_port,
tcm_loop_dump_proto_id(tl_hba));
return -EINVAL;
@@ -1188,7 +1149,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
ptr = strstr(i_port, "fc.");
if (ptr) {
if (tl_hba->tl_proto_id != SCSI_PROTOCOL_FCP) {
- printk(KERN_ERR "Passed FCP Initiator Port %s does not"
+ pr_err("Passed FCP Initiator Port %s does not"
" match target port protoid: %s\n", i_port,
tcm_loop_dump_proto_id(tl_hba));
return -EINVAL;
@@ -1199,7 +1160,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
ptr = strstr(i_port, "iqn.");
if (ptr) {
if (tl_hba->tl_proto_id != SCSI_PROTOCOL_ISCSI) {
- printk(KERN_ERR "Passed iSCSI Initiator Port %s does not"
+ pr_err("Passed iSCSI Initiator Port %s does not"
" match target port protoid: %s\n", i_port,
tcm_loop_dump_proto_id(tl_hba));
return -EINVAL;
@@ -1207,7 +1168,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
port_ptr = &i_port[0];
goto check_newline;
}
- printk(KERN_ERR "Unable to locate prefix for emulated Initiator Port:"
+ pr_err("Unable to locate prefix for emulated Initiator Port:"
" %s\n", i_port);
return -EINVAL;
/*
@@ -1247,15 +1208,15 @@ struct se_portal_group *tcm_loop_make_naa_tpg(
tpgt_str = strstr(name, "tpgt_");
if (!tpgt_str) {
- printk(KERN_ERR "Unable to locate \"tpgt_#\" directory"
+ pr_err("Unable to locate \"tpgt_#\" directory"
" group\n");
return ERR_PTR(-EINVAL);
}
tpgt_str += 5; /* Skip ahead of "tpgt_" */
tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);
- if (tpgt > TL_TPGS_PER_HBA) {
- printk(KERN_ERR "Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
+ if (tpgt >= TL_TPGS_PER_HBA) {
+ pr_err("Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
" %u\n", tpgt, TL_TPGS_PER_HBA);
return ERR_PTR(-EINVAL);
}
@@ -1266,12 +1227,12 @@ struct se_portal_group *tcm_loop_make_naa_tpg(
* Register the tl_tpg as a emulated SAS TCM Target Endpoint
*/
ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
- wwn, &tl_tpg->tl_se_tpg, (void *)tl_tpg,
+ wwn, &tl_tpg->tl_se_tpg, tl_tpg,
TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0)
return ERR_PTR(-ENOMEM);
- printk(KERN_INFO "TCM_Loop_ConfigFS: Allocated Emulated %s"
+ pr_debug("TCM_Loop_ConfigFS: Allocated Emulated %s"
" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
config_item_name(&wwn->wwn_group.cg_item), tpgt);
@@ -1298,7 +1259,10 @@ void tcm_loop_drop_naa_tpg(
*/
core_tpg_deregister(se_tpg);
- printk(KERN_INFO "TCM_Loop_ConfigFS: Deallocated Emulated %s"
+ tl_tpg->tl_hba = NULL;
+ tl_tpg->tl_tpgt = 0;
+
+ pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s"
" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
config_item_name(&wwn->wwn_group.cg_item), tpgt);
}
@@ -1319,7 +1283,7 @@ struct se_wwn *tcm_loop_make_scsi_hba(
tl_hba = kzalloc(sizeof(struct tcm_loop_hba), GFP_KERNEL);
if (!tl_hba) {
- printk(KERN_ERR "Unable to allocate struct tcm_loop_hba\n");
+ pr_err("Unable to allocate struct tcm_loop_hba\n");
return ERR_PTR(-ENOMEM);
}
/*
@@ -1338,22 +1302,21 @@ struct se_wwn *tcm_loop_make_scsi_hba(
goto check_len;
}
ptr = strstr(name, "iqn.");
- if (ptr) {
- tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;
- goto check_len;
+ if (!ptr) {
+ pr_err("Unable to locate prefix for emulated Target "
+ "Port: %s\n", name);
+ ret = -EINVAL;
+ goto out;
}
-
- printk(KERN_ERR "Unable to locate prefix for emulated Target Port:"
- " %s\n", name);
- return ERR_PTR(-EINVAL);
+ tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;
check_len:
if (strlen(name) >= TL_WWN_ADDR_LEN) {
- printk(KERN_ERR "Emulated NAA %s Address: %s, exceeds"
+ pr_err("Emulated NAA %s Address: %s, exceeds"
" max: %d\n", name, tcm_loop_dump_proto_id(tl_hba),
TL_WWN_ADDR_LEN);
- kfree(tl_hba);
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto out;
}
snprintf(&tl_hba->tl_wwn_address[0], TL_WWN_ADDR_LEN, "%s", &name[off]);
@@ -1368,7 +1331,7 @@ check_len:
sh = tl_hba->sh;
tcm_loop_hba_no_cnt++;
- printk(KERN_INFO "TCM_Loop_ConfigFS: Allocated emulated Target"
+ pr_debug("TCM_Loop_ConfigFS: Allocated emulated Target"
" %s Address: %s at Linux/SCSI Host ID: %d\n",
tcm_loop_dump_proto_id(tl_hba), name, sh->host_no);
@@ -1383,17 +1346,16 @@ void tcm_loop_drop_scsi_hba(
{
struct tcm_loop_hba *tl_hba = container_of(wwn,
struct tcm_loop_hba, tl_hba_wwn);
- int host_no = tl_hba->sh->host_no;
+
+ pr_debug("TCM_Loop_ConfigFS: Deallocating emulated Target"
+ " SAS Address: %s at Linux/SCSI Host ID: %d\n",
+ tl_hba->tl_wwn_address, tl_hba->sh->host_no);
/*
* Call device_unregister() on the original tl_hba->dev.
* tcm_loop_fabric_scsi.c:tcm_loop_release_adapter() will
* release *tl_hba;
*/
device_unregister(&tl_hba->dev);
-
- printk(KERN_INFO "TCM_Loop_ConfigFS: Deallocated emulated Target"
- " SAS Address: %s at Linux/SCSI Host ID: %d\n",
- config_item_name(&wwn->wwn_group.cg_item), host_no);
}
/* Start items for tcm_loop_cit */
@@ -1426,9 +1388,9 @@ static int tcm_loop_register_configfs(void)
* Register the top level struct config_item_type with TCM core
*/
fabric = target_fabric_configfs_init(THIS_MODULE, "loopback");
- if (!fabric) {
- printk(KERN_ERR "tcm_loop_register_configfs() failed!\n");
- return -1;
+ if (IS_ERR(fabric)) {
+ pr_err("tcm_loop_register_configfs() failed!\n");
+ return PTR_ERR(fabric);
}
/*
* Setup the fabric API of function pointers used by target_core_mod
@@ -1460,19 +1422,11 @@ static int tcm_loop_register_configfs(void)
&tcm_loop_tpg_release_fabric_acl;
fabric->tf_ops.tpg_get_inst_index = &tcm_loop_get_inst_index;
/*
- * Since tcm_loop is mapping physical memory from Linux/SCSI
- * struct scatterlist arrays for each struct scsi_cmnd I/O,
- * we do not need TCM to allocate a iovec array for
- * virtual memory address mappings
- */
- fabric->tf_ops.alloc_cmd_iovecs = NULL;
- /*
* Used for setting up remaining TCM resources in process context
*/
fabric->tf_ops.new_cmd_map = &tcm_loop_new_cmd_map;
fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
- fabric->tf_ops.release_cmd_to_pool = &tcm_loop_deallocate_core_cmd;
- fabric->tf_ops.release_cmd_direct = &tcm_loop_deallocate_core_cmd;
+ fabric->tf_ops.release_cmd = &tcm_loop_release_cmd;
fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
fabric->tf_ops.close_session = &tcm_loop_close_session;
fabric->tf_ops.stop_session = &tcm_loop_stop_session;
@@ -1489,7 +1443,6 @@ static int tcm_loop_register_configfs(void)
&tcm_loop_set_default_node_attributes;
fabric->tf_ops.get_task_tag = &tcm_loop_get_task_tag;
fabric->tf_ops.get_cmd_state = &tcm_loop_get_cmd_state;
- fabric->tf_ops.new_cmd_failure = &tcm_loop_new_cmd_failure;
fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
fabric->tf_ops.queue_status = &tcm_loop_queue_status;
fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
@@ -1527,7 +1480,7 @@ static int tcm_loop_register_configfs(void)
*/
ret = target_fabric_configfs_register(fabric);
if (ret < 0) {
- printk(KERN_ERR "target_fabric_configfs_register() for"
+ pr_err("target_fabric_configfs_register() for"
" TCM_Loop failed!\n");
target_fabric_configfs_free(fabric);
return -1;
@@ -1536,7 +1489,7 @@ static int tcm_loop_register_configfs(void)
* Setup our local pointer to *fabric.
*/
tcm_loop_fabric_configfs = fabric;
- printk(KERN_INFO "TCM_LOOP[0] - Set fabric ->"
+ pr_debug("TCM_LOOP[0] - Set fabric ->"
" tcm_loop_fabric_configfs\n");
return 0;
}
@@ -1548,7 +1501,7 @@ static void tcm_loop_deregister_configfs(void)
target_fabric_configfs_deregister(tcm_loop_fabric_configfs);
tcm_loop_fabric_configfs = NULL;
- printk(KERN_INFO "TCM_LOOP[0] - Cleared"
+ pr_debug("TCM_LOOP[0] - Cleared"
" tcm_loop_fabric_configfs\n");
}
@@ -1561,7 +1514,7 @@ static int __init tcm_loop_fabric_init(void)
__alignof__(struct tcm_loop_cmd),
0, NULL);
if (!tcm_loop_cmd_cache) {
- printk(KERN_ERR "kmem_cache_create() for"
+ pr_debug("kmem_cache_create() for"
" tcm_loop_cmd_cache failed\n");
return -ENOMEM;
}
diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h
index 7e9f7ab..6b76c7a 100644
--- a/drivers/target/loopback/tcm_loop.h
+++ b/drivers/target/loopback/tcm_loop.h
@@ -16,12 +16,6 @@
*/
#define TL_SCSI_MAX_CMD_LEN 32
-#ifdef CONFIG_LOOPBACK_TARGET_CDB_DEBUG
-# define TL_CDB_DEBUG(x...) printk(KERN_INFO x)
-#else
-# define TL_CDB_DEBUG(x...)
-#endif
-
struct tcm_loop_cmd {
/* State of Linux/SCSI CDB+Data descriptor */
u32 sc_cmd_state;
diff --git a/drivers/target/tcm_fc/Makefile b/drivers/target/tcm_fc/Makefile
index 7a5c2b6..20b14bb 100644
--- a/drivers/target/tcm_fc/Makefile
+++ b/drivers/target/tcm_fc/Makefile
@@ -1,15 +1,6 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/target/ \
- -I$(srctree)/drivers/scsi/ \
- -I$(srctree)/include/scsi/ \
- -I$(srctree)/drivers/target/tcm_fc/
-
-tcm_fc-y += tfc_cmd.o \
- tfc_conf.o \
- tfc_io.o \
- tfc_sess.o
+tcm_fc-y += tfc_cmd.o \
+ tfc_conf.o \
+ tfc_io.o \
+ tfc_sess.o
obj-$(CONFIG_TCM_FC) += tcm_fc.o
-
-ifdef CONFIGFS_TCM_FC_DEBUG
-EXTRA_CFLAGS += -DTCM_FC_DEBUG
-endif
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index 7b82f1b..be7ed12 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -23,30 +23,6 @@
#define FT_TPG_NAMELEN 32 /* max length of TPG name */
#define FT_LUN_NAMELEN 32 /* max length of LUN name */
-/*
- * Debug options.
- */
-#define FT_DEBUG_CONF 0x01 /* configuration messages */
-#define FT_DEBUG_SESS 0x02 /* session messages */
-#define FT_DEBUG_TM 0x04 /* TM operations */
-#define FT_DEBUG_IO 0x08 /* I/O commands */
-#define FT_DEBUG_DATA 0x10 /* Data transfer */
-
-extern unsigned int ft_debug_logging; /* debug options */
-
-#define FT_DEBUG(mask, fmt, args...) \
- do { \
- if (ft_debug_logging & (mask)) \
- printk(KERN_INFO "tcm_fc: %s: " fmt, \
- __func__, ##args); \
- } while (0)
-
-#define FT_CONF_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_CONF, fmt, ##args)
-#define FT_SESS_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_SESS, fmt, ##args)
-#define FT_TM_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_TM, fmt, ##args)
-#define FT_IO_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_IO, fmt, ##args)
-#define FT_DATA_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_DATA, fmt, ##args)
-
struct ft_transport_id {
__u8 format;
__u8 __resvd1[7];
@@ -122,8 +98,7 @@ struct ft_tpg {
struct list_head list; /* linkage in ft_lport_acl tpg_list */
struct list_head lun_list; /* head of LUNs */
struct se_portal_group se_tpg;
- struct task_struct *thread; /* processing thread */
- struct se_queue_obj qobj; /* queue for processing thread */
+ struct workqueue_struct *workqueue;
};
struct ft_lport_acl {
@@ -134,16 +109,10 @@ struct ft_lport_acl {
struct se_wwn fc_lport_wwn;
};
-enum ft_cmd_state {
- FC_CMD_ST_NEW = 0,
- FC_CMD_ST_REJ
-};
-
/*
* Commands
*/
struct ft_cmd {
- enum ft_cmd_state state;
u32 lun; /* LUN from request */
struct ft_sess *sess; /* session held for cmd */
struct fc_seq *seq; /* sequence in exchange mgr */
@@ -151,10 +120,11 @@ struct ft_cmd {
struct fc_frame *req_frame;
unsigned char *cdb; /* pointer to CDB inside frame */
u32 write_data_len; /* data received on writes */
- struct se_queue_req se_req;
+ struct work_struct work;
/* Local sense buffer */
unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
u32 was_ddp_setup:1; /* Set only if ddp is setup */
+ u32 aborted:1; /* Set if aborted by reset or timeout */
struct scatterlist *sg; /* Set only if DDP is setup */
u32 sg_cnt; /* No. of item in scatterlist */
};
@@ -187,7 +157,7 @@ int ft_lport_notify(struct notifier_block *, unsigned long, void *);
/*
* IO methods.
*/
-void ft_check_stop_free(struct se_cmd *);
+int ft_check_stop_free(struct se_cmd *);
void ft_release_cmd(struct se_cmd *);
int ft_queue_status(struct se_cmd *);
int ft_queue_data_in(struct se_cmd *);
@@ -195,14 +165,12 @@ int ft_write_pending(struct se_cmd *);
int ft_write_pending_status(struct se_cmd *);
u32 ft_get_task_tag(struct se_cmd *);
int ft_get_cmd_state(struct se_cmd *);
-void ft_new_cmd_failure(struct se_cmd *);
int ft_queue_tm_resp(struct se_cmd *);
int ft_is_state_remove(struct se_cmd *);
/*
* other internal functions.
*/
-int ft_thread(void *);
void ft_recv_req(struct ft_sess *, struct fc_frame *);
struct ft_tpg *ft_lport_find_tpg(struct fc_lport *);
struct ft_node_acl *ft_acl_get(struct ft_tpg *, struct fc_rport_priv *);
@@ -212,4 +180,9 @@ void ft_dump_cmd(struct ft_cmd *, const char *caller);
ssize_t ft_format_wwn(char *, size_t, u64);
+/*
+ * Underlying HW specific helper function
+ */
+void ft_invl_hw_context(struct ft_cmd *);
+
#endif /* __TCM_FC_H__ */
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index 3c3fa84..278819c 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>
@@ -45,7 +44,6 @@
#include <target/target_core_device.h>
#include <target/target_core_tpg.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
#include <target/target_core_tmr.h>
#include <target/configfs_macros.h>
@@ -59,33 +57,30 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
struct fc_exch *ep;
struct fc_seq *sp;
struct se_cmd *se_cmd;
- struct se_mem *mem;
- struct se_transport_task *task;
-
- if (!(ft_debug_logging & FT_DEBUG_IO))
- return;
+ struct scatterlist *sg;
+ int count;
se_cmd = &cmd->se_cmd;
- printk(KERN_INFO "%s: cmd %p state %d sess %p seq %p se_cmd %p\n",
- caller, cmd, cmd->state, cmd->sess, cmd->seq, se_cmd);
- printk(KERN_INFO "%s: cmd %p cdb %p\n",
+ pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n",
+ caller, cmd, cmd->sess, cmd->seq, se_cmd);
+ pr_debug("%s: cmd %p cdb %p\n",
caller, cmd, cmd->cdb);
- printk(KERN_INFO "%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
-
- task = T_TASK(se_cmd);
- printk(KERN_INFO "%s: cmd %p task %p se_num %u buf %p len %u se_cmd_flags <0x%x>\n",
- caller, cmd, task, task->t_tasks_se_num,
- task->t_task_buf, se_cmd->data_length, se_cmd->se_cmd_flags);
- if (task->t_mem_list)
- list_for_each_entry(mem, task->t_mem_list, se_list)
- printk(KERN_INFO "%s: cmd %p mem %p page %p "
- "len 0x%x off 0x%x\n",
- caller, cmd, mem,
- mem->se_page, mem->se_len, mem->se_off);
+ pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
+
+ pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
+ caller, cmd, se_cmd->t_data_nents,
+ se_cmd->data_length, se_cmd->se_cmd_flags);
+
+ for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count)
+ pr_debug("%s: cmd %p sg %p page %p "
+ "len 0x%x off 0x%x\n",
+ caller, cmd, sg,
+ sg_page(sg), sg->length, sg->offset);
+
sp = cmd->seq;
if (sp) {
ep = fc_seq_exch(sp);
- printk(KERN_INFO "%s: cmd %p sid %x did %x "
+ pr_debug("%s: cmd %p sid %x did %x "
"ox_id %x rx_id %x seq_id %x e_stat %x\n",
caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
sp->id, ep->esb_stat);
@@ -94,36 +89,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0);
}
-static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd)
-{
- struct se_queue_obj *qobj;
- unsigned long flags;
-
- qobj = &sess->tport->tpg->qobj;
- spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
- list_add_tail(&cmd->se_req.qr_list, &qobj->qobj_list);
- spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
- atomic_inc(&qobj->queue_cnt);
- wake_up_interruptible(&qobj->thread_wq);
-}
-
-static struct ft_cmd *ft_dequeue_cmd(struct se_queue_obj *qobj)
-{
- unsigned long flags;
- struct se_queue_req *qr;
-
- spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
- if (list_empty(&qobj->qobj_list)) {
- spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
- return NULL;
- }
- qr = list_first_entry(&qobj->qobj_list, struct se_queue_req, qr_list);
- list_del(&qr->qr_list);
- atomic_dec(&qobj->queue_cnt);
- spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
- return container_of(qr, struct ft_cmd, se_req);
-}
-
static void ft_free_cmd(struct ft_cmd *cmd)
{
struct fc_frame *fp;
@@ -147,9 +112,10 @@ void ft_release_cmd(struct se_cmd *se_cmd)
ft_free_cmd(cmd);
}
-void ft_check_stop_free(struct se_cmd *se_cmd)
+int ft_check_stop_free(struct se_cmd *se_cmd)
{
- transport_generic_free_cmd(se_cmd, 0, 1, 0);
+ transport_generic_free_cmd(se_cmd, 0);
+ return 1;
}
/*
@@ -164,6 +130,8 @@ int ft_queue_status(struct se_cmd *se_cmd)
struct fc_exch *ep;
size_t len;
+ if (cmd->aborted)
+ return 0;
ft_dump_cmd(cmd, __func__);
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
@@ -230,11 +198,13 @@ int ft_write_pending(struct se_cmd *se_cmd)
ft_dump_cmd(cmd, __func__);
+ if (cmd->aborted)
+ return 0;
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
fp = fc_frame_alloc(lport, sizeof(*txrdy));
if (!fp)
- return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
+ return -ENOMEM; /* Signal QUEUE_FULL */
txrdy = fc_frame_payload_get(fp, sizeof(*txrdy));
memset(txrdy, 0, sizeof(*txrdy));
@@ -256,18 +226,18 @@ int ft_write_pending(struct se_cmd *se_cmd)
(fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
if (se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
/*
- * Map se_mem list to scatterlist, so that
- * DDP can be setup. DDP setup function require
- * scatterlist. se_mem_list is internal to
- * TCM/LIO target
+ * cmd may have been broken up into multiple
+ * tasks. Link their sgs together so we can
+ * operate on them all at once.
*/
transport_do_task_sg_chain(se_cmd);
- cmd->sg = T_TASK(se_cmd)->t_tasks_sg_chained;
+ cmd->sg = se_cmd->t_tasks_sg_chained;
cmd->sg_cnt =
- T_TASK(se_cmd)->t_tasks_sg_chained_no;
+ se_cmd->t_tasks_sg_chained_no;
}
- if (cmd->sg && lport->tt.ddp_setup(lport, ep->xid,
- cmd->sg, cmd->sg_cnt))
+ if (cmd->sg && lport->tt.ddp_target(lport, ep->xid,
+ cmd->sg,
+ cmd->sg_cnt))
cmd->was_ddp_setup = 1;
}
}
@@ -279,14 +249,14 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd)
{
struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
+ if (cmd->aborted)
+ return ~0;
return fc_seq_exch(cmd->seq)->rxid;
}
int ft_get_cmd_state(struct se_cmd *se_cmd)
{
- struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
-
- return cmd->state;
+ return 0;
}
int ft_is_state_remove(struct se_cmd *se_cmd)
@@ -294,12 +264,6 @@ int ft_is_state_remove(struct se_cmd *se_cmd)
return 0; /* XXX TBD */
}
-void ft_new_cmd_failure(struct se_cmd *se_cmd)
-{
- /* XXX TBD */
- printk(KERN_INFO "%s: se_cmd %p\n", __func__, se_cmd);
-}
-
/*
* FC sequence response handler for follow-on sequences (data) and aborts.
*/
@@ -308,11 +272,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
struct ft_cmd *cmd = arg;
struct fc_frame_header *fh;
- if (IS_ERR(fp)) {
+ if (unlikely(IS_ERR(fp))) {
/* XXX need to find cmd if queued */
- cmd->se_cmd.t_state = TRANSPORT_REMOVE;
cmd->seq = NULL;
- transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+ cmd->aborted = true;
return;
}
@@ -326,10 +289,11 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
case FC_RCTL_DD_SOL_CTL: /* transfer ready */
case FC_RCTL_DD_DATA_DESC: /* transfer ready */
default:
- printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
+ pr_debug("%s: unhandled frame r_ctl %x\n",
__func__, fh->fh_r_ctl);
+ ft_invl_hw_context(cmd);
fc_frame_free(fp);
- transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+ transport_generic_free_cmd(&cmd->se_cmd, 0);
break;
}
}
@@ -351,7 +315,7 @@ static void ft_send_resp_status(struct fc_lport *lport,
struct fcp_resp_rsp_info *info;
fh = fc_frame_header_get(rx_fp);
- FT_IO_DBG("FCP error response: did %x oxid %x status %x code %x\n",
+ pr_debug("FCP error response: did %x oxid %x status %x code %x\n",
ntoh24(fh->fh_s_id), ntohs(fh->fh_ox_id), status, code);
len = sizeof(*fcp);
if (status == SAM_STAT_GOOD)
@@ -381,12 +345,23 @@ static void ft_send_resp_status(struct fc_lport *lport,
/*
* Send error or task management response.
- * Always frees the cmd and associated state.
*/
-static void ft_send_resp_code(struct ft_cmd *cmd, enum fcp_resp_rsp_codes code)
+static void ft_send_resp_code(struct ft_cmd *cmd,
+ enum fcp_resp_rsp_codes code)
{
ft_send_resp_status(cmd->sess->tport->lport,
cmd->req_frame, SAM_STAT_GOOD, code);
+}
+
+
+/*
+ * Send error or task management response.
+ * Always frees the cmd and associated state.
+ */
+static void ft_send_resp_code_and_free(struct ft_cmd *cmd,
+ enum fcp_resp_rsp_codes code)
+{
+ ft_send_resp_code(cmd, code);
ft_free_cmd(cmd);
}
@@ -423,16 +398,16 @@ static void ft_send_tm(struct ft_cmd *cmd)
* FCP4r01 indicates having a combination of
* tm_flags set is invalid.
*/
- FT_TM_DBG("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
- ft_send_resp_code(cmd, FCP_CMND_FIELDS_INVALID);
+ pr_debug("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
+ ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
return;
}
- FT_TM_DBG("alloc tm cmd fn %d\n", tm_func);
- tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func);
+ pr_debug("alloc tm cmd fn %d\n", tm_func);
+ tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func, GFP_KERNEL);
if (!tmr) {
- FT_TM_DBG("alloc failed\n");
- ft_send_resp_code(cmd, FCP_TMF_FAILED);
+ pr_debug("alloc failed\n");
+ ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
return;
}
cmd->se_cmd.se_tmr_req = tmr;
@@ -440,20 +415,20 @@ static void ft_send_tm(struct ft_cmd *cmd)
switch (fcp->fc_tm_flags) {
case FCP_TMF_LUN_RESET:
cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
- if (transport_get_lun_for_tmr(&cmd->se_cmd, cmd->lun) < 0) {
+ if (transport_lookup_tmr_lun(&cmd->se_cmd, cmd->lun) < 0) {
/*
* Make sure to clean up newly allocated TMR request
* since "unable to handle TMR request because failed
* to get to LUN"
*/
- FT_TM_DBG("Failed to get LUN for TMR func %d, "
+ pr_debug("Failed to get LUN for TMR func %d, "
"se_cmd %p, unpacked_lun %d\n",
tm_func, &cmd->se_cmd, cmd->lun);
ft_dump_cmd(cmd, __func__);
sess = cmd->sess;
transport_send_check_condition_and_sense(&cmd->se_cmd,
cmd->se_cmd.scsi_sense_reason, 0);
- transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+ transport_generic_free_cmd(&cmd->se_cmd, 0);
ft_sess_put(sess);
return;
}
@@ -478,6 +453,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
struct se_tmr_req *tmr = se_cmd->se_tmr_req;
enum fcp_resp_rsp_codes code;
+ if (cmd->aborted)
+ return 0;
switch (tmr->response) {
case TMR_FUNCTION_COMPLETE:
code = FCP_TMF_CMPL;
@@ -497,12 +474,14 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
code = FCP_TMF_FAILED;
break;
}
- FT_TM_DBG("tmr fn %d resp %d fcp code %d\n",
+ pr_debug("tmr fn %d resp %d fcp code %d\n",
tmr->function, tmr->response, code);
ft_send_resp_code(cmd, code);
return 0;
}
+static void ft_send_work(struct work_struct *work);
+
/*
* Handle incoming FCP command.
*/
@@ -521,11 +500,13 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
goto busy;
}
cmd->req_frame = fp; /* hold frame during cmd */
- ft_queue_cmd(sess, cmd);
+
+ INIT_WORK(&cmd->work, ft_send_work);
+ queue_work(sess->tport->tpg->workqueue, &cmd->work);
return;
busy:
- FT_IO_DBG("cmd or seq allocation failure - sending BUSY\n");
+ pr_debug("cmd or seq allocation failure - sending BUSY\n");
ft_send_resp_status(lport, fp, SAM_STAT_BUSY, 0);
fc_frame_free(fp);
ft_sess_put(sess); /* undo get from lookup */
@@ -550,7 +531,7 @@ void ft_recv_req(struct ft_sess *sess, struct fc_frame *fp)
case FC_RCTL_DD_DATA_DESC: /* transfer ready */
case FC_RCTL_ELS4_REQ: /* SRR, perhaps */
default:
- printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
+ pr_debug("%s: unhandled frame r_ctl %x\n",
__func__, fh->fh_r_ctl);
fc_frame_free(fp);
ft_sess_put(sess); /* undo get from lookup */
@@ -561,12 +542,13 @@ void ft_recv_req(struct ft_sess *sess, struct fc_frame *fp)
/*
* Send new command to target.
*/
-static void ft_send_cmd(struct ft_cmd *cmd)
+static void ft_send_work(struct work_struct *work)
{
+ struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
struct se_cmd *se_cmd;
struct fcp_cmnd *fcp;
- int data_dir;
+ int data_dir = 0;
u32 data_len;
int task_attr;
int ret;
@@ -639,7 +621,7 @@ static void ft_send_cmd(struct ft_cmd *cmd)
fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
- ret = transport_get_lun_for_cmd(&cmd->se_cmd, NULL, cmd->lun);
+ ret = transport_lookup_cmd_lun(&cmd->se_cmd, cmd->lun);
if (ret < 0) {
ft_dump_cmd(cmd, __func__);
transport_send_check_condition_and_sense(&cmd->se_cmd,
@@ -649,70 +631,27 @@ static void ft_send_cmd(struct ft_cmd *cmd)
ret = transport_generic_allocate_tasks(se_cmd, cmd->cdb);
- FT_IO_DBG("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
+ pr_debug("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
ft_dump_cmd(cmd, __func__);
- if (ret == -1) {
+ if (ret == -ENOMEM) {
transport_send_check_condition_and_sense(se_cmd,
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
- transport_generic_free_cmd(se_cmd, 0, 1, 0);
+ transport_generic_free_cmd(se_cmd, 0);
return;
}
- if (ret == -2) {
+ if (ret == -EINVAL) {
if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
ft_queue_status(se_cmd);
else
transport_send_check_condition_and_sense(se_cmd,
se_cmd->scsi_sense_reason, 0);
- transport_generic_free_cmd(se_cmd, 0, 1, 0);
+ transport_generic_free_cmd(se_cmd, 0);
return;
}
- transport_generic_handle_cdb(se_cmd);
+ transport_handle_cdb_direct(se_cmd);
return;
err:
- ft_send_resp_code(cmd, FCP_CMND_FIELDS_INVALID);
- return;
-}
-
-/*
- * Handle request in the command thread.
- */
-static void ft_exec_req(struct ft_cmd *cmd)
-{
- FT_IO_DBG("cmd state %x\n", cmd->state);
- switch (cmd->state) {
- case FC_CMD_ST_NEW:
- ft_send_cmd(cmd);
- break;
- default:
- break;
- }
-}
-
-/*
- * Processing thread.
- * Currently one thread per tpg.
- */
-int ft_thread(void *arg)
-{
- struct ft_tpg *tpg = arg;
- struct se_queue_obj *qobj = &tpg->qobj;
- struct ft_cmd *cmd;
- int ret;
-
- set_user_nice(current, -20);
-
- while (!kthread_should_stop()) {
- ret = wait_event_interruptible(qobj->thread_wq,
- atomic_read(&qobj->queue_cnt) || kthread_should_stop());
- if (ret < 0 || kthread_should_stop())
- goto out;
- cmd = ft_dequeue_cmd(qobj);
- if (cmd)
- ft_exec_req(cmd);
- }
-
-out:
- return 0;
+ ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
}
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 84e868c..7962325 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>
@@ -32,6 +31,7 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/configfs.h>
+#include <linux/kernel.h>
#include <linux/ctype.h>
#include <asm/unaligned.h>
#include <scsi/scsi.h>
@@ -48,7 +48,6 @@
#include <target/target_core_device.h>
#include <target/target_core_tpg.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
#include <target/configfs_macros.h>
#include "tcm_fc.h"
@@ -72,10 +71,10 @@ static ssize_t ft_parse_wwn(const char *name, u64 *wwn, int strict)
{
const char *cp;
char c;
- u32 nibble;
u32 byte = 0;
u32 pos = 0;
u32 err;
+ int val;
*wwn = 0;
for (cp = name; cp < &name[FT_NAMELEN - 1]; cp++) {
@@ -96,17 +95,14 @@ static ssize_t ft_parse_wwn(const char *name, u64 *wwn, int strict)
return cp - name;
}
err = 3;
- if (isdigit(c))
- nibble = c - '0';
- else if (isxdigit(c) && (islower(c) || !strict))
- nibble = tolower(c) - 'a' + 10;
- else
+ val = hex_to_bin(c);
+ if (val < 0 || (strict && isupper(c)))
goto fail;
- *wwn = (*wwn << 4) | nibble;
+ *wwn = (*wwn << 4) | val;
}
err = 4;
fail:
- FT_CONF_DBG("err %u len %zu pos %u byte %u\n",
+ pr_debug("err %u len %zu pos %u byte %u\n",
err, cp - name, pos, byte);
return -1;
}
@@ -216,14 +212,14 @@ static struct se_node_acl *ft_add_acl(
u64 wwpn;
u32 q_depth;
- FT_CONF_DBG("add acl %s\n", name);
+ pr_debug("add acl %s\n", name);
tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
if (ft_parse_wwn(name, &wwpn, 1) < 0)
return ERR_PTR(-EINVAL);
acl = kzalloc(sizeof(struct ft_node_acl), GFP_KERNEL);
- if (!(acl))
+ if (!acl)
return ERR_PTR(-ENOMEM);
acl->node_auth.port_name = wwpn;
@@ -239,11 +235,11 @@ static void ft_del_acl(struct se_node_acl *se_acl)
struct ft_node_acl *acl = container_of(se_acl,
struct ft_node_acl, se_node_acl);
- FT_CONF_DBG("del acl %s\n",
+ pr_debug("del acl %s\n",
config_item_name(&se_acl->acl_group.cg_item));
tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
- FT_CONF_DBG("del acl %p se_acl %p tpg %p se_tpg %p\n",
+ pr_debug("del acl %p se_acl %p tpg %p se_tpg %p\n",
acl, se_acl, tpg, &tpg->se_tpg);
core_tpg_del_initiator_node_acl(&tpg->se_tpg, se_acl, 1);
@@ -257,21 +253,21 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
struct se_portal_group *se_tpg = &tpg->se_tpg;
struct se_node_acl *se_acl;
- spin_lock_bh(&se_tpg->acl_node_lock);
+ spin_lock_irq(&se_tpg->acl_node_lock);
list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) {
acl = container_of(se_acl, struct ft_node_acl, se_node_acl);
- FT_CONF_DBG("acl %p port_name %llx\n",
+ pr_debug("acl %p port_name %llx\n",
acl, (unsigned long long)acl->node_auth.port_name);
if (acl->node_auth.port_name == rdata->ids.port_name ||
acl->node_auth.node_name == rdata->ids.node_name) {
- FT_CONF_DBG("acl %p port_name %llx matched\n", acl,
+ pr_debug("acl %p port_name %llx matched\n", acl,
(unsigned long long)rdata->ids.port_name);
found = acl;
/* XXX need to hold onto ACL */
break;
}
}
- spin_unlock_bh(&se_tpg->acl_node_lock);
+ spin_unlock_irq(&se_tpg->acl_node_lock);
return found;
}
@@ -280,11 +276,11 @@ struct se_node_acl *ft_tpg_alloc_fabric_acl(struct se_portal_group *se_tpg)
struct ft_node_acl *acl;
acl = kzalloc(sizeof(*acl), GFP_KERNEL);
- if (!(acl)) {
- printk(KERN_ERR "Unable to allocate struct ft_node_acl\n");
+ if (!acl) {
+ pr_err("Unable to allocate struct ft_node_acl\n");
return NULL;
}
- FT_CONF_DBG("acl %p\n", acl);
+ pr_debug("acl %p\n", acl);
return &acl->se_node_acl;
}
@@ -294,7 +290,7 @@ static void ft_tpg_release_fabric_acl(struct se_portal_group *se_tpg,
struct ft_node_acl *acl = container_of(se_acl,
struct ft_node_acl, se_node_acl);
- FT_CONF_DBG(KERN_INFO "acl %p\n", acl);
+ pr_debug("acl %p\n", acl);
kfree(acl);
}
@@ -308,10 +304,11 @@ static struct se_portal_group *ft_add_tpg(
{
struct ft_lport_acl *lacl;
struct ft_tpg *tpg;
+ struct workqueue_struct *wq;
unsigned long index;
int ret;
- FT_CONF_DBG("tcm_fc: add tpg %s\n", name);
+ pr_debug("tcm_fc: add tpg %s\n", name);
/*
* Name must be "tpgt_" followed by the index.
@@ -328,20 +325,21 @@ static struct se_portal_group *ft_add_tpg(
tpg->index = index;
tpg->lport_acl = lacl;
INIT_LIST_HEAD(&tpg->lun_list);
- transport_init_queue_obj(&tpg->qobj);
- ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
- (void *)tpg, TRANSPORT_TPG_TYPE_NORMAL);
- if (ret < 0) {
+ wq = alloc_workqueue("tcm_fc", 0, 1);
+ if (!wq) {
kfree(tpg);
return NULL;
}
- tpg->thread = kthread_run(ft_thread, tpg, "ft_tpg%lu", index);
- if (IS_ERR(tpg->thread)) {
+ ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+ tpg, TRANSPORT_TPG_TYPE_NORMAL);
+ if (ret < 0) {
+ destroy_workqueue(wq);
kfree(tpg);
return NULL;
}
+ tpg->workqueue = wq;
mutex_lock(&ft_lport_lock);
list_add_tail(&tpg->list, &lacl->tpg_list);
@@ -354,10 +352,10 @@ static void ft_del_tpg(struct se_portal_group *se_tpg)
{
struct ft_tpg *tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
- FT_CONF_DBG("del tpg %s\n",
+ pr_debug("del tpg %s\n",
config_item_name(&tpg->se_tpg.tpg_group.cg_item));
- kthread_stop(tpg->thread);
+ destroy_workqueue(tpg->workqueue);
/* Wait for sessions to be freed thru RCU, for BUG_ON below */
synchronize_rcu();
@@ -412,7 +410,7 @@ static struct se_wwn *ft_add_lport(
struct ft_lport_acl *old_lacl;
u64 wwpn;
- FT_CONF_DBG("add lport %s\n", name);
+ pr_debug("add lport %s\n", name);
if (ft_parse_wwn(name, &wwpn, 1) < 0)
return NULL;
lacl = kzalloc(sizeof(*lacl), GFP_KERNEL);
@@ -441,8 +439,7 @@ static void ft_del_lport(struct se_wwn *wwn)
struct ft_lport_acl *lacl = container_of(wwn,
struct ft_lport_acl, fc_lport_wwn);
- FT_CONF_DBG("del lport %s\n",
- config_item_name(&wwn->wwn_group.cg_item));
+ pr_debug("del lport %s\n", lacl->name);
mutex_lock(&ft_lport_lock);
list_del(&lacl->list);
mutex_unlock(&ft_lport_lock);
@@ -536,8 +533,7 @@ static struct target_core_fabric_ops ft_fabric_ops = {
.tpg_release_fabric_acl = ft_tpg_release_fabric_acl,
.tpg_get_inst_index = ft_tpg_get_inst_index,
.check_stop_free = ft_check_stop_free,
- .release_cmd_to_pool = ft_release_cmd,
- .release_cmd_direct = ft_release_cmd,
+ .release_cmd = ft_release_cmd,
.shutdown_session = ft_sess_shutdown,
.close_session = ft_sess_close,
.stop_session = ft_sess_stop,
@@ -550,7 +546,6 @@ static struct target_core_fabric_ops ft_fabric_ops = {
.set_default_node_attributes = ft_set_default_node_attr,
.get_task_tag = ft_get_task_tag,
.get_cmd_state = ft_get_cmd_state,
- .new_cmd_failure = ft_new_cmd_failure,
.queue_data_in = ft_queue_data_in,
.queue_status = ft_queue_status,
.queue_tm_rsp = ft_queue_tm_resp,
@@ -582,10 +577,10 @@ int ft_register_configfs(void)
* Register the top level struct config_item_type with TCM core
*/
fabric = target_fabric_configfs_init(THIS_MODULE, "fc");
- if (!fabric) {
- printk(KERN_INFO "%s: target_fabric_configfs_init() failed!\n",
+ if (IS_ERR(fabric)) {
+ pr_err("%s: target_fabric_configfs_init() failed!\n",
__func__);
- return -1;
+ return PTR_ERR(fabric);
}
fabric->tf_ops = ft_fabric_ops;
@@ -610,11 +605,8 @@ int ft_register_configfs(void)
*/
ret = target_fabric_configfs_register(fabric);
if (ret < 0) {
- FT_CONF_DBG("target_fabric_configfs_register() for"
+ pr_debug("target_fabric_configfs_register() for"
" FC Target failed!\n");
- printk(KERN_INFO
- "%s: target_fabric_configfs_register() failed!\n",
- __func__);
target_fabric_configfs_free(fabric);
return -1;
}
@@ -661,9 +653,7 @@ static void __exit ft_exit(void)
synchronize_rcu();
}
-#ifdef MODULE
MODULE_DESCRIPTION("FC TCM fabric driver " FT_VERSION);
MODULE_LICENSE("GPL");
module_init(ft_init);
module_exit(ft_exit);
-#endif /* MODULE */
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index 8c4a240..cebd235 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -28,7 +28,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>
@@ -39,6 +38,7 @@
#include <linux/configfs.h>
#include <linux/ctype.h>
#include <linux/hash.h>
+#include <linux/ratelimit.h>
#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
@@ -53,7 +53,6 @@
#include <target/target_core_device.h>
#include <target/target_core_tpg.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
#include <target/configfs_macros.h>
#include "tcm_fc.h"
@@ -65,49 +64,43 @@
int ft_queue_data_in(struct se_cmd *se_cmd)
{
struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
- struct se_transport_task *task;
struct fc_frame *fp = NULL;
struct fc_exch *ep;
struct fc_lport *lport;
- struct se_mem *mem;
+ struct scatterlist *sg = NULL;
size_t remaining;
u32 f_ctl = FC_FC_EX_CTX | FC_FC_REL_OFF;
- u32 mem_off;
+ u32 mem_off = 0;
u32 fh_off = 0;
u32 frame_off = 0;
size_t frame_len = 0;
- size_t mem_len;
+ size_t mem_len = 0;
size_t tlen;
size_t off_in_page;
- struct page *page;
+ struct page *page = NULL;
int use_sg;
int error;
void *page_addr;
void *from;
void *to = NULL;
+ if (cmd->aborted)
+ return 0;
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
cmd->seq = lport->tt.seq_start_next(cmd->seq);
- task = T_TASK(se_cmd);
- BUG_ON(!task);
remaining = se_cmd->data_length;
/*
- * Setup to use first mem list entry if any.
+ * Setup to use first mem list entry, unless no data.
*/
- if (task->t_tasks_se_num) {
- mem = list_first_entry(task->t_mem_list,
- struct se_mem, se_list);
- mem_len = mem->se_len;
- mem_off = mem->se_off;
- page = mem->se_page;
- } else {
- mem = NULL;
- mem_len = remaining;
- mem_off = 0;
- page = NULL;
+ BUG_ON(remaining && !se_cmd->t_data_sg);
+ if (remaining) {
+ sg = se_cmd->t_data_sg;
+ mem_len = sg->length;
+ mem_off = sg->offset;
+ page = sg_page(sg);
}
/* no scatter/gather in skb for odd word length due to fc_seq_send() */
@@ -115,12 +108,10 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
while (remaining) {
if (!mem_len) {
- BUG_ON(!mem);
- mem = list_entry(mem->se_list.next,
- struct se_mem, se_list);
- mem_len = min((size_t)mem->se_len, remaining);
- mem_off = mem->se_off;
- page = mem->se_page;
+ sg = sg_next(sg);
+ mem_len = min((size_t)sg->length, remaining);
+ mem_off = sg->offset;
+ page = sg_page(sg);
}
if (!frame_len) {
/*
@@ -148,18 +139,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
tlen = min(mem_len, frame_len);
if (use_sg) {
- if (!mem) {
- BUG_ON(!task->t_task_buf);
- page_addr = task->t_task_buf + mem_off;
- /*
- * In this case, offset is 'offset_in_page' of
- * (t_task_buf + mem_off) instead of 'mem_off'.
- */
- off_in_page = offset_in_page(page_addr);
- page = virt_to_page(page_addr);
- tlen = min(tlen, PAGE_SIZE - off_in_page);
- } else
- off_in_page = mem_off;
+ off_in_page = mem_off;
BUG_ON(!page);
get_page(page);
skb_fill_page_desc(fp_skb(fp),
@@ -169,7 +149,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
fp_skb(fp)->data_len += tlen;
fp_skb(fp)->truesize +=
PAGE_SIZE << compound_order(page);
- } else if (mem) {
+ } else {
BUG_ON(!page);
from = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
KM_SOFTIRQ0);
@@ -180,10 +160,6 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
memcpy(to, from, tlen);
kunmap_atomic(page_addr, KM_SOFTIRQ0);
to += tlen;
- } else {
- from = task->t_task_buf + mem_off;
- memcpy(to, from, tlen);
- to += tlen;
}
mem_off += tlen;
@@ -201,8 +177,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
error = lport->tt.seq_send(lport, cmd->seq, fp);
if (error) {
/* XXX For now, initiator will retry */
- if (printk_ratelimit())
- printk(KERN_ERR "%s: Failed to send frame %p, "
+ pr_err_ratelimited("%s: Failed to send frame %p, "
"xid <0x%x>, remaining %zu, "
"lso_max <0x%x>\n",
__func__, fp, ep->xid,
@@ -221,83 +196,64 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
struct fc_seq *seq = cmd->seq;
struct fc_exch *ep;
struct fc_lport *lport;
- struct se_transport_task *task;
struct fc_frame_header *fh;
- struct se_mem *mem;
- u32 mem_off;
+ struct scatterlist *sg = NULL;
+ u32 mem_off = 0;
u32 rel_off;
size_t frame_len;
- size_t mem_len;
+ size_t mem_len = 0;
size_t tlen;
- struct page *page;
+ struct page *page = NULL;
void *page_addr;
void *from;
void *to;
u32 f_ctl;
void *buf;
- task = T_TASK(se_cmd);
- BUG_ON(!task);
-
fh = fc_frame_header_get(fp);
if (!(ntoh24(fh->fh_f_ctl) & FC_FC_REL_OFF))
goto drop;
- /*
- * Doesn't expect even single byte of payload. Payload
- * is expected to be copied directly to user buffers
- * due to DDP (Large Rx offload) feature, hence
- * BUG_ON if BUF is non-NULL
- */
- buf = fc_frame_payload_get(fp, 1);
- if (cmd->was_ddp_setup && buf) {
- printk(KERN_INFO "%s: When DDP was setup, not expected to"
- "receive frame with payload, Payload shall be"
- "copied directly to buffer instead of coming "
- "via. legacy receive queues\n", __func__);
- BUG_ON(buf);
- }
-
- /*
- * If ft_cmd indicated 'ddp_setup', in that case only the last frame
- * should come with 'TSI bit being set'. If 'TSI bit is not set and if
- * data frame appears here, means error condition. In both the cases
- * release the DDP context (ddp_put) and in error case, as well
- * initiate error recovery mechanism.
- */
+ f_ctl = ntoh24(fh->fh_f_ctl);
ep = fc_seq_exch(seq);
+ lport = ep->lp;
if (cmd->was_ddp_setup) {
BUG_ON(!ep);
- lport = ep->lp;
BUG_ON(!lport);
- }
- if (cmd->was_ddp_setup && ep->xid != FC_XID_UNKNOWN) {
- f_ctl = ntoh24(fh->fh_f_ctl);
/*
- * If TSI bit set in f_ctl, means last write data frame is
- * received successfully where payload is posted directly
- * to user buffer and only the last frame's header is posted
- * in legacy receive queue
+ * Since DDP (Large Rx offload) was setup for this request,
+ * payload is expected to be copied directly to user buffers.
+ */
+ buf = fc_frame_payload_get(fp, 1);
+ if (buf)
+ pr_err("%s: xid 0x%x, f_ctl 0x%x, cmd->sg %p, "
+ "cmd->sg_cnt 0x%x. DDP was setup"
+ " hence not expected to receive frame with "
+ "payload, Frame will be dropped if"
+ "'Sequence Initiative' bit in f_ctl is"
+ "not set\n", __func__, ep->xid, f_ctl,
+ cmd->sg, cmd->sg_cnt);
+ /*
+ * Invalidate HW DDP context if it was setup for respective
+ * command. Invalidation of HW DDP context is requited in both
+ * situation (success and error).
*/
- if (f_ctl & FC_FC_SEQ_INIT) { /* TSI bit set in FC frame */
- cmd->write_data_len = lport->tt.ddp_done(lport,
- ep->xid);
+ ft_invl_hw_context(cmd);
+
+ /*
+ * If "Sequence Initiative (TSI)" bit set in f_ctl, means last
+ * write data frame is received successfully where payload is
+ * posted directly to user buffer and only the last frame's
+ * header is posted in receive queue.
+ *
+ * If "Sequence Initiative (TSI)" bit is not set, means error
+ * condition w.r.t. DDP, hence drop the packet and let explict
+ * ABORTS from other end of exchange timer trigger the recovery.
+ */
+ if (f_ctl & FC_FC_SEQ_INIT)
goto last_frame;
- } else {
- /*
- * Updating the write_data_len may be meaningless at
- * this point, but just in case if required in future
- * for debugging or any other purpose
- */
- printk(KERN_ERR "%s: Received frame with TSI bit not"
- " being SET, dropping the frame, "
- "cmd->sg <%p>, cmd->sg_cnt <0x%x>\n",
- __func__, cmd->sg, cmd->sg_cnt);
- cmd->write_data_len = lport->tt.ddp_done(lport,
- ep->xid);
- lport->tt.seq_exch_abort(cmd->seq, 0);
+ else
goto drop;
- }
}
rel_off = ntohl(fh->fh_parm_offset);
@@ -312,29 +268,22 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
frame_len = se_cmd->data_length - rel_off;
/*
- * Setup to use first mem list entry if any.
+ * Setup to use first mem list entry, unless no data.
*/
- if (task->t_tasks_se_num) {
- mem = list_first_entry(task->t_mem_list,
- struct se_mem, se_list);
- mem_len = mem->se_len;
- mem_off = mem->se_off;
- page = mem->se_page;
- } else {
- mem = NULL;
- page = NULL;
- mem_off = 0;
- mem_len = frame_len;
+ BUG_ON(frame_len && !se_cmd->t_data_sg);
+ if (frame_len) {
+ sg = se_cmd->t_data_sg;
+ mem_len = sg->length;
+ mem_off = sg->offset;
+ page = sg_page(sg);
}
while (frame_len) {
if (!mem_len) {
- BUG_ON(!mem);
- mem = list_entry(mem->se_list.next,
- struct se_mem, se_list);
- mem_len = mem->se_len;
- mem_off = mem->se_off;
- page = mem->se_page;
+ sg = sg_next(sg);
+ mem_len = sg->length;
+ mem_off = sg->offset;
+ page = sg_page(sg);
}
if (rel_off >= mem_len) {
rel_off -= mem_len;
@@ -347,19 +296,15 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
tlen = min(mem_len, frame_len);
- if (mem) {
- to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
- KM_SOFTIRQ0);
- page_addr = to;
- to += mem_off & ~PAGE_MASK;
- tlen = min(tlen, (size_t)(PAGE_SIZE -
- (mem_off & ~PAGE_MASK)));
- memcpy(to, from, tlen);
- kunmap_atomic(page_addr, KM_SOFTIRQ0);
- } else {
- to = task->t_task_buf + mem_off;
- memcpy(to, from, tlen);
- }
+ to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
+ KM_SOFTIRQ0);
+ page_addr = to;
+ to += mem_off & ~PAGE_MASK;
+ tlen = min(tlen, (size_t)(PAGE_SIZE -
+ (mem_off & ~PAGE_MASK)));
+ memcpy(to, from, tlen);
+ kunmap_atomic(page_addr, KM_SOFTIRQ0);
+
from += tlen;
frame_len -= tlen;
mem_off += tlen;
@@ -372,3 +317,40 @@ last_frame:
drop:
fc_frame_free(fp);
}
+
+/*
+ * Handle and cleanup any HW specific resources if
+ * received ABORTS, errors, timeouts.
+ */
+void ft_invl_hw_context(struct ft_cmd *cmd)
+{
+ struct fc_seq *seq = cmd->seq;
+ struct fc_exch *ep = NULL;
+ struct fc_lport *lport = NULL;
+
+ BUG_ON(!cmd);
+
+ /* Cleanup the DDP context in HW if DDP was setup */
+ if (cmd->was_ddp_setup && seq) {
+ ep = fc_seq_exch(seq);
+ if (ep) {
+ lport = ep->lp;
+ if (lport && (ep->xid <= lport->lro_xid)) {
+ /*
+ * "ddp_done" trigger invalidation of HW
+ * specific DDP context
+ */
+ cmd->write_data_len = lport->tt.ddp_done(lport,
+ ep->xid);
+
+ /*
+ * Resetting same variable to indicate HW's
+ * DDP context has been invalidated to avoid
+ * re_invalidation of same context (context is
+ * identified using ep->xid)
+ */
+ cmd->was_ddp_setup = 0;
+ }
+ }
+ }
+}
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 9a084b8..b328011 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>
@@ -46,10 +45,8 @@
#include <target/target_core_device.h>
#include <target/target_core_tpg.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
#include <target/configfs_macros.h>
-#include <scsi/libfc.h>
#include "tcm_fc.h"
static void ft_sess_delete_all(struct ft_tport *);
@@ -75,6 +72,7 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport)
if (tport) {
tport->tpg = tpg;
+ tpg->tport = tport;
return tport;
}
@@ -199,13 +197,13 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
if (sess->port_id == port_id) {
kref_get(&sess->kref);
rcu_read_unlock();
- FT_SESS_DBG("port_id %x found %p\n", port_id, sess);
+ pr_debug("port_id %x found %p\n", port_id, sess);
return sess;
}
}
out:
rcu_read_unlock();
- FT_SESS_DBG("port_id %x not found\n", port_id);
+ pr_debug("port_id %x not found\n", port_id);
return NULL;
}
@@ -241,7 +239,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
hlist_add_head_rcu(&sess->hash, head);
tport->sess_count++;
- FT_SESS_DBG("port_id %x sess %p\n", port_id, sess);
+ pr_debug("port_id %x sess %p\n", port_id, sess);
transport_register_session(&tport->tpg->se_tpg, &acl->se_node_acl,
sess->se_sess, sess);
@@ -315,7 +313,7 @@ int ft_sess_shutdown(struct se_session *se_sess)
{
struct ft_sess *sess = se_sess->fabric_sess_ptr;
- FT_SESS_DBG("port_id %x\n", sess->port_id);
+ pr_debug("port_id %x\n", sess->port_id);
return 1;
}
@@ -336,7 +334,7 @@ void ft_sess_close(struct se_session *se_sess)
mutex_unlock(&ft_lport_lock);
return;
}
- FT_SESS_DBG("port_id %x\n", port_id);
+ pr_debug("port_id %x\n", port_id);
ft_sess_unhash(sess);
mutex_unlock(&ft_lport_lock);
transport_deregister_session_configfs(se_sess);
@@ -349,7 +347,7 @@ void ft_sess_stop(struct se_session *se_sess, int sess_sleep, int conn_sleep)
{
struct ft_sess *sess = se_sess->fabric_sess_ptr;
- FT_SESS_DBG("port_id %x\n", sess->port_id);
+ pr_debug("port_id %x\n", sess->port_id);
}
int ft_sess_logged_in(struct se_session *se_sess)
@@ -465,7 +463,7 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
mutex_lock(&ft_lport_lock);
ret = ft_prli_locked(rdata, spp_len, rspp, spp);
mutex_unlock(&ft_lport_lock);
- FT_SESS_DBG("port_id %x flags %x ret %x\n",
+ pr_debug("port_id %x flags %x ret %x\n",
rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret);
return ret;
}
@@ -525,11 +523,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp)
struct ft_sess *sess;
u32 sid = fc_frame_sid(fp);
- FT_SESS_DBG("sid %x\n", sid);
+ pr_debug("sid %x\n", sid);
sess = ft_sess_get(lport, sid);
if (!sess) {
- FT_SESS_DBG("sid %x sess lookup failed\n", sid);
+ pr_debug("sid %x sess lookup failed\n", sid);
/* TBD XXX - if FCP_CMND, send PRLO */
fc_frame_free(fp);
return;
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 6f2c980..4222035 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -19,6 +19,11 @@ config HVC_CONSOLE
console. This driver allows each pSeries partition to have a console
which is accessed via the HMC.
+config HVC_OLD_HVSI
+ bool "Old driver for pSeries serial port (/dev/hvsi*)"
+ depends on HVC_CONSOLE
+ default n
+
config HVC_ISERIES
bool "iSeries Hypervisor Virtual Console support"
depends on PPC_ISERIES
@@ -29,6 +34,15 @@ config HVC_ISERIES
help
iSeries machines support a hypervisor virtual console.
+config HVC_OPAL
+ bool "OPAL Console support"
+ depends on PPC_POWERNV
+ select HVC_DRIVER
+ select HVC_IRQ
+ default y
+ help
+ PowerNV machines running under OPAL need that driver to get a console
+
config HVC_RTAS
bool "IBM RTAS Console support"
depends on PPC_RTAS
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index 40a25d9..89abf40b 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -1,4 +1,6 @@
-obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi_lib.o
+obj-$(CONFIG_HVC_OPAL) += hvc_opal.o hvsi_lib.o
+obj-$(CONFIG_HVC_OLD_HVSI) += hvsi.o
obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
obj-$(CONFIG_HVC_TILE) += hvc_tile.o
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index aa84555..443547b 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -31,6 +31,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/major.h>
+#include <linux/atomic.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -39,6 +40,7 @@
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/slab.h>
+#include <linux/serial_core.h>
#include <asm/uaccess.h>
@@ -69,6 +71,9 @@ static struct task_struct *hvc_task;
/* Picks up late kicks after list walk but before schedule() */
static int hvc_kicked;
+/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
+static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1);
+
static int hvc_init(void);
#ifdef CONFIG_MAGIC_SYSRQ
@@ -185,8 +190,8 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
return hvc_driver;
}
-static int __init hvc_console_setup(struct console *co, char *options)
-{
+static int hvc_console_setup(struct console *co, char *options)
+{
if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
return -ENODEV;
@@ -387,7 +392,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
* there is no buffered data otherwise sleeps on a wait queue
* waking periodically to check chars_in_buffer().
*/
- tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
+ tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT);
} else {
if (hp->count < 0)
printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
@@ -747,6 +752,58 @@ static int khvcd(void *unused)
return 0;
}
+static int hvc_tiocmget(struct tty_struct *tty)
+{
+ struct hvc_struct *hp = tty->driver_data;
+
+ if (!hp || !hp->ops->tiocmget)
+ return -EINVAL;
+ return hp->ops->tiocmget(hp);
+}
+
+static int hvc_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ struct hvc_struct *hp = tty->driver_data;
+
+ if (!hp || !hp->ops->tiocmset)
+ return -EINVAL;
+ return hp->ops->tiocmset(hp, set, clear);
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+int hvc_poll_init(struct tty_driver *driver, int line, char *options)
+{
+ return 0;
+}
+
+static int hvc_poll_get_char(struct tty_driver *driver, int line)
+{
+ struct tty_struct *tty = driver->ttys[0];
+ struct hvc_struct *hp = tty->driver_data;
+ int n;
+ char ch;
+
+ n = hp->ops->get_chars(hp->vtermno, &ch, 1);
+
+ if (n == 0)
+ return NO_POLL_CHAR;
+
+ return ch;
+}
+
+static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch)
+{
+ struct tty_struct *tty = driver->ttys[0];
+ struct hvc_struct *hp = tty->driver_data;
+ int n;
+
+ do {
+ n = hp->ops->put_chars(hp->vtermno, &ch, 1);
+ } while (n <= 0);
+}
+#endif
+
static const struct tty_operations hvc_ops = {
.open = hvc_open,
.close = hvc_close,
@@ -755,6 +812,13 @@ static const struct tty_operations hvc_ops = {
.unthrottle = hvc_unthrottle,
.write_room = hvc_write_room,
.chars_in_buffer = hvc_chars_in_buffer,
+ .tiocmget = hvc_tiocmget,
+ .tiocmset = hvc_tiocmset,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_init = hvc_poll_init,
+ .poll_get_char = hvc_poll_get_char,
+ .poll_put_char = hvc_poll_put_char,
+#endif
};
struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
@@ -765,7 +829,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
int i;
/* We wait until a driver actually comes along */
- if (!hvc_driver) {
+ if (atomic_inc_not_zero(&hvc_needs_init)) {
int err = hvc_init();
if (err)
return ERR_PTR(err);
diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
index 54381eba..c335a14 100644
--- a/drivers/tty/hvc/hvc_console.h
+++ b/drivers/tty/hvc/hvc_console.h
@@ -73,6 +73,10 @@ struct hv_ops {
int (*notifier_add)(struct hvc_struct *hp, int irq);
void (*notifier_del)(struct hvc_struct *hp, int irq);
void (*notifier_hangup)(struct hvc_struct *hp, int irq);
+
+ /* tiocmget/set implementation */
+ int (*tiocmget)(struct hvc_struct *hp);
+ int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear);
};
/* Register a vterm and a slot index for use as a console (console_init) */
diff --git a/drivers/tty/hvc/hvc_irq.c b/drivers/tty/hvc/hvc_irq.c
index 2623e17..c9adb05 100644
--- a/drivers/tty/hvc/hvc_irq.c
+++ b/drivers/tty/hvc/hvc_irq.c
@@ -28,7 +28,7 @@ int notifier_add_irq(struct hvc_struct *hp, int irq)
hp->irq_requested = 0;
return 0;
}
- rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED,
+ rc = request_irq(irq, hvc_handle_interrupt, 0,
"hvc_console", hp);
if (!rc)
hp->irq_requested = 1;
diff --git a/drivers/tty/hvc/hvc_iseries.c b/drivers/tty/hvc/hvc_iseries.c
index 21c5495..3f4a897 100644
--- a/drivers/tty/hvc/hvc_iseries.c
+++ b/drivers/tty/hvc/hvc_iseries.c
@@ -23,6 +23,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/console.h>
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index e6eea14..fc3c3ad 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -27,15 +27,28 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * TODO:
+ *
+ * - handle error in sending hvsi protocol packets
+ * - retry nego on subsequent sends ?
*/
+#undef DEBUG
+
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/module.h>
#include <asm/hvconsole.h>
#include <asm/vio.h>
#include <asm/prom.h>
#include <asm/firmware.h>
+#include <asm/hvsi.h>
+#include <asm/udbg.h>
#include "hvc_console.h"
@@ -43,59 +56,236 @@ static const char hvc_driver_name[] = "hvc_console";
static struct vio_device_id hvc_driver_table[] __devinitdata = {
{"serial", "hvterm1"},
+#ifndef HVC_OLD_HVSI
+ {"serial", "hvterm-protocol"},
+#endif
{ "", "" }
};
MODULE_DEVICE_TABLE(vio, hvc_driver_table);
-static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
+typedef enum hv_protocol {
+ HV_PROTOCOL_RAW,
+ HV_PROTOCOL_HVSI
+} hv_protocol_t;
+
+struct hvterm_priv {
+ u32 termno; /* HV term number */
+ hv_protocol_t proto; /* Raw data or HVSI packets */
+ struct hvsi_priv hvsi; /* HVSI specific data */
+ spinlock_t buf_lock;
+ char buf[SIZE_VIO_GET_CHARS];
+ int left;
+ int offset;
+};
+static struct hvterm_priv *hvterm_privs[MAX_NR_HVC_CONSOLES];
+/* For early boot console */
+static struct hvterm_priv hvterm_priv0;
+
+static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count)
{
- unsigned long got;
- int i;
+ struct hvterm_priv *pv = hvterm_privs[vtermno];
+ unsigned long i;
+ unsigned long flags;
+ int got;
- /*
- * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
- * so we play safe and avoid the situation where got > count which could
- * overload the flip buffer.
- */
- if (count < SIZE_VIO_GET_CHARS)
- return -EAGAIN;
+ if (WARN_ON(!pv))
+ return 0;
- got = hvc_get_chars(vtermno, buf, count);
+ spin_lock_irqsave(&pv->buf_lock, flags);
- /*
- * Work around a HV bug where it gives us a null
- * after every \r. -- paulus
- */
- for (i = 1; i < got; ++i) {
- if (buf[i] == 0 && buf[i-1] == '\r') {
- --got;
- if (i < got)
- memmove(&buf[i], &buf[i+1],
- got - i);
+ if (pv->left == 0) {
+ pv->offset = 0;
+ pv->left = hvc_get_chars(pv->termno, pv->buf, count);
+
+ /*
+ * Work around a HV bug where it gives us a null
+ * after every \r. -- paulus
+ */
+ for (i = 1; i < pv->left; ++i) {
+ if (pv->buf[i] == 0 && pv->buf[i-1] == '\r') {
+ --pv->left;
+ if (i < pv->left) {
+ memmove(&pv->buf[i], &pv->buf[i+1],
+ pv->left - i);
+ }
+ }
}
}
+
+ got = min(count, pv->left);
+ memcpy(buf, &pv->buf[pv->offset], got);
+ pv->offset += got;
+ pv->left -= got;
+
+ spin_unlock_irqrestore(&pv->buf_lock, flags);
+
return got;
}
-static const struct hv_ops hvc_get_put_ops = {
- .get_chars = filtered_get_chars,
- .put_chars = hvc_put_chars,
+static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+ struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+ if (WARN_ON(!pv))
+ return 0;
+
+ return hvc_put_chars(pv->termno, buf, count);
+}
+
+static const struct hv_ops hvterm_raw_ops = {
+ .get_chars = hvterm_raw_get_chars,
+ .put_chars = hvterm_raw_put_chars,
.notifier_add = notifier_add_irq,
.notifier_del = notifier_del_irq,
.notifier_hangup = notifier_hangup_irq,
};
+static int hvterm_hvsi_get_chars(uint32_t vtermno, char *buf, int count)
+{
+ struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+ if (WARN_ON(!pv))
+ return 0;
+
+ return hvsilib_get_chars(&pv->hvsi, buf, count);
+}
+
+static int hvterm_hvsi_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+ struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+ if (WARN_ON(!pv))
+ return 0;
+
+ return hvsilib_put_chars(&pv->hvsi, buf, count);
+}
+
+static int hvterm_hvsi_open(struct hvc_struct *hp, int data)
+{
+ struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+ int rc;
+
+ pr_devel("HVSI@%x: open !\n", pv->termno);
+
+ rc = notifier_add_irq(hp, data);
+ if (rc)
+ return rc;
+
+ return hvsilib_open(&pv->hvsi, hp);
+}
+
+static void hvterm_hvsi_close(struct hvc_struct *hp, int data)
+{
+ struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+ pr_devel("HVSI@%x: do close !\n", pv->termno);
+
+ hvsilib_close(&pv->hvsi, hp);
+
+ notifier_del_irq(hp, data);
+}
+
+void hvterm_hvsi_hangup(struct hvc_struct *hp, int data)
+{
+ struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+ pr_devel("HVSI@%x: do hangup !\n", pv->termno);
+
+ hvsilib_close(&pv->hvsi, hp);
+
+ notifier_hangup_irq(hp, data);
+}
+
+static int hvterm_hvsi_tiocmget(struct hvc_struct *hp)
+{
+ struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+ if (!pv)
+ return -EINVAL;
+ return pv->hvsi.mctrl;
+}
+
+static int hvterm_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
+ unsigned int clear)
+{
+ struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+ pr_devel("HVSI@%x: Set modem control, set=%x,clr=%x\n",
+ pv->termno, set, clear);
+
+ if (set & TIOCM_DTR)
+ hvsilib_write_mctrl(&pv->hvsi, 1);
+ else if (clear & TIOCM_DTR)
+ hvsilib_write_mctrl(&pv->hvsi, 0);
+
+ return 0;
+}
+
+static const struct hv_ops hvterm_hvsi_ops = {
+ .get_chars = hvterm_hvsi_get_chars,
+ .put_chars = hvterm_hvsi_put_chars,
+ .notifier_add = hvterm_hvsi_open,
+ .notifier_del = hvterm_hvsi_close,
+ .notifier_hangup = hvterm_hvsi_hangup,
+ .tiocmget = hvterm_hvsi_tiocmget,
+ .tiocmset = hvterm_hvsi_tiocmset,
+};
+
static int __devinit hvc_vio_probe(struct vio_dev *vdev,
- const struct vio_device_id *id)
+ const struct vio_device_id *id)
{
+ const struct hv_ops *ops;
struct hvc_struct *hp;
+ struct hvterm_priv *pv;
+ hv_protocol_t proto;
+ int i, termno = -1;
/* probed with invalid parameters. */
if (!vdev || !id)
return -EPERM;
- hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops,
- MAX_VIO_PUT_CHARS);
+ if (of_device_is_compatible(vdev->dev.of_node, "hvterm1")) {
+ proto = HV_PROTOCOL_RAW;
+ ops = &hvterm_raw_ops;
+ } else if (of_device_is_compatible(vdev->dev.of_node, "hvterm-protocol")) {
+ proto = HV_PROTOCOL_HVSI;
+ ops = &hvterm_hvsi_ops;
+ } else {
+ pr_err("hvc_vio: Unkown protocol for %s\n", vdev->dev.of_node->full_name);
+ return -ENXIO;
+ }
+
+ pr_devel("hvc_vio_probe() device %s, using %s protocol\n",
+ vdev->dev.of_node->full_name,
+ proto == HV_PROTOCOL_RAW ? "raw" : "hvsi");
+
+ /* Is it our boot one ? */
+ if (hvterm_privs[0] == &hvterm_priv0 &&
+ vdev->unit_address == hvterm_priv0.termno) {
+ pv = hvterm_privs[0];
+ termno = 0;
+ pr_devel("->boot console, using termno 0\n");
+ }
+ /* nope, allocate a new one */
+ else {
+ for (i = 0; i < MAX_NR_HVC_CONSOLES && termno < 0; i++)
+ if (!hvterm_privs[i])
+ termno = i;
+ pr_devel("->non-boot console, using termno %d\n", termno);
+ if (termno < 0)
+ return -ENODEV;
+ pv = kzalloc(sizeof(struct hvterm_priv), GFP_KERNEL);
+ if (!pv)
+ return -ENOMEM;
+ pv->termno = vdev->unit_address;
+ pv->proto = proto;
+ spin_lock_init(&pv->buf_lock);
+ hvterm_privs[termno] = pv;
+ hvsilib_init(&pv->hvsi, hvc_get_chars, hvc_put_chars,
+ pv->termno, 0);
+ }
+
+ hp = hvc_alloc(termno, vdev->irq, ops, MAX_VIO_PUT_CHARS);
if (IS_ERR(hp))
return PTR_ERR(hp);
dev_set_drvdata(&vdev->dev, hp);
@@ -106,8 +296,16 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
static int __devexit hvc_vio_remove(struct vio_dev *vdev)
{
struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
+ int rc, termno;
- return hvc_remove(hp);
+ termno = hp->vtermno;
+ rc = hvc_remove(hp);
+ if (rc == 0) {
+ if (hvterm_privs[termno] != &hvterm_priv0)
+ kfree(hvterm_privs[termno]);
+ hvterm_privs[termno] = NULL;
+ }
+ return rc;
}
static struct vio_driver hvc_vio_driver = {
@@ -140,34 +338,149 @@ static void __exit hvc_vio_exit(void)
}
module_exit(hvc_vio_exit);
-/* the device tree order defines our numbering */
-static int hvc_find_vtys(void)
+static void udbg_hvc_putc(char c)
{
- struct device_node *vty;
- int num_found = 0;
+ int count = -1;
- for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
- vty = of_find_node_by_name(vty, "vty")) {
- const uint32_t *vtermno;
+ if (c == '\n')
+ udbg_hvc_putc('\r');
- /* We have statically defined space for only a certain number
- * of console adapters.
- */
- if (num_found >= MAX_NR_HVC_CONSOLES) {
- of_node_put(vty);
+ do {
+ switch(hvterm_priv0.proto) {
+ case HV_PROTOCOL_RAW:
+ count = hvterm_raw_put_chars(0, &c, 1);
+ break;
+ case HV_PROTOCOL_HVSI:
+ count = hvterm_hvsi_put_chars(0, &c, 1);
break;
}
+ } while(count == 0);
+}
+
+static int udbg_hvc_getc_poll(void)
+{
+ int rc = 0;
+ char c;
- vtermno = of_get_property(vty, "reg", NULL);
- if (!vtermno)
- continue;
+ switch(hvterm_priv0.proto) {
+ case HV_PROTOCOL_RAW:
+ rc = hvterm_raw_get_chars(0, &c, 1);
+ break;
+ case HV_PROTOCOL_HVSI:
+ rc = hvterm_hvsi_get_chars(0, &c, 1);
+ break;
+ }
+ if (!rc)
+ return -1;
+ return c;
+}
- if (of_device_is_compatible(vty, "hvterm1")) {
- hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
- ++num_found;
+static int udbg_hvc_getc(void)
+{
+ int ch;
+ for (;;) {
+ ch = udbg_hvc_getc_poll();
+ if (ch == -1) {
+ /* This shouldn't be needed...but... */
+ volatile unsigned long delay;
+ for (delay=0; delay < 2000000; delay++)
+ ;
+ } else {
+ return ch;
}
}
+}
+
+void __init hvc_vio_init_early(void)
+{
+ struct device_node *stdout_node;
+ const u32 *termno;
+ const char *name;
+ const struct hv_ops *ops;
+
+ /* find the boot console from /chosen/stdout */
+ if (!of_chosen)
+ return;
+ name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+ if (name == NULL)
+ return;
+ stdout_node = of_find_node_by_path(name);
+ if (!stdout_node)
+ return;
+ name = of_get_property(stdout_node, "name", NULL);
+ if (!name) {
+ printk(KERN_WARNING "stdout node missing 'name' property!\n");
+ goto out;
+ }
+
+ /* Check if it's a virtual terminal */
+ if (strncmp(name, "vty", 3) != 0)
+ goto out;
+ termno = of_get_property(stdout_node, "reg", NULL);
+ if (termno == NULL)
+ goto out;
+ hvterm_priv0.termno = *termno;
+ spin_lock_init(&hvterm_priv0.buf_lock);
+ hvterm_privs[0] = &hvterm_priv0;
+
+ /* Check the protocol */
+ if (of_device_is_compatible(stdout_node, "hvterm1")) {
+ hvterm_priv0.proto = HV_PROTOCOL_RAW;
+ ops = &hvterm_raw_ops;
+ }
+ else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
+ hvterm_priv0.proto = HV_PROTOCOL_HVSI;
+ ops = &hvterm_hvsi_ops;
+ hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
+ hvterm_priv0.termno, 1);
+ /* HVSI, perform the handshake now */
+ hvsilib_establish(&hvterm_priv0.hvsi);
+ } else
+ goto out;
+ udbg_putc = udbg_hvc_putc;
+ udbg_getc = udbg_hvc_getc;
+ udbg_getc_poll = udbg_hvc_getc_poll;
+#ifdef HVC_OLD_HVSI
+ /* When using the old HVSI driver don't register the HVC
+ * backend for HVSI, only do udbg
+ */
+ if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
+ goto out;
+#endif
+ add_preferred_console("hvc", 0, NULL);
+ hvc_instantiate(0, 0, ops);
+out:
+ of_node_put(stdout_node);
+}
- return num_found;
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR
+void __init udbg_init_debug_lpar(void)
+{
+ hvterm_privs[0] = &hvterm_priv0;
+ hvterm_priv0.termno = 0;
+ hvterm_priv0.proto = HV_PROTOCOL_RAW;
+ spin_lock_init(&hvterm_priv0.buf_lock);
+ udbg_putc = udbg_hvc_putc;
+ udbg_getc = udbg_hvc_getc;
+ udbg_getc_poll = udbg_hvc_getc_poll;
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_LPAR */
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI
+void __init udbg_init_debug_lpar_hvsi(void)
+{
+ hvterm_privs[0] = &hvterm_priv0;
+ hvterm_priv0.termno = CONFIG_PPC_EARLY_DEBUG_HVSI_VTERMNO;
+ hvterm_priv0.proto = HV_PROTOCOL_HVSI;
+ spin_lock_init(&hvterm_priv0.buf_lock);
+ udbg_putc = udbg_hvc_putc;
+ udbg_getc = udbg_hvc_getc;
+ udbg_getc_poll = udbg_hvc_getc_poll;
+ hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
+ hvterm_priv0.termno, 1);
+ hvsilib_establish(&hvterm_priv0.hvsi);
}
-console_initcall(hvc_find_vtys);
+#endif /* CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI */
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 52fdf60..df8f8e0 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -167,7 +167,7 @@ static int __init xen_hvc_init(void)
if (xen_initial_domain()) {
ops = &dom0_hvc_ops;
- xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
+ xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
} else {
if (!xen_start_info->console.domU.evtchn)
return -ENODEV;
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 4c8b665..b9040be 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1057,7 +1057,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
* the conn was registered and now.
*/
if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
- IRQF_DISABLED, "ibmhvcs", hvcsd))) {
+ 0, "ibmhvcs", hvcsd))) {
/*
* It is possible the vty-server was removed after the irq was
* requested but before we have time to enable interrupts.
@@ -1237,7 +1237,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
irq = hvcsd->vdev->irq;
spin_unlock_irqrestore(&hvcsd->lock, flags);
- tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
+ tty_wait_until_sent_from_close(tty, HVCS_CLOSE_WAIT);
/*
* This line is important because it tells hvcs_open that this
@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(void)
goto register_fail;
}
- hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL);
if (!hvcs_pi_buff) {
rc = -ENOMEM;
goto buff_alloc_fail;
@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(void)
return 0;
kthread_fail:
- kfree(hvcs_pi_buff);
+ free_page((unsigned long)hvcs_pi_buff);
buff_alloc_fail:
tty_unregister_driver(hvcs_tty_driver);
register_fail:
@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void)
kthread_stop(hvcs_task);
spin_lock(&hvcs_pi_lock);
- kfree(hvcs_pi_buff);
+ free_page((unsigned long)hvcs_pi_buff);
hvcs_pi_buff = NULL;
spin_unlock(&hvcs_pi_lock);
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 8a8d637..cdfa3e0 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -49,6 +49,7 @@
#include <asm/uaccess.h>
#include <asm/vio.h>
#include <asm/param.h>
+#include <asm/hvsi.h>
#define HVSI_MAJOR 229
#define HVSI_MINOR 128
@@ -109,68 +110,6 @@ enum HVSI_PROTOCOL_STATE {
};
#define HVSI_CONSOLE 0x1
-#define VS_DATA_PACKET_HEADER 0xff
-#define VS_CONTROL_PACKET_HEADER 0xfe
-#define VS_QUERY_PACKET_HEADER 0xfd
-#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
-
-/* control verbs */
-#define VSV_SET_MODEM_CTL 1 /* to service processor only */
-#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
-#define VSV_CLOSE_PROTOCOL 3
-
-/* query verbs */
-#define VSV_SEND_VERSION_NUMBER 1
-#define VSV_SEND_MODEM_CTL_STATUS 2
-
-/* yes, these masks are not consecutive. */
-#define HVSI_TSDTR 0x01
-#define HVSI_TSCD 0x20
-
-struct hvsi_header {
- uint8_t type;
- uint8_t len;
- uint16_t seqno;
-} __attribute__((packed));
-
-struct hvsi_data {
- uint8_t type;
- uint8_t len;
- uint16_t seqno;
- uint8_t data[HVSI_MAX_OUTGOING_DATA];
-} __attribute__((packed));
-
-struct hvsi_control {
- uint8_t type;
- uint8_t len;
- uint16_t seqno;
- uint16_t verb;
- /* optional depending on verb: */
- uint32_t word;
- uint32_t mask;
-} __attribute__((packed));
-
-struct hvsi_query {
- uint8_t type;
- uint8_t len;
- uint16_t seqno;
- uint16_t verb;
-} __attribute__((packed));
-
-struct hvsi_query_response {
- uint8_t type;
- uint8_t len;
- uint16_t seqno;
- uint16_t verb;
- uint16_t query_seqno;
- union {
- uint8_t version;
- uint32_t mctrl_word;
- } u;
-} __attribute__((packed));
-
-
-
static inline int is_console(struct hvsi_struct *hp)
{
return hp->flags & HVSI_CONSOLE;
@@ -356,18 +295,18 @@ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
struct hvsi_query_response packet __ALIGNED__;
int wrote;
- packet.type = VS_QUERY_RESPONSE_PACKET_HEADER;
- packet.len = sizeof(struct hvsi_query_response);
- packet.seqno = atomic_inc_return(&hp->seqno);
+ packet.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+ packet.hdr.len = sizeof(struct hvsi_query_response);
+ packet.hdr.seqno = atomic_inc_return(&hp->seqno);
packet.verb = VSV_SEND_VERSION_NUMBER;
packet.u.version = HVSI_VERSION;
packet.query_seqno = query_seqno+1;
- pr_debug("%s: sending %i bytes\n", __func__, packet.len);
- dbg_dump_hex((uint8_t*)&packet, packet.len);
+ pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
- wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
- if (wrote != packet.len) {
+ wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+ if (wrote != packet.hdr.len) {
printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
hp->index);
return -EIO;
@@ -382,7 +321,7 @@ static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
switch (hp->state) {
case HVSI_WAIT_FOR_VER_QUERY:
- hvsi_version_respond(hp, query->seqno);
+ hvsi_version_respond(hp, query->hdr.seqno);
__set_state(hp, HVSI_OPEN);
break;
default:
@@ -640,16 +579,16 @@ static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
struct hvsi_query packet __ALIGNED__;
int wrote;
- packet.type = VS_QUERY_PACKET_HEADER;
- packet.len = sizeof(struct hvsi_query);
- packet.seqno = atomic_inc_return(&hp->seqno);
+ packet.hdr.type = VS_QUERY_PACKET_HEADER;
+ packet.hdr.len = sizeof(struct hvsi_query);
+ packet.hdr.seqno = atomic_inc_return(&hp->seqno);
packet.verb = verb;
- pr_debug("%s: sending %i bytes\n", __func__, packet.len);
- dbg_dump_hex((uint8_t*)&packet, packet.len);
+ pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
- wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
- if (wrote != packet.len) {
+ wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+ if (wrote != packet.hdr.len) {
printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
wrote);
return -EIO;
@@ -683,20 +622,20 @@ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
struct hvsi_control packet __ALIGNED__;
int wrote;
- packet.type = VS_CONTROL_PACKET_HEADER,
- packet.seqno = atomic_inc_return(&hp->seqno);
- packet.len = sizeof(struct hvsi_control);
+ packet.hdr.type = VS_CONTROL_PACKET_HEADER,
+ packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+ packet.hdr.len = sizeof(struct hvsi_control);
packet.verb = VSV_SET_MODEM_CTL;
packet.mask = HVSI_TSDTR;
if (mctrl & TIOCM_DTR)
packet.word = HVSI_TSDTR;
- pr_debug("%s: sending %i bytes\n", __func__, packet.len);
- dbg_dump_hex((uint8_t*)&packet, packet.len);
+ pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
- wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
- if (wrote != packet.len) {
+ wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+ if (wrote != packet.hdr.len) {
printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
return -EIO;
}
@@ -766,13 +705,13 @@ static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
- packet.type = VS_DATA_PACKET_HEADER;
- packet.seqno = atomic_inc_return(&hp->seqno);
- packet.len = count + sizeof(struct hvsi_header);
+ packet.hdr.type = VS_DATA_PACKET_HEADER;
+ packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+ packet.hdr.len = count + sizeof(struct hvsi_header);
memcpy(&packet.data, buf, count);
- ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
- if (ret == packet.len) {
+ ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+ if (ret == packet.hdr.len) {
/* return the number of chars written, not the packet length */
return count;
}
@@ -783,15 +722,15 @@ static void hvsi_close_protocol(struct hvsi_struct *hp)
{
struct hvsi_control packet __ALIGNED__;
- packet.type = VS_CONTROL_PACKET_HEADER;
- packet.seqno = atomic_inc_return(&hp->seqno);
- packet.len = 6;
+ packet.hdr.type = VS_CONTROL_PACKET_HEADER;
+ packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+ packet.hdr.len = 6;
packet.verb = VSV_CLOSE_PROTOCOL;
- pr_debug("%s: sending %i bytes\n", __func__, packet.len);
- dbg_dump_hex((uint8_t*)&packet, packet.len);
+ pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+ dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
- hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+ hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
}
static int hvsi_open(struct tty_struct *tty, struct file *filp)
@@ -1166,7 +1105,7 @@ static int __init hvsi_init(void)
struct hvsi_struct *hp = &hvsi_ports[i];
int ret = 1;
- ret = request_irq(hp->virq, hvsi_interrupt, IRQF_DISABLED, "hvsi", hp);
+ ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
if (ret)
printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
hp->virq, ret);
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 9488da7..b418947 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h
index 5b837e7..529bec6 100644
--- a/drivers/tty/serial/jsm/jsm.h
+++ b/drivers/tty/serial/jsm/jsm.h
@@ -88,7 +88,6 @@ enum {
/* 4 extra for alignment play space */
#define WRITEBUFLEN ((4096) + 4)
-#define MYFLIPLEN N_TTY_BUF_SIZE
#define JSM_VERSION "jsm: 1.2-1-INKERNEL"
#define JSM_PARTNUM "40002438_A-INKERNEL"
@@ -150,7 +149,6 @@ struct jsm_board
u32 bd_uart_offset; /* Space between each UART */
struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */
- char *flipbuf; /* Our flip buffer, alloced if board is found */
u32 bd_dividend; /* Board/UARTs specific dividend */
@@ -177,7 +175,6 @@ struct jsm_board
#define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */
#define CH_BREAK_SENDING 0x1000 /* Break is being sent */
#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */
-#define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */
#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */
/* Our Read/Error/Write queue sizes */
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 6c12d94..7545fe1 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -24,7 +24,7 @@
*
*
***********************************************************************/
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
@@ -160,27 +160,10 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n",
adapter_count, brd->rev, brd->irq);
- /*
- * allocate flip buffer for board.
- *
- * Okay to malloc with GFP_KERNEL, we are not at interrupt
- * context, and there are no locks held.
- */
- brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
- if (!brd->flipbuf) {
- /* XXX: leaking all resources from jsm_tty_init and
- jsm_uart_port_init here! */
- dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
- rc = -ENOMEM;
- goto out_free_uart;
- }
-
pci_set_drvdata(pdev, brd);
pci_save_state(pdev);
return 0;
- out_free_uart:
- jsm_remove_uart_port(brd);
out_free_irq:
jsm_remove_uart_port(brd);
free_irq(brd->irq, brd);
@@ -217,7 +200,6 @@ static void __devexit jsm_remove_one(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
- kfree(brd->flipbuf);
kfree(brd);
}
diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c
index bd6e846..81dfafa 100644
--- a/drivers/tty/serial/jsm/jsm_neo.c
+++ b/drivers/tty/serial/jsm/jsm_neo.c
@@ -522,7 +522,7 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx);
jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
- "Tx data: %x\n", circ->buf[circ->head]);
+ "Tx data: %x\n", circ->buf[circ->tail]);
circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
ch->ch_txcount++;
}
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index f343808..fb95acc 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -518,6 +518,8 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
/* Save original vc_unipagdir_loc in case we allocate a new one */
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
+ if (!p)
+ return -EINVAL;
if (p->readonly) return -EIO;
if (!ct) return 0;
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 3761ccf..a605549 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -33,7 +33,6 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/irq.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
@@ -43,6 +42,8 @@
#include <linux/notifier.h>
#include <linux/jiffies.h>
+#include <asm/irq_regs.h>
+
extern void ctrl_alt_del(void);
/*
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index fb864e7..7a0a12a 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -301,6 +301,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
/* Insert the contents of the selection buffer into the
* queue of the tty associated with the current console.
* Invoked by ioctl().
+ *
+ * Locking: always called with BTM from vt_ioctl
*/
int paste_selection(struct tty_struct *tty)
{
@@ -310,8 +312,6 @@ int paste_selection(struct tty_struct *tty)
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
- /* always called with BTM from vt_ioctl */
- WARN_ON(!tty_locked());
console_lock();
poke_blanked_console();
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index ab23201..fd89c42 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/errno.h>
+#include <linux/export.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index e41288a..c51803f 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(unregister_vt_notifier);
static void notify_write(struct vc_data *vc, unsigned int unicode)
{
- struct vt_notifier_param param = { .vc = vc, unicode = unicode };
+ struct vt_notifier_param param = { .vc = vc, .c = unicode };
atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, &param);
}
@@ -499,6 +499,7 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
#endif
if (DO_UPDATE(vc))
do_update_region(vc, (unsigned long) p, count);
+ notify_update(vc);
}
/* used by selection: complement pointer position */
@@ -515,6 +516,7 @@ void complement_pos(struct vc_data *vc, int offset)
scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, old, oldy, oldx);
+ notify_update(vc);
}
old_offset = offset;
@@ -532,8 +534,8 @@ void complement_pos(struct vc_data *vc, int offset)
oldy = (offset >> 1) / vc->vc_cols;
vc->vc_sw->con_putc(vc, new, oldy, oldx);
}
+ notify_update(vc);
}
-
}
static void insert_char(struct vc_data *vc, unsigned int nr)
@@ -657,7 +659,7 @@ static inline void save_screen(struct vc_data *vc)
* Redrawing of screen
*/
-static void clear_buffer_attributes(struct vc_data *vc)
+void clear_buffer_attributes(struct vc_data *vc)
{
unsigned short *p = (unsigned short *)vc->vc_origin;
int count = vc->vc_screenbuf_size / 2;
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index d2efe82..af57648 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -69,7 +69,7 @@ static ssize_t map_name_show(struct uio_mem *mem, char *buf)
static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
{
- return sprintf(buf, "0x%lx\n", mem->addr);
+ return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr);
}
static ssize_t map_size_show(struct uio_mem *mem, char *buf)
@@ -79,7 +79,7 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
{
- return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
+ return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr & ~PAGE_MASK);
}
struct map_sysfs_entry {
@@ -634,8 +634,7 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
page = virt_to_page(idev->info->mem[mi].addr + offset);
else
- page = vmalloc_to_page((void *)idev->info->mem[mi].addr
- + offset);
+ page = vmalloc_to_page((void *)(unsigned long)idev->info->mem[mi].addr + offset);
get_page(page);
vmf->page = page;
return 0;
@@ -651,16 +650,28 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
{
struct uio_device *idev = vma->vm_private_data;
int mi = uio_find_mem_index(vma);
+ struct uio_mem *mem;
if (mi < 0)
return -EINVAL;
+ mem = idev->info->mem + mi;
- vma->vm_flags |= VM_IO | VM_RESERVED;
+ if (vma->vm_end - vma->vm_start > mem->size)
+ return -EINVAL;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ /*
+ * We cannot use the vm_iomap_memory() helper here,
+ * because vma->vm_pgoff is the map index we looked
+ * up above in uio_find_mem_index(), rather than an
+ * actual page offset into the mmap.
+ *
+ * So we just do the physical mmap without a page
+ * offset.
+ */
return remap_pfn_range(vma,
vma->vm_start,
- idev->info->mem[mi].addr >> PAGE_SHIFT,
+ mem->addr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
}
@@ -750,14 +761,13 @@ static int uio_major_init(void)
uio_major = MAJOR(uio_dev);
uio_cdev = cdev;
- result = 0;
-out:
- return result;
+ return 0;
out_put:
kobject_put(&cdev->kobj);
out_unregister:
unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
- goto out;
+out:
+ return result;
}
static void uio_major_cleanup(void)
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index fc22e1e..02bd47b 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -24,7 +24,6 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/uio_driver.h>
-#include <linux/spinlock.h>
#define DRIVER_VERSION "0.01.0"
#define DRIVER_AUTHOR "Michael S. Tsirkin <mst@redhat.com>"
@@ -33,7 +32,6 @@
struct uio_pci_generic_dev {
struct uio_info info;
struct pci_dev *pdev;
- spinlock_t lock; /* guards command register accesses */
};
static inline struct uio_pci_generic_dev *
@@ -57,7 +55,6 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
BUILD_BUG_ON(PCI_COMMAND % 4);
BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
- spin_lock_irq(&gdev->lock);
pci_block_user_cfg_access(pdev);
/* Read both command and status registers in a single 32-bit operation.
@@ -83,7 +80,6 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
done:
pci_unblock_user_cfg_access(pdev);
- spin_unlock_irq(&gdev->lock);
return ret;
}
@@ -158,7 +154,6 @@ static int __devinit probe(struct pci_dev *pdev,
gdev->info.irq_flags = IRQF_SHARED;
gdev->info.handler = irqhandler;
gdev->pdev = pdev;
- spin_lock_init(&gdev->lock);
if (uio_register_device(&pdev->dev, &gdev->info))
goto err_register;
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
index 7d3e469..ff50595 100644
--- a/drivers/uio/uio_pdrv.c
+++ b/drivers/uio/uio_pdrv.c
@@ -11,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <linux/stringify.h>
+#include <linux/module.h>
#include <linux/slab.h>
#define DRIVER_NAME "uio_pdrv"
@@ -58,7 +59,7 @@ static int uio_pdrv_probe(struct platform_device *pdev)
uiomem->memtype = UIO_MEM_PHYS;
uiomem->addr = r->start;
- uiomem->size = r->end - r->start + 1;
+ uiomem->size = resource_size(r);
++uiomem;
}
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 0f424af..25de302 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -18,11 +18,16 @@
#include <linux/uio_driver.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/stringify.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
#define DRIVER_NAME "uio_pdrv_genirq"
struct uio_pdrv_genirq_platdata {
@@ -97,6 +102,27 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
int ret = -EINVAL;
int i;
+ if (!uioinfo) {
+ int irq;
+
+ /* alloc uioinfo for one device */
+ uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+ if (!uioinfo) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "unable to kmalloc\n");
+ goto bad2;
+ }
+ uioinfo->name = pdev->dev.of_node->name;
+ uioinfo->version = "devicetree";
+
+ /* Multiple IRQs are not supported */
+ irq = platform_get_irq(pdev, 0);
+ if (irq == -ENXIO)
+ uioinfo->irq = UIO_IRQ_NONE;
+ else
+ uioinfo->irq = irq;
+ }
+
if (!uioinfo || !uioinfo->name || !uioinfo->version) {
dev_err(&pdev->dev, "missing platform_data\n");
goto bad0;
@@ -137,7 +163,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
uiomem->memtype = UIO_MEM_PHYS;
uiomem->addr = r->start;
- uiomem->size = r->end - r->start + 1;
+ uiomem->size = resource_size(r);
++uiomem;
}
@@ -180,6 +206,10 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
kfree(priv);
pm_runtime_disable(&pdev->dev);
bad0:
+ /* kfree uioinfo for OF */
+ if (pdev->dev.of_node)
+ kfree(uioinfo);
+ bad2:
return ret;
}
@@ -193,6 +223,10 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
priv->uioinfo->handler = NULL;
priv->uioinfo->irqcontrol = NULL;
+ /* kfree uioinfo for OF */
+ if (pdev->dev.of_node)
+ kfree(priv->uioinfo);
+
kfree(priv);
return 0;
}
@@ -219,6 +253,15 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = {
.runtime_resume = uio_pdrv_genirq_runtime_nop,
};
+#ifdef CONFIG_OF
+static const struct of_device_id uio_of_genirq_match[] = {
+ { /* empty for now */ },
+};
+MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
+#else
+# define uio_of_genirq_match NULL
+#endif
+
static struct platform_driver uio_pdrv_genirq = {
.probe = uio_pdrv_genirq_probe,
.remove = uio_pdrv_genirq_remove,
@@ -226,6 +269,7 @@ static struct platform_driver uio_pdrv_genirq = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.pm = &uio_pdrv_genirq_dev_pm_ops,
+ .of_match_table = uio_of_genirq_match,
},
};
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e71521c..428f368 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -116,14 +116,14 @@ struct uea_cmvs_v1 {
u32 address;
u16 offset;
u32 data;
-} __attribute__ ((packed));
+} __packed;
struct uea_cmvs_v2 {
u32 group;
u32 address;
u32 offset;
u32 data;
-} __attribute__ ((packed));
+} __packed;
/* information about currently processed cmv */
struct cmv_dsc_e1 {
@@ -352,7 +352,7 @@ struct block_index {
__le32 PageAddress;
__le16 dummy1;
__le16 PageNumber;
-} __attribute__ ((packed));
+} __packed;
#define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000)
#define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4)
@@ -367,7 +367,7 @@ struct l1_code {
u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER];
struct block_index page_header[E4_NO_SWAPPAGE_HEADERS];
u8 code[0];
-} __attribute__ ((packed));
+} __packed;
/* structures describing a block within a DSP page */
struct block_info_e1 {
@@ -377,7 +377,7 @@ struct block_info_e1 {
__le16 wOvlOffset;
__le16 wOvl; /* overlay */
__le16 wLast;
-} __attribute__ ((packed));
+} __packed;
#define E1_BLOCK_INFO_SIZE 12
struct block_info_e4 {
@@ -387,7 +387,7 @@ struct block_info_e4 {
__be32 dwSize;
__be32 dwAddress;
__be16 wReserved;
-} __attribute__ ((packed));
+} __packed;
#define E4_BLOCK_INFO_SIZE 14
#define UEA_BIHDR 0xabcd
@@ -467,7 +467,7 @@ struct cmv_e1 {
__le32 dwSymbolicAddress;
__le16 wOffsetAddress;
__le32 dwData;
-} __attribute__ ((packed));
+} __packed;
struct cmv_e4 {
__be16 wGroup;
@@ -475,17 +475,17 @@ struct cmv_e4 {
__be16 wOffset;
__be16 wAddress;
__be32 dwData[6];
-} __attribute__ ((packed));
+} __packed;
/* structures representing swap information */
struct swap_info_e1 {
__u8 bSwapPageNo;
__u8 bOvl; /* overlay */
-} __attribute__ ((packed));
+} __packed;
struct swap_info_e4 {
__u8 bSwapPageNo;
-} __attribute__ ((packed));
+} __packed;
/* structures representing interrupt data */
#define e1_bSwapPageNo u.e1.s1.swapinfo.bSwapPageNo
@@ -499,23 +499,23 @@ union intr_data_e1 {
struct {
struct swap_info_e1 swapinfo;
__le16 wDataSize;
- } __attribute__ ((packed)) s1;
+ } __packed s1;
struct {
struct cmv_e1 cmv;
__le16 wDataSize;
- } __attribute__ ((packed)) s2;
-} __attribute__ ((packed));
+ } __packed s2;
+} __packed;
union intr_data_e4 {
struct {
struct swap_info_e4 swapinfo;
__le16 wDataSize;
- } __attribute__ ((packed)) s1;
+ } __packed s1;
struct {
struct cmv_e4 cmv;
__le16 wDataSize;
- } __attribute__ ((packed)) s2;
-} __attribute__ ((packed));
+ } __packed s2;
+} __packed;
struct intr_pkt {
__u8 bType;
@@ -528,15 +528,15 @@ struct intr_pkt {
union intr_data_e1 e1;
union intr_data_e4 e4;
} u;
-} __attribute__ ((packed));
+} __packed;
#define E1_INTR_PKT_SIZE 28
#define E4_INTR_PKT_SIZE 64
static struct usb_driver uea_driver;
static DEFINE_MUTEX(uea_mutex);
-static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III",
- "Eagle IV"};
+static const char * const chip_name[] = {
+ "ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"};
static int modem_index;
static unsigned int debug;
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 989e16e..d3448ca 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -81,6 +81,7 @@
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/kthread.h>
+#include <linux/ratelimit.h>
#ifdef VERBOSE_DEBUG
static int usbatm_print_packet(const unsigned char *data, int len);
@@ -668,8 +669,7 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
/* racy disconnection check - fine */
if (!instance || instance->disconnected) {
#ifdef DEBUG
- if (printk_ratelimit())
- printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
+ printk_ratelimited(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
#endif
err = -ENODEV;
goto fail;
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 62050f7..57ae44c 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -38,6 +38,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/c67x00.h>
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c
index 767af26..ba61dae 100644
--- a/drivers/usb/host/whci/debug.c
+++ b/drivers/usb/host/whci/debug.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/export.h>
#include "../../wusbcore/wusbhc.h"
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index 9546f6c..1e141f7 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -17,6 +17,7 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/uwb/umc.h>
#include "../../wusbcore/wusbhc.h"
diff --git a/drivers/usb/host/whci/init.c b/drivers/usb/host/whci/init.c
index f7582e8..d3e13b6 100644
--- a/drivers/usb/host/whci/init.c
+++ b/drivers/usb/host/whci/init.c
@@ -178,7 +178,7 @@ void whc_clean_up(struct whc *whc)
if (whc->qset_pool)
dma_pool_destroy(whc->qset_pool);
- len = whc->umc->resource.end - whc->umc->resource.start + 1;
+ len = resource_size(&whc->umc->resource);
if (whc->base)
iounmap(whc->base);
if (whc->base_phys)
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index a003796..27e209a 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -131,7 +131,7 @@
#include <linux/usb.h>
#include <linux/proc_fs.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/blkdev.h>
#include "../../scsi/scsi.h"
#include <scsi/scsi_host.h>
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index a04b2ff..91cd850 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
+#include <linux/export.h>
#include <linux/usb.h>
#include <linux/poll.h>
#include <linux/compat.h>
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
index e5ce42b..ebd6189 100644
--- a/drivers/usb/mon/mon_stat.c
+++ b/drivers/usb/mon/mon_stat.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <linux/usb.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index c302e19..ad40825 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -9,6 +9,7 @@
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/export.h>
#include <linux/mutex.h>
#include <linux/debugfs.h>
#include <linux/scatterlist.h>
@@ -670,6 +671,9 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
int busnum = ubus? ubus->busnum: 0;
int rc;
+ if (mon_dir == NULL)
+ return 0;
+
if (ubus != NULL) {
rc = snprintf(name, NAMESZ, "%dt", busnum);
if (rc <= 0 || rc >= NAMESZ)
@@ -740,12 +744,12 @@ int __init mon_text_init(void)
mondir = debugfs_create_dir("usbmon", usb_debug_root);
if (IS_ERR(mondir)) {
- printk(KERN_NOTICE TAG ": debugfs is not available\n");
- return -ENODEV;
+ /* debugfs not available, but we can use usbmon without it */
+ return 0;
}
if (mondir == NULL) {
printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
- return -ENODEV;
+ return -ENOMEM;
}
mon_dir = mondir;
return 0;
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 1309348..07a0346 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -3,17 +3,15 @@
# for silicon based on Mentor Graphics INVENTRA designs
#
-comment "Enable Host or Gadget support to see Inventra options"
- depends on !USB && USB_GADGET=n
-
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC
- depends on (USB || USB_GADGET)
+ depends on USB && USB_GADGET
depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523))
select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
select TWL4030_USB if MACH_OMAP_3430SDP
select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
select USB_OTG_UTILS
+ select USB_GADGET_DUALSPEED
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
help
Say Y here if your system has a dual role high speed USB
@@ -63,83 +61,10 @@ config USB_MUSB_BLACKFIN
config USB_MUSB_UX500
tristate "U8500 and U5500"
- depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500)
+ depends on (ARCH_U8500 && AB8500_USB)
endchoice
-choice
- prompt "Driver Mode"
- depends on USB_MUSB_HDRC
- help
- Dual-Role devices can support both host and peripheral roles,
- as well as a the special "OTG Device" role which can switch
- between both roles as needed.
-
-# use USB_MUSB_HDRC_HCD not USB_MUSB_HOST to #ifdef host side support;
-# OTG needs both roles, not just USB_MUSB_HOST.
-config USB_MUSB_HOST
- depends on USB
- bool "USB Host"
- help
- Say Y here if your system supports the USB host role.
- If it has a USB "A" (rectangular), "Mini-A" (uncommon),
- or "Mini-AB" connector, it supports the host role.
- (With a "Mini-AB" connector, you should enable USB OTG.)
-
-# use USB_GADGET_MUSB_HDRC not USB_MUSB_PERIPHERAL to #ifdef peripheral
-# side support ... OTG needs both roles
-config USB_MUSB_PERIPHERAL
- depends on USB_GADGET
- bool "USB Peripheral (gadget stack)"
- select USB_GADGET_MUSB_HDRC
- help
- Say Y here if your system supports the USB peripheral role.
- If it has a USB "B" (squarish), "Mini-B", or "Mini-AB"
- connector, it supports the peripheral role.
- (With a "Mini-AB" connector, you should enable USB OTG.)
-
-config USB_MUSB_OTG
- depends on USB && USB_GADGET && PM && EXPERIMENTAL
- bool "Both host and peripheral: USB OTG (On The Go) Device"
- select USB_GADGET_MUSB_HDRC
- select USB_OTG
- help
- The most notable feature of USB OTG is support for a
- "Dual-Role" device, which can act as either a device
- or a host. The initial role choice can be changed
- later, when two dual-role devices talk to each other.
-
- At this writing, the OTG support in this driver is incomplete,
- omitting the mandatory HNP or SRP protocols. However, some
- of the cable based role switching works. (That is, grounding
- the ID pin switches the controller to host mode, while leaving
- it floating leaves it in peripheral mode.)
-
- Select this if your system has a Mini-AB connector, or
- to simplify certain kinds of configuration.
-
- To implement your OTG Targeted Peripherals List (TPL), enable
- USB_OTG_WHITELIST and update "drivers/usb/core/otg_whitelist.h"
- to match your requirements.
-
-endchoice
-
-# enable peripheral support (including with OTG)
-config USB_GADGET_MUSB_HDRC
- bool
- depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
-# default y
-# select USB_GADGET_DUALSPEED
-# select USB_GADGET_SELECTED
-
-# enables host support (including with OTG)
-config USB_MUSB_HDRC_HCD
- bool
- depends on USB_MUSB_HDRC && (USB_MUSB_HOST || USB_MUSB_OTG)
- select USB_OTG if USB_GADGET_MUSB_HDRC
- default y
-
-
config MUSB_PIO_ONLY
bool 'Disable DMA (always use PIO)'
depends on USB_MUSB_HDRC
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index c4d228b..d8fd9d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -6,8 +6,8 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o
musb_hdrc-y := musb_core.o
-musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC) += musb_gadget_ep0.o musb_gadget.o
-musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD) += musb_virthub.o musb_host.o
+musb_hdrc-y += musb_gadget_ep0.o musb_gadget.o
+musb_hdrc-y += musb_virthub.o musb_host.o
musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o
# Hardware Glue Layer
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 23ac28f..e233d2b 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -27,6 +27,7 @@
*/
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -124,11 +125,7 @@ static void am35x_musb_disable(struct musb *musb)
musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
#define portstate(stmt) stmt
-#else
-#define portstate(stmt)
-#endif
static void am35x_musb_set_vbus(struct musb *musb, int is_on)
{
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index ae8c396..5e7cfba 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/prefetch.h>
#include <asm/cacheflush.h>
diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h
index bd9352a..c84dae5 100644
--- a/drivers/usb/musb/blackfin.h
+++ b/drivers/usb/musb/blackfin.h
@@ -47,7 +47,7 @@
* So, need to either use silicon v0.2+ or disable DMA mode in MUSB.
*/
#if ANOMALY_05000380 && defined(CONFIG_BF52x) && \
- defined(CONFIG_USB_MUSB_HDRC) && !defined(CONFIG_MUSB_PIO_ONLY)
+ !defined(CONFIG_MUSB_PIO_ONLY)
# error "Please use PIO mode in MUSB driver on bf52x chip v0.0 and v0.1"
#endif
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 318fb4e..64d7b38 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1313,6 +1313,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(cppi_interrupt);
/* Instantiate a software object representing a DMA controller. */
struct dma_controller *__init
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 662ed34..2613bfd 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -27,6 +27,7 @@
*/
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -172,11 +173,7 @@ static void da8xx_musb_disable(struct musb *musb)
musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-#define portstate(stmt) stmt
-#else
-#define portstate(stmt)
-#endif
+#define portstate(stmt) stmt
static void da8xx_musb_set_vbus(struct musb *musb, int is_on)
{
@@ -397,21 +394,15 @@ static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode)
cfgchip2 &= ~CFGCHIP2_OTGMODE;
switch (musb_mode) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
case MUSB_HOST: /* Force VBUS valid, ID = 0 */
cfgchip2 |= CFGCHIP2_FORCE_HOST;
break;
-#endif
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
cfgchip2 |= CFGCHIP2_FORCE_DEVICE;
break;
-#endif
-#ifdef CONFIG_USB_MUSB_OTG
case MUSB_OTG: /* Don't override the VBUS/ID comparators */
cfgchip2 |= CFGCHIP2_NO_OVERRIDE;
break;
-#endif
default:
dev_dbg(musb->controller, "Trying to set unsupported mode %u\n", musb_mode);
}
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 2a2adf6..7c569f5 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -33,9 +33,6 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <mach/gpio.h>
#include <mach/cputype.h>
#include <asm/mach-types.h>
@@ -143,12 +140,7 @@ static void davinci_musb_disable(struct musb *musb)
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
#define portstate(stmt) stmt
-#else
-#define portstate(stmt)
-#endif
-
/*
* VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM,
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index a0232a7..6f7d84e 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -328,8 +328,6 @@ void musb_load_testpacket(struct musb *musb)
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_USB_MUSB_OTG
-
/*
* Handles OTG hnp timeouts, such as b_ase0_brst
*/
@@ -401,8 +399,6 @@ void musb_hnp_stop(struct musb *musb)
musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16);
}
-#endif
-
/*
* Interrupt Service Routine to record USB "global" interrupts.
* Since these do not happen often and signify things of
@@ -432,7 +428,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
if (devctl & MUSB_DEVCTL_HM) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
void __iomem *mbase = musb->mregs;
switch (musb->xceiv->state) {
@@ -472,17 +467,13 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
"host",
otg_state_string(musb->xceiv->state));
}
-#endif
} else {
switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
case OTG_STATE_A_SUSPEND:
/* possibly DISCONNECT is upcoming */
musb->xceiv->state = OTG_STATE_A_HOST;
usb_hcd_resume_root_hub(musb_to_hcd(musb));
break;
-#endif
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
case OTG_STATE_B_WAIT_ACON:
case OTG_STATE_B_PERIPHERAL:
/* disconnect while suspended? we may
@@ -500,7 +491,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_B_IDLE:
musb->int_usb &= ~MUSB_INTR_SUSPEND;
break;
-#endif
default:
WARNING("bogus %s RESUME (%s)\n",
"peripheral",
@@ -509,7 +499,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* see manual for the order of the tests */
if (int_usb & MUSB_INTR_SESSREQ) {
void __iomem *mbase = musb->mregs;
@@ -609,14 +598,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
handled = IRQ_HANDLED;
}
-#endif
if (int_usb & MUSB_INTR_SUSPEND) {
dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n",
otg_state_string(musb->xceiv->state), devctl, power);
handled = IRQ_HANDLED;
switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_MUSB_OTG
case OTG_STATE_A_PERIPHERAL:
/* We also come here if the cable is removed, since
* this silicon doesn't report ID-no-longer-grounded.
@@ -633,7 +620,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
? : OTG_TIME_A_WAIT_BCON));
break;
-#endif
case OTG_STATE_B_IDLE:
if (!musb->is_active)
break;
@@ -642,13 +628,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
musb->is_active = is_otg_enabled(musb)
&& musb->xceiv->gadget->b_hnp_enable;
if (musb->is_active) {
-#ifdef CONFIG_USB_MUSB_OTG
musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies(
OTG_TIME_B_ASE0_BRST));
-#endif
}
break;
case OTG_STATE_A_WAIT_BCON:
@@ -672,7 +656,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (int_usb & MUSB_INTR_CONNECT) {
struct usb_hcd *hcd = musb_to_hcd(musb);
@@ -682,7 +665,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
musb->ep0_stage = MUSB_EP0_START;
-#ifdef CONFIG_USB_MUSB_OTG
/* flush endpoints when transitioning from Device Mode */
if (is_peripheral_active(musb)) {
/* REVISIT HNP; just force disconnect */
@@ -690,7 +672,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
-#endif
musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
|USB_PORT_STAT_HIGH_SPEED
|USB_PORT_STAT_ENABLE
@@ -739,7 +720,6 @@ b_host:
dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
otg_state_string(musb->xceiv->state), devctl);
}
-#endif /* CONFIG_USB_MUSB_HDRC_HCD */
if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
@@ -748,7 +728,6 @@ b_host:
handled = IRQ_HANDLED;
switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
case OTG_STATE_A_HOST:
case OTG_STATE_A_SUSPEND:
usb_hcd_resume_root_hub(musb_to_hcd(musb));
@@ -757,8 +736,6 @@ b_host:
musb_platform_try_idle(musb, jiffies
+ msecs_to_jiffies(musb->a_wait_bcon));
break;
-#endif /* HOST */
-#ifdef CONFIG_USB_MUSB_OTG
case OTG_STATE_B_HOST:
/* REVISIT this behaves for "real disconnect"
* cases; make sure the other transitions from
@@ -777,13 +754,10 @@ b_host:
/* FALLTHROUGH */
case OTG_STATE_B_WAIT_ACON:
/* FALLTHROUGH */
-#endif /* OTG */
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_IDLE:
musb_g_disconnect(musb);
break;
-#endif /* GADGET */
default:
WARNING("unhandled DISCONNECT transition (%s)\n",
otg_state_string(musb->xceiv->state));
@@ -814,7 +788,6 @@ b_host:
dev_dbg(musb->controller, "BUS RESET as %s\n",
otg_state_string(musb->xceiv->state));
switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_OTG
case OTG_STATE_A_SUSPEND:
/* We need to ignore disconnect on suspend
* otherwise tusb 2.0 won't reconnect after a
@@ -842,7 +815,6 @@ b_host:
musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb_g_reset(musb);
break;
-#endif
case OTG_STATE_B_IDLE:
musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
/* FALLTHROUGH */
@@ -927,7 +899,6 @@ void musb_start(struct musb *musb)
/* put into basic highspeed mode and start session */
musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
- | MUSB_POWER_SOFTCONN
| MUSB_POWER_HSENAB
/* ENSUSPEND wedges tusb */
/* | MUSB_POWER_ENSUSPEND */
@@ -1038,10 +1009,15 @@ static void musb_shutdown(struct platform_device *pdev)
* We don't currently use dynamic fifo setup capability to do anything
* more than selecting one of a bunch of predefined configurations.
*/
-#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
- || defined(CONFIG_USB_MUSB_AM35X)
+#if defined(CONFIG_USB_MUSB_TUSB6010) \
+ || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) \
+ || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
+ || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \
+ || defined(CONFIG_USB_MUSB_AM35X) \
+ || defined(CONFIG_USB_MUSB_AM35X_MODULE)
static ushort __initdata fifo_mode = 4;
-#elif defined(CONFIG_USB_MUSB_UX500)
+#elif defined(CONFIG_USB_MUSB_UX500) \
+ || defined(CONFIG_USB_MUSB_UX500_MODULE)
static ushort __initdata fifo_mode = 5;
#else
static ushort __initdata fifo_mode = 2;
@@ -1191,14 +1167,12 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
/* configure the FIFO */
musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* EP0 reserved endpoint for control, bidirectional;
* EP1 reserved for bulk, two unidirection halves.
*/
if (hw_ep->epnum == 1)
musb->bulk_ep = hw_ep;
/* REVISIT error check: be sure ep0 can both rx and tx ... */
-#endif
switch (cfg->style) {
case FIFO_TX:
musb_write_txfifosz(mbase, c_size);
@@ -1317,12 +1291,10 @@ done:
n + 1, musb->config->num_eps * 2 - 1,
offset, (1 << (musb->config->ram_bits + 2)));
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (!musb->bulk_ep) {
pr_debug("%s: missing bulk\n", musb_driver_name);
return -EINVAL;
}
-#endif
return 0;
}
@@ -1353,7 +1325,6 @@ static int __init ep_config_from_hw(struct musb *musb)
/* FIXME set up hw_ep->{rx,tx}_double_buffered */
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* pick an RX/TX endpoint for bulk */
if (hw_ep->max_packet_sz_tx < 512
|| hw_ep->max_packet_sz_rx < 512)
@@ -1365,15 +1336,12 @@ static int __init ep_config_from_hw(struct musb *musb)
if (musb->bulk_ep)
continue;
musb->bulk_ep = hw_ep;
-#endif
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (!musb->bulk_ep) {
pr_debug("%s: missing bulk\n", musb_driver_name);
return -EINVAL;
}
-#endif
return 0;
}
@@ -1429,13 +1397,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
} else {
musb->is_multipoint = 0;
type = "";
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
#ifndef CONFIG_USB_OTG_BLACKLIST_HUB
printk(KERN_ERR
"%s: kernel must blacklist external hubs\n",
musb_driver_name);
#endif
-#endif
}
/* log release info */
@@ -1479,11 +1445,9 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
#endif
hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
hw_ep->target_regs = musb_read_target_reg_base(i, mbase);
hw_ep->rx_reinit = 1;
hw_ep->tx_reinit = 1;
-#endif
if (hw_ep->max_packet_sz_tx) {
dev_dbg(musb->controller,
@@ -1513,8 +1477,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
- defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \
- defined(CONFIG_ARCH_U5500)
+ defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
static irqreturn_t generic_interrupt(int irq, void *__hci)
{
@@ -1561,24 +1524,30 @@ irqreturn_t musb_interrupt(struct musb *musb)
(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
musb->int_usb, musb->int_tx, musb->int_rx);
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
- if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
- if (!musb->gadget_driver) {
- dev_dbg(musb->controller, "No gadget driver loaded\n");
- return IRQ_HANDLED;
- }
-#endif
-
- /* the core can interrupt us for multiple reasons; docs have
- * a generic interrupt flowchart to follow
+ /**
+ * According to Mentor Graphics' documentation, flowchart on page 98,
+ * IRQ should be handled as follows:
+ *
+ * . Resume IRQ
+ * . Session Request IRQ
+ * . VBUS Error IRQ
+ * . Suspend IRQ
+ * . Connect IRQ
+ * . Disconnect IRQ
+ * . Reset/Babble IRQ
+ * . SOF IRQ (we're not using this one)
+ * . Endpoint 0 IRQ
+ * . TX Endpoints
+ * . RX Endpoints
+ *
+ * We will be following that flowchart in order to avoid any problems
+ * that might arise with internal Finite State Machine.
*/
+
if (musb->int_usb)
retval |= musb_stage0_irq(musb, musb->int_usb,
devctl, power);
- /* "stage 1" is handling endpoint irqs */
-
- /* handle endpoint 0 first */
if (musb->int_tx & 1) {
if (devctl & MUSB_DEVCTL_HM)
retval |= musb_h_ep0_irq(musb);
@@ -1586,43 +1555,37 @@ irqreturn_t musb_interrupt(struct musb *musb)
retval |= musb_g_ep0_irq(musb);
}
- /* RX on endpoints 1-15 */
- reg = musb->int_rx >> 1;
+ reg = musb->int_tx >> 1;
ep_num = 1;
while (reg) {
if (reg & 1) {
- /* musb_ep_select(musb->mregs, ep_num); */
- /* REVISIT just retval = ep->rx_irq(...) */
retval = IRQ_HANDLED;
if (devctl & MUSB_DEVCTL_HM) {
if (is_host_capable())
- musb_host_rx(musb, ep_num);
+ musb_host_tx(musb, ep_num);
} else {
if (is_peripheral_capable())
- musb_g_rx(musb, ep_num);
+ musb_g_tx(musb, ep_num);
}
}
-
reg >>= 1;
ep_num++;
}
- /* TX on endpoints 1-15 */
- reg = musb->int_tx >> 1;
+ reg = musb->int_rx >> 1;
ep_num = 1;
while (reg) {
if (reg & 1) {
- /* musb_ep_select(musb->mregs, ep_num); */
- /* REVISIT just retval |= ep->tx_irq(...) */
retval = IRQ_HANDLED;
if (devctl & MUSB_DEVCTL_HM) {
if (is_host_capable())
- musb_host_tx(musb, ep_num);
+ musb_host_rx(musb, ep_num);
} else {
if (is_peripheral_capable())
- musb_g_tx(musb, ep_num);
+ musb_g_rx(musb, ep_num);
}
}
+
reg >>= 1;
ep_num++;
}
@@ -1767,8 +1730,6 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-
/* Gadget drivers can't know that a host is connected so they might want
* to start SRP, but users can. This allows userspace to trigger SRP.
*/
@@ -1792,14 +1753,10 @@ musb_srp_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store);
-#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
-
static struct attribute *musb_attributes[] = {
&dev_attr_mode.attr,
&dev_attr_vbus.attr,
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
&dev_attr_srp.attr,
-#endif
NULL
};
@@ -1832,7 +1789,6 @@ allocate_instance(struct device *dev,
struct musb *musb;
struct musb_hw_ep *ep;
int epnum;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
struct usb_hcd *hcd;
hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev));
@@ -1850,12 +1806,6 @@ allocate_instance(struct device *dev,
musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
-#else
- musb = kzalloc(sizeof *musb, GFP_KERNEL);
- if (!musb)
- return NULL;
-
-#endif
dev_set_drvdata(dev, musb);
musb->mregs = mbase;
musb->ctrl_base = mbase;
@@ -1885,9 +1835,7 @@ static void musb_free(struct musb *musb)
sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
#endif
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
musb_gadget_cleanup(musb);
-#endif
if (musb->nIrq >= 0) {
if (musb->irq_wake)
@@ -1901,11 +1849,7 @@ static void musb_free(struct musb *musb)
dma_controller_destroy(c);
}
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
- usb_put_hcd(musb_to_hcd(musb));
-#else
kfree(musb);
-#endif
}
/*
@@ -1955,7 +1899,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
* - initializes musb->xceiv, usually by otg_get_transceiver()
* - stops powering VBUS
*
- * There are various transciever configurations. Blackfin,
+ * There are various transceiver configurations. Blackfin,
* DaVinci, TUSB60x0, and others integrate them. OMAP3 uses
* external/discrete ones in various flavors (twl4030 family,
* isp1504, non-OTG, etc) mostly hooking up through ULPI.
@@ -2000,9 +1944,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
if (status < 0)
goto fail3;
-#ifdef CONFIG_USB_MUSB_OTG
setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
-#endif
/* Init IRQ workqueue before request_irq */
INIT_WORK(&musb->irq_work, musb_irq_work);
@@ -2212,7 +2154,16 @@ static void musb_save_context(struct musb *musb)
musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
for (i = 0; i < musb->config->num_eps; ++i) {
- epio = musb->endpoints[i].regs;
+ struct musb_hw_ep *hw_ep;
+
+ hw_ep = &musb->endpoints[i];
+ if (!hw_ep)
+ continue;
+
+ epio = hw_ep->regs;
+ if (!epio)
+ continue;
+
musb->context.index_regs[i].txmaxp =
musb_readw(epio, MUSB_TXMAXP);
musb->context.index_regs[i].txcsr =
@@ -2278,7 +2229,16 @@ static void musb_restore_context(struct musb *musb)
musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
for (i = 0; i < musb->config->num_eps; ++i) {
- epio = musb->endpoints[i].regs;
+ struct musb_hw_ep *hw_ep;
+
+ hw_ep = &musb->endpoints[i];
+ if (!hw_ep)
+ continue;
+
+ epio = hw_ep->regs;
+ if (!epio)
+ continue;
+
musb_writew(epio, MUSB_TXMAXP,
musb->context.index_regs[i].txmaxp);
musb_writew(epio, MUSB_TXCSR,
@@ -2332,9 +2292,8 @@ static void musb_restore_context(struct musb *musb)
static int musb_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
+ struct musb *musb = dev_to_musb(dev);
unsigned long flags;
- struct musb *musb = dev_to_musb(&pdev->dev);
spin_lock_irqsave(&musb->lock, flags);
@@ -2348,19 +2307,12 @@ static int musb_suspend(struct device *dev)
*/
}
- musb_save_context(musb);
-
spin_unlock_irqrestore(&musb->lock, flags);
return 0;
}
static int musb_resume_noirq(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct musb *musb = dev_to_musb(&pdev->dev);
-
- musb_restore_context(musb);
-
/* for static cmos like DaVinci, register values were preserved
* unless for some reason the whole soc powered down or the USB
* module got reset through the PSC (vs just being disabled).
@@ -2425,34 +2377,10 @@ static struct platform_driver musb_driver = {
static int __init musb_init(void)
{
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (usb_disabled())
return 0;
-#endif
- pr_info("%s: version " MUSB_VERSION ", "
-#ifdef CONFIG_MUSB_PIO_ONLY
- "pio"
-#elif defined(CONFIG_USB_TI_CPPI_DMA)
- "cppi-dma"
-#elif defined(CONFIG_USB_INVENTRA_DMA)
- "musb-dma"
-#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
- "tusb-omap-dma"
-#elif defined(CONFIG_USB_UX500_DMA)
- "ux500-dma"
-#else
- "?dma?"
-#endif
- ", "
-#ifdef CONFIG_USB_MUSB_OTG
- "otg (peripheral+host)"
-#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
- "peripheral"
-#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
- "host"
-#endif
- ,
+ pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
musb_driver_name);
return platform_driver_probe(&musb_driver, musb_probe);
}
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 0e053b5..b3c065a 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -72,10 +72,6 @@ struct musb_ep;
#include <linux/usb/hcd.h>
#include "musb_host.h"
-
-
-#ifdef CONFIG_USB_MUSB_OTG
-
#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL)
#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG)
@@ -86,24 +82,6 @@ struct musb_ep;
#define is_peripheral_active(m) (!(m)->is_host)
#define is_host_active(m) ((m)->is_host)
-#else
-#define is_peripheral_enabled(musb) is_peripheral_capable()
-#define is_host_enabled(musb) is_host_capable()
-#define is_otg_enabled(musb) 0
-
-#define is_peripheral_active(musb) is_peripheral_capable()
-#define is_host_active(musb) is_host_capable()
-#endif
-
-#if defined(CONFIG_USB_MUSB_OTG) || defined(CONFIG_USB_MUSB_PERIPHERAL)
-/* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't always
- * override that choice selection (often USB_GADGET_DUMMY_HCD).
- */
-#ifndef CONFIG_USB_GADGET_MUSB_HDRC
-#error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC
-#endif
-#endif /* need MUSB gadget selection */
-
#ifndef CONFIG_HAVE_CLK
/* Dummy stub for clk framework */
#define clk_get(dev, id) NULL
@@ -119,8 +97,6 @@ struct musb_ep;
/****************************** PERIPHERAL ROLE *****************************/
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-
#define is_peripheral_capable() (1)
extern irqreturn_t musb_g_ep0_irq(struct musb *);
@@ -132,40 +108,14 @@ extern void musb_g_resume(struct musb *);
extern void musb_g_wakeup(struct musb *);
extern void musb_g_disconnect(struct musb *);
-#else
-
-#define is_peripheral_capable() (0)
-
-static inline irqreturn_t musb_g_ep0_irq(struct musb *m) { return IRQ_NONE; }
-static inline void musb_g_reset(struct musb *m) {}
-static inline void musb_g_suspend(struct musb *m) {}
-static inline void musb_g_resume(struct musb *m) {}
-static inline void musb_g_wakeup(struct musb *m) {}
-static inline void musb_g_disconnect(struct musb *m) {}
-
-#endif
-
/****************************** HOST ROLE ***********************************/
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-
#define is_host_capable() (1)
extern irqreturn_t musb_h_ep0_irq(struct musb *);
extern void musb_host_tx(struct musb *, u8);
extern void musb_host_rx(struct musb *, u8);
-#else
-
-#define is_host_capable() (0)
-
-static inline irqreturn_t musb_h_ep0_irq(struct musb *m) { return IRQ_NONE; }
-static inline void musb_host_tx(struct musb *m, u8 e) {}
-static inline void musb_host_rx(struct musb *m, u8 e) {}
-
-#endif
-
-
/****************************** CONSTANTS ********************************/
#ifndef MUSB_C_NUM_EPS
@@ -222,7 +172,8 @@ enum musb_g_ep0_state {
#endif
/* TUSB mapping: "flat" plus ep0 special cases */
-#if defined(CONFIG_USB_MUSB_TUSB6010)
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
#define musb_ep_select(_mbase, _epnum) \
musb_writeb((_mbase), MUSB_INDEX, (_epnum))
#define MUSB_EP_OFFSET MUSB_TUSB_OFFSET
@@ -261,7 +212,7 @@ enum musb_g_ep0_state {
* @try_ilde: tries to idle the IP
* @vbus_status: returns vbus status if possible
* @set_vbus: forces vbus status
- * @channel_program: pre check for standard dma channel_program func
+ * @adjust_channel_params: pre check for standard dma channel_program func
*/
struct musb_platform_ops {
int (*init)(struct musb *musb);
@@ -291,7 +242,8 @@ struct musb_hw_ep {
void __iomem *fifo;
void __iomem *regs;
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
void __iomem *conf;
#endif
@@ -308,14 +260,14 @@ struct musb_hw_ep {
struct dma_channel *tx_channel;
struct dma_channel *rx_channel;
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
/* TUSB has "asynchronous" and "synchronous" dma modes */
dma_addr_t fifo_async;
dma_addr_t fifo_sync;
void __iomem *fifo_sync_va;
#endif
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
void __iomem *target_regs;
/* currently scheduled peripheral endpoint */
@@ -324,31 +276,20 @@ struct musb_hw_ep {
u8 rx_reinit;
u8 tx_reinit;
-#endif
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
/* peripheral side */
struct musb_ep ep_in; /* TX */
struct musb_ep ep_out; /* RX */
-#endif
};
static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
{
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
return next_request(&hw_ep->ep_in);
-#else
- return NULL;
-#endif
}
static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
{
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
return next_request(&hw_ep->ep_out);
-#else
- return NULL;
-#endif
}
struct musb_csr_regs {
@@ -393,7 +334,6 @@ struct musb {
u32 port1_status;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
unsigned long rh_timer;
enum musb_h_ep0_state ep0_stage;
@@ -411,7 +351,6 @@ struct musb {
struct list_head out_bulk; /* of musb_qh */
struct timer_list otg_timer;
-#endif
struct notifier_block nb;
struct dma_controller *dma_controller;
@@ -420,7 +359,8 @@ struct musb {
void __iomem *ctrl_base;
void __iomem *mregs;
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
dma_addr_t async;
dma_addr_t sync;
void __iomem *sync_va;
@@ -472,7 +412,6 @@ struct musb {
#define can_bulk_combine(musb,type) \
(((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
/* is_suspended means USB B_PERIPHERAL suspend */
unsigned is_suspended:1;
@@ -496,7 +435,6 @@ struct musb {
enum musb_g_ep0_state ep0_state;
struct usb_gadget g; /* the gadget */
struct usb_gadget_driver *gadget_driver; /* its driver */
-#endif
/*
* FIXME: Remove this flag.
@@ -518,12 +456,10 @@ struct musb {
#endif
};
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
static inline struct musb *gadget_to_musb(struct usb_gadget *g)
{
return container_of(g, struct musb, g);
}
-#endif
#ifdef CONFIG_BLACKFIN
static inline int musb_read_fifosize(struct musb *musb,
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
index b0176e4..61f4ee4 100644
--- a/drivers/usb/musb/musb_debugfs.c
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -41,12 +41,6 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#ifdef CONFIG_ARM
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/mach-types.h>
-#endif
-
#include <asm/uaccess.h>
#include "musb_core.h"
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 99ceaef..9c8845a 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -643,6 +643,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
u16 len;
u16 csr = musb_readw(epio, MUSB_RXCSR);
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
+ u8 use_mode_1;
if (hw_ep->is_shared_fifo)
musb_ep = &hw_ep->ep_in;
@@ -692,6 +693,18 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (csr & MUSB_RXCSR_RXPKTRDY) {
len = musb_readw(epio, MUSB_RXCOUNT);
+
+ /*
+ * Enable Mode 1 on RX transfers only when short_not_ok flag
+ * is set. Currently short_not_ok flag is set only from
+ * file_storage and f_mass_storage drivers
+ */
+
+ if (request->short_not_ok && len == musb_ep->packet_sz)
+ use_mode_1 = 1;
+ else
+ use_mode_1 = 0;
+
if (request->actual < request->length) {
#ifdef CONFIG_USB_INVENTRA_DMA
if (is_buffer_mapped(req)) {
@@ -713,7 +726,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
* most these gadgets, end of is signified either by a short packet,
* or filling the last byte of the buffer. (Sending extra data in
* that last pckate should trigger an overflow fault.) But in mode 1,
- * we don't get DMA completion interrrupt for short packets.
+ * we don't get DMA completion interrupt for short packets.
*
* Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
* to get endpoint interrupt on every DMA req, but that didn't seem
@@ -723,37 +736,41 @@ static void rxstate(struct musb *musb, struct musb_request *req)
* then becomes usable as a runtime "use mode 1" hint...
*/
- csr |= MUSB_RXCSR_DMAENAB;
-#ifdef USE_MODE1
- csr |= MUSB_RXCSR_AUTOCLEAR;
- /* csr |= MUSB_RXCSR_DMAMODE; */
-
- /* this special sequence (enabling and then
- * disabling MUSB_RXCSR_DMAMODE) is required
- * to get DMAReq to activate
- */
- musb_writew(epio, MUSB_RXCSR,
- csr | MUSB_RXCSR_DMAMODE);
-#else
- if (!musb_ep->hb_mult &&
- musb_ep->hw_ep->rx_double_buffered)
+ /* Experimental: Mode1 works with mass storage use cases */
+ if (use_mode_1) {
csr |= MUSB_RXCSR_AUTOCLEAR;
-#endif
- musb_writew(epio, MUSB_RXCSR, csr);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ csr |= MUSB_RXCSR_DMAENAB;
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ /*
+ * this special sequence (enabling and then
+ * disabling MUSB_RXCSR_DMAMODE) is required
+ * to get DMAReq to activate
+ */
+ musb_writew(epio, MUSB_RXCSR,
+ csr | MUSB_RXCSR_DMAMODE);
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ } else {
+ if (!musb_ep->hb_mult &&
+ musb_ep->hw_ep->rx_double_buffered)
+ csr |= MUSB_RXCSR_AUTOCLEAR;
+ csr |= MUSB_RXCSR_DMAENAB;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
if (request->actual < request->length) {
int transfer_size = 0;
-#ifdef USE_MODE1
- transfer_size = min(request->length - request->actual,
- channel->max_len);
-#else
- transfer_size = min(request->length - request->actual,
- (unsigned)len);
-#endif
- if (transfer_size <= musb_ep->packet_sz)
- musb_ep->dma->desired_mode = 0;
- else
+ if (use_mode_1) {
+ transfer_size = min(request->length - request->actual,
+ channel->max_len);
musb_ep->dma->desired_mode = 1;
+ } else {
+ transfer_size = min(request->length - request->actual,
+ (unsigned)len);
+ musb_ep->dma->desired_mode = 0;
+ }
use_dma = c->channel_program(
channel,
@@ -1038,7 +1055,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
goto fail;
/* REVISIT this rules out high bandwidth periodic transfers */
- tmp = le16_to_cpu(desc->wMaxPacketSize);
+ tmp = usb_endpoint_maxp(desc);
if (tmp & ~0x07ff) {
int ok;
@@ -1217,6 +1234,7 @@ static int musb_gadget_disable(struct usb_ep *ep)
}
musb_ep->desc = NULL;
+ musb_ep->end_point.desc = NULL;
/* abort all pending DMA and requests */
nuke(musb_ep, -ESHUTDOWN);
@@ -1681,8 +1699,8 @@ static void musb_pullup(struct musb *musb, int is_on)
/* FIXME if on, HdrcStart; if off, HdrcStop */
- dev_dbg(musb->controller, "gadget %s D+ pullup %s\n",
- musb->gadget_driver->function, is_on ? "on" : "off");
+ dev_dbg(musb->controller, "gadget D+ pullup %s\n",
+ is_on ? "on" : "off");
musb_writeb(musb->mregs, MUSB_POWER, power);
}
@@ -1733,6 +1751,11 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
+static int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver);
+static int musb_gadget_stop(struct usb_gadget *g,
+ struct usb_gadget_driver *driver);
+
static const struct usb_gadget_ops musb_gadget_operations = {
.get_frame = musb_gadget_get_frame,
.wakeup = musb_gadget_wakeup,
@@ -1740,6 +1763,8 @@ static const struct usb_gadget_ops musb_gadget_operations = {
/* .vbus_session = musb_gadget_vbus_session, */
.vbus_draw = musb_gadget_vbus_draw,
.pullup = musb_gadget_pullup,
+ .udc_start = musb_gadget_start,
+ .udc_stop = musb_gadget_stop,
};
/* ----------------------------------------------------------------------- */
@@ -1750,7 +1775,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
* about there being only one external upstream port. It assumes
* all peripheral ports are external...
*/
-static struct musb *the_gadget;
static void musb_gadget_release(struct device *dev)
{
@@ -1837,9 +1861,6 @@ int __init musb_gadget_setup(struct musb *musb)
* musb peripherals at the same time, only the bus lock
* is probably held.
*/
- if (the_gadget)
- return -EBUSY;
- the_gadget = musb;
musb->g.ops = &musb_gadget_operations;
musb->g.is_dualspeed = 1;
@@ -1863,18 +1884,24 @@ int __init musb_gadget_setup(struct musb *musb)
status = device_register(&musb->g.dev);
if (status != 0) {
put_device(&musb->g.dev);
- the_gadget = NULL;
+ return status;
}
+ status = usb_add_gadget_udc(musb->controller, &musb->g);
+ if (status)
+ goto err;
+
+ return 0;
+err:
+ musb->g.dev.parent = NULL;
+ device_unregister(&musb->g.dev);
return status;
}
void musb_gadget_cleanup(struct musb *musb)
{
- if (musb != the_gadget)
- return;
-
- device_unregister(&musb->g.dev);
- the_gadget = NULL;
+ usb_del_gadget_udc(&musb->g);
+ if (musb->g.dev.parent)
+ device_unregister(&musb->g.dev);
}
/*
@@ -1886,59 +1913,30 @@ void musb_gadget_cleanup(struct musb *musb)
* -ENOMEM no memory to perform the operation
*
* @param driver the gadget driver
- * @param bind the driver's bind function
* @return <0 if error, 0 if everything is fine
*/
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
{
- struct musb *musb = the_gadget;
+ struct musb *musb = gadget_to_musb(g);
unsigned long flags;
int retval = -EINVAL;
- if (!driver
- || driver->speed != USB_SPEED_HIGH
- || !bind || !driver->setup)
- goto err0;
-
- /* driver must be initialized to support peripheral mode */
- if (!musb) {
- dev_dbg(musb->controller, "no dev??\n");
- retval = -ENODEV;
+ if (driver->speed < USB_SPEED_HIGH)
goto err0;
- }
pm_runtime_get_sync(musb->controller);
dev_dbg(musb->controller, "registering driver %s\n", driver->function);
- if (musb->gadget_driver) {
- dev_dbg(musb->controller, "%s is already bound to %s\n",
- musb_driver_name,
- musb->gadget_driver->driver.name);
- retval = -EBUSY;
- goto err0;
- }
-
- spin_lock_irqsave(&musb->lock, flags);
+ musb->softconnect = 0;
musb->gadget_driver = driver;
- musb->g.dev.driver = &driver->driver;
- driver->driver.bus = NULL;
- musb->softconnect = 1;
- spin_unlock_irqrestore(&musb->lock, flags);
-
- retval = bind(&musb->g);
- if (retval) {
- dev_dbg(musb->controller, "bind to driver %s failed --> %d\n",
- driver->driver.name, retval);
- goto err1;
- }
spin_lock_irqsave(&musb->lock, flags);
+ musb->is_active = 1;
otg_set_peripheral(musb->xceiv, &musb->g);
musb->xceiv->state = OTG_STATE_B_IDLE;
- musb->is_active = 1;
/*
* FIXME this ignores the softconnect flag. Drivers are
@@ -1950,8 +1948,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
if (!is_otg_enabled(musb))
musb_start(musb);
- otg_set_peripheral(musb->xceiv, &musb->g);
-
spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) {
@@ -1983,15 +1979,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
err2:
if (!is_otg_enabled(musb))
musb_stop(musb);
-
-err1:
- musb->gadget_driver = NULL;
- musb->g.dev.driver = NULL;
-
err0:
return retval;
}
-EXPORT_SYMBOL(usb_gadget_probe_driver);
static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
{
@@ -2028,10 +2018,6 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
nuke(&hw_ep->ep_out, -ESHUTDOWN);
}
}
-
- spin_unlock(&musb->lock);
- driver->disconnect(&musb->g);
- spin_lock(&musb->lock);
}
}
@@ -2041,17 +2027,12 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
*
* @param driver the gadget driver to unregister
*/
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int musb_gadget_stop(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
{
- struct musb *musb = the_gadget;
+ struct musb *musb = gadget_to_musb(g);
unsigned long flags;
- if (!driver || !driver->unbind || !musb)
- return -EINVAL;
-
- if (!musb->gadget_driver)
- return -EINVAL;
-
if (musb->xceiv->last_event == USB_EVENT_NONE)
pm_runtime_get_sync(musb->controller);
@@ -2062,9 +2043,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
spin_lock_irqsave(&musb->lock, flags);
-#ifdef CONFIG_USB_MUSB_OTG
musb_hnp_stop(musb);
-#endif
(void) musb_gadget_vbus_draw(&musb->g, 0);
@@ -2074,13 +2053,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
- spin_unlock_irqrestore(&musb->lock, flags);
- driver->unbind(&musb->g);
- spin_lock_irqsave(&musb->lock, flags);
-
- musb->gadget_driver = NULL;
- musb->g.dev.driver = NULL;
-
musb->is_active = 0;
musb_platform_try_idle(musb, 0);
spin_unlock_irqrestore(&musb->lock, flags);
@@ -2100,8 +2072,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
/* ----------------------------------------------------------------------- */
@@ -2187,7 +2157,6 @@ void musb_g_disconnect(struct musb *musb)
switch (musb->xceiv->state) {
default:
-#ifdef CONFIG_USB_MUSB_OTG
dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
otg_state_string(musb->xceiv->state));
musb->xceiv->state = OTG_STATE_A_IDLE;
@@ -2199,7 +2168,6 @@ void musb_g_disconnect(struct musb *musb)
break;
case OTG_STATE_B_WAIT_ACON:
case OTG_STATE_B_HOST:
-#endif
case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_IDLE:
musb->xceiv->state = OTG_STATE_B_IDLE;
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index b2faff2..6a0d046 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -88,7 +88,6 @@ static int service_tx_status_request(
case USB_RECIP_DEVICE:
result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED;
result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
-#ifdef CONFIG_USB_MUSB_OTG
if (musb->g.is_otg) {
result[0] |= musb->g.b_hnp_enable
<< USB_DEVICE_B_HNP_ENABLE;
@@ -97,7 +96,6 @@ static int service_tx_status_request(
result[0] |= musb->g.a_hnp_support
<< USB_DEVICE_A_HNP_SUPPORT;
}
-#endif
break;
case USB_RECIP_INTERFACE:
@@ -392,7 +390,6 @@ __acquires(musb->lock)
if (handled > 0)
musb->test_mode = true;
break;
-#ifdef CONFIG_USB_MUSB_OTG
case USB_DEVICE_B_HNP_ENABLE:
if (!musb->g.is_otg)
goto stall;
@@ -409,7 +406,6 @@ __acquires(musb->lock)
goto stall;
musb->g.a_alt_hnp_support = 1;
break;
-#endif
case USB_DEVICE_DEBUG_MODE:
handled = 0;
break;
@@ -683,6 +679,14 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
musb_readb(mbase, MUSB_FADDR),
decode_ep0stage(musb->ep0_state));
+ if (csr & MUSB_CSR0_P_DATAEND) {
+ /*
+ * If DATAEND is set we should not call the callback,
+ * hence the status stage is not complete.
+ */
+ return IRQ_HANDLED;
+ }
+
/* I sent a stall.. need to acknowledge it now.. */
if (csr & MUSB_CSR0_P_SENTSTALL) {
musb_writew(regs, MUSB_CSR0,
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 8b2473f..79cb0af 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -774,6 +774,10 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
if (musb->double_buffer_not_ok)
musb_writew(epio, MUSB_TXMAXP,
hw_ep->max_packet_sz_tx);
+ else if (can_bulk_split(musb, qh->type))
+ musb_writew(epio, MUSB_TXMAXP, packet_sz
+ | ((hw_ep->max_packet_sz_tx /
+ packet_sz) - 1) << 11);
else
musb_writew(epio, MUSB_TXMAXP,
qh->maxpacket |
@@ -1932,7 +1936,7 @@ static int musb_urb_enqueue(
INIT_LIST_HEAD(&qh->ring);
qh->is_ready = 1;
- qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize);
+ qh->maxpacket = usb_endpoint_maxp(epd);
qh->type = usb_endpoint_type(epd);
/* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier.
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 14b0077..622d09f 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -95,7 +95,6 @@ extern const struct hc_driver musb_hc_driver;
static inline struct urb *next_urb(struct musb_qh *qh)
{
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
struct list_head *queue;
if (!qh)
@@ -104,9 +103,6 @@ static inline struct urb *next_urb(struct musb_qh *qh)
if (list_empty(queue))
return NULL;
return list_entry(queue->next, struct urb, urb_list);
-#else
- return NULL;
-#endif
}
#endif /* _MUSB_HOST_H */
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
index 8241070..03f2655 100644
--- a/drivers/usb/musb/musb_regs.h
+++ b/drivers/usb/musb/musb_regs.h
@@ -234,7 +234,8 @@
#define MUSB_TESTMODE 0x0F /* 8 bit */
/* Get offset for a given FIFO from musb->mregs */
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
#define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20))
#else
#define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4))
@@ -295,7 +296,8 @@
#define MUSB_FLAT_OFFSET(_epnum, _offset) \
(0x100 + (0x10*(_epnum)) + (_offset))
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
/* TUSB6010 EP0 configuration register is special */
#define MUSB_TUSB_OFFSET(_epnum, _offset) \
(0x10 + _offset)
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 2d80a57..e9f80ad 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -88,14 +88,12 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
OTG_TIME_A_AIDL_BDIS));
musb_platform_try_idle(musb, 0);
break;
-#ifdef CONFIG_USB_MUSB_OTG
case OTG_STATE_B_HOST:
musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
musb->is_active = is_otg_enabled(musb)
&& musb->xceiv->host->b_hnp_enable;
musb_platform_try_idle(musb, 0);
break;
-#endif
default:
dev_dbg(musb->controller, "bogus rh suspend? %s\n",
otg_state_string(musb->xceiv->state));
@@ -118,13 +116,11 @@ static void musb_port_reset(struct musb *musb, bool do_reset)
u8 power;
void __iomem *mbase = musb->mregs;
-#ifdef CONFIG_USB_MUSB_OTG
if (musb->xceiv->state == OTG_STATE_B_IDLE) {
dev_dbg(musb->controller, "HNP: Returning from HNP; no hub reset from b_idle\n");
musb->port1_status &= ~USB_PORT_STAT_RESET;
return;
}
-#endif
if (!is_host_active(musb))
return;
@@ -191,14 +187,12 @@ void musb_root_disconnect(struct musb *musb)
switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND:
-#ifdef CONFIG_USB_MUSB_OTG
if (is_otg_enabled(musb)
&& musb->xceiv->host->b_hnp_enable) {
musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
musb->g.is_a_peripheral = 1;
break;
}
-#endif
/* FALLTHROUGH */
case OTG_STATE_A_HOST:
musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index f70c5a5..57a6085 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -408,7 +408,7 @@ dma_controller_create(struct musb *musb, void __iomem *base)
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
- if (request_irq(irq, dma_controller_irq, IRQF_DISABLED,
+ if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
dev_err(dev, "request_irq %d failed!\n", irq);
dma_controller_destroy(&controller->controller);
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 6958ab9..a8f0c09 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -51,9 +51,7 @@ static void musb_do_idle(unsigned long _musb)
{
struct musb *musb = (void *)_musb;
unsigned long flags;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
u8 power;
-#endif
u8 devctl;
spin_lock_irqsave(&musb->lock, flags);
@@ -70,7 +68,6 @@ static void musb_do_idle(unsigned long _musb)
MUSB_HST_MODE(musb);
}
break;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
case OTG_STATE_A_SUSPEND:
/* finish RESUME signaling? */
if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
@@ -87,15 +84,12 @@ static void musb_do_idle(unsigned long _musb)
musb->xceiv->state = OTG_STATE_A_HOST;
}
break;
-#endif
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
case OTG_STATE_A_HOST:
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE)
musb->xceiv->state = OTG_STATE_B_IDLE;
else
musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
-#endif
default:
break;
}
@@ -243,13 +237,11 @@ static int musb_otg_notifications(struct notifier_block *nb,
dev_dbg(musb->controller, "ID GND\n");
if (is_otg_enabled(musb)) {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
if (musb->gadget_driver) {
pm_runtime_get_sync(musb->controller);
otg_init(musb->xceiv);
omap2430_musb_set_vbus(musb, 1);
}
-#endif
} else {
pm_runtime_get_sync(musb->controller);
otg_init(musb->xceiv);
@@ -260,21 +252,16 @@ static int musb_otg_notifications(struct notifier_block *nb,
case USB_EVENT_VBUS:
dev_dbg(musb->controller, "VBUS Connect\n");
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
if (musb->gadget_driver)
pm_runtime_get_sync(musb->controller);
-#endif
otg_init(musb->xceiv);
break;
case USB_EVENT_NONE:
dev_dbg(musb->controller, "VBUS Disconnect\n");
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
- if (musb->gadget_driver)
-#endif
- {
+ if (musb->gadget_driver) {
pm_runtime_mark_last_busy(musb->controller);
pm_runtime_put_autosuspend(musb->controller);
}
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index b410357..ec14801 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/prefetch.h>
#include <linux/usb.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
@@ -269,8 +270,6 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
static struct musb *the_musb;
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-
/* This is used by gadget drivers, and OTG transceiver logic, allowing
* at most mA current to be drawn from VBUS during a Default-B session
* (that is, while VBUS exceeds 4.4V). In Default-A (including pure host
@@ -310,10 +309,6 @@ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
return 0;
}
-#else
-#define tusb_draw_power NULL
-#endif
-
/* workaround for issue 13: change clock during chip idle
* (to be fixed in rev3 silicon) ... symptoms include disconnect
* or looping suspend/resume cycles
@@ -440,19 +435,15 @@ static void musb_do_idle(unsigned long _musb)
if (is_host_active(musb) && (musb->port1_status >> 16))
goto done;
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
- if (is_peripheral_enabled(musb) && !musb->gadget_driver)
+ if (is_peripheral_enabled(musb) && !musb->gadget_driver) {
wakeups = 0;
- else {
+ } else {
wakeups = TUSB_PRCM_WHOSTDISCON
- | TUSB_PRCM_WBUS
+ | TUSB_PRCM_WBUS
| TUSB_PRCM_WVBUS;
if (is_otg_enabled(musb))
wakeups |= TUSB_PRCM_WID;
}
-#else
- wakeups = TUSB_PRCM_WHOSTDISCON | TUSB_PRCM_WBUS;
-#endif
tusb_allow_idle(musb, wakeups);
}
done:
@@ -610,30 +601,22 @@ static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode)
switch (musb_mode) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
case MUSB_HOST: /* Disable PHY ID detect, ground ID */
phy_otg_ctrl &= ~TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
dev_conf |= TUSB_DEV_CONF_ID_SEL;
dev_conf &= ~TUSB_DEV_CONF_SOFT_ID;
break;
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
case MUSB_PERIPHERAL: /* Disable PHY ID detect, keep ID pull-up on */
phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
dev_conf |= (TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID);
break;
-#endif
-
-#ifdef CONFIG_USB_MUSB_OTG
case MUSB_OTG: /* Use PHY ID detection */
phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
dev_conf &= ~(TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID);
break;
-#endif
default:
dev_dbg(musb->controller, "Trying to set mode %i\n", musb_mode);
@@ -684,7 +667,6 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
/* B-dev state machine: no vbus ~= disconnect */
if ((is_otg_enabled(musb) && !musb->xceiv->default_a)
|| !is_host_enabled(musb)) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* ? musb_root_disconnect(musb); */
musb->port1_status &=
~(USB_PORT_STAT_CONNECTION
@@ -693,7 +675,6 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
| USB_PORT_STAT_HIGH_SPEED
| USB_PORT_STAT_TEST
);
-#endif
if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
dev_dbg(musb->controller, "Forcing disconnect (no interrupt)\n");
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index c784e6c..b67b4bc 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -20,6 +20,7 @@
#include <plat/mux.h>
#include "musb_core.h"
+#include "tusb6010.h"
#define to_chdat(c) ((struct tusb_omap_dma_ch *)(c)->private_data)
@@ -89,7 +90,7 @@ static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
if (reg != 0) {
- dev_dbg(musb->controller, "ep%i dmareq0 is busy for ep%i\n",
+ dev_dbg(chdat->musb->controller, "ep%i dmareq0 is busy for ep%i\n",
chdat->epnum, reg & 0xf);
return -EAGAIN;
}
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index cecace4..ef4333f 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -65,7 +65,8 @@ static void ux500_tx_work(struct work_struct *data)
struct musb *musb = hw_ep->musb;
unsigned long flags;
- DBG(4, "DMA tx transfer done on hw_ep=%d\n", hw_ep->epnum);
+ dev_dbg(musb->controller, "DMA tx transfer done on hw_ep=%d\n",
+ hw_ep->epnum);
spin_lock_irqsave(&musb->lock, flags);
ux500_channel->channel.actual_len = ux500_channel->cur_len;
@@ -84,7 +85,8 @@ static void ux500_rx_work(struct work_struct *data)
struct musb *musb = hw_ep->musb;
unsigned long flags;
- DBG(4, "DMA rx transfer done on hw_ep=%d\n", hw_ep->epnum);
+ dev_dbg(musb->controller, "DMA rx transfer done on hw_ep=%d\n",
+ hw_ep->epnum);
spin_lock_irqsave(&musb->lock, flags);
ux500_channel->channel.actual_len = ux500_channel->cur_len;
@@ -116,9 +118,11 @@ static bool ux500_configure_channel(struct dma_channel *channel,
enum dma_slave_buswidth addr_width;
dma_addr_t usb_fifo_addr = (MUSB_FIFO_OFFSET(hw_ep->epnum) +
ux500_channel->controller->phy_base);
+ struct musb *musb = ux500_channel->controller->private_data;
- DBG(4, "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
- packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
+ dev_dbg(musb->controller,
+ "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
+ packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
ux500_channel->cur_len = len;
@@ -133,15 +137,13 @@ static bool ux500_configure_channel(struct dma_channel *channel,
DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_conf.direction = direction;
- if (direction == DMA_FROM_DEVICE) {
- slave_conf.src_addr = usb_fifo_addr;
- slave_conf.src_addr_width = addr_width;
- slave_conf.src_maxburst = 16;
- } else {
- slave_conf.dst_addr = usb_fifo_addr;
- slave_conf.dst_addr_width = addr_width;
- slave_conf.dst_maxburst = 16;
- }
+ slave_conf.src_addr = usb_fifo_addr;
+ slave_conf.src_addr_width = addr_width;
+ slave_conf.src_maxburst = 16;
+ slave_conf.dst_addr = usb_fifo_addr;
+ slave_conf.dst_addr_width = addr_width;
+ slave_conf.dst_maxburst = 16;
+
dma_chan->device->device_control(dma_chan, DMA_SLAVE_CONFIG,
(unsigned long) &slave_conf);
@@ -166,6 +168,7 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,
struct ux500_dma_controller *controller = container_of(c,
struct ux500_dma_controller, controller);
struct ux500_dma_channel *ux500_channel = NULL;
+ struct musb *musb = controller->private_data;
u8 ch_num = hw_ep->epnum - 1;
u32 max_ch;
@@ -192,7 +195,7 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,
ux500_channel->hw_ep = hw_ep;
ux500_channel->is_allocated = 1;
- DBG(7, "hw_ep=%d, is_tx=0x%x, channel=%d\n",
+ dev_dbg(musb->controller, "hw_ep=%d, is_tx=0x%x, channel=%d\n",
hw_ep->epnum, is_tx, ch_num);
return &(ux500_channel->channel);
@@ -201,8 +204,9 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,
static void ux500_dma_channel_release(struct dma_channel *channel)
{
struct ux500_dma_channel *ux500_channel = channel->private_data;
+ struct musb *musb = ux500_channel->controller->private_data;
- DBG(7, "channel=%d\n", ux500_channel->ch_num);
+ dev_dbg(musb->controller, "channel=%d\n", ux500_channel->ch_num);
if (ux500_channel->is_allocated) {
ux500_channel->is_allocated = 0;
@@ -252,8 +256,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel)
void __iomem *epio = musb->endpoints[ux500_channel->hw_ep->epnum].regs;
u16 csr;
- DBG(4, "channel=%d, is_tx=%d\n", ux500_channel->ch_num,
- ux500_channel->is_tx);
+ dev_dbg(musb->controller, "channel=%d, is_tx=%d\n",
+ ux500_channel->ch_num, ux500_channel->is_tx);
if (channel->status == MUSB_DMA_STATUS_BUSY) {
if (ux500_channel->is_tx) {
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig
index b2e6491..6f4afa4 100644
--- a/drivers/usb/renesas_usbhs/Kconfig
+++ b/drivers/usb/renesas_usbhs/Kconfig
@@ -1,16 +1,15 @@
#
-# Renesas USB Controller Drivers
+# Renesas USBHS Controller Drivers
#
config USB_RENESAS_USBHS
tristate 'Renesas USBHS controller'
- depends on SUPERH || ARCH_SHMOBILE
+ depends on USB && USB_GADGET
default n
help
- Renesas USBHS is a discrete USB host and peripheral controller chip
- that supports both full and high speed USB 2.0 data transfers.
- It has nine or more configurable endpoints, and endpoint zero.
+ Renesas USBHS is a discrete USB host and peripheral controller chip
+ that supports both full and high speed USB 2.0 data transfers.
+ It has nine or more configurable endpoints, and endpoint zero.
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "renesas_usbhs" and force all
- gadget drivers to also be dynamically linked.
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "renesas_usbhs"
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile
index b8798ad..bc8aef4 100644
--- a/drivers/usb/renesas_usbhs/Makefile
+++ b/drivers/usb/renesas_usbhs/Makefile
@@ -4,6 +4,12 @@
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o
-renesas_usbhs-y := common.o mod.o pipe.o
+renesas_usbhs-y := common.o mod.o pipe.o fifo.o
-renesas_usbhs-$(CONFIG_USB_RENESAS_USBHS_UDC) += mod_gadget.o
+ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),)
+ renesas_usbhs-y += mod_host.o
+endif
+
+ifneq ($(CONFIG_USB_RENESAS_USBHS_UDC),)
+ renesas_usbhs-y += mod_gadget.o
+endif
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index f3664d6..08c679c 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -21,6 +21,29 @@
#include <linux/sysfs.h>
#include "./common.h"
+/*
+ * image of renesas_usbhs
+ *
+ * ex) gadget case
+
+ * mod.c
+ * mod_gadget.c
+ * mod_host.c pipe.c fifo.c
+ *
+ * +-------+ +-----------+
+ * | pipe0 |------>| fifo pio |
+ * +------------+ +-------+ +-----------+
+ * | mod_gadget |=====> | pipe1 |--+
+ * +------------+ +-------+ | +-----------+
+ * | pipe2 | | +-| fifo dma0 |
+ * +------------+ +-------+ | | +-----------+
+ * | mod_host | | pipe3 |<-|--+
+ * +------------+ +-------+ | +-----------+
+ * | .... | +--->| fifo dma1 |
+ * | .... | +-----------+
+ */
+
+
#define USBHSF_RUNTIME_PWCTRL (1 << 0)
/* status */
@@ -38,8 +61,8 @@
*/
#define usbhs_platform_call(priv, func, args...)\
(!(priv) ? -ENODEV : \
- !((priv)->pfunc->func) ? 0 : \
- (priv)->pfunc->func(args))
+ !((priv)->pfunc.func) ? 0 : \
+ (priv)->pfunc.func(args))
/*
* common functions
@@ -91,6 +114,10 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
{
u16 mask = DCFM | DRPD | DPRPU;
u16 val = DCFM | DRPD;
+ int has_otg = usbhs_get_dparam(priv, has_otg);
+
+ if (has_otg)
+ usbhs_bset(priv, DVSTCTR, (EXTLP | PWEN), (EXTLP | PWEN));
/*
* if enable
@@ -124,19 +151,133 @@ int usbhs_frame_get_num(struct usbhs_priv *priv)
}
/*
+ * usb request functions
+ */
+void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
+{
+ u16 val;
+
+ val = usbhs_read(priv, USBREQ);
+ req->bRequest = (val >> 8) & 0xFF;
+ req->bRequestType = (val >> 0) & 0xFF;
+
+ req->wValue = usbhs_read(priv, USBVAL);
+ req->wIndex = usbhs_read(priv, USBINDX);
+ req->wLength = usbhs_read(priv, USBLENG);
+}
+
+void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
+{
+ usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType);
+ usbhs_write(priv, USBVAL, req->wValue);
+ usbhs_write(priv, USBINDX, req->wIndex);
+ usbhs_write(priv, USBLENG, req->wLength);
+
+ usbhs_bset(priv, DCPCTR, SUREQ, SUREQ);
+}
+
+/*
+ * bus/vbus functions
+ */
+void usbhs_bus_send_sof_enable(struct usbhs_priv *priv)
+{
+ u16 status = usbhs_read(priv, DVSTCTR) & (USBRST | UACT);
+
+ if (status != USBRST) {
+ struct device *dev = usbhs_priv_to_dev(priv);
+ dev_err(dev, "usbhs should be reset\n");
+ }
+
+ usbhs_bset(priv, DVSTCTR, (USBRST | UACT), UACT);
+}
+
+void usbhs_bus_send_reset(struct usbhs_priv *priv)
+{
+ usbhs_bset(priv, DVSTCTR, (USBRST | UACT), USBRST);
+}
+
+int usbhs_bus_get_speed(struct usbhs_priv *priv)
+{
+ u16 dvstctr = usbhs_read(priv, DVSTCTR);
+
+ switch (RHST & dvstctr) {
+ case RHST_LOW_SPEED:
+ return USB_SPEED_LOW;
+ case RHST_FULL_SPEED:
+ return USB_SPEED_FULL;
+ case RHST_HIGH_SPEED:
+ return USB_SPEED_HIGH;
+ }
+
+ return USB_SPEED_UNKNOWN;
+}
+
+int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable)
+{
+ struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+
+ return usbhs_platform_call(priv, set_vbus, pdev, enable);
+}
+
+static void usbhsc_bus_init(struct usbhs_priv *priv)
+{
+ usbhs_write(priv, DVSTCTR, 0);
+
+ usbhs_vbus_ctrl(priv, 0);
+}
+
+/*
+ * device configuration
+ */
+int usbhs_set_device_speed(struct usbhs_priv *priv, int devnum,
+ u16 upphub, u16 hubport, u16 speed)
+{
+ struct device *dev = usbhs_priv_to_dev(priv);
+ u16 usbspd = 0;
+ u32 reg = DEVADD0 + (2 * devnum);
+
+ if (devnum > 10) {
+ dev_err(dev, "cannot set speed to unknown device %d\n", devnum);
+ return -EIO;
+ }
+
+ if (upphub > 0xA) {
+ dev_err(dev, "unsupported hub number %d\n", upphub);
+ return -EIO;
+ }
+
+ switch (speed) {
+ case USB_SPEED_LOW:
+ usbspd = USBSPD_SPEED_LOW;
+ break;
+ case USB_SPEED_FULL:
+ usbspd = USBSPD_SPEED_FULL;
+ break;
+ case USB_SPEED_HIGH:
+ usbspd = USBSPD_SPEED_HIGH;
+ break;
+ default:
+ dev_err(dev, "unsupported speed %d\n", speed);
+ return -EIO;
+ }
+
+ usbhs_write(priv, reg, UPPHUB(upphub) |
+ HUBPORT(hubport)|
+ USBSPD(usbspd));
+
+ return 0;
+}
+
+/*
* local functions
*/
-static void usbhsc_bus_ctrl(struct usbhs_priv *priv, int enable)
+static void usbhsc_set_buswait(struct usbhs_priv *priv)
{
int wait = usbhs_get_dparam(priv, buswait_bwait);
- u16 data = 0;
- if (enable) {
- /* set bus wait if platform have */
- if (wait)
- usbhs_bset(priv, BUSWAIT, 0x000F, wait);
- }
- usbhs_write(priv, DVSTCTR, data);
+ /* set bus wait if platform have */
+ if (wait)
+ usbhs_bset(priv, BUSWAIT, 0x000F, wait);
}
/*
@@ -168,10 +309,8 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
/* USB on */
usbhs_sys_clock_ctrl(priv, enable);
- usbhsc_bus_ctrl(priv, enable);
} else {
/* USB off */
- usbhsc_bus_ctrl(priv, enable);
usbhs_sys_clock_ctrl(priv, enable);
/* disable PM */
@@ -180,13 +319,10 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
}
/*
- * notify hotplug
+ * hotplug
*/
-static void usbhsc_notify_hotplug(struct work_struct *work)
+static void usbhsc_hotplug(struct usbhs_priv *priv)
{
- struct usbhs_priv *priv = container_of(work,
- struct usbhs_priv,
- notify_hotplug_work.work);
struct platform_device *pdev = usbhs_priv_to_pdev(priv);
struct usbhs_mod *mod = usbhs_mod_get_current(priv);
int id;
@@ -214,6 +350,10 @@ static void usbhsc_notify_hotplug(struct work_struct *work)
if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
usbhsc_power_ctrl(priv, enable);
+ /* bus init */
+ usbhsc_set_buswait(priv);
+ usbhsc_bus_init(priv);
+
/* module start */
usbhs_mod_call(priv, start, priv);
@@ -223,6 +363,9 @@ static void usbhsc_notify_hotplug(struct work_struct *work)
/* module stop */
usbhs_mod_call(priv, stop, priv);
+ /* bus init */
+ usbhsc_bus_init(priv);
+
/* power off */
if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
usbhsc_power_ctrl(priv, enable);
@@ -234,6 +377,17 @@ static void usbhsc_notify_hotplug(struct work_struct *work)
}
}
+/*
+ * notify hotplug
+ */
+static void usbhsc_notify_hotplug(struct work_struct *work)
+{
+ struct usbhs_priv *priv = container_of(work,
+ struct usbhs_priv,
+ notify_hotplug_work.work);
+ usbhsc_hotplug(priv);
+}
+
int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
{
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
@@ -251,7 +405,7 @@ int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
/*
* platform functions
*/
-static int __devinit usbhs_probe(struct platform_device *pdev)
+static int usbhs_probe(struct platform_device *pdev)
{
struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
struct renesas_usbhs_driver_callback *dfunc;
@@ -292,22 +446,28 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
/*
* care platform info
*/
- priv->pfunc = &info->platform_callback;
- priv->dparam = &info->driver_param;
+ memcpy(&priv->pfunc,
+ &info->platform_callback,
+ sizeof(struct renesas_usbhs_platform_callback));
+ memcpy(&priv->dparam,
+ &info->driver_param,
+ sizeof(struct renesas_usbhs_driver_param));
/* set driver callback functions for platform */
dfunc = &info->driver_callback;
dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug;
/* set default param if platform doesn't have */
- if (!priv->dparam->pipe_type) {
- priv->dparam->pipe_type = usbhsc_default_pipe_type;
- priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
+ if (!priv->dparam.pipe_type) {
+ priv->dparam.pipe_type = usbhsc_default_pipe_type;
+ priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
}
+ if (!priv->dparam.pio_dma_border)
+ priv->dparam.pio_dma_border = 64; /* 64byte */
/* FIXME */
/* runtime power control ? */
- if (priv->pfunc->get_vbus)
+ if (priv->pfunc.get_vbus)
usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL);
/*
@@ -323,10 +483,14 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
if (ret < 0)
goto probe_end_iounmap;
- ret = usbhs_mod_probe(priv);
+ ret = usbhs_fifo_probe(priv);
if (ret < 0)
goto probe_end_pipe_exit;
+ ret = usbhs_mod_probe(priv);
+ if (ret < 0)
+ goto probe_end_fifo_exit;
+
/* dev_set_drvdata should be called after usbhs_mod_init */
dev_set_drvdata(&pdev->dev, priv);
@@ -374,6 +538,8 @@ probe_end_call_remove:
usbhs_platform_call(priv, hardware_exit, pdev);
probe_end_mod_exit:
usbhs_mod_remove(priv);
+probe_end_fifo_exit:
+ usbhs_fifo_remove(priv);
probe_end_pipe_exit:
usbhs_pipe_remove(priv);
probe_end_iounmap:
@@ -404,6 +570,7 @@ static int __devexit usbhs_remove(struct platform_device *pdev)
usbhs_platform_call(priv, hardware_exit, pdev);
usbhs_mod_remove(priv);
+ usbhs_fifo_remove(priv);
usbhs_pipe_remove(priv);
iounmap(priv->base);
kfree(priv);
@@ -411,9 +578,60 @@ static int __devexit usbhs_remove(struct platform_device *pdev)
return 0;
}
+static int usbhsc_suspend(struct device *dev)
+{
+ struct usbhs_priv *priv = dev_get_drvdata(dev);
+ struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+
+ if (mod) {
+ usbhs_mod_call(priv, stop, priv);
+ usbhs_mod_change(priv, -1);
+ }
+
+ if (mod || !usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+ usbhsc_power_ctrl(priv, 0);
+
+ return 0;
+}
+
+static int usbhsc_resume(struct device *dev)
+{
+ struct usbhs_priv *priv = dev_get_drvdata(dev);
+ struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+
+ usbhs_platform_call(priv, phy_reset, pdev);
+
+ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+ usbhsc_power_ctrl(priv, 1);
+
+ usbhsc_hotplug(priv);
+
+ return 0;
+}
+
+static int usbhsc_runtime_nop(struct device *dev)
+{
+ /* Runtime PM callback shared between ->runtime_suspend()
+ * and ->runtime_resume(). Simply returns success.
+ *
+ * This driver re-initializes all registers after
+ * pm_runtime_get_sync() anyway so there is no need
+ * to save and restore registers here.
+ */
+ return 0;
+}
+
+static const struct dev_pm_ops usbhsc_pm_ops = {
+ .suspend = usbhsc_suspend,
+ .resume = usbhsc_resume,
+ .runtime_suspend = usbhsc_runtime_nop,
+ .runtime_resume = usbhsc_runtime_nop,
+};
+
static struct platform_driver renesas_usbhs_driver = {
.driver = {
.name = "renesas_usbhs",
+ .pm = &usbhsc_pm_ops,
},
.probe = usbhs_probe,
.remove = __devexit_p(usbhs_remove),
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index 0aadcb4..8729da5 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -36,6 +36,12 @@ struct usbhs_priv;
#define CFIFO 0x0014
#define CFIFOSEL 0x0020
#define CFIFOCTR 0x0022
+#define D0FIFO 0x0100
+#define D0FIFOSEL 0x0028
+#define D0FIFOCTR 0x002A
+#define D1FIFO 0x0120
+#define D1FIFOSEL 0x002C
+#define D1FIFOCTR 0x002E
#define INTENB0 0x0030
#define INTENB1 0x0032
#define BRDYENB 0x0036
@@ -60,6 +66,41 @@ struct usbhs_priv;
#define PIPEMAXP 0x006C
#define PIPEPERI 0x006E
#define PIPEnCTR 0x0070
+#define PIPE1TRE 0x0090
+#define PIPE1TRN 0x0092
+#define PIPE2TRE 0x0094
+#define PIPE2TRN 0x0096
+#define PIPE3TRE 0x0098
+#define PIPE3TRN 0x009A
+#define PIPE4TRE 0x009C
+#define PIPE4TRN 0x009E
+#define PIPE5TRE 0x00A0
+#define PIPE5TRN 0x00A2
+#define PIPEBTRE 0x00A4
+#define PIPEBTRN 0x00A6
+#define PIPECTRE 0x00A8
+#define PIPECTRN 0x00AA
+#define PIPEDTRE 0x00AC
+#define PIPEDTRN 0x00AE
+#define PIPEETRE 0x00B0
+#define PIPEETRN 0x00B2
+#define PIPEFTRE 0x00B4
+#define PIPEFTRN 0x00B6
+#define PIPE9TRE 0x00B8
+#define PIPE9TRN 0x00BA
+#define PIPEATRE 0x00BC
+#define PIPEATRN 0x00BE
+#define DEVADD0 0x00D0 /* Device address n configuration */
+#define DEVADD1 0x00D2
+#define DEVADD2 0x00D4
+#define DEVADD3 0x00D6
+#define DEVADD4 0x00D8
+#define DEVADD5 0x00DA
+#define DEVADD6 0x00DC
+#define DEVADD7 0x00DE
+#define DEVADD8 0x00E0
+#define DEVADD9 0x00E2
+#define DEVADDA 0x00E4
/* SYSCFG */
#define SCKE (1 << 10) /* USB Module Clock Enable */
@@ -72,12 +113,15 @@ struct usbhs_priv;
/* DVSTCTR */
#define EXTLP (1 << 10) /* Controls the EXTLP pin output state */
#define PWEN (1 << 9) /* Controls the PWEN pin output state */
+#define USBRST (1 << 6) /* Bus Reset Output */
+#define UACT (1 << 4) /* USB Bus Enable */
#define RHST (0x7) /* Reset Handshake */
#define RHST_LOW_SPEED 1 /* Low-speed connection */
#define RHST_FULL_SPEED 2 /* Full-speed connection */
#define RHST_HIGH_SPEED 3 /* High-speed connection */
/* CFIFOSEL */
+#define DREQE (1 << 12) /* DMA Transfer Request Enable */
#define MBW_32 (0x2 << 10) /* CFIFO Port Access Bit Width */
/* CFIFOCTR */
@@ -128,6 +172,15 @@ struct usbhs_priv;
#define NODATA_STATUS_STAGE 5 /* Control write NoData status stage */
#define SEQUENCE_ERROR 6 /* Control transfer sequence error */
+/* INTSTS1 */
+#define OVRCR (1 << 15) /* OVRCR Interrupt Status */
+#define BCHG (1 << 14) /* USB Bus Change Interrupt Status */
+#define DTCH (1 << 12) /* USB Disconnection Detect Interrupt Status */
+#define ATTCH (1 << 11) /* ATTCH Interrupt Status */
+#define EOFERR (1 << 6) /* EOF Error Detect Interrupt Status */
+#define SIGN (1 << 5) /* Setup Transaction Error Interrupt Status */
+#define SACK (1 << 4) /* Setup Transaction ACK Response Interrupt Status */
+
/* PIPECFG */
/* DCPCFG */
#define TYPE_NONE (0 << 14) /* Transfer Type */
@@ -152,9 +205,11 @@ struct usbhs_priv;
/* PIPEnCTR */
/* DCPCTR */
#define BSTS (1 << 15) /* Buffer Status */
+#define SUREQ (1 << 14) /* Sending SETUP Token */
#define CSSTS (1 << 12) /* CSSTS Status */
-#define SQCLR (1 << 8) /* Toggle Bit Clear */
#define ACLRM (1 << 9) /* Buffer Auto-Clear Mode */
+#define SQCLR (1 << 8) /* Toggle Bit Clear */
+#define SQSET (1 << 7) /* Toggle Bit Set */
#define PBUSY (1 << 5) /* Pipe Busy */
#define PID_MASK (0x3) /* Response PID */
#define PID_NAK 0
@@ -164,9 +219,21 @@ struct usbhs_priv;
#define CCPL (1 << 2) /* Control Transfer End Enable */
+/* PIPEnTRE */
+#define TRENB (1 << 9) /* Transaction Counter Enable */
+#define TRCLR (1 << 8) /* Transaction Counter Clear */
+
/* FRMNUM */
#define FRNM_MASK (0x7FF)
+/* DEVADDn */
+#define UPPHUB(x) (((x) & 0xF) << 11) /* HUB Register */
+#define HUBPORT(x) (((x) & 0x7) << 8) /* HUB Port for Target Device */
+#define USBSPD(x) (((x) & 0x3) << 6) /* Device Transfer Rate */
+#define USBSPD_SPEED_LOW 0x1
+#define USBSPD_SPEED_FULL 0x2
+#define USBSPD_SPEED_HIGH 0x3
+
/*
* struct
*/
@@ -175,8 +242,8 @@ struct usbhs_priv {
void __iomem *base;
unsigned int irq;
- struct renesas_usbhs_platform_callback *pfunc;
- struct renesas_usbhs_driver_param *dparam;
+ struct renesas_usbhs_platform_callback pfunc;
+ struct renesas_usbhs_driver_param dparam;
struct delayed_work notify_hotplug_work;
struct platform_device *pdev;
@@ -194,6 +261,11 @@ struct usbhs_priv {
* pipe control
*/
struct usbhs_pipe_info pipe_info;
+
+ /*
+ * fifo control
+ */
+ struct usbhs_fifo_info fifo_info;
};
/*
@@ -204,6 +276,10 @@ void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data);
void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev);
+
+#define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f)
+#define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f)
+
/*
* sysconfig
*/
@@ -214,15 +290,35 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
/*
+ * usb request
+ */
+void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req);
+void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req);
+
+/*
+ * bus
+ */
+void usbhs_bus_send_sof_enable(struct usbhs_priv *priv);
+void usbhs_bus_send_reset(struct usbhs_priv *priv);
+int usbhs_bus_get_speed(struct usbhs_priv *priv);
+int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable);
+
+/*
* frame
*/
int usbhs_frame_get_num(struct usbhs_priv *priv);
/*
+ * device config
+ */
+int usbhs_set_device_speed(struct usbhs_priv *priv, int devnum, u16 upphub,
+ u16 hubport, u16 speed);
+
+/*
* data
*/
struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev);
-#define usbhs_get_dparam(priv, param) (priv->dparam->param)
+#define usbhs_get_dparam(priv, param) (priv->dparam.param)
#define usbhs_priv_to_pdev(priv) (priv->pdev)
#define usbhs_priv_to_dev(priv) (&priv->pdev->dev)
#define usbhs_priv_to_lock(priv) (&priv->lock)
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index a577f8f..ad96a38 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -58,7 +58,7 @@ void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
info->irq_vbus = usbhsm_autonomy_irq_vbus;
- priv->pfunc->get_vbus = usbhsm_autonomy_get_vbus;
+ priv->pfunc.get_vbus = usbhsm_autonomy_get_vbus;
usbhs_irq_callback_update(priv, NULL);
}
@@ -93,8 +93,9 @@ struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
return ret;
}
-int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod)
+int usbhs_mod_is_host(struct usbhs_priv *priv)
{
+ struct usbhs_mod *mod = usbhs_mod_get_current(priv);
struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
if (!mod)
@@ -139,13 +140,17 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
/*
* install host/gadget driver
*/
- ret = usbhs_mod_gadget_probe(priv);
+ ret = usbhs_mod_host_probe(priv);
if (ret < 0)
return ret;
+ ret = usbhs_mod_gadget_probe(priv);
+ if (ret < 0)
+ goto mod_init_host_err;
+
/* irq settings */
ret = request_irq(priv->irq, usbhs_interrupt,
- IRQF_DISABLED, dev_name(dev), priv);
+ 0, dev_name(dev), priv);
if (ret) {
dev_err(dev, "irq request err\n");
goto mod_init_gadget_err;
@@ -155,12 +160,15 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
mod_init_gadget_err:
usbhs_mod_gadget_remove(priv);
+mod_init_host_err:
+ usbhs_mod_host_remove(priv);
return ret;
}
void usbhs_mod_remove(struct usbhs_priv *priv)
{
+ usbhs_mod_host_remove(priv);
usbhs_mod_gadget_remove(priv);
free_irq(priv->irq, priv);
}
@@ -168,20 +176,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)
/*
* status functions
*/
-int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state)
-{
- switch (irq_state->dvstctr & RHST) {
- case RHST_LOW_SPEED:
- return USB_SPEED_LOW;
- case RHST_FULL_SPEED:
- return USB_SPEED_FULL;
- case RHST_HIGH_SPEED:
- return USB_SPEED_HIGH;
- }
-
- return USB_SPEED_UNKNOWN;
-}
-
int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
{
int state = irq_state->intsts0 & DVSQ_MASK;
@@ -221,8 +215,6 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
state->intsts0 = usbhs_read(priv, INTSTS0);
state->intsts1 = usbhs_read(priv, INTSTS1);
- state->dvstctr = usbhs_read(priv, DVSTCTR);
-
/* mask */
if (mod) {
state->brdysts = usbhs_read(priv, BRDYSTS);
@@ -269,6 +261,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
* see also
* usbhs_irq_setting_update
*/
+
+ /* INTSTS0 */
if (irq_state.intsts0 & VBINT)
usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
@@ -284,15 +278,38 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
if (irq_state.intsts0 & BRDY)
usbhs_mod_call(priv, irq_ready, priv, &irq_state);
+ /* INTSTS1 */
+ if (irq_state.intsts1 & ATTCH)
+ usbhs_mod_call(priv, irq_attch, priv, &irq_state);
+
+ if (irq_state.intsts1 & DTCH)
+ usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
+
+ if (irq_state.intsts1 & SIGN)
+ usbhs_mod_call(priv, irq_sign, priv, &irq_state);
+
+ if (irq_state.intsts1 & SACK)
+ usbhs_mod_call(priv, irq_sack, priv, &irq_state);
+
return IRQ_HANDLED;
}
void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
{
u16 intenb0 = 0;
+ u16 intenb1 = 0;
struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
+ /*
+ * BEMPENB/BRDYENB are picky.
+ * below method is required
+ *
+ * - clear INTSTS0
+ * - update BEMPENB/BRDYENB
+ * - update INTSTS0
+ */
usbhs_write(priv, INTENB0, 0);
+ usbhs_write(priv, INTENB1, 0);
usbhs_write(priv, BEMPENB, 0);
usbhs_write(priv, BRDYENB, 0);
@@ -310,6 +327,9 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
intenb0 |= VBSE;
if (mod) {
+ /*
+ * INTSTS0
+ */
if (mod->irq_ctrl_stage)
intenb0 |= CTRE;
@@ -322,7 +342,26 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
usbhs_write(priv, BRDYENB, mod->irq_brdysts);
intenb0 |= BRDYE;
}
+
+ /*
+ * INTSTS1
+ */
+ if (mod->irq_attch)
+ intenb1 |= ATTCHE;
+
+ if (mod->irq_dtch)
+ intenb1 |= DTCHE;
+
+ if (mod->irq_sign)
+ intenb1 |= SIGNE;
+
+ if (mod->irq_sack)
+ intenb1 |= SACKE;
}
- usbhs_write(priv, INTENB0, intenb0);
+ if (intenb0)
+ usbhs_write(priv, INTENB0, intenb0);
+
+ if (intenb1)
+ usbhs_write(priv, INTENB1, intenb1);
}
diff --git a/drivers/usb/renesas_usbhs/mod.h b/drivers/usb/renesas_usbhs/mod.h
index 5c845a2..6c68755 100644
--- a/drivers/usb/renesas_usbhs/mod.h
+++ b/drivers/usb/renesas_usbhs/mod.h
@@ -30,7 +30,6 @@ struct usbhs_irq_state {
u16 brdysts;
u16 nrdysts;
u16 bempsts;
- u16 dvstctr;
};
struct usbhs_mod {
@@ -42,26 +41,48 @@ struct usbhs_mod {
int (*start)(struct usbhs_priv *priv);
int (*stop)(struct usbhs_priv *priv);
- /* INTSTS0 :: DVST (DVSQ) */
+ /*
+ * INTSTS0
+ */
+
+ /* DVST (DVSQ) */
int (*irq_dev_state)(struct usbhs_priv *priv,
struct usbhs_irq_state *irq_state);
- /* INTSTS0 :: CTRT (CTSQ) */
+ /* CTRT (CTSQ) */
int (*irq_ctrl_stage)(struct usbhs_priv *priv,
struct usbhs_irq_state *irq_state);
- /* INTSTS0 :: BEMP */
- /* BEMPSTS */
+ /* BEMP / BEMPSTS */
int (*irq_empty)(struct usbhs_priv *priv,
struct usbhs_irq_state *irq_state);
u16 irq_bempsts;
- /* INTSTS0 :: BRDY */
- /* BRDYSTS */
+ /* BRDY / BRDYSTS */
int (*irq_ready)(struct usbhs_priv *priv,
struct usbhs_irq_state *irq_state);
u16 irq_brdysts;
+ /*
+ * INTSTS1
+ */
+
+ /* ATTCHE */
+ int (*irq_attch)(struct usbhs_priv *priv,
+ struct usbhs_irq_state *irq_state);
+
+ /* DTCHE */
+ int (*irq_dtch)(struct usbhs_priv *priv,
+ struct usbhs_irq_state *irq_state);
+
+ /* SIGN */
+ int (*irq_sign)(struct usbhs_priv *priv,
+ struct usbhs_irq_state *irq_state);
+
+ /* SACK */
+ int (*irq_sack)(struct usbhs_priv *priv,
+ struct usbhs_irq_state *irq_state);
+
struct usbhs_priv *priv;
};
@@ -89,7 +110,7 @@ struct usbhs_mod_info {
struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id);
struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv);
void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *usb, int id);
-int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod);
+int usbhs_mod_is_host(struct usbhs_priv *priv);
int usbhs_mod_change(struct usbhs_priv *priv, int id);
int usbhs_mod_probe(struct usbhs_priv *priv);
void usbhs_mod_remove(struct usbhs_priv *priv);
@@ -99,7 +120,6 @@ void usbhs_mod_autonomy_mode(struct usbhs_priv *priv);
/*
* status functions
*/
-int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state);
int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state);
int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state);
@@ -119,11 +139,26 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod);
})
/*
- * gadget control
+ * host / gadget control
*/
-#ifdef CONFIG_USB_RENESAS_USBHS_UDC
-extern int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv);
-extern void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv);
+#if defined(CONFIG_USB_RENESAS_USBHS_HCD) || \
+ defined(CONFIG_USB_RENESAS_USBHS_HCD_MODULE)
+extern int usbhs_mod_host_probe(struct usbhs_priv *priv);
+extern int usbhs_mod_host_remove(struct usbhs_priv *priv);
+#else
+static inline int usbhs_mod_host_probe(struct usbhs_priv *priv)
+{
+ return 0;
+}
+static inline void usbhs_mod_host_remove(struct usbhs_priv *priv)
+{
+}
+#endif
+
+#if defined(CONFIG_USB_RENESAS_USBHS_UDC) || \
+ defined(CONFIG_USB_RENESAS_USBHS_UDC_MODULE)
+extern int usbhs_mod_gadget_probe(struct usbhs_priv *priv);
+extern void usbhs_mod_gadget_remove(struct usbhs_priv *priv);
#else
static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
{
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 547486c..0b1fc07 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -14,6 +14,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -26,26 +27,24 @@
*/
struct usbhsg_request {
struct usb_request req;
- struct list_head node;
+ struct usbhs_pkt pkt;
};
#define EP_NAME_SIZE 8
struct usbhsg_gpriv;
-struct usbhsg_pipe_handle;
struct usbhsg_uep {
struct usb_ep ep;
struct usbhs_pipe *pipe;
- struct list_head list;
char ep_name[EP_NAME_SIZE];
struct usbhsg_gpriv *gpriv;
- struct usbhsg_pipe_handle *handler;
};
struct usbhsg_gpriv {
struct usb_gadget gadget;
struct usbhs_mod mod;
+ struct list_head link;
struct usbhsg_uep *uep;
int uep_size;
@@ -58,12 +57,6 @@ struct usbhsg_gpriv {
#define USBHSG_STATUS_WEDGE (1 << 2)
};
-struct usbhsg_pipe_handle {
- int (*prepare)(struct usbhsg_uep *uep, struct usbhsg_request *ureq);
- int (*try_run)(struct usbhsg_uep *uep, struct usbhsg_request *ureq);
- void (*irq_mask)(struct usbhsg_uep *uep, int enable);
-};
-
struct usbhsg_recip_handle {
char *name;
int (*device)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
@@ -83,7 +76,7 @@ struct usbhsg_recip_handle {
struct usbhsg_gpriv, mod)
#define __usbhsg_for_each_uep(start, pos, g, i) \
- for (i = start, pos = (g)->uep; \
+ for (i = start, pos = (g)->uep + i; \
i < (g)->uep_size; \
i++, pos = (g)->uep + i)
@@ -100,7 +93,6 @@ struct usbhsg_recip_handle {
container_of(r, struct usbhsg_request, req)
#define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep)
-#define usbhsg_gpriv_to_lock(gp) usbhs_priv_to_lock((gp)->mod.priv)
#define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv)
#define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv)
#define usbhsg_gpriv_to_dcp(gp) ((gp)->uep)
@@ -110,6 +102,10 @@ struct usbhsg_recip_handle {
#define usbhsg_pipe_to_uep(p) ((p)->mod_private)
#define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv))
+#define usbhsg_ureq_to_pkt(u) (&(u)->pkt)
+#define usbhsg_pkt_to_ureq(i) \
+ container_of(i, struct usbhsg_request, pkt)
+
#define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN)
/* status */
@@ -118,119 +114,19 @@ struct usbhsg_recip_handle {
#define usbhsg_status_clr(gp, b) (gp->status &= ~b)
#define usbhsg_status_has(gp, b) (gp->status & b)
-/*
- * usbhsg_trylock
- *
- * This driver don't use spin_try_lock
- * to avoid warning of CONFIG_DEBUG_SPINLOCK
- */
-static spinlock_t *usbhsg_trylock(struct usbhsg_gpriv *gpriv,
- unsigned long *flags)
-{
- spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv);
-
- /* check spin lock status
- * to avoid deadlock/nest */
- if (spin_is_locked(lock))
- return NULL;
-
- spin_lock_irqsave(lock, *flags);
-
- return lock;
-}
-
-static void usbhsg_unlock(spinlock_t *lock, unsigned long *flags)
-{
- if (!lock)
- return;
+/* controller */
+LIST_HEAD(the_controller_link);
- spin_unlock_irqrestore(lock, *flags);
-}
+#define usbhsg_for_each_controller(gpriv)\
+ list_for_each_entry(gpriv, &the_controller_link, link)
+#define usbhsg_controller_register(gpriv)\
+ list_add_tail(&(gpriv)->link, &the_controller_link)
+#define usbhsg_controller_unregister(gpriv)\
+ list_del_init(&(gpriv)->link)
/*
- * list push/pop
+ * queue push/pop
*/
-static void usbhsg_queue_push(struct usbhsg_uep *uep,
- struct usbhsg_request *ureq)
-{
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
-
- /*
- ********* assume under spin lock *********
- */
- list_del_init(&ureq->node);
- list_add_tail(&ureq->node, &uep->list);
- ureq->req.actual = 0;
- ureq->req.status = -EINPROGRESS;
-
- dev_dbg(dev, "pipe %d : queue push (%d)\n",
- usbhs_pipe_number(pipe),
- ureq->req.length);
-}
-
-static struct usbhsg_request *usbhsg_queue_get(struct usbhsg_uep *uep)
-{
- /*
- ********* assume under spin lock *********
- */
- if (list_empty(&uep->list))
- return NULL;
-
- return list_entry(uep->list.next, struct usbhsg_request, node);
-}
-
-#define usbhsg_queue_prepare(uep) __usbhsg_queue_handler(uep, 1);
-#define usbhsg_queue_handle(uep) __usbhsg_queue_handler(uep, 0);
-static int __usbhsg_queue_handler(struct usbhsg_uep *uep, int prepare)
-{
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- struct usbhsg_request *ureq;
- spinlock_t *lock;
- unsigned long flags;
- int ret = 0;
-
- if (!uep->handler) {
- dev_err(dev, "no handler function\n");
- return -EIO;
- }
-
- /*
- * CAUTION [*queue handler*]
- *
- * This function will be called for start/restart queue operation.
- * OTOH the most much worry for USB driver is spinlock nest.
- * Specially it are
- * - usb_ep_ops :: queue
- * - usb_request :: complete
- *
- * But the caller of this function need not care about spinlock.
- * This function is using usbhsg_trylock for it.
- * if "is_locked" is 1, this mean this function lock it.
- * but if it is 0, this mean it is already under spin lock.
- * see also
- * CAUTION [*endpoint queue*]
- * CAUTION [*request complete*]
- */
-
- /****************** spin try lock *******************/
- lock = usbhsg_trylock(gpriv, &flags);
-
- ureq = usbhsg_queue_get(uep);
- if (ureq) {
- if (prepare)
- ret = uep->handler->prepare(uep, ureq);
- else
- ret = uep->handler->try_run(uep, ureq);
- }
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ******************/
-
- return ret;
-}
-
static void usbhsg_queue_pop(struct usbhsg_uep *uep,
struct usbhsg_request *ureq,
int status)
@@ -239,289 +135,111 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- /*
- ********* assume under spin lock *********
- */
-
- /*
- * CAUTION [*request complete*]
- *
- * There is a possibility not to be called in correct order
- * if "complete" is called without spinlock.
- *
- * So, this function assume it is under spinlock,
- * and call usb_request :: complete.
- *
- * But this "complete" will push next usb_request.
- * It mean "usb_ep_ops :: queue" which is using spinlock is called
- * under spinlock.
- *
- * To avoid dead-lock, this driver is using usbhsg_trylock.
- * CAUTION [*endpoint queue*]
- * CAUTION [*queue handler*]
- */
-
dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
- list_del_init(&ureq->node);
-
ureq->req.status = status;
ureq->req.complete(&uep->ep, &ureq->req);
-
- /* more request ? */
- if (0 == status)
- usbhsg_queue_prepare(uep);
-}
-
-/*
- * irq enable/disable function
- */
-#define usbhsg_irq_callback_ctrl(uep, status, enable) \
- ({ \
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); \
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); \
- struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); \
- struct usbhs_mod *mod = usbhs_mod_get_current(priv); \
- if (!mod) \
- return; \
- if (enable) \
- mod->irq_##status |= (1 << usbhs_pipe_number(pipe)); \
- else \
- mod->irq_##status &= ~(1 << usbhs_pipe_number(pipe)); \
- usbhs_irq_callback_update(priv, mod); \
- })
-
-static void usbhsg_irq_empty_ctrl(struct usbhsg_uep *uep, int enable)
-{
- usbhsg_irq_callback_ctrl(uep, bempsts, enable);
}
-static void usbhsg_irq_ready_ctrl(struct usbhsg_uep *uep, int enable)
+static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
{
- usbhsg_irq_callback_ctrl(uep, brdysts, enable);
-}
+ struct usbhs_pipe *pipe = pkt->pipe;
+ struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
+ struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
-/*
- * handler function
- */
-static int usbhsg_try_run_ctrl_stage_end(struct usbhsg_uep *uep,
- struct usbhsg_request *ureq)
-{
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ ureq->req.actual = pkt->actual;
- /*
- ********* assume under spin lock *********
- */
-
- usbhs_dcp_control_transfer_done(pipe);
usbhsg_queue_pop(uep, ureq, 0);
-
- return 0;
}
-static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,
- struct usbhsg_request *ureq)
+static void usbhsg_queue_push(struct usbhsg_uep *uep,
+ struct usbhsg_request *ureq)
{
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
- struct usb_request *req = &ureq->req;
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- void *buf;
- int remainder, send;
- int is_done = 0;
- int enable;
- int maxp;
-
- /*
- ********* assume under spin lock *********
- */
-
- maxp = usbhs_pipe_get_maxpacket(pipe);
- buf = req->buf + req->actual;
- remainder = req->length - req->actual;
-
- send = usbhs_fifo_write(pipe, buf, remainder);
+ struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq);
+ struct usb_request *req = &ureq->req;
- /*
- * send < 0 : pipe busy
- * send = 0 : send zero packet
- * send > 0 : send data
- *
- * send <= max_packet
- */
- if (send > 0)
- req->actual += send;
-
- /* send all packet ? */
- if (send < remainder)
- is_done = 0; /* there are remainder data */
- else if (send < maxp)
- is_done = 1; /* short packet */
- else
- is_done = !req->zero; /* send zero packet ? */
+ req->actual = 0;
+ req->status = -EINPROGRESS;
+ usbhs_pkt_push(pipe, pkt, usbhsg_queue_done,
+ req->buf, req->length, req->zero);
+ usbhs_pkt_start(pipe);
- dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
+ dev_dbg(dev, "pipe %d : queue push (%d)\n",
usbhs_pipe_number(pipe),
- remainder, send, is_done, req->zero);
-
- /*
- * enable interrupt and send again in irq handler
- * if it still have remainder data which should be sent.
- */
- enable = !is_done;
- uep->handler->irq_mask(uep, enable);
-
- /*
- * usbhs_fifo_enable execute
- * - after callback_update,
- * - before queue_pop / stage_end
- */
- usbhs_fifo_enable(pipe);
-
- /*
- * all data were sent ?
- */
- if (is_done) {
- /* it care below call in
- "function mode" */
- if (usbhsg_is_dcp(uep))
- usbhs_dcp_control_transfer_done(pipe);
-
- usbhsg_queue_pop(uep, ureq, 0);
- }
-
- return 0;
+ req->length);
}
-static int usbhsg_prepare_send_packet(struct usbhsg_uep *uep,
- struct usbhsg_request *ureq)
+/*
+ * dma map/unmap
+ */
+static int usbhsg_dma_map(struct device *dev,
+ struct usbhs_pkt *pkt,
+ enum dma_data_direction dir)
{
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
+ struct usb_request *req = &ureq->req;
- /*
- ********* assume under spin lock *********
- */
+ if (pkt->dma != DMA_ADDR_INVALID) {
+ dev_err(dev, "dma is already mapped\n");
+ return -EIO;
+ }
+
+ if (req->dma == DMA_ADDR_INVALID) {
+ pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
+ } else {
+ dma_sync_single_for_device(dev, req->dma, req->length, dir);
+ pkt->dma = req->dma;
+ }
- usbhs_fifo_prepare_write(pipe);
- usbhsg_try_run_send_packet(uep, ureq);
+ if (dma_mapping_error(dev, pkt->dma)) {
+ dev_err(dev, "dma mapping error %x\n", pkt->dma);
+ return -EIO;
+ }
return 0;
}
-static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep,
- struct usbhsg_request *ureq)
+static int usbhsg_dma_unmap(struct device *dev,
+ struct usbhs_pkt *pkt,
+ enum dma_data_direction dir)
{
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
struct usb_request *req = &ureq->req;
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- void *buf;
- int maxp;
- int remainder, recv;
- int is_done = 0;
-
- /*
- ********* assume under spin lock *********
- */
-
- maxp = usbhs_pipe_get_maxpacket(pipe);
- buf = req->buf + req->actual;
- remainder = req->length - req->actual;
-
- recv = usbhs_fifo_read(pipe, buf, remainder);
- /*
- * recv < 0 : pipe busy
- * recv >= 0 : receive data
- *
- * recv <= max_packet
- */
- if (recv < 0)
- return -EBUSY;
-
- /* update parameters */
- req->actual += recv;
- if ((recv == remainder) || /* receive all data */
- (recv < maxp)) /* short packet */
- is_done = 1;
-
- dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n",
- usbhs_pipe_number(pipe),
- remainder, recv, is_done, req->zero);
+ if (pkt->dma == DMA_ADDR_INVALID) {
+ dev_err(dev, "dma is not mapped\n");
+ return -EIO;
+ }
- /* read all data ? */
- if (is_done) {
- int disable = 0;
+ if (req->dma == DMA_ADDR_INVALID)
+ dma_unmap_single(dev, pkt->dma, pkt->length, dir);
+ else
+ dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
- uep->handler->irq_mask(uep, disable);
- usbhs_fifo_disable(pipe);
- usbhsg_queue_pop(uep, ureq, 0);
- }
+ pkt->dma = DMA_ADDR_INVALID;
return 0;
}
-static int usbhsg_prepare_receive_packet(struct usbhsg_uep *uep,
- struct usbhsg_request *ureq)
+static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
{
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
- int enable = 1;
- int ret;
-
- /*
- ********* assume under spin lock *********
- */
-
- ret = usbhs_fifo_prepare_read(pipe);
- if (ret < 0)
- return ret;
+ struct usbhs_pipe *pipe = pkt->pipe;
+ struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
+ struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+ struct device *dev = usbhsg_gpriv_to_dev(gpriv);
+ enum dma_data_direction dir;
- /*
- * data will be read in interrupt handler
- */
- uep->handler->irq_mask(uep, enable);
+ dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- return ret;
+ if (map)
+ return usbhsg_dma_map(dev, pkt, dir);
+ else
+ return usbhsg_dma_unmap(dev, pkt, dir);
}
-static struct usbhsg_pipe_handle usbhsg_handler_send_by_empty = {
- .prepare = usbhsg_prepare_send_packet,
- .try_run = usbhsg_try_run_send_packet,
- .irq_mask = usbhsg_irq_empty_ctrl,
-};
-
-static struct usbhsg_pipe_handle usbhsg_handler_send_by_ready = {
- .prepare = usbhsg_prepare_send_packet,
- .try_run = usbhsg_try_run_send_packet,
- .irq_mask = usbhsg_irq_ready_ctrl,
-};
-
-static struct usbhsg_pipe_handle usbhsg_handler_recv_by_ready = {
- .prepare = usbhsg_prepare_receive_packet,
- .try_run = usbhsg_try_run_receive_packet,
- .irq_mask = usbhsg_irq_ready_ctrl,
-};
-
-static struct usbhsg_pipe_handle usbhsg_handler_ctrl_stage_end = {
- .prepare = usbhsg_try_run_ctrl_stage_end,
- .try_run = usbhsg_try_run_ctrl_stage_end,
-};
-
-/*
- * DCP pipe can NOT use "ready interrupt" for "send"
- * it should use "empty" interrupt.
- * see
- * "Operation" - "Interrupt Function" - "BRDY Interrupt"
- *
- * on the other hand, normal pipe can use "ready interrupt" for "send"
- * even though it is single/double buffer
- */
-#define usbhsg_handler_send_ctrl usbhsg_handler_send_by_empty
-#define usbhsg_handler_recv_ctrl usbhsg_handler_recv_by_ready
-
-#define usbhsg_handler_send_packet usbhsg_handler_send_by_ready
-#define usbhsg_handler_recv_packet usbhsg_handler_recv_by_ready
-
/*
* USB_TYPE_STANDARD / clear feature functions
*/
@@ -546,15 +264,13 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) {
- usbhs_fifo_disable(pipe);
- usbhs_pipe_clear_sequence(pipe);
- usbhs_fifo_enable(pipe);
+ usbhs_pipe_disable(pipe);
+ usbhs_pipe_sequence_data0(pipe);
+ usbhs_pipe_enable(pipe);
}
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
- usbhsg_queue_prepare(uep);
-
return 0;
}
@@ -575,6 +291,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
struct usbhsg_uep *uep;
+ struct usbhs_pipe *pipe;
int recip = ctrl->bRequestType & USB_RECIP_MASK;
int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
int ret;
@@ -583,9 +300,11 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
char *msg;
uep = usbhsg_gpriv_to_nth_uep(gpriv, nth);
- if (!usbhsg_uep_to_pipe(uep)) {
+ pipe = usbhsg_uep_to_pipe(uep);
+ if (!pipe) {
dev_err(dev, "wrong recip request\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto usbhsg_recip_run_handle_end;
}
switch (recip) {
@@ -608,10 +327,20 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
}
if (func) {
+ unsigned long flags;
+
dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg);
+
+ /******************** spin lock ********************/
+ usbhs_lock(priv, flags);
ret = func(priv, uep, ctrl);
+ usbhs_unlock(priv, flags);
+ /******************** spin unlock ******************/
}
+usbhsg_recip_run_handle_end:
+ usbhs_pkt_start(pipe);
+
return ret;
}
@@ -626,7 +355,7 @@ static int usbhsg_irq_dev_state(struct usbhs_priv *priv,
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- gpriv->gadget.speed = usbhs_status_get_usb_speed(irq_state);
+ gpriv->gadget.speed = usbhs_bus_get_speed(priv);
dev_dbg(dev, "state = %x : speed : %d\n",
usbhs_status_get_device_state(irq_state),
@@ -660,13 +389,13 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
switch (stage) {
case READ_DATA_STAGE:
- dcp->handler = &usbhsg_handler_send_ctrl;
+ pipe->handler = &usbhs_fifo_pio_push_handler;
break;
case WRITE_DATA_STAGE:
- dcp->handler = &usbhsg_handler_recv_ctrl;
+ pipe->handler = &usbhs_fifo_pio_pop_handler;
break;
case NODATA_STATUS_STAGE:
- dcp->handler = &usbhsg_handler_ctrl_stage_end;
+ pipe->handler = &usbhs_ctrl_stage_end_handler;
break;
default:
return ret;
@@ -695,128 +424,27 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
ret = gpriv->driver->setup(&gpriv->gadget, &ctrl);
if (ret < 0)
- usbhs_fifo_stall(pipe);
+ usbhs_pipe_stall(pipe);
return ret;
}
-static int usbhsg_irq_empty(struct usbhs_priv *priv,
- struct usbhs_irq_state *irq_state)
-{
- struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
- struct usbhsg_uep *uep;
- struct usbhs_pipe *pipe;
- struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- int i, ret;
-
- if (!irq_state->bempsts) {
- dev_err(dev, "debug %s !!\n", __func__);
- return -EIO;
- }
-
- dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts);
-
- /*
- * search interrupted "pipe"
- * not "uep".
- */
- usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
- if (!(irq_state->bempsts & (1 << i)))
- continue;
-
- uep = usbhsg_pipe_to_uep(pipe);
- ret = usbhsg_queue_handle(uep);
- if (ret < 0)
- dev_err(dev, "send error %d : %d\n", i, ret);
- }
-
- return 0;
-}
-
-static int usbhsg_irq_ready(struct usbhs_priv *priv,
- struct usbhs_irq_state *irq_state)
-{
- struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
- struct usbhsg_uep *uep;
- struct usbhs_pipe *pipe;
- struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- int i, ret;
-
- if (!irq_state->brdysts) {
- dev_err(dev, "debug %s !!\n", __func__);
- return -EIO;
- }
-
- dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts);
-
- /*
- * search interrupted "pipe"
- * not "uep".
- */
- usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
- if (!(irq_state->brdysts & (1 << i)))
- continue;
-
- uep = usbhsg_pipe_to_uep(pipe);
- ret = usbhsg_queue_handle(uep);
- if (ret < 0)
- dev_err(dev, "receive error %d : %d\n", i, ret);
- }
-
- return 0;
-}
-
/*
*
* usb_dcp_ops
*
*/
-static int usbhsg_dcp_enable(struct usbhsg_uep *uep)
-{
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
- struct usbhs_pipe *pipe;
-
- /*
- ********* assume under spin lock *********
- */
-
- pipe = usbhs_dcp_malloc(priv);
- if (!pipe)
- return -EIO;
-
- uep->pipe = pipe;
- uep->pipe->mod_private = uep;
- INIT_LIST_HEAD(&uep->list);
-
- return 0;
-}
-
-#define usbhsg_dcp_disable usbhsg_pipe_disable
static int usbhsg_pipe_disable(struct usbhsg_uep *uep)
{
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
- struct usbhsg_request *ureq;
- int disable = 0;
-
- /*
- ********* assume under spin lock *********
- */
+ struct usbhs_pkt *pkt;
- usbhs_fifo_disable(pipe);
-
- /*
- * disable pipe irq
- */
- usbhsg_irq_empty_ctrl(uep, disable);
- usbhsg_irq_ready_ctrl(uep, disable);
+ usbhs_pipe_disable(pipe);
while (1) {
- ureq = usbhsg_queue_get(uep);
- if (!ureq)
+ pkt = usbhs_pkt_pop(pipe, NULL);
+ if (!pkt)
break;
-
- usbhsg_queue_pop(uep, ureq, -ECONNRESET);
}
return 0;
@@ -843,57 +471,55 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
struct usbhs_pipe *pipe;
- spinlock_t *lock;
- unsigned long flags;
int ret = -EIO;
/*
* if it already have pipe,
* nothing to do
*/
- if (uep->pipe)
+ if (uep->pipe) {
+ usbhs_pipe_clear(uep->pipe);
+ usbhs_pipe_sequence_data0(uep->pipe);
return 0;
+ }
- /******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
-
- pipe = usbhs_pipe_malloc(priv, desc);
+ pipe = usbhs_pipe_malloc(priv,
+ usb_endpoint_type(desc),
+ usb_endpoint_dir_in(desc));
if (pipe) {
uep->pipe = pipe;
pipe->mod_private = uep;
- INIT_LIST_HEAD(&uep->list);
+ /* set epnum / maxp */
+ usbhs_pipe_config_update(pipe, 0,
+ usb_endpoint_num(desc),
+ usb_endpoint_maxp(desc));
+
+ /*
+ * usbhs_fifo_dma_push/pop_handler try to
+ * use dmaengine if possible.
+ * It will use pio handler if impossible.
+ */
if (usb_endpoint_dir_in(desc))
- uep->handler = &usbhsg_handler_send_packet;
+ pipe->handler = &usbhs_fifo_dma_push_handler;
else
- uep->handler = &usbhsg_handler_recv_packet;
+ pipe->handler = &usbhs_fifo_dma_pop_handler;
ret = 0;
}
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ******************/
-
return ret;
}
static int usbhsg_ep_disable(struct usb_ep *ep)
{
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- spinlock_t *lock;
- unsigned long flags;
- int ret;
-
- /******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
-
- ret = usbhsg_pipe_disable(uep);
+ struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ******************/
+ if (!pipe)
+ return -EINVAL;
- return ret;
+ return usbhsg_pipe_disable(uep);
}
static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
@@ -905,7 +531,10 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
if (!ureq)
return NULL;
- INIT_LIST_HEAD(&ureq->node);
+ usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
+
+ ureq->req.dma = DMA_ADDR_INVALID;
+
return &ureq->req;
}
@@ -914,7 +543,7 @@ static void usbhsg_ep_free_request(struct usb_ep *ep,
{
struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
- WARN_ON(!list_empty(&ureq->node));
+ WARN_ON(!list_empty(&ureq->pkt.node));
kfree(ureq);
}
@@ -925,69 +554,27 @@ static int usbhsg_ep_queue(struct usb_ep *ep, struct usb_request *req,
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
- spinlock_t *lock;
- unsigned long flags;
- int ret = 0;
-
- /*
- * CAUTION [*endpoint queue*]
- *
- * This function will be called from usb_request :: complete
- * or usb driver timing.
- * If this function is called from usb_request :: complete,
- * it is already under spinlock on this driver.
- * but it is called frm usb driver, this function should call spinlock.
- *
- * This function is using usbshg_trylock to solve this issue.
- * if "is_locked" is 1, this mean this function lock it.
- * but if it is 0, this mean it is already under spin lock.
- * see also
- * CAUTION [*queue handler*]
- * CAUTION [*request complete*]
- */
-
- /******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
/* param check */
if (usbhsg_is_not_connected(gpriv) ||
unlikely(!gpriv->driver) ||
unlikely(!pipe))
- ret = -ESHUTDOWN;
- else
- usbhsg_queue_push(uep, ureq);
+ return -ESHUTDOWN;
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ******************/
+ usbhsg_queue_push(uep, ureq);
- usbhsg_queue_prepare(uep);
-
- return ret;
+ return 0;
}
static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
- struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- spinlock_t *lock;
- unsigned long flags;
-
- /*
- * see
- * CAUTION [*queue handler*]
- * CAUTION [*endpoint queue*]
- * CAUTION [*request complete*]
- */
-
- /******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
+ struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
usbhsg_queue_pop(uep, ureq, -ECONNRESET);
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ******************/
-
return 0;
}
@@ -996,42 +583,32 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+ struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
- spinlock_t *lock;
unsigned long flags;
- int ret = -EAGAIN;
-
- /*
- * see
- * CAUTION [*queue handler*]
- * CAUTION [*endpoint queue*]
- * CAUTION [*request complete*]
- */
- /******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
- if (!usbhsg_queue_get(uep)) {
+ usbhsg_pipe_disable(uep);
- dev_dbg(dev, "set halt %d (pipe %d)\n",
- halt, usbhs_pipe_number(pipe));
+ dev_dbg(dev, "set halt %d (pipe %d)\n",
+ halt, usbhs_pipe_number(pipe));
- if (halt)
- usbhs_fifo_stall(pipe);
- else
- usbhs_fifo_disable(pipe);
+ /******************** spin lock ********************/
+ usbhs_lock(priv, flags);
- if (halt && wedge)
- usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE);
- else
- usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE);
+ if (halt)
+ usbhs_pipe_stall(pipe);
+ else
+ usbhs_pipe_disable(pipe);
- ret = 0;
- }
+ if (halt && wedge)
+ usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE);
+ else
+ usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE);
- usbhsg_unlock(lock, &flags);
+ usbhs_unlock(priv, flags);
/******************** spin unlock ******************/
- return ret;
+ return 0;
}
static int usbhsg_ep_set_halt(struct usb_ep *ep, int value)
@@ -1067,28 +644,40 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
struct usbhs_mod *mod = usbhs_mod_get_current(priv);
struct device *dev = usbhs_priv_to_dev(priv);
- spinlock_t *lock;
unsigned long flags;
+ int ret = 0;
/******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
+ usbhs_lock(priv, flags);
- /*
- * enable interrupt and systems if ready
- */
usbhsg_status_set(gpriv, status);
if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) &&
usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)))
- goto usbhsg_try_start_unlock;
+ ret = -1; /* not ready */
+
+ usbhs_unlock(priv, flags);
+ /******************** spin unlock ********************/
+
+ if (ret < 0)
+ return 0; /* not ready is not error */
+ /*
+ * enable interrupt and systems if ready
+ */
dev_dbg(dev, "start gadget\n");
/*
* pipe initialize and enable DCP
*/
- usbhs_pipe_init(priv);
+ usbhs_pipe_init(priv,
+ usbhsg_dma_map_ctrl);
+ usbhs_fifo_init(priv);
usbhsg_uep_init(gpriv);
- usbhsg_dcp_enable(dcp);
+
+ /* dcp init */
+ dcp->pipe = usbhs_dcp_malloc(priv);
+ dcp->pipe->mod_private = dcp;
+ usbhs_pipe_config_update(dcp->pipe, 0, 0, 64);
/*
* system config enble
@@ -1105,16 +694,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
*/
mod->irq_dev_state = usbhsg_irq_dev_state;
mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage;
- mod->irq_empty = usbhsg_irq_empty;
- mod->irq_ready = usbhsg_irq_ready;
- mod->irq_bempsts = 0;
- mod->irq_brdysts = 0;
usbhs_irq_callback_update(priv, mod);
-usbhsg_try_start_unlock:
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ********************/
-
return 0;
}
@@ -1124,31 +705,33 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
struct usbhs_mod *mod = usbhs_mod_get_current(priv);
struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
struct device *dev = usbhs_priv_to_dev(priv);
- spinlock_t *lock;
unsigned long flags;
+ int ret = 0;
/******************** spin lock ********************/
- lock = usbhsg_trylock(gpriv, &flags);
+ usbhs_lock(priv, flags);
- /*
- * disable interrupt and systems if 1st try
- */
usbhsg_status_clr(gpriv, status);
if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) &&
!usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))
- goto usbhsg_try_stop_unlock;
+ ret = -1; /* already done */
+
+ usbhs_unlock(priv, flags);
+ /******************** spin unlock ********************/
+
+ if (ret < 0)
+ return 0; /* already done is not error */
+
+ /*
+ * disable interrupt and systems if 1st try
+ */
+ usbhs_fifo_quit(priv);
/* disable all irq */
mod->irq_dev_state = NULL;
mod->irq_ctrl_stage = NULL;
- mod->irq_empty = NULL;
- mod->irq_ready = NULL;
- mod->irq_bempsts = 0;
- mod->irq_brdysts = 0;
usbhs_irq_callback_update(priv, mod);
- usbhsg_dcp_disable(dcp);
-
gpriv->gadget.speed = USB_SPEED_UNKNOWN;
/* disable sys */
@@ -1156,21 +739,11 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
usbhs_sys_function_ctrl(priv, 0);
usbhs_sys_usb_ctrl(priv, 0);
- usbhsg_unlock(lock, &flags);
- /******************** spin unlock ********************/
-
- if (gpriv->driver &&
- gpriv->driver->disconnect)
- gpriv->driver->disconnect(&gpriv->gadget);
+ usbhsg_pipe_disable(dcp);
dev_dbg(dev, "stop gadget\n");
return 0;
-
-usbhsg_try_stop_unlock:
- usbhsg_unlock(lock, &flags);
-
- return 0;
}
/*
@@ -1178,89 +751,40 @@ usbhsg_try_stop_unlock:
* linux usb function
*
*/
-struct usbhsg_gpriv *the_controller;
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int usbhsg_gadget_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct usbhsg_gpriv *gpriv = the_controller;
- struct usbhs_priv *priv;
- struct device *dev;
- int ret;
+ struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+ struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
- if (!bind ||
- !driver ||
+ if (!driver ||
!driver->setup ||
- driver->speed != USB_SPEED_HIGH)
+ driver->speed < USB_SPEED_FULL)
return -EINVAL;
- if (!gpriv)
- return -ENODEV;
- if (gpriv->driver)
- return -EBUSY;
-
- dev = usbhsg_gpriv_to_dev(gpriv);
- priv = usbhsg_gpriv_to_priv(gpriv);
/* first hook up the driver ... */
gpriv->driver = driver;
gpriv->gadget.dev.driver = &driver->driver;
- ret = device_add(&gpriv->gadget.dev);
- if (ret) {
- dev_err(dev, "device_add error %d\n", ret);
- goto add_fail;
- }
-
- ret = bind(&gpriv->gadget);
- if (ret) {
- dev_err(dev, "bind to driver %s error %d\n",
- driver->driver.name, ret);
- goto bind_fail;
- }
-
- dev_dbg(dev, "bind %s\n", driver->driver.name);
-
return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD);
-
-bind_fail:
- device_del(&gpriv->gadget.dev);
-add_fail:
- gpriv->driver = NULL;
- gpriv->gadget.dev.driver = NULL;
-
- return ret;
}
-EXPORT_SYMBOL(usb_gadget_probe_driver);
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int usbhsg_gadget_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct usbhsg_gpriv *gpriv = the_controller;
- struct usbhs_priv *priv;
- struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-
- if (!gpriv)
- return -ENODEV;
+ struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+ struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
if (!driver ||
- !driver->unbind ||
- driver != gpriv->driver)
+ !driver->unbind)
return -EINVAL;
- dev = usbhsg_gpriv_to_dev(gpriv);
- priv = usbhsg_gpriv_to_priv(gpriv);
-
usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
- device_del(&gpriv->gadget.dev);
+ gpriv->gadget.dev.driver = NULL;
gpriv->driver = NULL;
- if (driver->disconnect)
- driver->disconnect(&gpriv->gadget);
-
- driver->unbind(&gpriv->gadget);
- dev_dbg(dev, "unbind %s\n", driver->driver.name);
-
return 0;
}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*
* usb gadget ops
@@ -1275,6 +799,8 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
static struct usb_gadget_ops usbhsg_gadget_ops = {
.get_frame = usbhsg_get_frame,
+ .udc_start = usbhsg_gadget_start,
+ .udc_stop = usbhsg_gadget_stop,
};
static int usbhsg_start(struct usbhs_priv *priv)
@@ -1284,16 +810,29 @@ static int usbhsg_start(struct usbhs_priv *priv)
static int usbhsg_stop(struct usbhs_priv *priv)
{
+ struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
+
+ /* cable disconnect */
+ if (gpriv->driver &&
+ gpriv->driver->disconnect)
+ gpriv->driver->disconnect(&gpriv->gadget);
+
return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
}
-int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
+static void usbhs_mod_gadget_release(struct device *pdev)
+{
+ /* do nothing */
+}
+
+int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
{
struct usbhsg_gpriv *gpriv;
struct usbhsg_uep *uep;
struct device *dev = usbhs_priv_to_dev(priv);
int pipe_size = usbhs_get_dparam(priv, pipe_size);
int i;
+ int ret;
gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL);
if (!gpriv) {
@@ -1304,6 +843,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL);
if (!uep) {
dev_err(dev, "Could not allocate ep\n");
+ ret = -ENOMEM;
goto usbhs_mod_gadget_probe_err_gpriv;
}
@@ -1331,12 +871,15 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
/*
* init gadget
*/
- device_initialize(&gpriv->gadget.dev);
dev_set_name(&gpriv->gadget.dev, "gadget");
gpriv->gadget.dev.parent = dev;
+ gpriv->gadget.dev.release = usbhs_mod_gadget_release;
gpriv->gadget.name = "renesas_usbhs_udc";
gpriv->gadget.ops = &usbhsg_gadget_ops;
gpriv->gadget.is_dualspeed = 1;
+ ret = device_register(&gpriv->gadget.dev);
+ if (ret < 0)
+ goto err_add_udc;
INIT_LIST_HEAD(&gpriv->gadget.ep_list);
@@ -1350,7 +893,6 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
uep->ep.name = uep->ep_name;
uep->ep.ops = &usbhsg_ep_ops;
INIT_LIST_HEAD(&uep->ep.ep_list);
- INIT_LIST_HEAD(&uep->list);
/* init DCP */
if (usbhsg_is_dcp(uep)) {
@@ -1364,22 +906,38 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
}
}
- the_controller = gpriv;
+ usbhsg_controller_register(gpriv);
+
+ ret = usb_add_gadget_udc(dev, &gpriv->gadget);
+ if (ret)
+ goto err_register;
+
dev_info(dev, "gadget probed\n");
return 0;
+err_register:
+ device_unregister(&gpriv->gadget.dev);
+err_add_udc:
+ kfree(gpriv->uep);
+
usbhs_mod_gadget_probe_err_gpriv:
kfree(gpriv);
- return -ENOMEM;
+ return ret;
}
-void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
+void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
{
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
+ usb_del_gadget_udc(&gpriv->gadget);
+
+ device_unregister(&gpriv->gadget.dev);
+
+ usbhsg_controller_unregister(gpriv);
+
kfree(gpriv->uep);
kfree(gpriv);
}
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index bc4521c..c74389c 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -15,7 +15,6 @@
*
*/
#include <linux/delay.h>
-#include <linux/io.h>
#include <linux/slab.h>
#include "./common.h"
#include "./pipe.h"
@@ -23,21 +22,13 @@
/*
* macros
*/
-#define usbhsp_priv_to_pipeinfo(pr) (&(pr)->pipe_info)
-#define usbhsp_pipe_to_priv(p) ((p)->priv)
-
#define usbhsp_addr_offset(p) ((usbhs_pipe_number(p) - 1) * 2)
-#define usbhsp_is_dcp(p) ((p)->priv->pipe_info.pipe == (p))
-
#define usbhsp_flags_set(p, f) ((p)->flags |= USBHS_PIPE_FLAGS_##f)
#define usbhsp_flags_clr(p, f) ((p)->flags &= ~USBHS_PIPE_FLAGS_##f)
#define usbhsp_flags_has(p, f) ((p)->flags & USBHS_PIPE_FLAGS_##f)
#define usbhsp_flags_init(p) do {(p)->flags = 0; } while (0)
-#define usbhsp_type(p) ((p)->pipe_type)
-#define usbhsp_type_is(p, t) ((p)->pipe_type == t)
-
/*
* for debug
*/
@@ -48,28 +39,9 @@ static char *usbhsp_pipe_name[] = {
[USB_ENDPOINT_XFER_ISOC] = "ISO",
};
-/*
- * usb request functions
- */
-void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
-{
- u16 val;
-
- val = usbhs_read(priv, USBREQ);
- req->bRequest = (val >> 8) & 0xFF;
- req->bRequestType = (val >> 0) & 0xFF;
-
- req->wValue = usbhs_read(priv, USBVAL);
- req->wIndex = usbhs_read(priv, USBINDX);
- req->wLength = usbhs_read(priv, USBLENG);
-}
-
-void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
+char *usbhs_pipe_name(struct usbhs_pipe *pipe)
{
- usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType);
- usbhs_write(priv, USBVAL, req->wValue);
- usbhs_write(priv, USBINDX, req->wIndex);
- usbhs_write(priv, USBLENG, req->wLength);
+ return usbhsp_pipe_name[usbhs_pipe_type(pipe)];
}
/*
@@ -77,10 +49,10 @@ void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
*/
static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
int offset = usbhsp_addr_offset(pipe);
- if (usbhsp_is_dcp(pipe))
+ if (usbhs_pipe_is_dcp(pipe))
usbhs_bset(priv, DCPCTR, mask, val);
else
usbhs_bset(priv, PIPEnCTR + offset, mask, val);
@@ -88,10 +60,10 @@ static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe)
{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
int offset = usbhsp_addr_offset(pipe);
- if (usbhsp_is_dcp(pipe))
+ if (usbhs_pipe_is_dcp(pipe))
return usbhs_read(priv, DCPCTR);
else
return usbhs_read(priv, PIPEnCTR + offset);
@@ -104,25 +76,14 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe,
u16 dcp_reg, u16 pipe_reg,
u16 mask, u16 val)
{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
- if (usbhsp_is_dcp(pipe))
+ if (usbhs_pipe_is_dcp(pipe))
usbhs_bset(priv, dcp_reg, mask, val);
else
usbhs_bset(priv, pipe_reg, mask, val);
}
-static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe,
- u16 dcp_reg, u16 pipe_reg)
-{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-
- if (usbhsp_is_dcp(pipe))
- return usbhs_read(priv, dcp_reg);
- else
- return usbhs_read(priv, pipe_reg);
-}
-
/*
* DCPCFG/PIPECFG functions
*/
@@ -136,7 +97,7 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
*/
static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
{
- if (usbhsp_is_dcp(pipe))
+ if (usbhs_pipe_is_dcp(pipe))
return;
__usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val);
@@ -150,17 +111,12 @@ static void usbhsp_pipe_maxp_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
__usbhsp_pipe_xxx_set(pipe, DCPMAXP, PIPEMAXP, mask, val);
}
-static u16 usbhsp_pipe_maxp_get(struct usbhs_pipe *pipe)
-{
- return __usbhsp_pipe_xxx_get(pipe, DCPMAXP, PIPEMAXP);
-}
-
/*
* pipe control functions
*/
static void usbhsp_pipe_select(struct usbhs_pipe *pipe)
{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
/*
* On pipe, this is necessary before
@@ -182,7 +138,7 @@ static void usbhsp_pipe_select(struct usbhs_pipe *pipe)
static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
int timeout = 1024;
u16 val;
@@ -205,7 +161,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
* - "Pipe Control Registers Switching Procedure"
*/
usbhs_write(priv, CFIFOSEL, 0);
- usbhs_fifo_disable(pipe);
+ usbhs_pipe_disable(pipe);
do {
val = usbhsp_pipectrl_get(pipe);
@@ -220,7 +176,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
return -EBUSY;
}
-static int usbhsp_pipe_is_accessible(struct usbhs_pipe *pipe)
+int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe)
{
u16 val;
@@ -253,7 +209,7 @@ static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe)
}
}
-void usbhs_fifo_disable(struct usbhs_pipe *pipe)
+void usbhs_pipe_disable(struct usbhs_pipe *pipe)
{
int timeout = 1024;
u16 val;
@@ -273,7 +229,7 @@ void usbhs_fifo_disable(struct usbhs_pipe *pipe)
} while (timeout--);
}
-void usbhs_fifo_enable(struct usbhs_pipe *pipe)
+void usbhs_pipe_enable(struct usbhs_pipe *pipe)
{
/* see "Pipe n Control Register" - "PID" */
__usbhsp_pid_try_nak_if_stall(pipe);
@@ -281,7 +237,7 @@ void usbhs_fifo_enable(struct usbhs_pipe *pipe)
usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF);
}
-void usbhs_fifo_stall(struct usbhs_pipe *pipe)
+void usbhs_pipe_stall(struct usbhs_pipe *pipe)
{
u16 pid = usbhsp_pipectrl_get(pipe);
@@ -302,191 +258,6 @@ void usbhs_fifo_stall(struct usbhs_pipe *pipe)
}
/*
- * CFIFO ctrl
- */
-void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe)
-{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-
- usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
-}
-
-static void usbhsp_fifo_clear(struct usbhs_pipe *pipe)
-{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-
- usbhs_write(priv, CFIFOCTR, BCLR);
-}
-
-static int usbhsp_fifo_barrier(struct usbhs_priv *priv)
-{
- int timeout = 1024;
-
- do {
- /* The FIFO port is accessible */
- if (usbhs_read(priv, CFIFOCTR) & FRDY)
- return 0;
-
- udelay(10);
- } while (timeout--);
-
- return -EBUSY;
-}
-
-static int usbhsp_fifo_rcv_len(struct usbhs_priv *priv)
-{
- return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
-}
-
-static int usbhsp_fifo_select(struct usbhs_pipe *pipe, int write)
-{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
- struct device *dev = usbhs_priv_to_dev(priv);
- int timeout = 1024;
- u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
- u16 base = usbhs_pipe_number(pipe); /* CURPIPE */
-
- if (usbhsp_is_dcp(pipe))
- base |= (1 == write) << 5; /* ISEL */
-
- /* "base" will be used below */
- usbhs_write(priv, CFIFOSEL, base | MBW_32);
-
- /* check ISEL and CURPIPE value */
- while (timeout--) {
- if (base == (mask & usbhs_read(priv, CFIFOSEL)))
- return 0;
- udelay(10);
- }
-
- dev_err(dev, "fifo select error\n");
-
- return -EIO;
-}
-
-int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
-{
- return usbhsp_fifo_select(pipe, 1);
-}
-
-int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len)
-{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
- void __iomem *addr = priv->base + CFIFO;
- int maxp = usbhs_pipe_get_maxpacket(pipe);
- int total_len;
- int i, ret;
-
- ret = usbhsp_pipe_is_accessible(pipe);
- if (ret < 0)
- return ret;
-
- ret = usbhsp_fifo_select(pipe, 1);
- if (ret < 0)
- return ret;
-
- ret = usbhsp_fifo_barrier(priv);
- if (ret < 0)
- return ret;
-
- len = min(len, maxp);
- total_len = len;
-
- /*
- * FIXME
- *
- * 32-bit access only
- */
- if (len >= 4 &&
- !((unsigned long)buf & 0x03)) {
- iowrite32_rep(addr, buf, len / 4);
- len %= 4;
- buf += total_len - len;
- }
-
- /* the rest operation */
- for (i = 0; i < len; i++)
- iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
-
- if (total_len < maxp)
- usbhs_fifo_send_terminator(pipe);
-
- return total_len;
-}
-
-int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
-{
- int ret;
-
- /*
- * select pipe and enable it to prepare packet receive
- */
- ret = usbhsp_fifo_select(pipe, 0);
- if (ret < 0)
- return ret;
-
- usbhs_fifo_enable(pipe);
-
- return ret;
-}
-
-int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len)
-{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
- void __iomem *addr = priv->base + CFIFO;
- int rcv_len;
- int i, ret;
- int total_len;
- u32 data = 0;
-
- ret = usbhsp_fifo_select(pipe, 0);
- if (ret < 0)
- return ret;
-
- ret = usbhsp_fifo_barrier(priv);
- if (ret < 0)
- return ret;
-
- rcv_len = usbhsp_fifo_rcv_len(priv);
-
- /*
- * Buffer clear if Zero-Length packet
- *
- * see
- * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
- */
- if (0 == rcv_len) {
- usbhsp_fifo_clear(pipe);
- return 0;
- }
-
- len = min(rcv_len, len);
- total_len = len;
-
- /*
- * FIXME
- *
- * 32-bit access only
- */
- if (len >= 4 &&
- !((unsigned long)buf & 0x03)) {
- ioread32_rep(addr, buf, len / 4);
- len %= 4;
- buf += rcv_len - len;
- }
-
- /* the rest operation */
- for (i = 0; i < len; i++) {
- if (!(i & 0x03))
- data = ioread32(addr);
-
- buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
- }
-
- return total_len;
-}
-
-/*
* pipe setup
*/
static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe)
@@ -494,16 +265,16 @@ static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe)
/*
* only ISO / BULK pipe can use double buffer
*/
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) ||
- usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) ||
+ usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
return 1;
return 0;
}
static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
- const struct usb_endpoint_descriptor *desc,
- int is_host)
+ int is_host,
+ int dir_in)
{
u16 type = 0;
u16 bfre = 0;
@@ -519,7 +290,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
};
int is_double = usbhsp_possible_double_buffer(pipe);
- if (usbhsp_is_dcp(pipe))
+ if (usbhs_pipe_is_dcp(pipe))
return -EINVAL;
/*
@@ -532,37 +303,40 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
*/
/* TYPE */
- type = type_array[usbhsp_type(pipe)];
+ type = type_array[usbhs_pipe_type(pipe)];
/* BFRE */
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
- usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK))
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
+ usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
bfre = 0; /* FIXME */
/* DBLB */
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
- usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK))
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
+ usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
dblb = (is_double) ? DBLB : 0;
/* CNTMD */
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK))
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
cntmd = 0; /* FIXME */
/* DIR */
- if (usb_endpoint_dir_in(desc))
- usbhsp_flags_set(pipe, IS_DIR_IN);
+ if (dir_in)
+ usbhsp_flags_set(pipe, IS_DIR_HOST);
- if ((is_host && usb_endpoint_dir_out(desc)) ||
- (!is_host && usb_endpoint_dir_in(desc)))
+ if ((is_host && !dir_in) ||
+ (!is_host && dir_in))
dir |= DIR_OUT;
+ if (!dir)
+ usbhsp_flags_set(pipe, IS_DIR_IN);
+
/* SHTNAK */
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) &&
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) &&
!dir)
shtnak = SHTNAK;
/* EPNUM */
- epnum = 0xF & usb_endpoint_num(desc);
+ epnum = 0; /* see usbhs_pipe_config_update() */
return type |
bfre |
@@ -573,22 +347,10 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
epnum;
}
-static u16 usbhsp_setup_pipemaxp(struct usbhs_pipe *pipe,
- const struct usb_endpoint_descriptor *desc,
- int is_host)
-{
- /* host should set DEVSEL */
-
- /* reutn MXPS */
- return PIPE_MAXP_MASK & le16_to_cpu(desc->wMaxPacketSize);
-}
-
-static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe,
- const struct usb_endpoint_descriptor *desc,
- int is_host)
+static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe)
{
- struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
- struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+ struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
struct device *dev = usbhs_priv_to_dev(priv);
int pipe_num = usbhs_pipe_number(pipe);
int is_double = usbhsp_possible_double_buffer(pipe);
@@ -629,9 +391,9 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe,
* INT : 64 byte
* ISOC: 512 byte
*/
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_CONTROL))
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_CONTROL))
buff_size = 256;
- else if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT))
+ else if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT))
buff_size = 64;
else
buff_size = 512;
@@ -641,7 +403,7 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe,
/* BUFNMB has been reserved for INT pipe
* see above */
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) {
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) {
bufnmb = pipe_num - 2;
} else {
bufnmb = info->bufnmb_last;
@@ -661,16 +423,42 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe,
(0xff & bufnmb) << 0;
}
+void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
+ u16 epnum, u16 maxp)
+{
+ if (devsel > 0xA) {
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+ struct device *dev = usbhs_priv_to_dev(priv);
+
+ dev_err(dev, "devsel error %d\n", devsel);
+
+ devsel = 0;
+ }
+
+ usbhsp_pipe_barrier(pipe);
+
+ pipe->maxp = maxp;
+
+ usbhsp_pipe_select(pipe);
+ usbhsp_pipe_maxp_set(pipe, 0xFFFF,
+ (devsel << 12) |
+ maxp);
+
+ if (!usbhs_pipe_is_dcp(pipe))
+ usbhsp_pipe_cfg_set(pipe, 0x000F, epnum);
+}
+
/*
* pipe control
*/
int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe)
{
- u16 mask = usbhsp_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK;
-
- usbhsp_pipe_select(pipe);
-
- return (int)(usbhsp_pipe_maxp_get(pipe) & mask);
+ /*
+ * see
+ * usbhs_pipe_config_update()
+ * usbhs_dcp_malloc()
+ */
+ return pipe->maxp;
}
int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe)
@@ -678,9 +466,23 @@ int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe)
return usbhsp_flags_has(pipe, IS_DIR_IN);
}
-void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe)
+int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
{
- usbhsp_pipectrl_set(pipe, SQCLR, SQCLR);
+ return usbhsp_flags_has(pipe, IS_DIR_HOST);
+}
+
+void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int data)
+{
+ u16 mask = (SQCLR | SQSET);
+ u16 val = (data) ? SQSET : SQCLR;
+
+ usbhsp_pipectrl_set(pipe, mask, val);
+}
+
+void usbhs_pipe_clear(struct usbhs_pipe *pipe)
+{
+ usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
+ usbhsp_pipectrl_set(pipe, ACLRM, 0);
}
static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
@@ -693,7 +495,7 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
*/
pipe = NULL;
usbhs_for_each_pipe_with_dcp(pos, priv, i) {
- if (!usbhsp_type_is(pos, type))
+ if (!usbhs_pipe_type_is(pos, type))
continue;
if (usbhsp_flags_has(pos, IS_USED))
continue;
@@ -714,9 +516,10 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
return pipe;
}
-void usbhs_pipe_init(struct usbhs_priv *priv)
+void usbhs_pipe_init(struct usbhs_priv *priv,
+ int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
{
- struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+ struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
struct usbhs_pipe *pipe;
int i;
@@ -734,34 +537,41 @@ void usbhs_pipe_init(struct usbhs_priv *priv)
*/
info->bufnmb_last = 4;
usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
- if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT))
+ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT))
info->bufnmb_last++;
usbhsp_flags_init(pipe);
+ pipe->fifo = NULL;
pipe->mod_private = NULL;
+ INIT_LIST_HEAD(&pipe->list);
- usbhsp_fifo_clear(pipe);
+ /* pipe force init */
+ usbhs_pipe_clear(pipe);
}
+
+ info->dma_map_ctrl = dma_map_ctrl;
}
struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
- const struct usb_endpoint_descriptor *desc)
+ int endpoint_type,
+ int dir_in)
{
struct device *dev = usbhs_priv_to_dev(priv);
- struct usbhs_mod *mod = usbhs_mod_get_current(priv);
struct usbhs_pipe *pipe;
- int is_host = usbhs_mod_is_host(priv, mod);
+ int is_host = usbhs_mod_is_host(priv);
int ret;
- u16 pipecfg, pipebuf, pipemaxp;
+ u16 pipecfg, pipebuf;
- pipe = usbhsp_get_pipe(priv, usb_endpoint_type(desc));
+ pipe = usbhsp_get_pipe(priv, endpoint_type);
if (!pipe) {
dev_err(dev, "can't get pipe (%s)\n",
- usbhsp_pipe_name[usb_endpoint_type(desc)]);
+ usbhsp_pipe_name[endpoint_type]);
return NULL;
}
- usbhs_fifo_disable(pipe);
+ INIT_LIST_HEAD(&pipe->list);
+
+ usbhs_pipe_disable(pipe);
/* make sure pipe is not busy */
ret = usbhsp_pipe_barrier(pipe);
@@ -770,30 +580,40 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
return NULL;
}
- pipecfg = usbhsp_setup_pipecfg(pipe, desc, is_host);
- pipebuf = usbhsp_setup_pipebuff(pipe, desc, is_host);
- pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host);
-
- /* buffer clear
- * see PIPECFG :: BFRE */
- usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
- usbhsp_pipectrl_set(pipe, ACLRM, 0);
+ pipecfg = usbhsp_setup_pipecfg(pipe, is_host, dir_in);
+ pipebuf = usbhsp_setup_pipebuff(pipe);
usbhsp_pipe_select(pipe);
usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg);
usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf);
- usbhsp_pipe_maxp_set(pipe, 0xFFFF, pipemaxp);
- usbhs_pipe_clear_sequence(pipe);
+ usbhs_pipe_sequence_data0(pipe);
dev_dbg(dev, "enable pipe %d : %s (%s)\n",
usbhs_pipe_number(pipe),
- usbhsp_pipe_name[usb_endpoint_type(desc)],
+ usbhs_pipe_name(pipe),
usbhs_pipe_is_dir_in(pipe) ? "in" : "out");
+ /*
+ * epnum / maxp are still not set to this pipe.
+ * call usbhs_pipe_config_update() after this function !!
+ */
+
return pipe;
}
+void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
+{
+ if (pipe->fifo)
+ pipe->fifo->pipe = NULL;
+
+ pipe->fifo = fifo;
+
+ if (fifo)
+ fifo->pipe = pipe;
+}
+
+
/*
* dcp control
*/
@@ -805,33 +625,39 @@ struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv)
if (!pipe)
return NULL;
+ INIT_LIST_HEAD(&pipe->list);
+
/*
- * dcpcfg : default
- * dcpmaxp : default
- * pipebuf : nothing to do
+ * call usbhs_pipe_config_update() after this function !!
*/
- usbhsp_pipe_select(pipe);
- usbhs_pipe_clear_sequence(pipe);
-
return pipe;
}
void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe)
{
- WARN_ON(!usbhsp_is_dcp(pipe));
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
- usbhs_fifo_enable(pipe);
- usbhsp_pipectrl_set(pipe, CCPL, CCPL);
+ WARN_ON(!usbhs_pipe_is_dcp(pipe));
+
+ usbhs_pipe_enable(pipe);
+
+ if (!usbhs_mod_is_host(priv)) /* funconly */
+ usbhsp_pipectrl_set(pipe, CCPL, CCPL);
}
+void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out)
+{
+ usbhsp_pipe_cfg_set(pipe, DIR_OUT,
+ dir_out ? DIR_OUT : 0);
+}
/*
* pipe module function
*/
int usbhs_pipe_probe(struct usbhs_priv *priv)
{
- struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+ struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
struct usbhs_pipe *pipe;
struct device *dev = usbhs_priv_to_dev(priv);
u32 *pipe_type = usbhs_get_dparam(priv, pipe_type);
@@ -857,7 +683,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv)
*/
usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
pipe->priv = priv;
- usbhsp_type(pipe) = pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK;
+
+ usbhs_pipe_type(pipe) =
+ pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK;
dev_dbg(dev, "pipe %x\t: %s\n",
i, usbhsp_pipe_name[pipe_type[i]]);
@@ -868,7 +696,7 @@ int usbhs_pipe_probe(struct usbhs_priv *priv)
void usbhs_pipe_remove(struct usbhs_priv *priv)
{
- struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+ struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
kfree(info->pipe);
}
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 1cca9b7..6334fc6 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -18,6 +18,7 @@
#define RENESAS_USB_PIPE_H
#include "./common.h"
+#include "./fifo.h"
/*
* struct
@@ -26,10 +27,17 @@ struct usbhs_pipe {
u32 pipe_type; /* USB_ENDPOINT_XFER_xxx */
struct usbhs_priv *priv;
+ struct usbhs_fifo *fifo;
+ struct list_head list;
+
+ int maxp;
u32 flags;
#define USBHS_PIPE_FLAGS_IS_USED (1 << 0)
#define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1)
+#define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2)
+
+ struct usbhs_pkt_handle *handler;
void *mod_private;
};
@@ -38,6 +46,8 @@ struct usbhs_pipe_info {
struct usbhs_pipe *pipe;
int size; /* array size of "pipe" */
int bufnmb_last; /* FIXME : driver needs good allocator */
+
+ int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map);
};
/*
@@ -55,50 +65,50 @@ struct usbhs_pipe_info {
__usbhs_for_each_pipe(0, pos, &((priv)->pipe_info), i)
/*
- * pipe module probe / remove
+ * data
*/
-int usbhs_pipe_probe(struct usbhs_priv *priv);
-void usbhs_pipe_remove(struct usbhs_priv *priv);
-
-/*
- * cfifo
- */
-int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len);
-int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len);
-int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe);
-int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe);
-
-void usbhs_fifo_enable(struct usbhs_pipe *pipe);
-void usbhs_fifo_disable(struct usbhs_pipe *pipe);
-void usbhs_fifo_stall(struct usbhs_pipe *pipe);
-
-void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe);
-
-
-/*
- * usb request
- */
-void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req);
-void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req);
+#define usbhs_priv_to_pipeinfo(pr) (&(pr)->pipe_info)
/*
* pipe control
*/
+char *usbhs_pipe_name(struct usbhs_pipe *pipe);
struct usbhs_pipe
-*usbhs_pipe_malloc(struct usbhs_priv *priv,
- const struct usb_endpoint_descriptor *desc);
-
+*usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in);
+int usbhs_pipe_probe(struct usbhs_priv *priv);
+void usbhs_pipe_remove(struct usbhs_priv *priv);
int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
-void usbhs_pipe_init(struct usbhs_priv *priv);
+int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe);
+void usbhs_pipe_init(struct usbhs_priv *priv,
+ int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
-void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe);
-
+void usbhs_pipe_clear(struct usbhs_pipe *pipe);
+int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe);
+void usbhs_pipe_enable(struct usbhs_pipe *pipe);
+void usbhs_pipe_disable(struct usbhs_pipe *pipe);
+void usbhs_pipe_stall(struct usbhs_pipe *pipe);
+void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
+void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
+ u16 epnum, u16 maxp);
+
+#define usbhs_pipe_sequence_data0(pipe) usbhs_pipe_data_sequence(pipe, 0)
+#define usbhs_pipe_sequence_data1(pipe) usbhs_pipe_data_sequence(pipe, 1)
+void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int data);
+
+#define usbhs_pipe_to_priv(p) ((p)->priv)
#define usbhs_pipe_number(p) (int)((p) - (p)->priv->pipe_info.pipe)
+#define usbhs_pipe_is_dcp(p) ((p)->priv->pipe_info.pipe == (p))
+#define usbhs_pipe_to_fifo(p) ((p)->fifo)
+#define usbhs_pipe_is_busy(p) usbhs_pipe_to_fifo(p)
+
+#define usbhs_pipe_type(p) ((p)->pipe_type)
+#define usbhs_pipe_type_is(p, t) ((p)->pipe_type == t)
/*
* dcp control
*/
struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv);
void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe);
+void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out);
#endif /* RENESAS_USB_PIPE_H */
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index c0c5665..200fd7c 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -298,7 +298,7 @@ static int cbaf_cdid_get(struct cbaf *cbaf)
if (result < needed) {
dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs "
"%zu bytes needed)\n", (size_t)result, needed);
- return result;
+ return -ENOENT;
}
strlcpy(cbaf->device_name, di->DeviceFriendlyName, CBA_NAME_LEN);
@@ -350,7 +350,7 @@ static ssize_t cbaf_wusb_chid_store(struct device *dev,
return result;
result = cbaf_cdid_get(cbaf);
if (result < 0)
- return -result;
+ return result;
return size;
}
static DEVICE_ATTR(wusb_chid, 0600, cbaf_wusb_chid_show, cbaf_wusb_chid_store);
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 7ec24e4..231009a 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -90,6 +90,7 @@
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/export.h>
#include "wusbhc.h"
static void wusbhc_devconnect_acked_work(struct work_struct *work);
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c
index 0a57ff0..b8c7258 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -38,6 +38,7 @@
*/
#include <linux/usb/wusb.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "wusbhc.h"
/* Initialize the MMCIEs handling mechanism */
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c
index 39de390..59ff254 100644
--- a/drivers/usb/wusbcore/rh.c
+++ b/drivers/usb/wusbcore/rh.c
@@ -70,6 +70,7 @@
* wusbhc_rh_start_port_reset() ??? unimplemented
*/
#include <linux/slab.h>
+#include <linux/export.h>
#include "wusbhc.h"
/*
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c
index b60799b..371f617 100644
--- a/drivers/usb/wusbcore/security.c
+++ b/drivers/usb/wusbcore/security.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/usb/ch9.h>
#include <linux/random.h>
+#include <linux/export.h>
#include "wusbhc.h"
static void wusbhc_set_gtk_callback(struct urb *urb);
diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index 59a748a..9e4a924 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -23,6 +23,7 @@
* FIXME: docs
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include "wusbhc.h"
#include "wa-hc.h"
@@ -43,7 +44,7 @@ int wa_create(struct wahc *wa, struct usb_interface *iface)
/* Fill up Data Transfer EP pointers */
wa->dti_epd = &iface->cur_altsetting->endpoint[1].desc;
wa->dto_epd = &iface->cur_altsetting->endpoint[2].desc;
- wa->xfer_result_size = le16_to_cpu(wa->dti_epd->wMaxPacketSize);
+ wa->xfer_result_size = usb_endpoint_maxp(wa->dti_epd);
wa->xfer_result = kmalloc(wa->xfer_result_size, GFP_KERNEL);
if (wa->xfer_result == NULL)
goto error_xfer_result_alloc;
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index ca80171..ca1031b 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -58,9 +58,10 @@
* destination address.
*/
#include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "wusbhc.h"
#include "wa-hc.h"
@@ -331,7 +332,10 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa,
/* FIXME: compute so seg_size > ep->maxpktsize */
rpipe->descr.wBlocks = cpu_to_le16(16); /* given */
/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
- rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize);
+ if (usb_endpoint_xfer_isoc(&ep->desc))
+ rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize;
+ else
+ rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize;
rpipe->descr.bHSHubAddress = 0; /* reserved: zero */
rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum);
/* FIXME: use maximum speed as supported or recommended by device */
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6ccd93a..5f6df6e 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -83,12 +83,15 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/hash.h>
+#include <linux/ratelimit.h>
+#include <linux/export.h>
#include "wa-hc.h"
#include "wusbhc.h"
enum {
- WA_SEGS_MAX = 255,
+ /* [WUSB] section 8.3.3 allocates 7 bits for the segment index. */
+ WA_SEGS_MAX = 128,
};
enum wa_seg_status {
@@ -442,7 +445,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize;
xfer->segs = (urb->transfer_buffer_length + xfer->seg_size - 1)
/ xfer->seg_size;
- if (xfer->segs >= WA_SEGS_MAX) {
+ if (xfer->segs > WA_SEGS_MAX) {
dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n",
(int)(urb->transfer_buffer_length / xfer->seg_size),
WA_SEGS_MAX);
@@ -1217,16 +1220,14 @@ static int wa_xfer_status_to_errno(u8 status)
if (status == 0)
return 0;
if (status >= ARRAY_SIZE(xlat)) {
- if (printk_ratelimit())
- printk(KERN_ERR "%s(): BUG? "
+ printk_ratelimited(KERN_ERR "%s(): BUG? "
"Unknown WA transfer status 0x%02x\n",
__func__, real_status);
return -EINVAL;
}
errno = xlat[status];
if (unlikely(errno > 0)) {
- if (printk_ratelimit())
- printk(KERN_ERR "%s(): BUG? "
+ printk_ratelimited(KERN_ERR "%s(): BUG? "
"Inconsistent WA status: 0x%02x\n",
__func__, real_status);
errno = -errno;
diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c
index a2eaa3c..de81ebf 100644
--- a/drivers/uwb/est.c
+++ b/drivers/uwb/est.c
@@ -41,6 +41,7 @@
*/
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/i1480/dfu/dfu.c b/drivers/uwb/i1480/dfu/dfu.c
index da7b1d0..b08d1c2 100644
--- a/drivers/uwb/i1480/dfu/dfu.c
+++ b/drivers/uwb/i1480/dfu/dfu.c
@@ -33,6 +33,7 @@
#include <linux/device.h>
#include <linux/uwb.h>
#include <linux/random.h>
+#include <linux/export.h>
/*
* i1480_rceb_check - Check RCEB for expected field values
diff --git a/drivers/uwb/ie.c b/drivers/uwb/ie.c
index 30acec7..902b0f2 100644
--- a/drivers/uwb/ie.c
+++ b/drivers/uwb/ie.c
@@ -25,6 +25,7 @@
*/
#include <linux/slab.h>
+#include <linux/export.h>
#include "uwb-internal.h"
/**
diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c
index 90113ba..3c9e929 100644
--- a/drivers/uwb/lc-dev.c
+++ b/drivers/uwb/lc-dev.c
@@ -25,9 +25,11 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
+#include <linux/export.h>
#include <linux/err.h>
#include <linux/kdev_t.h>
#include <linux/random.h>
+#include <linux/stat.h>
#include "uwb-internal.h"
/* We initialize addresses to 0xff (invalid, as it is bcast) */
@@ -439,16 +441,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce)
uwb_dev->mac_addr = *bce->mac_addr;
uwb_dev->dev_addr = bce->dev_addr;
dev_set_name(&uwb_dev->dev, macbuf);
+
+ /* plug the beacon cache */
+ bce->uwb_dev = uwb_dev;
+ uwb_dev->bce = bce;
+ uwb_bce_get(bce); /* released in uwb_dev_sys_release() */
+
result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc);
if (result < 0) {
dev_err(dev, "new device %s: cannot instantiate device\n",
macbuf);
goto error_dev_add;
}
- /* plug the beacon cache */
- bce->uwb_dev = uwb_dev;
- uwb_dev->bce = bce;
- uwb_bce_get(bce); /* released in uwb_dev_sys_release() */
+
dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n",
macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name,
dev_name(rc->uwb_dev.dev.parent));
@@ -456,6 +461,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce)
return;
error_dev_add:
+ bce->uwb_dev = NULL;
+ uwb_bce_put(bce);
kfree(uwb_dev);
return;
}
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c
index b4395f4..4d688c7 100644
--- a/drivers/uwb/lc-rc.c
+++ b/drivers/uwb/lc-rc.c
@@ -36,6 +36,7 @@
#include <linux/etherdevice.h>
#include <linux/usb.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c
index 47146c8..8cb71bb 100644
--- a/drivers/uwb/neh.c
+++ b/drivers/uwb/neh.c
@@ -85,6 +85,7 @@
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c
index 99a19c1..8ee7d90 100644
--- a/drivers/uwb/pal.c
+++ b/drivers/uwb/pal.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/uwb.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c
index f0d5549..d58dfec 100644
--- a/drivers/uwb/radio.c
+++ b/drivers/uwb/radio.c
@@ -17,6 +17,7 @@
*/
#include <linux/kernel.h>
#include <linux/uwb.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c
index 3de630b..7032285 100644
--- a/drivers/uwb/reset.c
+++ b/drivers/uwb/reset.c
@@ -32,6 +32,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index 78c8922..0b0d8bc 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -19,6 +19,7 @@
#include <linux/uwb.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/export.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/scan.c b/drivers/uwb/scan.c
index 367aa12..cbb6a5e 100644
--- a/drivers/uwb/scan.c
+++ b/drivers/uwb/scan.c
@@ -36,6 +36,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include "uwb-internal.h"
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index 5fad4e7..82a84d5 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
+#include <linux/module.h>
#include <linux/uwb/umc.h>
#include <linux/pci.h>
diff --git a/drivers/uwb/umc-dev.c b/drivers/uwb/umc-dev.c
index b2948ec..4613c13 100644
--- a/drivers/uwb/umc-dev.c
+++ b/drivers/uwb/umc-dev.c
@@ -6,6 +6,7 @@
* This file is released under the GNU GPL v2.
*/
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/uwb/umc.h>
diff --git a/drivers/uwb/umc-drv.c b/drivers/uwb/umc-drv.c
index 367b5eb..26d0ae1 100644
--- a/drivers/uwb/umc-drv.c
+++ b/drivers/uwb/umc-drv.c
@@ -6,6 +6,7 @@
* This file is released under the GNU GPL v2.
*/
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/uwb/umc.h>
int __umc_driver_register(struct umc_driver *umc_drv, struct module *module,
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h
index 157485c..a7494bf 100644
--- a/drivers/uwb/uwb-internal.h
+++ b/drivers/uwb/uwb-internal.h
@@ -28,7 +28,6 @@
#ifndef __UWB_INTERNAL_H__
#define __UWB_INTERNAL_H__
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/uwb.h>
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c
index 001c8b4..bdcb13c 100644
--- a/drivers/uwb/uwbd.c
+++ b/drivers/uwb/uwbd.c
@@ -256,7 +256,7 @@ static void uwbd_event_handle(struct uwb_event *evt)
* UWB Daemon
*
* Listens to all UWB notifications and takes care to track the state
- * of the UWB neighboorhood for the kernel. When we do a run, we
+ * of the UWB neighbourhood for the kernel. When we do a run, we
* spinlock, move the list to a private copy and release the
* lock. Hold it as little as possible. Not a conflict: it is
* guaranteed we own the events in the private list.
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c
index 70a004a..3ae3c70 100644
--- a/drivers/uwb/whc-rc.c
+++ b/drivers/uwb/whc-rc.c
@@ -222,7 +222,7 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc)
struct umc_dev *umc_dev = whcrc->umc_dev;
whcrc->area = umc_dev->resource.start;
- whcrc->rc_len = umc_dev->resource.end - umc_dev->resource.start + 1;
+ whcrc->rc_len = resource_size(&umc_dev->resource);
result = -EBUSY;
if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) == NULL) {
dev_err(dev, "can't request URC region (%zu bytes @ 0x%lx): %d\n",
diff --git a/drivers/uwb/whci.c b/drivers/uwb/whci.c
index b221142..f48093e 100644
--- a/drivers/uwb/whci.c
+++ b/drivers/uwb/whci.c
@@ -7,6 +7,7 @@
*/
#include <linux/delay.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index f274826..7ef84c1 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -12,6 +12,7 @@
#include <linux/virtio_net.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/rcupdate.h>
@@ -28,10 +29,18 @@
#include "vhost.h"
+static int experimental_zcopytx;
+module_param(experimental_zcopytx, int, 0444);
+MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
+
/* Max number of bytes transferred before requeueing the job.
* Using this limit prevents one virtqueue from starving others. */
#define VHOST_NET_WEIGHT 0x80000
+/* MAX number of TX used buffers for outstanding zerocopy */
+#define VHOST_MAX_PEND 128
+#define VHOST_GOODCOPY_LEN 256
+
enum {
VHOST_NET_VQ_RX = 0,
VHOST_NET_VQ_TX = 1,
@@ -54,6 +63,12 @@ struct vhost_net {
enum vhost_net_poll_state tx_poll_state;
};
+static bool vhost_sock_zcopy(struct socket *sock)
+{
+ return unlikely(experimental_zcopytx) &&
+ sock_flag(sock->sk, SOCK_ZEROCOPY);
+}
+
/* Pop first len bytes from iovec. Return number of segments used. */
static int move_iovec_hdr(struct iovec *from, struct iovec *to,
size_t len, int iov_count)
@@ -129,6 +144,8 @@ static void handle_tx(struct vhost_net *net)
int err, wmem;
size_t hdr_size;
struct socket *sock;
+ struct vhost_ubuf_ref *uninitialized_var(ubufs);
+ bool zcopy;
/* TODO: check that we are running from vhost_worker? */
sock = rcu_dereference_check(vq->private_data, 1);
@@ -149,8 +166,13 @@ static void handle_tx(struct vhost_net *net)
if (wmem < sock->sk->sk_sndbuf / 2)
tx_poll_stop(net);
hdr_size = vq->vhost_hlen;
+ zcopy = vhost_sock_zcopy(sock);
for (;;) {
+ /* Release DMAs done buffers first */
+ if (zcopy)
+ vhost_zerocopy_signal_used(vq);
+
head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
ARRAY_SIZE(vq->iov),
&out, &in,
@@ -160,12 +182,25 @@ static void handle_tx(struct vhost_net *net)
break;
/* Nothing new? Wait for eventfd to tell us they refilled. */
if (head == vq->num) {
+ int num_pends;
+
wmem = atomic_read(&sock->sk->sk_wmem_alloc);
if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
tx_poll_start(net, sock);
set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
break;
}
+ /* If more outstanding DMAs, queue the work.
+ * Handle upend_idx wrap around
+ */
+ num_pends = likely(vq->upend_idx >= vq->done_idx) ?
+ (vq->upend_idx - vq->done_idx) :
+ (vq->upend_idx + UIO_MAXIOV - vq->done_idx);
+ if (unlikely(num_pends > VHOST_MAX_PEND)) {
+ tx_poll_start(net, sock);
+ set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+ break;
+ }
if (unlikely(vhost_enable_notify(&net->dev, vq))) {
vhost_disable_notify(&net->dev, vq);
continue;
@@ -188,9 +223,40 @@ static void handle_tx(struct vhost_net *net)
iov_length(vq->hdr, s), hdr_size);
break;
}
+ /* use msg_control to pass vhost zerocopy ubuf info to skb */
+ if (zcopy) {
+ vq->heads[vq->upend_idx].id = head;
+ if (len < VHOST_GOODCOPY_LEN) {
+ /* copy don't need to wait for DMA done */
+ vq->heads[vq->upend_idx].len =
+ VHOST_DMA_DONE_LEN;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ ubufs = NULL;
+ } else {
+ struct ubuf_info *ubuf;
+ ubuf = vq->ubuf_info + vq->upend_idx;
+
+ vq->heads[vq->upend_idx].len = len;
+ ubuf->callback = vhost_zerocopy_callback;
+ ubuf->arg = vq->ubufs;
+ ubuf->desc = vq->upend_idx;
+ msg.msg_control = ubuf;
+ msg.msg_controllen = sizeof(ubuf);
+ ubufs = vq->ubufs;
+ kref_get(&ubufs->kref);
+ }
+ vq->upend_idx = (vq->upend_idx + 1) % UIO_MAXIOV;
+ }
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
+ if (zcopy) {
+ if (ubufs)
+ vhost_ubuf_put(ubufs);
+ vq->upend_idx = ((unsigned)vq->upend_idx - 1) %
+ UIO_MAXIOV;
+ }
vhost_discard_vq_desc(vq, 1);
tx_poll_start(net, sock);
break;
@@ -198,7 +264,8 @@ static void handle_tx(struct vhost_net *net)
if (err != len)
pr_debug("Truncated TX packet: "
" len %d != %zd\n", err, len);
- vhost_add_used_and_signal(&net->dev, vq, head, 0);
+ if (!zcopy)
+ vhost_add_used_and_signal(&net->dev, vq, head, 0);
total_len += len;
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
@@ -252,9 +319,13 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
r = -ENOBUFS;
goto err;
}
- d = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
+ r = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
ARRAY_SIZE(vq->iov) - seg, &out,
&in, log, log_num);
+ if (unlikely(r < 0))
+ goto err;
+
+ d = r;
if (d == vq->num) {
r = 0;
goto err;
@@ -279,6 +350,12 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
*iovcount = seg;
if (unlikely(log))
*log_num = nlogs;
+
+ /* Detect overrun */
+ if (unlikely(datalen > 0)) {
+ r = UIO_MAXIOV + 1;
+ goto err;
+ }
return headcount;
err:
vhost_discard_vq_desc(vq, headcount);
@@ -333,6 +410,14 @@ static void handle_rx(struct vhost_net *net)
/* On error, stop handling until the next kick. */
if (unlikely(headcount < 0))
break;
+ /* On overrun, truncate and discard */
+ if (unlikely(headcount > UIO_MAXIOV)) {
+ msg.msg_iovlen = 1;
+ err = sock->ops->recvmsg(NULL, sock, &msg,
+ 1, MSG_DONTWAIT | MSG_TRUNC);
+ pr_debug("Discarded rx packet: len %zd\n", sock_len);
+ continue;
+ }
/* OK, now we need to know about added descriptors. */
if (!headcount) {
if (unlikely(vhost_enable_notify(&net->dev, vq))) {
@@ -604,6 +689,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
{
struct socket *sock, *oldsock;
struct vhost_virtqueue *vq;
+ struct vhost_ubuf_ref *ubufs, *oldubufs = NULL;
int r;
mutex_lock(&n->dev.mutex);
@@ -633,13 +719,31 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
oldsock = rcu_dereference_protected(vq->private_data,
lockdep_is_held(&vq->mutex));
if (sock != oldsock) {
+ ubufs = vhost_ubuf_alloc(vq, sock && vhost_sock_zcopy(sock));
+ if (IS_ERR(ubufs)) {
+ r = PTR_ERR(ubufs);
+ goto err_ubufs;
+ }
+ oldubufs = vq->ubufs;
+ vq->ubufs = ubufs;
vhost_net_disable_vq(n, vq);
rcu_assign_pointer(vq->private_data, sock);
vhost_net_enable_vq(n, vq);
+
+ r = vhost_init_used(vq);
+ if (r)
+ goto err_vq;
}
mutex_unlock(&vq->mutex);
+ if (oldubufs) {
+ vhost_ubuf_put_and_wait(oldubufs);
+ mutex_lock(&vq->mutex);
+ vhost_zerocopy_signal_used(vq);
+ mutex_unlock(&vq->mutex);
+ }
+
if (oldsock) {
vhost_net_flush_vq(n, index);
fput(oldsock->file);
@@ -648,6 +752,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
mutex_unlock(&n->dev.mutex);
return 0;
+err_ubufs:
+ fput(sock->file);
err_vq:
mutex_unlock(&vq->mutex);
err:
@@ -777,6 +883,8 @@ static struct miscdevice vhost_net_misc = {
static int vhost_net_init(void)
{
+ if (experimental_zcopytx)
+ vhost_enable_zcopy(VHOST_NET_VQ_TX);
return misc_register(&vhost_net_misc);
}
module_init(vhost_net_init);
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 734e1d7..fc9a1d7 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -195,8 +195,13 @@ static long vhost_test_run(struct vhost_test *n, int test)
lockdep_is_held(&vq->mutex));
rcu_assign_pointer(vq->private_data, priv);
+ r = vhost_init_used(&n->vqs[index]);
+
mutex_unlock(&vq->mutex);
+ if (r)
+ goto err;
+
if (oldpriv) {
vhost_test_flush_vq(n, index);
}
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index e3fac28..738707a 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -37,6 +37,8 @@ enum {
VHOST_MEMORY_F_LOG = 0x1,
};
+static unsigned vhost_zcopy_mask __read_mostly;
+
#define vhost_used_event(vq) ((u16 __user *)&vq->avail->ring[vq->num])
#define vhost_avail_event(vq) ((u16 __user *)&vq->used->ring[vq->num])
@@ -179,6 +181,9 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->call_ctx = NULL;
vq->call = NULL;
vq->log_ctx = NULL;
+ vq->upend_idx = 0;
+ vq->done_idx = 0;
+ vq->ubufs = NULL;
}
static int vhost_worker(void *data)
@@ -227,10 +232,28 @@ static int vhost_worker(void *data)
return 0;
}
+static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq)
+{
+ kfree(vq->indirect);
+ vq->indirect = NULL;
+ kfree(vq->log);
+ vq->log = NULL;
+ kfree(vq->heads);
+ vq->heads = NULL;
+ kfree(vq->ubuf_info);
+ vq->ubuf_info = NULL;
+}
+
+void vhost_enable_zcopy(int vq)
+{
+ vhost_zcopy_mask |= 0x1 << vq;
+}
+
/* Helper to allocate iovec buffers for all vqs. */
static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
{
int i;
+ bool zcopy;
for (i = 0; i < dev->nvqs; ++i) {
dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
@@ -239,19 +262,21 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
GFP_KERNEL);
dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
UIO_MAXIOV, GFP_KERNEL);
-
+ zcopy = vhost_zcopy_mask & (0x1 << i);
+ if (zcopy)
+ dev->vqs[i].ubuf_info =
+ kmalloc(sizeof *dev->vqs[i].ubuf_info *
+ UIO_MAXIOV, GFP_KERNEL);
if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
- !dev->vqs[i].heads)
+ !dev->vqs[i].heads ||
+ (zcopy && !dev->vqs[i].ubuf_info))
goto err_nomem;
}
return 0;
err_nomem:
- for (; i >= 0; --i) {
- kfree(dev->vqs[i].indirect);
- kfree(dev->vqs[i].log);
- kfree(dev->vqs[i].heads);
- }
+ for (; i >= 0; --i)
+ vhost_vq_free_iovecs(&dev->vqs[i]);
return -ENOMEM;
}
@@ -259,14 +284,8 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
{
int i;
- for (i = 0; i < dev->nvqs; ++i) {
- kfree(dev->vqs[i].indirect);
- dev->vqs[i].indirect = NULL;
- kfree(dev->vqs[i].log);
- dev->vqs[i].log = NULL;
- kfree(dev->vqs[i].heads);
- dev->vqs[i].heads = NULL;
- }
+ for (i = 0; i < dev->nvqs; ++i)
+ vhost_vq_free_iovecs(&dev->vqs[i]);
}
long vhost_dev_init(struct vhost_dev *dev,
@@ -289,6 +308,7 @@ long vhost_dev_init(struct vhost_dev *dev,
dev->vqs[i].log = NULL;
dev->vqs[i].indirect = NULL;
dev->vqs[i].heads = NULL;
+ dev->vqs[i].ubuf_info = NULL;
dev->vqs[i].dev = dev;
mutex_init(&dev->vqs[i].mutex);
vhost_vq_reset(dev, dev->vqs + i);
@@ -392,6 +412,30 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
return 0;
}
+/* In case of DMA done not in order in lower device driver for some reason.
+ * upend_idx is used to track end of used idx, done_idx is used to track head
+ * of used idx. Once lower device DMA done contiguously, we will signal KVM
+ * guest used idx.
+ */
+int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq)
+{
+ int i;
+ int j = 0;
+
+ for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
+ if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) {
+ vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
+ vhost_add_used_and_signal(vq->dev, vq,
+ vq->heads[i].id, 0);
+ ++j;
+ } else
+ break;
+ }
+ if (j)
+ vq->done_idx = i;
+ return j;
+}
+
/* Caller should have device mutex */
void vhost_dev_cleanup(struct vhost_dev *dev)
{
@@ -402,6 +446,13 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
vhost_poll_stop(&dev->vqs[i].poll);
vhost_poll_flush(&dev->vqs[i].poll);
}
+ /* Wait for all lower device DMAs done. */
+ if (dev->vqs[i].ubufs)
+ vhost_ubuf_put_and_wait(dev->vqs[i].ubufs);
+
+ /* Signal guest as appropriate. */
+ vhost_zerocopy_signal_used(&dev->vqs[i]);
+
if (dev->vqs[i].error_ctx)
eventfd_ctx_put(dev->vqs[i].error_ctx);
if (dev->vqs[i].error)
@@ -580,17 +631,6 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
return 0;
}
-static int init_used(struct vhost_virtqueue *vq,
- struct vring_used __user *used)
-{
- int r = put_user(vq->used_flags, &used->flags);
-
- if (r)
- return r;
- vq->signalled_used_valid = false;
- return get_user(vq->last_used_idx, &used->idx);
-}
-
static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
{
struct file *eventfp, *filep = NULL,
@@ -703,10 +743,6 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
}
}
- r = init_used(vq, (struct vring_used __user *)(unsigned long)
- a.used_user_addr);
- if (r)
- break;
vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
@@ -847,6 +883,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
}
if (eventfp != d->log_file) {
filep = d->log_file;
+ d->log_file = eventfp;
ctx = d->log_ctx;
d->log_ctx = eventfp ?
eventfd_ctx_fileget(eventfp) : NULL;
@@ -961,6 +998,57 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
return 0;
}
+static int vhost_update_used_flags(struct vhost_virtqueue *vq)
+{
+ void __user *used;
+ if (__put_user(vq->used_flags, &vq->used->flags) < 0)
+ return -EFAULT;
+ if (unlikely(vq->log_used)) {
+ /* Make sure the flag is seen before log. */
+ smp_wmb();
+ /* Log used flag write. */
+ used = &vq->used->flags;
+ log_write(vq->log_base, vq->log_addr +
+ (used - (void __user *)vq->used),
+ sizeof vq->used->flags);
+ if (vq->log_ctx)
+ eventfd_signal(vq->log_ctx, 1);
+ }
+ return 0;
+}
+
+static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
+{
+ if (__put_user(vq->avail_idx, vhost_avail_event(vq)))
+ return -EFAULT;
+ if (unlikely(vq->log_used)) {
+ void __user *used;
+ /* Make sure the event is seen before log. */
+ smp_wmb();
+ /* Log avail event write */
+ used = vhost_avail_event(vq);
+ log_write(vq->log_base, vq->log_addr +
+ (used - (void __user *)vq->used),
+ sizeof *vhost_avail_event(vq));
+ if (vq->log_ctx)
+ eventfd_signal(vq->log_ctx, 1);
+ }
+ return 0;
+}
+
+int vhost_init_used(struct vhost_virtqueue *vq)
+{
+ int r;
+ if (!vq->private_data)
+ return 0;
+
+ r = vhost_update_used_flags(vq);
+ if (r)
+ return r;
+ vq->signalled_used_valid = false;
+ return get_user(vq->last_used_idx, &vq->used->idx);
+}
+
static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
struct iovec iov[], int iov_size)
{
@@ -1432,34 +1520,20 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
return false;
vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
- r = put_user(vq->used_flags, &vq->used->flags);
+ r = vhost_update_used_flags(vq);
if (r) {
vq_err(vq, "Failed to enable notification at %p: %d\n",
&vq->used->flags, r);
return false;
}
} else {
- r = put_user(vq->avail_idx, vhost_avail_event(vq));
+ r = vhost_update_avail_event(vq, vq->avail_idx);
if (r) {
vq_err(vq, "Failed to update avail event index at %p: %d\n",
vhost_avail_event(vq), r);
return false;
}
}
- if (unlikely(vq->log_used)) {
- void __user *used;
- /* Make sure data is seen before log. */
- smp_wmb();
- used = vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX) ?
- &vq->used->flags : vhost_avail_event(vq);
- /* Log used flags or event index entry write. Both are 16 bit
- * fields. */
- log_write(vq->log_base, vq->log_addr +
- (used - (void __user *)vq->used),
- sizeof(u16));
- if (vq->log_ctx)
- eventfd_signal(vq->log_ctx, 1);
- }
/* They could have slipped one in as we were doing that: make
* sure it's written, then check again. */
smp_mb();
@@ -1482,9 +1556,55 @@ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
return;
vq->used_flags |= VRING_USED_F_NO_NOTIFY;
if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
- r = put_user(vq->used_flags, &vq->used->flags);
+ r = vhost_update_used_flags(vq);
if (r)
vq_err(vq, "Failed to enable notification at %p: %d\n",
&vq->used->flags, r);
}
}
+
+static void vhost_zerocopy_done_signal(struct kref *kref)
+{
+ struct vhost_ubuf_ref *ubufs = container_of(kref, struct vhost_ubuf_ref,
+ kref);
+ wake_up(&ubufs->wait);
+}
+
+struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *vq,
+ bool zcopy)
+{
+ struct vhost_ubuf_ref *ubufs;
+ /* No zero copy backend? Nothing to count. */
+ if (!zcopy)
+ return NULL;
+ ubufs = kmalloc(sizeof *ubufs, GFP_KERNEL);
+ if (!ubufs)
+ return ERR_PTR(-ENOMEM);
+ kref_init(&ubufs->kref);
+ init_waitqueue_head(&ubufs->wait);
+ ubufs->vq = vq;
+ return ubufs;
+}
+
+void vhost_ubuf_put(struct vhost_ubuf_ref *ubufs)
+{
+ kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+}
+
+void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
+{
+ kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+ wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+ kfree(ubufs);
+}
+
+void vhost_zerocopy_callback(void *arg)
+{
+ struct ubuf_info *ubuf = arg;
+ struct vhost_ubuf_ref *ubufs = ubuf->arg;
+ struct vhost_virtqueue *vq = ubufs->vq;
+
+ /* set len = 1 to mark this desc buffers done DMA */
+ vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
+ kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 8e03379..a801e28 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -11,7 +11,12 @@
#include <linux/uio.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ring.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
+
+/* This is for zerocopy, used buffer len is set to 1 when lower device DMA
+ * done */
+#define VHOST_DMA_DONE_LEN 1
+#define VHOST_DMA_CLEAR_LEN 0
struct vhost_device;
@@ -50,6 +55,18 @@ struct vhost_log {
u64 len;
};
+struct vhost_virtqueue;
+
+struct vhost_ubuf_ref {
+ struct kref kref;
+ wait_queue_head_t wait;
+ struct vhost_virtqueue *vq;
+};
+
+struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy);
+void vhost_ubuf_put(struct vhost_ubuf_ref *);
+void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *);
+
/* The virtqueue structure describes a queue attached to a device. */
struct vhost_virtqueue {
struct vhost_dev *dev;
@@ -114,6 +131,16 @@ struct vhost_virtqueue {
/* Log write descriptors */
void __user *log_base;
struct vhost_log *log;
+ /* vhost zerocopy support fields below: */
+ /* last used idx for outstanding DMA zerocopy buffers */
+ int upend_idx;
+ /* first used idx for DMA done zerocopy buffers */
+ int done_idx;
+ /* an array of userspace buffers info */
+ struct ubuf_info *ubuf_info;
+ /* Reference counting for outstanding ubufs.
+ * Protected by vq mutex. Writers must also take device mutex. */
+ struct vhost_ubuf_ref *ubufs;
};
struct vhost_dev {
@@ -147,6 +174,7 @@ int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
struct vhost_log *log, unsigned int *log_num);
void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
+int vhost_init_used(struct vhost_virtqueue *);
int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
unsigned count);
@@ -160,6 +188,8 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
unsigned int log_num, u64 len);
+void vhost_zerocopy_callback(void *arg);
+int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
#define vq_err(vq, fmt, ...) do { \
pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
@@ -186,4 +216,6 @@ static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
return acked_features & (1 << bit);
}
+void vhost_enable_zcopy(int vq);
+
#endif
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index d7aaec5..44bdce4 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3458,9 +3458,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev,
raddr = addr + 0x7ff000UL;
rrp = &pdev->resource[2];
- if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
+ if ((rrp->flags & IORESOURCE_MEM) &&
+ request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
par->aux_start = rrp->start;
- par->aux_size = rrp->end - rrp->start + 1;
+ par->aux_size = resource_size(rrp);
raddr = rrp->start;
PRINTKI("using auxiliary register aperture\n");
}
@@ -3550,7 +3551,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev,
/* Reserve space */
res_start = rp->start;
- res_size = rp->end - rp->start + 1;
+ res_size = resource_size(rp);
if (!request_mem_region(res_start, res_size, "atyfb"))
return -EBUSY;
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index e45833c..182bd68 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -4,6 +4,7 @@
*/
#include <linux/delay.h>
+#include <asm/unaligned.h>
#include <linux/fb.h>
#include <video/mach64.h>
#include "atyfb.h"
@@ -419,7 +420,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
u32 *pbitmap, dwords = (src_bytes + 3) / 4;
for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
wait_for_fifo(1, par);
- aty_st_le32(HOST_DATA0, le32_to_cpup(pbitmap), par);
+ aty_st_le32(HOST_DATA0, get_unaligned_le32(pbitmap), par);
}
}
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index 46f72ed..4b87318 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -5,6 +5,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/string.h>
+#include "../fb_draw.h"
#include <asm/io.h>
@@ -157,24 +158,33 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
+ u16 l = 0xaaaa;
b = *src++;
m = *msk++;
switch (cursor->rop) {
case ROP_XOR:
// Upper 4 bits of mask data
- fb_writeb(cursor_bits_lookup[(b ^ m) >> 4], dst++);
+ l = cursor_bits_lookup[(b ^ m) >> 4] |
// Lower 4 bits of mask
- fb_writeb(cursor_bits_lookup[(b ^ m) & 0x0f],
- dst++);
+ (cursor_bits_lookup[(b ^ m) & 0x0f] << 8);
break;
case ROP_COPY:
// Upper 4 bits of mask data
- fb_writeb(cursor_bits_lookup[(b & m) >> 4], dst++);
+ l = cursor_bits_lookup[(b & m) >> 4] |
// Lower 4 bits of mask
- fb_writeb(cursor_bits_lookup[(b & m) & 0x0f],
- dst++);
+ (cursor_bits_lookup[(b & m) & 0x0f] << 8);
break;
}
+ /*
+ * If cursor size is not a multiple of 8 characters
+ * we must pad it with transparent pattern (0xaaaa).
+ */
+ if ((j + 1) * 8 > cursor->image.width) {
+ l = comp(l, 0xaaaa,
+ (1 << ((cursor->image.width & 7) * 2)) - 1);
+ }
+ fb_writeb(l & 0xff, dst++);
+ fb_writeb(l >> 8, dst++);
}
dst += offset;
}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 32f8cf6..1506848 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
{
struct radeonfb_info *rinfo = info->par;
- if ((var->xoffset + var->xres > var->xres_virtual)
- || (var->yoffset + var->yres > var->yres_virtual))
- return -EINVAL;
+ if ((var->xoffset + info->var.xres > info->var.xres_virtual)
+ || (var->yoffset + info->var.yres > info->var.yres_virtual))
+ return -EINVAL;
if (rinfo->asleep)
return 0;
radeon_fifo_wait(2);
- OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
- * var->bits_per_pixel / 8) & ~7);
+ OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
+ var->xoffset * info->var.bits_per_pixel / 8) & ~7);
return 0;
}
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 28b1a83..6cbb206 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -205,7 +205,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
int bottom_only)
{
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
unsigned int cw = vc->vc_font.width;
unsigned int ch = vc->vc_font.height;
unsigned int rw = info->var.xres - (vc->vc_cols*cw);
@@ -214,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bs = info->var.yres - bh;
struct fb_fillrect region;
- region.color = attr_bgcol_ec(bgshift, vc, info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 41b32ae..5a3cbf6 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -197,9 +197,8 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bh = info->var.xres - (vc->vc_rows*ch);
unsigned int bs = vc->vc_rows*ch;
struct fb_fillrect region;
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
- region.color = attr_bgcol_ec(bgshift,vc,info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6a73782..7d3fd9b 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -181,9 +181,8 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bh = info->var.xres - (vc->vc_rows*ch);
unsigned int rs = info->var.yres - rw;
struct fb_fillrect region;
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
- region.color = attr_bgcol_ec(bgshift,vc,info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index ff0872c..19e3714 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -227,9 +227,8 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int rw = info->var.xres - (vc->vc_cols*cw);
unsigned int bh = info->var.yres - (vc->vc_rows*ch);
struct fb_fillrect region;
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
- region.color = attr_bgcol_ec(bgshift,vc,info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 915fd74..9d8feac 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -42,6 +42,7 @@
#include <linux/kd.h>
#include <linux/slab.h>
#include <linux/vt_kern.h>
+#include <linux/sched.h>
#include <linux/selection.h>
#include <linux/spinlock.h>
#include <linux/ioport.h>
@@ -50,7 +51,7 @@
#include <video/vga.h>
#include <asm/io.h>
-static DEFINE_SPINLOCK(vga_lock);
+static DEFINE_RAW_SPINLOCK(vga_lock);
static int cursor_size_lastfrom;
static int cursor_size_lastto;
static u32 vgacon_xres;
@@ -157,7 +158,7 @@ static inline void write_vga(unsigned char reg, unsigned int val)
* ddprintk might set the console position from interrupt
* handlers, thus the write has to be IRQ-atomic.
*/
- spin_lock_irqsave(&vga_lock, flags);
+ raw_spin_lock_irqsave(&vga_lock, flags);
#ifndef SLOW_VGA
v1 = reg + (val & 0xff00);
@@ -170,7 +171,7 @@ static inline void write_vga(unsigned char reg, unsigned int val)
outb_p(reg + 1, vga_video_port_reg);
outb_p(val & 0xff, vga_video_port_val);
#endif
- spin_unlock_irqrestore(&vga_lock, flags);
+ raw_spin_unlock_irqrestore(&vga_lock, flags);
}
static inline void vga_set_mem_top(struct vc_data *c)
@@ -664,7 +665,7 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
cursor_size_lastfrom = from;
cursor_size_lastto = to;
- spin_lock_irqsave(&vga_lock, flags);
+ raw_spin_lock_irqsave(&vga_lock, flags);
if (vga_video_type >= VIDEO_TYPE_VGAC) {
outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
curs = inb_p(vga_video_port_val);
@@ -682,7 +683,7 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
outb_p(curs, vga_video_port_val);
outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
outb_p(cure, vga_video_port_val);
- spin_unlock_irqrestore(&vga_lock, flags);
+ raw_spin_unlock_irqrestore(&vga_lock, flags);
}
static void vgacon_cursor(struct vc_data *c, int mode)
@@ -757,7 +758,7 @@ static int vgacon_doresize(struct vc_data *c,
unsigned int scanlines = height * c->vc_font.height;
u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
- spin_lock_irqsave(&vga_lock, flags);
+ raw_spin_lock_irqsave(&vga_lock, flags);
vgacon_xres = width * VGA_FONTWIDTH;
vgacon_yres = height * c->vc_font.height;
@@ -808,7 +809,7 @@ static int vgacon_doresize(struct vc_data *c,
outb_p(vsync_end, vga_video_port_val);
}
- spin_unlock_irqrestore(&vga_lock, flags);
+ raw_spin_unlock_irqrestore(&vga_lock, flags);
return 0;
}
@@ -891,11 +892,11 @@ static void vga_vesa_blank(struct vgastate *state, int mode)
{
/* save original values of VGA controller registers */
if (!vga_vesa_blanked) {
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
vga_state.HorizontalTotal = inb_p(vga_video_port_val);
@@ -918,7 +919,7 @@ static void vga_vesa_blank(struct vgastate *state, int mode)
/* assure that video is enabled */
/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
/* test for vertical retrace in process.... */
@@ -954,13 +955,13 @@ static void vga_vesa_blank(struct vgastate *state, int mode)
/* restore both index registers */
vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
}
static void vga_vesa_unblank(struct vgastate *state)
{
/* restore original values of VGA controller registers */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
@@ -985,7 +986,7 @@ static void vga_vesa_unblank(struct vgastate *state)
/* restore index/control registers */
vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
}
static void vga_pal_blank(struct vgastate *state)
@@ -1064,7 +1065,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
unsigned short video_port_status = vga_video_port_reg + 6;
int font_select = 0x00, beg, i;
char *charmap;
-
+ bool clear_attribs = false;
if (vga_video_type != VIDEO_TYPE_EGAM) {
charmap = (char *) VGA_MAP_MEM(colourmap, 0);
beg = 0x0e;
@@ -1104,7 +1105,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 4 * cmapsz;
#endif
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
/* First, the Sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
/* CPU writes only to map 2 */
@@ -1120,15 +1121,19 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
/* map start at A000:0000 */
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
if (arg) {
if (set)
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
vga_writeb(arg[i], charmap + i);
+ cond_resched();
+ }
else
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
arg[i] = vga_readb(charmap + i);
+ cond_resched();
+ }
/*
* In 512-character mode, the character map is not contiguous if
@@ -1139,15 +1144,19 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 2 * cmapsz;
arg += cmapsz;
if (set)
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
vga_writeb(arg[i], charmap + i);
+ cond_resched();
+ }
else
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
arg[i] = vga_readb(charmap + i);
+ cond_resched();
+ }
}
}
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
/* First, the sequencer, Synchronous reset */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
/* CPU writes to maps 0 and 1 */
@@ -1169,12 +1178,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
/* if 512 char mode is already enabled don't re-enable it. */
if ((set) && (ch512 != vga_512_chars)) {
- /* attribute controller */
- for (i = 0; i < MAX_NR_CONSOLES; i++) {
- struct vc_data *c = vc_cons[i].d;
- if (c && c->vc_sw == &vga_con)
- c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
- }
vga_512_chars = ch512;
/* 256-char: enable intensity bit
512-char: disable intensity bit */
@@ -1185,8 +1188,22 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
it means, but it works, and it appears necessary */
inb_p(video_port_status);
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
+ clear_attribs = true;
+ }
+ raw_spin_unlock_irq(&vga_lock);
+
+ if (clear_attribs) {
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *c = vc_cons[i].d;
+ if (c && c->vc_sw == &vga_con) {
+ /* force hi font mask to 0, so we always clear
+ the bit on either transition */
+ c->vc_hi_font_mask = 0x00;
+ clear_buffer_attributes(c);
+ c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+ }
+ }
}
- spin_unlock_irq(&vga_lock);
return 0;
}
@@ -1211,26 +1228,26 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
registers; they are write-only on EGA, but it appears that they
are all don't care bits on EGA, so I guess it doesn't matter. */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
ovr = inb_p(vga_video_port_val);
outb_p(0x09, vga_video_port_reg); /* Font size register */
fsr = inb_p(vga_video_port_val);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
vde = maxscan & 0xff; /* Vertical display end reg */
ovr = (ovr & 0xbd) + /* Overflow register */
((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
outb_p(ovr, vga_video_port_val);
outb_p(0x09, vga_video_port_reg); /* Font size */
outb_p(fsr, vga_video_port_val);
outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
outb_p(vde, vga_video_port_val);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
vga_video_font_height = fontheight;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index f37de60..1414b73 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -137,7 +137,7 @@
#define DRAM_ON 0x08
#define DRAM_OFF 0xE7
#define PG_ENABLE_MASK 0x01
-#define RING_SIZE_MASK (RINGBUFFER_SIZE - 1);
+#define RING_SIZE_MASK (RINGBUFFER_SIZE - 1)
/* defines for restoring registers partially */
#define ADDR_MAP_MASK (0x07 << 5)
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 38065cf..fbad61d 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
xoffset = ROUND_DOWN_TO(var->xoffset, 8);
yoffset = var->yoffset;
- if ((xoffset + var->xres > var->xres_virtual) ||
- (yoffset + var->yres > var->yres_virtual))
+ if ((xoffset + info->var.xres > info->var.xres_virtual) ||
+ (yoffset + info->var.yres > info->var.yres_virtual))
return -EINVAL;
offset = (yoffset * dinfo->pitch) +
- (xoffset * var->bits_per_pixel) / 8;
+ (xoffset * info->var.bits_per_pixel) / 8;
offset += dinfo->fb.offset << 12;
diff --git a/drivers/video/logo/.gitignore b/drivers/video/logo/.gitignore
new file mode 100644
index 0000000..e48355f
--- /dev/null
+++ b/drivers/video/logo/.gitignore
@@ -0,0 +1,7 @@
+#
+# Generated files
+#
+*_mono.c
+*_vga16.c
+*_clut224.c
+*_gray256.c
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index ea7a8cc..4bbe1b0 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -25,6 +25,21 @@ static int nologo;
module_param(nologo, bool, 0);
MODULE_PARM_DESC(nologo, "Disables startup logo");
+/*
+ * Logos are located in the initdata, and will be freed in kernel_init.
+ * Use late_init to mark the logos as freed to prevent any further use.
+ */
+
+static bool logos_freed;
+
+static int __init fb_logo_late_init(void)
+{
+ logos_freed = true;
+ return 0;
+}
+
+late_initcall(fb_logo_late_init);
+
/* logo's are marked __initdata. Use __init_refok to tell
* modpost that it is intended that this function uses data
* marked __initdata.
@@ -33,7 +48,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
{
const struct linux_logo *logo = NULL;
- if (nologo)
+ if (nologo || logos_freed)
return NULL;
if (depth >= 1) {
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 8335a6f..0d5cb85 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -192,10 +192,18 @@ void matrox_cfbX_init(struct matrox_fb_info *minfo)
minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
minfo->accel.m_opmode = mopmode;
+ minfo->accel.m_access = maccess;
+ minfo->accel.m_pitch = mpitch;
}
EXPORT_SYMBOL(matrox_cfbX_init);
+static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
+{
+ mga_outl(M_MACCESS, minfo->accel.m_access);
+ mga_outl(M_PITCH, minfo->accel.m_pitch);
+}
+
static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
int sx, int dy, int dx, int height, int width)
{
@@ -207,7 +215,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
CRITBEGIN
if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
- mga_fifo(2);
+ mga_fifo(4);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_AR5, vxres);
@@ -215,7 +224,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
start = sy*vxres+sx+curr_ydstorg(minfo);
end = start+width;
} else {
- mga_fifo(3);
+ mga_fifo(5);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_SGN, 5);
mga_outl(M_AR5, -vxres);
@@ -224,7 +234,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
start = end+width;
dy += height-1;
}
- mga_fifo(4);
+ mga_fifo(6);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_AR0, end);
mga_outl(M_AR3, start);
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
@@ -246,7 +257,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
CRITBEGIN
if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
- mga_fifo(2);
+ mga_fifo(4);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_AR5, vxres);
@@ -254,7 +266,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
start = sy*vxres+sx+curr_ydstorg(minfo);
end = start+width;
} else {
- mga_fifo(3);
+ mga_fifo(5);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_SGN, 5);
mga_outl(M_AR5, -vxres);
@@ -263,7 +276,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
start = end+width;
dy += height-1;
}
- mga_fifo(5);
+ mga_fifo(7);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_AR0, end);
mga_outl(M_AR3, start);
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
@@ -298,7 +312,8 @@ static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
CRITBEGIN
- mga_fifo(5);
+ mga_fifo(7);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
mga_outl(M_FCOL, color);
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
@@ -341,7 +356,8 @@ static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
width >>= 1;
sx >>= 1;
if (width) {
- mga_fifo(5);
+ mga_fifo(7);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
mga_outl(M_FCOL, bgx);
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
@@ -415,7 +431,8 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
CRITBEGIN
- mga_fifo(3);
+ mga_fifo(5);
+ matrox_accel_restore_maccess(minfo);
if (easy)
mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
else
@@ -425,7 +442,8 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
fxbndry = ((xx + width - 1) << 16) | xx;
mmio = minfo->mmio.vbase;
- mga_fifo(6);
+ mga_fifo(8);
+ matrox_accel_restore_maccess(minfo);
mga_writel(mmio, M_FXBNDRY, fxbndry);
mga_writel(mmio, M_AR0, ar0);
mga_writel(mmio, M_AR3, 0);
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 11ed57b..89a8a89a 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -307,6 +307,8 @@ struct matrox_accel_data {
#endif
u_int32_t m_dwg_rect;
u_int32_t m_opmode;
+ u_int32_t m_access;
+ u_int32_t m_pitch;
};
struct v4l2_queryctrl;
@@ -696,7 +698,7 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
#define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
-#define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000)
+#define WaitTillIdle() do { mga_inl(M_STATUS); do {} while (mga_inl(M_STATUS) & 0x10000); } while (0)
/* code speedup */
#ifdef CONFIG_FB_MATROX_MILLENIUM
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
index b953099..273769b 100644
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -13,6 +13,7 @@
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "mb862xxfb.h"
#include "mb862xx_reg.h"
@@ -23,7 +24,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
u32 reg;
do {
- udelay(1);
+ udelay(10);
reg = inreg(i2c, GC_I2C_BCR);
if (reg & (I2C_INT | I2C_BER))
break;
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index f70bd63..11a7a33 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -17,6 +17,7 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
@@ -278,7 +279,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var,
reg = pack(var->yoffset, var->xoffset);
outreg(disp, GC_L0WY_L0WX, reg);
- reg = pack(var->yres_virtual, var->xres_virtual);
+ reg = pack(info->var.yres_virtual, info->var.xres_virtual);
outreg(disp, GC_L0WH_L0WW, reg);
return 0;
}
@@ -697,7 +698,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
goto fbrel;
}
- res_size = 1 + res.end - res.start;
+ res_size = resource_size(&res);
par->res = request_mem_region(res.start, res_size, DRV_NAME);
if (par->res == NULL) {
dev_err(dev, "Cannot claim framebuffer/mmio\n");
@@ -737,7 +738,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
if (mb862xx_gdc_init(par))
goto io_unmap;
- if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED,
+ if (request_irq(par->irq, mb862xx_intr, 0,
DRV_NAME, (void *)par)) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;
@@ -787,7 +788,7 @@ static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
{
struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
struct mb862xxfb_par *par = fbi->par;
- resource_size_t res_size = 1 + par->res->end - par->res->start;
+ resource_size_t res_size = resource_size(par->res);
unsigned long reg;
dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
@@ -1073,7 +1074,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
if (mb862xx_pci_gdc_init(par))
goto io_unmap;
- if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED,
+ if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
DRV_NAME, (void *)par)) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index afea9ab..6ce3416 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -34,7 +34,7 @@
#include "regs.h"
#include "reg_bits.h"
-static unsigned long virt_base_2700;
+static void __iomem *virt_base_2700;
#define write_reg(val, reg) do { writel((val), (reg)); } while(0)
@@ -850,7 +850,7 @@ static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
{
/* make frame buffer memory enter self-refresh mode */
write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
- while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
+ while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM)
; /* empty statement */
/* reset the device, since it's initial state is 'mostly sleeping' */
@@ -946,7 +946,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
ret = -EINVAL;
goto err3;
}
- virt_base_2700 = (unsigned long)mfbi->reg_virt_addr;
+ virt_base_2700 = mfbi->reg_virt_addr;
mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
res_size(mfbi->fb_req));
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 178b072..4527cbf 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev)
mddi->int_enable = 0;
mddi_writel(mddi->int_enable, INTEN);
- ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
+ ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
&mddi->client_data);
if (ret) {
printk(KERN_ERR "mddi: failed to request enable irq!\n");
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c3636d5..cb2ddf1 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -28,6 +28,7 @@
#include <mach/msm_iomap.h>
#include <mach/msm_fb.h>
#include <linux/platform_device.h>
+#include <linux/export.h>
#include "mdp_hw.h"
@@ -406,8 +407,7 @@ int mdp_probe(struct platform_device *pdev)
goto error_get_irq;
}
- mdp->base = ioremap(resource->start,
- resource->end - resource->start);
+ mdp->base = ioremap(resource->start, resource_size(resource));
if (mdp->base == 0) {
printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
ret = -ENOMEM;
@@ -422,10 +422,11 @@ int mdp_probe(struct platform_device *pdev)
clk = clk_get(&pdev->dev, "mdp_clk");
if (IS_ERR(clk)) {
printk(KERN_INFO "mdp: failed to get mdp clk");
- return PTR_ERR(clk);
+ ret = PTR_ERR(clk);
+ goto error_get_clk;
}
- ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
+ ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
if (ret)
goto error_request_irq;
disable_irq(mdp->irq);
@@ -496,6 +497,7 @@ int mdp_probe(struct platform_device *pdev)
error_device_register:
free_irq(mdp->irq, mdp);
error_request_irq:
+error_get_clk:
iounmap(mdp->base);
error_get_irq:
error_ioremap:
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index ec35130..c6e3b4f 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -525,10 +525,9 @@ static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
return -ENOMEM;
}
fb->fix.smem_start = resource->start;
- fb->fix.smem_len = resource->end - resource->start;
- fbram = ioremap(resource->start,
- resource->end - resource->start);
- if (fbram == 0) {
+ fb->fix.smem_len = resource_size(resource);
+ fbram = ioremap(resource->start, resource_size(resource));
+ if (fbram == NULL) {
printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
return -ENOMEM;
}
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 609a280..8d8e1fe 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
Supports LCD Panel used in TI SDP3430 and EVM boards,
OMAP3517 EVM boards and CM-T35.
+config PANEL_DVI
+ tristate "DVI output"
+ depends on OMAP2_DSS_DPI
+ help
+ Driver for external monitors, connected via DVI. The driver uses i2c
+ to read EDID information from the monitor.
+
config PANEL_LGPHILIPS_LB035Q02
tristate "LG.Philips LB035Q02 LCD Panel"
depends on OMAP2_DSS_DPI && SPI
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS_DPI
- select BACKLIGHT_CLASS_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
help
LCD Panel used in TI's SDP3430 and EVM boards
config PANEL_NEC_NL8048HL11_01B
tristate "NEC NL8048HL11-01B Panel"
depends on OMAP2_DSS_DPI
+ depends on SPI
+ depends on BACKLIGHT_CLASS_DEVICE
help
This NEC NL8048HL11-01B panel is TFT LCD
used in the Zoom2/3/3630 sdp boards.
+config PANEL_PICODLP
+ tristate "TI PICO DLP mini-projector"
+ depends on OMAP2_DSS && I2C
+ help
+ A mini-projector used in TI's SDP4430 and EVM boards
+ For more info please visit http://www.dlp.com/projector/
+
config PANEL_TAAL
tristate "Taal DSI Panel"
depends on OMAP2_DSS_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
help
Taal DSI command mode panel from TPO.
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
config PANEL_ACX565AKM
tristate "ACX565AKM Panel"
depends on OMAP2_DSS_SDI && SPI
- select BACKLIGHT_CLASS_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
help
This is the LCD panel used on Nokia N900
+
+config PANEL_N8X0
+ tristate "N8X0 Panel"
+ depends on OMAP2_DSS_RFBI && SPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ This is the LCD panel used on Nokia N8x0
endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 0f601ab3a..fbfafc6 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,8 +1,11 @@
obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
+obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
+obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
+obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75..519c47d 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -58,30 +58,6 @@ struct panel_config {
/* Panel configurations */
static struct panel_config generic_dpi_panels[] = {
- /* Generic Panel */
- {
- {
- .x_res = 640,
- .y_res = 480,
-
- .pixel_clock = 23500,
-
- .hfp = 48,
- .hsw = 32,
- .hbp = 80,
-
- .vfp = 3,
- .vsw = 4,
- .vbp = 7,
- },
- .acbi = 0x0,
- .acb = 0x0,
- .config = OMAP_DSS_LCD_TFT,
- .power_on_delay = 0,
- .power_off_delay = 0,
- .name = "generic",
- },
-
/* Sharp LQ043T1DG01 */
{
{
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "powertip_ph480272t",
},
+
+ /* Innolux AT070TN83 */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 40000,
+
+ .hsw = 48,
+ .hfp = 1,
+ .hbp = 1,
+
+ .vsw = 3,
+ .vfp = 12,
+ .vbp = 25,
+ },
+ .acbi = 0x0,
+ .acb = 0x28,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "innolux_at070tn83",
+ },
+
+ /* NEC NL2432DR22-11B */
+ {
+ {
+ .x_res = 240,
+ .y_res = 320,
+
+ .pixel_clock = 5400,
+
+ .hsw = 3,
+ .hfp = 3,
+ .hbp = 39,
+
+ .vsw = 1,
+ .vfp = 2,
+ .vbp = 7,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .name = "nec_nl2432dr22-11b",
+ },
+
+ /* Unknown panel used in OMAP H4 */
+ {
+ {
+ .x_res = 240,
+ .y_res = 320,
+
+ .pixel_clock = 6250,
+
+ .hsw = 15,
+ .hfp = 15,
+ .hbp = 60,
+
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 1,
+ },
+ .config = OMAP_DSS_LCD_TFT,
+
+ .name = "h4",
+ },
+
+ /* Unknown panel used in Samsung OMAP2 Apollon */
+ {
+ {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 6250,
+
+ .hsw = 41,
+ .hfp = 2,
+ .hbp = 2,
+
+ .vsw = 10,
+ .vfp = 2,
+ .vbp = 2,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+
+ .name = "apollon",
+ },
};
struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index fdd5d4ae..80c3f6a 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -35,26 +35,12 @@
#include <video/omapdss.h>
#include <video/omap-panel-nokia-dsi.h>
+#include <video/mipi_display.h>
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
#define DCS_READ_NUM_ERRORS 0x05
-#define DCS_READ_POWER_MODE 0x0a
-#define DCS_READ_MADCTL 0x0b
-#define DCS_READ_PIXEL_FORMAT 0x0c
-#define DCS_RDDSDR 0x0f
-#define DCS_SLEEP_IN 0x10
-#define DCS_SLEEP_OUT 0x11
-#define DCS_DISPLAY_OFF 0x28
-#define DCS_DISPLAY_ON 0x29
-#define DCS_COLUMN_ADDR 0x2a
-#define DCS_PAGE_ADDR 0x2b
-#define DCS_MEMORY_WRITE 0x2c
-#define DCS_TEAR_OFF 0x34
-#define DCS_TEAR_ON 0x35
-#define DCS_MEM_ACC_CTRL 0x36
-#define DCS_PIXEL_FORMAT 0x3a
#define DCS_BRIGHTNESS 0x51
#define DCS_CTRL_DISPLAY 0x53
#define DCS_WRITE_CABC 0x55
@@ -222,8 +208,6 @@ struct taal_data {
struct delayed_work te_timeout_work;
- bool use_dsi_bl;
-
bool cabc_broken;
unsigned cabc_mode;
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
hw_guard_wait(td);
- cmd = DCS_SLEEP_IN;
+ cmd = MIPI_DCS_ENTER_SLEEP_MODE;
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
if (r)
return r;
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
hw_guard_wait(td);
- r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
+ r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
if (r)
return r;
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
u8 mode;
int b5, b6, b7;
- r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
if (r)
return r;
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
mode &= ~((1<<7) | (1<<6) | (1<<5));
mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
- return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
+ return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
}
static int taal_set_update_window(struct taal_data *td,
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
u16 y2 = y + h - 1;
u8 buf[5];
- buf[0] = DCS_COLUMN_ADDR;
+ buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
buf[1] = (x1 >> 8) & 0xff;
buf[2] = (x1 >> 0) & 0xff;
buf[3] = (x2 >> 8) & 0xff;
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
if (r)
return r;
- buf[0] = DCS_PAGE_ADDR;
+ buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
buf[1] = (y1 >> 8) & 0xff;
buf[2] = (y1 >> 0) & 0xff;
buf[3] = (y2 >> 8) & 0xff;
@@ -504,14 +488,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
r = omapdss_dsi_display_enable(dssdev);
- if (r)
- goto err;
+ if (r) {
+ dev_err(&dssdev->dev, "failed to enable DSI\n");
+ goto err1;
+ }
omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
r = _taal_enable_te(dssdev, true);
- if (r)
- goto err;
+ if (r) {
+ dev_err(&dssdev->dev, "failed to re-enable TE");
+ goto err2;
+ }
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
@@ -521,13 +509,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
-err:
- dev_err(&dssdev->dev, "exit ULPS failed");
- r = taal_panel_reset(dssdev);
-
- enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
- td->ulps_enabled = false;
+err2:
+ dev_err(&dssdev->dev, "failed to exit ULPS");
+ r = taal_panel_reset(dssdev);
+ if (!r) {
+ enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+ td->ulps_enabled = false;
+ }
+err1:
taal_queue_ulps_work(dssdev);
return r;
@@ -549,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
int level;
@@ -563,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
mutex_lock(&td->lock);
- if (td->use_dsi_bl) {
- if (td->enabled) {
- dsi_bus_lock(dssdev);
+ if (td->enabled) {
+ dsi_bus_lock(dssdev);
- r = taal_wake_up(dssdev);
- if (!r)
- r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
+ r = taal_wake_up(dssdev);
+ if (!r)
+ r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
- dsi_bus_unlock(dssdev);
- } else {
- r = 0;
- }
+ dsi_bus_unlock(dssdev);
} else {
- if (!panel_data->set_backlight)
- r = -EINVAL;
- else
- r = panel_data->set_backlight(dssdev, level);
+ r = 0;
}
mutex_unlock(&td->lock);
@@ -958,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
{
struct backlight_properties props;
struct taal_data *td;
- struct backlight_device *bldev;
+ struct backlight_device *bldev = NULL;
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
struct panel_config *panel_config = NULL;
int r, i;
@@ -984,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
dssdev->panel.config = OMAP_DSS_LCD_TFT;
dssdev->panel.timings = panel_config->timings;
- dssdev->ctrl.pixel_size = 24;
+ dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
td = kzalloc(sizeof(*td), GFP_KERNEL);
if (!td) {
@@ -1019,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
- /* if no platform set_backlight() defined, presume DSI backlight
- * control */
- memset(&props, 0, sizeof(struct backlight_properties));
- if (!panel_data->set_backlight)
- td->use_dsi_bl = true;
-
- if (td->use_dsi_bl)
+ if (panel_data->use_dsi_backlight) {
+ memset(&props, 0, sizeof(struct backlight_properties));
props.max_brightness = 255;
- else
- props.max_brightness = 127;
-
- props.type = BACKLIGHT_RAW;
- bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
- dssdev, &taal_bl_ops, &props);
- if (IS_ERR(bldev)) {
- r = PTR_ERR(bldev);
- goto err_bl;
- }
- td->bldev = bldev;
+ props.type = BACKLIGHT_RAW;
+ bldev = backlight_device_register(dev_name(&dssdev->dev),
+ &dssdev->dev, dssdev, &taal_bl_ops, &props);
+ if (IS_ERR(bldev)) {
+ r = PTR_ERR(bldev);
+ goto err_bl;
+ }
+
+ td->bldev = bldev;
- bldev->props.fb_blank = FB_BLANK_UNBLANK;
- bldev->props.power = FB_BLANK_UNBLANK;
- if (td->use_dsi_bl)
+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
+ bldev->props.power = FB_BLANK_UNBLANK;
bldev->props.brightness = 255;
- else
- bldev->props.brightness = 127;
- taal_bl_update_status(bldev);
+ taal_bl_update_status(bldev);
+ }
if (panel_data->use_ext_te) {
int gpio = panel_data->ext_te_gpio;
@@ -1061,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
gpio_direction_input(gpio);
r = request_irq(gpio_to_irq(gpio), taal_te_isr,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_RISING,
"taal vsync", dssdev);
if (r) {
@@ -1105,7 +1078,8 @@ err_irq:
if (panel_data->use_ext_te)
gpio_free(panel_data->ext_te_gpio);
err_gpio:
- backlight_device_unregister(bldev);
+ if (bldev != NULL)
+ backlight_device_unregister(bldev);
err_bl:
destroy_workqueue(td->workqueue);
err_wq:
@@ -1134,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
}
bldev = td->bldev;
- bldev->props.power = FB_BLANK_POWERDOWN;
- taal_bl_update_status(bldev);
- backlight_device_unregister(bldev);
+ if (bldev != NULL) {
+ bldev->props.power = FB_BLANK_POWERDOWN;
+ taal_bl_update_status(bldev);
+ backlight_device_unregister(bldev);
+ }
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
@@ -1189,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
if (r)
goto err;
- r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
+ MIPI_DCS_PIXEL_FMT_24BIT);
if (r)
goto err;
@@ -1203,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
goto err;
}
- r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
if (r)
goto err;
@@ -1240,12 +1217,9 @@ static void taal_power_off(struct omap_dss_device *dssdev)
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int r;
- r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
- if (!r) {
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
+ if (!r)
r = taal_sleep_in(td);
- /* HACK: wait a bit so that the message goes through */
- msleep(10);
- }
if (r) {
dev_err(&dssdev->dev,
@@ -1317,8 +1291,11 @@ static void taal_disable(struct omap_dss_device *dssdev)
dsi_bus_lock(dssdev);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
- taal_wake_up(dssdev);
- taal_power_off(dssdev);
+ int r;
+
+ r = taal_wake_up(dssdev);
+ if (!r)
+ taal_power_off(dssdev);
}
dsi_bus_unlock(dssdev);
@@ -1523,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
int r;
if (enable)
- r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
else
- r = taal_dcs_write_0(td, DCS_TEAR_OFF);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
if (!panel_data->use_ext_te)
omapdss_dsi_enable_te(dssdev, enable);
@@ -1845,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
- r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@@ -1858,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
- r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@@ -1874,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
/* Self-diagnostics result is also shown on TE GPIO line. We need
* to re-enable TE after self diagnostics */
if (td->te_enabled && panel_data->use_ext_te) {
- r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
if (r)
goto err;
}
@@ -1897,20 +1874,6 @@ err:
mutex_unlock(&td->lock);
}
-static int taal_set_update_mode(struct omap_dss_device *dssdev,
- enum omap_dss_update_mode mode)
-{
- if (mode != OMAP_DSS_UPDATE_MANUAL)
- return -EINVAL;
- return 0;
-}
-
-static enum omap_dss_update_mode taal_get_update_mode(
- struct omap_dss_device *dssdev)
-{
- return OMAP_DSS_UPDATE_MANUAL;
-}
-
static struct omap_dss_driver taal_driver = {
.probe = taal_probe,
.remove = __exit_p(taal_remove),
@@ -1920,9 +1883,6 @@ static struct omap_dss_driver taal_driver = {
.suspend = taal_suspend,
.resume = taal_resume,
- .set_update_mode = taal_set_update_mode,
- .get_update_mode = taal_get_update_mode,
-
.update = taal_update,
.sync = taal_sync,
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index aa33386..83d3fe7 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,5 +1,5 @@
menuconfig FB_OMAP2
- tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
+ tristate "OMAP2+ frame buffer support"
depends on FB && OMAP2_DSS
select OMAP2_VRAM
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index cff4503..df7bcce 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/omapfb.h>
#include <linux/vmalloc.h>
+#include <linux/export.h>
#include <video/omapdss.h>
#include <plat/vrfb.h>
@@ -316,67 +317,67 @@ int omapfb_update_window(struct fb_info *fbi,
}
EXPORT_SYMBOL(omapfb_update_window);
-static int omapfb_set_update_mode(struct fb_info *fbi,
+int omapfb_set_update_mode(struct fb_info *fbi,
enum omapfb_update_mode mode)
{
struct omap_dss_device *display = fb2display(fbi);
- enum omap_dss_update_mode um;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb_display_data *d;
int r;
- if (!display || !display->driver->set_update_mode)
+ if (!display)
return -EINVAL;
- switch (mode) {
- case OMAPFB_UPDATE_DISABLED:
- um = OMAP_DSS_UPDATE_DISABLED;
- break;
+ if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
+ return -EINVAL;
- case OMAPFB_AUTO_UPDATE:
- um = OMAP_DSS_UPDATE_AUTO;
- break;
+ omapfb_lock(fbdev);
- case OMAPFB_MANUAL_UPDATE:
- um = OMAP_DSS_UPDATE_MANUAL;
- break;
+ d = get_display_data(fbdev, display);
- default:
- return -EINVAL;
+ if (d->update_mode == mode) {
+ omapfb_unlock(fbdev);
+ return 0;
}
- r = display->driver->set_update_mode(display, um);
+ r = 0;
+
+ if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ if (mode == OMAPFB_AUTO_UPDATE)
+ omapfb_start_auto_update(fbdev, display);
+ else /* MANUAL_UPDATE */
+ omapfb_stop_auto_update(fbdev, display);
+
+ d->update_mode = mode;
+ } else { /* AUTO_UPDATE */
+ if (mode == OMAPFB_MANUAL_UPDATE)
+ r = -EINVAL;
+ }
+
+ omapfb_unlock(fbdev);
return r;
}
-static int omapfb_get_update_mode(struct fb_info *fbi,
+int omapfb_get_update_mode(struct fb_info *fbi,
enum omapfb_update_mode *mode)
{
struct omap_dss_device *display = fb2display(fbi);
- enum omap_dss_update_mode m;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb_display_data *d;
if (!display)
return -EINVAL;
- if (!display->driver->get_update_mode) {
- *mode = OMAPFB_AUTO_UPDATE;
- return 0;
- }
+ omapfb_lock(fbdev);
- m = display->driver->get_update_mode(display);
+ d = get_display_data(fbdev, display);
- switch (m) {
- case OMAP_DSS_UPDATE_DISABLED:
- *mode = OMAPFB_UPDATE_DISABLED;
- break;
- case OMAP_DSS_UPDATE_AUTO:
- *mode = OMAPFB_AUTO_UPDATE;
- break;
- case OMAP_DSS_UPDATE_MANUAL:
- *mode = OMAPFB_MANUAL_UPDATE;
- break;
- default:
- BUG();
- }
+ *mode = d->update_mode;
+
+ omapfb_unlock(fbdev);
return 0;
}
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 505bc12..f7c1753 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -46,6 +46,10 @@ static char *def_vram;
static int def_vrfb;
static int def_rotate;
static int def_mirror;
+static bool auto_update;
+static unsigned int auto_update_freq;
+module_param(auto_update, bool, 0);
+module_param(auto_update_freq, uint, 0644);
#ifdef DEBUG
unsigned int omapfb_debug;
@@ -804,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
static void omapfb_calc_addr(const struct omapfb_info *ofbi,
const struct fb_var_screeninfo *var,
const struct fb_fix_screeninfo *fix,
- int rotation, u32 *paddr, void __iomem **vaddr)
+ int rotation, u32 *paddr)
{
u32 data_start_p;
- void __iomem *data_start_v;
int offset;
- if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
- data_start_v = NULL;
- } else {
+ else
data_start_p = omapfb_get_region_paddr(ofbi);
- data_start_v = omapfb_get_region_vaddr(ofbi);
- }
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
offset = calc_rotation_offset_vrfb(var, fix, rotation);
@@ -824,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
offset = calc_rotation_offset_dma(var, fix, rotation);
data_start_p += offset;
- data_start_v += offset;
if (offset)
DBG("offset %d, %d = %d\n",
var->xoffset, var->yoffset, offset);
- DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+ DBG("paddr %x\n", data_start_p);
*paddr = data_start_p;
- *vaddr = data_start_v;
}
/* setup overlay according to the fb */
@@ -846,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
struct fb_fix_screeninfo *fix = &fbi->fix;
enum omap_color_mode mode = 0;
u32 data_start_p = 0;
- void __iomem *data_start_v = NULL;
struct omap_overlay_info info;
int xres, yres;
int screen_width;
@@ -876,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
}
if (ofbi->region->size)
- omapfb_calc_addr(ofbi, var, fix, rotation,
- &data_start_p, &data_start_v);
+ omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
@@ -906,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
mirror = ofbi->mirror;
info.paddr = data_start_p;
- info.vaddr = data_start_v;
info.screen_width = screen_width;
info.width = xres;
info.height = yres;
@@ -1188,7 +1183,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
break;
if (regno < 16) {
- u16 pal;
+ u32 pal;
pal = ((red >> (16 - var->red.length)) <<
var->red.offset) |
((green >> (16 - var->green.length)) <<
@@ -1242,6 +1237,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb_display_data *d;
int r = 0;
if (!display)
@@ -1249,6 +1245,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
omapfb_lock(fbdev);
+ d = get_display_data(fbdev, display);
+
switch (blank) {
case FB_BLANK_UNBLANK:
if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
@@ -1257,6 +1255,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->driver->resume)
r = display->driver->resume(display);
+ if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
+ d->update_mode == OMAPFB_AUTO_UPDATE &&
+ !d->auto_update_work_enabled)
+ omapfb_start_auto_update(fbdev, display);
+
break;
case FB_BLANK_NORMAL:
@@ -1268,6 +1271,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
goto exit;
+ if (d->auto_update_work_enabled)
+ omapfb_stop_auto_update(fbdev, display);
+
if (display->driver->suspend)
r = display->driver->suspend(display);
@@ -1724,6 +1730,78 @@ err:
return r;
}
+static void omapfb_auto_update_work(struct work_struct *work)
+{
+ struct omap_dss_device *dssdev;
+ struct omap_dss_driver *dssdrv;
+ struct omapfb_display_data *d;
+ u16 w, h;
+ unsigned int freq;
+ struct omapfb2_device *fbdev;
+
+ d = container_of(work, struct omapfb_display_data,
+ auto_update_work.work);
+
+ dssdev = d->dssdev;
+ dssdrv = dssdev->driver;
+ fbdev = d->fbdev;
+
+ if (!dssdrv || !dssdrv->update)
+ return;
+
+ if (dssdrv->sync)
+ dssdrv->sync(dssdev);
+
+ dssdrv->get_resolution(dssdev, &w, &h);
+ dssdrv->update(dssdev, 0, 0, w, h);
+
+ freq = auto_update_freq;
+ if (freq == 0)
+ freq = 20;
+ queue_delayed_work(fbdev->auto_update_wq,
+ &d->auto_update_work, HZ / freq);
+}
+
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display)
+{
+ struct omapfb_display_data *d;
+
+ if (fbdev->auto_update_wq == NULL) {
+ struct workqueue_struct *wq;
+
+ wq = create_singlethread_workqueue("omapfb_auto_update");
+
+ if (wq == NULL) {
+ dev_err(fbdev->dev, "Failed to create workqueue for "
+ "auto-update\n");
+ return;
+ }
+
+ fbdev->auto_update_wq = wq;
+ }
+
+ d = get_display_data(fbdev, display);
+
+ INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
+
+ d->auto_update_work_enabled = true;
+
+ omapfb_auto_update_work(&d->auto_update_work.work);
+}
+
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display)
+{
+ struct omapfb_display_data *d;
+
+ d = get_display_data(fbdev, display);
+
+ cancel_delayed_work_sync(&d->auto_update_work);
+
+ d->auto_update_work_enabled = false;
+}
+
/* initialize fb_info, var, fix to something sane based on the display */
static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
{
@@ -1858,10 +1936,21 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
}
for (i = 0; i < fbdev->num_displays; i++) {
- if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
- fbdev->displays[i]->driver->disable(fbdev->displays[i]);
+ struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
- omap_dss_put_device(fbdev->displays[i]);
+ if (fbdev->displays[i].auto_update_work_enabled)
+ omapfb_stop_auto_update(fbdev, dssdev);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
+ dssdev->driver->disable(dssdev);
+
+ omap_dss_put_device(dssdev);
+ }
+
+ if (fbdev->auto_update_wq != NULL) {
+ flush_workqueue(fbdev->auto_update_wq);
+ destroy_workqueue(fbdev->auto_update_wq);
+ fbdev->auto_update_wq = NULL;
}
dev_set_drvdata(fbdev->dev, NULL);
@@ -2084,14 +2173,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
int r;
u8 bpp;
struct omap_video_timings timings, temp_timings;
+ struct omapfb_display_data *d;
r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
if (r)
return r;
- fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
- fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
- ++fbdev->num_bpp_overrides;
+ d = get_display_data(fbdev, display);
+ d->bpp_override = bpp;
if (display->driver->check_timings) {
r = display->driver->check_timings(display, &timings);
@@ -2117,14 +2206,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
- int i;
+ struct omapfb_display_data *d;
BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
- for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
- if (dssdev == fbdev->bpp_overrides[i].dssdev)
- return fbdev->bpp_overrides[i].bpp;
- }
+ d = get_display_data(fbdev, dssdev);
+
+ if (d->bpp_override != 0)
+ return d->bpp_override;
return dssdev->driver->get_recommended_bpp(dssdev);
}
@@ -2156,9 +2245,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
display = NULL;
for (i = 0; i < fbdev->num_displays; ++i) {
- if (strcmp(fbdev->displays[i]->name,
+ if (strcmp(fbdev->displays[i].dssdev->name,
display_str) == 0) {
- display = fbdev->displays[i];
+ display = fbdev->displays[i].dssdev;
break;
}
}
@@ -2178,10 +2267,92 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
return r;
}
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+ struct omap_video_timings *t)
+{
+ t->x_res = m->xres;
+ t->y_res = m->yres;
+ t->pixel_clock = PICOS2KHZ(m->pixclock);
+ t->hsw = m->hsync_len;
+ t->hfp = m->right_margin;
+ t->hbp = m->left_margin;
+ t->vsw = m->vsync_len;
+ t->vfp = m->lower_margin;
+ t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+ struct omap_video_timings *timings)
+{
+ struct fb_monspecs *specs;
+ u8 *edid;
+ int r, i, best_xres, best_idx, len;
+
+ if (!display->driver->read_edid)
+ return -ENODEV;
+
+ len = 0x80 * 2;
+ edid = kmalloc(len, GFP_KERNEL);
+
+ r = display->driver->read_edid(display, edid, len);
+ if (r < 0)
+ goto err1;
+
+ specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+ fb_edid_to_monspecs(edid, specs);
+
+ if (edid[126] > 0)
+ fb_edid_add_monspecs(edid + 0x80, specs);
+
+ best_xres = 0;
+ best_idx = -1;
+
+ for (i = 0; i < specs->modedb_len; ++i) {
+ struct fb_videomode *m;
+ struct omap_video_timings t;
+
+ m = &specs->modedb[i];
+
+ if (m->pixclock == 0)
+ continue;
+
+ /* skip repeated pixel modes */
+ if (m->xres == 2880 || m->xres == 1440)
+ continue;
+
+ fb_videomode_to_omap_timings(m, &t);
+
+ r = display->driver->check_timings(display, &t);
+ if (r == 0 && best_xres < m->xres) {
+ best_xres = m->xres;
+ best_idx = i;
+ }
+ }
+
+ if (best_xres == 0) {
+ r = -ENOENT;
+ goto err2;
+ }
+
+ fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+ r = 0;
+
+err2:
+ fb_destroy_modedb(specs->modedb);
+ kfree(specs);
+err1:
+ kfree(edid);
+
+ return r;
+}
+
static int omapfb_init_display(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
struct omap_dss_driver *dssdrv = dssdev->driver;
+ struct omapfb_display_data *d;
int r;
r = dssdrv->enable(dssdev);
@@ -2191,8 +2362,20 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return r;
}
+ d = get_display_data(fbdev, dssdev);
+
+ d->fbdev = fbdev;
+
if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
u16 w, h;
+
+ if (auto_update) {
+ omapfb_start_auto_update(fbdev, dssdev);
+ d->update_mode = OMAPFB_AUTO_UPDATE;
+ } else {
+ d->update_mode = OMAPFB_MANUAL_UPDATE;
+ }
+
if (dssdrv->enable_te) {
r = dssdrv->enable_te(dssdev, 1);
if (r) {
@@ -2201,16 +2384,6 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
}
}
- if (dssdrv->set_update_mode) {
- r = dssdrv->set_update_mode(dssdev,
- OMAP_DSS_UPDATE_MANUAL);
- if (r) {
- dev_err(fbdev->dev,
- "Failed to set update mode\n");
- return r;
- }
- }
-
dssdrv->get_resolution(dssdev, &w, &h);
r = dssdrv->update(dssdev, 0, 0, w, h);
if (r) {
@@ -2219,15 +2392,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return r;
}
} else {
- if (dssdrv->set_update_mode) {
- r = dssdrv->set_update_mode(dssdev,
- OMAP_DSS_UPDATE_AUTO);
- if (r) {
- dev_err(fbdev->dev,
- "Failed to set update mode\n");
- return r;
- }
- }
+ d->update_mode = OMAPFB_AUTO_UPDATE;
}
return 0;
@@ -2275,14 +2440,23 @@ static int omapfb_probe(struct platform_device *pdev)
fbdev->num_displays = 0;
dssdev = NULL;
for_each_dss_dev(dssdev) {
+ struct omapfb_display_data *d;
+
omap_dss_get_device(dssdev);
if (!dssdev->driver) {
- dev_err(&pdev->dev, "no driver for display\n");
- r = -ENODEV;
+ dev_warn(&pdev->dev, "no driver for display: %s\n",
+ dssdev->name);
+ omap_dss_put_device(dssdev);
+ continue;
}
- fbdev->displays[fbdev->num_displays++] = dssdev;
+ d = &fbdev->displays[fbdev->num_displays++];
+ d->dssdev = dssdev;
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+ d->update_mode = OMAPFB_MANUAL_UPDATE;
+ else
+ d->update_mode = OMAPFB_AUTO_UPDATE;
}
if (r)
@@ -2302,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)
for (i = 0; i < fbdev->num_managers; i++)
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+ /* gfx overlay should be the default one. find a display
+ * connected to that, and use it as default display */
+ ovl = omap_dss_get_overlay(0);
+ if (ovl->manager && ovl->manager->device) {
+ def_display = ovl->manager->device;
+ } else {
+ dev_warn(&pdev->dev, "cannot find default display\n");
+ def_display = NULL;
+ }
+
if (def_mode && strlen(def_mode) > 0) {
if (omapfb_parse_def_modes(fbdev))
dev_warn(&pdev->dev, "cannot parse default modes\n");
+ } else if (def_display && def_display->driver->set_timings &&
+ def_display->driver->check_timings) {
+ struct omap_video_timings t;
+
+ r = omapfb_find_best_mode(def_display, &t);
+
+ if (r == 0)
+ def_display->driver->set_timings(def_display, &t);
}
r = omapfb_create_framebuffers(fbdev);
@@ -2321,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)
DBG("mgr->apply'ed\n");
- /* gfx overlay should be the default one. find a display
- * connected to that, and use it as default display */
- ovl = omap_dss_get_overlay(0);
- if (ovl->manager && ovl->manager->device) {
- def_display = ovl->manager->device;
- } else {
- dev_warn(&pdev->dev, "cannot find default display\n");
- def_display = NULL;
- }
-
if (def_display) {
r = omapfb_init_display(fbdev, def_display);
if (r) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 2f5e817..1694d51 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
- int mirror;
+ bool mirror;
int r;
struct fb_var_screeninfo new_var;
- r = kstrtoint(buf, 0, &mirror);
+ r = strtobool(buf, &mirror);
if (r)
return r;
- mirror = !!mirror;
-
if (!lock_fb_info(fbi))
return -ENODEV;
@@ -518,6 +516,39 @@ static ssize_t show_virt(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
}
+static ssize_t show_upd_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ enum omapfb_update_mode mode;
+ int r;
+
+ r = omapfb_get_update_mode(fbi, &mode);
+
+ if (r)
+ return r;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
+}
+
+static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ unsigned mode;
+ int r;
+
+ r = kstrtouint(buf, 0, &mode);
+ if (r)
+ return r;
+
+ r = omapfb_set_update_mode(fbi, mode);
+ if (r)
+ return r;
+
+ return count;
+}
+
static struct device_attribute omapfb_attrs[] = {
__ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
store_rotate_type),
@@ -528,6 +559,7 @@ static struct device_attribute omapfb_attrs[] = {
store_overlays_rotate),
__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+ __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
};
int omapfb_create_sysfs(struct omapfb2_device *fbdev)
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index aa1b1d9..fdf0ede 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -73,6 +73,15 @@ struct omapfb_info {
bool mirror;
};
+struct omapfb_display_data {
+ struct omapfb2_device *fbdev;
+ struct omap_dss_device *dssdev;
+ u8 bpp_override;
+ enum omapfb_update_mode update_mode;
+ bool auto_update_work_enabled;
+ struct delayed_work auto_update_work;
+};
+
struct omapfb2_device {
struct device *dev;
struct mutex mtx;
@@ -86,17 +95,13 @@ struct omapfb2_device {
struct omapfb2_mem_region regions[10];
unsigned num_displays;
- struct omap_dss_device *displays[10];
+ struct omapfb_display_data displays[10];
unsigned num_overlays;
struct omap_overlay *overlays[10];
unsigned num_managers;
struct omap_overlay_manager *managers[10];
- unsigned num_bpp_overrides;
- struct {
- struct omap_dss_device *dssdev;
- u8 bpp;
- } bpp_overrides[10];
+ struct workqueue_struct *auto_update_wq;
};
struct omapfb_colormode {
@@ -128,6 +133,13 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
u16 posx, u16 posy, u16 outw, u16 outh);
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display);
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display);
+int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
+int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
+
/* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
@@ -143,6 +155,19 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
return NULL;
}
+static inline struct omapfb_display_data *get_display_data(
+ struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
+{
+ int i;
+
+ for (i = 0; i < fbdev->num_displays; ++i)
+ if (fbdev->displays[i].dssdev == dssdev)
+ return &fbdev->displays[i];
+
+ /* This should never happen */
+ BUG();
+}
+
static inline void omapfb_lock(struct omapfb2_device *fbdev)
{
mutex_lock(&fbdev->mtx);
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
index 5ec4f2d..50e0039 100644
--- a/drivers/video/pnx4008/sdum.c
+++ b/drivers/video/pnx4008/sdum.c
@@ -30,7 +30,7 @@
#include <linux/clk.h>
#include <linux/gfp.h>
#include <asm/uaccess.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include "sdum.h"
#include "fbcommon.h"
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index fabc90d..d8ab7be 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1816,8 +1816,6 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
specs->modedb, specs->modedb_len,
NULL, 8);
} else if (specs->modedb != NULL) {
- /* get first mode in database as fallback */
- modedb = specs->modedb[0];
/* get preferred timing */
if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
int i;
@@ -1828,6 +1826,9 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
break;
}
}
+ } else {
+ /* otherwise, get first mode in database */
+ modedb = specs->modedb[0];
}
var->bits_per_pixel = 8;
riva_update_var(var, &modedb);
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
index bbcc055..bfefa62 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/savage/savagefb_accel.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/fb.h>
+#include <linux/module.h>
#include "savagefb.h"
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 4de541c..beb4950 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r
vgaHWProtect(par, 0);
}
-static void savagefb_update_start(struct savagefb_par *par,
- struct fb_var_screeninfo *var)
+static void savagefb_update_start(struct savagefb_par *par, int base)
{
- int base;
-
- base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
- * ((var->bits_per_pixel+7) / 8)) >> 2;
-
- /* now program the start address registers */
+ /* program the start address registers */
vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
vga_out8(0x3d4, 0x69, par);
@@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct savagefb_par *par = info->par;
+ int base;
+
+ base = (var->yoffset * info->fix.line_length
+ + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
- savagefb_update_start(par, var);
+ savagefb_update_start(par, base);
return 0;
}
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 7525984..078ca21 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
}
static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
+ struct fb_var_screeninfo *var)
{
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
-
- ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
+ ivideo->current_base = var->yoffset * info->var.xres_virtual
+ + var->xoffset;
/* calculate base bpp dep. */
- switch(var->bits_per_pixel) {
+ switch (info->var.bits_per_pixel) {
case 32:
break;
case 16:
@@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
int err;
- if(var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
-
- if(var->yoffset > (var->yres_virtual - var->yres))
- return -EINVAL;
-
- if(var->vmode & FB_VMODE_YWRAP)
+ if (var->vmode & FB_VMODE_YWRAP)
return -EINVAL;
- if(var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
+ if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+ var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
- if((err = sisfb_pan_var(ivideo, var)) < 0)
+ err = sisfb_pan_var(ivideo, info, var);
+ if (err < 0)
return err;
info->var.xoffset = var->xoffset;
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
index 7491abf..43d11ec 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/vermilion/vermilion.h
@@ -31,7 +31,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/mutex.h>
#define VML_DEVICE_GPU 0x5002
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index b1f3647..9138e51 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
}
/* DVI Set Mode */
-void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
- int set_iga)
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga)
{
- struct VideoModeTable *rb_mode;
- struct crt_mode_table *pDviTiming;
- unsigned long desirePixelClock, maxPixelClock;
- pDviTiming = mode->crtc;
- desirePixelClock = pDviTiming->refresh_rate
- * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total
- / 1000000;
- maxPixelClock = (unsigned long)viaparinfo->
- tmds_setting_info->max_pixel_clock;
-
- DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
-
- if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
- rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
- mode->crtc[0].crtc.ver_addr);
- if (rb_mode) {
- mode = rb_mode;
- pDviTiming = rb_mode->crtc;
- }
+ struct fb_var_screeninfo dvi_var = *var;
+ struct crt_mode_table *rb_mode;
+ int maxPixelClock;
+
+ maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
+ if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
+ rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
+ if (rb_mode)
+ viafb_fill_var_timing_info(&dvi_var, rb_mode);
}
- viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
+
+ viafb_fill_crtc_timing(&dvi_var, iga);
}
/* Sense DVI Connector */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index f473dd0..e2116aa 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -59,7 +59,6 @@ void viafb_dvi_enable(void);
bool __devinit viafb_tmds_trasmitter_identify(void);
void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
struct tmds_setting_information *tmds_setting);
-void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp,
- int set_iga);
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga);
#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index e10d824..3102171 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -35,6 +35,8 @@ int viafb_LCD_ON ;
int viafb_LCD2_ON;
int viafb_SAMM_ON;
int viafb_dual_fb;
+unsigned int viafb_second_xres = 640;
+unsigned int viafb_second_yres = 480;
int viafb_hotplug_Xres = 640;
int viafb_hotplug_Yres = 480;
int viafb_hotplug_bpp = 32;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index ff969dc..275dbbb 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method;
extern int viafb_lcd_mode;
extern int viafb_CRT_ON;
+extern unsigned int viafb_second_xres;
+extern unsigned int viafb_second_yres;
extern int viafb_hotplug_Xres;
extern int viafb_hotplug_Yres;
extern int viafb_hotplug_bpp;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 47b1353..8497727 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = {
{IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
};
-static struct iga1_crtc_timing iga1_crtc_reg = {
- /* IGA1 Horizontal Total */
- {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
- /* IGA1 Horizontal Addressable Video */
- {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
- /* IGA1 Horizontal Blank Start */
- {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
- /* IGA1 Horizontal Blank End */
- {IGA1_HOR_BLANK_END_REG_NUM,
- {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
- /* IGA1 Horizontal Sync Start */
- {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
- /* IGA1 Horizontal Sync End */
- {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
- /* IGA1 Vertical Total */
- {IGA1_VER_TOTAL_REG_NUM,
- {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
- /* IGA1 Vertical Addressable Video */
- {IGA1_VER_ADDR_REG_NUM,
- {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
- /* IGA1 Vertical Blank Start */
- {IGA1_VER_BLANK_START_REG_NUM,
- {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
- /* IGA1 Vertical Blank End */
- {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
- /* IGA1 Vertical Sync Start */
- {IGA1_VER_SYNC_START_REG_NUM,
- {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
- /* IGA1 Vertical Sync End */
- {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
-};
-
-static struct iga2_crtc_timing iga2_crtc_reg = {
- /* IGA2 Horizontal Total */
- {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
- /* IGA2 Horizontal Addressable Video */
- {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
- /* IGA2 Horizontal Blank Start */
- {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
- /* IGA2 Horizontal Blank End */
- {IGA2_HOR_BLANK_END_REG_NUM,
- {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
- /* IGA2 Horizontal Sync Start */
- {IGA2_HOR_SYNC_START_REG_NUM,
- {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
- /* IGA2 Horizontal Sync End */
- {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
- /* IGA2 Vertical Total */
- {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
- /* IGA2 Vertical Addressable Video */
- {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
- /* IGA2 Vertical Blank Start */
- {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
- /* IGA2 Vertical Blank End */
- {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
- /* IGA2 Vertical Sync Start */
- {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
- /* IGA2 Vertical Sync End */
- {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
-};
-
static struct rgbLUT palLUT_table[] = {
/* {R,G,B} */
/* Index 0x00~0x03 */
@@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga)
via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
}
-void viafb_load_crtc_timing(struct display_timing device_timing,
- int set_iga)
+static struct display_timing var_to_timing(const struct fb_var_screeninfo *var)
{
- int i;
- int viafb_load_reg_num = 0;
- int reg_value = 0;
- struct io_register *reg = NULL;
-
- viafb_unlock_crt();
-
- for (i = 0; i < 12; i++) {
- if (set_iga == IGA1) {
- switch (i) {
- case H_TOTAL_INDEX:
- reg_value =
- IGA1_HOR_TOTAL_FORMULA(device_timing.
- hor_total);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_total.reg_num;
- reg = iga1_crtc_reg.hor_total.reg;
- break;
- case H_ADDR_INDEX:
- reg_value =
- IGA1_HOR_ADDR_FORMULA(device_timing.
- hor_addr);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_addr.reg_num;
- reg = iga1_crtc_reg.hor_addr.reg;
- break;
- case H_BLANK_START_INDEX:
- reg_value =
- IGA1_HOR_BLANK_START_FORMULA
- (device_timing.hor_blank_start);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_blank_start.reg_num;
- reg = iga1_crtc_reg.hor_blank_start.reg;
- break;
- case H_BLANK_END_INDEX:
- reg_value =
- IGA1_HOR_BLANK_END_FORMULA
- (device_timing.hor_blank_start,
- device_timing.hor_blank_end);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_blank_end.reg_num;
- reg = iga1_crtc_reg.hor_blank_end.reg;
- break;
- case H_SYNC_START_INDEX:
- reg_value =
- IGA1_HOR_SYNC_START_FORMULA
- (device_timing.hor_sync_start);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_sync_start.reg_num;
- reg = iga1_crtc_reg.hor_sync_start.reg;
- break;
- case H_SYNC_END_INDEX:
- reg_value =
- IGA1_HOR_SYNC_END_FORMULA
- (device_timing.hor_sync_start,
- device_timing.hor_sync_end);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_sync_end.reg_num;
- reg = iga1_crtc_reg.hor_sync_end.reg;
- break;
- case V_TOTAL_INDEX:
- reg_value =
- IGA1_VER_TOTAL_FORMULA(device_timing.
- ver_total);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_total.reg_num;
- reg = iga1_crtc_reg.ver_total.reg;
- break;
- case V_ADDR_INDEX:
- reg_value =
- IGA1_VER_ADDR_FORMULA(device_timing.
- ver_addr);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_addr.reg_num;
- reg = iga1_crtc_reg.ver_addr.reg;
- break;
- case V_BLANK_START_INDEX:
- reg_value =
- IGA1_VER_BLANK_START_FORMULA
- (device_timing.ver_blank_start);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_blank_start.reg_num;
- reg = iga1_crtc_reg.ver_blank_start.reg;
- break;
- case V_BLANK_END_INDEX:
- reg_value =
- IGA1_VER_BLANK_END_FORMULA
- (device_timing.ver_blank_start,
- device_timing.ver_blank_end);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_blank_end.reg_num;
- reg = iga1_crtc_reg.ver_blank_end.reg;
- break;
- case V_SYNC_START_INDEX:
- reg_value =
- IGA1_VER_SYNC_START_FORMULA
- (device_timing.ver_sync_start);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_sync_start.reg_num;
- reg = iga1_crtc_reg.ver_sync_start.reg;
- break;
- case V_SYNC_END_INDEX:
- reg_value =
- IGA1_VER_SYNC_END_FORMULA
- (device_timing.ver_sync_start,
- device_timing.ver_sync_end);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_sync_end.reg_num;
- reg = iga1_crtc_reg.ver_sync_end.reg;
- break;
-
- }
- }
-
- if (set_iga == IGA2) {
- switch (i) {
- case H_TOTAL_INDEX:
- reg_value =
- IGA2_HOR_TOTAL_FORMULA(device_timing.
- hor_total);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_total.reg_num;
- reg = iga2_crtc_reg.hor_total.reg;
- break;
- case H_ADDR_INDEX:
- reg_value =
- IGA2_HOR_ADDR_FORMULA(device_timing.
- hor_addr);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_addr.reg_num;
- reg = iga2_crtc_reg.hor_addr.reg;
- break;
- case H_BLANK_START_INDEX:
- reg_value =
- IGA2_HOR_BLANK_START_FORMULA
- (device_timing.hor_blank_start);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_blank_start.reg_num;
- reg = iga2_crtc_reg.hor_blank_start.reg;
- break;
- case H_BLANK_END_INDEX:
- reg_value =
- IGA2_HOR_BLANK_END_FORMULA
- (device_timing.hor_blank_start,
- device_timing.hor_blank_end);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_blank_end.reg_num;
- reg = iga2_crtc_reg.hor_blank_end.reg;
- break;
- case H_SYNC_START_INDEX:
- reg_value =
- IGA2_HOR_SYNC_START_FORMULA
- (device_timing.hor_sync_start);
- if (UNICHROME_CN700 <=
- viaparinfo->chip_info->gfx_chip_name)
- viafb_load_reg_num =
- iga2_crtc_reg.hor_sync_start.
- reg_num;
- else
- viafb_load_reg_num = 3;
- reg = iga2_crtc_reg.hor_sync_start.reg;
- break;
- case H_SYNC_END_INDEX:
- reg_value =
- IGA2_HOR_SYNC_END_FORMULA
- (device_timing.hor_sync_start,
- device_timing.hor_sync_end);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_sync_end.reg_num;
- reg = iga2_crtc_reg.hor_sync_end.reg;
- break;
- case V_TOTAL_INDEX:
- reg_value =
- IGA2_VER_TOTAL_FORMULA(device_timing.
- ver_total);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_total.reg_num;
- reg = iga2_crtc_reg.ver_total.reg;
- break;
- case V_ADDR_INDEX:
- reg_value =
- IGA2_VER_ADDR_FORMULA(device_timing.
- ver_addr);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_addr.reg_num;
- reg = iga2_crtc_reg.ver_addr.reg;
- break;
- case V_BLANK_START_INDEX:
- reg_value =
- IGA2_VER_BLANK_START_FORMULA
- (device_timing.ver_blank_start);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_blank_start.reg_num;
- reg = iga2_crtc_reg.ver_blank_start.reg;
- break;
- case V_BLANK_END_INDEX:
- reg_value =
- IGA2_VER_BLANK_END_FORMULA
- (device_timing.ver_blank_start,
- device_timing.ver_blank_end);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_blank_end.reg_num;
- reg = iga2_crtc_reg.ver_blank_end.reg;
- break;
- case V_SYNC_START_INDEX:
- reg_value =
- IGA2_VER_SYNC_START_FORMULA
- (device_timing.ver_sync_start);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_sync_start.reg_num;
- reg = iga2_crtc_reg.ver_sync_start.reg;
- break;
- case V_SYNC_END_INDEX:
- reg_value =
- IGA2_VER_SYNC_END_FORMULA
- (device_timing.ver_sync_start,
- device_timing.ver_sync_end);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_sync_end.reg_num;
- reg = iga2_crtc_reg.ver_sync_end.reg;
- break;
-
- }
- }
- viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
- }
-
- viafb_lock_crt();
+ struct display_timing timing;
+
+ timing.hor_addr = var->xres;
+ timing.hor_sync_start = timing.hor_addr + var->right_margin;
+ timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
+ timing.hor_total = timing.hor_sync_end + var->left_margin;
+ timing.hor_blank_start = timing.hor_addr;
+ timing.hor_blank_end = timing.hor_total;
+ timing.ver_addr = var->yres;
+ timing.ver_sync_start = timing.ver_addr + var->lower_margin;
+ timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
+ timing.ver_total = timing.ver_sync_end + var->upper_margin;
+ timing.ver_blank_start = timing.ver_addr;
+ timing.ver_blank_end = timing.ver_total;
+ return timing;
}
-void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
- struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga)
{
- struct display_timing crt_reg;
- int i;
- int index = 0;
- int h_addr, v_addr;
- u32 clock, refresh = viafb_refresh;
-
- if (viafb_SAMM_ON && set_iga == IGA2)
- refresh = viafb_refresh1;
-
- for (i = 0; i < video_mode->mode_array; i++) {
- index = i;
-
- if (crt_table[i].refresh_rate == refresh)
- break;
- }
-
- crt_reg = crt_table[index].crtc;
-
- /* Mode 640x480 has border, but LCD/DFP didn't have border. */
- /* So we would delete border. */
- if ((viafb_LCD_ON | viafb_DVI_ON)
- && video_mode->crtc[0].crtc.hor_addr == 640
- && video_mode->crtc[0].crtc.ver_addr == 480
- && refresh == 60) {
- /* The border is 8 pixels. */
- crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
-
- /* Blanking time should add left and right borders. */
- crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
- }
-
- h_addr = crt_reg.hor_addr;
- v_addr = crt_reg.ver_addr;
- if (set_iga == IGA1) {
- viafb_unlock_crt();
- viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
- }
-
- switch (set_iga) {
- case IGA1:
- viafb_load_crtc_timing(crt_reg, IGA1);
- break;
- case IGA2:
- viafb_load_crtc_timing(crt_reg, IGA2);
- break;
- }
-
- viafb_lock_crt();
- viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
- viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
+ struct display_timing crt_reg = var_to_timing(var);
- /* load FIFO */
- if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
- && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
- viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
+ if (iga == IGA1)
+ via_set_primary_timing(&crt_reg);
+ else if (iga == IGA2)
+ via_set_secondary_timing(&crt_reg);
- clock = crt_reg.hor_total * crt_reg.ver_total
- * crt_table[index].refresh_rate;
- viafb_set_vclock(clock, set_iga);
+ viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
+ if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
+ && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
+ viafb_load_FIFO_reg(iga, var->xres, var->yres);
+ viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
}
void __devinit viafb_init_chip_info(int chip_type)
@@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info)
return polarity;
}
-int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
- struct VideoModeTable *vmode_tbl1, int video_bpp1)
+static void hw_init(void)
{
- int i, j;
- int port;
- u32 devices = viaparinfo->shared->iga1_devices
- | viaparinfo->shared->iga2_devices;
- u8 value, index, mask;
- struct crt_mode_table *crt_timing;
- struct crt_mode_table *crt_timing1 = NULL;
-
- device_screen_off();
- crt_timing = vmode_tbl->crtc;
-
- if (viafb_SAMM_ON == 1) {
- crt_timing1 = vmode_tbl1->crtc;
- }
+ int i;
inb(VIAStatus);
outb(0x00, VIAAR);
@@ -2147,9 +1810,12 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
break;
}
+ /* magic required on VX900 for correct modesetting on IGA1 */
+ via_write_reg_mask(VIACR, 0x45, 0x00, 0x01);
+
+ /* probably this should go to the scaling code one day */
+ via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */
viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
- device_off();
- via_set_state(devices, VIA_STATE_OFF);
/* Fill VPIT Parameters */
/* Write Misc Register */
@@ -2175,12 +1841,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
inb(VIAStatus);
outb(0x20, VIAAR);
+ load_fix_bit_crtc_reg();
+}
+
+int viafb_setmode(int video_bpp, int video_bpp1)
+{
+ int j;
+ int port;
+ u32 devices = viaparinfo->shared->iga1_devices
+ | viaparinfo->shared->iga2_devices;
+ u8 value, index, mask;
+ struct fb_var_screeninfo var2;
+
+ device_screen_off();
+ device_off();
+ via_set_state(devices, VIA_STATE_OFF);
+
+ hw_init();
+
/* Update Patch Register */
if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
- || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
- && vmode_tbl->crtc[0].crtc.hor_addr == 1024
- && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
+ || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
+ && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
for (j = 0; j < res_patch_table[0].table_length; j++) {
index = res_patch_table[0].io_reg_table[j].index;
port = res_patch_table[0].io_reg_table[j].port;
@@ -2190,7 +1873,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
}
}
- load_fix_bit_crtc_reg();
via_set_primary_pitch(viafbinfo->fix.line_length);
via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
: viafbinfo->fix.line_length);
@@ -2208,23 +1890,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
/* Clear On Screen */
+ if (viafb_dual_fb) {
+ var2 = viafbinfo1->var;
+ } else if (viafb_SAMM_ON) {
+ viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
+ viafb_second_xres, viafb_second_yres, viafb_refresh1));
+ var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
+ }
+
/* CRT set mode */
if (viafb_CRT_ON) {
- if (viafb_SAMM_ON &&
- viaparinfo->shared->iga2_devices & VIA_CRT) {
- viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
- video_bpp1 / 8, IGA2);
- } else {
- viafb_fill_crtc_timing(crt_timing, vmode_tbl,
- video_bpp / 8,
+ if (viaparinfo->shared->iga2_devices & VIA_CRT
+ && viafb_SAMM_ON)
+ viafb_fill_crtc_timing(&var2, IGA2);
+ else
+ viafb_fill_crtc_timing(&viafbinfo->var,
(viaparinfo->shared->iga1_devices & VIA_CRT)
? IGA1 : IGA2);
- }
/* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
to 8 alignment (1368),there is several pixels (2 pixels)
on right side of screen. */
- if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
+ if (viafbinfo->var.xres % 8) {
viafb_unlock_crt();
viafb_write_reg(CR02, VIACR,
viafb_read_reg(VIACR, CR02) - 1);
@@ -2233,31 +1920,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
}
if (viafb_DVI_ON) {
- if (viafb_SAMM_ON &&
- (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
- viafb_dvi_set_mode(viafb_get_mode
- (viaparinfo->tmds_setting_info->h_active,
- viaparinfo->tmds_setting_info->
- v_active),
- video_bpp1, viaparinfo->
- tmds_setting_info->iga_path);
- } else {
- viafb_dvi_set_mode(viafb_get_mode
- (viaparinfo->tmds_setting_info->h_active,
- viaparinfo->
- tmds_setting_info->v_active),
- video_bpp, viaparinfo->
- tmds_setting_info->iga_path);
- }
+ if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
+ && viafb_SAMM_ON)
+ viafb_dvi_set_mode(&var2, IGA2);
+ else
+ viafb_dvi_set_mode(&viafbinfo->var,
+ viaparinfo->tmds_setting_info->iga_path);
}
if (viafb_LCD_ON) {
if (viafb_SAMM_ON &&
(viaparinfo->lvds_setting_info->iga_path == IGA2)) {
viaparinfo->lvds_setting_info->bpp = video_bpp1;
- viafb_lcd_set_mode(crt_timing1, viaparinfo->
- lvds_setting_info,
- &viaparinfo->chip_info->lvds_chip_info);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
} else {
/* IGA1 doesn't have LCD scaling, so set it center. */
if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
@@ -2265,18 +1941,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
LCD_CENTERING;
}
viaparinfo->lvds_setting_info->bpp = video_bpp;
- viafb_lcd_set_mode(crt_timing, viaparinfo->
- lvds_setting_info,
- &viaparinfo->chip_info->lvds_chip_info);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
}
}
if (viafb_LCD2_ON) {
if (viafb_SAMM_ON &&
(viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
viaparinfo->lvds_setting_info2->bpp = video_bpp1;
- viafb_lcd_set_mode(crt_timing1, viaparinfo->
- lvds_setting_info2,
- &viaparinfo->chip_info->lvds_chip_info2);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2);
} else {
/* IGA1 doesn't have LCD scaling, so set it center. */
if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
@@ -2284,9 +1958,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
LCD_CENTERING;
}
viaparinfo->lvds_setting_info2->bpp = video_bpp;
- viafb_lcd_set_mode(crt_timing, viaparinfo->
- lvds_setting_info2,
- &viaparinfo->chip_info->lvds_chip_info2);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2);
}
}
@@ -2296,8 +1969,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
/* If set mode normally, save resolution information for hot-plug . */
if (!viafb_hotplug) {
- viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
- viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
+ viafb_hotplug_Xres = viafbinfo->var.xres;
+ viafb_hotplug_Yres = viafbinfo->var.yres;
viafb_hotplug_bpp = video_bpp;
viafb_hotplug_refresh = viafb_refresh;
@@ -2348,42 +2021,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
return 1;
}
-int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
-{
- int i;
- struct crt_mode_table *best;
- struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
-
- if (!vmode)
- return RES_640X480_60HZ_PIXCLOCK;
-
- best = &vmode->crtc[0];
- for (i = 1; i < vmode->mode_array; i++) {
- if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
- < abs(best->refresh_rate - vmode_refresh))
- best = &vmode->crtc[i];
- }
-
- return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
- * 1000 / best->refresh_rate;
-}
-
int viafb_get_refresh(int hres, int vres, u32 long_refresh)
{
- int i;
struct crt_mode_table *best;
- struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
- if (!vmode)
+ best = viafb_get_best_mode(hres, vres, long_refresh);
+ if (!best)
return 60;
- best = &vmode->crtc[0];
- for (i = 1; i < vmode->mode_array; i++) {
- if (abs(vmode->crtc[i].refresh_rate - long_refresh)
- < abs(best->refresh_rate - long_refresh))
- best = &vmode->crtc[i];
- }
-
if (abs(best->refresh_rate - long_refresh) > 3) {
if (hres == 1200 && vres == 900)
return 49; /* OLPC DCON only supports 50 Hz */
@@ -2485,21 +2130,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
}
/*According var's xres, yres fill var's other timing information*/
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
- struct VideoModeTable *vmode_tbl)
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+ struct crt_mode_table *mode)
{
- struct crt_mode_table *crt_timing = NULL;
struct display_timing crt_reg;
- int i = 0, index = 0;
- crt_timing = vmode_tbl->crtc;
- for (i = 0; i < vmode_tbl->mode_array; i++) {
- index = i;
- if (crt_timing[i].refresh_rate == refresh)
- break;
- }
- crt_reg = crt_timing[index].crtc;
- var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
+ crt_reg = mode->crtc;
+ var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total)
+ * 1000 / mode->refresh_rate;
var->left_margin =
crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
@@ -2509,8 +2147,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
var->vsync_len = crt_reg.ver_sync_end;
var->sync = 0;
- if (crt_timing[index].h_sync_polarity == POSITIVE)
+ if (mode->h_sync_polarity == POSITIVE)
var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (crt_timing[index].v_sync_polarity == POSITIVE)
+ if (mode->v_sync_polarity == POSITIVE)
var->sync |= FB_SYNC_VERT_HIGH_ACT;
}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index c7239eb..4db5b6e 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -51,40 +51,6 @@
#define VIA_HSYNC_NEGATIVE 0x01
#define VIA_VSYNC_NEGATIVE 0x02
-/***************************************************
-* Definition IGA1 Design Method of CRTC Registers *
-****************************************************/
-#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5)
-#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1)
-#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1)
-#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1)
-#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8)
-#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8)
-
-#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2)
-#define IGA1_VER_ADDR_FORMULA(x) ((x)-1)
-#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1)
-#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
-#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1)
-#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
-
-/***************************************************
-** Definition IGA2 Design Method of CRTC Registers *
-****************************************************/
-#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1)
-#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1)
-#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1)
-#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1)
-#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1)
-#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1)
-
-#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1)
-#define IGA2_VER_ADDR_FORMULA(x) ((x)-1)
-#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1)
-#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
-#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1)
-#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
-
/**********************************************************/
/* Definition IGA2 Design Method of CRTC Shadow Registers */
/**********************************************************/
@@ -97,33 +63,6 @@
#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
-/* Define Register Number for IGA1 CRTC Timing */
-
-/* location: {CR00,0,7},{CR36,3,3} */
-#define IGA1_HOR_TOTAL_REG_NUM 2
-/* location: {CR01,0,7} */
-#define IGA1_HOR_ADDR_REG_NUM 1
-/* location: {CR02,0,7} */
-#define IGA1_HOR_BLANK_START_REG_NUM 1
-/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
-#define IGA1_HOR_BLANK_END_REG_NUM 3
-/* location: {CR04,0,7},{CR33,4,4} */
-#define IGA1_HOR_SYNC_START_REG_NUM 2
-/* location: {CR05,0,4} */
-#define IGA1_HOR_SYNC_END_REG_NUM 1
-/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
-#define IGA1_VER_TOTAL_REG_NUM 4
-/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
-#define IGA1_VER_ADDR_REG_NUM 4
-/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
-#define IGA1_VER_BLANK_START_REG_NUM 4
-/* location: {CR16,0,7} */
-#define IGA1_VER_BLANK_END_REG_NUM 1
-/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
-#define IGA1_VER_SYNC_START_REG_NUM 4
-/* location: {CR11,0,3} */
-#define IGA1_VER_SYNC_END_REG_NUM 1
-
/* Define Register Number for IGA2 Shadow CRTC Timing */
/* location: {CR6D,0,7},{CR71,3,3} */
@@ -143,37 +82,6 @@
/* location: {CR76,0,3} */
#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
-/* Define Register Number for IGA2 CRTC Timing */
-
-/* location: {CR50,0,7},{CR55,0,3} */
-#define IGA2_HOR_TOTAL_REG_NUM 2
-/* location: {CR51,0,7},{CR55,4,6} */
-#define IGA2_HOR_ADDR_REG_NUM 2
-/* location: {CR52,0,7},{CR54,0,2} */
-#define IGA2_HOR_BLANK_START_REG_NUM 2
-/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
-is reserved, so it may have problem to set 1600x1200 on IGA2. */
-/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
-#define IGA2_HOR_BLANK_END_REG_NUM 3
-/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
-/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
-#define IGA2_HOR_SYNC_START_REG_NUM 4
-
-/* location: {CR57,0,7},{CR5C,6,6} */
-#define IGA2_HOR_SYNC_END_REG_NUM 2
-/* location: {CR58,0,7},{CR5D,0,2} */
-#define IGA2_VER_TOTAL_REG_NUM 2
-/* location: {CR59,0,7},{CR5D,3,5} */
-#define IGA2_VER_ADDR_REG_NUM 2
-/* location: {CR5A,0,7},{CR5C,0,2} */
-#define IGA2_VER_BLANK_START_REG_NUM 2
-/* location: {CR5E,0,7},{CR5C,3,5} */
-#define IGA2_VER_BLANK_END_REG_NUM 2
-/* location: {CR5E,0,7},{CR5F,5,7} */
-#define IGA2_VER_SYNC_START_REG_NUM 2
-/* location: {CR5F,0,4} */
-#define IGA2_VER_SYNC_END_REG_NUM 1
-
/* Define Fetch Count Register*/
/* location: {SR1C,0,7},{SR1D,0,1} */
@@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
/* location: {CR78,0,7},{CR79,6,7} */
#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
-/************************************************
- ***** Define IGA1 Display Timing *****
- ************************************************/
struct io_register {
u8 io_addr;
u8 start_bit;
u8 end_bit;
};
-/* IGA1 Horizontal Total */
-struct iga1_hor_total {
- int reg_num;
- struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA1 Horizontal Addressable Video */
-struct iga1_hor_addr {
- int reg_num;
- struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
-};
-
-/* IGA1 Horizontal Blank Start */
-struct iga1_hor_blank_start {
- int reg_num;
- struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
-};
-
-/* IGA1 Horizontal Blank End */
-struct iga1_hor_blank_end {
- int reg_num;
- struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA1 Horizontal Sync Start */
-struct iga1_hor_sync_start {
- int reg_num;
- struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
-};
-
-/* IGA1 Horizontal Sync End */
-struct iga1_hor_sync_end {
- int reg_num;
- struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
-};
-
-/* IGA1 Vertical Total */
-struct iga1_ver_total {
- int reg_num;
- struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
-};
-
-/* IGA1 Vertical Addressable Video */
-struct iga1_ver_addr {
- int reg_num;
- struct io_register reg[IGA1_VER_ADDR_REG_NUM];
-};
-
-/* IGA1 Vertical Blank Start */
-struct iga1_ver_blank_start {
- int reg_num;
- struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA1 Vertical Blank End */
-struct iga1_ver_blank_end {
- int reg_num;
- struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA1 Vertical Sync Start */
-struct iga1_ver_sync_start {
- int reg_num;
- struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA1 Vertical Sync End */
-struct iga1_ver_sync_end {
- int reg_num;
- struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
-};
-
/*****************************************************
** Define IGA2 Shadow Display Timing ****
*****************************************************/
@@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end {
struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
};
-/*****************************************************
-** Define IGA2 Display Timing ****
-******************************************************/
-
-/* IGA2 Horizontal Total */
-struct iga2_hor_total {
- int reg_num;
- struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA2 Horizontal Addressable Video */
-struct iga2_hor_addr {
- int reg_num;
- struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
-};
-
-/* IGA2 Horizontal Blank Start */
-struct iga2_hor_blank_start {
- int reg_num;
- struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Horizontal Blank End */
-struct iga2_hor_blank_end {
- int reg_num;
- struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Horizontal Sync Start */
-struct iga2_hor_sync_start {
- int reg_num;
- struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Horizontal Sync End */
-struct iga2_hor_sync_end {
- int reg_num;
- struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
-};
-
-/* IGA2 Vertical Total */
-struct iga2_ver_total {
- int reg_num;
- struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
-};
-
-/* IGA2 Vertical Addressable Video */
-struct iga2_ver_addr {
- int reg_num;
- struct io_register reg[IGA2_VER_ADDR_REG_NUM];
-};
-
-/* IGA2 Vertical Blank Start */
-struct iga2_ver_blank_start {
- int reg_num;
- struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Vertical Blank End */
-struct iga2_ver_blank_end {
- int reg_num;
- struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Vertical Sync Start */
-struct iga2_ver_sync_start {
- int reg_num;
- struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Vertical Sync End */
-struct iga2_ver_sync_end {
- int reg_num;
- struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
-};
-
/* IGA1 Fetch Count Register */
struct iga1_fetch_count {
int reg_num;
@@ -817,21 +574,6 @@ struct display_queue_expire_num {
iga2_display_queue_expire_num_reg;
};
-struct iga1_crtc_timing {
- struct iga1_hor_total hor_total;
- struct iga1_hor_addr hor_addr;
- struct iga1_hor_blank_start hor_blank_start;
- struct iga1_hor_blank_end hor_blank_end;
- struct iga1_hor_sync_start hor_sync_start;
- struct iga1_hor_sync_end hor_sync_end;
- struct iga1_ver_total ver_total;
- struct iga1_ver_addr ver_addr;
- struct iga1_ver_blank_start ver_blank_start;
- struct iga1_ver_blank_end ver_blank_end;
- struct iga1_ver_sync_start ver_sync_start;
- struct iga1_ver_sync_end ver_sync_end;
-};
-
struct iga2_shadow_crtc_timing {
struct iga2_shadow_hor_total hor_total_shadow;
struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
@@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing {
struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
};
-struct iga2_crtc_timing {
- struct iga2_hor_total hor_total;
- struct iga2_hor_addr hor_addr;
- struct iga2_hor_blank_start hor_blank_start;
- struct iga2_hor_blank_end hor_blank_end;
- struct iga2_hor_sync_start hor_sync_start;
- struct iga2_hor_sync_end hor_sync_end;
- struct iga2_ver_total ver_total;
- struct iga2_ver_addr ver_addr;
- struct iga2_ver_blank_start ver_blank_start;
- struct iga2_ver_blank_end ver_blank_end;
- struct iga2_ver_sync_start ver_sync_start;
- struct iga2_ver_sync_end ver_sync_end;
-};
-
/* device ID */
#define CLE266_FUNCTION3 0x3123
#define KM400_FUNCTION3 0x3205
@@ -910,9 +637,7 @@ extern int viafb_LCD_ON;
extern int viafb_DVI_ON;
extern int viafb_hotplug;
-void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
- struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
-
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga);
void viafb_set_vclock(u32 CLK, int set_iga);
void viafb_load_reg(int timing_value, int viafb_load_reg_num,
struct io_register *reg,
@@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
*p_gfx_dpa_setting);
-int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
- struct VideoModeTable *vmode_tbl1, int video_bpp1);
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
- struct VideoModeTable *vmode_tbl);
+int viafb_setmode(int video_bpp, int video_bpp1);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+ struct crt_mode_table *mode);
void __devinit viafb_init_chip_info(int chip_type);
void __devinit viafb_init_dac(int set_iga);
-int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
int viafb_get_refresh(int hres, int vres, u32 float_refresh);
void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 6e06981..5f3b4e3 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information
}
/* LCD Set Mode */
-void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
- struct lvds_setting_information *plvds_setting_info,
- struct lvds_chip_information *plvds_chip_info)
+void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
{
int set_iga = plvds_setting_info->iga_path;
int mode_bpp = plvds_setting_info->bpp;
@@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
int panel_hres = plvds_setting_info->lcd_panel_hres;
int panel_vres = plvds_setting_info->lcd_panel_vres;
u32 clock;
- struct display_timing mode_crt_reg, panel_crt_reg;
- struct crt_mode_table *panel_crt_table = NULL;
- struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
- panel_vres);
+ struct display_timing mode_crt_reg, panel_crt_reg, timing;
+ struct crt_mode_table *mode_crt_table, *panel_crt_table;
DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
/* Get mode table */
+ mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
mode_crt_reg = mode_crt_table->crtc;
/* Get panel table Pointer */
- panel_crt_table = vmode_tbl->crtc;
+ panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
panel_crt_reg = panel_crt_table->crtc;
DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
@@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total
* panel_crt_table->refresh_rate;
plvds_setting_info->vclk = clock;
- if (set_iga == IGA1) {
- /* IGA1 doesn't have LCD scaling, so set it as centering. */
- viafb_load_crtc_timing(lcd_centering_timging
- (mode_crt_reg, panel_crt_reg), IGA1);
+
+ if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
+ && plvds_setting_info->display_method == LCD_EXPANDSION) {
+ timing = panel_crt_reg;
+ load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
} else {
- /* Expansion */
- if (plvds_setting_info->display_method == LCD_EXPANDSION
- && (set_hres < panel_hres || set_vres < panel_vres)) {
- /* expansion timing IGA2 loaded panel set timing*/
- viafb_load_crtc_timing(panel_crt_reg, IGA2);
- DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
- load_lcd_scaling(set_hres, set_vres, panel_hres,
- panel_vres);
- DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
- } else { /* Centering */
- /* centering timing IGA2 always loaded panel
- and mode releative timing */
- viafb_load_crtc_timing(lcd_centering_timging
- (mode_crt_reg, panel_crt_reg), IGA2);
- viafb_write_reg_mask(CR79, VIACR, 0x00,
+ timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg);
+ if (set_iga == IGA2)
+ /* disable scaling */
+ via_write_reg_mask(VIACR, 0x79, 0x00,
BIT0 + BIT1 + BIT2);
- /* LCD scaling disabled */
- }
}
+ timing.hor_blank_end += timing.hor_blank_start;
+ timing.hor_sync_end += timing.hor_sync_start;
+ timing.ver_blank_end += timing.ver_blank_start;
+ timing.ver_sync_end += timing.ver_sync_start;
+ if (set_iga == IGA1)
+ via_set_primary_timing(&timing);
+ else if (set_iga == IGA2)
+ via_set_secondary_timing(&timing);
+
/* Fetch count for IGA2 only */
viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
index 75f60a6..77ca7b8 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/via/lcd.h
@@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
*plvds_chip_info,
struct lvds_setting_information
*plvds_setting_info);
-void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
- struct lvds_setting_information *plvds_setting_info,
- struct lvds_chip_information *plvds_chip_info);
+void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
bool __devinit viafb_lvds_trasmitter_identify(void);
void viafb_init_lvds_output_interface(struct lvds_chip_information
*plvds_chip_info,
struct lvds_setting_information
*plvds_setting_info);
bool viafb_lcd_get_mobile_state(bool *mobile);
-void viafb_load_crtc_timing(struct display_timing device_timing,
- int set_iga);
#endif /* __LCD_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 1603023..c01c1c1 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -22,6 +22,8 @@
#ifndef __SHARE_H__
#define __SHARE_H__
+#include "via_modesetting.h"
+
/* Define Bit Field */
#define BIT0 0x01
#define BIT1 0x02
@@ -634,10 +636,6 @@
#define V_SYNC_SATRT_SHADOW_INDEX 18
#define V_SYNC_END_SHADOW_INDEX 19
-/* Definition Video Mode Pixel Clock (picoseconds)
-*/
-#define RES_640X480_60HZ_PIXCLOCK 39722
-
/* LCD display method
*/
#define LCD_EXPANDSION 0x00
@@ -648,23 +646,6 @@
#define LCD_OPENLDI 0x00
#define LCD_SPWG 0x01
-/* Define display timing
-*/
-struct display_timing {
- u16 hor_total;
- u16 hor_addr;
- u16 hor_blank_start;
- u16 hor_blank_end;
- u16 hor_sync_start;
- u16 hor_sync_end;
- u16 ver_total;
- u16 ver_addr;
- u16 ver_blank_start;
- u16 ver_blank_end;
- u16 ver_sync_start;
- u16 ver_sync_end;
-};
-
struct crt_mode_table {
int refresh_rate;
int h_sync_polarity;
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index eb112b6..dd58b53 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = {
* The OLPC XO-1.5 puts the camera power and reset lines onto
* GPIO 2C.
*/
-static const struct via_port_cfg olpc_adap_configs[] = {
+static struct via_port_cfg olpc_adap_configs[] = {
[VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
[VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
[VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
index ab53418..d69cfef 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/via/via-gpio.c
@@ -10,6 +10,7 @@
#include <linux/platform_device.h>
#include <linux/via-core.h>
#include <linux/via-gpio.h>
+#include <linux/export.h>
/*
* The ports we know about. Note that the port-25 gpios are not
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
index 3cddcff..0e431ae 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/via/via_modesetting.c
@@ -29,6 +29,110 @@
#include "share.h"
#include "debug.h"
+
+void via_set_primary_timing(const struct display_timing *timing)
+{
+ struct display_timing raw;
+
+ raw.hor_total = timing->hor_total / 8 - 5;
+ raw.hor_addr = timing->hor_addr / 8 - 1;
+ raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
+ raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
+ raw.hor_sync_start = timing->hor_sync_start / 8;
+ raw.hor_sync_end = timing->hor_sync_end / 8;
+ raw.ver_total = timing->ver_total - 2;
+ raw.ver_addr = timing->ver_addr - 1;
+ raw.ver_blank_start = timing->ver_blank_start - 1;
+ raw.ver_blank_end = timing->ver_blank_end - 1;
+ raw.ver_sync_start = timing->ver_sync_start - 1;
+ raw.ver_sync_end = timing->ver_sync_end - 1;
+
+ /* unlock timing registers */
+ via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
+
+ via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
+ via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
+ via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
+ via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
+ via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
+ via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
+ | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
+ via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
+ via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
+ | (raw.ver_addr >> (8 - 1) & 0x02)
+ | (raw.ver_sync_start >> (8 - 2) & 0x04)
+ | (raw.ver_blank_start >> (8 - 3) & 0x08)
+ | (raw.ver_total >> (9 - 5) & 0x20)
+ | (raw.ver_addr >> (9 - 6) & 0x40)
+ | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
+ via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
+ 0x20);
+ via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
+ via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
+ via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
+ via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
+ via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
+ via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
+ | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
+ via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
+ | (raw.ver_sync_start >> (10 - 1) & 0x02)
+ | (raw.ver_addr >> (10 - 2) & 0x04)
+ | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
+ via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
+
+ /* lock timing registers */
+ via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
+
+ /* reset timing control */
+ via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
+ via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
+}
+
+void via_set_secondary_timing(const struct display_timing *timing)
+{
+ struct display_timing raw;
+
+ raw.hor_total = timing->hor_total - 1;
+ raw.hor_addr = timing->hor_addr - 1;
+ raw.hor_blank_start = timing->hor_blank_start - 1;
+ raw.hor_blank_end = timing->hor_blank_end - 1;
+ raw.hor_sync_start = timing->hor_sync_start - 1;
+ raw.hor_sync_end = timing->hor_sync_end - 1;
+ raw.ver_total = timing->ver_total - 1;
+ raw.ver_addr = timing->ver_addr - 1;
+ raw.ver_blank_start = timing->ver_blank_start - 1;
+ raw.ver_blank_end = timing->ver_blank_end - 1;
+ raw.ver_sync_start = timing->ver_sync_start - 1;
+ raw.ver_sync_end = timing->ver_sync_end - 1;
+
+ via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
+ via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
+ via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
+ via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
+ via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
+ | (raw.hor_blank_end >> (8 - 3) & 0x38)
+ | (raw.hor_sync_start >> (8 - 6) & 0xC0));
+ via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
+ | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
+ via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
+ via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
+ via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
+ via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
+ via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
+ via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
+ via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
+ | (raw.ver_blank_end >> (8 - 3) & 0x38)
+ | (raw.hor_sync_end >> (8 - 6) & 0x40)
+ | (raw.hor_sync_start >> (10 - 7) & 0x80));
+ via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
+ | (raw.ver_addr >> (8 - 3) & 0x38)
+ | (raw.hor_blank_end >> (11 - 6) & 0x40)
+ | (raw.hor_sync_start >> (11 - 7) & 0x80));
+ via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
+ via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
+ | (raw.ver_sync_start >> (8 - 5) & 0xE0));
+}
+
void via_set_primary_address(u32 addr)
{
DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
index 0138845..06e09fe 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/via/via_modesetting.h
@@ -33,6 +33,24 @@
#define VIA_PITCH_MAX 0x3FF8
+struct display_timing {
+ u16 hor_total;
+ u16 hor_addr;
+ u16 hor_blank_start;
+ u16 hor_blank_end;
+ u16 hor_sync_start;
+ u16 hor_sync_end;
+ u16 ver_total;
+ u16 ver_addr;
+ u16 ver_blank_start;
+ u16 ver_blank_end;
+ u16 ver_sync_start;
+ u16 ver_sync_end;
+};
+
+
+void via_set_primary_timing(const struct display_timing *timing);
+void via_set_secondary_timing(const struct display_timing *timing);
void via_set_primary_address(u32 addr);
void via_set_secondary_address(u32 addr);
void via_set_primary_pitch(u32 pitch);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index dd1276e..a13c258 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -38,8 +38,6 @@ static char *viafb_mode1;
static int viafb_bpp = 32;
static int viafb_bpp1 = 32;
-static unsigned int viafb_second_xres = 640;
-static unsigned int viafb_second_yres = 480;
static unsigned int viafb_second_offset;
static int viafb_second_size;
@@ -201,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
int depth, refresh;
- struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par;
u32 line;
@@ -211,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
return -EINVAL;
- vmode_entry = viafb_get_mode(var->xres, var->yres);
- if (!vmode_entry) {
+ /* the refresh rate is not important here, as we only want to know
+ * whether the resolution exists
+ */
+ if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
DEBUG_MSG(KERN_INFO
"viafb: Mode %dx%dx%d not supported!!\n",
var->xres, var->yres, var->bits_per_pixel);
@@ -254,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
get_var_refresh(var));
/* Adjust var according to our driver's own table */
- viafb_fill_var_timing_info(var, refresh, vmode_entry);
+ viafb_fill_var_timing_info(var,
+ viafb_get_best_mode(var->xres, var->yres, refresh));
if (var->accel_flags & FB_ACCELF_TEXT &&
!ppar->shared->vdev->engine_mmio)
var->accel_flags = 0;
@@ -265,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
static int viafb_set_par(struct fb_info *info)
{
struct viafb_par *viapar = info->par;
- struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
int refresh;
DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
@@ -274,10 +273,7 @@ static int viafb_set_par(struct fb_info *info)
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
viafbinfo->var.bits_per_pixel, 0);
- vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
if (viafb_dual_fb) {
- vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
- viafbinfo1->var.yres);
viafb_update_device_setting(viafbinfo1->var.xres,
viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
1);
@@ -285,8 +281,6 @@ static int viafb_set_par(struct fb_info *info)
DEBUG_MSG(KERN_INFO
"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
viafb_second_xres, viafb_second_yres, viafb_bpp1);
- vmode_entry1 = viafb_get_mode(viafb_second_xres,
- viafb_second_yres);
viafb_update_device_setting(viafb_second_xres,
viafb_second_yres, viafb_bpp1, 1);
@@ -294,7 +288,8 @@ static int viafb_set_par(struct fb_info *info)
refresh = viafb_get_refresh(info->var.xres, info->var.yres,
get_var_refresh(&info->var));
- if (vmode_entry) {
+ if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres,
+ refresh)) {
if (viafb_dual_fb && viapar->iga_path == IGA2) {
viafb_bpp1 = info->var.bits_per_pixel;
viafb_refresh1 = refresh;
@@ -307,8 +302,7 @@ static int viafb_set_par(struct fb_info *info)
info->flags &= ~FBINFO_HWACCEL_DISABLED;
else
info->flags |= FBINFO_HWACCEL_DISABLED;
- viafb_setmode(vmode_entry, info->var.bits_per_pixel,
- vmode_entry1, viafb_bpp1);
+ viafb_setmode(info->var.bits_per_pixel, viafb_bpp1);
viafb_pan_display(&info->var, info);
}
@@ -1164,7 +1158,8 @@ static ssize_t viafb_dvp0_proc_write(struct file *file,
for (i = 0; i < 3; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0, (unsigned long *)&reg_val);
+ if (kstrtou8(value, 0, &reg_val) < 0)
+ return -EINVAL;
DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
reg_val);
switch (i) {
@@ -1234,7 +1229,8 @@ static ssize_t viafb_dvp1_proc_write(struct file *file,
for (i = 0; i < 3; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0, (unsigned long *)&reg_val);
+ if (kstrtou8(value, 0, &reg_val) < 0)
+ return -EINVAL;
switch (i) {
case 0:
viafb_write_reg_mask(CR9B, VIACR,
@@ -1292,7 +1288,8 @@ static ssize_t viafb_dfph_proc_write(struct file *file,
if (copy_from_user(&buf[0], buffer, length))
return -EFAULT;
buf[length - 1] = '\0'; /*Ensure end string */
- strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+ if (kstrtou8(buf, 0, &reg_val) < 0)
+ return -EINVAL;
viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
return count;
}
@@ -1331,7 +1328,8 @@ static ssize_t viafb_dfpl_proc_write(struct file *file,
if (copy_from_user(&buf[0], buffer, length))
return -EFAULT;
buf[length - 1] = '\0'; /*Ensure end string */
- strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+ if (kstrtou8(buf, 0, &reg_val) < 0)
+ return -EINVAL;
viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
return count;
}
@@ -1400,8 +1398,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
for (i = 0; i < 2; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0,
- (unsigned long *)&reg_val.Data);
+ if (kstrtou8(value, 0, &reg_val.Data) < 0)
+ return -EINVAL;
switch (i) {
case 0:
reg_val.Index = 0x08;
@@ -1437,8 +1435,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
for (i = 0; i < 2; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0,
- (unsigned long *)&reg_val.Data);
+ if (kstrtou8(value, 0, &reg_val.Data) < 0)
+ return -EINVAL;
switch (i) {
case 0:
reg_val.Index = 0x08;
@@ -1735,7 +1733,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
{
u32 default_xres, default_yres;
- struct VideoModeTable *vmode_entry;
struct fb_var_screeninfo default_var;
int rc;
u32 viafb_par_length;
@@ -1808,7 +1805,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
}
parse_mode(viafb_mode, &default_xres, &default_yres);
- vmode_entry = viafb_get_mode(default_xres, default_yres);
if (viafb_SAMM_ON == 1)
parse_mode(viafb_mode1, &viafb_second_xres,
&viafb_second_yres);
@@ -1818,9 +1814,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres_virtual = default_xres;
default_var.yres_virtual = default_yres;
default_var.bits_per_pixel = viafb_bpp;
- viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
- default_var.xres, default_var.yres, viafb_refresh),
- viafb_get_mode(default_var.xres, default_var.yres));
+ viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+ default_var.xres, default_var.yres, viafb_refresh));
viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
viafbinfo->var = default_var;
@@ -1859,9 +1854,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres_virtual = viafb_second_xres;
default_var.yres_virtual = viafb_second_yres;
default_var.bits_per_pixel = viafb_bpp1;
- viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
- default_var.xres, default_var.yres, viafb_refresh1),
- viafb_get_mode(default_var.xres, default_var.yres));
+ viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+ default_var.xres, default_var.yres, viafb_refresh1));
viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
viafb_check_var(&default_var, viafbinfo1);
@@ -1956,61 +1950,67 @@ static int __init viafb_setup(void)
if (!*this_opt)
continue;
- if (!strncmp(this_opt, "viafb_mode1=", 12))
+ if (!strncmp(this_opt, "viafb_mode1=", 12)) {
viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
- else if (!strncmp(this_opt, "viafb_mode=", 11))
+ } else if (!strncmp(this_opt, "viafb_mode=", 11)) {
viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
- else if (!strncmp(this_opt, "viafb_bpp1=", 11))
- strict_strtoul(this_opt + 11, 0,
- (unsigned long *)&viafb_bpp1);
- else if (!strncmp(this_opt, "viafb_bpp=", 10))
- strict_strtoul(this_opt + 10, 0,
- (unsigned long *)&viafb_bpp);
- else if (!strncmp(this_opt, "viafb_refresh1=", 15))
- strict_strtoul(this_opt + 15, 0,
- (unsigned long *)&viafb_refresh1);
- else if (!strncmp(this_opt, "viafb_refresh=", 14))
- strict_strtoul(this_opt + 14, 0,
- (unsigned long *)&viafb_refresh);
- else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
- strict_strtoul(this_opt + 21, 0,
- (unsigned long *)&viafb_lcd_dsp_method);
- else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
- strict_strtoul(this_opt + 19, 0,
- (unsigned long *)&viafb_lcd_panel_id);
- else if (!strncmp(this_opt, "viafb_accel=", 12))
- strict_strtoul(this_opt + 12, 0,
- (unsigned long *)&viafb_accel);
- else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
- strict_strtoul(this_opt + 14, 0,
- (unsigned long *)&viafb_SAMM_ON);
- else if (!strncmp(this_opt, "viafb_active_dev=", 17))
+ } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
+ if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
+ if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
+ if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
+ if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
+ if (kstrtoint(this_opt + 21, 0,
+ &viafb_lcd_dsp_method) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
+ if (kstrtoint(this_opt + 19, 0,
+ &viafb_lcd_panel_id) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_accel=", 12)) {
+ if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
+ if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
- else if (!strncmp(this_opt,
- "viafb_display_hardware_layout=", 30))
- strict_strtoul(this_opt + 30, 0,
- (unsigned long *)&viafb_display_hardware_layout);
- else if (!strncmp(this_opt, "viafb_second_size=", 18))
- strict_strtoul(this_opt + 18, 0,
- (unsigned long *)&viafb_second_size);
- else if (!strncmp(this_opt,
- "viafb_platform_epia_dvi=", 24))
- strict_strtoul(this_opt + 24, 0,
- (unsigned long *)&viafb_platform_epia_dvi);
- else if (!strncmp(this_opt,
- "viafb_device_lcd_dualedge=", 26))
- strict_strtoul(this_opt + 26, 0,
- (unsigned long *)&viafb_device_lcd_dualedge);
- else if (!strncmp(this_opt, "viafb_bus_width=", 16))
- strict_strtoul(this_opt + 16, 0,
- (unsigned long *)&viafb_bus_width);
- else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
- strict_strtoul(this_opt + 15, 0,
- (unsigned long *)&viafb_lcd_mode);
- else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
+ } else if (!strncmp(this_opt,
+ "viafb_display_hardware_layout=", 30)) {
+ if (kstrtoint(this_opt + 30, 0,
+ &viafb_display_hardware_layout) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
+ if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt,
+ "viafb_platform_epia_dvi=", 24)) {
+ if (kstrtoint(this_opt + 24, 0,
+ &viafb_platform_epia_dvi) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt,
+ "viafb_device_lcd_dualedge=", 26)) {
+ if (kstrtoint(this_opt + 26, 0,
+ &viafb_device_lcd_dualedge) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
+ if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
+ if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
- else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
+ } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
+ }
}
return 0;
}
@@ -2022,7 +2022,7 @@ static int __init viafb_setup(void)
int __init viafb_init(void)
{
u32 dummy_x, dummy_y;
- int r;
+ int r = 0;
if (machine_is_olpc())
/* Apply XO-1.5-specific configuration. */
@@ -2034,9 +2034,9 @@ int __init viafb_init(void)
return r;
#endif
if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
- || !viafb_get_mode(dummy_x, dummy_y)
+ || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
|| parse_mode(viafb_mode1, &dummy_x, &dummy_y)
- || !viafb_get_mode(dummy_x, dummy_y)
+ || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
|| viafb_bpp < 0 || viafb_bpp > 32
|| viafb_bpp1 < 0 || viafb_bpp1 > 32
|| parse_active_dev())
@@ -2045,7 +2045,7 @@ int __init viafb_init(void)
printk(KERN_INFO
"VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
VERSION_MAJOR, VERSION_MINOR);
- return 0;
+ return r;
}
void __exit viafb_exit(void)
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 58df74e..0911cac 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = {
/*r_rate,hsp,vsp */
/*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
{REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP,
- {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
+ {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} },
{REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP,
{840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
{REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP,
@@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
-struct VideoModeTable *viafb_get_mode(int hres, int vres)
+static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n,
+ int hres, int vres)
{
- u32 i;
- for (i = 0; i < ARRAY_SIZE(viafb_modes); i++)
- if (viafb_modes[i].mode_array &&
- viafb_modes[i].crtc[0].crtc.hor_addr == hres &&
- viafb_modes[i].crtc[0].crtc.ver_addr == vres)
+ int i;
+
+ for (i = 0; i < n; i++)
+ if (vmt[i].mode_array &&
+ vmt[i].crtc[0].crtc.hor_addr == hres &&
+ vmt[i].crtc[0].crtc.ver_addr == vres)
return &viafb_modes[i];
return NULL;
}
-struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt,
+ int refresh)
{
- u32 i;
- for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++)
- if (viafb_rb_modes[i].mode_array &&
- viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres &&
- viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres)
- return &viafb_rb_modes[i];
+ struct crt_mode_table *best;
+ int i;
- return NULL;
+ if (!vmt)
+ return NULL;
+
+ best = &vmt->crtc[0];
+ for (i = 1; i < vmt->mode_array; i++) {
+ if (abs(vmt->crtc[i].refresh_rate - refresh)
+ < abs(best->refresh_rate - refresh))
+ best = &vmt->crtc[i];
+ }
+
+ return best;
+}
+
+static struct VideoModeTable *viafb_get_mode(int hres, int vres)
+{
+ return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
+}
+
+struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh)
+{
+ return get_best_mode(viafb_get_mode(hres, vres), refresh);
+}
+
+static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+{
+ return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres,
+ vres);
+}
+
+struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh)
+{
+ return get_best_mode(viafb_get_rb_mode(hres, vres), refresh);
}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 3751289..5917a2b 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[];
extern struct patch_table res_patch_table[];
extern struct VPITTable VPIT;
-struct VideoModeTable *viafb_get_mode(int hres, int vres);
-struct VideoModeTable *viafb_get_rb_mode(int hres, int vres);
+struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh);
+struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh);
#endif /* __VIAMODE_H__ */
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 3dd6294..1a61939 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -7,6 +7,8 @@ config VIRTIO_RING
tristate
depends on VIRTIO
+menu "Virtio drivers"
+
config VIRTIO_PCI
tristate "PCI driver for virtio devices (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
@@ -33,3 +35,15 @@ config VIRTIO_BALLOON
If unsure, say M.
+ config VIRTIO_MMIO
+ tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
+ depends on HAS_IOMEM && EXPERIMENTAL
+ select VIRTIO
+ select VIRTIO_RING
+ ---help---
+ This drivers provides support for memory mapped virtio
+ platform device driver.
+
+ If unsure, say N.
+
+endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 6738c44..5a4c63c 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_VIRTIO) += virtio.o
obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
+obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index efb35aa..cc02a9b 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -1,6 +1,7 @@
#include <linux/virtio.h>
#include <linux/spinlock.h>
#include <linux/virtio_config.h>
+#include <linux/module.h>
/* Unique numbering for virtio devices. */
static unsigned int dev_index;
@@ -8,33 +9,32 @@ static unsigned int dev_index;
static ssize_t device_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "0x%04x\n", dev->id.device);
}
static ssize_t vendor_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "0x%04x\n", dev->id.vendor);
}
static ssize_t status_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
}
static ssize_t modalias_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
-
+ struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "virtio:d%08Xv%08X\n",
dev->id.device, dev->id.vendor);
}
static ssize_t features_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
- struct virtio_device *dev = container_of(_d, struct virtio_device, dev);
+ struct virtio_device *dev = dev_to_virtio(_d);
unsigned int i;
ssize_t len = 0;
@@ -69,7 +69,7 @@ static inline int virtio_id_match(const struct virtio_device *dev,
static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
{
unsigned int i;
- struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_dv);
const struct virtio_device_id *ids;
ids = container_of(_dr, struct virtio_driver, driver)->id_table;
@@ -81,7 +81,7 @@ static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
{
- struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_dv);
return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X",
dev->id.device, dev->id.vendor);
@@ -109,7 +109,7 @@ EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
static int virtio_dev_probe(struct device *_d)
{
int err, i;
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_d);
struct virtio_driver *drv = container_of(dev->dev.driver,
struct virtio_driver, driver);
u32 device_features;
@@ -147,7 +147,7 @@ static int virtio_dev_probe(struct device *_d)
static int virtio_dev_remove(struct device *_d)
{
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_device *dev = dev_to_virtio(_d);
struct virtio_driver *drv = container_of(dev->dev.driver,
struct virtio_driver, driver);
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index e058ace..28153fb 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -25,6 +25,7 @@
#include <linux/freezer.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
struct virtio_balloon
{
@@ -270,6 +271,12 @@ static int balloon(void *_vballoon)
else if (diff < 0)
leak_balloon(vb, -diff);
update_balloon_size(vb);
+
+ /*
+ * For large balloon changes, we could spend a lot of time
+ * and always have work to do. Be nice if preempt disabled.
+ */
+ cond_resched();
}
return 0;
}
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index ecb9254..13f6cd8 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -169,11 +169,29 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
}
+/* wait for pending irq handlers */
+static void vp_synchronize_vectors(struct virtio_device *vdev)
+{
+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+ int i;
+
+ if (vp_dev->intx_enabled)
+ synchronize_irq(vp_dev->pci_dev->irq);
+
+ for (i = 0; i < vp_dev->msix_vectors; ++i)
+ synchronize_irq(vp_dev->msix_entries[i].vector);
+}
+
static void vp_reset(struct virtio_device *vdev)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
/* 0 status means a reset. */
iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+ /* Flush out the status write, and flush in device writes,
+ * including MSi-X interrupts, if any. */
+ ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+ /* Flush pending VQ/configuration callbacks. */
+ vp_synchronize_vectors(vdev);
}
/* the notify function used when creating a virt queue */
@@ -415,9 +433,13 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index,
}
}
- spin_lock_irqsave(&vp_dev->lock, flags);
- list_add(&info->node, &vp_dev->virtqueues);
- spin_unlock_irqrestore(&vp_dev->lock, flags);
+ if (callback) {
+ spin_lock_irqsave(&vp_dev->lock, flags);
+ list_add(&info->node, &vp_dev->virtqueues);
+ spin_unlock_irqrestore(&vp_dev->lock, flags);
+ } else {
+ INIT_LIST_HEAD(&info->node);
+ }
return vq;
@@ -590,11 +612,13 @@ static struct virtio_config_ops virtio_pci_config_ops = {
static void virtio_pci_release_dev(struct device *_d)
{
- /*
- * No need for a release method as we allocate/free
- * all devices together with the pci devices.
- * Provide an empty one to avoid getting a warning from core.
- */
+ struct virtio_device *vdev = dev_to_virtio(_d);
+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+
+ /* As struct device is a kobject, it's not safe to
+ * free the memory (including the reference counter itself)
+ * until it's release callback. */
+ kfree(vp_dev);
}
/* the PCI probing function */
@@ -682,7 +706,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
pci_iounmap(pci_dev, vp_dev->ioaddr);
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
- kfree(vp_dev);
}
#ifdef CONFIG_PM
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index a0aecab..4a88ac3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -21,6 +21,7 @@
#include <linux/virtio_config.h>
#include <linux/device.h>
#include <linux/slab.h>
+#include <linux/module.h>
/* virtio guest is communicating with a virtual "device" that actually runs on
* a host processor. Memory barriers are used to control SMP effects. */
@@ -579,4 +580,14 @@ void vring_transport_features(struct virtio_device *vdev)
}
EXPORT_SYMBOL_GPL(vring_transport_features);
+/* return the size of the vring within the virtqueue */
+unsigned int virtqueue_get_vring_size(struct virtqueue *_vq)
+{
+
+ struct vring_virtqueue *vq = to_vvq(_vq);
+
+ return vq->vring.num;
+}
+EXPORT_SYMBOL_GPL(virtqueue_get_vring_size);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 02bf7bf..b5abaae 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -1,7 +1,7 @@
/*
* dscore.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -1024,5 +1024,5 @@ module_init(ds_init);
module_exit(ds_fini);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)");
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index 1550431..f667c26 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -1,7 +1,7 @@
/*
* matrox_w1.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
*/
#include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <linux/delay.h>
@@ -39,7 +39,7 @@
#include "../w1_log.h"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio).");
static struct pci_device_id matrox_w1_tbl[] = {
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c
index c377818..7c8cdb8 100644
--- a/drivers/w1/slaves/w1_ds2408.c
+++ b/drivers/w1/slaves/w1_ds2408.c
@@ -373,7 +373,7 @@ static int w1_f29_add_slave(struct w1_slave *sl)
static void w1_f29_remove_slave(struct w1_slave *sl)
{
int i;
- for (i = NB_SYSFS_BIN_FILES; i <= 0; --i)
+ for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
sysfs_remove_bin_file(&sl->dev.kobj,
&(w1_f29_sysfs_bin_files[i]));
}
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
index 483d451..5754c9a 100644
--- a/drivers/w1/slaves/w1_ds2760.c
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -114,43 +114,7 @@ static struct bin_attribute w1_ds2760_bin_attr = {
.read = w1_ds2760_read_bin,
};
-static DEFINE_IDR(bat_idr);
-static DEFINE_MUTEX(bat_idr_lock);
-
-static int new_bat_id(void)
-{
- int ret;
-
- while (1) {
- int id;
-
- ret = idr_pre_get(&bat_idr, GFP_KERNEL);
- if (ret == 0)
- return -ENOMEM;
-
- mutex_lock(&bat_idr_lock);
- ret = idr_get_new(&bat_idr, NULL, &id);
- mutex_unlock(&bat_idr_lock);
-
- if (ret == 0) {
- ret = id & MAX_ID_MASK;
- break;
- } else if (ret == -EAGAIN) {
- continue;
- } else {
- break;
- }
- }
-
- return ret;
-}
-
-static void release_bat_id(int id)
-{
- mutex_lock(&bat_idr_lock);
- idr_remove(&bat_idr, id);
- mutex_unlock(&bat_idr_lock);
-}
+static DEFINE_IDA(bat_ida);
static int w1_ds2760_add_slave(struct w1_slave *sl)
{
@@ -158,7 +122,7 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
int id;
struct platform_device *pdev;
- id = new_bat_id();
+ id = ida_simple_get(&bat_ida, 0, 0, GFP_KERNEL);
if (id < 0) {
ret = id;
goto noid;
@@ -187,7 +151,7 @@ bin_attr_failed:
pdev_add_failed:
platform_device_unregister(pdev);
pdev_alloc_failed:
- release_bat_id(id);
+ ida_simple_remove(&bat_ida, id);
noid:
success:
return ret;
@@ -199,7 +163,7 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl)
int id = pdev->id;
platform_device_unregister(pdev);
- release_bat_id(id);
+ ida_simple_remove(&bat_ida, id);
sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
}
@@ -217,14 +181,14 @@ static int __init w1_ds2760_init(void)
{
printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
" chip - (c) 2004-2005, Szabolcs Gyurko\n");
- idr_init(&bat_idr);
+ ida_init(&bat_ida);
return w1_register_family(&w1_ds2760_family);
}
static void __exit w1_ds2760_exit(void)
{
w1_unregister_family(&w1_ds2760_family);
- idr_destroy(&bat_idr);
+ ida_destroy(&bat_ida);
}
EXPORT_SYMBOL(w1_ds2760_read);
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c
index 505b17d..39f78c0 100644
--- a/drivers/w1/slaves/w1_ds2780.c
+++ b/drivers/w1/slaves/w1_ds2780.c
@@ -121,43 +121,7 @@ static struct bin_attribute w1_ds2780_bin_attr = {
.read = w1_ds2780_read_bin,
};
-static DEFINE_IDR(bat_idr);
-static DEFINE_MUTEX(bat_idr_lock);
-
-static int new_bat_id(void)
-{
- int ret;
-
- while (1) {
- int id;
-
- ret = idr_pre_get(&bat_idr, GFP_KERNEL);
- if (ret == 0)
- return -ENOMEM;
-
- mutex_lock(&bat_idr_lock);
- ret = idr_get_new(&bat_idr, NULL, &id);
- mutex_unlock(&bat_idr_lock);
-
- if (ret == 0) {
- ret = id & MAX_ID_MASK;
- break;
- } else if (ret == -EAGAIN) {
- continue;
- } else {
- break;
- }
- }
-
- return ret;
-}
-
-static void release_bat_id(int id)
-{
- mutex_lock(&bat_idr_lock);
- idr_remove(&bat_idr, id);
- mutex_unlock(&bat_idr_lock);
-}
+static DEFINE_IDA(bat_ida);
static int w1_ds2780_add_slave(struct w1_slave *sl)
{
@@ -165,7 +129,7 @@ static int w1_ds2780_add_slave(struct w1_slave *sl)
int id;
struct platform_device *pdev;
- id = new_bat_id();
+ id = ida_simple_get(&bat_ida, 0, 0, GFP_KERNEL);
if (id < 0) {
ret = id;
goto noid;
@@ -194,7 +158,7 @@ bin_attr_failed:
pdev_add_failed:
platform_device_unregister(pdev);
pdev_alloc_failed:
- release_bat_id(id);
+ ida_simple_remove(&bat_ida, id);
noid:
return ret;
}
@@ -205,7 +169,7 @@ static void w1_ds2780_remove_slave(struct w1_slave *sl)
int id = pdev->id;
platform_device_unregister(pdev);
- release_bat_id(id);
+ ida_simple_remove(&bat_ida, id);
sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr);
}
@@ -221,14 +185,14 @@ static struct w1_family w1_ds2780_family = {
static int __init w1_ds2780_init(void)
{
- idr_init(&bat_idr);
+ ida_init(&bat_ida);
return w1_register_family(&w1_ds2780_family);
}
static void __exit w1_ds2780_exit(void)
{
w1_unregister_family(&w1_ds2780_family);
- idr_destroy(&bat_idr);
+ ida_destroy(&bat_ida);
}
module_init(w1_ds2780_init);
diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c
index cc8c02e..8465562 100644
--- a/drivers/w1/slaves/w1_smem.c
+++ b/drivers/w1/slaves/w1_smem.c
@@ -1,7 +1,7 @@
/*
* w1_smem.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
#include "../w1_family.h"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
static struct w1_family w1_smem_family_01 = {
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 17726a0..a1ef9b5 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -1,7 +1,7 @@
/*
* w1_therm.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
#include "../w1_family.h"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
/* Allow the strong pullup to be disabled, but default to enabled.
@@ -86,6 +86,11 @@ static struct w1_family w1_therm_family_DS1822 = {
.fops = &w1_therm_fops,
};
+static struct w1_family w1_therm_family_DS28EA00 = {
+ .fid = W1_THERM_DS28EA00,
+ .fops = &w1_therm_fops,
+};
+
struct w1_therm_family_converter
{
u8 broken;
@@ -111,6 +116,10 @@ static struct w1_therm_family_converter w1_therm_families[] = {
.f = &w1_therm_family_DS18B20,
.convert = w1_DS18B20_convert_temp
},
+ {
+ .f = &w1_therm_family_DS28EA00,
+ .convert = w1_DS18B20_convert_temp
+ },
};
static inline int w1_DS18B20_convert_temp(u8 rom[9])
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index cbff966..5149d4e 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -1,7 +1,7 @@
/*
* w1.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "w1.h"
#include "w1_log.h"
@@ -42,7 +42,7 @@
#include "w1_netlink.h"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
static int w1_timeout = 10;
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 1ce23fc..4d012ca 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -1,7 +1,7 @@
/*
* w1.h
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index 4a09904..e930977 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -1,7 +1,7 @@
/*
* w1_family.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/sched.h> /* schedule_timeout() */
#include <linux/delay.h>
+#include <linux/export.h>
#include "w1_family.h"
#include "w1.h"
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 97479ae..490cda2 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -1,7 +1,7 @@
/*
* w1_family.h
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
#include <linux/types.h>
#include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define W1_FAMILY_DEFAULT 0
#define W1_FAMILY_SMEM_01 0x01
@@ -38,6 +38,7 @@
#define W1_EEPROM_DS2431 0x2D
#define W1_FAMILY_DS2760 0x30
#define W1_FAMILY_DS2780 0x32
+#define W1_THERM_DS28EA00 0x42
#define MAXNAMELEN 32
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index b50be3f..6828835 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -1,7 +1,7 @@
/*
* w1_int.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,8 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/moduleparam.h>
#include "w1.h"
#include "w1_log.h"
@@ -78,6 +80,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
memcpy(&dev->dev, device, sizeof(struct device));
dev_set_name(&dev->dev, "w1_bus_master%u", dev->id);
snprintf(dev->name, sizeof(dev->name), "w1_bus_master%u", dev->id);
+ dev->dev.init_name = dev->name;
dev->driver = driver;
diff --git a/drivers/w1/w1_int.h b/drivers/w1/w1_int.h
index 4274082..2ad7d44 100644
--- a/drivers/w1/w1_int.h
+++ b/drivers/w1/w1_int.h
@@ -1,7 +1,7 @@
/*
* w1_int.h
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 8e8b64c..3135b2c 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -1,7 +1,7 @@
/*
* w1_io.c
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -158,13 +158,18 @@ EXPORT_SYMBOL_GPL(w1_write_8);
static u8 w1_read_bit(struct w1_master *dev)
{
int result;
+ unsigned long flags;
+ /* sample timing is critical here */
+ local_irq_save(flags);
dev->bus_master->write_bit(dev->bus_master->data, 0);
w1_delay(6);
dev->bus_master->write_bit(dev->bus_master->data, 1);
w1_delay(9);
result = dev->bus_master->read_bit(dev->bus_master->data);
+ local_irq_restore(flags);
+
w1_delay(55);
return result & 0x1;
diff --git a/drivers/w1/w1_log.h b/drivers/w1/w1_log.h
index e6ab7cf..9c7bd62 100644
--- a/drivers/w1/w1_log.h
+++ b/drivers/w1/w1_log.h
@@ -1,7 +1,7 @@
/*
* w1_log.h
*
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 55aabd9..73705af 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -1,7 +1,7 @@
/*
* w1_netlink.c
*
- * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2003 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -54,28 +54,29 @@ static void w1_send_slave(struct w1_master *dev, u64 rn)
struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1);
struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1);
int avail;
+ u64 *data;
/* update kernel slave list */
w1_slave_found(dev, rn);
avail = dev->priv_size - cmd->len;
- if (avail > 8) {
- u64 *data = (void *)(cmd + 1) + cmd->len;
+ if (avail < 8) {
+ msg->ack++;
+ cn_netlink_send(msg, 0, GFP_KERNEL);
- *data = rn;
- cmd->len += 8;
- hdr->len += 8;
- msg->len += 8;
- return;
+ msg->len = sizeof(struct w1_netlink_msg) +
+ sizeof(struct w1_netlink_cmd);
+ hdr->len = sizeof(struct w1_netlink_cmd);
+ cmd->len = 0;
}
- msg->ack++;
- cn_netlink_send(msg, 0, GFP_KERNEL);
+ data = (void *)(cmd + 1) + cmd->len;
- msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd);
- hdr->len = sizeof(struct w1_netlink_cmd);
- cmd->len = 0;
+ *data = rn;
+ cmd->len += 8;
+ hdr->len += 8;
+ msg->len += 8;
}
static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg,
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index 27e950f..b0922dc 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -1,7 +1,7 @@
/*
* w1_netlink.h
*
- * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2003 Evgeniy Polyakov <zbr@ioremap.net>
*
*
* This program is free software; you can redistribute it and/or modify